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