From c516c3f52c0887d02d5990ee819bd0ef80ea7d0f Mon Sep 17 00:00:00 2001 From: VivianDee <115420678+VivianDee@users.noreply.github.com> Date: Wed, 15 Oct 2025 12:46:13 +0100 Subject: [PATCH 1/5] [fix]: Provide loan charge scheduleand swagger doc --- app/api/routes/routes.py | 8 +-- app/api/services/provide_loan.py | 52 +++++++++++++++----- app/swagger/schemas/ProvideLoanResponse.json | 35 +++++++++++++ 3 files changed, 80 insertions(+), 15 deletions(-) diff --git a/app/api/routes/routes.py b/app/api/routes/routes.py index 2bf06c5..a18a62a 100644 --- a/app/api/routes/routes.py +++ b/app/api/routes/routes.py @@ -42,10 +42,10 @@ def swagger_json(): return send_from_directory(swagger_dir, "digifi_swagger.json") -# @api.route("/swagger/") -# def serve_paths(filename): -# swagger_dir = os.path.join("swagger") -# return send_from_directory(swagger_dir, filename) +@api.route("/swagger/") +def serve_paths(filename): + swagger_dir = os.path.join("swagger") + return send_from_directory(swagger_dir, filename) # EligibilityCheck Endpoint diff --git a/app/api/services/provide_loan.py b/app/api/services/provide_loan.py index 86c0fe7..2a4615f 100644 --- a/app/api/services/provide_loan.py +++ b/app/api/services/provide_loan.py @@ -17,6 +17,7 @@ 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 @@ -162,16 +163,14 @@ 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 + ) + response_data = { "requestId": request_id, "transactionId": transaction_id, @@ -215,4 +214,35 @@ 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): + 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) + + return charge_schedule_items + + diff --git a/app/swagger/schemas/ProvideLoanResponse.json b/app/swagger/schemas/ProvideLoanResponse.json index c4c688e..c9891fe 100644 --- a/app/swagger/schemas/ProvideLoanResponse.json +++ b/app/swagger/schemas/ProvideLoanResponse.json @@ -25,6 +25,41 @@ "type": "string", "example": "98016510058" }, + "schedule": { + "type": "array", + "description": "List of loan repayment components with due dates and amounts.", + "items": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "example": 1 + }, + "amountDue": { + "type": "number", + "example": 2000.0 + }, + "componentName": { + "type": "string", + "example": "INTEREST" + }, + "dueDate": { + "type": "string", + "format": "date-time", + "example": "2026-01-13T11:36:39.890747+00:00" + }, + "startDate": { + "type": "string", + "format": "date-time", + "example": "2025-10-15T11:36:39.890747+00:00" + }, + "loanRef": { + "type": "string", + "example": "TRX1760528156816285USSD3MPC" + } + } + } + }, "resultCode": { "type": "string", "example": "00" From fe5d3fbc6e70dce4d805a2147f1cc71ac37af28d Mon Sep 17 00:00:00 2001 From: VivianDee <115420678+VivianDee@users.noreply.github.com> Date: Wed, 15 Oct 2025 12:54:49 +0100 Subject: [PATCH 2/5] Update AuthorizeRefresh.json --- app/swagger/paths/AuthorizeRefresh.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/swagger/paths/AuthorizeRefresh.json b/app/swagger/paths/AuthorizeRefresh.json index a5f19ee..cbb0408 100644 --- a/app/swagger/paths/AuthorizeRefresh.json +++ b/app/swagger/paths/AuthorizeRefresh.json @@ -1,6 +1,6 @@ { "post": { - "tags": ["Authorize Refresh"], + "tags": ["AuthorizeRefresh"], "summary": "Customer Authorize Refresh Request", "description": "Customer Authorize Refresh Request", "operationId": "AuthorizeRefresh", From b7e3527f3541385c06a5551bf60f97d19430e8bd Mon Sep 17 00:00:00 2001 From: "CHIEFSOFT\\ameye" Date: Thu, 16 Oct 2025 23:49:38 -0400 Subject: [PATCH 3/5] added network --- docker-compose.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index ef41164..b960d19 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,3 +1,4 @@ +version: '3.8' services: digifi-bank-to-product-core: build: . @@ -11,4 +12,14 @@ services: - DATABASE_URL=postgresql+psycopg2://${DATABASE_USER}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME} volumes: - .:/app - restart: always \ No newline at end of file + restart: always + networks: + - my_custom_network + + +networks: + my_custom_network: + driver: bridge + ipam: + config: + - subnet: 10.244.0.0/26 From 550895b8effd48b756f12977b6a2336b7add48a3 Mon Sep 17 00:00:00 2001 From: "CHIEFSOFT\\ameye" Date: Fri, 17 Oct 2025 19:22:29 -0400 Subject: [PATCH 4/5] rearrange for parts --- app/__init__.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/app/__init__.py b/app/__init__.py index deb9ed6..6ed6ea4 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -22,19 +22,17 @@ def create_app(): # import oracledb # oracledb.init_oracle_client(lib_dir=None) + app = Flask(__name__) + + # Load configuration + app.config.from_object(Config) + + CORS(app) + JWTManager(app) + CORS(app, supports_credentials=True) + try: - - app = Flask(__name__) - - # Load configuration - app.config.from_object(Config) - - CORS(app) - - JWTManager(app) - CORS(app, supports_credentials=True) - # Swagger Doc SWAGGER_URL = app.config.get("SWAGGER_URL") API_URL = app.config.get("API_URL") @@ -45,6 +43,11 @@ def create_app(): swagger_ui_blueprint = get_swaggerui_blueprint(SWAGGER_URL, API_URL) app.register_blueprint(swagger_ui_blueprint, url_prefix=SWAGGER_URL) + except Exception as e: + print(f"Swagger Unexpected error occurred: {e}") + + + try: # Error Handlers register_error_handlers(app) From 68aca1407ceece851d5f8ffa290e28ae39a751d8 Mon Sep 17 00:00:00 2001 From: "CHIEFSOFT\\ameye" Date: Fri, 17 Oct 2025 19:48:58 -0400 Subject: [PATCH 5/5] SELECT table_name FROM user_tables ORDER BY table_name --- app/api/routes/routes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/api/routes/routes.py b/app/api/routes/routes.py index a18a62a..858539f 100644 --- a/app/api/routes/routes.py +++ b/app/api/routes/routes.py @@ -140,7 +140,7 @@ def health_check(): # Check database connection try: logger.info(f"Database Health == : {SQLALCHEMY_DATABASE_URI}") - db.session.execute(text("SELECT 1")) + db.session.execute(text("SELECT table_name FROM user_tables ORDER BY table_name")) except Exception as e: db_status = "Connection Failed" errors.append(f"Database Error: {str(e)}")