import uuid from decimal import Decimal from django.db import models from django.db.models import Q class CostType(models.TextChoices): COMMISSION = "commission", "Комиссия" DELIVERY = "delivery", "Доставка" STORAGE = "storage", "Хранение" ADVERTISING = "advertising", "Реклама" ACQUIRING = "acquiring", "Эквайринг" RETURN = "return", "Возврат" OTHER = "other", "Прочее" class Cost(models.Model): """Additional product- or sale-line-level expense.""" id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) project = models.ForeignKey( "commerce.ExternalProject", null=True, blank=True, on_delete=models.PROTECT ) source = models.ForeignKey( "commerce.SourceSystem", on_delete=models.PROTECT, related_name="costs", verbose_name="Источник", ) product = models.ForeignKey( "commerce.Product", on_delete=models.PROTECT, null=True, blank=True, related_name="costs", verbose_name="Товар", ) sale_line = models.ForeignKey( "commerce.SaleLine", on_delete=models.CASCADE, null=True, blank=True, related_name="costs", verbose_name="Позиция продажи", ) external_id = models.CharField("Внешний ID", max_length=255, blank=True) channel = models.CharField("Канал продаж", max_length=64, blank=True, db_index=True) cost_type = models.CharField("Тип расхода", max_length=32, choices=CostType.choices) amount = models.DecimalField( "Сумма", max_digits=18, decimal_places=2, default=Decimal("0") ) currency = models.CharField("Валюта", max_length=3, default="RUB") occurred_at = models.DateTimeField("Дата расхода", db_index=True) metadata = models.JSONField("Дополнительные данные", default=dict, blank=True) created_at = models.DateTimeField("Создано", auto_now_add=True) class Meta: verbose_name = "Расход" verbose_name_plural = "Расходы" constraints = [ models.CheckConstraint( condition=Q(product__isnull=False) | Q(sale_line__isnull=False) | Q(project__isnull=False), name="commerce_cost_has_target", ), models.UniqueConstraint( fields=["source", "external_id", "cost_type"], condition=~Q(external_id=""), name="commerce_cost_source_external_type", ), ] indexes = [ models.Index( fields=["product", "occurred_at"], name="commerce_cost_product_date" ) ] def __str__(self): return f"{self.get_cost_type_display()}: {self.amount} {self.currency}"