from decimal import Decimal from django.db import models from flower.common import ModelBase from basic_info import models as basic_info_models class PurchaseOrderKindEnum(models.IntegerChoices): """采购单类型""" WHOLESALE = 1, '大货' SAMPLE = 2, '样板' class PurchaseOrderStatusEnum(models.IntegerChoices): """采购单状态""" PENDING = 1, '审批中' APPROVED = 2, '审批通过' CANCELLED = 3, '作废' class PurchaseOrder(ModelBase): """采购单模型(业务模块)""" id = models.BigAutoField(primary_key=True) merchant = models.ForeignKey( basic_info_models.Merchant, on_delete=models.PROTECT, related_name='purchase_orders', verbose_name='所属商户', ) supplier = models.ForeignKey( basic_info_models.Supplier, on_delete=models.PROTECT, related_name='purchase_orders', verbose_name='供应商', ) purchase_date = models.DateField(verbose_name='采购日期') kind = models.IntegerField( choices=PurchaseOrderKindEnum.choices, default=PurchaseOrderKindEnum.WHOLESALE, verbose_name='采购单类型', ) operator = models.ForeignKey( basic_info_models.Employee, on_delete=models.PROTECT, related_name='purchase_orders', verbose_name='经办人', ) warehouse = models.ForeignKey( basic_info_models.WareHouse, on_delete=models.PROTECT, related_name='purchase_orders', verbose_name='仓库', ) status = models.IntegerField( choices=PurchaseOrderStatusEnum.choices, default=PurchaseOrderStatusEnum.PENDING, verbose_name='状态', ) remarks = models.TextField(blank=True, null=True, verbose_name='备注') def __str__(self): return f'采购订单 {self.id} - {self.supplier.name}' class Meta: verbose_name = '采购单' verbose_name_plural = '采购单' def get_total_amount(self) -> Decimal: return sum(item.total_amount() for item in self.items.all()) def get_total_quantity(self) -> Decimal: return sum(item.quantity for item in self.items.all()) def get_total_diff_quantity(self) -> Decimal: return sum(item.diff_quantity() for item in self.items.all()) class PurchaseOrderItem(ModelBase): """采购单明细模型""" id = models.BigAutoField(primary_key=True) purchase_order = models.ForeignKey( PurchaseOrder, on_delete=models.CASCADE, related_name='items', verbose_name='采购单', ) product = models.ForeignKey( basic_info_models.Product, on_delete=models.PROTECT, related_name='purchase_order_items', verbose_name='产品', ) price = models.DecimalField(max_digits=15, decimal_places=2, verbose_name='单价') color = models.CharField(max_length=50, null=True, blank=True, verbose_name='颜色') quantity = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='数量') unit = models.CharField(max_length=50, verbose_name='单位') spec = models.CharField(max_length=100, null=True, blank=True, verbose_name='规格') empty_diff_percent = models.DecimalField( max_digits=15, decimal_places=2, verbose_name='空差百分比', ) # if purchase_order.warehouse.mode != WarehouseModeEnum.UNRESTRICTED, then quantity_of_rolls is required quantity_of_rolls = models.CharField( max_length=255, null=True, blank=True, verbose_name='各条数数量', ) num_of_rolls = models.PositiveIntegerField(default=1, verbose_name='条数') batch_number = models.CharField(null=True, blank=True, max_length=100, verbose_name='批次号') remarks = models.TextField(blank=True, null=True, verbose_name='备注') class Meta: verbose_name = '采购单明细' verbose_name_plural = '采购单明细' def real_quantity(self): return round(self.quantity * (1 - self.empty_diff_percent / 100), 2) def diff_quantity(self): return round(self.quantity * (self.empty_diff_percent / 100), 2) def total_amount(self): return round(self.price * self.real_quantity(), 2)