122 lines
4.2 KiB
Python
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})
|