1
0
forked from erp-dev/erp

feat: BalanceChangeRecord

This commit is contained in:
2025-12-01 15:22:59 +08:00
parent 9acc4e14fc
commit a3b4af2602
8 changed files with 359 additions and 14 deletions

View File

@@ -25,15 +25,25 @@ class BalanceService:
merchant: basic_info_models.Merchant,
supplier: basic_info_models.Supplier,
delta: Decimal,
source_type: models.BalanceChangeSourceEnum,
source_id: int,
request_id: str | None = None,
remarks: str | None = '',
extra_meta: Dict[str, Any] | None = None,
):
with transaction.atomic():
balance, _ = models.SupplierBalance.objects.select_for_update().get_or_create(
merchant=merchant,
supplier=supplier,
defaults={'balance': Decimal('0')},
)
balance.balance += delta
balance.save(update_fields=['balance', 'updated_at'])
BalanceService._adjust_balance(
merchant=merchant,
counterparty=supplier,
balance_model=models.SupplierBalance,
balance_field='supplier',
delta=delta,
target_type=models.BalanceChangeTargetEnum.SUPPLIER,
source_type=source_type,
source_id=source_id,
request_id=request_id,
remarks=remarks,
extra_meta=extra_meta,
)
@staticmethod
def adjust_customer_balance(
@@ -41,16 +51,77 @@ class BalanceService:
merchant: basic_info_models.Merchant,
customer: basic_info_models.Customer,
delta: Decimal,
source_type: models.BalanceChangeSourceEnum,
source_id: int,
request_id: str | None = None,
remarks: str | None = '',
extra_meta: Dict[str, Any] | None = None,
):
BalanceService._adjust_balance(
merchant=merchant,
counterparty=customer,
balance_model=models.CustomerBalance,
balance_field='customer',
delta=delta,
target_type=models.BalanceChangeTargetEnum.CUSTOMER,
source_type=source_type,
source_id=source_id,
request_id=request_id,
remarks=remarks,
extra_meta=extra_meta,
)
@staticmethod
def _adjust_balance(
*,
merchant: basic_info_models.Merchant,
counterparty,
balance_model,
balance_field: str,
delta: Decimal,
target_type: models.BalanceChangeTargetEnum,
source_type: models.BalanceChangeSourceEnum,
source_id: int,
request_id: str | None,
remarks: str | None,
extra_meta: Dict[str, Any] | None,
):
meta_payload = extra_meta or {}
remarks_value = remarks or ''
with transaction.atomic():
balance, _ = models.CustomerBalance.objects.select_for_update().get_or_create(
balance, _ = balance_model.objects.select_for_update().get_or_create(
merchant=merchant,
customer=customer,
defaults={'balance': Decimal('0')},
**{balance_field: counterparty},
)
before = balance.balance
balance.balance += delta
balance.save(update_fields=['balance', 'updated_at'])
record_kwargs = {
'merchant': merchant,
'target_type': target_type,
'source_type': source_type,
'source_id': source_id,
'delta': delta,
'direction': (
models.BalanceChangeDirectionEnum.INCREASE
if delta >= 0
else models.BalanceChangeDirectionEnum.DECREASE
),
'balance_before': before,
'balance_after': balance.balance,
'request_id': request_id,
'remarks': remarks_value,
'extra_meta': meta_payload,
}
if target_type == models.BalanceChangeTargetEnum.SUPPLIER:
record_kwargs['supplier'] = counterparty
else:
record_kwargs['customer'] = counterparty
models.BalanceChangeRecord.objects.create(**record_kwargs)
@staticmethod
def get_customer_balance(
*,
@@ -373,6 +444,8 @@ def review_payment_order(
merchant=locked.merchant,
supplier=locked.supplier,
delta=-locked.amount,
source_type=models.BalanceChangeSourceEnum.PAYMENT_ORDER,
source_id=locked.id,
)
locked.refresh_from_db(fields=['status', 'updated_at'])
return locked
@@ -424,6 +497,8 @@ def review_receipt_order(
merchant=locked.merchant,
customer=locked.customer,
delta=-locked.amount,
source_type=models.BalanceChangeSourceEnum.RECEIPT_ORDER,
source_id=locked.id,
)
locked.refresh_from_db(fields=['status', 'updated_at'])
return locked
@@ -577,6 +652,8 @@ def _approve_purchase_order(
merchant=locked_order.merchant,
supplier=locked_order.supplier,
delta=locked_order.get_total_amount(),
source_type=models.BalanceChangeSourceEnum.PURCHASE_ORDER,
source_id=locked_order.id,
)
created_by_id = getattr(reviewed_by, 'id', None)
@@ -632,6 +709,8 @@ def _approve_sales_order(
merchant=locked_order.merchant,
customer=locked_order.customer,
delta=locked_order.get_total_amount(),
source_type=models.BalanceChangeSourceEnum.SALES_ORDER,
source_id=locked_order.id,
)
created_by_id = getattr(reviewed_by, 'id', None)