from decimal import Decimal 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 .fixtures import create_basic_fixtures, create_sales_fixtures class OrderBalanceBeforeSnapshotTestCase(TestCase): def setUp(self): ( self.supplier_merchant, self.supplier, _supplier_strict_warehouse, self.supplier_warehouse, self.supplier_product, self.supplier_operator, ) = create_basic_fixtures() ( self.customer_merchant, self.customer, _customer_strict_warehouse, self.customer_warehouse, _customer_strict_out_warehouse, self.customer_product, self.customer_operator, ) = create_sales_fixtures() def _supplier_items(self): return [ { 'product_id': self.supplier_product.id, 'quantity': '3', 'num_of_rolls': 1, 'price': '12.50', } ] def _customer_items(self): return [ { 'product_id': self.customer_product.id, 'quantity': '4', 'num_of_rolls': 1, 'price': '8.25', } ] def _create_supplier_orders(self): purchase_order = services.create_purchase_order( merchant=self.supplier_merchant, supplier=self.supplier, order_date=timezone.now().date(), warehouse=self.supplier_warehouse, operator=self.supplier_operator, items=self._supplier_items(), ) purchase_return_order = services.create_purchase_return_order( merchant=self.supplier_merchant, supplier=self.supplier, return_date=timezone.now().date(), warehouse=self.supplier_warehouse, operator=self.supplier_operator, items=self._supplier_items(), purchase_order=purchase_order, ) return purchase_order, purchase_return_order def _create_customer_orders(self): sales_order = services.create_sales_order( merchant=self.customer_merchant, customer=self.customer, order_date=timezone.now().date(), warehouse=self.customer_warehouse, operator=self.customer_operator, items=self._customer_items(), ) sales_return_order = services.create_sales_return_order( merchant=self.customer_merchant, customer=self.customer, return_date=timezone.now().date(), warehouse=self.customer_warehouse, operator=self.customer_operator, items=self._customer_items(), sales_order=sales_order, ) return sales_order, sales_return_order def test_all_four_creation_services_capture_current_balance(self): business_models.SupplierBalance.objects.create( merchant=self.supplier_merchant, supplier=self.supplier, balance=Decimal('123.45'), ) business_models.CustomerBalance.objects.create( merchant=self.customer_merchant, customer=self.customer, balance=Decimal('-67.89'), ) purchase_order, purchase_return_order = self._create_supplier_orders() sales_order, sales_return_order = self._create_customer_orders() self.assertEqual(purchase_order.balance_before_snapshot, Decimal('123.45')) self.assertEqual(purchase_return_order.balance_before_snapshot, Decimal('123.45')) self.assertEqual(sales_order.balance_before_snapshot, Decimal('-67.89')) self.assertEqual(sales_return_order.balance_before_snapshot, Decimal('-67.89')) def test_missing_balance_rows_snapshot_zero_instead_of_null(self): purchase_order, purchase_return_order = self._create_supplier_orders() sales_order, sales_return_order = self._create_customer_orders() for order in ( purchase_order, purchase_return_order, sales_order, sales_return_order, ): self.assertEqual(order.balance_before_snapshot, Decimal('0')) self.assertIsNotNone(order.balance_before_snapshot) def test_updates_and_later_balance_changes_do_not_recalculate_snapshot(self): supplier_balance = business_models.SupplierBalance.objects.create( merchant=self.supplier_merchant, supplier=self.supplier, balance=Decimal('100.00'), ) customer_balance = business_models.CustomerBalance.objects.create( merchant=self.customer_merchant, customer=self.customer, balance=Decimal('200.00'), ) purchase_order, purchase_return_order = self._create_supplier_orders() sales_order, sales_return_order = self._create_customer_orders() other_supplier = basic_models.Supplier.objects.create( merchant=self.supplier_merchant, name='快照测试供应商B', ) other_customer = basic_models.Customer.objects.create( merchant=self.customer_merchant, name='快照测试客户B', ) business_models.SupplierBalance.objects.create( merchant=self.supplier_merchant, supplier=other_supplier, balance=Decimal('999.00'), ) business_models.CustomerBalance.objects.create( merchant=self.customer_merchant, customer=other_customer, balance=Decimal('888.00'), ) supplier_balance.balance = Decimal('300.00') supplier_balance.save(update_fields=['balance', 'updated_at']) customer_balance.balance = Decimal('400.00') customer_balance.save(update_fields=['balance', 'updated_at']) services.update_purchase_order( purchase_order=purchase_order, supplier=other_supplier, items=self._supplier_items(), ) services.update_purchase_return_order( purchase_return_order=purchase_return_order, supplier=other_supplier, items=self._supplier_items(), ) services.update_sales_order( sales_order=sales_order, customer=other_customer, items=self._customer_items(), ) services.update_sales_return_order( sales_return_order=sales_return_order, customer=other_customer, items=self._customer_items(), ) for order in (purchase_order, purchase_return_order): order.refresh_from_db() self.assertEqual(order.balance_before_snapshot, Decimal('100.00')) for order in (sales_order, sales_return_order): order.refresh_from_db() self.assertEqual(order.balance_before_snapshot, Decimal('200.00')) def test_api_serializers_expose_snapshot_as_read_only(self): business_models.SupplierBalance.objects.create( merchant=self.supplier_merchant, supplier=self.supplier, balance=Decimal('123.45'), ) business_models.CustomerBalance.objects.create( merchant=self.customer_merchant, customer=self.customer, balance=Decimal('67.89'), ) purchase_order, purchase_return_order = self._create_supplier_orders() sales_order, sales_return_order = self._create_customer_orders() from api_v1.views.business.purchase.views import PurchaseOrderSerializer from api_v1.views.business.purchase_return.views import PurchaseReturnOrderSerializer from api_v1.views.business.sales.views import SalesOrderSerializer from api_v1.views.business.sales_return.views import SalesReturnOrderSerializer cases = ( (PurchaseOrderSerializer, purchase_order, '123.45'), (PurchaseReturnOrderSerializer, purchase_return_order, '123.45'), (SalesOrderSerializer, sales_order, '67.89'), (SalesReturnOrderSerializer, sales_return_order, '67.89'), ) for serializer_class, order, expected in cases: with self.subTest(serializer=serializer_class.__name__): self.assertEqual(serializer_class(order).data['balance_before_snapshot'], expected) serializer = serializer_class( order, data={'balance_before_snapshot': '9999.99'}, partial=True, ) self.assertTrue(serializer.is_valid(), serializer.errors) self.assertNotIn('balance_before_snapshot', serializer.validated_data)