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, )