1
0
forked from erp-dev/erp

feat: statement for supplier and customer

This commit is contained in:
2025-12-01 22:55:52 +08:00
parent fae33809ac
commit d522c0a9b0
15 changed files with 1085 additions and 52 deletions

View File

@@ -328,35 +328,128 @@ class MakeStockChangeCompletedTestCase(StockServicesTestCase):
product_id=self.product_fabric_a.id,
warehouse_id=self.warehouse_main.id
)
def test_complete_inbound_record_existing_inventory(self):
"""测试完成入库记录(更新现有库存)"""
# 创建现有库存
existing_inventory = models.Inventory.objects.create(
merchant=self.merchant,
product=self.product_fabric_a,
warehouse=self.warehouse_main,
quantity=50,
num_of_rolls=5
num_of_rolls=5,
)
with patch('stock.services.create_stock_snapshot') as mock_snapshot:
mock_snapshot.return_value = MagicMock()
result = services.make_stock_change_completed(self.stock_change_in)
self.assertTrue(result)
# 检查库存更新
existing_inventory.refresh_from_db()
self.assertEqual(existing_inventory.quantity, 150) # 50 + 100
self.assertEqual(existing_inventory.num_of_rolls, 6) # 5 + 1
# 验证记录状态
self.assertEqual(existing_inventory.quantity, 150)
self.assertEqual(existing_inventory.num_of_rolls, 6)
self.stock_change_in.refresh_from_db()
self.assertTrue(self.stock_change_in.is_finished)
class StockOffsetServiceTestCase(TestCase):
"""测试库存红冲逻辑"""
def setUp(self):
self.merchant = Merchant.objects.create(
name='红冲商户',
type=MerchantTypeEnum.STORE,
)
self.warehouse = WareHouse.objects.create(
merchant=self.merchant,
name='红冲仓',
mode=WareHouseModeEnum.RESTRICT_IN,
)
category = ProductCategory.objects.create(
merchant=self.merchant,
name='红冲品类',
product_prefix='RC',
)
self.product = Product.objects.create(
merchant=self.merchant,
category=category,
name='红冲产品',
human_id='RC-001',
unit=ProductUnitEnum.METER,
)
self.stock_service = services.StockFlowService(merchant=self.merchant, created_by=None)
self.source_record, _, _ = services.create_stock_change_record_with_details(
merchant=self.merchant,
created_by=None,
type=models.StockChangeTypeEnum.ADD,
warehouse_id=self.warehouse.id,
source_type=models.StockChangeSourceEnum.PURCHASE,
source_id=101,
products=[{'product': self.product.id, 'quantity': [Decimal('10')]}],
)
services.make_stock_change_completed(self.source_record)
def test_offset_stock_change_creates_reverse_record(self):
offset_record, details, detail_count = self.stock_service.offset_stock_change(
source_record_id=self.source_record.id,
reason='测试红冲',
)
self.assertEqual(offset_record.type, models.StockChangeTypeEnum.REMOVE)
self.assertEqual(offset_record.source_type, models.StockChangeSourceEnum.OFFSET)
self.assertEqual(detail_count, 1)
self.assertEqual(len(details), 1)
inventory = models.Inventory.objects.get(product=self.product, warehouse=self.warehouse)
self.assertEqual(inventory.quantity, 0)
self.assertTrue(
models.StockSnapshot.objects.filter(
stock_change_record=self.source_record,
cancelled=True,
offset_id__isnull=False,
).exists()
)
def test_offset_cannot_repeat(self):
self.stock_service.offset_stock_change(
source_record_id=self.source_record.id,
reason='第一次红冲',
)
with self.assertRaises(ValueError):
self.stock_service.offset_stock_change(
source_record_id=self.source_record.id,
reason='再次红冲',
)
def test_offset_requires_finished_record(self):
record, _, _ = services.create_stock_change_record_with_details(
merchant=self.merchant,
created_by=None,
type=models.StockChangeTypeEnum.ADD,
warehouse_id=self.warehouse.id,
source_type=models.StockChangeSourceEnum.PURCHASE,
source_id=202,
products=[{'product': self.product.id, 'quantity': [Decimal('8')]}],
)
with self.assertRaises(ValueError):
self.stock_service.offset_stock_change(
source_record_id=record.id,
reason='未完成记录红冲',
)
def test_offset_checks_merchant(self):
other_merchant = Merchant.objects.create(
name='外部商户',
type=MerchantTypeEnum.STORE,
)
other_service = services.StockFlowService(merchant=other_merchant, created_by=None)
with self.assertRaises(ValueError):
other_service.offset_stock_change(
source_record_id=self.source_record.id,
reason='跨商户红冲',
)
class CreateStockChangeRecordWithDetailsTestCase(StockServicesTestCase):
"""测试 create_stock_change_record_with_details 服务"""
@@ -893,8 +986,8 @@ class StockFlowServiceTestCase(TestCase):
source_id=11,
items=[{'product_id': self.product.id, 'value': '9', 'num_of_rolls': 4}],
)
self.assertEqual(count, 3) # 4 + 4 + 1
self.assertEqual(len(details), 3)
self.assertEqual(count, 4)
self.assertEqual(len(details), 4)
def test_stock_out_restrict_mode_consumes_details(self):
_, inbound_details, _ = self.service.stock_in(