From 17c760981aa022f04f6ef101ebd134b929e795e7 Mon Sep 17 00:00:00 2001 From: VivianDee <115420678+VivianDee@users.noreply.github.com> Date: Mon, 20 Oct 2025 16:47:47 +0100 Subject: [PATCH 1/2] [add]: routes and defaults --- app/api/routes/routes.py | 2 +- app/api/services/provide_loan.py | 69 ++++++++++++++++++++++++++------ app/swagger/digifi_swagger.json | 52 ++++++++++++------------ 3 files changed, 83 insertions(+), 40 deletions(-) diff --git a/app/api/routes/routes.py b/app/api/routes/routes.py index 2bf06c5..d78e366 100644 --- a/app/api/routes/routes.py +++ b/app/api/routes/routes.py @@ -158,7 +158,7 @@ def health_check(): except Exception as e: - events_service_status = "Connection Successful" + events_service_status = "Connection Failed" status = "failed" errors.append(f"Events Service connection failed: {str(e)}") diff --git a/app/api/services/provide_loan.py b/app/api/services/provide_loan.py index 86c0fe7..88dfe5c 100644 --- a/app/api/services/provide_loan.py +++ b/app/api/services/provide_loan.py @@ -143,10 +143,10 @@ class ProvideLoanService(BaseService): db.session.flush() current_product_id = offer.product_id - schedule = LoanRepaymentSchedule.add_repayment_schedule(loan = loan, num_schedules = num_schedules, transaction_id = transaction_id) + schedules = LoanRepaymentSchedule.add_repayment_schedule(loan = loan, num_schedules = num_schedules, transaction_id = transaction_id) - if not schedule: + if not schedules: logger.error(f"Failed to create repayment schedule for loan ID {loan.id}") return ResponseHelper.error(result_description="Failed to generate loan repayment schedule.") @@ -162,16 +162,15 @@ class ProvideLoanService(BaseService): else: return ResponseHelper.error(result_description="Invalid Customer or Account") - charge_schedule_items = [] - for idx, charge in enumerate(loan_charges, start=len(charge_schedule_items) + 1): - charge_schedule_items.append({ - "id": idx, - "dueDate": charge.due_date.isoformat(), - "amountDue": float(charge.amount), - "componentName": charge.code.upper(), # e.g. INTEREST, MGMT_FEE, VAT_FEE - "startDate": charge.created_at.isoformat(), - }) - + + charge_schedule_items = ProvideLoanService.get_charge_schedule_items( + loan_charges=loan_charges, + offer=offer, + loan_ref=loan_ref, + amount=amount, + schedules=schedules + ) + response_data = { "requestId": request_id, "transactionId": transaction_id, @@ -215,4 +214,48 @@ class ProvideLoanService(BaseService): response = EventServiceIntegration.direct_loan(transaction_id=transaction_id) return response - + @classmethod + def get_charge_schedule_items(cls, loan_charges, offer, loan_ref, amount, schedules): + now = datetime.now(timezone.utc) + due_date = now + timedelta(days=offer.tenor) + + charge_schedule_items = [] + + charge_schedule_items.append({ + "id": 1, + "dueDate": due_date.isoformat(), + "amountDue": amount, + "componentName": "PRINCIPAL", + "startDate": now.isoformat(), + }) + + + for idx, charge in enumerate(loan_charges, start=len(charge_schedule_items) + 1): + item = { + "id": idx, + "dueDate": charge.due_date.isoformat(), + "amountDue": float(charge.amount), + "componentName": charge.code.upper(), # e.g. INTEREST, MGMT_FEE, VAT_FEE + "startDate": charge.created_at.isoformat(), + } + + if charge.code.upper() == "INTEREST": + item["loanRef"] = loan_ref + + charge_schedule_items.append(item) + + + for idx, schedule in enumerate(schedules, start=len(charge_schedule_items) + 1): + item = { + "id": idx, + "dueDate": schedule.due_date.isoformat(), + "amountDue": float(schedule.installment_amount), + "componentName": "DEFAULT", + "startDate": schedule.created_at.isoformat(), + "loanRef": loan_ref + } + charge_schedule_items.append(item) + + return charge_schedule_items + + diff --git a/app/swagger/digifi_swagger.json b/app/swagger/digifi_swagger.json index 6e0f87c..4027959 100644 --- a/app/swagger/digifi_swagger.json +++ b/app/swagger/digifi_swagger.json @@ -28,6 +28,10 @@ } ], "tags": [ + { + "name": "Health", + "description": "System health check including DB status." + }, { "name": "Authorize", "description": "This feature will be used for authorizing customers.", @@ -83,34 +87,9 @@ "description": "Find out more", "url": "https://www.simbrellang.net" } - }, - { - "name": "Health", - "description": "System health check including DB status." } ], "paths": { - "/Authorize": { - "$ref": "swagger/paths/Authorize.json" - }, - "/AuthorizeRefresh": { - "$ref": "swagger/paths/AuthorizeRefresh.json" - }, - "/EligibilityCheck": { - "$ref": "swagger/paths/EligibilityCheck.json" - }, - "/SelectOffer": { - "$ref": "swagger/paths/SelectOffer.json" - }, - "/ProvideLoan": { - "$ref": "swagger/paths/ProvideLoan.json" - }, - "/LoanStatus": { - "$ref": "swagger/paths/LoanStatus.json" - }, - "/Repayment": { - "$ref": "swagger/paths/Repayment.json" - }, "/health": { "get": { "tags": ["Health"], @@ -135,7 +114,7 @@ "content": { "application/json": { "example": { - "status": "ok", + "status": "failed", "db_status": "Connection Failed", "events_service_status": "unhealthy", "error":["could not connect to server: Connection refused"] @@ -145,6 +124,27 @@ } } } + }, + "/Authorize": { + "$ref": "swagger/paths/Authorize.json" + }, + "/AuthorizeRefresh": { + "$ref": "swagger/paths/AuthorizeRefresh.json" + }, + "/EligibilityCheck": { + "$ref": "swagger/paths/EligibilityCheck.json" + }, + "/SelectOffer": { + "$ref": "swagger/paths/SelectOffer.json" + }, + "/ProvideLoan": { + "$ref": "swagger/paths/ProvideLoan.json" + }, + "/LoanStatus": { + "$ref": "swagger/paths/LoanStatus.json" + }, + "/Repayment": { + "$ref": "swagger/paths/Repayment.json" } }, "components": { From ccd5b12f2ca052e4621ec9df310976c1f7ef7b1b Mon Sep 17 00:00:00 2001 From: VivianDee <115420678+VivianDee@users.noreply.github.com> Date: Mon, 20 Oct 2025 16:57:57 +0100 Subject: [PATCH 2/2] Update provide_loan.py --- app/api/services/provide_loan.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/api/services/provide_loan.py b/app/api/services/provide_loan.py index addb7b1..a361f08 100644 --- a/app/api/services/provide_loan.py +++ b/app/api/services/provide_loan.py @@ -11,13 +11,12 @@ from threading import Thread from app.models import Loan, Offer, Charge , TransactionOffer, RACCheck from app.api.enums import LoanStatus from app.extensions import db -from datetime import datetime, timezone +from datetime import datetime, timezone, timedelta from dateutil.relativedelta import relativedelta from app.api.integrations import EventServiceIntegration from app.models import LoanRepaymentSchedule from app.api.services.offer_analysis import OfferAnalysis from app.api.helpers.response_helper import ResponseHelper -from datetime import datetime, timezone, timedelta class ProvideLoanService(BaseService): TRANSACTION_TYPE = TransactionType.PROVIDE_LOAN