added extra query
This commit is contained in:
+147
-147
@@ -1,148 +1,148 @@
|
||||
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:
|
||||
|
||||
@classmethod
|
||||
def get_loan_by_transaction_id(cls, transaction_id):
|
||||
"""
|
||||
Get the loan by transaction ID
|
||||
"""
|
||||
return Loan.get_loan_by_transaction_id(transaction_id)
|
||||
@classmethod
|
||||
def get_loan_by_loan_id(cls, loan_id):
|
||||
"""
|
||||
Get the loan by ID
|
||||
"""
|
||||
return Loan.get_loan_by_loan_id(loan_id)
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_loan_by_debt_id(cls, debt_id):
|
||||
"""
|
||||
Get the loan by transaction ID
|
||||
"""
|
||||
return Loan.get_loan_by_debt_id(debt_id)
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_loan_charge_by_debt_id(cls, debt_id):
|
||||
"""
|
||||
Get the loan charge by debt ID
|
||||
"""
|
||||
return LoanCharge.get_loan_charge_by_debt_id(debt_id)
|
||||
|
||||
@classmethod
|
||||
def set_disbursement_date(cls, loan_id, customer_id):
|
||||
"""
|
||||
Update the disbursement status of the loan with the given loan_id.
|
||||
"""
|
||||
return Loan.set_disbursement_date(loan_id, customer_id)
|
||||
@classmethod
|
||||
def set_disburse_verify_date(cls, loan_id, customer_id):
|
||||
"""
|
||||
Update the disburse verify date of the loan with the given loan_id.
|
||||
"""
|
||||
return Loan.set_disburse_verify_date(loan_id, customer_id)
|
||||
|
||||
@classmethod
|
||||
def set_disbursement_result(cls, loan_id, result, description):
|
||||
"""
|
||||
Update the disbursement result of the loan with the given loan_id.
|
||||
"""
|
||||
return Loan.set_disbursement_result(loan_id, result, description)
|
||||
|
||||
@classmethod
|
||||
def set_disbursement_loan_description(cls,loan_id,description):
|
||||
|
||||
return Loan.set_disbursement_message(loan_id, description)
|
||||
|
||||
|
||||
@classmethod
|
||||
def set_disburse_verify_result(cls, loan_id, result, description):
|
||||
"""
|
||||
Update the disburse verify result of the loan with the given loan_id.
|
||||
"""
|
||||
return Loan.set_disburse_verify_result(loan_id, result, description)
|
||||
|
||||
@classmethod
|
||||
def get_latest_loan_without_disburse_date(cls):
|
||||
"""
|
||||
Get the latest loan without a disbursement date.
|
||||
"""
|
||||
return Loan.get_latest_loan_without_disburse_date()
|
||||
|
||||
@classmethod
|
||||
def get_latest_loan_with_disburse_date(cls):
|
||||
"""
|
||||
Get the latest loan without a disbursement date.
|
||||
"""
|
||||
return Loan.get_latest_loan_with_disburse_date()
|
||||
|
||||
@classmethod
|
||||
def get_customer_loans(cls, customer_id):
|
||||
"""
|
||||
Get customer's active loans by customer_id.
|
||||
"""
|
||||
|
||||
return Loan.get_customer_loans(customer_id=customer_id)
|
||||
@classmethod
|
||||
def get_customer_active_loans(cls, customer_id):
|
||||
"""
|
||||
Get customer's active loans by customer_id.
|
||||
"""
|
||||
|
||||
return Loan.get_customer_active_loans(customer_id=customer_id)
|
||||
|
||||
@classmethod
|
||||
def update_status(cls, loan_id, status):
|
||||
"""
|
||||
Update the status of the loan with the given loan_id.
|
||||
"""
|
||||
# Retrieve loan
|
||||
return Loan.update_status(loan_id, status)
|
||||
@classmethod
|
||||
def update_loan_balance(cls,loan_id,amount_collected):
|
||||
"""
|
||||
update the loan balance after successful repayment
|
||||
"""
|
||||
return Loan.update_loan_balance(loan_id,amount_collected)
|
||||
|
||||
@classmethod
|
||||
def get_overdue_loans(cls):
|
||||
"""
|
||||
Get all overdue loans.
|
||||
"""
|
||||
return Loan.get_overdue_loans()
|
||||
@classmethod
|
||||
def apply_penal_to_loan(cls,loan_id,penal_charge):
|
||||
return Loan.apply_penal_to_loan(loan_id,penal_charge)
|
||||
@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
|
||||
|
||||
|
||||
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:
|
||||
|
||||
@classmethod
|
||||
def get_loan_by_transaction_id(cls, transaction_id):
|
||||
"""
|
||||
Get the loan by transaction ID
|
||||
"""
|
||||
return Loan.get_loan_by_transaction_id(transaction_id)
|
||||
@classmethod
|
||||
def get_loan_by_loan_id(cls, loan_id):
|
||||
"""
|
||||
Get the loan by ID
|
||||
"""
|
||||
return Loan.get_loan_by_loan_id(loan_id)
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_loan_by_debt_id(cls, debt_id):
|
||||
"""
|
||||
Get the loan by transaction ID
|
||||
"""
|
||||
return Loan.get_loan_by_debt_id(debt_id)
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_loan_charge_by_debt_id(cls, debt_id):
|
||||
"""
|
||||
Get the loan charge by debt ID
|
||||
"""
|
||||
return LoanCharge.get_loan_charge_by_debt_id(debt_id)
|
||||
|
||||
@classmethod
|
||||
def set_disbursement_date(cls, loan_id, customer_id):
|
||||
"""
|
||||
Update the disbursement status of the loan with the given loan_id.
|
||||
"""
|
||||
return Loan.set_disbursement_date(loan_id, customer_id)
|
||||
@classmethod
|
||||
def set_disburse_verify_date(cls, loan_id, customer_id):
|
||||
"""
|
||||
Update the disburse verify date of the loan with the given loan_id.
|
||||
"""
|
||||
return Loan.set_disburse_verify_date(loan_id, customer_id)
|
||||
|
||||
@classmethod
|
||||
def set_disbursement_result(cls, loan_id, result, description):
|
||||
"""
|
||||
Update the disbursement result of the loan with the given loan_id.
|
||||
"""
|
||||
return Loan.set_disbursement_result(loan_id, result, description)
|
||||
|
||||
@classmethod
|
||||
def set_disbursement_loan_description(cls,loan_id,description):
|
||||
|
||||
return Loan.set_disbursement_message(loan_id, description)
|
||||
|
||||
|
||||
@classmethod
|
||||
def set_disburse_verify_result(cls, loan_id, result, description):
|
||||
"""
|
||||
Update the disburse verify result of the loan with the given loan_id.
|
||||
"""
|
||||
return Loan.set_disburse_verify_result(loan_id, result, description)
|
||||
|
||||
@classmethod
|
||||
def get_latest_loan_without_disburse_date(cls):
|
||||
"""
|
||||
Get the latest loan without a disbursement date.
|
||||
"""
|
||||
return Loan.get_latest_loan_without_disburse_date()
|
||||
|
||||
@classmethod
|
||||
def get_latest_loan_with_disburse_date(cls):
|
||||
"""
|
||||
Get the latest loan without a disbursement date.
|
||||
"""
|
||||
return Loan.get_latest_loan_with_disburse_date()
|
||||
|
||||
@classmethod
|
||||
def get_customer_loans(cls, customer_id):
|
||||
"""
|
||||
Get customer's active loans by customer_id.
|
||||
"""
|
||||
|
||||
return Loan.get_customer_loans(customer_id=customer_id)
|
||||
@classmethod
|
||||
def get_customer_active_loans(cls, customer_id):
|
||||
"""
|
||||
Get customer's active loans by customer_id.
|
||||
"""
|
||||
|
||||
return Loan.get_customer_active_loans(customer_id=customer_id)
|
||||
|
||||
@classmethod
|
||||
def update_status(cls, loan_id, status):
|
||||
"""
|
||||
Update the status of the loan with the given loan_id.
|
||||
"""
|
||||
# Retrieve loan
|
||||
return Loan.update_status(loan_id, status)
|
||||
@classmethod
|
||||
def update_loan_balance(cls,loan_id,amount_collected):
|
||||
"""
|
||||
update the loan balance after successful repayment
|
||||
"""
|
||||
return Loan.update_loan_balance(loan_id,amount_collected)
|
||||
|
||||
@classmethod
|
||||
def get_overdue_loans(cls):
|
||||
"""
|
||||
Get all overdue loans.
|
||||
"""
|
||||
return Loan.get_overdue_loans()
|
||||
@classmethod
|
||||
def apply_penal_to_loan(cls,loan_id,penal_charge):
|
||||
return Loan.apply_penal_to_loan(loan_id,penal_charge)
|
||||
@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
|
||||
|
||||
|
||||
|
||||
+12
-12
@@ -1,13 +1,13 @@
|
||||
from app.models.loan_charge import LoanCharge
|
||||
|
||||
class LoanChargesService:
|
||||
@classmethod
|
||||
def create_penal_charges_for_loan(cls, loan_id, transaction_id, percent, penal_no, schedule_number, penal_amount=0.0,):
|
||||
return LoanCharge.create_penal_charges_for_loan(loan_id, transaction_id, percent, penal_no,schedule_number, penal_amount)
|
||||
@classmethod
|
||||
def get_last_penal_no(cls,loan_id):
|
||||
return LoanCharge.get_last_penal_no(loan_id)
|
||||
|
||||
@classmethod
|
||||
def get_penal_charges_by_loan_id(cls,loan_id):
|
||||
from app.models.loan_charge import LoanCharge
|
||||
|
||||
class LoanChargesService:
|
||||
@classmethod
|
||||
def create_penal_charges_for_loan(cls, loan_id, transaction_id, percent, penal_no, schedule_number, penal_amount=0.0,):
|
||||
return LoanCharge.create_penal_charges_for_loan(loan_id, transaction_id, percent, penal_no,schedule_number, penal_amount)
|
||||
@classmethod
|
||||
def get_last_penal_no(cls,loan_id):
|
||||
return LoanCharge.get_last_penal_no(loan_id)
|
||||
|
||||
@classmethod
|
||||
def get_penal_charges_by_loan_id(cls,loan_id):
|
||||
return LoanCharge.get_penal_charges_by_loan_id(loan_id)
|
||||
@@ -1,136 +1,136 @@
|
||||
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:
|
||||
|
||||
@classmethod
|
||||
def get_repayment_schedule_by_loan_id(cls, loan_id, include_paid=True):
|
||||
return LoanRepaymentSchedule.get_repayment_schedule_by_loan_id(loan_id, include_paid=include_paid)
|
||||
@classmethod
|
||||
def get_overdue_repayment_schedule(cls):
|
||||
return LoanRepaymentSchedule.get_overdue_repayment_schedule()
|
||||
@classmethod
|
||||
def get_active_overdue_repayment_schedule(cls):
|
||||
return LoanRepaymentSchedule.get_active_overdue_repayment_schedule()
|
||||
@classmethod
|
||||
def get_partially_paid_overdue_repayment_schedule(cls):
|
||||
return LoanRepaymentSchedule.get_partially_paid_overdue_repayment_schedule()
|
||||
@classmethod
|
||||
def get_repayment_schedule_by_id_and_transaction_id(cls, id, transaction_id):
|
||||
return LoanRepaymentSchedule.get_repayment_schedule_by_id_and_transaction_id(id, transaction_id)
|
||||
|
||||
@classmethod
|
||||
def get_repayment_schedule_by_transaction_id(cls, transaction_id):
|
||||
return LoanRepaymentSchedule.get_repayment_schedule_by_transaction_id(transaction_id)
|
||||
|
||||
@classmethod
|
||||
def update_repayment_schedule_status(cls, schedule_id):
|
||||
"""
|
||||
Update repayment schedule status.
|
||||
"""
|
||||
return LoanRepaymentSchedule.update_repayment_schedule_status(schedule_id)
|
||||
@classmethod
|
||||
def update_repayment_schedule_status_to_active(cls, schedule_id):
|
||||
"""
|
||||
Update repayment schedule status.
|
||||
"""
|
||||
return LoanRepaymentSchedule.update_repayment_schedule_status_to_active(schedule_id)
|
||||
@classmethod
|
||||
def update_repayment_schedule_balance(cls, schedule_id, amount_collected):
|
||||
"""
|
||||
Update repayment schedule balance.
|
||||
"""
|
||||
return LoanRepaymentSchedule.update_repayment_schedule_balance(schedule_id, amount_collected)
|
||||
@classmethod
|
||||
def calculate_penal_charge(cls, schedule):
|
||||
"""
|
||||
Calculate penal charge for a repayment schedule.
|
||||
"""
|
||||
return LoanRepaymentSchedule.calculate_penal_charge(schedule)
|
||||
|
||||
@classmethod
|
||||
def update_repayment_schedule_description(cls, schedule_id, description):
|
||||
"""
|
||||
Update repayment schedule description.
|
||||
"""
|
||||
return LoanRepaymentSchedule.update_repayment_schedule_description(schedule_id, description)
|
||||
|
||||
@classmethod
|
||||
def get_overdue_repayment_schedule_with_grace_period(cls, grace_period_days, limit=None):
|
||||
return LoanRepaymentSchedule.get_overdue_repayment_schedule_with_grace_period(grace_period_days, limit=limit)
|
||||
|
||||
@classmethod
|
||||
def apply_penal_to_schedule(cls, schedule_id, penal_amount):
|
||||
"""
|
||||
Apply penal charge to a repayment schedule.
|
||||
"""
|
||||
return LoanRepaymentSchedule.apply_penal_to_schedule(schedule_id, penal_amount)
|
||||
@staticmethod
|
||||
def handle_schedule_updates(updated_loan, data, amount_collected, message, loan_data):
|
||||
"""
|
||||
Handles updating loan repayment schedules depending on loan status
|
||||
and overdue schedule data.
|
||||
"""
|
||||
try:
|
||||
# Case 1: Loan fully repaid → mark all schedules paid
|
||||
if updated_loan and updated_loan.get('status') == LoanStatus.REPAID:
|
||||
repayment_schedule = LoanRepaymentScheduleService.get_repayment_schedule_by_loan_id(
|
||||
updated_loan['debtId'], include_paid=False
|
||||
)
|
||||
logger.info(f'Loan repayment schedule: {repayment_schedule}')
|
||||
|
||||
if repayment_schedule:
|
||||
for installment in repayment_schedule:
|
||||
try:
|
||||
logger.info(f'Processing installment: {installment}')
|
||||
LoanRepaymentScheduleService.update_repayment_schedule_status(installment.id)
|
||||
LoanRepaymentScheduleService.update_repayment_schedule_description(
|
||||
installment.id,
|
||||
message
|
||||
)
|
||||
logger.info(f'Updated installment {installment.id} as paid')
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to update installment {installment.id}: {e}")
|
||||
logger.info('All installments processed')
|
||||
|
||||
# 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: 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:
|
||||
schedule_to_update = LoanRepaymentScheduleService.get_repayment_schedule_by_id_and_transaction_id(
|
||||
data["overdueLoanScheduleId"], data["transactionId"]
|
||||
)
|
||||
logger.info(f"Schedule to update: {schedule_to_update}")
|
||||
|
||||
if schedule_to_update is None:
|
||||
logger.warning(
|
||||
f"Repayment schedule not found for ID {data['overdueLoanScheduleId']} "
|
||||
f"and transaction ID {loan_data['transactionId']}"
|
||||
)
|
||||
else:
|
||||
if not schedule_to_update.paid:
|
||||
update_schedule_balance = LoanRepaymentScheduleService.update_repayment_schedule_balance(
|
||||
schedule_to_update.id, amount_collected
|
||||
)
|
||||
logger.info(f"Updated loan schedule balance: {update_schedule_balance}")
|
||||
LoanRepaymentScheduleService.update_repayment_schedule_description(
|
||||
schedule_to_update.id,
|
||||
message
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to update repayment schedule installment: {e}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error while handling schedule updates: {e}")
|
||||
|
||||
|
||||
|
||||
|
||||
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:
|
||||
|
||||
@classmethod
|
||||
def get_repayment_schedule_by_loan_id(cls, loan_id, include_paid=True):
|
||||
return LoanRepaymentSchedule.get_repayment_schedule_by_loan_id(loan_id, include_paid=include_paid)
|
||||
@classmethod
|
||||
def get_overdue_repayment_schedule(cls):
|
||||
return LoanRepaymentSchedule.get_overdue_repayment_schedule()
|
||||
@classmethod
|
||||
def get_active_overdue_repayment_schedule(cls):
|
||||
return LoanRepaymentSchedule.get_active_overdue_repayment_schedule()
|
||||
@classmethod
|
||||
def get_partially_paid_overdue_repayment_schedule(cls):
|
||||
return LoanRepaymentSchedule.get_partially_paid_overdue_repayment_schedule()
|
||||
@classmethod
|
||||
def get_repayment_schedule_by_id_and_transaction_id(cls, id, transaction_id):
|
||||
return LoanRepaymentSchedule.get_repayment_schedule_by_id_and_transaction_id(id, transaction_id)
|
||||
|
||||
@classmethod
|
||||
def get_repayment_schedule_by_transaction_id(cls, transaction_id):
|
||||
return LoanRepaymentSchedule.get_repayment_schedule_by_transaction_id(transaction_id)
|
||||
|
||||
@classmethod
|
||||
def update_repayment_schedule_status(cls, schedule_id):
|
||||
"""
|
||||
Update repayment schedule status.
|
||||
"""
|
||||
return LoanRepaymentSchedule.update_repayment_schedule_status(schedule_id)
|
||||
@classmethod
|
||||
def update_repayment_schedule_status_to_active(cls, schedule_id):
|
||||
"""
|
||||
Update repayment schedule status.
|
||||
"""
|
||||
return LoanRepaymentSchedule.update_repayment_schedule_status_to_active(schedule_id)
|
||||
@classmethod
|
||||
def update_repayment_schedule_balance(cls, schedule_id, amount_collected):
|
||||
"""
|
||||
Update repayment schedule balance.
|
||||
"""
|
||||
return LoanRepaymentSchedule.update_repayment_schedule_balance(schedule_id, amount_collected)
|
||||
@classmethod
|
||||
def calculate_penal_charge(cls, schedule):
|
||||
"""
|
||||
Calculate penal charge for a repayment schedule.
|
||||
"""
|
||||
return LoanRepaymentSchedule.calculate_penal_charge(schedule)
|
||||
|
||||
@classmethod
|
||||
def update_repayment_schedule_description(cls, schedule_id, description):
|
||||
"""
|
||||
Update repayment schedule description.
|
||||
"""
|
||||
return LoanRepaymentSchedule.update_repayment_schedule_description(schedule_id, description)
|
||||
|
||||
@classmethod
|
||||
def get_overdue_repayment_schedule_with_grace_period(cls, grace_period_days, limit=None):
|
||||
return LoanRepaymentSchedule.get_overdue_repayment_schedule_with_grace_period(grace_period_days, limit=limit)
|
||||
|
||||
@classmethod
|
||||
def apply_penal_to_schedule(cls, schedule_id, penal_amount):
|
||||
"""
|
||||
Apply penal charge to a repayment schedule.
|
||||
"""
|
||||
return LoanRepaymentSchedule.apply_penal_to_schedule(schedule_id, penal_amount)
|
||||
@staticmethod
|
||||
def handle_schedule_updates(updated_loan, data, amount_collected, message, loan_data):
|
||||
"""
|
||||
Handles updating loan repayment schedules depending on loan status
|
||||
and overdue schedule data.
|
||||
"""
|
||||
try:
|
||||
# Case 1: Loan fully repaid → mark all schedules paid
|
||||
if updated_loan and updated_loan.get('status') == LoanStatus.REPAID:
|
||||
repayment_schedule = LoanRepaymentScheduleService.get_repayment_schedule_by_loan_id(
|
||||
updated_loan['debtId'], include_paid=False
|
||||
)
|
||||
logger.info(f'Loan repayment schedule: {repayment_schedule}')
|
||||
|
||||
if repayment_schedule:
|
||||
for installment in repayment_schedule:
|
||||
try:
|
||||
logger.info(f'Processing installment: {installment}')
|
||||
LoanRepaymentScheduleService.update_repayment_schedule_status(installment.id)
|
||||
LoanRepaymentScheduleService.update_repayment_schedule_description(
|
||||
installment.id,
|
||||
message
|
||||
)
|
||||
logger.info(f'Updated installment {installment.id} as paid')
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to update installment {installment.id}: {e}")
|
||||
logger.info('All installments processed')
|
||||
|
||||
# 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: 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:
|
||||
schedule_to_update = LoanRepaymentScheduleService.get_repayment_schedule_by_id_and_transaction_id(
|
||||
data["overdueLoanScheduleId"], data["transactionId"]
|
||||
)
|
||||
logger.info(f"Schedule to update: {schedule_to_update}")
|
||||
|
||||
if schedule_to_update is None:
|
||||
logger.warning(
|
||||
f"Repayment schedule not found for ID {data['overdueLoanScheduleId']} "
|
||||
f"and transaction ID {loan_data['transactionId']}"
|
||||
)
|
||||
else:
|
||||
if not schedule_to_update.paid:
|
||||
update_schedule_balance = LoanRepaymentScheduleService.update_repayment_schedule_balance(
|
||||
schedule_to_update.id, amount_collected
|
||||
)
|
||||
logger.info(f"Updated loan schedule balance: {update_schedule_balance}")
|
||||
LoanRepaymentScheduleService.update_repayment_schedule_description(
|
||||
schedule_to_update.id,
|
||||
message
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to update repayment schedule installment: {e}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error while handling schedule updates: {e}")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+77
-77
@@ -1,78 +1,78 @@
|
||||
from app.models import Repayment
|
||||
|
||||
class RepaymentService:
|
||||
|
||||
@staticmethod
|
||||
def get_repayment_by_transaction_id(transaction_id):
|
||||
"""
|
||||
Get the repayment by transaction ID
|
||||
"""
|
||||
return Repayment.get_repayment_by_transaction_id(transaction_id)
|
||||
@staticmethod
|
||||
def get_repayment_by_id(id):
|
||||
"""
|
||||
Get the repayment by ID
|
||||
"""
|
||||
return Repayment.get_repayment_by_id(id)
|
||||
|
||||
@classmethod
|
||||
def set_repay_date(cls, repayment_id, customer_id):
|
||||
"""
|
||||
Update the repay status of the repayment with the given repayment_id.
|
||||
"""
|
||||
return Repayment.set_repay_date(repayment_id, customer_id)
|
||||
|
||||
@classmethod
|
||||
def set_repay_verify_date(cls, repayment_id, customer_id):
|
||||
"""
|
||||
Update the verify date of the repayment with the given repayment_id.
|
||||
"""
|
||||
return Repayment.set_repay_verify_date(repayment_id, customer_id)
|
||||
|
||||
@classmethod
|
||||
def set_repay_result(cls, repayment_id, result, description):
|
||||
"""
|
||||
Update the repay result of the repayment with the given repayment_id.
|
||||
"""
|
||||
return Repayment.set_repay_result(repayment_id, result, description)
|
||||
|
||||
@classmethod
|
||||
def set_verify_date_result(cls, repayment_id, result, description):
|
||||
"""
|
||||
Update the verify result of the repayment with the given repayment_id.
|
||||
"""
|
||||
return Repayment.set_verify_date_result(repayment_id, result, description)
|
||||
|
||||
@classmethod
|
||||
def get_latest_repayment_without_repay_date(cls):
|
||||
"""
|
||||
Get the latest repayment without a repay date.
|
||||
"""
|
||||
return Repayment.get_latest_repayment_without_repay_date()
|
||||
@classmethod
|
||||
def get_latest_repayment_with_loanId(cls,loan_id):
|
||||
"""
|
||||
Get the latest repayment with loan id.
|
||||
"""
|
||||
return Repayment.get_latest_repayment_with_loanId(loan_id)
|
||||
|
||||
@classmethod
|
||||
def get_latest_loan_with_repay_date(cls):
|
||||
"""
|
||||
Get the latest repayment with a repay date and no verification date.
|
||||
"""
|
||||
return Repayment.get_latest_loan_with_repay_date()
|
||||
|
||||
@classmethod
|
||||
def add_repayment(cls, data):
|
||||
"""
|
||||
Add a new repayment entry.
|
||||
"""
|
||||
return Repayment.add_repayment(data)
|
||||
|
||||
@classmethod
|
||||
def create_repayment(cls, repayment_data):
|
||||
"""
|
||||
Add a new repayment entry.
|
||||
"""
|
||||
from app.models import Repayment
|
||||
|
||||
class RepaymentService:
|
||||
|
||||
@staticmethod
|
||||
def get_repayment_by_transaction_id(transaction_id):
|
||||
"""
|
||||
Get the repayment by transaction ID
|
||||
"""
|
||||
return Repayment.get_repayment_by_transaction_id(transaction_id)
|
||||
@staticmethod
|
||||
def get_repayment_by_id(id):
|
||||
"""
|
||||
Get the repayment by ID
|
||||
"""
|
||||
return Repayment.get_repayment_by_id(id)
|
||||
|
||||
@classmethod
|
||||
def set_repay_date(cls, repayment_id, customer_id):
|
||||
"""
|
||||
Update the repay status of the repayment with the given repayment_id.
|
||||
"""
|
||||
return Repayment.set_repay_date(repayment_id, customer_id)
|
||||
|
||||
@classmethod
|
||||
def set_repay_verify_date(cls, repayment_id, customer_id):
|
||||
"""
|
||||
Update the verify date of the repayment with the given repayment_id.
|
||||
"""
|
||||
return Repayment.set_repay_verify_date(repayment_id, customer_id)
|
||||
|
||||
@classmethod
|
||||
def set_repay_result(cls, repayment_id, result, description):
|
||||
"""
|
||||
Update the repay result of the repayment with the given repayment_id.
|
||||
"""
|
||||
return Repayment.set_repay_result(repayment_id, result, description)
|
||||
|
||||
@classmethod
|
||||
def set_verify_date_result(cls, repayment_id, result, description):
|
||||
"""
|
||||
Update the verify result of the repayment with the given repayment_id.
|
||||
"""
|
||||
return Repayment.set_verify_date_result(repayment_id, result, description)
|
||||
|
||||
@classmethod
|
||||
def get_latest_repayment_without_repay_date(cls):
|
||||
"""
|
||||
Get the latest repayment without a repay date.
|
||||
"""
|
||||
return Repayment.get_latest_repayment_without_repay_date()
|
||||
@classmethod
|
||||
def get_latest_repayment_with_loanId(cls,loan_id):
|
||||
"""
|
||||
Get the latest repayment with loan id.
|
||||
"""
|
||||
return Repayment.get_latest_repayment_with_loanId(loan_id)
|
||||
|
||||
@classmethod
|
||||
def get_latest_loan_with_repay_date(cls):
|
||||
"""
|
||||
Get the latest repayment with a repay date and no verification date.
|
||||
"""
|
||||
return Repayment.get_latest_loan_with_repay_date()
|
||||
|
||||
@classmethod
|
||||
def add_repayment(cls, data):
|
||||
"""
|
||||
Add a new repayment entry.
|
||||
"""
|
||||
return Repayment.add_repayment(data)
|
||||
|
||||
@classmethod
|
||||
def create_repayment(cls, repayment_data):
|
||||
"""
|
||||
Add a new repayment entry.
|
||||
"""
|
||||
return Repayment.create_repayment(repayment_data)
|
||||
@@ -1,11 +1,11 @@
|
||||
from app.models import RepaymentsData
|
||||
|
||||
class RepaymentService:
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_repayment_data(cls,data):
|
||||
"""
|
||||
Add a new repayment data entry.
|
||||
"""
|
||||
from app.models import RepaymentsData
|
||||
|
||||
class RepaymentService:
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_repayment_data(cls,data):
|
||||
"""
|
||||
Add a new repayment data entry.
|
||||
"""
|
||||
return RepaymentsData.add_repayment_data(data)
|
||||
+23
-23
@@ -1,24 +1,24 @@
|
||||
from app.models import Salary
|
||||
|
||||
class SalaryService:
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_salary_data(cls,data):
|
||||
"""
|
||||
Add a new salary data entry.
|
||||
"""
|
||||
return Salary.add_salary_data(data)
|
||||
|
||||
@classmethod
|
||||
def get_pending_salaries(cls):
|
||||
"""
|
||||
Get the pending salary for a given customer.
|
||||
"""
|
||||
return Salary.get_pending_salaries()
|
||||
@classmethod
|
||||
def update_status(cls, salary_id, status):
|
||||
"""
|
||||
Update the status of the salary with the given salary_id.
|
||||
"""
|
||||
from app.models import Salary
|
||||
|
||||
class SalaryService:
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_salary_data(cls,data):
|
||||
"""
|
||||
Add a new salary data entry.
|
||||
"""
|
||||
return Salary.add_salary_data(data)
|
||||
|
||||
@classmethod
|
||||
def get_pending_salaries(cls):
|
||||
"""
|
||||
Get the pending salary for a given customer.
|
||||
"""
|
||||
return Salary.get_pending_salaries()
|
||||
@classmethod
|
||||
def update_status(cls, salary_id, status):
|
||||
"""
|
||||
Update the status of the salary with the given salary_id.
|
||||
"""
|
||||
return Salary.update_status(salary_id, status)
|
||||
@@ -1,17 +1,17 @@
|
||||
from app.models import Transaction
|
||||
|
||||
class TransactionService:
|
||||
|
||||
@staticmethod
|
||||
def get_transaction_by_transaction_id(transaction_id):
|
||||
"""
|
||||
Get the transaction by ID
|
||||
"""
|
||||
return Transaction.get_transaction_by_transaction_id(transaction_id)
|
||||
|
||||
@staticmethod
|
||||
def create_transaction(transaction_id, account_id, customer_id, type, channel):
|
||||
"""
|
||||
Create Transaction Entry
|
||||
"""
|
||||
return Transaction.create_transaction(transaction_id, account_id, customer_id, type, channel)
|
||||
from app.models import Transaction
|
||||
|
||||
class TransactionService:
|
||||
|
||||
@staticmethod
|
||||
def get_transaction_by_transaction_id(transaction_id):
|
||||
"""
|
||||
Get the transaction by ID
|
||||
"""
|
||||
return Transaction.get_transaction_by_transaction_id(transaction_id)
|
||||
|
||||
@staticmethod
|
||||
def create_transaction(transaction_id, account_id, customer_id, type, channel):
|
||||
"""
|
||||
Create Transaction Entry
|
||||
"""
|
||||
return Transaction.create_transaction(transaction_id, account_id, customer_id, type, channel)
|
||||
|
||||
Reference in New Issue
Block a user