Files
dealerhub/backend/apps/partner/views.py
T

122 lines
4.2 KiB
Python

"""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/<customer_id>/"""
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})