diff --git a/app/api/schemas/eligibility_check.py b/app/api/schemas/eligibility_check.py deleted file mode 100644 index 7b901c2..0000000 --- a/app/api/schemas/eligibility_check.py +++ /dev/null @@ -1,10 +0,0 @@ -from marshmallow import Schema, fields - -class EligibilityCheckSchema(Schema): - transactionId = fields.Str(required=True) - countryCode = fields.Str(required=True) - customerId = fields.Str(required=True) - accountId = fields.Str(required=True) - msisdn = fields.Str(required=True) - accountId = fields.Str(required=True) - channel = fields.Str(required=True) diff --git a/app/api/schemas/loan_status.py b/app/api/schemas/loan_status.py deleted file mode 100644 index 7599d5f..0000000 --- a/app/api/schemas/loan_status.py +++ /dev/null @@ -1,8 +0,0 @@ -from marshmallow import Schema, fields - -# Loan Information Schema -class LoanStatusSchema(Schema): - transactionId = fields.Str(required=True) - customerId = fields.Str(required=True) - msisdn = fields.Str(required=False) - channel = fields.Str(required=True) \ No newline at end of file diff --git a/app/api/schemas/notification_callback.py b/app/api/schemas/notification_callback.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/api/schemas/provide_loan.py b/app/api/schemas/provide_loan.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/api/schemas/repayment.py b/app/api/schemas/repayment.py deleted file mode 100644 index 2d05321..0000000 --- a/app/api/schemas/repayment.py +++ /dev/null @@ -1,11 +0,0 @@ -from marshmallow import Schema, fields - -# Repayment Schema -class RepaymentSchema(Schema): - type = fields.Str(required=False) - msisdn = fields.Str(required=False) #optional - debtId = fields.Str(required=True) - productId = fields.Str(required=True) - transactionId = fields.Str(required=True) - customerId = fields.Str(required=True) - channel = fields.Str(required=True) diff --git a/app/api/schemas/select_offer.py b/app/api/schemas/select_offer.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/api/services/__init__.py b/app/api/services/__init__.py index 6ed730f..811857d 100644 --- a/app/api/services/__init__.py +++ b/app/api/services/__init__.py @@ -1,10 +1,4 @@ -from app.api.services.eligibility_check import EligibilityCheckService -from app.api.services.select_offer import SelectOfferService -from app.api.services.provide_loan import ProvideLoanService -from app.api.services.loan_status import LoanStatusService -from app.api.services.repayment import RepaymentService from app.api.services.customer_consent import CustomerConsentService -from app.api.services.notification_callback import NotificationCallbackService from app.api.services.authorization import AuthorizationService from app.api.services.transaction import TransactionService from app.api.services.loan import LoanService diff --git a/app/api/services/eligibility_check.py b/app/api/services/eligibility_check.py deleted file mode 100644 index 256ddf3..0000000 --- a/app/api/services/eligibility_check.py +++ /dev/null @@ -1,113 +0,0 @@ -from flask import session, jsonify -from app.utils.logger import logger -from app.api.services.base_service import BaseService -from app.api.schemas.eligibility_check import EligibilityCheckSchema -from marshmallow import ValidationError -from app.api.enums import TransactionType -from app.api.integrations import SimbrellaIntegration -from app.extensions import db - -class EligibilityCheckService(BaseService): - TRANSACTION_TYPE = TransactionType.ELIGIBILITY_CHECK - - @staticmethod - def process_request(data): - """ - Process the EligibilityCheck request. - - Args: - data (dict): The request data. - - Returns: - dict: A standardized response. - """ - try: - with db.session.begin(): - - validated_data = EligibilityCheckService.validate_data(data, EligibilityCheckSchema()) - account_id = validated_data.get('accountId') - customer_id = validated_data.get('customerId') - transactionId = validated_data.get('transactionId') - msisdn = validated_data.get('msisdn') - - customer = EligibilityCheckService.get_or_create_customer(validated_data = validated_data) - - if (EligibilityCheckService.validate_account_ownership(account_id = account_id, customer_id = customer_id)): - - transaction = EligibilityCheckService.log_transaction(validated_data = validated_data) - - if not transaction: - logger.error(f"Failed to log transaction") - return jsonify({ - "message": "Failed to log transaction." - }), 400 - - else: - return jsonify({ - "message": "Invalid Customer or Account" - }), 400 - - # Call RACCheck - response = SimbrellaIntegration.rac_check( - customer_id = customer_id, - account_id = account_id, - transaction_id = transaction.id, - ) - logger.error(f"This is Response Returned ****** : {str(response)}") - - # this chck for error is not valid - logger.error(f"Check for ERROR is not valid ****** FIX THIS !!!!!") - #if "error" in response or response.get("status") != 200: - # return jsonify({"message": "RACCheck failed"}), 400 - - offers = [ - { - "offerId": "SAL90", - "productId": "2030", - "minAmount": 5000, - "maxAmount": 100000, - "tenor": 30 - }, - { - "offerId": "SAL30", - "productId": "2090", - "minAmount": 3000, - "maxAmount": 500000, - "tenor": 90 - } - ] - - # Simulate processing - response_data = { - "customerId": customer_id, - "transactionId": transactionId, - "countryCode": "NG", - "msisdn": msisdn, - "eligibleOffers": offers, - "resultDescription": "Successful", - "resultCode": "00", - "accountId": account_id - } - - return response_data - - except ValidationError as err: - - logger.error(f"Validation Error: {getattr(err, 'messages', str(err))}") - - return jsonify({ - "message": "Validation exception" - }) , 422 - - except ValueError as err: - logger.error(f"{getattr(err, 'messages', str(err))}") - - return jsonify({ - "message": str(err) - }) , 400 - - except Exception as e: - logger.error(f"An error occurred: {str(e)}", exc_info=True) - return jsonify({ - "message": "Internal Server Error" - }) , 500 \ No newline at end of file diff --git a/app/api/services/loan.py b/app/api/services/loan.py index 71c2f8f..8169740 100644 --- a/app/api/services/loan.py +++ b/app/api/services/loan.py @@ -85,5 +85,6 @@ class LoanService(BaseService): except Exception as e: logger.error(f"An error occurred: {str(e)}", exc_info=True) return jsonify({ - "message": f"Internal Server Error: {str(e)}" + "message": "Internal Server Error" + # "message": f"Internal Server Error: {str(e)}" }), 500 diff --git a/app/api/services/loan_status.py b/app/api/services/loan_status.py deleted file mode 100644 index f80b7f2..0000000 --- a/app/api/services/loan_status.py +++ /dev/null @@ -1,100 +0,0 @@ -from flask import request, jsonify -from marshmallow import ValidationError -from app.models import Customer -from app.utils.logger import logger -from app.api.schemas.loan_status import LoanStatusSchema -from app.api.services.base_service import BaseService -from app.api.enums import TransactionType -from app.extensions import db - - -class LoanStatusService(BaseService): - TRANSACTION_TYPE = TransactionType.LOAN_STATUS - - @staticmethod - def process_request(data): - """ - Process the Loan Information request. - - Args: - data (dict): The request data. - - Returns: - dict: A standardized response. - """ - try: - with db.session.begin(): - # Validate data - validated_data = LoanStatusService.validate_data(data, LoanStatusSchema()) - - - customer_id = validated_data.get('customerId') - customer = Customer.get_customer(customer_id) - transactionId = validated_data.get('transactionId') - - # Get loans - loans = [loan.to_dict() for loan in customer.loans] - - - validated_data['refId'] = customer.id - validated_data['refModel'] = "customer" - - - transaction = LoanStatusService.log_transaction(validated_data = validated_data) - - if not transaction: - logger.error(f"Failed to log transaction") - return jsonify({ - "message": "Failed to log transaction." - }), 400 - - - # loans = [ - # { - # "debtId": "123456789", - # "loanDate": "2019-10-18 14:26:21.063", - # "dueDate": "2019-11-20 14:26:21.063", - # "currentLoanAmount": 8500, - # "initialLoanAmount": 10000, - # "defaultPenaltyFee": 0, - # "continuousFee": 0, - # "productId": "101" - # } - # ] - - # Simulated processing logic - response_data = { - "customerId": customer_id, - "transactionId": transactionId, - "loans": loans, - "totalDebtAmount": 8500, - "resultCode": "00", - "resultDescription": "Successful" - } - - db.session.commit() - return response_data - - except ValidationError as err: - - logger.error(f"Validation Error: {getattr(err, 'messages', str(err))}") - db.session.rollback() - - return jsonify({ - "message": "Validation exception" - }) , 422 - - except ValueError as err: - logger.error(f"{getattr(err, 'messages', str(err))}") - db.session.rollback() - - return jsonify({ - "message": str(err) - }) , 400 - - except Exception as e: - logger.error(f"An error occurred: {str(e)}", exc_info=True) - db.session.rollback() - return jsonify({ - "message": "Internal Server Error" - }) , 500 \ No newline at end of file diff --git a/app/api/services/notification_callback.py b/app/api/services/notification_callback.py deleted file mode 100644 index 6257b2b..0000000 --- a/app/api/services/notification_callback.py +++ /dev/null @@ -1,63 +0,0 @@ -from flask import request, jsonify -from marshmallow import ValidationError -from app.api.services.base_service import BaseService -from app.api.enums import TransactionType -from app.utils.logger import logger -from app.api.schemas.notification_callback import NotificationCallbackSchema -from app.extensions import db - -class NotificationCallbackService(BaseService): - TRANSACTION_TYPE = TransactionType.NOTIFICATION_CALLBACK - - @staticmethod - def process_request(data): - """ - Process the NotificationCallback request. - - Args: - data (dict): The request data. - - Returns: - dict: A standardized response. - """ - try: - logger.info("Processing NotificationCallback request") - - # Validate input data using the NotificationCallback schema - schema = NotificationCallbackSchema() - validated_data = schema.load(data) # Raises ValidationError if invalid - - # Simulated processing logic - response_data = { - "resultCode": "00", - "resultDescription": "Successful" - } - - - # return ResponseHelper.success( - # data=response_data, - # message="Notification callback processed successfully" - # ) - - return response_data - - except ValidationError as err: - - logger.error(f"Validation Error: {getattr(err, 'messages', str(err))}") - - return jsonify({ - "message": "Validation exception" - }) , 422 - - except ValueError as err: - logger.error(f"{getattr(err, 'messages', str(err))}") - - return jsonify({ - "message": str(err) - }) , 400 - - except Exception as e: - logger.error(f"An error occurred: {str(e)}", exc_info=True) - return jsonify({ - "message": "Internal Server Error" - }) , 500 diff --git a/app/api/services/provide_loan.py b/app/api/services/provide_loan.py deleted file mode 100644 index b496265..0000000 --- a/app/api/services/provide_loan.py +++ /dev/null @@ -1,120 +0,0 @@ -from flask import request, jsonify -from marshmallow import ValidationError -from app.api.integrations.kafka import KafkaIntegration -from app.api.services.base_service import BaseService -from app.api.enums import TransactionType -from app.utils.logger import logger -from app.api.schemas.provide_loan import ProvideLoanSchema -from threading import Thread -from app.models.loan import Loan -from app.api.enums import LoanStatus -from app.extensions import db - -class ProvideLoanService(BaseService): - TRANSACTION_TYPE = TransactionType.PROVIDE_LOAN - - - @staticmethod - def process_request(data): - """ - Process the ProvideLoan request. - - Args: - data (dict): The request data. - - Returns: - dict: A standardized response. - """ - try: - with db.session.begin(): - validated_data = ProvideLoanService.validate_data(data, ProvideLoanSchema()) - account_id = validated_data.get('accountId') - customer_id = validated_data.get('customerId') - request_id = validated_data.get('requestId') - transaction_id = validated_data.get('transactionId') - - if (ProvideLoanService.validate_account_ownership(account_id = account_id, customer_id = customer_id)): - - - # Save the loan details - loan = Loan.create_loan( - customer_id=customer_id, - account_id=account_id, - offer_id=validated_data.get('offerId'), - principal_amount=validated_data.get('requestedAmount'), - status=LoanStatus.ACTIVE - ) - - if not loan: - logger.error(f"Failed to save loan details") - return jsonify({ - "message": "Failed to save loan details." - }), 400 - - db.session.flush() - validated_data['refId'] = loan.id - validated_data['refModel'] = "loan" - - # Log Transaction - transaction = ProvideLoanService.log_transaction(validated_data = validated_data) - - if not transaction: - logger.error(f"Failed to log transaction") - return jsonify({ - "message": "Failed to log transaction." - }), 400 - - - - else: - return jsonify({ - "message": "Invalid Customer or Account" - }), 400 - - - response_data = { - "requestId": request_id, - "transactionId": transaction_id, - "customerId": customer_id, - "accountId": account_id, - "msisdn": "3451342", - "resultCode": "00", - "resultDescription": "Successful" - } - - - # KafkaIntegration.send_loan_request(loan_data = response_data, request_id = request_id) - # Call Kafka in a background thread - thread = Thread(target=ProvideLoanService.async_send_to_kafka, args=(response_data, request_id, "PROCESS_PAYMENT")) - thread.start() - - db.session.commit() - return response_data - - except ValidationError as err: - - logger.error(f"Validation Error: {getattr(err, 'messages', str(err))}") - db.session.rollback() - - return jsonify({ - "message": "Validation exception" - }) , 422 - - except ValueError as err: - logger.error(f"{getattr(err, 'messages', str(err))}") - db.session.rollback() - - return jsonify({ - "message": str(err) - }) , 400 - - except Exception as e: - logger.error(f"An error occurred: {str(e)}", exc_info=True) - db.session.rollback() - return jsonify({ - "message": "Internal Server Error" - }) , 500 - - - - diff --git a/app/api/services/repayment.py b/app/api/services/repayment.py deleted file mode 100644 index 33be586..0000000 --- a/app/api/services/repayment.py +++ /dev/null @@ -1,111 +0,0 @@ -from flask import request, jsonify -from marshmallow import ValidationError -from app.api.enums.loan_status import LoanStatus -from app.models import Repayment -from app.models.loan import Loan -from app.utils.logger import logger -from app.api.schemas.repayment import RepaymentSchema -from app.api.services.base_service import BaseService -from app.api.enums import TransactionType -from threading import Thread -from app.extensions import db - -class RepaymentService(BaseService): - TRANSACTION_TYPE = TransactionType.REPAYMENT - - @staticmethod - def process_request(data): - """ - Process the Repayment request. - - Args: - data (dict): The request data. - - Returns: - dict: A standardized response. - """ - try: - with db.session.begin(): - validated_data = RepaymentService.validate_data(data, RepaymentSchema()) - customer_id = validated_data.get('customerId') - request_id = validated_data.get('requestId') - loan_id = validated_data.get('debtId') - product_id = validated_data.get('productId') - - - - # Save the repayment details - repayment = Repayment.create_repayment( - customer_id = customer_id, - loan_id = loan_id, - product_id = product_id - - ) - - if not repayment: - logger.error(f"Failed to save repayment details") - return jsonify({ - "message": "Failed to save repayment details." - }), 400 - - db.session.flush() - - validated_data['refId'] = repayment.id - validated_data['refModel'] = "repayment" - - #Update Loan status - Loan.update_status(loan_id = loan_id, status = LoanStatus.REPAID) - - transaction = RepaymentService.log_transaction(validated_data = validated_data) - - if not transaction: - logger.error(f"Failed to log transaction") - return jsonify({ - "message": "Failed to log transaction." - }), 400 - - - # Simulated processing logic - response_data = { - "customerId": customer_id, - "productId": product_id, - "debtId": loan_id, - "resultCode": "00", - "resultDescription": "Successful" - } - - # return ResponseHelper.success( - # data=response_data, - # message="Repayment processed successfully" - # ) - - # Call Kafka in a background thread - thread = Thread(target=RepaymentService.async_send_to_kafka, args=(response_data, request_id, "LOAN_REPAYMENT")) - thread.start() - - db.session.commit() - return response_data - - except ValidationError as err: - - logger.error(f"Validation Error: {getattr(err, 'messages', str(err))}") - db.session.rollback() - - return jsonify({ - "message": "Validation exception" - }) , 422 - - except ValueError as err: - logger.error(f"{getattr(err, 'messages', str(err))}") - db.session.rollback() - - return jsonify({ - "message": str(err) - }) , 400 - - except Exception as e: - logger.error(f"An error occurred: {str(e)}", exc_info=True) - db.session.rollback() - return jsonify({ - "message": "Internal Server Error" - }) , 500 diff --git a/app/api/services/select_offer.py b/app/api/services/select_offer.py deleted file mode 100644 index 6a0a914..0000000 --- a/app/api/services/select_offer.py +++ /dev/null @@ -1,93 +0,0 @@ -from flask import request, jsonify -from marshmallow import ValidationError -from app.api.services.base_service import BaseService -from app.api.enums import TransactionType -from app.utils.logger import logger -from app.api.schemas.select_offer import SelectOfferSchema -from app.extensions import db - - -class SelectOfferService(BaseService): - TRANSACTION_TYPE = TransactionType.SELECT_OFFER - - @staticmethod - def process_request(data): - """ - Process the SelectOffer request. - - Args: - data (dict): The request data. - - Returns: - dict: A standardized response. - """ - try: - with db.session.begin(): - validated_data = SelectOfferService.validate_data( - data, SelectOfferSchema() - ) - account_id = validated_data.get("accountId") - customer_id = validated_data.get("customerId") - - if SelectOfferService.validate_account_ownership( - account_id=account_id, customer_id=customer_id - ): - transaction = SelectOfferService.log_transaction( - validated_data=validated_data - ) - - if not transaction: - logger.error(f"Failed to log transaction") - return jsonify({"message": "Failed to log transaction."}), 400 - else: - return jsonify({"message": "Invalid Customer or Account"}), 400 - - offers = [ - { - "offerId": "14451", - "productId": "2030", - "amount": 10000.0, - "upfrontPayment": 1000.0, - "interestRate": 3.0, - "managementRate": 1.0, - "managementFee": 1.0, - "insuranceRate": 1.0, - "insuranceFee": 100.0, - "VATRate": 7.5, - "VATAmount": 100.0, - "recommendedRepaymentDates": ["2022-11-30"], - "installmentAmount": 11000.0, - "totalRepaymentAmount": 11000.0, - } - ] - - # Business logic - selecting an offer - response_data = { - "outstandingDebtAmount": 0, - "requestId": "202111170001371256908", - "transactionId": transaction.id, - "customerId": customer_id, - "accountId": account_id, - "loan": offers, - "resultCode": "00", - "resultDescription": "Successful", - } - - db.session.commit() - return response_data - - except ValidationError as err: - - logger.error(f"Validation Error: {getattr(err, 'messages', str(err))}") - db.session.rollback() - return jsonify({"message": "Validation exception"}), 422 - - except ValueError as err: - logger.error(f"{getattr(err, 'messages', str(err))}") - db.session.rollback() - return jsonify({"message": str(err)}), 400 - - except Exception as e: - logger.error(f"An error occurred: {str(e)}", exc_info=True) - db.session.rollback() - return jsonify({"message": "Internal Server Error"}), 500 diff --git a/app/models/offer.py b/app/models/offer.py deleted file mode 100644 index ce62fa2..0000000 --- a/app/models/offer.py +++ /dev/null @@ -1,16 +0,0 @@ -from datetime import datetime, timezone -from app.extensions import db - -class Offer(db.Model): - __tablename__ = 'offers' - - id = db.Column(db.Integer, primary_key=True) - product_id = db.Column(db.String, nullable=False) - min_amount = db.Column(db.Float, nullable=False) - max_amount = db.Column(db.Float, nullable=False) - tenor = db.Column(db.Integer, nullable=False) - created_at = db.Column(db.DateTime, default=datetime.now(timezone.utc)) - updated_at = db.Column(db.DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc)) - - def __repr__(self): - return f'' \ No newline at end of file diff --git a/app/models/repayment.py b/app/models/repayment.py deleted file mode 100644 index c313131..0000000 --- a/app/models/repayment.py +++ /dev/null @@ -1,53 +0,0 @@ -from datetime import datetime, timezone -from app.api.enums.loan_status import LoanStatus -from app.extensions import db -from app.models.customer import Customer -from app.models.loan import Loan -from sqlalchemy.exc import IntegrityError - - -class Repayment(db.Model): - __tablename__ = 'repayments' - - id = db.Column( - db.Integer, - primary_key=True, - autoincrement=True, - ) - loan_id = db.Column(db.String(50), nullable=False) - customer_id = db.Column(db.String(50), nullable=False) - product_id = db.Column(db.String(20), nullable=True) - created_at = db.Column(db.DateTime, default=datetime.now(timezone.utc)) - updated_at = db.Column(db.DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc)) - - @classmethod - def create_repayment(cls, customer_id, loan_id, product_id): - - - # Check customer exists - if not Customer.is_valid_customer(customer_id): - raise ValueError("Invalid customer") - - # Check loan exists - loan = Loan.get_customer_loan(loan_id = loan_id, customer_id = customer_id) - - # Check that the loan is active - if loan.status != LoanStatus.ACTIVE: - raise ValueError(f"Repayment cannot be processed. Loan status: ({loan.status})") - - - repayment = cls( - customer_id=customer_id, - loan_id=loan_id, - product_id=product_id, - ) - - try: - db.session.add(repayment) - except IntegrityError as err: - raise ValueError(f"Database integrity error: {err}") - - return repayment - - def __repr__(self): - return f''