overdue loans

This commit was merged in pull request #45.
This commit is contained in:
Chinenye Nmoh
2025-08-27 15:49:17 +01:00
parent fb460471fb
commit a174340b2f
4 changed files with 42 additions and 44 deletions
+28
View File
@@ -1,4 +1,8 @@
from app.models import Loan, LoanCharge
from app.utils.logger import logger
from app.enums.loan_status import LoanStatus
from decimal import Decimal, ROUND_HALF_UP
from app.services.loan_repayment_schedule import LoanRepaymentScheduleService
class LoanService:
@@ -106,5 +110,29 @@ class LoanService:
Get all overdue loans.
"""
return Loan.get_overdue_loans()
@staticmethod
def _update_loan_after_collection(loan, loan_data, updated_loan, amount_collected, data, response_message):
if loan.balance is None or loan.balance <= 0:
logger.warning(f"Loan ID {loan.id} has no balance. Skipping loan update.")
updated_loan = loan.to_dict()
else:
updated_loan = LoanService.update_loan_balance(int(loan_data['debtId']), amount_collected)
updated_balance = Decimal(str(updated_loan['balance'])).quantize(Decimal('0.01'))
if updated_balance <= Decimal('0.00'):
updated_loan = LoanService.update_status(updated_loan['debtId'], LoanStatus.REPAID)
else:
updated_loan = LoanService.update_status(updated_loan['debtId'], LoanStatus.ACTIVE_PARTIAL)
logger.info(f"Updated loan status: {updated_loan.get('status')}")
# lets update the loan repayment schedule
LoanRepaymentScheduleService.handle_schedule_updates(
updated_loan=updated_loan,
data=data,
amount_collected=amount_collected,
message=response_message,
loan_data=loan_data
)
return updated_loan
+7 -2
View File
@@ -1,6 +1,7 @@
from app.models.loan_repayment_schedule import LoanRepaymentSchedule
from app.utils.logger import logger
from app.enums.loan_status import LoanStatus
from decimal import Decimal, ROUND_HALF_UP
class LoanRepaymentScheduleService:
@@ -40,6 +41,7 @@ class LoanRepaymentScheduleService:
"""
return LoanRepaymentSchedule.update_repayment_schedule_description(schedule_id, description)
@staticmethod
def handle_schedule_updates(updated_loan, data, amount_collected, message, loan_data):
"""
@@ -68,12 +70,12 @@ class LoanRepaymentScheduleService:
logger.error(f"Failed to update installment {installment.id}: {e}")
logger.info('All installments processed')
# Case 2: Partial repayment without overdueLoanScheduleId
# Case 2: Partial repayment made on a full loan without overdueLoanScheduleId
elif updated_loan and updated_loan.get('status') == LoanStatus.ACTIVE_PARTIAL and not data.get('overdueLoanScheduleId'):
logger.info("Partial repayment detected, but no overdue schedule ID provided.")
# TODO: implement proportional installment updates
# Case 3: Overdue schedule repayment → update balance & description
# Case 3: when we are processing Overdue schedule repayment → update balance & description
elif data.get('overdueLoanScheduleId') is not None:
logger.info(f"Overdue loan schedule ID: {data['overdueLoanScheduleId']}")
try:
@@ -102,4 +104,7 @@ class LoanRepaymentScheduleService:
except Exception as e:
logger.error(f"Unexpected error while handling schedule updates: {e}")