from __future__ import annotations from rest_framework import views from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from basic_info import models as basic_models from business import services as business_services from api_v1.views.stock_change_views.mixins import StockChangeViewMixin from . import serializers as statement_serializers class StatementViewBase(StockChangeViewMixin, views.APIView): """ 提供对账单视图的公共实现:权限校验、序列化上下文及响应构造。 """ permission_classes = [IsAuthenticated] serializer_class = statement_serializers.StatementResponseSerializer def get_serializer_context(self): return { 'request': self.request, 'view': self, 'summary_builder': business_services.build_statement_summary, } def _build_response(self, payload: dict): serializer = self.serializer_class( instance=payload, context=self.get_serializer_context(), ) return Response(serializer.data) class CustomerStatementView(StatementViewBase): """ 返回指定客户的业务单据对账单,包含销售单、销售退货单与收款单。 """ def get(self, request, customer_id: int): if not self.check_employee_permission(request): return self.permission_error_response('无权限访问') merchant = request.user.employee.merchant try: customer = basic_models.Customer.objects.get(id=customer_id, merchant=merchant) except basic_models.Customer.DoesNotExist: return self.not_found_response('客户不存在') payload = business_services.build_customer_statement(merchant=merchant, customer=customer) return self._build_response(payload) class SupplierStatementView(StatementViewBase): """ 返回指定供应商的业务单据对账单,包含采购单、采购退货单与付款单。 """ def get(self, request, supplier_id: int): if not self.check_employee_permission(request): return self.permission_error_response('无权限访问') merchant = request.user.employee.merchant try: supplier = basic_models.Supplier.objects.get(id=supplier_id, merchant=merchant) except basic_models.Supplier.DoesNotExist: return self.not_found_response('供应商不存在') payload = business_services.build_supplier_statement(merchant=merchant, supplier=supplier) return self._build_response(payload) class StatementRecordView(StatementViewBase): """ 根据业务主体与单据信息查询单条对账记录,返回与列表接口一致的 schema。 """ def get(self, request): if not self.check_employee_permission(request): return self.permission_error_response('无权限访问') serializer = statement_serializers.StatementRecordQuerySerializer(data=request.query_params) serializer.is_valid(raise_exception=True) params = serializer.validated_data merchant = request.user.employee.merchant counterparty_type = params['counterparty_type'] counterparty_id = params['counterparty_id'] order_type = params['order_type'] order_id = params['order_id'] if counterparty_type == 'customer': try: counterparty = basic_models.Customer.objects.get(id=counterparty_id, merchant=merchant) except basic_models.Customer.DoesNotExist: return self.not_found_response('客户不存在') payload = business_services.build_customer_statement(merchant=merchant, customer=counterparty) else: try: counterparty = basic_models.Supplier.objects.get(id=counterparty_id, merchant=merchant) except basic_models.Supplier.DoesNotExist: return self.not_found_response('供应商不存在') payload = business_services.build_supplier_statement(merchant=merchant, supplier=counterparty) matched_records = [ record for record in payload.get('records', []) if record['source_type'] == order_type and record['source_id'] == order_id ] if not matched_records: return self.not_found_response('未找到匹配的对账记录') single_payload = { 'counterparty': payload['counterparty'], 'counterparty_name': payload['counterparty_name'], 'records': matched_records, } return self._build_response(single_payload)