forked from erp-dev/erp
feat: statement api for business module
This commit is contained in:
@@ -13,6 +13,9 @@ class StatementRecordSerializer(serializers.Serializer):
|
||||
counterparty_name = serializers.CharField()
|
||||
positive_amount = serializers.DecimalField(max_digits=15, decimal_places=2)
|
||||
negative_amount = serializers.DecimalField(max_digits=15, decimal_places=2)
|
||||
cumulative_amount = serializers.CharField()
|
||||
current_balance = serializers.CharField()
|
||||
arrears_amount = serializers.CharField()
|
||||
extra = serializers.DictField(required=False)
|
||||
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ from rest_framework.response import Response
|
||||
from basic_info import models as basic_models
|
||||
from business import models as business_models
|
||||
from api_v1.views.stock_change_views.mixins import StockChangeViewMixin
|
||||
from business import services as business_services
|
||||
from . import serializers as statement_serializers
|
||||
|
||||
TWO_PLACES = Decimal('0.01')
|
||||
@@ -24,6 +25,11 @@ class StatementViewBase(StockChangeViewMixin, views.APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
serializer_class = statement_serializers.StatementResponseSerializer
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self._current_balance_display: str | None = None
|
||||
self._current_balance_value: Decimal | None = None
|
||||
|
||||
def get_serializer_context(self):
|
||||
return {
|
||||
'request': self.request,
|
||||
@@ -32,11 +38,12 @@ class StatementViewBase(StockChangeViewMixin, views.APIView):
|
||||
}
|
||||
|
||||
def _build_response(self, counterparty, records: List[dict]):
|
||||
processed_records = self._attach_running_totals(records)
|
||||
serializer = self.serializer_class(
|
||||
instance={
|
||||
'counterparty': counterparty.id,
|
||||
'counterparty_name': counterparty.name,
|
||||
'records': records,
|
||||
'records': processed_records,
|
||||
},
|
||||
context=self.get_serializer_context(),
|
||||
)
|
||||
@@ -102,6 +109,22 @@ class StatementViewBase(StockChangeViewMixin, views.APIView):
|
||||
'negative_total': self._decimal_to_string(total_negative),
|
||||
}
|
||||
|
||||
def _attach_running_totals(self, records: List[dict]) -> List[dict]:
|
||||
running_total = ZERO
|
||||
current_balance_value = self._current_balance_value or ZERO
|
||||
current_balance_display = self._current_balance_display or self._decimal_to_string(current_balance_value)
|
||||
processed = []
|
||||
for record in records:
|
||||
record_copy = dict(record)
|
||||
record_copy['cumulative_amount'] = self._decimal_to_string(running_total)
|
||||
record_copy['current_balance'] = current_balance_display
|
||||
arrears_amount = current_balance_value - running_total
|
||||
record_copy['arrears_amount'] = self._decimal_to_string(arrears_amount)
|
||||
delta = record_copy['positive_amount'] - record_copy['negative_amount']
|
||||
running_total += delta
|
||||
processed.append(record_copy)
|
||||
return processed
|
||||
|
||||
|
||||
class CustomerStatementView(StatementViewBase):
|
||||
"""
|
||||
@@ -118,6 +141,7 @@ class CustomerStatementView(StatementViewBase):
|
||||
except basic_models.Customer.DoesNotExist:
|
||||
return self.not_found_response('客户不存在')
|
||||
|
||||
self._get_customer_balance(merchant, customer)
|
||||
records = self._collect_customer_records(merchant, customer)
|
||||
return self._build_response(customer, records)
|
||||
|
||||
@@ -212,6 +236,15 @@ class CustomerStatementView(StatementViewBase):
|
||||
)
|
||||
return records
|
||||
|
||||
def _get_customer_balance(self, merchant, customer):
|
||||
balance = business_services.BalanceService.get_customer_balance(
|
||||
merchant=merchant,
|
||||
customer=customer,
|
||||
)
|
||||
self._current_balance_value = balance
|
||||
self._current_balance_display = self._decimal_to_string(balance)
|
||||
return self._current_balance_display
|
||||
|
||||
|
||||
class SupplierStatementView(StatementViewBase):
|
||||
"""
|
||||
@@ -228,6 +261,7 @@ class SupplierStatementView(StatementViewBase):
|
||||
except basic_models.Supplier.DoesNotExist:
|
||||
return self.not_found_response('供应商不存在')
|
||||
|
||||
self._get_supplier_balance(merchant, supplier)
|
||||
records = self._collect_supplier_records(merchant, supplier)
|
||||
return self._build_response(supplier, records)
|
||||
|
||||
@@ -322,4 +356,13 @@ class SupplierStatementView(StatementViewBase):
|
||||
)
|
||||
return records
|
||||
|
||||
def _get_supplier_balance(self, merchant, supplier):
|
||||
balance = business_services.BalanceService.get_supplier_balance(
|
||||
merchant=merchant,
|
||||
supplier=supplier,
|
||||
)
|
||||
self._current_balance_value = balance
|
||||
self._current_balance_display = self._decimal_to_string(balance)
|
||||
return self._current_balance_display
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user