forked from erp-dev/erp
fix: docs
This commit is contained in:
@@ -1437,6 +1437,20 @@ class BusinessRedFlushAPITestCase(TestCase):
|
||||
order.refresh_from_db()
|
||||
self.assertEqual(order.status, business_models.PurchaseOrderStatusEnum.APPROVED)
|
||||
self.assertTrue(order.is_red_flushed)
|
||||
self.assertEqual(
|
||||
business_models.BalanceChangeRecord.objects.filter(
|
||||
source_type=business_models.BalanceChangeSourceEnum.PURCHASE_ORDER,
|
||||
source_id=order.id,
|
||||
red_flush_id=order.red_flush_id,
|
||||
).count(),
|
||||
2,
|
||||
)
|
||||
self.assertTrue(
|
||||
stock_models.StockChangeRecord.objects.filter(
|
||||
source_type=stock_models.StockChangeSourceEnum.OFFSET,
|
||||
red_flush_id=order.red_flush_id,
|
||||
).exists()
|
||||
)
|
||||
|
||||
def test_sales_order_red_flush_success(self):
|
||||
order = self._create_approved_sales_order()
|
||||
@@ -1495,6 +1509,54 @@ class BusinessRedFlushAPITestCase(TestCase):
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertTrue(response.data['is_red_flushed'])
|
||||
|
||||
def test_red_flush_requires_employee_permission(self):
|
||||
order = self._create_approved_payment_order()
|
||||
user_without_employee = User.objects.create_user(username='red_flush_no_employee', password='pass123')
|
||||
self.client.force_authenticate(user=user_without_employee)
|
||||
|
||||
response = self.client.post(
|
||||
f'/api/v1/payment-orders/{order.id}/red-flush/',
|
||||
{'reason': '无员工身份红冲'},
|
||||
format='json',
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(response.data['error'], '无权限访问')
|
||||
order.refresh_from_db()
|
||||
self.assertFalse(order.is_red_flushed)
|
||||
|
||||
def test_purchase_order_red_flush_stock_failure_returns_400_and_rolls_back(self):
|
||||
order = services.create_purchase_order(
|
||||
merchant=self.merchant,
|
||||
supplier=self.supplier,
|
||||
order_date=datetime.date(2025, 11, 26),
|
||||
warehouse=self.warehouse,
|
||||
operator=self.employee,
|
||||
items=self._items(),
|
||||
)
|
||||
services.review_purchase_order(
|
||||
purchase_order=order,
|
||||
target_status=business_models.PurchaseOrderStatusEnum.APPROVED,
|
||||
reviewed_by=self.user,
|
||||
)
|
||||
|
||||
response = self.client.post(
|
||||
f'/api/v1/purchase-orders/{order.id}/red-flush/',
|
||||
{'reason': '缺库存记录红冲'},
|
||||
format='json',
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertIn('采购单缺少可红冲的库存记录', response.data['error'])
|
||||
order.refresh_from_db()
|
||||
self.assertFalse(order.is_red_flushed)
|
||||
records = business_models.BalanceChangeRecord.objects.filter(
|
||||
source_type=business_models.BalanceChangeSourceEnum.PURCHASE_ORDER,
|
||||
source_id=order.id,
|
||||
)
|
||||
self.assertEqual(records.count(), 1)
|
||||
self.assertFalse(records.first().cancelled)
|
||||
|
||||
def test_red_flush_rejects_external_payment_order(self):
|
||||
order = self._create_approved_payment_order()
|
||||
order.is_external_source = True
|
||||
|
||||
@@ -167,7 +167,9 @@
|
||||
- **响应**:`{"customer": 12, "customer_name": "张三", "balance": "1234.50"}`
|
||||
- `balance` 为字符串格式的十进制数,正数表示客户欠款,应收;负数表示已收超额。
|
||||
|
||||
如需对 `items` 结构、仓库模式或审批流程做深入了解,请参阅:
|
||||
如需对 `items` 结构、仓库模式、审批流程或红冲 API 做深入了解,请参阅:
|
||||
- `docs/2026-06-12_business_red_flush_api.md`
|
||||
- `docs/2026-06-12_business_red_flush_design.md`
|
||||
- `docs/purchase_order_approval_and_red_flush.md`
|
||||
- `docs/sales_order_approval_and_red_flush.md`
|
||||
|
||||
|
||||
@@ -364,6 +364,7 @@ class PrintingJobListSerializer(serializers.ModelSerializer):
|
||||
is_sales_order_bound = serializers.SerializerMethodField()
|
||||
billed_quantity = serializers.DecimalField(max_digits=18, decimal_places=2, read_only=True)
|
||||
merchant_id = serializers.IntegerField(source='merchant.id', read_only=True, allow_null=True)
|
||||
fabric = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = models.PrintingJob
|
||||
@@ -377,6 +378,7 @@ class PrintingJobListSerializer(serializers.ModelSerializer):
|
||||
'is_sales_order_bound',
|
||||
'batch_advance_records',
|
||||
'saleitems',
|
||||
'fabric',
|
||||
'created_at', 'updated_at'
|
||||
]
|
||||
read_only_fields = [
|
||||
@@ -449,6 +451,9 @@ class PrintingJobListSerializer(serializers.ModelSerializer):
|
||||
def get_is_sales_order_bound(self, obj):
|
||||
return _get_is_sales_order_bound(obj)
|
||||
|
||||
def get_fabric(self, obj):
|
||||
return obj.printing_order.fabric
|
||||
|
||||
|
||||
class PrintingJobDetailSerializer(serializers.ModelSerializer):
|
||||
"""印染款式明细详情序列化器"""
|
||||
@@ -470,6 +475,7 @@ class PrintingJobDetailSerializer(serializers.ModelSerializer):
|
||||
is_sales_order_bound = serializers.SerializerMethodField()
|
||||
billed_quantity = serializers.DecimalField(max_digits=18, decimal_places=2, read_only=True)
|
||||
merchant_id = serializers.IntegerField(source='merchant.id', read_only=True, allow_null=True)
|
||||
fabric = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = models.PrintingJob
|
||||
@@ -483,6 +489,7 @@ class PrintingJobDetailSerializer(serializers.ModelSerializer):
|
||||
'is_sales_order_bound',
|
||||
'batch_advance_records',
|
||||
'saleitems',
|
||||
'fabric',
|
||||
'created_at', 'updated_at'
|
||||
]
|
||||
read_only_fields = [
|
||||
@@ -524,6 +531,9 @@ class PrintingJobDetailSerializer(serializers.ModelSerializer):
|
||||
def get_is_sales_order_bound(self, obj):
|
||||
return _get_is_sales_order_bound(obj)
|
||||
|
||||
def get_fabric(self, obj):
|
||||
return obj.printing_order.fabric
|
||||
|
||||
|
||||
class PrintingJobCreateUpdateSerializer(serializers.ModelSerializer):
|
||||
"""印染款式明细创建/更新序列化器"""
|
||||
|
||||
Reference in New Issue
Block a user