Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fe5d3fbc6e | |||
| c516c3f52c | |||
| f8da81d564 | |||
| 9da259900c | |||
| 4da0b8c716 | |||
| ddb08d8063 | |||
| 8c405c5d2e | |||
| 4c95112bde | |||
| 324293ee96 |
+27
-23
@@ -20,40 +20,44 @@ from flask_jwt_extended import (
|
||||
def create_app():
|
||||
"""Factory function to create a Flask app instance"""
|
||||
# import oracledb
|
||||
|
||||
|
||||
# oracledb.init_oracle_client(lib_dir=None)
|
||||
|
||||
app = Flask(__name__)
|
||||
try:
|
||||
|
||||
# Load configuration
|
||||
app.config.from_object(Config)
|
||||
app = Flask(__name__)
|
||||
|
||||
CORS(app)
|
||||
# Load configuration
|
||||
app.config.from_object(Config)
|
||||
|
||||
JWTManager(app)
|
||||
CORS(app, supports_credentials=True)
|
||||
CORS(app)
|
||||
|
||||
# Swagger Doc
|
||||
SWAGGER_URL = app.config.get("SWAGGER_URL")
|
||||
API_URL = app.config.get("API_URL")
|
||||
JWTManager(app)
|
||||
CORS(app, supports_credentials=True)
|
||||
|
||||
# Register blueprints
|
||||
app.register_blueprint(api)
|
||||
# Swagger Doc
|
||||
SWAGGER_URL = app.config.get("SWAGGER_URL")
|
||||
API_URL = app.config.get("API_URL")
|
||||
|
||||
swagger_ui_blueprint = get_swaggerui_blueprint(SWAGGER_URL, API_URL)
|
||||
app.register_blueprint(swagger_ui_blueprint, url_prefix=SWAGGER_URL)
|
||||
# Register blueprints
|
||||
app.register_blueprint(api)
|
||||
|
||||
# Error Handlers
|
||||
register_error_handlers(app)
|
||||
swagger_ui_blueprint = get_swaggerui_blueprint(SWAGGER_URL, API_URL)
|
||||
app.register_blueprint(swagger_ui_blueprint, url_prefix=SWAGGER_URL)
|
||||
|
||||
from . import models
|
||||
# Error Handlers
|
||||
register_error_handlers(app)
|
||||
|
||||
# Initialize Flask-Mail
|
||||
mail.init_app(app)
|
||||
from . import models
|
||||
|
||||
# Database and Migrations
|
||||
db.init_app(app)
|
||||
# Initialize Flask-Mail
|
||||
mail.init_app(app)
|
||||
|
||||
migrate.init_app(app, db)
|
||||
# Database and Migrations
|
||||
db.init_app(app)
|
||||
|
||||
return app
|
||||
migrate.init_app(app, db)
|
||||
|
||||
return app
|
||||
except Exception as e:
|
||||
print(f"An unexpected error occurred: {e}")
|
||||
|
||||
@@ -118,19 +118,28 @@ def notification_callback():
|
||||
response = NotificationCallbackService.process_request(data)
|
||||
return response
|
||||
|
||||
|
||||
# Health Check Endpoint
|
||||
@api.route("/health", methods=["GET"])
|
||||
def health_check():
|
||||
|
||||
SQLALCHEMY_DATABASE_URI = settings.SQLALCHEMY_DATABASE_URI
|
||||
response = {}
|
||||
db_status = "Connection Successful"
|
||||
events_service_status = "Connection Successful"
|
||||
errors = []
|
||||
status = "ok"
|
||||
|
||||
|
||||
# Extract the database URI
|
||||
try:
|
||||
db_uri = db.engine.url.render_as_string(hide_password=False)
|
||||
db_uri = db_uri
|
||||
except Exception as e:
|
||||
db_uri = "Unavailable"
|
||||
|
||||
|
||||
# Check database connection
|
||||
try:
|
||||
logger.info(f"Database Health == : {SQLALCHEMY_DATABASE_URI}")
|
||||
db.session.execute(text("SELECT 1"))
|
||||
except Exception as e:
|
||||
db_status = "Connection Failed"
|
||||
@@ -158,6 +167,7 @@ def health_check():
|
||||
"status": status,
|
||||
"db_status": db_status,
|
||||
"events_service_status": events_service_status,
|
||||
"db_uri": db_uri,
|
||||
"errors": errors or None
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -158,20 +159,26 @@ class ProvideLoanService(BaseService):
|
||||
|
||||
loan_charges = LoanCharge.create_charges_for_loan(loan_id = loan_id, transaction_id = transaction_id, referenced_amount = 800, charges = charges)
|
||||
|
||||
|
||||
|
||||
else:
|
||||
return ResponseHelper.error(result_description="Invalid Customer or Account")
|
||||
|
||||
|
||||
|
||||
|
||||
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,
|
||||
"loanRef": loan_ref,
|
||||
"customerId": customer_id,
|
||||
"accountId": account_id,
|
||||
"msisdn": customer.msisdn
|
||||
"msisdn": customer.msisdn,
|
||||
"schedule": charge_schedule_items,
|
||||
}
|
||||
|
||||
|
||||
@@ -207,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
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"post": {
|
||||
"tags": ["Authorize Refresh"],
|
||||
"tags": ["AuthorizeRefresh"],
|
||||
"summary": "Customer Authorize Refresh Request",
|
||||
"description": "Customer Authorize Refresh Request",
|
||||
"operationId": "AuthorizeRefresh",
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user