"""销售模型:SalesOrder(销售订单)+ SalesBill(销售单/出库单)。""" from decimal import Decimal from django.db import models from apps.core.base_models import TenantScopedModel class SalesOrder(TenantScopedModel): """销售订单(可选,预先订货流程)。""" STATE_CHOICES = [ ("draft", "草稿"), ("confirmed", "已确认"), ("delivered", "已发货"), ("cancelled", "已取消"), ] bill_no = models.CharField(max_length=64) customer = models.ForeignKey( "partner.Customer", on_delete=models.PROTECT, related_name="sales_orders", ) warehouse = models.ForeignKey( "inventory.Warehouse", on_delete=models.PROTECT, related_name="sales_orders", ) bill_date = models.DateField() expected_date = models.DateField(null=True, blank=True) total_amount = models.DecimalField(max_digits=18, decimal_places=4, default=0) state = models.CharField(max_length=16, choices=STATE_CHOICES, default="draft") remark = models.TextField(blank=True, default="") class Meta: db_table = "sales_order" unique_together = [("tenant", "bill_no")] ordering = ["-bill_date", "-id"] verbose_name_plural = "销售订单" class SalesOrderLine(TenantScopedModel): order = models.ForeignKey( SalesOrder, on_delete=models.CASCADE, related_name="lines" ) product = models.ForeignKey( "catalog.Product", on_delete=models.PROTECT, related_name="so_lines" ) source_unit = models.ForeignKey( "catalog.Unit", null=True, blank=True, on_delete=models.SET_NULL, related_name="%(class)s_lines", help_text="录入单位(空=按基本单位)", ) source_quantity = models.DecimalField( max_digits=18, decimal_places=4, null=True, blank=True, help_text="录入数量(按录入单位;quantity 恒为基本单位数量)", ) quantity = models.DecimalField(max_digits=18, decimal_places=4) unit_price = models.DecimalField(max_digits=18, decimal_places=4) amount = models.DecimalField(max_digits=18, decimal_places=4, default=0) delivered_qty = models.DecimalField(max_digits=18, decimal_places=4, default=0) class Meta: db_table = "sales_order_line" ordering = ["id"] class SalesBill(TenantScopedModel): """销售单(实际出库时生成)。""" STATE_CHOICES = [ ("draft", "草稿"), ("confirmed", "已过账"), ("cancelled", "已取消"), ] bill_no = models.CharField(max_length=64) customer = models.ForeignKey( "partner.Customer", on_delete=models.PROTECT, related_name="sales_bills", ) warehouse = models.ForeignKey( "inventory.Warehouse", on_delete=models.PROTECT, related_name="sales_bills", ) order = models.ForeignKey( SalesOrder, null=True, blank=True, on_delete=models.SET_NULL, related_name="bills", ) bill_date = models.DateField() total_amount = models.DecimalField(max_digits=18, decimal_places=4, default=0) round_off = models.DecimalField( max_digits=18, decimal_places=4, default=0, help_text="抹零金额(行合计-净额)" ) state = models.CharField(max_length=16, choices=STATE_CHOICES, default="draft") remark = models.TextField(blank=True, default="") class Meta: db_table = "sales_bill" unique_together = [("tenant", "bill_no")] ordering = ["-bill_date", "-id"] verbose_name_plural = "销售单" class SalesBillLine(TenantScopedModel): bill = models.ForeignKey( SalesBill, on_delete=models.CASCADE, related_name="lines" ) product = models.ForeignKey( "catalog.Product", on_delete=models.PROTECT, related_name="sb_lines" ) source_unit = models.ForeignKey( "catalog.Unit", null=True, blank=True, on_delete=models.SET_NULL, related_name="%(class)s_lines", help_text="录入单位(空=按基本单位)", ) source_quantity = models.DecimalField( max_digits=18, decimal_places=4, null=True, blank=True, help_text="录入数量(按录入单位;quantity 恒为基本单位数量)", ) quantity = models.DecimalField(max_digits=18, decimal_places=4) unit_price = models.DecimalField(max_digits=18, decimal_places=4) amount = models.DecimalField(max_digits=18, decimal_places=4, default=0) # 税率(D4):行级快照,避免事后改商品税率影响历史单据 tax_rate = models.DecimalField( max_digits=6, decimal_places=4, default=0, help_text="行税率(0.13 = 13%);价内口径:amount 为含税额", ) tax_amount = models.DecimalField( max_digits=18, decimal_places=4, default=0, help_text="行税额(从含税额中拆出)", ) class Meta: db_table = "sales_bill_line" ordering = ["id"]