"""partner async ViewSets(多租户基类来自 apps.core.viewset)。""" from adrf.decorators import api_view from rest_framework.exceptions import ValidationError from apps.core.viewset import BaseTenantViewSet from .models import PriceLevel, Contact, Customer, Supplier from .serializers import ( PriceLevelSerializer, ContactSerializer, CustomerSerializer, SupplierSerializer, ) class PriceLevelViewSet(BaseTenantViewSet): model = PriceLevel serializer_class = PriceLevelSerializer search_fields = ["code", "name"] class ContactViewSet(BaseTenantViewSet): model = Contact serializer_class = ContactSerializer search_fields = ["name", "phone", "email"] class CustomerViewSet(BaseTenantViewSet): model = Customer serializer_class = CustomerSerializer search_fields = ["code", "name", "phone", "contact_name", "tax_number"] class SupplierViewSet(BaseTenantViewSet): model = Supplier serializer_class = SupplierSerializer search_fields = ["code", "name", "phone", "contact_name", "tax_number"] @api_view(["GET"]) async def credit_usage_view(request, customer_id): """客户信用额度占用:GET /api/v1/partner/credit-usage//""" from asgiref.sync import sync_to_async from rest_framework.response import Response from rest_framework.exceptions import NotFound from apps.core.viewset import resolve_tenant from .services import credit_usage tenant = await sync_to_async(resolve_tenant)( request.META.get("HTTP_X_TENANT_ID", "") ) if tenant is None: raise ValidationError({"tenant": "无法识别租户"}) def _load(): return Customer.objects.filter(tenant=tenant, pk=customer_id).first() customer = await sync_to_async(_load)() if customer is None: raise NotFound("customer not found") usage = await sync_to_async(credit_usage)(tenant=tenant, customer=customer) return Response({ "customer_id": customer.id, "customer_code": customer.code, "customer_name": customer.name, "limit": str(usage["limit"]), "outstanding": str(usage["outstanding"]), "available": str(usage["available"]) if usage["available"] is not None else None, }) @api_view(["GET"]) async def price_quote(request): """批量报价:GET /api/v1/partner/price-quote/?customer_id=&product_ids=1,2,3 返回每个商品的 {product_id, price, source, last_price, min_price, max_price}。 """ from asgiref.sync import sync_to_async from rest_framework.response import Response from rest_framework.exceptions import ValidationError from apps.core.viewset import resolve_tenant from .services import quote_price code = request.META.get("HTTP_X_TENANT_ID", "") tenant = await sync_to_async(resolve_tenant)(code) if tenant is None: raise ValidationError({"tenant": "无法识别租户"}) customer_id = request.query_params.get("customer_id") product_ids = request.query_params.get("product_ids", "") if not customer_id or not product_ids: raise ValidationError({"detail": "customer_id 与 product_ids 必填"}) def _load(): customer = Customer.objects.filter(tenant=tenant, pk=customer_id).first() products = list( __import__("apps.catalog.models", fromlist=["Product"]) .Product.objects.filter(tenant=tenant, pk__in=product_ids.split(",")) ) return customer, products customer, products = await sync_to_async(_load)() if customer is None: raise ValidationError({"customer_id": "客户不存在"}) results = [] for p in products: q = await sync_to_async(quote_price)(tenant=tenant, customer=customer, product=p) results.append({ "product_id": p.id, "product_code": p.code, "product_name": p.name, "price": str(q["price"]), "source": q["source"], "last_price": str(q["last_price"]) if q["last_price"] is not None else None, "min_price": str(q["min_price"]) if q["min_price"] is not None else None, "max_price": str(q["max_price"]) if q["max_price"] is not None else None, }) return Response({"customer_id": int(customer_id), "results": results})