1
0
forked from erp-dev/erp

feat: correct first

This commit is contained in:
2026-05-19 23:41:34 +08:00
parent f409f2e6ee
commit b97e86257e
25 changed files with 3885 additions and 25 deletions

View File

@@ -1903,6 +1903,8 @@ STATEMENT_ORDER_TYPE_CHOICES = (
('sales_order', '销售单'),
('sales_return_order', '销售退货单'),
('receipt_order', '收款单'),
('external_sales_order', '外部销售单'),
('external_sales_return_order', '外部销售退货单'),
('purchase_order', '采购单'),
('purchase_return_order', '采购退货单'),
('payment_order', '付款单'),
@@ -1917,9 +1919,10 @@ def build_customer_statement(
"""
根据客户历史单据生成对账记录,供多个 API 复用。
"""
balance = BalanceService.get_customer_balance(merchant=merchant, customer=customer)
builder = _CustomerStatementBuilder(merchant=merchant, current_balance=balance)
local_balance = BalanceService.get_customer_balance(merchant=merchant, customer=customer)
builder = _CustomerStatementBuilder(merchant=merchant, current_balance=local_balance)
records = builder.collect_records(customer)
builder.adjust_current_balance(builder.external_balance_adjustment)
return builder.build_payload(
counterparty_id=customer.id,
counterparty_name=customer.name,
@@ -1975,6 +1978,10 @@ class _StatementBuilder:
self._current_balance_value = _normalize_statement_amount(current_balance)
self._current_balance_display = _decimal_to_string(self._current_balance_value)
def adjust_current_balance(self, delta: Decimal) -> None:
self._current_balance_value += _normalize_statement_amount(delta)
self._current_balance_display = _decimal_to_string(self._current_balance_value)
def collect_records(self, counterparty) -> List[dict]: # pragma: no cover - interface only
raise NotImplementedError
@@ -2008,6 +2015,7 @@ class _StatementBuilder:
warehouse: basic_info_models.WareHouse | None = None,
positive_amount,
negative_amount,
remarks: str | None = '',
items: List[dict] | None = None,
extra: dict | None = None,
) -> dict:
@@ -2026,6 +2034,7 @@ class _StatementBuilder:
'warehouse': warehouse,
'positive_amount': _normalize_statement_amount(positive_amount),
'negative_amount': _normalize_statement_amount(negative_amount),
'remarks': remarks or '',
'items': items,
}
if extra:
@@ -2107,11 +2116,16 @@ class _StatementBuilder:
class _CustomerStatementBuilder(_StatementBuilder):
def __init__(self, *, merchant: basic_info_models.Merchant, current_balance: Decimal):
super().__init__(merchant=merchant, current_balance=current_balance)
self.external_balance_adjustment = Decimal('0')
def collect_records(self, customer: basic_info_models.Customer) -> List[dict]:
records: List[dict] = []
records.extend(self._build_sales_records(customer))
records.extend(self._build_sales_return_records(customer))
records.extend(self._build_receipt_records(customer))
records.extend(self._build_external_statement_records(customer))
return records
def _build_sales_records(self, customer: basic_info_models.Customer) -> List[dict]:
@@ -2141,6 +2155,7 @@ class _CustomerStatementBuilder(_StatementBuilder):
warehouse=order.warehouse,
positive_amount=order.get_total_amount(),
negative_amount=_STATEMENT_ZERO,
remarks=order.remarks,
items=items,
)
)
@@ -2173,6 +2188,7 @@ class _CustomerStatementBuilder(_StatementBuilder):
warehouse=order.warehouse,
positive_amount=_STATEMENT_ZERO,
negative_amount=order.get_total_amount(),
remarks=order.remarks,
items=items,
)
)
@@ -2189,6 +2205,9 @@ class _CustomerStatementBuilder(_StatementBuilder):
)
records = []
for order in qs:
# ERP 口径:收款单的 ZkJinE 从应收侧扣减(负的 positive_amount
# 已收只展示 FkJinEorder.amount。净效果与 settlement_amount 一致。
discount = order.discount_amount or Decimal('0')
records.append(
self._build_record(
counterparty_id=order.customer_id,
@@ -2200,8 +2219,55 @@ class _CustomerStatementBuilder(_StatementBuilder):
recorded_at=order.created_at,
status=order.status,
status_label=order.get_status_display(),
positive_amount=_STATEMENT_ZERO,
negative_amount=order.get_total_amount(),
positive_amount=-discount,
negative_amount=order.amount,
remarks=order.remarks,
)
)
return records
def _build_external_statement_records(self, customer: basic_info_models.Customer) -> List[dict]:
qs = models.ExternalCustomerStatementOrder.objects.filter(
merchant=self.merchant,
customer=customer,
).order_by('occurred_at', 'recorded_at', 'id')
records = []
for order in qs:
sf = order.sf_amount or Decimal('0')
zk = order.zk_amount or Decimal('0')
if order.category == models.ExternalCustomerStatementCategoryEnum.SALE:
source_type = 'external_sales_order'
source_label = '外部销售单'
# 净应收 = 毛额 - 折扣;现场收款作为 negative_amount 减少欠款
positive_amount = order.total_amount - zk
negative_amount = sf
else:
source_type = 'external_sales_return_order'
source_label = '外部销售退货单'
# 退货减少应收:退货金额 + 退货折扣都减少欠款
positive_amount = _STATEMENT_ZERO
negative_amount = order.total_amount + zk
self.external_balance_adjustment += positive_amount - negative_amount
records.append(
self._build_record(
counterparty_id=order.customer_id,
counterparty_name=order.customer.name,
source_type=source_type,
source_label=source_label,
source_id=order.id,
occurred_at=order.occurred_at,
recorded_at=order.recorded_at or order.created_at,
status=models.ReceiptOrderStatusEnum.APPROVED,
status_label='已同步',
positive_amount=positive_amount,
negative_amount=negative_amount,
remarks=order.remarks,
items=list(order.items_payload or []),
extra={
'external_source_id': order.external_source_id,
'external_customer_id': order.external_customer_id,
'settlement_method': order.settlement_method,
},
)
)
return records
@@ -2242,6 +2308,7 @@ class _SupplierStatementBuilder(_StatementBuilder):
warehouse=order.warehouse,
positive_amount=order.get_total_amount(),
negative_amount=_STATEMENT_ZERO,
remarks=order.remarks,
items=items,
)
)
@@ -2274,6 +2341,7 @@ class _SupplierStatementBuilder(_StatementBuilder):
warehouse=order.warehouse,
positive_amount=_STATEMENT_ZERO,
negative_amount=order.get_total_amount(),
remarks=order.remarks,
items=items,
)
)
@@ -2303,6 +2371,7 @@ class _SupplierStatementBuilder(_StatementBuilder):
status_label=order.get_status_display(),
positive_amount=_STATEMENT_ZERO,
negative_amount=order.get_total_amount(),
remarks=order.remarks,
)
)
return records