1
0
forked from erp-dev/erp
Files
erpnew/business/tests/test_service_edge_cases.py
2026-06-12 13:57:21 +08:00

344 lines
14 KiB
Python

from django.test import TestCase
from django.utils import timezone
from basic_info import models as basic_models
from business import models as business_models, services
from stock import models as stock_models
from .fixtures import create_basic_fixtures, create_sales_fixtures
class BusinessServiceEdgeCaseTestCase(TestCase):
def _disable_auto_stock_tasks(self, merchant):
basic_models.MerchantSetting.objects.filter(
merchant=merchant,
key=basic_models.MerchantSettingKeyEnum.AUTO_CREATE_STOCK_CHANGE_TASKS,
).update(val_bool=False)
def test_sales_order_kind_and_date_validation_errors(self):
merchant, customer, _, warehouse, _, product, operator = create_sales_fixtures()
with self.assertRaises(ValueError):
services.create_sales_order(
merchant=merchant,
customer=customer,
order_date=timezone.now().date(),
warehouse=warehouse,
operator=operator,
items=[{'product_id': product.id, 'quantity': 1, 'num_of_rolls': 1, 'price': '1'}],
kind='invalid',
)
with self.assertRaises(ValueError):
services.create_sales_order(
merchant=merchant,
customer=customer,
order_date=timezone.now().date(),
warehouse=warehouse,
operator=operator,
items=[{'product_id': product.id, 'quantity': 1, 'num_of_rolls': 1, 'price': '1'}],
kind=999,
)
with self.assertRaises(ValueError):
services.create_sales_order(
merchant=merchant,
customer=customer,
order_date='not-a-date',
warehouse=warehouse,
operator=operator,
items=[{'product_id': product.id, 'quantity': 1, 'num_of_rolls': 1, 'price': '1'}],
)
with self.assertRaises(ValueError):
services.create_sales_order(
merchant=merchant,
customer=customer,
order_date=object(),
warehouse=warehouse,
operator=operator,
items=[{'product_id': product.id, 'quantity': 1, 'num_of_rolls': 1, 'price': '1'}],
)
def test_return_order_source_validation_errors(self):
merchant, supplier, _, warehouse, product, operator = create_basic_fixtures()
other_supplier = basic_models.Supplier.objects.create(merchant=merchant, name='其他供应商')
purchase_order = services.create_purchase_order(
merchant=merchant,
supplier=supplier,
order_date=timezone.now().date(),
warehouse=warehouse,
operator=operator,
items=[{'product_id': product.id, 'quantity': 1, 'num_of_rolls': 1, 'price': '1'}],
)
with self.assertRaises(ValueError):
services.create_purchase_return_order(
merchant=merchant,
supplier=supplier,
return_date=timezone.now().date(),
warehouse=warehouse,
operator=operator,
purchase_order_id=999999,
items=[{'product_id': product.id, 'quantity': 1, 'num_of_rolls': 1, 'price': '1'}],
)
with self.assertRaises(ValueError):
services.create_purchase_return_order(
merchant=merchant,
supplier=other_supplier,
return_date=timezone.now().date(),
warehouse=warehouse,
operator=operator,
purchase_order=purchase_order,
items=[{'product_id': product.id, 'quantity': 1, 'num_of_rolls': 1, 'price': '1'}],
)
sales_merchant, customer, _, sales_warehouse, _, sales_product, sales_operator = create_sales_fixtures()
other_customer = basic_models.Customer.objects.create(merchant=sales_merchant, name='其他客户')
sales_order = services.create_sales_order(
merchant=sales_merchant,
customer=customer,
order_date=timezone.now().date(),
warehouse=sales_warehouse,
operator=sales_operator,
items=[{'product_id': sales_product.id, 'quantity': 1, 'num_of_rolls': 1, 'price': '1'}],
)
with self.assertRaises(ValueError):
services.create_sales_return_order(
merchant=sales_merchant,
customer=customer,
return_date=timezone.now().date(),
warehouse=sales_warehouse,
operator=sales_operator,
sales_order_id=999999,
items=[{'product_id': sales_product.id, 'quantity': 1, 'num_of_rolls': 1, 'price': '1'}],
)
with self.assertRaises(ValueError):
services.create_sales_return_order(
merchant=sales_merchant,
customer=other_customer,
return_date=timezone.now().date(),
warehouse=sales_warehouse,
operator=sales_operator,
sales_order=sales_order,
items=[{'product_id': sales_product.id, 'quantity': 1, 'num_of_rolls': 1, 'price': '1'}],
)
def test_empty_items_and_update_source_validation_errors(self):
merchant, supplier, _, warehouse, product, operator = create_basic_fixtures()
purchase_order = services.create_purchase_order(
merchant=merchant,
supplier=supplier,
order_date=timezone.now().date(),
warehouse=warehouse,
operator=operator,
items=[{'product_id': product.id, 'quantity': 1, 'num_of_rolls': 1, 'price': '1'}],
)
with self.assertRaises(ValueError):
services.update_purchase_order(purchase_order=purchase_order, items=[])
updated = services.update_purchase_order(
purchase_order=purchase_order,
items=[{'product_id': product.id, 'quantity': 1, 'num_of_rolls': 1, 'price': '1'}],
from_pre_purchase_order_id=123,
)
self.assertEqual(updated.from_pre_purchase_order_id, 123)
sales_merchant, customer, _, sales_warehouse, _, sales_product, sales_operator = create_sales_fixtures()
with self.assertRaises(ValueError):
services.create_sales_order(
merchant=sales_merchant,
customer=customer,
order_date=timezone.now().date(),
warehouse=sales_warehouse,
operator=sales_operator,
items=[],
)
with self.assertRaises(ValueError):
services.create_purchase_return_order(
merchant=merchant,
supplier=supplier,
return_date=timezone.now().date(),
warehouse=warehouse,
operator=operator,
items=[],
)
return_order = services.create_purchase_return_order(
merchant=merchant,
supplier=supplier,
return_date=timezone.now().date(),
warehouse=warehouse,
operator=operator,
items=[{'product_id': product.id, 'quantity': 1, 'num_of_rolls': 1, 'price': '1'}],
)
return_order.purchase_order = None
return_order.save(update_fields=['purchase_order'])
with self.assertRaises(ValueError):
services.update_purchase_return_order(
purchase_return_order=return_order,
purchase_order_id=999999,
items=[{'product_id': product.id, 'quantity': 1, 'num_of_rolls': 1, 'price': '1'}],
)
with self.assertRaises(ValueError):
services.create_sales_return_order(
merchant=sales_merchant,
customer=customer,
return_date=timezone.now().date(),
warehouse=sales_warehouse,
operator=sales_operator,
items=[],
)
def test_review_invalid_targets_and_cancelled_reapprove_errors(self):
merchant, supplier, _, warehouse, product, operator = create_basic_fixtures()
purchase_order = services.create_purchase_order(
merchant=merchant,
supplier=supplier,
order_date=timezone.now().date(),
warehouse=warehouse,
operator=operator,
items=[{'product_id': product.id, 'quantity': 1, 'num_of_rolls': 1, 'price': '1'}],
)
with self.assertRaises(ValueError):
services.review_purchase_order(purchase_order=purchase_order, target_status=999)
services.review_purchase_order(
purchase_order=purchase_order,
target_status=business_models.PurchaseOrderStatusEnum.CANCELLED,
)
with self.assertRaises(ValueError):
services.review_purchase_order(
purchase_order=purchase_order,
target_status=business_models.PurchaseOrderStatusEnum.APPROVED,
)
payment = services.create_payment_order(
merchant=merchant,
supplier=supplier,
payment_date=timezone.now().date(),
amount='1',
operator=operator,
)
services.review_payment_order(payment_order=payment, target_status=business_models.PaymentOrderStatusEnum.CANCELLED)
with self.assertRaises(ValueError):
services.review_payment_order(payment_order=payment, target_status=business_models.PaymentOrderStatusEnum.APPROVED)
def test_resolve_helpers_require_instance_or_id(self):
with self.assertRaises(ValueError):
services._resolve_purchase_order_instance(None, None)
with self.assertRaises(ValueError):
services._resolve_sales_order_instance(None, None)
with self.assertRaises(ValueError):
services._resolve_purchase_return_order_instance(None, None)
with self.assertRaises(ValueError):
services._resolve_sales_return_order_instance(None, None)
with self.assertRaises(ValueError):
services._resolve_payment_order_instance(None, None)
with self.assertRaises(ValueError):
services._resolve_receipt_order_instance(None, None)
def test_stock_entry_sync_not_found_payloads(self):
self.assertEqual(
services.create_purchase_order_stock_entries_sync(
purchase_order_id=999999,
warehouse_id=1,
items=[],
)['error'],
'purchase_order_not_found',
)
self.assertEqual(
services.create_sales_order_stock_entries_sync(
sales_order_id=999999,
warehouse_id=1,
items=[],
)['error'],
'sales_order_not_found',
)
self.assertEqual(
services.create_purchase_return_order_stock_entries_sync(
purchase_return_order_id=999999,
warehouse_id=1,
items=[],
)['error'],
'purchase_return_order_not_found',
)
self.assertEqual(
services.create_sales_return_order_stock_entries_sync(
sales_return_order_id=999999,
warehouse_id=1,
items=[],
)['error'],
'sales_return_order_not_found',
)
def test_build_stock_flow_items_error_branches(self):
merchant, supplier, warehouse_strict, _, product, operator = create_basic_fixtures()
order = services.create_purchase_order(
merchant=merchant,
supplier=supplier,
order_date=timezone.now().date(),
warehouse=warehouse_strict,
operator=operator,
items=[{'product_id': product.id, 'numbers': [1], 'price': '1'}],
)
order.items.all().delete()
with self.assertRaises(ValueError):
services._build_stock_flow_items_from_order(order)
order = services.create_purchase_order(
merchant=merchant,
supplier=supplier,
order_date=timezone.now().date(),
warehouse=warehouse_strict,
operator=operator,
items=[{'product_id': product.id, 'numbers': [1], 'price': '1'}],
)
item = order.items.first()
item.quantity_of_rolls = ''
item.save(update_fields=['quantity_of_rolls'])
with self.assertRaises(ValueError):
services._build_stock_flow_items_from_order(order)
def test_bind_purchase_order_stock_change_record_error_branches(self):
merchant, supplier, warehouse_strict, warehouse_relaxed, product, operator = create_basic_fixtures()
self._disable_auto_stock_tasks(merchant)
order = services.create_purchase_order(
merchant=merchant,
supplier=supplier,
order_date=timezone.now().date(),
warehouse=warehouse_strict,
operator=operator,
items=[{'product_id': product.id, 'numbers': [1], 'price': '1'}],
)
bound_record = stock_models.StockChangeRecord.objects.create(
merchant=merchant,
type=stock_models.StockChangeTypeEnum.ADD,
warehouse=warehouse_strict,
source_type=stock_models.StockChangeSourceEnum.PURCHASE,
source_id=123,
)
with self.assertRaises(ValueError):
services.bind_purchase_order_stock_change_record(
purchase_order_id=order.id,
stock_change_record_id=bound_record.id,
)
wrong_warehouse_record = stock_models.StockChangeRecord.objects.create(
merchant=merchant,
type=stock_models.StockChangeTypeEnum.ADD,
warehouse=warehouse_relaxed,
source_type=stock_models.StockChangeSourceEnum.PURCHASE,
)
with self.assertRaises(ValueError):
services.bind_purchase_order_stock_change_record(
purchase_order_id=order.id,
stock_change_record_id=wrong_warehouse_record.id,
)
sales_source_record = stock_models.StockChangeRecord.objects.create(
merchant=merchant,
type=stock_models.StockChangeTypeEnum.ADD,
warehouse=warehouse_strict,
source_type=stock_models.StockChangeSourceEnum.SALES_RETURN,
)
with self.assertRaises(ValueError):
services.bind_purchase_order_stock_change_record(
purchase_order_id=order.id,
stock_change_record_id=sales_source_record.id,
)