from decimal import Decimal from django.conf import settings from django.core.validators import MinValueValidator, RegexValidator from django.db import models class ReportingEntry(models.Model): """Supplementary, documented facts absent from the operational sources. Purchases and cash movements are not automatically expensed again in profit: sales already carry their cost of goods. Corrections retain the audit trail. """ class Kind(models.TextChoices): PRODUCTION = "production", "Выпуск продукции" PURCHASE = "purchase", "Закупка для производства" TAX = "tax", "Уплаченные налоги сотрудника" OVERHEAD = "overhead", "Общие расходы" CASH_IN = "cash_in", "Поступление денег" CASH_OUT = "cash_out", "Выплата денег" kind = models.CharField(max_length=16, choices=Kind.choices) date = models.DateField("Дата факта", db_index=True) reference = models.CharField("Документ / уникальный номер", max_length=200) description = models.CharField("Описание", max_length=500, blank=True) external_project = models.ForeignKey( "commerce.ExternalProject", null=True, blank=True, on_delete=models.PROTECT ) project = models.ForeignKey( "projects.Project", null=True, blank=True, on_delete=models.PROTECT ) product = models.ForeignKey( "commerce.Product", null=True, blank=True, on_delete=models.PROTECT ) employee = models.ForeignKey( settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.PROTECT ) quantity = models.DecimalField( max_digits=18, decimal_places=4, default=0, validators=[MinValueValidator(Decimal("0"))], ) amount = models.DecimalField( max_digits=18, decimal_places=2, default=0, validators=[MinValueValidator(Decimal("0"))], ) currency = models.CharField( max_length=3, default="RUB", validators=[RegexValidator(r"^[A-Z]{3}$")] ) created_by = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.PROTECT, related_name="reporting_entries_created", ) created_at = models.DateTimeField(auto_now_add=True) voided_at = models.DateTimeField(null=True, blank=True) voided_by = models.ForeignKey( settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.PROTECT, related_name="reporting_entries_voided", ) class Meta: ordering = ["-date", "-pk"] constraints = [ models.UniqueConstraint( fields=["kind", "reference"], name="reporting_entry_reference_unique" ), models.CheckConstraint( condition=models.Q(amount__gte=0, quantity__gte=0), name="reporting_entry_nonnegative", ), models.CheckConstraint( condition=( models.Q( kind="production", product__isnull=False, employee__isnull=True, quantity__gt=0, amount=0, ) | models.Q(kind="purchase", employee__isnull=True, amount__gt=0) | models.Q( kind="tax", employee__isnull=False, product__isnull=True, amount__gt=0, quantity=0, ) | models.Q( kind__in=["overhead", "cash_in", "cash_out"], product__isnull=True, employee__isnull=True, amount__gt=0, quantity=0, ) ), name="reporting_entry_kind_fields", ), ]