baseline: 批次A-D 成果 + membership 半成品(测试红)
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
"""sales 序列化器(async 兼容)。"""
|
||||
|
||||
from rest_framework import serializers
|
||||
from apps.core.serializers import AsyncModelSerializer
|
||||
from .models import SalesOrder, SalesOrderLine, SalesBill, SalesBillLine
|
||||
|
||||
|
||||
class SalesOrderLineSerializer(AsyncModelSerializer):
|
||||
product_code = serializers.CharField(source="product.code", read_only=True)
|
||||
product_name = serializers.CharField(source="product.name", read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = SalesOrderLine
|
||||
fields = ["id", "product", "product_code", "product_name",
|
||||
"quantity", "unit_price", "amount", "delivered_qty"]
|
||||
read_only_fields = ["id", "amount", "delivered_qty"]
|
||||
|
||||
|
||||
class SalesOrderSerializer(AsyncModelSerializer):
|
||||
customer_code = serializers.CharField(source="customer.code", read_only=True)
|
||||
warehouse_code = serializers.CharField(source="warehouse.code", read_only=True)
|
||||
lines = SalesOrderLineSerializer(many=True, required=False)
|
||||
|
||||
class Meta:
|
||||
model = SalesOrder
|
||||
fields = [
|
||||
"id", "bill_no", "customer", "customer_code",
|
||||
"warehouse", "warehouse_code",
|
||||
"bill_date", "expected_date", "total_amount", "state", "remark",
|
||||
"lines",
|
||||
]
|
||||
read_only_fields = ["id", "bill_no", "total_amount", "state"]
|
||||
|
||||
|
||||
class SalesBillLineSerializer(AsyncModelSerializer):
|
||||
product_code = serializers.CharField(source="product.code", read_only=True)
|
||||
product_name = serializers.CharField(source="product.name", read_only=True)
|
||||
unit_name = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = SalesBillLine
|
||||
fields = ["id", "product", "product_code", "product_name",
|
||||
"quantity", "source_unit", "source_quantity", "unit_name",
|
||||
"unit_price", "amount", "tax_rate", "tax_amount"]
|
||||
read_only_fields = ["id", "amount", "tax_amount"]
|
||||
|
||||
def get_unit_name(self, obj):
|
||||
unit = obj.source_unit or getattr(obj.product, "base_unit", None)
|
||||
return unit.name if unit else ""
|
||||
|
||||
|
||||
class SalesBillSerializer(AsyncModelSerializer):
|
||||
customer_code = serializers.CharField(source="customer.code", read_only=True)
|
||||
customer_name = serializers.CharField(source="customer.name", read_only=True)
|
||||
warehouse_code = serializers.CharField(source="warehouse.code", read_only=True)
|
||||
round_off = serializers.DecimalField(max_digits=18, decimal_places=4, read_only=True)
|
||||
# 单据税额合计 = 各行 tax_amount 之和(D4;前端展示"其中税额")
|
||||
tax_total = serializers.SerializerMethodField()
|
||||
lines = SalesBillLineSerializer(many=True, required=False)
|
||||
|
||||
def get_tax_total(self, obj):
|
||||
"""在内存里汇总已预取的行,避免每张单一次 aggregate(N+1)。
|
||||
|
||||
旧实现 `obj.lines.aggregate(Sum("tax_amount"))` 对列表页的每一行都发一条 SQL
|
||||
(实测 50 张单 = 50 次聚合)。列表接口已 prefetch `lines`,
|
||||
这里直接遍历内存对象即可。详情接口若未预取,all() 也只多一次查询。
|
||||
"""
|
||||
return str(sum((ln.tax_amount or 0) for ln in obj.lines.all()))
|
||||
|
||||
class Meta:
|
||||
model = SalesBill
|
||||
fields = [
|
||||
"id", "bill_no", "customer", "customer_code", "customer_name",
|
||||
"warehouse", "warehouse_code", "order",
|
||||
"bill_date", "total_amount", "round_off", "tax_total", "state", "remark",
|
||||
"lines",
|
||||
]
|
||||
read_only_fields = ["id", "bill_no", "total_amount", "state"]
|
||||
Reference in New Issue
Block a user