Ejemplo n.º 1
0
class FundTransfer(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    account = models.ForeignKey(Account, on_delete=models.CASCADE)
    iban_beneficiary = IBANField()
    bic_beneficiary = models.CharField(max_length=11, blank=True)
    bank_beneficiary = models.CharField(max_length=200, blank=True)
    name_beneficiary = models.CharField(max_length=150, blank=True)
    amount = models.FloatField(default=0, validators=[MinValueValidator(0)])
    amount_bgn = models.FloatField(default=0,
                                   validators=[MinValueValidator(0)])
    currency = models.ForeignKey(Currency, on_delete=models.CASCADE, default=1)
    details = models.CharField(max_length=150)
    created = models.DateTimeField(auto_now_add=True)
    last_updated = models.DateTimeField(auto_now=True)
    status = models.CharField(max_length=10,
                              choices=[(s.name, s.value)
                                       for s in TransferStatusEnum],
                              default='I')
    otp_generated = models.CharField(max_length=10, blank=True)
    pin_otp = models.CharField(max_length=10, blank=True)
    user_approved = models.ForeignKey(User,
                                      related_name='ft_approval',
                                      on_delete=models.CASCADE,
                                      blank=True,
                                      null=True)
    reference_cbs = models.CharField(max_length=20, blank=True)
    payment_system = models.CharField(max_length=7,
                                      choices=[(p.name, p.value)
                                               for p in PaymentSystemEnum],
                                      default='I')
Ejemplo n.º 2
0
class CreditCard(models.Model):
    IBAN = IBANField(null=True, default=None)
    cardHolderName = models.CharField(max_length=25)

    def __str__(self):
        return "Carte N°" + str(
            self.id
        ) + " - Détenteur : " + self.cardHolderName + " | IBAN : " + self.iban
Ejemplo n.º 3
0
class Accounts(models.Model):
    CURRENCY = (
        ('Dollars', 'Dollars'),
        ('Euro', 'Euro'),
        ('Lira', 'Lira'),
    )
    the_owner = models.ForeignKey(User, on_delete=models.CASCADE)
    currency = models.CharField(max_length=50, choices=CURRENCY, null=True)
    account_name = models.CharField(primary_key=True, max_length=100)
    amount = models.IntegerField(default=0)
    iban = IBANField(enforce_database_constraint=True, unique=True)
    account_no = IBANField(enforce_database_constraint=True, unique=True)

    def __str__(self):
        return "Account Owner: {} / {} / {}".format(str(self.the_owner),
                                                    str(self.iban),
                                                    str(self.currency))
Ejemplo n.º 4
0
class CustomUser(AbstractUser):
    iban = IBANField(enforce_database_constraint=True, unique=True)
    created_by = models.ForeignKey(
        'self',
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
    )
    REQUIRED_FIELDS = ['iban', 'first_name', 'last_name', 'email']
Ejemplo n.º 5
0
class Usuario(models.Model):
    owner = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
    name = models.CharField(max_length=250, default="")
    surname = models.CharField(max_length=250, default="")
    iban = IBANField(enforce_database_constraint=True, unique=True)
    concatenado = models.CharField(max_length=200, default="")

    def __str__(self):
        return self.concatenado
Ejemplo n.º 6
0
class Bank_Account(models.Model):
    iban = IBANField()
    bank = models.CharField(max_length=15,choices=BANK_CHOICES)

    def get_absolute_url(self):
        return reverse('statement-detail', args=[str(self.iban)])

    def __str__(self):
        return f'{self.bank}, {self.iban}'
Ejemplo n.º 7
0
class Account(models.Model):
    """
    Bank account. All Fund transfers are initiated from an account
    """
    DJANGO_BANK_BIC = 'DJNG8280'

    product = models.ForeignKey(AccountProduct, on_delete=models.CASCADE)
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE, null=True)
    users = models.ManyToManyField(User)
    iban = IBANField(enforce_database_constraint=True, unique=True)
    balance = models.FloatField(validators=[MinValueValidator(0)], default=0)
    currency = models.ForeignKey(Currency, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    status = models.CharField(max_length=7,
                              choices=[(s.name, s.value)
                                       for s in AccountStatusEnum],
                              default='A')

    def __str__(self):
        return f"{self.iban} {self.currency.code}"
Ejemplo n.º 8
0
class UserForm(forms.ModelForm):
    name = forms.CharField(min_length=2, max_length=15)
    surname = forms.CharField(max_length=200)
    iban = IBANField(enforce_database_constraint=True, unique=True)
    concatenado = forms.CharField(max_length=200,
                                  widget=forms.HiddenInput,
                                  required=False)

    class Meta:
        model = Usuario
        fields = ('concatenado', 'name', 'surname', 'iban')

    def clean_name(self):
        name = self.cleaned_data.get('name')
        return name.upper()

    def clean_surname(self):
        surname = self.cleaned_data.get('surname')
        return surname.upper()

    def clean_iban(self):
        iban = self.cleaned_data.get('iban')
        if (Usuario.objects.filter(iban=iban)):
            raise forms.ValidationError("Error,  " + iban + " is registred")
            return iban
        return iban

    def clean_email(self):
        email = self.cleaned_data.get('email')
        lista_usuarios = Usuario.objects.all()
        if (Usuario.objects.filter(email=email)):
            raise forms.ValidationError("Error, email " + email +
                                        " is registred")
            return email
        return email

    def clean(self):
        if (self.is_valid()):
            name = self.cleaned_data.get('name')
            surname = self.cleaned_data.get('surname')
            self.cleaned_data['concatenado'] = name + " " + surname
Ejemplo n.º 9
0
class Customer(models.Model):
    first_name = models.CharField(max_length=32, db_index=True)
    last_name = models.CharField(max_length=32, db_index=True)
    iban = IBANField(
        unique=True,
        help_text="Up to 34 chars bank account number, depends on country.")
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL,
                                   null=True,
                                   on_delete=models.SET(get_sentinel_user),
                                   related_name='customers_added')

    def __str__(self):
        return " ".join([self.first_name, self.last_name])

    def created_by_email_display(self):
        if self.created_by == get_sentinel_user():
            return '(DELETED)'
        return self.created_by.email

    created_by_email_display.short_description = 'created by'
    created_by_email_display.admin_order_field = 'created_by__email'
Ejemplo n.º 10
0
class MangoPayBankAccount(models.Model):
    mangopay_user = models.ForeignKey(MangoPayUser,
                                      related_name="mangopay_bank_accounts")
    mangopay_id = models.PositiveIntegerField(null=True, blank=True)
    iban = IBANField()
    bic = SWIFTBICField()
    address = models.CharField(max_length=254)

    def create(self):
        client = get_mangopay_api_client()
        mangopay_bank_account = BankAccount()
        mangopay_bank_account.UserId = self.mangopay_user.mangopay_id
        mangopay_bank_account.OwnerName = \
            self.mangopay_user.user.get_full_name()
        mangopay_bank_account.OwnerAddress = self.address
        mangopay_bank_account.IBAN = self.iban
        mangopay_bank_account.BIC = self.bic
        created_bank_account = client.users.CreateBankAccount(
            str(self.mangopay_user.mangopay_id), mangopay_bank_account)
        self.mangopay_id = created_bank_account.Id
        self.save()
Ejemplo n.º 11
0
class Profile(models.Model):
    user = models.OneToOneField(User)
    type = models.CharField(max_length=20, choices=PROFILE_TYPE, default=FINAL)
    phone = models.CharField(max_length=20, validators=[validate_phone_number])
    picture = models.URLField(null=True, blank=True)
    swift_bank_account = SWIFTBICField(null=True, blank=True)
    iban_bank_account = IBANField(null=True, blank=True)
    account_name = models.CharField(max_length=255, blank=True, null=True)
    documents = ArrayField(models.URLField(),
                           null=True,
                           blank=True,
                           help_text=_("Separate urls using a comma"))
    work_days = ArrayField(models.IntegerField(
        validators=[MinValueValidator(0),
                    MaxValueValidator(6)]),
                           null=True,
                           blank=True,
                           help_text=_("Separate using a comma"))
    work_hours = ArrayField(models.IntegerField(
        validators=[MinValueValidator(0),
                    MaxValueValidator(23)]),
                            null=True,
                            blank=True,
                            help_text=_("Separate using a comma"))
    city = ArrayField(models.IntegerField(null=True,
                                          blank=True,
                                          validators=[validate_city]),
                      null=True,
                      blank=True,
                      help_text=_("Separate using a comma"))
    rating = models.FloatField(default=0)
    fee = models.FloatField(default=0)
    language = models.CharField(max_length=7,
                                default="en",
                                blank=True,
                                null=True)

    def __str__(self):
        return "%s - %s" % (self.user.email, self.type)
Ejemplo n.º 12
0
class Vendor(models.Model):
    rating = models.FloatField(
        null=True,
        blank=True,
        validators=[MaxValueValidator(5),
                    MinValueValidator(1)])
    IBAN = IBANField(null=True, default=None)
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    # Param: upload_to='directory'
    photo = models.TextField(blank=True, null=True, max_length=None)
    no_rue = models.CharField(max_length=6)
    adresse = models.CharField(max_length=25)
    code_postal = models.PositiveIntegerField(
        validators=[MaxValueValidator(9999),
                    MinValueValidator(1000)])
    ville = models.CharField(max_length=25)
    pays = models.CharField(max_length=25)

    def __str__(self):
        if (self.user.first_name == ""):
            return self.user.username
        else:
            return self.user.first_name
Ejemplo n.º 13
0
class Invoice(models.Model):
    """
    Model representing Invoice itself.
    It keeps all necessary information described at https://www.gov.uk/vat-record-keeping/vat-invoices
    """
    COUNTER_PERIOD = Choices(('DAILY', _('daily')), ('MONTHLY', _('monthly')),
                             ('YEARLY', _('yearly')))

    TYPE = Choices(('INVOICE', _(u'Invoice')),
                   ('ADVANCE', _(u'Advance invoice')),
                   ('PROFORMA', _(u'Proforma invoice')),
                   ('CREDIT_NOTE', _(u'Credit note')))

    STATUS = Choices(('NEW', _(u'new')), ('SENT', _(u'sent')),
                     ('RETURNED', _(u'returned')),
                     ('CANCELED', _(u'canceled')), ('PAID', _(u'paid')))

    PAYMENT_METHOD = Choices(('BANK_TRANSFER', _(u'bank transfer')),
                             ('CASH', _(u'cash')),
                             ('CASH_ON_DELIVERY', _(u'cash on delivery')),
                             ('PAYMENT_CARD', _(u'payment card')))

    DELIVERY_METHOD = Choices(
        ('PERSONAL_PICKUP', _(u'personal pickup')),
        ('MAILING', _(u'mailing')),
        ('DIGITAL', _(u'digital')),
    )

    CONSTANT_SYMBOL = Choices(
        ('0001',
         _(u'0001 - Payments for goods based on legal and executable decision from legal authority'
           )), ('0008', _(u'0008 - Cashless payments for goods')),
        ('0038', _(u'0038 - Cashless funds for wages')),
        ('0058', _(u'0058 - Cashless penalty and delinquency charges')),
        ('0068',
         _(u'0068 - Transfer of funds for wages and other personal costs')),
        ('0138', _(u'0138 - Cashless deductions at source')),
        ('0168', _(u'0168 - Cashless payments in loans')),
        ('0178', _(u'0178 - Sales from provided services')),
        ('0298', _(u'0298 - Other cashless transfers')),
        ('0304', _(u'0304 - Prior payments for services')),
        ('0308', _(u'0308 - Cashless payments for services')),
        ('0358',
         _(u'0358 - Payments dedicated to payout through post offices')),
        ('0379', _(u'0379 - Other income, income from postal order')),
        ('0498', _(u'0498 - Payments in loans')),
        ('0558', _(u'0558 - Cashless other financial payments')),
        ('0934', _(u'0934 - Benefits - prior payments')),
        ('0968', _(u'0968 - Other cashless transfers')),
        ('1144', _(u'1144 - Prior payment - advance')),
        ('1148', _(u'1148 - Payment - current advance')),
        ('1744',
         _(u'1744 - Accounting of tax at income tax of physical body and corporate body'
           )),
        ('1748',
         _(u'1748 - Income tax of physical body and corporate body based on declared tax year'
           )),
        ('3118',
         _(u'3118 - Insurance and empl. contrib. to insur. co. and the Labor Office'
           )), ('3344', _(u'3344 - Penalty from message - prior')),
        ('3348', _(u'3348 - Penalty from message')),
        ('3354', _(u'3354 - Insurance payments by insurance companies')),
        ('3558',
         _(u'3558 - Cashless insurance payments by insurance companies')),
        ('8147', _(u'8147 - Payment (posted together with the instruction)')))

    # General information
    type = models.CharField(_(u'type'),
                            max_length=64,
                            choices=TYPE,
                            default=TYPE.INVOICE)
    sequence = models.IntegerField(_(u'sequence'), db_index=True, blank=True)
    number = models.CharField(_(u'number'), max_length=128, blank=True)
    status = models.CharField(_(u'status'),
                              choices=STATUS,
                              max_length=64,
                              default=STATUS.NEW)
    subtitle = models.CharField(_(u'subtitle'), max_length=255, blank=True)
    related_document = models.CharField(_(u'related document'),
                                        max_length=100,
                                        blank=True)
    language = models.CharField(_(u'language'),
                                max_length=10,
                                choices=settings.LANGUAGES)
    note = models.CharField(_(u'note'),
                            max_length=255,
                            blank=True,
                            default=_(u'Thank you for using our services.'))
    date_issue = models.DateField(_(u'issue date'))
    date_tax_point = models.DateField(_(u'tax point date'),
                                      help_text=_(u'time of supply'))
    date_due = models.DateField(_(u'due date'), help_text=_(u'payment till'))
    date_sent = MonitorField(monitor='status',
                             when=[STATUS.SENT],
                             verbose_name=_(u'date sent'),
                             blank=True,
                             null=True,
                             default=None)
    date_paid = MonitorField(monitor='status',
                             when=[STATUS.PAID],
                             verbose_name=_(u'date paid'),
                             blank=True,
                             null=True,
                             default=None)

    # Payment details
    currency = models.CharField(_(u'currency'),
                                max_length=10,
                                choices=CURRENCY_CHOICES)
    credit = models.DecimalField(_(u'credit'),
                                 max_digits=10,
                                 decimal_places=2,
                                 default=0)
    #already_paid = models.DecimalField(_(u'already paid'), max_digits=10, decimal_places=2, default=0)

    payment_method = models.CharField(_(u'payment method'),
                                      choices=PAYMENT_METHOD,
                                      max_length=64)
    constant_symbol = models.CharField(_(u'constant symbol'),
                                       max_length=64,
                                       choices=CONSTANT_SYMBOL,
                                       blank=True)
    variable_symbol = models.PositiveIntegerField(
        _(u'variable symbol'),
        validators=[MinValueValidator(0),
                    MaxValueValidator(9999999999)],
        blank=True,
        null=True,
        default=None)
    specific_symbol = models.PositiveIntegerField(
        _(u'specific symbol'),
        validators=[MinValueValidator(0),
                    MaxValueValidator(9999999999)],
        blank=True,
        null=True,
        default=None)
    reference = models.CharField(_(u'reference'), max_length=140, blank=True)

    bank_name = models.CharField(_(u'bank name'), max_length=255, blank=True)
    bank_street = models.CharField(_(u'bank street and number'),
                                   max_length=255,
                                   blank=True)
    bank_zip = models.CharField(_(u'bank ZIP'), max_length=255, blank=True)
    bank_city = models.CharField(_(u'bank city'), max_length=255, blank=True)
    bank_country = CountryField(_(u'bank country'), max_length=255, blank=True)
    bank_iban = IBANField(verbose_name=_(u'Account number (IBAN)'),
                          default=None)
    bank_swift_bic = SWIFTBICField(verbose_name=_(u'Bank SWIFT / BIC'),
                                   default=None)

    # Issuer details
    supplier_name = models.CharField(_(u'supplier name'),
                                     max_length=255,
                                     default=None)
    supplier_street = models.CharField(_(u'supplier street and number'),
                                       max_length=255,
                                       blank=True)
    supplier_zip = models.CharField(_(u'supplier ZIP'),
                                    max_length=255,
                                    blank=True)
    supplier_city = models.CharField(_(u'supplier city'),
                                     max_length=255,
                                     blank=True)
    supplier_country = CountryField(_(u'supplier country'), default=None)
    supplier_registration_id = models.CharField(_(u'supplier Reg. No.'),
                                                max_length=255,
                                                blank=True)
    supplier_tax_id = models.CharField(_(u'supplier Tax No.'),
                                       max_length=255,
                                       blank=True)
    supplier_vat_id = VATField(_(u'supplier VAT No.'), blank=True)
    supplier_additional_info = JSONField(
        _(u'supplier additional information'),
        load_kwargs={'object_pairs_hook': OrderedDict},
        blank=True,
        null=True,
        default=None)  # for example www or legal matters

    # Contact details
    issuer_name = models.CharField(_(u'issuer name'),
                                   max_length=255,
                                   blank=True)
    issuer_email = models.EmailField(_(u'issuer email'), blank=True)
    issuer_phone = models.CharField(_(u'issuer phone'),
                                    max_length=255,
                                    blank=True)

    # Customer details
    customer_name = models.CharField(_(u'customer name'), max_length=255)
    customer_street = models.CharField(_(u'customer street and number'),
                                       max_length=255,
                                       blank=True)
    customer_zip = models.CharField(_(u'customer ZIP'),
                                    max_length=255,
                                    blank=True)
    customer_city = models.CharField(_(u'customer city'),
                                     max_length=255,
                                     blank=True)
    customer_country = CountryField(_(u'customer country'))
    customer_registration_id = models.CharField(_(u'customer Reg. No.'),
                                                max_length=255,
                                                blank=True)
    customer_tax_id = models.CharField(_(u'customer Tax No.'),
                                       max_length=255,
                                       blank=True)
    customer_vat_id = VATField(_(u'customer VAT No.'), blank=True)
    customer_additional_info = JSONField(
        _(u'customer additional information'),
        load_kwargs={'object_pairs_hook': OrderedDict},
        blank=True,
        null=True,
        default=None)
    customer_email = models.EmailField(_(u'customer email'), blank=True)
    customer_phone = models.CharField(_(u'customer phone'),
                                      max_length=255,
                                      blank=True)

    # Shipping details
    shipping_name = models.CharField(_(u'shipping name'),
                                     max_length=255,
                                     blank=True)
    shipping_street = models.CharField(_(u'shipping street and number'),
                                       max_length=255,
                                       blank=True)
    shipping_zip = models.CharField(_(u'shipping ZIP'),
                                    max_length=255,
                                    blank=True)
    shipping_city = models.CharField(_(u'shipping city'),
                                     max_length=255,
                                     blank=True)
    shipping_country = CountryField(_(u'shipping country'), blank=True)

    # Delivery details
    delivery_method = models.CharField(_(u'delivery method'),
                                       choices=DELIVERY_METHOD,
                                       max_length=64,
                                       default=DELIVERY_METHOD.PERSONAL_PICKUP)

    # sums (auto calculated fields)
    total = models.DecimalField(_(u'total'),
                                max_digits=10,
                                decimal_places=2,
                                blank=True,
                                default=0)
    vat = models.DecimalField(_(u'VAT'),
                              max_digits=10,
                              decimal_places=2,
                              blank=True,
                              null=True,
                              default=0)

    # Other
    attachments = JSONField(_(u'attachments'),
                            load_kwargs={'object_pairs_hook': OrderedDict},
                            blank=True,
                            null=True,
                            default=None)
    created = models.DateTimeField(_(u'created'), auto_now_add=True)
    modified = models.DateTimeField(_(u'modified'), auto_now=True)
    objects = InvoiceQuerySet.as_manager()

    class Meta:
        db_table = 'invoicing_invoices'
        verbose_name = _(u'invoice')
        verbose_name_plural = _(u'invoices')
        ordering = ('date_issue', 'sequence')
        default_permissions = ('list', 'view', 'add', 'change', 'delete')

    def __str__(self):
        return self.number

    def __unicode__(self):
        return self.number

    @transaction.atomic
    def save(self, **kwargs):
        if self.sequence in EMPTY_VALUES:
            self.sequence = Invoice.get_next_sequence(
                self.type, self.date_issue, getattr(self, 'number_prefix',
                                                    None))
        if self.number in EMPTY_VALUES:
            self.number = self._get_number(getattr(self, 'number_format',
                                                   None))

        return super(Invoice, self).save(**kwargs)

    def get_absolute_url(self):
        return getattr(
            settings, 'INVOICING_INVOICE_ABSOLUTE_URL',
            lambda invoice: reverse('invoicing:invoice_detail',
                                    args=(invoice.pk, )))(self)

    @staticmethod
    def get_next_sequence(type, important_date, number_prefix=None):
        """
        Returns next invoice sequence based on ``settings.INVOICING_COUNTER_PERIOD``.

        .. warning::

            This is only used to prepopulate ``sequence`` field on saving new invoice.
            To get invoice sequence always use ``sequence`` field.

        .. note::

            To get invoice number use ``number`` field.

        :return: string (generated next sequence)
        """
        with transaction.atomic():
            Invoice.objects.lock()

            invoice_counter_reset = getattr(settings,
                                            'INVOICING_COUNTER_PERIOD',
                                            Invoice.COUNTER_PERIOD.YEARLY)

            if invoice_counter_reset == Invoice.COUNTER_PERIOD.DAILY:
                relative_invoices = Invoice.objects.filter(
                    date_issue=important_date)

            elif invoice_counter_reset == Invoice.COUNTER_PERIOD.YEARLY:
                relative_invoices = Invoice.objects.filter(
                    date_issue__year=important_date.year)

            elif invoice_counter_reset == Invoice.COUNTER_PERIOD.MONTHLY:
                relative_invoices = Invoice.objects.filter(
                    date_issue__year=important_date.year,
                    date_issue__month=important_date.month)

            else:
                raise ImproperlyConfigured(
                    "INVOICING_COUNTER_PERIOD can be set only to these values: DAILY, MONTHLY, YEARLY."
                )

            invoice_counter_per_type = getattr(settings,
                                               'INVOICING_COUNTER_PER_TYPE',
                                               False)

            if invoice_counter_per_type:
                relative_invoices = relative_invoices.filter(type=type)

            if number_prefix is not None:
                relative_invoices = relative_invoices.filter(
                    number__startswith=number_prefix)

            start_from = getattr(settings, 'INVOICING_NUMBER_START_FROM', 1)
            last_sequence = relative_invoices.aggregate(
                Max('sequence'))['sequence__max'] or start_from - 1

            return last_sequence + 1

    def _get_number(self, number_format=None):
        """
        Generates on the fly invoice number from template provided by ``settings.INVOICING_NUMBER_FORMAT``.
        ``Invoice`` object is provided as ``invoice`` variable to the template, therefore all object fields
        can be used to generate number format.

        .. warning::

            This is only used to prepopulate ``number`` field on saving new invoice.
            To get invoice number always use ``number`` field.

        :return: string (generated number)
        """
        if not number_format:
            number_format = getattr(
                settings, "INVOICING_NUMBER_FORMAT",
                "{{ invoice.date_tax_point|date:'Y' }}/{{ invoice.sequence }}")
        return Template(number_format).render(Context({'invoice': self}))

    def get_tax_rate(self):
        if self.taxation_policy:
            # There is taxation policy -> get tax rate
            customer_country_code = self.customer_country.code if self.customer_country else None
            supplier_country_code = self.supplier_country.code if self.supplier_country else None
            return self.taxation_policy.get_tax_rate(self.customer_vat_id,
                                                     customer_country_code,
                                                     supplier_country_code)
        else:
            # If there is not any special taxation policy, set default tax rate
            return TaxationPolicy.get_default_tax()

    @property
    def taxation_policy(self):
        taxation_policy = getattr(settings, 'INVOICING_TAXATION_POLICY', None)
        if taxation_policy is not None:
            return import_name(taxation_policy)

        # Check if supplier is from EU
        if self.supplier_country:
            if EUTaxationPolicy.is_in_EU(self.supplier_country.code):
                return EUTaxationPolicy

        return None

    @property
    def is_overdue(self):
        return self.date_due < now().date() and self.status not in [
            self.STATUS.PAID, self.STATUS.CANCELED
        ]

    @property
    def overdue_days(self):
        return (now().date() - self.date_due).days

    @property
    def payment_term(self):
        return (self.date_due - self.date_issue).days if self.total > 0 else 0

    def set_supplier_data(self, supplier):
        self.supplier_name = supplier.get('name')
        self.supplier_street = supplier.get('street', '')
        self.supplier_zip = supplier.get('zip', '')
        self.supplier_city = supplier.get('city', '')
        self.supplier_country = supplier.get('country_code')
        self.supplier_registration_id = supplier.get('registration_id', '')
        self.supplier_tax_id = supplier.get('tax_id', '')
        self.supplier_vat_id = supplier.get('vat_id', '')
        self.supplier_additional_info = supplier.get('additional_info', None)

        bank = supplier.get('bank')
        self.bank_name = bank.get('name')
        self.bank_street = bank.get('street')
        self.bank_zip = bank.get('zip')
        self.bank_city = bank.get('city')
        self.bank_country = bank.get('country_code')
        self.bank_iban = bank.get('iban')
        self.bank_swift_bic = bank.get('swift_bic')

    def set_customer_data(self, customer):
        self.customer_name = customer.get('name')
        self.customer_street = customer.get('street', '')
        self.customer_zip = customer.get('zip', '')
        self.customer_city = customer.get('city', '')
        self.customer_country = customer.get('country_code')
        self.customer_registration_id = customer.get('registration_id', '')
        self.customer_tax_id = customer.get('tax_id', '')
        self.customer_vat_id = customer.get('vat_id', '')
        self.customer_additional_info = customer.get('additional_info', None)

    def set_shipping_data(self, shipping):
        self.shipping_name = shipping.get('name', '')
        self.shipping_street = shipping.get('street', '')
        self.shipping_zip = shipping.get('zip', '')
        self.shipping_city = shipping.get('city', '')
        self.shipping_country = shipping.get('country_code', '')

    # http://www.superfaktura.sk/blog/neplatca-dph-vzor-faktury/
    def is_supplier_vat_id_visible(self):
        is_supplier_vat_id_visible = getattr(
            settings, 'INVOICING_IS_SUPPLIER_VAT_ID_VISIBLE', None)

        if is_supplier_vat_id_visible is not None:
            return is_supplier_vat_id_visible(self)

        if self.vat is None and self.supplier_country == self.customer_country:
            return False

        # VAT is not 0
        if self.vat != 0 or self.item_set.filter(tax_rate__gt=0).exists():
            return True

        # VAT is 0, check if customer is from EU and from same country as supplier
        is_EU_customer = EUTaxationPolicy.is_in_EU(
            self.customer_country.code) if self.customer_country else False

        return is_EU_customer and self.supplier_country != self.customer_country

    @property
    def vat_summary(self):
        #rates_and_sum = self.item_set.all().annotate(base=Sum(F('qty')*F('price_per_unit'))).values('tax_rate', 'base')
        #rates_and_sum = self.item_set.all().values('tax_rate').annotate(Sum('price_per_unit'))
        #rates_and_sum = self.item_set.all().values('tax_rate').annotate(Sum(F('qty')*F('price_per_unit')))

        from django.db import connection
        cursor = connection.cursor()
        cursor.execute(
            'select tax_rate as rate, SUM(quantity*unit_price*(100-discount)/100) as base, ROUND(CAST(SUM(quantity*unit_price*((100-discount)/100)*(tax_rate/100)) AS numeric), 2) as vat from invoicing_items where invoice_id = %s group by tax_rate;',
            [self.pk])

        desc = cursor.description
        return [
            dict(zip([col[0] for col in desc], row))
            for row in cursor.fetchall()
        ]

    @cached_property
    def has_discount(self):
        if not self.item_set.exists():
            return False

        discounts = list(set(self.item_set.values_list('discount', flat=True)))
        return len(discounts) > 1 or discounts[0] > 0

    @cached_property
    def has_unit(self):
        if not self.item_set.exists():
            return False

        units = list(set(self.item_set.values_list('unit', flat=True)))
        return len(units) > 1 or units[0] != Item.UNIT_EMPTY

    @cached_property
    def max_quantity(self):
        quantity = self.item_set.aggregate(Max('quantity'))
        return quantity.get('quantity__max', 1) if quantity else 1

    @property
    def subtotal(self):
        sum = 0
        for item in self.item_set.all():
            sum += item.subtotal
        return round(sum, 2)

    def calculate_vat(self):
        if len(self.vat_summary) == 1 and self.vat_summary[0]['vat'] is None:
            return None

        vat = 0
        for vat_rate in self.vat_summary:
            vat += vat_rate['vat'] or 0
        return vat

    def calculate_total(self):
        # TODO: save into model field on post_save signal for InvoiceItem

        #total = self.subtotal + self.vat  # subtotal with vat
        total = 0
        for vat_rate in self.vat_summary:
            total += float(vat_rate['vat'] or 0) + float(vat_rate['base'])

        #total *= float((100 - float(self.discount)) / 100)  # subtract discount amount
        total -= float(self.credit)  # subtract credit
        #total -= self.already_paid  # subtract already paid
        return round(total, 2)
Ejemplo n.º 14
0
class Invoice(models.Model):
    COUNTER_PERIOD = Choices(('DAILY', _('daily')), ('MONTHLY', _('monthly')),
                             ('YEARLY', _('yearly')))

    TYPE = Choices(('INVOICE', _(u'Invoice')),
                   ('ADVANCE', _(u'Advance invoice')),
                   ('PROFORMA', _(u'Proforma invoice')),
                   ('VAT_CREDIT_NOTE', _(u'VAT credit note')))

    STATUS = Choices(('NEW', _(u'new')), ('SENT', _(u'sent')),
                     ('RETURNED', _(u'returned')),
                     ('CANCELED', _(u'canceled')), ('PAID', _(u'paid')))

    PAYMENT_METHOD = Choices(('BANK_TRANSFER', _(u'bank transfer')),
                             ('CASH', _(u'cash')),
                             ('CASH_ON_DELIVERY', _(u'cash on delivery')),
                             ('PAYMENT_CARD', _(u'payment card')))

    DELIVERY_METHOD = Choices(('PERSONAL_PICKUP', _(u'personal pickup')),
                              ('MAILING', _(u'mailing')))

    CONSTANT_SYMBOL = Choices(
        ('0001',
         _(u'0001 - Payments for goods based on legal and executable decision from legal authority'
           )), ('0008', _(u'0008 - Cashless payments for goods')),
        ('0038', _(u'0038 - Cashless funds for wages')),
        ('0058', _(u'0058 - Cashless penalty and delinquency charges')),
        ('0068',
         _(u'0068 - Transfer of funds for wages and other personal costs')),
        ('0138', _(u'0138 - Cashless deductions at source')),
        ('0168', _(u'0168 - Cashless payments in loans')),
        ('0178', _(u'0178 - Sales from provided services')),
        ('0298', _(u'0298 - Other cashless transfers')),
        ('0304', _(u'0304 - Prior payments for services')),
        ('0308', _(u'0308 - Cashless payments for services')),
        ('0358',
         _(u'0358 - Payments dedicated to payout through post offices')),
        ('0379', _(u'0379 - Other income, income from postal order')),
        ('0498', _(u'0498 - Payments in loans')),
        ('0558', _(u'0558 - Cashless other financial payments')),
        ('0934', _(u'0934 - Benefits - prior payments')),
        ('0968', _(u'0968 - Other cashless transfers')),
        ('1144', _(u'1144 - Prior payment - advance')),
        ('1148', _(u'1148 - Payment - current advance')),
        ('1744',
         _(u'1744 - Accounting of tax at income tax of physical body and corporate body'
           )),
        ('1748',
         _(u'1748 - Income tax of physical body and corporate body based on declared tax year'
           )),
        ('3118',
         _(u'3118 - Insurance and empl. contrib. to insur. co. and the Labor Office'
           )), ('3344', _(u'3344 - Penalty from message - prior')),
        ('3354', _(u'3354 - Insurance payments by insurance companies')),
        ('3558',
         _(u'3558 - Cashless insurance payments by insurance companies')),
        ('8147', _(u'8147 - Payment (posted together with the instruction)')))

    # General information
    type = models.CharField(_(u'type'),
                            max_length=64,
                            choices=TYPE,
                            default=TYPE.INVOICE)
    number = models.IntegerField(_(u'number'), db_index=True, blank=True)
    full_number = models.CharField(max_length=128, blank=True)
    status = models.CharField(_(u'status'),
                              choices=STATUS,
                              max_length=64,
                              default=STATUS.NEW)
    subtitle = models.CharField(_(u'subtitle'),
                                max_length=255,
                                blank=True,
                                null=True,
                                default=None)
    language = models.CharField(_(u'language'),
                                max_length=2,
                                choices=settings.LANGUAGES)
    note = models.CharField(_(u'note'),
                            max_length=255,
                            blank=True,
                            null=True,
                            default=_(u'Thank you for using our services.'))
    date_issue = models.DateField(_(u'issue date'))
    date_tax_point = models.DateField(_(u'tax point date'))  # time of supply
    date_due = models.DateField(_(u'due date'))  # payment till
    date_sent = MonitorField(monitor='status',
                             when=[STATUS.SENT],
                             blank=True,
                             null=True,
                             default=None)

    # Payment details
    currency = models.CharField(_(u'currency'),
                                max_length=10,
                                choices=CURRENCY_CHOICES)
    discount = models.DecimalField(_(u'discount (%)'),
                                   max_digits=3,
                                   decimal_places=1,
                                   default=0)
    credit = models.DecimalField(_(u'credit'),
                                 max_digits=10,
                                 decimal_places=2,
                                 default=0)
    #already_paid = models.DecimalField(_(u'already paid'), max_digits=10, decimal_places=2, default=0)

    payment_method = models.CharField(_(u'payment method'),
                                      choices=PAYMENT_METHOD,
                                      max_length=64)
    constant_symbol = models.CharField(_(u'constant symbol'),
                                       max_length=64,
                                       choices=CONSTANT_SYMBOL,
                                       blank=True,
                                       null=True,
                                       default=None)
    variable_symbol = models.PositiveIntegerField(_(u'variable symbol'),
                                                  max_length=10,
                                                  blank=True,
                                                  null=True,
                                                  default=None)
    specific_symbol = models.PositiveIntegerField(_(u'specific symbol'),
                                                  max_length=10,
                                                  blank=True,
                                                  null=True,
                                                  default=None)
    reference = models.CharField(_(u'reference'),
                                 max_length=140,
                                 blank=True,
                                 null=True,
                                 default=None)

    bank_name = models.CharField(_(u'bank name'),
                                 max_length=255,
                                 blank=True,
                                 null=True,
                                 default=lambda: default_supplier('bank.name'))
    bank_street = models.CharField(
        _(u'bank street and number'),
        max_length=255,
        blank=True,
        null=True,
        default=lambda: default_supplier('bank.street'))
    bank_zip = models.CharField(_(u'bank ZIP'),
                                max_length=255,
                                blank=True,
                                null=True,
                                default=lambda: default_supplier('bank.zip'))
    bank_city = models.CharField(_(u'bank city'),
                                 max_length=255,
                                 blank=True,
                                 null=True,
                                 default=lambda: default_supplier('bank.city'))
    bank_country = CountryField(
        _(u'bank country'),
        max_length=255,
        blank=True,
        null=True,
        default=lambda: default_supplier('bank.country_code'))
    bank_iban = IBANField(verbose_name=_(u'Account number (IBAN)'),
                          default=lambda: default_supplier('bank.iban'))
    bank_swift_bic = SWIFTBICField(
        verbose_name=_(u'Bank SWIFT / BIC'),
        default=lambda: default_supplier('bank.swift_bic'))

    # Issuer details
    supplier_name = models.CharField(_(u'supplier name'),
                                     max_length=255,
                                     default=lambda: default_supplier('name'))
    supplier_street = models.CharField(
        _(u'supplier street and number'),
        max_length=255,
        blank=True,
        null=True,
        default=lambda: default_supplier('street'))
    supplier_zip = models.CharField(_(u'supplier ZIP'),
                                    max_length=255,
                                    blank=True,
                                    null=True,
                                    default=lambda: default_supplier('zip'))
    supplier_city = models.CharField(_(u'supplier city'),
                                     max_length=255,
                                     blank=True,
                                     null=True,
                                     default=lambda: default_supplier('city'))
    supplier_country = CountryField(
        _(u'supplier country'),
        default=lambda: default_supplier('country_code'))
    supplier_registration_id = models.CharField(
        _(u'supplier Reg. No.'),
        max_length=255,
        blank=True,
        null=True,
        default=lambda: default_supplier('registration_id'))
    supplier_tax_id = models.CharField(
        _(u'supplier Tax No.'),
        max_length=255,
        blank=True,
        null=True,
        default=lambda: default_supplier('tax_id'))
    supplier_vat_id = VATField(_(u'supplier VAT No.'),
                               blank=True,
                               null=True,
                               default=lambda: default_supplier('vat_id'))
    supplier_additional_info = JSONField(
        _(u'supplier additional information'),
        load_kwargs={'object_pairs_hook': OrderedDict},
        blank=True,
        null=True,
        default=lambda: default_supplier('additional_info'
                                         ))  # for example www or legal matters

    # Contact details
    issuer_name = models.CharField(_(u'issuer name'),
                                   max_length=255,
                                   blank=True,
                                   null=True,
                                   default=None)
    issuer_email = models.EmailField(_(u'issuer email'),
                                     blank=True,
                                     null=True,
                                     default=None)
    issuer_phone = models.CharField(_(u'issuer phone'),
                                    max_length=255,
                                    blank=True,
                                    null=True,
                                    default=None)

    # Customer details
    customer_name = models.CharField(_(u'customer name'), max_length=255)
    customer_street = models.CharField(_(u'customer street and number'),
                                       max_length=255,
                                       blank=True,
                                       null=True,
                                       default=None)
    customer_zip = models.CharField(_(u'customer ZIP'),
                                    max_length=255,
                                    blank=True,
                                    null=True,
                                    default=None)
    customer_city = models.CharField(_(u'customer city'),
                                     max_length=255,
                                     blank=True,
                                     null=True,
                                     default=None)
    customer_country = CountryField(_(u'customer country'))
    customer_registration_id = models.CharField(_(u'customer Reg. No.'),
                                                max_length=255,
                                                blank=True,
                                                null=True,
                                                default=None)
    customer_tax_id = models.CharField(_(u'customer Tax No.'),
                                       max_length=255,
                                       blank=True,
                                       null=True,
                                       default=None)
    customer_vat_id = VATField(_(u'customer VAT ID'),
                               blank=True,
                               null=True,
                               default=None)
    customer_additional_info = JSONField(
        _(u'customer additional information'),
        load_kwargs={'object_pairs_hook': OrderedDict},
        blank=True,
        null=True,
        default=None)

    # Shipping details
    shipping_name = models.CharField(_(u'shipping name'),
                                     max_length=255,
                                     blank=True,
                                     null=True,
                                     default=None)
    shipping_street = models.CharField(_(u'shipping street and number'),
                                       max_length=255,
                                       blank=True,
                                       null=True,
                                       default=None)
    shipping_zip = models.CharField(_(u'shipping ZIP'),
                                    max_length=255,
                                    blank=True,
                                    null=True,
                                    default=None)
    shipping_city = models.CharField(_(u'shipping city'),
                                     max_length=255,
                                     blank=True,
                                     null=True,
                                     default=None)
    shipping_country = CountryField(_(u'shipping country'),
                                    blank=True,
                                    null=True,
                                    default=None)

    # Delivery details
    delivery_method = models.CharField(_(u'delivery method'),
                                       choices=DELIVERY_METHOD,
                                       max_length=64,
                                       default=DELIVERY_METHOD.PERSONAL_PICKUP)

    # Other
    created = models.DateTimeField(_(u'created'), auto_now_add=True)
    modified = models.DateTimeField(_(u'modified'), auto_now=True)

    class Meta:
        db_table = 'invoicing_invoices'
        verbose_name = _(u'invoice')
        verbose_name_plural = _(u'invoices')
        ordering = ('date_issue', 'number')

    def __unicode__(self):
        return self.full_number

    def save(self, **kwargs):
        if self.number in EMPTY_VALUES:
            self.number = self._get_next_number()

        if self.full_number in EMPTY_VALUES:
            self.full_number = self._get_full_number()

        return super(Invoice, self).save(**kwargs)

    def get_absolute_url(self):
        return reverse('invoicing:invoice_detail', args=(self.pk, ))

    def _get_next_number(self):
        """
        Returnes next invoice number based on ``settings.INVOICING_COUNTER_PERIOD``.

        .. warning::

            This is only used to prepopulate ``number`` field on saving new invoice.
            To get invoice number always use ``number`` field.

        .. note::

            To get invoice full number use ``full_number`` field.

        :return: string (generated next number)
        """
        invoice_counter_reset = getattr(settings, 'INVOICING_COUNTER_PERIOD',
                                        Invoice.COUNTER_PERIOD.YEARLY)

        if invoice_counter_reset == Invoice.COUNTER_PERIOD.DAILY:
            relative_invoices = Invoice.objects.filter(
                date_issue=self.date_issue, type=self.type)

        elif invoice_counter_reset == Invoice.COUNTER_PERIOD.YEARLY:
            relative_invoices = Invoice.objects.filter(
                date_issue__year=self.date_issue.year, type=self.type)

        elif invoice_counter_reset == Invoice.COUNTER_PERIOD.MONTHLY:
            relative_invoices = Invoice.objects.filter(
                date_issue__year=self.date_issue.year,
                date_issue__month=self.date_issue.month,
                type=self.type)

        else:
            raise ImproperlyConfigured(
                "INVOICING_COUNTER_PERIOD can be set only to these values: DAILY, MONTHLY, YEARLY."
            )

        last_number = relative_invoices.aggregate(
            Max('number'))['number__max'] or 0

        return last_number + 1

    def _get_full_number(self):
        """
        Generates on the fly invoice full number from template provided by ``settings.INVOICING_NUMBER_FORMAT``.
        ``Invoice`` object is provided as ``invoice`` variable to the template, therefore all object fields
        can be used to generate full number format.

        .. warning::

            This is only used to prepopulate ``full_number`` field on saving new invoice.
            To get invoice full number always use ``full_number`` field.

        :return: string (generated full number)
        """
        number_format = getattr(
            settings, "INVOICING_NUMBER_FORMAT",
            "{{ invoice.date_issue|date:'Y' }}/{{ invoice.number }}")
        return Template(number_format).render(Context({'invoice': self}))

    @property
    def taxation_policy(self):
        taxation_policy = getattr(settings, 'INVOICING_TAXATION_POLICY', None)
        if taxation_policy is not None:
            return import_name(taxation_policy)

        # Check if supplier is from EU
        if self.supplier_country:
            if EUTaxationPolicy.is_in_EU(self.supplier_country.code):
                return EUTaxationPolicy

        return None

    @property
    def is_overdue(self):
        return self.date_due < now().date() and self.status != self.STATUS.PAID

    @property
    def overdue_days(self):
        return (now().date() - self.date_due).days

    @property
    def payment_term(self):
        return (self.date_due - self.date_issue).days

    def set_supplier_data(self, supplier):
        self.supplier_name = supplier.get('name')
        self.supplier_street = supplier.get('street', None)
        self.supplier_zip = supplier.get('zip', None)
        self.supplier_city = supplier.get('city', None)
        self.supplier_country = supplier.get('country_code')
        self.supplier_registration_id = supplier.get('registration_id', None)
        self.supplier_tax_id = supplier.get('tax_id', None)
        self.supplier_vat_id = supplier.get('vat_id', None)
        self.supplier_additional_info = supplier.get('additional_info', None)

        bank = supplier.get('bank')
        self.bank_name = bank.get('name')
        self.bank_street = bank.get('street')
        self.bank_zip = bank.get('zip')
        self.bank_city = bank.get('city')
        self.bank_country = bank.get('country_code')
        self.bank_iban = bank.get('iban')
        self.bank_swift_bic = bank.get('swift_bic')

    def set_customer_data(self, customer):
        self.customer_name = customer.get('name')
        self.customer_street = customer.get('street', None)
        self.customer_zip = customer.get('zip', None)
        self.customer_city = customer.get('city', None)
        self.customer_country = customer.get('country_code')
        self.customer_registration_id = customer.get('registration_id', None)
        self.customer_tax_id = customer.get('tax_id', None)
        self.customer_vat_id = customer.get('vat_id', None)
        self.customer_additional_info = customer.get('additional_info', None)

    def set_shipping_data(self, shipping):
        self.shipping_name = shipping.get('name', None)
        self.shipping_street = shipping.get('street', None)
        self.shipping_zip = shipping.get('zip', None)
        self.shipping_city = shipping.get('city', None)
        self.shipping_country = shipping.get('country_code', None)

    def is_supplier_vat_id_visible(self):
        # VAT is not 0
        if self.vat != 0 or self.invoiceitem_set.filter(
                tax_rate__gt=0).exists():
            return True

        # VAT is 0, check if customer is from EU and from same country as supplier
        is_EU_customer = EUTaxationPolicy.is_in_EU(
            self.customer_country.code) if self.customer_country else False

        return is_EU_customer and self.supplier_country != self.customer_country

    @property
    def subtotal(self):
        sum = 0
        for item in self.invoiceitem_set.all():
            sum += item.subtotal
        return round_to_two_places(sum)

    @property
    def vat(self):
        vat = 0
        for item in self.invoiceitem_set.all():
            vat += item.vat
        return round_to_two_places(vat)

    @property
    def discount_value(self):
        total = self.subtotal + self.vat  # subtotal with vat
        discount_value = total * (Decimal(self.discount) / 100
                                  )  # subtract discount amount
        return round_to_two_places(discount_value)

    @property
    def total(self):
        total = self.subtotal + self.vat  # subtotal with vat
        total *= (
            (100 - Decimal(self.discount)) / 100)  # subtract discount amount
        total -= self.credit  # subtract credit
        #total -= self.already_paid  # subtract already paid
        return round_to_two_places(total)
Ejemplo n.º 15
0
class Invoice(models.Model):
    client = models.ForeignKey(User, related_name='invoices',
                               null=True, on_delete=models.SET_NULL)

    name = models.CharField(max_length=100, default='My invoice')

    YEARLY = 'Y'
    MONTHLY = 'M'
    WEEKLY = 'W'
    DAILY = 'D'
    REGULARITY_CHOICES = [
        (YEARLY, 'Yearly'),
        (MONTHLY, 'Monthly'),
        (WEEKLY, 'Weekly'),
        (DAILY, 'Daily'),
    ]
    regularity = models.CharField(max_length=1,
                                  choices=REGULARITY_CHOICES,
                                  default=MONTHLY)
    is_regular = models.BooleanField()
    due_date = models.DateField()
    is_paid = models.BooleanField(default=False)

    WEBSITE = 'WEB'
    FILE = 'FIL'
    CREDENTIALS = 'CRD'
    INVOICE_TYPE_CHOICES = [
        (WEBSITE, 'Website'),
        (FILE, 'File'),
        (CREDENTIALS, 'Credentials'),
    ]
    invoice_type = models.CharField(max_length=3,
                                    choices=INVOICE_TYPE_CHOICES)

    website = models.URLField(blank=True)
    login = models.CharField(max_length=100, blank=True)
    password = models.CharField(max_length=100, blank=True)

    file = models.FileField(upload_to='user_files', blank=True)

    iban = IBANField(blank=True)
    full_name = models.CharField(max_length=100, blank=True)

    total = models.DecimalField(decimal_places=2, blank=True,
                                max_digits=9)
    comments = models.TextField()

    def get_regular_delta(self) -> relativedelta:
        if self.regularity == self.DAILY:
            return relativedelta(days=1)
        if self.regularity == self.WEEKLY:
            return relativedelta(weeks=1)
        if self.regularity == self.MONTHLY:
            return relativedelta(months=1)
        if self.regularity == self.YEARLY:
            return relativedelta(years=1)

    def pay(self, author: User):
        # todo validation
        self.client.add_to_balance(-self.total)
        if self.is_regular:
            self.due_date += self.get_regular_delta()
        else:
            self.is_paid = True
        self.invoice_logs.create(paid_by=author)
        self.save()

    def __str__(self):
        return f"Invoice {self.name} till {self.due_date}"
Ejemplo n.º 16
0
class Contact(MoneybirdSynchronizableResourceModel):
    class Meta:
        verbose_name = "contact"
        verbose_name_plural = "contacts"

    moneybird_resource_path_name = "contacts"
    moneybird_resource_name = "contact"

    moneybird_data_fields = [
        "company_name",
        "firstname",
        "lastname",
        "attention",
        "address1",
        "address2",
        "zipcode",
        "city",
        "country",
        "phone",
        "delivery_method",
        "send_invoices_to_attention",
        "send_invoices_to_email",
        "send_estimates_to_attention",
        "send_estimates_to_email",
        "email",
        "email_ubl",
        "customer_id",
        "chamber_of_commerce",
        "tax_number",
        "bank_account",
        "sepa_active",
        "sepa_iban",
        "sepa_iban_account_name",
        "sepa_bic",
        "sepa_mandate_id",
        "sepa_sequence_type",
    ]
    moneybird_readonly_data_fields = ["attention", "email"]

    DELIVERY_METHOD_EMAIL = "Email"
    DELIVERY_METHOD_SIMPLERINVOICING = "Simplerinvoicing"
    DELIVERY_METHOD_POST = "Post"
    DELIVERY_METHOD_MANUAL = "Manual"
    DELIVERY_METHOD_CHOICES = (
        (DELIVERY_METHOD_EMAIL, "Email"),
        (DELIVERY_METHOD_SIMPLERINVOICING, "Simplerinvoicing"),
        (DELIVERY_METHOD_POST, "Post"),
        (DELIVERY_METHOD_MANUAL, "Manual"),
    )

    SEPA_RCUR = "RCUR"
    SEPA_FRST = "FRST"
    SEPA_OOFF = "OOFF"
    SEPA_FNAL = "FNAL"
    SEPA_SEQUENCE_TYPE_CHOICES = (
        (SEPA_RCUR, "RCUR"),
        (SEPA_FRST, "FRST"),
        (SEPA_OOFF, "OOFF"),
        (SEPA_FNAL, "FNAL"),
    )

    company_name = models.CharField(blank=True, null=True, max_length=100)
    firstname = models.CharField(blank=True, null=True, max_length=100)
    lastname = models.CharField(blank=True, null=True, max_length=100)
    address1 = models.CharField(blank=True, null=True, max_length=100)
    address2 = models.CharField(blank=True, null=True, max_length=100)
    zipcode = models.CharField(blank=True, null=True, max_length=10)
    city = models.CharField(blank=True, null=True, max_length=100)
    country = CountryField(
        blank=True,
        null=True,
        help_text="Will be automatically set to the standard Moneybird administration country if empty.",
    )
    phone = models.CharField(blank=True, null=True, max_length=100)
    delivery_method = models.CharField(
        blank=True, null=True, choices=DELIVERY_METHOD_CHOICES, default=DELIVERY_METHOD_EMAIL, max_length=16
    )
    customer_id = models.IntegerField(
        blank=True,
        null=True,
        help_text="Will be assigned automatically if empty. Should be unique for the administration.",
    )
    tax_number = models.CharField(blank=True, null=True, max_length=100)
    chamber_of_commerce = models.CharField(blank=True, null=True, max_length=100)
    bank_account = models.CharField(blank=True, null=True, max_length=100)
    attention = models.CharField(blank=True, null=True, max_length=100)

    email = models.CharField(blank=True, null=True, max_length=200,)
    email_ubl = models.BooleanField(blank=True, null=True)
    send_invoices_to_attention = models.CharField(blank=True, null=True, max_length=100)
    send_invoices_to_email = models.CharField(
        blank=True, null=True, max_length=200, help_text="Can be a single email or a comma-separated list of emails"
    )
    send_estimates_to_attention = models.CharField(blank=True, null=True, max_length=100)
    send_estimates_to_email = models.CharField(
        blank=True, null=True, max_length=200, help_text="Can be a single email or a comma-separated list of emails"
    )
    sepa_active = models.BooleanField(default=False, help_text="When true, all SEPA fields are required.")
    sepa_iban = IBANField(enforce_database_constraint=True, blank=True, null=True, max_length=100)
    sepa_iban_account_name = models.CharField(blank=True, null=True, max_length=100)
    sepa_bic = models.CharField(blank=True, null=True, max_length=100)
    sepa_mandate_id = models.CharField(blank=True, null=True, max_length=100)
    sepa_mandate_date = models.DateField(blank=True, null=True, help_text="Should be a date in the past.")
    sepa_sequence_type = models.CharField(blank=True, null=True, choices=SEPA_SEQUENCE_TYPE_CHOICES, max_length=4)
    # TODO add sales_invoices_url

    def get_moneybird_attr(self, field):
        if field == "country":
            return self.country.code
        return super(Contact, self).get_moneybird_attr(field)

    def set_moneybird_attr(self, field, value):
        if field == "country":
            self.country = value
        return super(Contact, self).set_moneybird_attr(field, value)

    def get_full_name(self):
        if self.firstname and self.lastname:
            return f"{self.firstname} {self.lastname}"
        elif self.firstname:
            return self.firstname
        return self.lastname

    def get_display_name(self):
        if self.company_name and self.get_full_name():
            return f"{self.company_name} ({self.get_full_name()})"
        elif self.company_name:
            return self.company_name
        return self.get_full_name()

    def __str__(self):
        if self.customer_id:
            return f"{self.get_display_name()} ({self.customer_id})"
        return self.get_display_name()
Ejemplo n.º 17
0
class Account(models.Model):
    number = IBANField(primary_key=True)
    label = models.CharField(max_length=255)

    def __str__(self):
        return self.label