from django.db import models from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.fields import GenericForeignKey from dateutil.relativedelta import relativedelta class AuthoringDatesModel(models.Model): created_at = models.DateTimeField(auto_now_add=True, null=True) modified_at = models.DateTimeField(auto_now=True) class Meta: abstract = True class Source(AuthoringDatesModel): name = models.CharField(max_length=150) def __str__(self): return self.name class OnlineSource(Source): url = models.URLField(max_length=200) class PhysicalSource(Source): # TODO auto add coordinates by searching shop address latitude = models.FloatField() longitude = models.FloatField() class Category(AuthoringDatesModel): name = models.CharField(max_length=150) type = models.CharField( max_length=20, choices=[ ("Fixed", "Fixed expense"), ("Variable", "Variable expense"), ], default="Variable", ) # Surcharge de la manière d'afficher un objet sensor def __str__(self): return self.name class Meta: # db_table = 'book' # Permet de personnaliser le nom de la table en BDD verbose_name = "Category" # Le nom lisbile du modèle verbose_name_plural = "Categories" # Le nom au pluriel du modèle ordering = ("name", "type") # Le tri par défaut dans les listes class MetaExpense(AuthoringDatesModel): category = models.ForeignKey( Category, related_name="%(app_label)s_%(class)s_related", on_delete=models.PROTECT, ) source = models.ForeignKey( Source, related_name="%(app_label)s_%(class)s_related", on_delete=models.PROTECT ) class Meta: abstract = True class RawExpense(models.Model): name = models.CharField(max_length=150) date = models.DateField() amount = models.DecimalField(max_digits=10, decimal_places=2) class LoneExpense(RawExpense, MetaExpense): def __str__(self): return self.name class Meta: # db_table = 'book' # Permet de personnaliser le nom de la table en BDD verbose_name = "LoneExpense" # Le nom lisbile du modèle verbose_name_plural = "LoneExpenses" # Le nom au pluriel du modèle ordering = ("name", "date", "amount") # Le tri par défaut dans les listes class Expense(models.Model): object_id = models.PositiveIntegerField() content_type = models.ForeignKey( ContentType, related_name="%(app_label)s_%(class)s_related", on_delete=models.CASCADE, ) content_object = GenericForeignKey("content_type", "object_id") # Surcharge de la manière d'afficher un objet sensor def __str__(self): return self.content_object.name class Meta: # db_table = 'book' # Permet de personnaliser le nom de la table en BDD verbose_name = "Expense" # Le nom lisbile du modèle verbose_name_plural = "Expenses" # Le nom au pluriel du modèle """ ordering = ("name", "date", "amount") # Le tri par défaut dans les listes """ class MultiplePaymentExepense(RawExpense, MetaExpense): payments = models.ManyToManyField( RawExpense, related_name="multiple_payment_expense" ) number_of_payment = models.PositiveIntegerField() def set_payments(self, first_payment_amout): print(f"set payment 0 {first_payment_amout}") payment = RawExpense( date=self.date, name=self.name + " 1 payment", amount=first_payment_amout ) self.save() payment.save() print(f"set payment 1 {payment.amount}") self.payments.add(payment) print("set payment 2") rest_to_pay = (self.amount - payment.amount) / (self.number_of_payment - 1) for i in range(1, self.number_of_payment): print(i) date = self.date + relativedelta(months=i) payment = RawExpense( name=f"{self.name} {i+1} payment", date=date, amount=rest_to_pay ) payment.save() self.payments.add(payment) self.save() print(self.payments.count()) def __str__(self): return self.name class Meta: # db_table = 'book' # Permet de personnaliser le nom de la table en BDD verbose_name = "MultiplePaymentExpense" # Le nom lisbile du modèle verbose_name_plural = "MultiplePaymentExpenses" # Le nom au pluriel du modèle ordering = ("name", "date", "amount")