Files
dealerhub/backend/apps/sales/serializers.py
T

79 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""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"]