1
0
forked from erp-dev/erp

feat: red flush

This commit is contained in:
2026-06-12 13:57:21 +08:00
parent 80db7867f4
commit 0bcaa2db44
33 changed files with 2997 additions and 17 deletions

View File

@@ -20,6 +20,7 @@ class PaymentOrderSerializer(serializers.ModelSerializer):
'id', 'supplier', 'supplier_name', 'bank_account', 'bank_account_name',
'payment_date', 'amount', 'discount_amount', 'settlement_amount',
'operator', 'operator_name', 'status', 'is_external_source', 'external_source_id',
'is_red_flushed', 'red_flush_id', 'red_flushed_at',
'remarks', 'markup', 'created_at', 'updated_at',
]
read_only_fields = [
@@ -31,6 +32,9 @@ class PaymentOrderSerializer(serializers.ModelSerializer):
'status',
'is_external_source',
'external_source_id',
'is_red_flushed',
'red_flush_id',
'red_flushed_at',
'created_at',
'updated_at',
]
@@ -164,3 +168,42 @@ class PaymentOrderReviewView(StockChangeViewMixin, views.APIView):
)
return Response(PaymentOrderSerializer(refreshed).data, status=status.HTTP_200_OK)
class PaymentOrderRedFlushSerializer(serializers.Serializer):
reason = serializers.CharField(required=True, allow_blank=False, trim_whitespace=True)
class PaymentOrderRedFlushView(StockChangeViewMixin, views.APIView):
permission_classes = [IsAuthenticated]
def post(self, request, pk: int):
if not self.check_employee_permission(request):
return self.permission_error_response('无权限访问')
merchant = request.user.employee.merchant
try:
payment_order = (
business_models.PaymentOrder.objects.select_related('supplier', 'operator', 'bank_account')
.get(id=pk, merchant=merchant)
)
except business_models.PaymentOrder.DoesNotExist:
return self.not_found_response('付款单不存在')
serializer = PaymentOrderRedFlushSerializer(data=request.data or {})
serializer.is_valid(raise_exception=True)
try:
red_flushed_order = business_services.red_flush_payment_order(
merchant=merchant,
payment_order=payment_order,
red_flushed_by=request.user,
reason=serializer.validated_data['reason'],
)
except ValueError as exc:
return Response({'error': str(exc)}, status=status.HTTP_400_BAD_REQUEST)
refreshed = (
business_models.PaymentOrder.objects.select_related('supplier', 'operator', 'bank_account')
.get(id=red_flushed_order.id)
)
return Response(PaymentOrderSerializer(refreshed).data, status=status.HTTP_200_OK)

View File

@@ -53,10 +53,14 @@ class PurchaseOrderSerializer(serializers.ModelSerializer):
'id', 'human_id', 'supplier', 'supplier_name', 'purchase_date', 'kind',
'total_amount', 'diff_quantity', 'total_quantity',
'operator', 'operator_name', 'warehouse', 'warehouse_name',
'status', 'remarks', 'created_at', 'updated_at', 'items',
'quantity_of_rolls',
'status', 'is_red_flushed', 'red_flush_id', 'red_flushed_at',
'remarks', 'created_at', 'updated_at', 'items', 'quantity_of_rolls',
]
read_only_fields = [
'id', 'created_at', 'updated_at', 'items', 'supplier_name',
'operator_name', 'warehouse_name', 'is_red_flushed',
'red_flush_id', 'red_flushed_at',
]
read_only_fields = ['id', 'created_at', 'updated_at', 'items', 'supplier_name', 'operator_name', 'warehouse_name']
class PurchaseOrderPagination(pagination.LimitOffsetPagination):
@@ -258,6 +262,46 @@ class PurchaseOrderReviewView(StockChangeViewMixin, views.APIView):
return Response(PurchaseOrderSerializer(refreshed_order).data, status=status.HTTP_200_OK)
class PurchaseOrderRedFlushSerializer(serializers.Serializer):
reason = serializers.CharField(required=True, allow_blank=False, trim_whitespace=True)
class PurchaseOrderRedFlushView(StockChangeViewMixin, views.APIView):
"""采购单红冲"""
permission_classes = [IsAuthenticated]
def post(self, request, pk: int):
if not self.check_employee_permission(request):
return self.permission_error_response('无权限访问')
merchant = request.user.employee.merchant
try:
purchase_order = business_models.PurchaseOrder.objects.select_related(
'supplier', 'operator', 'warehouse'
).prefetch_related('items').get(id=pk, merchant=merchant)
except business_models.PurchaseOrder.DoesNotExist:
return self.not_found_response('采购单不存在')
serializer = PurchaseOrderRedFlushSerializer(data=request.data or {})
serializer.is_valid(raise_exception=True)
try:
red_flushed_order = business_services.red_flush_purchase_order(
merchant=merchant,
purchase_order=purchase_order,
red_flushed_by=request.user,
reason=serializer.validated_data['reason'],
)
except ValueError as exc:
return Response({'error': str(exc)}, status=status.HTTP_400_BAD_REQUEST)
refreshed_order = business_models.PurchaseOrder.objects.select_related(
'supplier', 'operator', 'warehouse'
).prefetch_related('items').get(id=red_flushed_order.id)
return Response(PurchaseOrderSerializer(refreshed_order).data, status=status.HTTP_200_OK)
class PurchaseOrderBindStockChangeSerializer(serializers.Serializer):
stock_change_record_id = serializers.IntegerField(min_value=1)
@@ -300,4 +344,3 @@ class PurchaseOrderBindStockChangeView(StockChangeViewMixin, views.APIView):
},
status=status.HTTP_200_OK,
)

View File

@@ -57,12 +57,13 @@ class PurchaseReturnOrderSerializer(serializers.ModelSerializer):
'id', 'human_id', 'supplier', 'supplier_name', 'purchase_order', 'return_date',
'total_amount', 'diff_quantity', 'total_quantity',
'operator', 'operator_name', 'warehouse', 'warehouse_name',
'status', 'remarks', 'created_at', 'updated_at', 'items',
'quantity_of_rolls',
'status', 'is_red_flushed', 'red_flush_id', 'red_flushed_at',
'remarks', 'created_at', 'updated_at', 'items', 'quantity_of_rolls',
]
read_only_fields = [
'id', 'created_at', 'updated_at', 'items',
'supplier_name', 'operator_name', 'warehouse_name',
'is_red_flushed', 'red_flush_id', 'red_flushed_at',
]
@@ -260,3 +261,40 @@ class PurchaseReturnOrderReviewView(StockChangeViewMixin, views.APIView):
).prefetch_related('items').get(id=purchase_return_order.id)
return Response(PurchaseReturnOrderSerializer(refreshed_order).data, status=status.HTTP_200_OK)
class PurchaseReturnOrderRedFlushSerializer(serializers.Serializer):
reason = serializers.CharField(required=True, allow_blank=False, trim_whitespace=True)
class PurchaseReturnOrderRedFlushView(StockChangeViewMixin, views.APIView):
permission_classes = [IsAuthenticated]
def post(self, request, pk: int):
if not self.check_employee_permission(request):
return self.permission_error_response('无权限访问')
merchant = request.user.employee.merchant
try:
purchase_return_order = business_models.PurchaseReturnOrder.objects.select_related(
'supplier', 'operator', 'warehouse'
).prefetch_related('items').get(id=pk, merchant=merchant)
except business_models.PurchaseReturnOrder.DoesNotExist:
return self.not_found_response('采购退货单不存在')
serializer = PurchaseReturnOrderRedFlushSerializer(data=request.data or {})
serializer.is_valid(raise_exception=True)
try:
red_flushed_order = business_services.red_flush_purchase_return_order(
merchant=merchant,
purchase_return_order=purchase_return_order,
red_flushed_by=request.user,
reason=serializer.validated_data['reason'],
)
except ValueError as exc:
return Response({'error': str(exc)}, status=status.HTTP_400_BAD_REQUEST)
refreshed_order = business_models.PurchaseReturnOrder.objects.select_related(
'supplier', 'operator', 'warehouse'
).prefetch_related('items').get(id=red_flushed_order.id)
return Response(PurchaseReturnOrderSerializer(refreshed_order).data, status=status.HTTP_200_OK)

View File

@@ -20,6 +20,7 @@ class ReceiptOrderSerializer(serializers.ModelSerializer):
'id', 'customer', 'customer_name', 'bank_account', 'bank_account_name',
'receipt_date', 'amount', 'discount_amount', 'settlement_amount',
'operator', 'operator_name', 'status', 'is_external_source', 'external_source_id',
'is_red_flushed', 'red_flush_id', 'red_flushed_at',
'remarks', 'markup', 'created_at', 'updated_at',
]
read_only_fields = [
@@ -31,6 +32,9 @@ class ReceiptOrderSerializer(serializers.ModelSerializer):
'status',
'is_external_source',
'external_source_id',
'is_red_flushed',
'red_flush_id',
'red_flushed_at',
'created_at',
'updated_at',
]
@@ -164,3 +168,42 @@ class ReceiptOrderReviewView(StockChangeViewMixin, views.APIView):
)
return Response(ReceiptOrderSerializer(refreshed).data, status=status.HTTP_200_OK)
class ReceiptOrderRedFlushSerializer(serializers.Serializer):
reason = serializers.CharField(required=True, allow_blank=False, trim_whitespace=True)
class ReceiptOrderRedFlushView(StockChangeViewMixin, views.APIView):
permission_classes = [IsAuthenticated]
def post(self, request, pk: int):
if not self.check_employee_permission(request):
return self.permission_error_response('无权限访问')
merchant = request.user.employee.merchant
try:
receipt_order = (
business_models.ReceiptOrder.objects.select_related('customer', 'operator', 'bank_account')
.get(id=pk, merchant=merchant)
)
except business_models.ReceiptOrder.DoesNotExist:
return self.not_found_response('收款单不存在')
serializer = ReceiptOrderRedFlushSerializer(data=request.data or {})
serializer.is_valid(raise_exception=True)
try:
red_flushed_order = business_services.red_flush_receipt_order(
merchant=merchant,
receipt_order=receipt_order,
red_flushed_by=request.user,
reason=serializer.validated_data['reason'],
)
except ValueError as exc:
return Response({'error': str(exc)}, status=status.HTTP_400_BAD_REQUEST)
refreshed = (
business_models.ReceiptOrder.objects.select_related('customer', 'operator', 'bank_account')
.get(id=red_flushed_order.id)
)
return Response(ReceiptOrderSerializer(refreshed).data, status=status.HTTP_200_OK)

View File

@@ -54,10 +54,14 @@ class SalesOrderSerializer(serializers.ModelSerializer):
'id', 'human_id', 'customer', 'customer_name', 'sales_date', 'kind',
'total_amount', 'diff_quantity', 'total_quantity',
'operator', 'operator_name', 'warehouse', 'warehouse_name',
'status', 'remarks', 'created_at', 'updated_at', 'items',
'quantity_of_rolls',
'status', 'is_red_flushed', 'red_flush_id', 'red_flushed_at',
'remarks', 'created_at', 'updated_at', 'items', 'quantity_of_rolls',
]
read_only_fields = [
'id', 'created_at', 'updated_at', 'items', 'customer_name',
'operator_name', 'warehouse_name', 'is_red_flushed',
'red_flush_id', 'red_flushed_at',
]
read_only_fields = ['id', 'created_at', 'updated_at', 'items', 'customer_name', 'operator_name', 'warehouse_name']
class SalesOrderPagination(pagination.LimitOffsetPagination):
@@ -267,3 +271,42 @@ class SalesOrderReviewView(StockChangeViewMixin, views.APIView):
).prefetch_related('items').get(id=sales_order.id)
return Response(SalesOrderSerializer(refreshed_order).data, status=status.HTTP_200_OK)
class SalesOrderRedFlushSerializer(serializers.Serializer):
reason = serializers.CharField(required=True, allow_blank=False, trim_whitespace=True)
class SalesOrderRedFlushView(StockChangeViewMixin, views.APIView):
"""销售单红冲"""
permission_classes = [IsAuthenticated]
def post(self, request, pk: int):
if not self.check_employee_permission(request):
return self.permission_error_response('无权限访问')
merchant = request.user.employee.merchant
try:
sales_order = business_models.SalesOrder.objects.select_related(
'customer', 'operator', 'warehouse'
).prefetch_related('items').get(id=pk, merchant=merchant)
except business_models.SalesOrder.DoesNotExist:
return self.not_found_response('销售单不存在')
serializer = SalesOrderRedFlushSerializer(data=request.data or {})
serializer.is_valid(raise_exception=True)
try:
red_flushed_order = business_services.red_flush_sales_order(
merchant=merchant,
sales_order=sales_order,
red_flushed_by=request.user,
reason=serializer.validated_data['reason'],
)
except ValueError as exc:
return Response({'error': str(exc)}, status=status.HTTP_400_BAD_REQUEST)
refreshed_order = business_models.SalesOrder.objects.select_related(
'customer', 'operator', 'warehouse'
).prefetch_related('items').get(id=red_flushed_order.id)
return Response(SalesOrderSerializer(refreshed_order).data, status=status.HTTP_200_OK)

View File

@@ -56,11 +56,13 @@ class SalesReturnOrderSerializer(serializers.ModelSerializer):
'id', 'human_id', 'customer', 'customer_name', 'sales_order', 'return_date',
'total_amount', 'diff_quantity', 'total_quantity', 'quantity_of_rolls',
'operator', 'operator_name', 'warehouse', 'warehouse_name',
'status', 'remarks', 'created_at', 'updated_at', 'items',
'status', 'is_red_flushed', 'red_flush_id', 'red_flushed_at',
'remarks', 'created_at', 'updated_at', 'items',
]
read_only_fields = [
'id', 'created_at', 'updated_at', 'items',
'customer_name', 'operator_name', 'warehouse_name',
'is_red_flushed', 'red_flush_id', 'red_flushed_at',
]
@@ -258,3 +260,40 @@ class SalesReturnOrderReviewView(StockChangeViewMixin, views.APIView):
).prefetch_related('items').get(id=sales_return_order.id)
return Response(SalesReturnOrderSerializer(refreshed_order).data, status=status.HTTP_200_OK)
class SalesReturnOrderRedFlushSerializer(serializers.Serializer):
reason = serializers.CharField(required=True, allow_blank=False, trim_whitespace=True)
class SalesReturnOrderRedFlushView(StockChangeViewMixin, views.APIView):
permission_classes = [IsAuthenticated]
def post(self, request, pk: int):
if not self.check_employee_permission(request):
return self.permission_error_response('无权限访问')
merchant = request.user.employee.merchant
try:
sales_return_order = business_models.SalesReturnOrder.objects.select_related(
'customer', 'operator', 'warehouse'
).prefetch_related('items').get(id=pk, merchant=merchant)
except business_models.SalesReturnOrder.DoesNotExist:
return self.not_found_response('销售退货单不存在')
serializer = SalesReturnOrderRedFlushSerializer(data=request.data or {})
serializer.is_valid(raise_exception=True)
try:
red_flushed_order = business_services.red_flush_sales_return_order(
merchant=merchant,
sales_return_order=sales_return_order,
red_flushed_by=request.user,
reason=serializer.validated_data['reason'],
)
except ValueError as exc:
return Response({'error': str(exc)}, status=status.HTTP_400_BAD_REQUEST)
refreshed_order = business_models.SalesReturnOrder.objects.select_related(
'customer', 'operator', 'warehouse'
).prefetch_related('items').get(id=red_flushed_order.id)
return Response(SalesReturnOrderSerializer(refreshed_order).data, status=status.HTTP_200_OK)