Files

111 lines
3.9 KiB
Python
Raw Permalink 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.
"""商品中心 async ViewSets(多租户基类来自 apps.core.viewset)。"""
from decimal import Decimal
from asgiref.sync import sync_to_async
from adrf.viewsets import ModelViewSet
from rest_framework.decorators import action
from rest_framework.response import Response
from apps.core.viewset import BaseTenantViewSet, StandardAsyncPagination
from .models import Category, Brand, Unit, Product, UnitConversion
from .serializers import (
CategorySerializer,
BrandSerializer,
UnitSerializer,
ProductSerializer,
)
class CategoryViewSet(BaseTenantViewSet):
model = Category
serializer_class = CategorySerializer
search_fields = ["code", "name"]
class BrandViewSet(BaseTenantViewSet):
model = Brand
serializer_class = BrandSerializer
search_fields = ["code", "name"]
class UnitViewSet(BaseTenantViewSet):
model = Unit
serializer_class = UnitSerializer
search_fields = ["code", "name"]
class ProductViewSet(BaseTenantViewSet):
model = Product
serializer_class = ProductSerializer
search_fields = ["code", "name", "barcode", "spec"]
quota_kind = "products" # 套餐配额:商品数上限(批次 C1)
@action(detail=True, methods=["get"], url_path="units")
async def units(self, request, pk=None):
"""商品的可用录入单位与换算价:GET /api/v1/catalog/products/<id>/units/
返回基本单位 + 全部 UnitConversion(rate 与按 rate 折算的销售价),
供开单页"选择录入单位"使用。
"""
tenant = await self.get_tenant()
if tenant is None:
from rest_framework.exceptions import ValidationError
raise ValidationError({"tenant": "无法识别租户"})
def _load():
product = (
Product.objects.filter(tenant=tenant, pk=pk)
.select_related("base_unit")
.first()
)
if product is None:
return None
convs = list(
UnitConversion.objects.filter(product=product)
.select_related("unit")
.order_by("unit__code")
)
base_unit = product.base_unit
rows = []
if base_unit is not None:
rows.append({
"unit_id": base_unit.id,
"unit_code": base_unit.code,
"unit_name": base_unit.name,
"rate": "1",
"is_base": True,
"price": str(product.sale_price),
"cost_price": str(product.cost_price),
})
for c in convs:
rows.append({
"unit_id": c.unit_id,
"unit_code": c.unit.code,
"unit_name": c.unit.name,
"rate": str(c.rate),
"is_base": False,
"price": str((product.sale_price * c.rate).quantize(Decimal("0.0001"))),
"cost_price": str((product.cost_price * c.rate).quantize(Decimal("0.0001"))),
})
return {
"product_id": product.id,
"product_code": product.code,
"product_name": product.name,
"base_unit_id": base_unit.id if base_unit else None,
"base_unit_name": base_unit.name if base_unit else "",
"sale_price": str(product.sale_price),
"cost_price": str(product.cost_price),
"min_sale_price": str(product.min_sale_price or 0),
"tax_rate": str(product.tax_rate or 0),
"is_batch_managed": product.is_batch_managed,
"shelf_life_days": product.shelf_life_days,
"units": rows,
}
data = await sync_to_async(_load)()
if data is None:
from rest_framework.exceptions import NotFound
raise NotFound("product not found")
return Response(data)