from django.db import models from django.utils.translation import gettext_lazy as _ from django.core.exceptions import ValidationError class Sale(models.Model): customer = models.CharField(max_length=100) date = models.DateField("Date") phone = models.CharField(max_length=13, null=True, blank=True) description = models.CharField(max_length=255, null=True, blank=True) def __str__(self): return f"{self.date} {self.customer}" class SaleLine(models.Model): sale = models.ForeignKey(Sale, on_delete=models.CASCADE) product = models.CharField(max_length=100) quantity = models.IntegerField(null=True) unit_price = models.DecimalField(max_digits=9, decimal_places=2) description = models.CharField(max_length=255, null=True, blank=True) def __str__(self): return f"{self.sale} - {self.product}" class MeasuringUnits(models.TextChoices): UNIT = 'UNIT', _('Unit') class ProductCategory(models.Model): name = models.CharField(max_length=100, unique=True) def __str__(self): return self.name class Product(models.Model): name = models.CharField(max_length=100, unique=True) price = models.DecimalField(max_digits=9, decimal_places=2) measuring_unit = models.CharField( max_length=20, choices=MeasuringUnits.choices, default=MeasuringUnits.UNIT ) categories = models.ManyToManyField(ProductCategory) def __str__(self): return self.name class PyamentMethods(models.TextChoices): CASH = 'CASH', _('Cash') CONFIAR = 'CONFIAR', _('Confiar') BANCOLOMBIA = 'BANCOLOMBIA', _('Bancolombia') class ReconciliationJarSummary(): def __init__(self, payments): self._validate_payments(payments) self._payments = payments def _validate_payments(self, payments): pass @property def total(self): return sum([p.amount for p in self.payments]) @property def payments(self): return self._payments class ReconciliationJar(models.Model): is_valid = models.BooleanField(default=False) date_time = models.DateTimeField() description = models.CharField(max_length=255, null=True, blank=True) reconcilier = models.CharField(max_length=255, null=False, blank=False) cash_taken = models.DecimalField(max_digits=9, decimal_places=2) cash_discrepancy = models.DecimalField(max_digits=9, decimal_places=2) def manual_clean(self): payments_amount = sum([p.amount for p in self.payment_set.all()]) reconciliation_ammount = sum([ self.cash_taken, self.cash_discrepancy, ]) if reconciliation_ammount != payments_amount: raise ValidationError( {"cash_take": _("The taken ammount has discrepancy.")} ) self.is_valid = True class Payment(models.Model): date_time = models.DateTimeField() type_payment = models.CharField( max_length=30, choices=PyamentMethods.choices, default=PyamentMethods.CASH ) amount = models.DecimalField(max_digits=9, decimal_places=2) reconciliation_jar = models.ForeignKey( ReconciliationJar, null=True, default=None, blank=True, on_delete=models.RESTRICT ) description = models.CharField(max_length=255, null=True, blank=True) @classmethod def get_reconciliation_jar_summary(cls): return ReconciliationJarSummary( cls.objects.filter( type_payment=PyamentMethods.CASH, reconciliation_jar=None ) )