diff --git a/app/integrations/simbrella.py b/app/integrations/simbrella.py index b83b9c3..091b6d3 100644 --- a/app/integrations/simbrella.py +++ b/app/integrations/simbrella.py @@ -11,6 +11,8 @@ from app.services.repayment import RepaymentService from app.extensions import db from app.services.repayments_data import RepaymentsData from app.services.salary import SalaryService +from app.enums.loan_status import LoanStatus +from decimal import Decimal, ROUND_HALF_UP class SimbrellaClient: @@ -277,48 +279,41 @@ class SimbrellaClient: "fbnTransactionId": result.get('fbnTransactionId') or collect_loan_data.get('fbnTransactionId'), "accountId": result.get('accountId') or collect_loan_data.get('accountId'), "customerId": result.get('customerId') or collect_loan_data.get('customerId'), - "amountCollected": result.get('amountCollected'), + "amountCollected": float(result.get('amountCollected', 0)), "repaymentAmount": collect_loan_data.get('collectAmount'), "responseCode": result.get('responseCode'), "responseDescr": result.get('responseMessage'), - "balance":result.get('lienAmount') + "balance": round(float(result.get('lienAmount', 0)), 2) } - + new_repayment_data = RepaymentsData.add_repayment_data(data_to_add) - logger.info(f"Repayment data added successfully: {new_repayment_data.to_dict()}") - if not new_repayment_data: - logger.info(f"Failed to add repayment data") - - return ResponseHelper.success(response.json(), "Successful") + if new_repayment_data: + logger.info(f"Repayment data added successfully: {new_repayment_data.to_dict()}") + else: + logger.warning("Failed to add repayment data") + + # Process loan update only if successful + if result.get('responseCode') == '00': + amount_collected = Decimal(str(result.get('amountCollected', 0))).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP) + logger.info(f'amount collected {amount_collected}') + updated_loan = LoanService.update_loan_balance(int(loan_data['debtId']), amount_collected) + logger.info(f'updated loan {updated_loan}') + updated_balance = Decimal(str(updated_loan['balance'])).quantize(Decimal('0.01')) + logger.info(f'updated balance {updated_balance}') + + if updated_balance <= Decimal('0.00'): + repaid = LoanService.update_status(updated_loan['debtId'], LoanStatus.REPAID) + logger.info(f'updated loan with repaid {repaid}') + else: + LoanService.update_status(updated_loan['debtId'], LoanStatus.ACTIVE_PARTIAL) + logger.info(f'updated loan with partial ') + + return ResponseHelper.success(result, "Successful") + except Exception as e: - logger.info(f"Failed to call CollectLoan endpoint: {e}") + logger.exception("Failed to call CollectLoan endpoint") return ResponseHelper.error("Failed to call CollectLoan endpoint") - - @staticmethod - def refresh_disbursement(data): - - try: - logger.info(f"Here is your Disbursement Request data ***** : {data}") - - return ResponseHelper.success(data, "Successful") - - except Exception as e: - logger.info(f"Failed to call Disbursement endpoint: {e}") - raise - - @staticmethod - def payment_callback(data): - - try: - logger.info(f"Here is your Payment Callback Request data ***** : {data}") - - return ResponseHelper.success(data, "Successful") - - except Exception as e: - logger.info(f"Failed to call Payment Callback endpoint: {e}") - raise - @staticmethod def penal_charge(data): diff --git a/app/models/loan.py b/app/models/loan.py index 0d598e6..be28cc4 100644 --- a/app/models/loan.py +++ b/app/models/loan.py @@ -240,19 +240,66 @@ class Loan(db.Model): return customer_loans, total_amount + @classmethod def update_status(cls, loan_id, status): """ - Update the status of the loan with the given loan_id. + Update the status of the loan record with the given loan_id. """ - # Retrieve loan - loan = cls.query.get(loan_id) + try: + # Retrieve loan record + loan = cls.query.get(loan_id) + + if not loan: + raise ValueError(f"Loan with ID {loan_id} does not exist.") + + if loan.status == status: + return loan.to_dict() # Still return the current state if no change + + # Update status and timestamp + loan.status = status + loan.updated_at = datetime.now(timezone.utc) + db.session.commit() - if not loan: - raise ValueError(f"Loan with ID {loan_id} does not exist.") + logger.info("Loan status updated and committed.") + return loan.to_dict() - if loan.status == status: - return + except Exception as e: + db.session.rollback() + logger.error(f"Error updating loan status: {e}") + raise Exception(f"Error updating loan status: {str(e)}") + + + @classmethod + def update_loan_balance(cls, loan_id, amount_collected): + """ + Update the balance of a loan after successful repayment. + """ + try: + # Fetch the loan record + loan = cls.query.get(loan_id) - # Update loan status and the updated_at timestamp - loan.status = status \ No newline at end of file + if not loan: + raise ValueError(f"Loan with ID {loan_id} does not exist.") + + # Ensure valid repayment amount + if amount_collected <= 0: + raise ValueError("Repayment amount must be greater than zero.") + if loan.balance is None: + raise ValueError("There is no balance for this loan") + + if amount_collected > loan.balance: + raise ValueError("Repayment amount exceeds current loan balance.") + + # Deduct the amount from the current balance + loan.balance -= amount_collected + loan.updated_at = datetime.now(timezone.utc) + db.session.commit() + + logger.info(f"Loan balance updated for loan ID {loan_id}. New balance: {loan.balance}") + return loan.to_dict() + + except Exception as e: + db.session.rollback() + logger.error(f"Error updating loan balance: {e}") + raise Exception(f"Error updating loan balance: {str(e)}") \ No newline at end of file diff --git a/app/services/loan.py b/app/services/loan.py index 042ad48..293b1be 100644 --- a/app/services/loan.py +++ b/app/services/loan.py @@ -86,3 +86,9 @@ class LoanService: """ # 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)