corrected db commit error #37

Merged
ameye merged 1 commits from test into master 2025-07-11 10:27:02 +00:00
5 changed files with 67 additions and 32 deletions
+35 -4
View File
@@ -7,6 +7,7 @@ from app.utils.extras import preprocess_loan_charges_data
import random import random
import random import random
import string import string
from app.extensions import db
from app.utils.logger import logger from app.utils.logger import logger
from flask import jsonify, current_app from flask import jsonify, current_app
from app.services.transactions import TransactionService from app.services.transactions import TransactionService
@@ -18,6 +19,8 @@ from app.enums.loan_status import LoanStatus
from decimal import Decimal, ROUND_HALF_UP from decimal import Decimal, ROUND_HALF_UP
from requests.exceptions import SSLError, RequestException,Timeout from requests.exceptions import SSLError, RequestException,Timeout
import sys import sys
from requests.exceptions import ReadTimeout, ConnectTimeout
import socket
class SimbrellaClient: class SimbrellaClient:
@@ -273,11 +276,11 @@ class SimbrellaClient:
try: try:
logger.info(f"Sending CollectLoan request............ {collect_loan_data}") logger.info(f"Sending CollectLoan request............ {collect_loan_data}")
response = requests.post(api_url, json=collect_loan_data, timeout=30, headers=get_headers()) response = requests.post(api_url, json=collect_loan_data, timeout=90, headers=get_headers())
logger.info(f"HTTP response object: {response}") logger.info(f"HTTP response object: {response}")
if response.status_code == 404: if response.status_code == 404:
db.session.rollback()
RepaymentService.set_repay_result( RepaymentService.set_repay_result(
repayment_data['Id'], repayment_data['Id'],
'404', '404',
@@ -326,6 +329,7 @@ class SimbrellaClient:
updated_loan = LoanService.update_loan_balance(int(loan_data['debtId']), amount_collected) updated_loan = LoanService.update_loan_balance(int(loan_data['debtId']), amount_collected)
logger.info(f"Updated loan: {updated_loan}") logger.info(f"Updated loan: {updated_loan}")
except Exception as ex: except Exception as ex:
db.session.rollback()
logger.error(f"Error updating loan balance for loan ID {loan.id}: {ex}") logger.error(f"Error updating loan balance for loan ID {loan.id}: {ex}")
return ResponseHelper.error("Error updating loan balance") return ResponseHelper.error("Error updating loan balance")
@@ -342,28 +346,55 @@ class SimbrellaClient:
partial = LoanService.update_status(updated_loan['debtId'], LoanStatus.ACTIVE_PARTIAL) partial = LoanService.update_status(updated_loan['debtId'], LoanStatus.ACTIVE_PARTIAL)
logger.info(f'Updated loan with partial status: {partial}') logger.info(f'Updated loan with partial status: {partial}')
except Exception as e: except Exception as e:
db.session.rollback()
logger.error(f"Error while updating loan status for debtId {updated_loan['debtId']}: {e}") logger.error(f"Error while updating loan status for debtId {updated_loan['debtId']}: {e}")
return ResponseHelper.success(result, "Successful") return ResponseHelper.success(result, "Successful")
except SSLError as ssl_err: except SSLError as ssl_err:
db.session.rollback()
logger.exception(f"SSL error while calling Simbrella endpoint: {ssl_err}") logger.exception(f"SSL error while calling Simbrella endpoint: {ssl_err}")
return ResponseHelper.error("SSL handshake failed with Simbrella", status_code=502, error=str(ssl_err)) return ResponseHelper.error("SSL handshake failed with Simbrella", status_code=502, error=str(ssl_err))
except Timeout as timeout_err: except (Timeout, ReadTimeout, ConnectTimeout, socket.timeout, TimeoutError) as timeout_err:
db.session.rollback()
logger.exception(f"Timeout while calling Simbrella: {timeout_err}") logger.exception(f"Timeout while calling Simbrella: {timeout_err}")
RepaymentService.set_repay_result(
repayment_data['Id'],
'500',
'There was a timeout while calling Simbrella'
)
return ResponseHelper.error("Connection to Simbrella timed out", status_code=504, error=str(timeout_err)) return ResponseHelper.error("Connection to Simbrella timed out", status_code=504, error=str(timeout_err))
except RequestException as req_err: except RequestException as req_err:
db.session.rollback()
logger.exception(f"RequestException while calling Simbrella: {req_err}") logger.exception(f"RequestException while calling Simbrella: {req_err}")
RepaymentService.set_repay_result(
repayment_data['Id'],
'500',
'There was a request error while calling Simbrella'
)
return ResponseHelper.error("Connection to Simbrella failed", status_code=503, error=str(req_err)) return ResponseHelper.error("Connection to Simbrella failed", status_code=503, error=str(req_err))
except SystemExit as sys_exit: except SystemExit as sys_exit:
db.session.rollback()
logger.error(f"SystemExit was triggered: {sys_exit}") logger.error(f"SystemExit was triggered: {sys_exit}")
RepaymentService.set_repay_result(
repayment_data['Id'],
'500',
'There was a system error while calling Simbrella'
)
return ResponseHelper.error("Unexpected shutdown detected", status_code=500, error=str(sys_exit)) return ResponseHelper.error("Unexpected shutdown detected", status_code=500, error=str(sys_exit))
except Exception as e: except Exception as e:
db.session.rollback()
logger.exception(f"Unexpected error occurred while calling CollectLoan: {e}") logger.exception(f"Unexpected error occurred while calling CollectLoan: {e}")
RepaymentService.set_repay_result(
repayment_data['Id'],
'500',
'Unexpected error while processing loan collection'
)
return ResponseHelper.error("Unexpected error while processing loan collection", status_code=500, error=str(e)) return ResponseHelper.error("Unexpected error while processing loan collection", status_code=500, error=str(e))
-2
View File
@@ -1,5 +1,4 @@
from datetime import datetime, timezone from datetime import datetime, timezone
from app.extensions import db
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from datetime import timedelta from datetime import timedelta
@@ -93,7 +92,6 @@ class Loan(db.Model):
'reference': self.reference, 'reference': self.reference,
'balance': self.balance, 'balance': self.balance,
'tenor': self.tenor, 'tenor': self.tenor,
} }
@classmethod @classmethod
+4 -2
View File
@@ -150,10 +150,11 @@ class Repayment(db.Model):
try: try:
logger.info(f"Updating repay date for repayment ID {repayment_id} to {current_time}") logger.info(f"Updating repay date for repayment ID {repayment_id} to {current_time}")
db.session.commit() db.session.commit()
return repayment.to_dict()
except Exception as e: except Exception as e:
db.session.rollback() db.session.rollback()
logger.error(f"Failed to update repay date: {e}") logger.error(f"Failed to update repay date: {e}")
raise raise e
@classmethod @classmethod
def set_repay_verify_date(cls, repayment_id, customer_id): def set_repay_verify_date(cls, repayment_id, customer_id):
""" """
@@ -181,11 +182,12 @@ class Repayment(db.Model):
except Exception as e: except Exception as e:
db.session.rollback() db.session.rollback()
logger.error(f"Failed to update repay verify date: {e}") logger.error(f"Failed to update repay verify date: {e}")
raise raise e
@classmethod @classmethod
def set_repay_result(cls, repayment_id, result, description): def set_repay_result(cls, repayment_id, result, description):
logger.info("repay result called")
""" """
Update the repayment result and description of the repayment with the given repayment_id. Update the repayment result and description of the repayment with the given repayment_id.
""" """
+1 -1
View File
@@ -25,7 +25,7 @@ class RepaymentsData(db.Model):
"response_code": self.response_code, "response_code": self.response_code,
"response_descr": self.response_descr, "response_descr": self.response_descr,
"customerId": self.customer_id, "customerId": self.customer_id,
"accountId": self.customer_id, "accountId": self.account_id,
"fbnTransactionId": self.fbn_transaction_id, "fbnTransactionId": self.fbn_transaction_id,
"repaymentAmount": self.repayment_amount, "repaymentAmount": self.repayment_amount,
"amountCollected": self.amount_collected, "amountCollected": self.amount_collected,
+26 -22
View File
@@ -1,5 +1,6 @@
from flask import Blueprint, request, jsonify, current_app from flask import Blueprint, request, jsonify, current_app
import requests import requests
from app.extensions import db
from app.config import settings from app.config import settings
from app.helpers.response_helper import ResponseHelper from app.helpers.response_helper import ResponseHelper
from app.utils.auth import get_headers from app.utils.auth import get_headers
@@ -167,6 +168,7 @@ def process_salary_list():
try: try:
SalaryService.update_status(pending_salary.id, "PROCESSING") SalaryService.update_status(pending_salary.id, "PROCESSING")
except Exception as e: except Exception as e:
db.session.rollback()
logger.warning(f"Could not update status for salary ID {pending_salary.id}: {e}") logger.warning(f"Could not update status for salary ID {pending_salary.id}: {e}")
continue continue
@@ -177,6 +179,7 @@ def process_salary_list():
logger.warning(f"No loans found for customer ID: {pending_salary.customer_id}") logger.warning(f"No loans found for customer ID: {pending_salary.customer_id}")
continue continue
except Exception as e: except Exception as e:
db.session.rollback()
logger.error(f"Error fetching loans for customer ID {pending_salary.customer_id}: {e}") logger.error(f"Error fetching loans for customer ID {pending_salary.customer_id}: {e}")
continue continue
@@ -197,40 +200,41 @@ def process_salary_list():
logger.info(f"Creating repayment with data: {repayment_data}") logger.info(f"Creating repayment with data: {repayment_data}")
repayment = RepaymentService.create_repayment(repayment_data) repayment = RepaymentService.create_repayment(repayment_data)
if not repayment: if not repayment or isinstance(repayment, dict) and "error" in repayment:
logger.error(f"Repayment creation failed for loan ID {loan.id}") db.session.rollback() # important in case create_repayment failed mid-way
logger.error(f"Repayment creation failed for loan ID {loan.id}: {repayment}")
continue continue
# Update loan status to START_REPAY
try: try:
LoanService.update_status(loan_id=loan.id, status=LoanStatus.START_REPAY) LoanService.update_status(loan_id=loan.id, status=LoanStatus.START_REPAY)
except Exception as e: except Exception as e:
db.session.rollback()
logger.error(f"Failed to update loan status for loan ID {loan.id}: {e}") logger.error(f"Failed to update loan status for loan ID {loan.id}: {e}")
logger.info(f"Created repayment ID: {repayment.id}") logger.info(f"Created repayment ID: {repayment.id}")
# Step 5: Call Simbrella
try:
simbrella_response = SimbrellaClient.collect_loan_user_salary_detect(repayment.to_dict())
if isinstance(simbrella_response, tuple):
simbrella_response, status_code = simbrella_response
logger.warning(f"Simbrella returned tuple: status={status_code}, response={simbrella_response}")
if isinstance(simbrella_response, dict):
if simbrella_response.get("status") != "success":
logger.warning(f"Simbrella failed for repayment ID {repayment.id}: {simbrella_response}")
else:
logger.warning(f"Unexpected Simbrella response: {type(simbrella_response)}")
except Exception as e:
logger.error(f"Failed to call Simbrella for repayment ID {repayment.id}: {e}")
except Exception as e: except Exception as e:
db.session.rollback()
logger.error(f"Error creating repayment for loan ID {loan.id}: {e}") logger.error(f"Error creating repayment for loan ID {loan.id}: {e}")
continue continue
# Step 5: Call Simbrella to collect loan
try:
simbrella_response = SimbrellaClient.collect_loan_user_salary_detect(repayment.to_dict())
if isinstance(simbrella_response, tuple):
simbrella_response, status_code = simbrella_response
logger.warning(f"Simbrella returned tuple: status={status_code}, response={simbrella_response}")
if isinstance(simbrella_response, dict):
status = simbrella_response.get("status")
if status != "success":
logger.warning(f"Simbrella call failed for repayment ID {repayment.id}: {simbrella_response}")
else:
logger.warning(f"Unexpected Simbrella response type: {type(simbrella_response)}")
except Exception as e:
logger.error(f"Failed to call Simbrella for repayment ID {repayment.id}: {e}")
logger.info(f"Finished processing salary ID: {pending_salary.id}") logger.info(f"Finished processing salary ID: {pending_salary.id}")
return ResponseHelper.success([], "Processed all pending salaries") return ResponseHelper.success([], "Processed all pending salaries")