diff --git a/app/config.py b/app/config.py index 2b2d4e1..1a1f906 100644 --- a/app/config.py +++ b/app/config.py @@ -54,7 +54,12 @@ class Config: MAIL_USE_SSL = os.getenv('MAIL_USE_SSL', 'False').lower() in ('true', '1', 'yes') MAIL_DEFAULT_SENDER = ('FirstAdvance', 'firstadvance@dynamikservices.tech') MAIL_RECEIVER= os.getenv('MAIL_RECEIVER', 'chinenyeumeaku@gmail.com,umeakuchinenye@gmail.com') - + + OVERDUE_LOAN_BATCH_SIZE = int(os.getenv("OVERDUE_LOAN_BATCH_SIZE", 10)) + OVERDUE_LOAN_DELAY_SECONDS = int(os.getenv("OVERDUE_LOAN_DELAY_SECONDS", 5)) + OVERDUE_LOAN_BATCH_DELAY_SECONDS = int( + os.getenv("OVERDUE_LOAN_BATCH_DELAY_SECONDS", 5) + ) BANK_CALL_API_TIME_OUT = os.getenv("BANK_CALL_API_TIME_OUT", 100) BANK_CALL_BASE_URL = os.getenv("BANK_CALL_BASE_URL", "https://bank-emulator.dev.simbrellang.net/api") BANK_CALL_SMS_BASE_URL= os.getenv("BANK_CALL_SMS_BASE_URL","https://first-advance-middleware-develop.fbn-devops-dev-asenv.appserviceenvironment.net/SMS") diff --git a/app/enums/repayment_schedule_status.py b/app/enums/repayment_schedule_status.py index 3a1938f..b67c3ed 100644 --- a/app/enums/repayment_schedule_status.py +++ b/app/enums/repayment_schedule_status.py @@ -2,4 +2,6 @@ from enum import Enum class RepaymentScheduleStatus(str, Enum): PARTIALLY_PAID = "partially_paid" - REPAID = "repaid" \ No newline at end of file + REPAID = "repaid" + ACTIVE = "active" + OVERDUE = "overdue" \ No newline at end of file diff --git a/app/helpers/collect_loan_helper.py b/app/helpers/collect_loan_helper.py index 369d4b2..73e04b1 100644 --- a/app/helpers/collect_loan_helper.py +++ b/app/helpers/collect_loan_helper.py @@ -53,5 +53,11 @@ class CollectLoanHelper: "countryId": "NG", "comment": "COLLECT LOAN" } - + + @staticmethod + def chunk_list(data, chunk_size): + """Yield successive chunk_size chunks from data.""" + for i in range(0, len(data), chunk_size): + yield data[i:i + chunk_size] + \ No newline at end of file diff --git a/app/routes/autocall.py b/app/routes/autocall.py index f06aba1..0965c46 100644 --- a/app/routes/autocall.py +++ b/app/routes/autocall.py @@ -1,8 +1,10 @@ +import time as time_module from flask import Blueprint, request, jsonify, current_app import requests from app.extensions import db from app.config import settings from app.helpers.response_helper import ResponseHelper +from app.helpers.collect_loan_helper import CollectLoanHelper from app.utils.auth import get_headers from app.utils.logger import logger from app.integrations.simbrella import SimbrellaClient @@ -450,15 +452,33 @@ def overdue_loans(): if not overdue_loans: logger.info("No overdue loans found.") return ResponseHelper.success(message="No overdue loans found", status_code=200) + #get batch size from settings + loan_delay_seconds = max(0, settings.OVERDUE_LOAN_DELAY_SECONDS) + batch_delay_seconds = max(0, settings.OVERDUE_LOAN_BATCH_DELAY_SECONDS) + batch_size = max(1, settings.OVERDUE_LOAN_BATCH_SIZE) + + loan_chunks = list(CollectLoanHelper.chunk_list(overdue_loans, batch_size)) + logger.info(f"Found {len(loan_chunks)} loan chunks to process.") + # Step 2: Process each loan - for loan in overdue_loans: - process_overdue_loan(loan) + for chunk_index, loan_chunk in enumerate(loan_chunks): + logger.info(f"Processing chunk {chunk_index + 1} of {len(loan_chunks)} with {len(loan_chunk)} loans.") + for loan in loan_chunk: + try: + process_overdue_loan(loan) + except Exception: + logger.exception(f"Failed processing loan {loan.id}") + finally: + time_module.sleep(loan_delay_seconds) + if chunk_index < len(loan_chunks) - 1: + logger.info(f"Waiting {batch_delay_seconds} seconds before processing next chunk...") + time_module.sleep(batch_delay_seconds) # Delay between chunks return ResponseHelper.success(message="Processed overdue loans successfully", status_code=200) except Exception as e: - logger.error(f"Error fetching overdue loans: {e}") + logger.exception(f"Error fetching overdue loans: {e}") return ResponseHelper.error("Failed to fetch overdue loans", status_code=500, error=str(e))