expephalon/core/models/billable.py

58 lines
2.1 KiB
Python

from django.db.models import IntegerChoices, Model, ForeignKey, CASCADE, TextField, PositiveIntegerField, BooleanField, DateField
from django.utils import timezone
from core.models.profiles import ClientProfile
from core.models.brands import Brand
from core.fields.base import LongCharField
from core.fields.numbers import CostField
from core.models.local import Currency
from dateutil.relativedelta import relativedelta
class ActionChoices(IntegerChoices):
WAIT = 0, "Do not invoice for now"
NEXT = 1, "Add to client's next invoice"
CRON = 2, "Invoice at next cron run"
DATE = 3, "Invoice at date"
class CycleChoices(IntegerChoices):
DAYS = 0, "Days"
WEEKS = 1, "Weeks"
MONTHS = 2, "Months"
YEARS = 3, "Years"
class Billable(Model):
client = ForeignKey(ClientProfile, on_delete=CASCADE)
brand = ForeignKey(Brand, on_delete=CASCADE)
name = LongCharField()
description = TextField()
individual_cost = CostField()
amount = PositiveIntegerField()
currency = ForeignKey(Currency, on_delete=CASCADE)
taxable = BooleanField()
action = PositiveIntegerField(choices=ActionChoices.choices)
date = DateField(null=True)
recur_cycle = PositiveIntegerField(choices=CycleChoices.choices, null=True)
recur_count = PositiveIntegerField(null=True)
def next_invoicing(self):
from core.models.invoices import InvoiceItem, Invoice
if not self.recur_cycle == ActionChoices.DATE:
return False
try:
invoiceitems = InvoiceItem.objects.filter(billable=self)
invoice = Invoice.objects.filter(invoiceitem_set__contains=invoiceitems).latest("created")
delta = relativedelta(days=self.recur_count if self.recur_cycle == CycleChoices.DAYS else 0,
weeks=self.recur_count if self.recur_cycle == CycleChoices.WEEKS else 0,
months=self.recur_count if self.recur_cycle == CycleChoices.MONTHS else 0,
years=self.recur_count if self.recur_cycle == CycleChoices.YEARS else 0)
return invoice.created + delta
except:
return self.date