From d2e272e44b4ab6a390269f46ae81acf5c1b3b957 Mon Sep 17 00:00:00 2001 From: "oluyemi.a.simbrellang.com" Date: Thu, 17 Apr 2025 17:16:01 +0100 Subject: [PATCH] eliminated some hardcoded values --- app/integrations/simbrella.py | 34 ++++++++++++++++++++++++----- app/models/__init__.py | 6 ++++- app/models/account.py | 25 +++++++++++++++++++++ app/models/customer.py | 41 +++++++++++++++++++++++++++++++++++ app/models/loan.py | 7 +++++- app/models/loan_charge.py | 8 ++++++- app/services/loan.py | 17 +++++++++++++++ app/utils/extras.py | 16 ++++++++++++++ 8 files changed, 145 insertions(+), 9 deletions(-) create mode 100644 app/models/account.py create mode 100644 app/models/customer.py create mode 100644 app/services/loan.py create mode 100644 app/utils/extras.py diff --git a/app/integrations/simbrella.py b/app/integrations/simbrella.py index b40f21c..3f74720 100644 --- a/app/integrations/simbrella.py +++ b/app/integrations/simbrella.py @@ -1,6 +1,8 @@ import requests from app.config import settings +from app.services.loan import LoanService from app.utils.auth import get_headers +from app.utils.extras import preprocess_loan_charges_data from app.utils.logger import logger from flask import jsonify, current_app from app.services.transactions import TransactionService @@ -26,21 +28,42 @@ class SimbrellaClient: logger.info(f"Transaction id: {data['transactionId']}, was not found") return 0 + # Fetch the loan based on the transaction_id + logger.info(f"Fetching the loan with transaction ID: {data['transactionId']}") + loan = LoanService.get_loan_by_transaction_id(transaction_id=data['transactionId']) + logger.info(f"Response from database: {loan}") + + # If loan is not found + if not loan: + logger.info(f"Could not find loan with transaction id: {data['transactionId']}") + return 0 + + loan_data = loan.to_dict() + logger.info(f"Here is your loan data: {loan_data}") + + loan_charges = preprocess_loan_charges_data([loan_charge.to_dict() for loan_charge in loan.loan_charges]) + logger.info(f"Here are your loan_charges: {loan_charges}") + + mgt_fee = loan_charges.get("MGTFEE")['amount'] + + vat_fee = loan_charges.get("VAT")['amount'] + disbursement_data ={ "requestId": data['requestId'], "transactionId": data['transactionId'], - "debtId": "273194670", + "debtId": loan_data['debtId'], "customerId": data['customerId'], "accountId": data['accountId'], - "productId": "101", - "provideAmount": 100000, + "productId": loan_data['productId'], + "provideAmount": loan_data['currentLoanAmount'], "collectAmountInterest": 5000, - "collectAmountMgtFee": 1000, + "collectAmountMgtFee": mgt_fee, "collectAmountInsurance": 1000, - "collectAmountVAT": 75, + "collectAmountVAT": vat_fee, "countryId": "01", "comment": "Loan Disbursement", } + try: logger.info(f"Here is your Disbursement Request data ****** : {disbursement_data}") response = requests.post(api_url, json=disbursement_data, timeout=10, headers=get_headers()) @@ -51,7 +74,6 @@ class SimbrellaClient: #raise return 0 - # return jsonify(response.json()), response.status_code return 1 @staticmethod diff --git a/app/models/__init__.py b/app/models/__init__.py index 7621c0f..705f676 100644 --- a/app/models/__init__.py +++ b/app/models/__init__.py @@ -1,4 +1,8 @@ from .transactions import Transaction from .repayment import Repayment +from .loan import Loan +from .loan_charge import LoanCharge +from .customer import Customer +from .account import Account -__all__ = ['Transaction', 'Repayment'] \ No newline at end of file +__all__ = ['Transaction', 'Repayment', 'Loan', 'LoanCharge', 'Customer', 'Account'] \ No newline at end of file diff --git a/app/models/account.py b/app/models/account.py new file mode 100644 index 0000000..7394b3a --- /dev/null +++ b/app/models/account.py @@ -0,0 +1,25 @@ +from datetime import datetime, timezone +from sqlalchemy.orm import relationship +from app.extensions import db + + +class Account(db.Model): + __tablename__ = 'accounts' + + id = db.Column(db.String(50), primary_key=True) + customer_id = db.Column(db.String(50), nullable=False) + account_type = db.Column(db.String(50)) + status = db.Column(db.String(20), default='active') + lien_amount = db.Column(db.Float, default=0.0) + 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)) + + customer = relationship( + "Customer", + primaryjoin="Customer.id == Account.customer_id", + foreign_keys=[customer_id], + back_populates="accounts", + ) + + def __repr__(self): + return f'' diff --git a/app/models/customer.py b/app/models/customer.py new file mode 100644 index 0000000..d5f2650 --- /dev/null +++ b/app/models/customer.py @@ -0,0 +1,41 @@ +from datetime import datetime, timezone +from sqlalchemy.orm import relationship +from app.extensions import db + + +class Customer(db.Model): + __tablename__ = 'customers' + + id = db.Column(db.String(50), primary_key=True) + msisdn = db.Column(db.String(20), unique=True, nullable=False) + country_code = db.Column(db.String(3), 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)) + + accounts = relationship( + "Account", + primaryjoin="Customer.id == Account.customer_id", + foreign_keys="Account.customer_id", + back_populates="customer", + ) + + loans = relationship( + "Loan", + primaryjoin="Customer.id == Loan.customer_id", + foreign_keys="Loan.customer_id", + back_populates="customer", + ) + + @classmethod + def get_customer(cls, customer_id): + """ + Get customer by ID. + """ + customer = cls.query.filter_by(id=customer_id).first() + + if not customer: + raise ValueError(f"Customer does not exist") + return customer + + def __repr__(self): + return f'' diff --git a/app/models/loan.py b/app/models/loan.py index 656ac3c..277f383 100644 --- a/app/models/loan.py +++ b/app/models/loan.py @@ -54,6 +54,11 @@ class Loan(db.Model): 'continuousFee': self.continuous_fee, 'collectionType': self.collection_type, 'status': self.status, + 'productId': self.product_id, 'dueDate': self.due_date.isoformat() if self.due_date else None, 'loanDate': self.created_at.isoformat if self.created_at else None - } \ No newline at end of file + } + + @classmethod + def get_loan_by_transaction_id(cls, transaction_id): + return cls.query.filter_by(transaction_id=transaction_id).first() \ No newline at end of file diff --git a/app/models/loan_charge.py b/app/models/loan_charge.py index da12479..0a04789 100644 --- a/app/models/loan_charge.py +++ b/app/models/loan_charge.py @@ -1,4 +1,6 @@ from datetime import datetime, timezone, timedelta +from os.path import devnull + from app.extensions import db from sqlalchemy.orm import relationship @@ -40,4 +42,8 @@ class LoanCharge(db.Model): 'percent': self.percent, 'description': self.description, 'due': self.due - } \ No newline at end of file + } + + @classmethod + def get_loan_charge_by_debt_id(cls, debt_id): + return cls.query.filter_by(loan_id=debt_id) \ No newline at end of file diff --git a/app/services/loan.py b/app/services/loan.py new file mode 100644 index 0000000..b86067b --- /dev/null +++ b/app/services/loan.py @@ -0,0 +1,17 @@ +from app.models import Loan, LoanCharge + +class LoanService: + + @classmethod + def get_loan_by_transaction_id(cls, transaction_id): + """ + Get the loan by transaction ID + """ + return Loan.get_loan_by_transaction_id(transaction_id) + + @classmethod + def get_loan_charge_by_debt_id(cls, debt_id): + """ + Get the loan charge by debt ID + """ + return LoanCharge.get_loan_charge_by_debt_id(debt_id) \ No newline at end of file diff --git a/app/utils/extras.py b/app/utils/extras.py new file mode 100644 index 0000000..effc889 --- /dev/null +++ b/app/utils/extras.py @@ -0,0 +1,16 @@ +def preprocess_loan_charges_data(data): + """ + Preprocesses the data into a dictionary for efficient lookups by 'code'. + + Args: + data: A list of dictionaries. + + Returns: + A dictionary where keys are 'code' values and values are the corresponding dictionaries from the input data. + If multiple items have the same code, the last one encountered will be stored. + """ + preprocessed = {} + for item in data: + if 'code' in item: + preprocessed[item['code']] = item + return preprocessed \ No newline at end of file