forked from erp-dev/erp
feat: correct first
This commit is contained in:
@@ -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),
|
||||
# 已收只展示 FkJinE(order.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
|
||||
|
||||
Reference in New Issue
Block a user