initial commit

This commit is contained in:
lennyaiko
2025-03-27 11:29:36 +01:00
commit 8e2d371218
35 changed files with 548 additions and 0 deletions
+27
View File
@@ -0,0 +1,27 @@
from flask import Flask
from flask_cors import CORS
from app.config import Config
from app.routes import auth_bp, eligibility_bp
from app.errors import method_not_allowed, unsupported_media_type
def create_app():
"""Factory function to create a Flask app instance"""
app = Flask(__name__)
# Load configuration
app.config.from_object(Config)
CORS(app)
# Register blueprints
app.register_blueprint(auth_bp)
# app.register_blueprint(loan_bp)
app.register_blueprint(eligibility_bp, url_prefix="/eligibility")
# app.register_blueprint(repayment_bp)
# Error Handlers
app.register_error_handler(405, method_not_allowed)
app.register_error_handler(415, unsupported_media_type)
return app
Binary file not shown.
Binary file not shown.
+9
View File
@@ -0,0 +1,9 @@
import os
class Config:
"""Base configuration for Flask app"""
SECRET_KEY = os.getenv("SECRET_KEY", "supersecretkey")
API_BASE_URL = "https://coreapi.dev.simbrellang.net/v1/api/salary"
JWT_SECRET_KEY = os.getenv("JWT_SECRET_KEY", "your_jwt_secret")
DEBUG = True
+1
View File
@@ -0,0 +1 @@
from .handlers import method_not_allowed, unsupported_media_type
Binary file not shown.
Binary file not shown.
+18
View File
@@ -0,0 +1,18 @@
from flask import jsonify
from app.helpers.response_helper import ResponseHelper
def method_not_allowed(error):
return ResponseHelper.method_not_allowed(message="Method Not Allowed")
def not_found(error):
return ResponseHelper.not_found(message="URL Not Found")
def bad_request(error):
return ResponseHelper.bad_request(message="Bad Request")
def unsupported_media_type(error):
return ResponseHelper.error(message="Unsupported Media Type", status_code=415)
+251
View File
@@ -0,0 +1,251 @@
from flask import jsonify
from typing import List, Dict, Union, Optional, Any
class ResponseHelper:
"""
A helper class for building standardized JSON responses in Flask.
"""
@staticmethod
def build_response(
status: bool,
message: str,
data: Optional[Union[Dict, List, str]] = None,
status_code: int = 200,
error: Optional[Union[Dict, str]] = None,
) -> Dict[str, Any]:
"""
Build a standardized JSON response.
Args:
status (bool): Indicates whether the request was successful.
message (str): A message describing the result of the request.
data (Optional[Union[Dict, List, str]]): The data to return in the response.
status_code (int): The HTTP status code for the response.
error (Optional[Union[Dict, str]]): Any error details to include in the response.
Returns:
Dict[str, Any]: A dictionary representing the JSON response.
"""
response = {
"status": status,
"statusCode": status_code,
"message": message,
"data": data if data is not None else {},
"error": error if error is not None else {},
}
return jsonify(response), status_code
@staticmethod
def success(
data: Optional[Union[Dict, List, str]] = None,
message: str = "Successful",
status_code: int = 200,
error: Optional[Union[Dict, str]] = None,
) -> Dict[str, Any]:
"""
Return a success response.
Args:
data (Optional[Union[Dict, List, str]]): The data to return in the response.
message (str): A message describing the result of the request.
status_code (int): The HTTP status code for the response.
error (Optional[Union[Dict, str]]): Any error details to include in the response.
Returns:
Dict[str, Any]: A dictionary representing the JSON response.
"""
return ResponseHelper.build_response(True, message, data, status_code, error)
@staticmethod
def error(
message: str = "An error occurred",
status_code: int = 400,
data: Optional[Union[Dict, List, str]] = None,
error: Optional[Union[Dict, str]] = None,
) -> Dict[str, Any]:
"""
Return an error response.
Args:
message (str): A message describing the error.
status_code (int): The HTTP status code for the response.
data (Optional[Union[Dict, List, str]]): The data to return in the response.
error (Optional[Union[Dict, str]]): Any error details to include in the response.
Returns:
Dict[str, Any]: A dictionary representing the JSON response.
"""
return ResponseHelper.build_response(False, message, data, status_code, error)
@staticmethod
def created(
data: Optional[Union[Dict, List, str]] = None,
message: str = "Resource created successfully",
error: Optional[Union[Dict, str]] = None,
) -> Dict[str, Any]:
"""
Return a response for a created resource.
Args:
data (Optional[Union[Dict, List, str]]): The data to return in the response.
message (str): A message describing the result of the request.
error (Optional[Union[Dict, str]]): Any error details to include in the response.
Returns:
Dict[str, Any]: A dictionary representing the JSON response.
"""
return ResponseHelper.build_response(True, message, data, 201, error)
@staticmethod
def updated(
data: Optional[Union[Dict, List, str]] = None,
message: str = "Resource updated successfully",
error: Optional[Union[Dict, str]] = None,
) -> Dict[str, Any]:
"""
Return a response for an updated resource.
Args:
data (Optional[Union[Dict, List, str]]): The data to return in the response.
message (str): A message describing the result of the request.
error (Optional[Union[Dict, str]]): Any error details to include in the response.
Returns:
Dict[str, Any]: A dictionary representing the JSON response.
"""
return ResponseHelper.build_response(True, message, data, 200, error)
@staticmethod
def internal_server_error(
message: str = "Internal Server Error",
data: Optional[Union[Dict, List, str]] = None,
error: Optional[Union[Dict, str]] = None,
) -> Dict[str, Any]:
"""
Return a response for an internal server error.
Args:
message (str): A message describing the error.
data (Optional[Union[Dict, List, str]]): The data to return in the response.
error (Optional[Union[Dict, str]]): Any error details to include in the response.
Returns:
Dict[str, Any]: A dictionary representing the JSON response.
"""
return ResponseHelper.build_response(False, message, data, 500, error)
@staticmethod
def unauthorized(
message: str = "Unauthorized",
data: Optional[Union[Dict, List, str]] = None,
error: Optional[Union[Dict, str]] = None,
) -> Dict[str, Any]:
"""
Return a response for an unauthorized request.
Args:
message (str): A message describing the error.
data (Optional[Union[Dict, List, str]]): The data to return in the response.
error (Optional[Union[Dict, str]]): Any error details to include in the response.
Returns:
Dict[str, Any]: A dictionary representing the JSON response.
"""
return ResponseHelper.build_response(False, message, data, 401, error)
@staticmethod
def forbidden(
message: str = "Forbidden",
data: Optional[Union[Dict, List, str]] = None,
error: Optional[Union[Dict, str]] = None,
) -> Dict[str, Any]:
"""
Return a response for a forbidden request.
Args:
message (str): A message describing the error.
data (Optional[Union[Dict, List, str]]): The data to return in the response.
error (Optional[Union[Dict, str]]): Any error details to include in the response.
Returns:
Dict[str, Any]: A dictionary representing the JSON response.
"""
return ResponseHelper.build_response(False, message, data, 403, error)
@staticmethod
def not_found(
message: str = "Resource not found",
data: Optional[Union[Dict, List, str]] = None,
error: Optional[Union[Dict, str]] = None,
) -> Dict[str, Any]:
"""
Return a response for a not found resource.
Args:
message (str): A message describing the error.
data (Optional[Union[Dict, List, str]]): The data to return in the response.
error (Optional[Union[Dict, str]]): Any error details to include in the response.
Returns:
Dict[str, Any]: A dictionary representing the JSON response.
"""
return ResponseHelper.build_response(False, message, data, 404, error)
@staticmethod
def unprocessable_entity(
message: str = "Unprocessable entity",
data: Optional[Union[Dict, List, str]] = None,
error: Optional[Union[Dict, str]] = None,
) -> Dict[str, Any]:
"""
Return a response for an unprocessable entity.
Args:
message (str): A message describing the error.
data (Optional[Union[Dict, List, str]]): The data to return in the response.
error (Optional[Union[Dict, str]]): Any error details to include in the response.
Returns:
Dict[str, Any]: A dictionary representing the JSON response.
"""
return ResponseHelper.build_response(False, message, data, 422, error)
@staticmethod
def method_not_allowed(
message: str = "Method Not Allowed",
data: Optional[Union[Dict, List, str]] = None,
error: Optional[Union[Dict, str]] = None,
) -> Dict[str, Any]:
"""
Return a response for a method not allowed error.
Args:
message (str): A message describing the error.
data (Optional[Union[Dict, List, str]]): The data to return in the response.
error (Optional[Union[Dict, str]]): Any error details to include in the response.
Returns:
Dict[str, Any]: A dictionary representing the JSON response.
"""
return ResponseHelper.build_response(False, message, data, 405, error)
@staticmethod
def bad_request(
message: str = "Bad Request",
data: Optional[Union[Dict, List, str]] = None,
error: Optional[Union[Dict, str]] = None,
) -> Dict[str, Any]:
"""
Return a response for a bad request error.
Args:
message (str): A message describing the error.
data (Optional[Union[Dict, List, str]]): The data to return in the response.
error (Optional[Union[Dict, str]]): Any error details to include in the response.
Returns:
Dict[str, Any]: A dictionary representing the JSON response.
"""
return ResponseHelper.build_response(False, message, data, 400, error)
+4
View File
@@ -0,0 +1,4 @@
from .authentication import auth_bp
from .eligibility import eligibility_bp
# from .loan import loan_bp
# from .repayment import repayment_bp
Binary file not shown.
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
from flask import Blueprint, request, jsonify
import requests
from app.utils.auth import get_headers
auth_bp = Blueprint("auth", __name__)
@auth_bp.route("/health", methods=["GET"])
def health():
return jsonify({"status": "Up"})
@auth_bp.route("/login", methods=["POST"])
def login():
data = request.json
api_url = "https://coreapi.dev.simbrellang.net/api/auth/login"
response = requests.post(api_url, json=data)
if response.status_code == 200:
return jsonify(response.json()), 200
return jsonify({"error": "Invalid credentials"}), response.status_code
+42
View File
@@ -0,0 +1,42 @@
from flask import Blueprint, request, jsonify, current_app
import requests
from app.utils.auth import get_headers
eligibility_bp = Blueprint("eligibility", __name__)
@eligibility_bp.route("/check", methods=["POST"])
def eligibility_check():
data = request.json
api_url = f"{current_app.config['API_BASE_URL']}/EligibilityCheck"
print(api_url)
# response = requests.post(api_url, json=data, headers=get_headers())
# return jsonify(response.json()), response.status_code
response = {
"customerId": "CN621868",
"transactionId": "Tr201712RK9232P115",
"countryCode": "NGR",
"msisdn": "2348012345678",
"eligibleOffers": [
{
"offerId": 101,
"minAmount": 5000,
"maxAmount": 20000,
"productId": 2030,
"tenor": 30,
},
{
"offerId": 102,
"minAmount": 20000,
"maxAmount": 50000,
"productId": 2090,
"tenor": 90,
},
],
"resultCode": "00",
"resultDescription": "Successful",
}
return jsonify(response), 200
View File
View File
View File
Binary file not shown.
Binary file not shown.
+8
View File
@@ -0,0 +1,8 @@
import requests
from flask import current_app
def get_headers():
return {
"Authorization": f"Bearer {current_app.config['JWT_SECRET_KEY']}",
"Content-Type": "application/json"
}
+13
View File
@@ -0,0 +1,13 @@
import logging
# Configure logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
handlers=[
# logging.StreamHandler(), # Log to console
logging.FileHandler("app.log", mode='a') # Log to file
]
)
logger = logging.getLogger("DetectionService")