forked from erp-dev/erp
166 lines
6.8 KiB
Python
166 lines
6.8 KiB
Python
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 BusinessStatementServiceTestCase(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_build_customer_statement_collects_all_customer_records(self):
|
|
merchant, customer, warehouse_strict, warehouse_relaxed, _, product, operator = create_sales_fixtures()
|
|
self._disable_auto_stock_tasks(merchant)
|
|
today = timezone.now().date()
|
|
|
|
sales_order = services.create_sales_order(
|
|
merchant=merchant,
|
|
customer=customer,
|
|
order_date=today,
|
|
warehouse=warehouse_strict,
|
|
operator=operator,
|
|
items=[{'product_id': product.id, 'numbers': [6, 4], 'price': '10', 'unit': '米'}],
|
|
remarks='销售对账',
|
|
)
|
|
services.review_sales_order(
|
|
sales_order=sales_order,
|
|
target_status=business_models.SalesOrderStatusEnum.APPROVED,
|
|
)
|
|
|
|
return_order = services.create_sales_return_order(
|
|
merchant=merchant,
|
|
customer=customer,
|
|
return_date=today,
|
|
warehouse=warehouse_relaxed,
|
|
operator=operator,
|
|
items=[{'product_id': product.id, 'quantity': 3, 'num_of_rolls': 1, 'price': '10'}],
|
|
remarks='销退对账',
|
|
)
|
|
services.review_sales_return_order(
|
|
sales_return_order=return_order,
|
|
target_status=business_models.SalesReturnStatusEnum.APPROVED,
|
|
)
|
|
|
|
receipt_order = services.create_receipt_order(
|
|
merchant=merchant,
|
|
customer=customer,
|
|
receipt_date=today,
|
|
amount='20',
|
|
discount_amount='2',
|
|
operator=operator,
|
|
remarks='收款对账',
|
|
)
|
|
services.review_receipt_order(
|
|
receipt_order=receipt_order,
|
|
target_status=business_models.ReceiptOrderStatusEnum.APPROVED,
|
|
)
|
|
|
|
business_models.ExternalCustomerStatementOrder.objects.create(
|
|
merchant=merchant,
|
|
customer=customer,
|
|
category=business_models.ExternalCustomerStatementCategoryEnum.SALE,
|
|
external_source_id='EXT-SALE-1',
|
|
occurred_at=today,
|
|
total_amount=Decimal('50'),
|
|
sf_amount=Decimal('5'),
|
|
zk_amount=Decimal('3'),
|
|
items_payload=[{'product_name': '外部销售'}],
|
|
)
|
|
business_models.ExternalCustomerStatementOrder.objects.create(
|
|
merchant=merchant,
|
|
customer=customer,
|
|
category=business_models.ExternalCustomerStatementCategoryEnum.SALE_RETURN,
|
|
external_source_id='EXT-RETURN-1',
|
|
occurred_at=today,
|
|
total_amount=Decimal('7'),
|
|
zk_amount=Decimal('1'),
|
|
items_payload=[{'product_name': '外部退货'}],
|
|
)
|
|
|
|
payload = services.build_customer_statement(merchant=merchant, customer=customer)
|
|
|
|
source_types = {record['source_type'] for record in payload['records']}
|
|
self.assertEqual(
|
|
source_types,
|
|
{
|
|
'sales_order',
|
|
'sales_return_order',
|
|
'receipt_order',
|
|
'external_sales_order',
|
|
'external_sales_return_order',
|
|
},
|
|
)
|
|
sales_record = next(record for record in payload['records'] if record['source_type'] == 'sales_order')
|
|
self.assertEqual(sales_record['items'][0]['quantity'], Decimal('10'))
|
|
self.assertEqual(sales_record['items'][0]['quantity_of_rolls'], [6, 4])
|
|
receipt_record = next(record for record in payload['records'] if record['source_type'] == 'receipt_order')
|
|
self.assertEqual(receipt_record['positive_amount'], Decimal('-2.00'))
|
|
self.assertEqual(receipt_record['negative_amount'], Decimal('20.00'))
|
|
summary = services.build_statement_summary(payload)
|
|
self.assertIn('positive_total', summary)
|
|
self.assertIn('negative_total', summary)
|
|
|
|
def test_build_supplier_statement_collects_all_supplier_records(self):
|
|
merchant, supplier, warehouse_strict, warehouse_relaxed, product, operator = create_basic_fixtures()
|
|
self._disable_auto_stock_tasks(merchant)
|
|
today = timezone.now().date()
|
|
|
|
purchase_order = services.create_purchase_order(
|
|
merchant=merchant,
|
|
supplier=supplier,
|
|
order_date=today,
|
|
warehouse=warehouse_strict,
|
|
operator=operator,
|
|
items=[{'product_id': product.id, 'numbers': [8, 2], 'price': '9', 'unit': '米'}],
|
|
remarks='采购对账',
|
|
)
|
|
services.review_purchase_order(
|
|
purchase_order=purchase_order,
|
|
target_status=business_models.PurchaseOrderStatusEnum.APPROVED,
|
|
)
|
|
|
|
return_order = services.create_purchase_return_order(
|
|
merchant=merchant,
|
|
supplier=supplier,
|
|
return_date=today,
|
|
warehouse=warehouse_relaxed,
|
|
operator=operator,
|
|
items=[{'product_id': product.id, 'quantity': 4, 'num_of_rolls': 1, 'price': '9'}],
|
|
remarks='采退对账',
|
|
)
|
|
services.review_purchase_return_order(
|
|
purchase_return_order=return_order,
|
|
target_status=business_models.PurchaseReturnStatusEnum.APPROVED,
|
|
)
|
|
|
|
payment_order = services.create_payment_order(
|
|
merchant=merchant,
|
|
supplier=supplier,
|
|
payment_date=today,
|
|
amount='15',
|
|
operator=operator,
|
|
remarks='付款对账',
|
|
)
|
|
services.review_payment_order(
|
|
payment_order=payment_order,
|
|
target_status=business_models.PaymentOrderStatusEnum.APPROVED,
|
|
)
|
|
|
|
payload = services.build_supplier_statement(merchant=merchant, supplier=supplier)
|
|
|
|
source_types = {record['source_type'] for record in payload['records']}
|
|
self.assertEqual(source_types, {'purchase_order', 'purchase_return_order', 'payment_order'})
|
|
purchase_record = next(record for record in payload['records'] if record['source_type'] == 'purchase_order')
|
|
self.assertEqual(purchase_record['items'][0]['quantity'], Decimal('10'))
|
|
self.assertEqual(purchase_record['items'][0]['num_of_rolls'], 2)
|
|
payment_record = next(record for record in payload['records'] if record['source_type'] == 'payment_order')
|
|
self.assertEqual(payment_record['negative_amount'], Decimal('15.00'))
|