added failed loans endpoint
This commit was merged in pull request #70.
This commit is contained in:
@@ -26,6 +26,12 @@ autocall_bp = Blueprint("autocall", __name__)
|
||||
#
|
||||
@autocall_bp.route("/refresh-verify-disbursement", methods=["GET"])
|
||||
def verify_transaction():
|
||||
"""
|
||||
Get the latest loan with disbursement date and no verification date.
|
||||
Then call the verify transaction endpoint with the loan data.
|
||||
This is called after disbursement to ensure the loan was actually disbursed
|
||||
Then a verification date is set
|
||||
"""
|
||||
logger.info(f"Calling VerifyTransaction Components")
|
||||
|
||||
loan = LoanService.get_latest_loan_with_disburse_date()
|
||||
@@ -49,6 +55,11 @@ def verify_transaction():
|
||||
|
||||
@autocall_bp.route("/refresh-disbursement", methods=["GET"])
|
||||
def disbursement():
|
||||
"""
|
||||
Get the latest loan without disbursement date.
|
||||
Then call the disburse loan endpoint with the loan data.
|
||||
"""
|
||||
|
||||
# data = request.json()
|
||||
logger.info(f"Calling Disbursement Components")
|
||||
loan = LoanService.get_latest_loan_without_disburse_date()
|
||||
@@ -72,6 +83,14 @@ def disbursement():
|
||||
|
||||
@autocall_bp.route("/retry-disbursement", methods=["POST"])
|
||||
def retry_disbursement():
|
||||
"""
|
||||
This takes in a transaction id as input and
|
||||
retries the disbursement for the loan with that transaction id.
|
||||
This is to be used in cases where the disbursement failed due to network issues
|
||||
or other transient issues. It will call the disbursement endpoint
|
||||
with the loan data for the loan with the given transaction id.
|
||||
"""
|
||||
|
||||
try:
|
||||
data = request.get_json()
|
||||
logger.info(f"Retry Transaction ID Data Received for :::: {data}")
|
||||
@@ -103,8 +122,64 @@ def retry_disbursement():
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to call retry disbursement {data}: {e}")
|
||||
|
||||
@autocall_bp.route("/retry-failed-disbursements", methods=["GET"])
|
||||
def retry_failed_disbursements():
|
||||
"""
|
||||
This endpoint is for retrying failed disbursements.
|
||||
It will get the list of failed disbursements and call the disbursement endpoint for each of them.
|
||||
This is to be used in cases where the disbursement failed due to network issues or other transient issues. It will call the disbursement endpoint
|
||||
with the loan data for the loan with the given transaction id.
|
||||
"""
|
||||
|
||||
try:
|
||||
logger.info(f"Calling Retry Failed Disbursements Components")
|
||||
failed_disbursements = LoanService.get_failed_disbursements()
|
||||
if not failed_disbursements:
|
||||
logger.info(f"No failed disbursements found")
|
||||
return ResponseHelper.success(message="No failed disbursements found", status_code=200)
|
||||
|
||||
logger.info(f"Found {len(failed_disbursements)} failed disbursements to retry")
|
||||
#get batch size from settings
|
||||
# Safe config values
|
||||
batch_size = max(1, settings.FAILED_DISBURSEMENT_BATCH_SIZE or 1)
|
||||
delay_seconds = max(0, settings.FAILED_DISBURSEMENT_DELAY_SECONDS or 0)
|
||||
batch_delay = max(0, settings.FAILED_DISBURSEMENT_BATCH_DELAY_SECONDS or 0)
|
||||
for i in range(0, len(failed_disbursements), batch_size):
|
||||
batch = failed_disbursements[i:i + batch_size]
|
||||
for loan in batch:
|
||||
logger.info(f"Retrying disbursement for loan ID {loan.id}")
|
||||
loan_data = loan.to_dict()
|
||||
|
||||
data = {
|
||||
"transactionId": loan_data.get('transactionId'),
|
||||
"FbnTransactionId": loan_data.get('transactionId'),
|
||||
"debtId": str(loan_data.get('debtId')),
|
||||
"customerId": loan_data.get('customerId'),
|
||||
"accountId": loan_data.get('accountId'),
|
||||
"productId": str(loan_data.get('productId', "")),
|
||||
"provideAmount": loan_data.get('currentLoanAmount'),
|
||||
}
|
||||
response = SimbrellaClient.disburse_loan(data)
|
||||
logger.info(f"Retry Disbursement Result Received for loan ID {loan.id}: {response}")
|
||||
time_module.sleep(delay_seconds)
|
||||
time_module.sleep(batch_delay)
|
||||
return ResponseHelper.success(message="Retry Failed Disbursements Request Sent Successfully", status_code=200)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to retry disbursements: {e}")
|
||||
return ResponseHelper.error("Failed to retry disbursements", status_code=500, error=str(e))
|
||||
|
||||
|
||||
|
||||
|
||||
@autocall_bp.route("/direct/loan", methods=["POST"])
|
||||
def direct_loan():
|
||||
"""
|
||||
This endpoint is for directly calling the disbursement endpoint with a transaction id.
|
||||
This is to be used in cases where the disbursement failed due to network issues
|
||||
or other transient issues. It will call the disbursement endpoint
|
||||
with the loan data for the loan with the given transaction id.
|
||||
"""
|
||||
|
||||
data = request.get_json()
|
||||
logger.info(f"Data received: {data}")
|
||||
|
||||
@@ -156,6 +231,10 @@ def direct_loan():
|
||||
|
||||
@autocall_bp.route("/direct/repayment", methods=["POST"])
|
||||
def direct_repayment():
|
||||
"""
|
||||
This endpoint is for directly calling the collect loan endpoint with a transaction id.
|
||||
"""
|
||||
|
||||
data = request.get_json()
|
||||
logger.info(f"Data received: {data}")
|
||||
|
||||
@@ -239,6 +318,9 @@ def direct_repayment():
|
||||
|
||||
@autocall_bp.route("/refresh-verify-collection", methods=["GET"])
|
||||
def refresh_verify_collection():
|
||||
"""
|
||||
This endpoint is for directly calling the verify collection endpoint.
|
||||
"""
|
||||
data = request.get_json()
|
||||
logger.info(f"Calling Verify Collection")
|
||||
|
||||
@@ -248,6 +330,11 @@ def refresh_verify_collection():
|
||||
|
||||
@autocall_bp.route("/refresh-collection", methods=["GET"])
|
||||
def refresh_collection():
|
||||
"""
|
||||
This endpoint is for directly calling the collect loan endpoint.
|
||||
It will get the latest repayment with no repay date and call the collect loan endpoint with that repayment data.
|
||||
This is to be used in cases where the collection failed due to network issues or other transient issues. It will call the collection endpoint
|
||||
"""
|
||||
#data = request.get_json()
|
||||
logger.info(f"Calling Collection ")
|
||||
#grab the last repayments with repay date is none
|
||||
@@ -283,7 +370,11 @@ def payment_callback():
|
||||
return response
|
||||
|
||||
@autocall_bp.route("/penal-charge", methods=["POST"])
|
||||
|
||||
def penal_charge():
|
||||
"""
|
||||
This endpoint is for directly calling the penal charge endpoint.
|
||||
"""
|
||||
data = request.get_json()
|
||||
logger.info(f"Calling Penal Charge Endpoint")
|
||||
|
||||
@@ -296,6 +387,13 @@ def penal_charge():
|
||||
|
||||
@autocall_bp.route("/analytic-salary-detect", methods=["POST"])
|
||||
def salary_detect():
|
||||
"""
|
||||
Creates new salary data
|
||||
Gets the salary list not yet processed
|
||||
then, gets the loan list for each salary and
|
||||
creates repayments for each loan with the salary data,
|
||||
then calls the collect loan endpoint for each repayment created.
|
||||
"""
|
||||
payload = request.get_json()
|
||||
logger.info("Calling Salary Detect endpoint")
|
||||
|
||||
@@ -421,6 +519,7 @@ def process_salary_list():
|
||||
|
||||
@autocall_bp.route("/report", methods=["GET"])
|
||||
def report():
|
||||
"""This endpoint is for generating the report and sending the email."""
|
||||
try:
|
||||
report_data = get_report_data()
|
||||
logger.info(f"Generated report data: {report_data}")
|
||||
@@ -435,6 +534,12 @@ def report():
|
||||
|
||||
@autocall_bp.route("/process-penal-charges", methods=["GET"])
|
||||
def process_penal_charges():
|
||||
"""
|
||||
This endpoint is for processing penal charges for overdue loans schedule with grace period.
|
||||
It will check for overdue loans, calculate the penal charge,
|
||||
create a new penal charge record, update the loan and repayment schedule with the new penal charge, and call the Simbrella endpoint to update the penal charge on their system.
|
||||
"""
|
||||
|
||||
try:
|
||||
OVERDUE_GRACE_PERIOD_DAYS = settings.OVERDUE_GRACE_PERIOD_DAYS
|
||||
OVERDUE_PROCESSING_LIST_LIMIT = settings.OVERDUE_PROCESSING_LIST_LIMIT
|
||||
@@ -549,6 +654,12 @@ def process_penal_charges():
|
||||
|
||||
@autocall_bp.route("/overdue-loans", methods=["GET"])
|
||||
def overdue_loans():
|
||||
"""
|
||||
This endpoint is for processing overdue loans.
|
||||
It will get all active overdue loan schedules,
|
||||
and then for each loan schedule, it will create a repayment, update the loan status, and call the Simbrella endpoint to collect the loan.
|
||||
"""
|
||||
|
||||
try:
|
||||
# Step 1: Get all active overdue loans
|
||||
overdue_loans = LoanRepaymentScheduleService.get_active_overdue_repayment_schedule()
|
||||
|
||||
Reference in New Issue
Block a user