diff --git a/app/api/services/base_service.py b/app/api/services/base_service.py index 60aab4c..7669fab 100644 --- a/app/api/services/base_service.py +++ b/app/api/services/base_service.py @@ -79,41 +79,51 @@ class BaseService: return {"error": "No charges found for the offer"} loan_charges = offer.charges - interest = cls.get_charge_detail(loan_charges, "INTEREST", amount) - management = cls.get_charge_detail(loan_charges, "MGTFEE", amount) - insurance = cls.get_charge_detail(loan_charges, "INSURANCE", amount) - vat = cls.get_charge_detail(loan_charges, "VAT", amount) + tenor = offer.tenor // 30 # Convert to months + interest = cls.get_charge_detail(charges = loan_charges, code = "INTEREST", amount = amount) + management = cls.get_charge_detail(charges = loan_charges, code = "MGTFEE", amount = amount) + insurance = cls.get_charge_detail(charges = loan_charges, code = "INSURANCE", amount = amount) + vat = cls.get_charge_detail(charges = loan_charges, code = "VAT", amount = amount, management_fee = management["fee"]) - # Up-front payment: (principal + only those fees due immediately i.e due_days == 0) - upfront_payment = amount + sum( - amount * charge.percent / 100 - for charge in loan_charges - if charge.due == 0 - ) + # Separate fees into upfront and postpaid + upfront_fees = [ + fee["fee"] + for fee in [interest, management, insurance, vat] + if fee["due_days"] == 0 + ] - # Total amount: (principal + all fees) - total_amount = amount + sum( - amount * charge.percent / 100 - for charge in loan_charges - ) + postpaid_fees = [ + fee["fee"] + for fee in [interest, management, insurance, vat] + if fee["due_days"] != 0 + ] + + # Up-front payment: (only those fees due immediately i.e due_days == 0) + upfront_payment = sum(upfront_fees) + + # Repayment amount: (principal + only those fees not due immediately i.e due_days != 0) + repayment_amount = amount + sum(postpaid_fees) * tenor + + # Total amount: (upfront_payment + repayment_amount) + total_amount = upfront_payment + repayment_amount # Calculate the installment amount - tenor = offer.tenor - installment_amount = total_amount / tenor + installment_amount = repayment_amount / tenor return { "interest": interest, "management": management, "insurance": insurance, "vat": vat, - "upfront_payment": upfront_payment, - "total_amount": total_amount, - "installment_amount": installment_amount + "upfront_payment": round(upfront_payment, 2), + "repayment_amount": round(repayment_amount, 2), + "installment_amount": round(installment_amount, 2), + "total_amount": round(total_amount, 2) } @classmethod - def get_charge_detail(cls, charges, code, amount): + def get_charge_detail(cls, charges, code, amount, management_fee=None): """ Get details for a specific charge code from a list of loan charges. @@ -123,10 +133,16 @@ class BaseService: for charge in charges: if charge.code == code: + fee = ( + management_fee * charge.percent / 100 + if code == "VAT" and management_fee is not None + else amount * charge.percent / 100 + ) + return { "rate": charge.percent, - "fee": amount * charge.percent / 100, - "due_days": charge.due, + "fee": fee, + "due_days": charge.due } return {"rate": 0, "fee": 0, "due_days": 0} diff --git a/app/api/services/provide_loan.py b/app/api/services/provide_loan.py index 99484e2..74a521a 100644 --- a/app/api/services/provide_loan.py +++ b/app/api/services/provide_loan.py @@ -65,7 +65,7 @@ class ProvideLoanService(BaseService): charges = ProvideLoanService.calculate_charges(offer, amount) upfront_fee = charges["upfront_payment"] - repayment_amount = charges["total_amount"] + repayment_amount = charges["repayment_amount"] installment_amount = charges["installment_amount"] diff --git a/requirements.txt b/requirements.txt index 124ae97..820a23d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -37,5 +37,5 @@ confluent-kafka==1.9.2 -python-dateutil>=2.8.0 +python-dateutil