From 31b0367e6a95b9b4fb6b4eecef140a3435cffe19 Mon Sep 17 00:00:00 2001 From: VivianDee <115420678+VivianDee@users.noreply.github.com> Date: Mon, 19 May 2025 14:37:19 +0100 Subject: [PATCH] [update]: Offers --- app/api/services/eligibility_check.py | 40 ++++++++++++++++++++++-- app/models/account.py | 4 ++- app/models/charge.py | 4 ++- app/models/customer.py | 8 ++++- app/models/loan.py | 4 ++- app/models/loan_charge.py | 4 ++- app/models/loan_repayment_schedule.py | 4 ++- app/models/offer.py | 6 +++- app/models/rac_checks.py | 4 ++- app/models/repayment.py | 4 ++- app/models/transaction.py | 4 ++- app/models/transaction_offers.py | 44 +++++++++++++++++++++++++-- 12 files changed, 116 insertions(+), 14 deletions(-) diff --git a/app/api/services/eligibility_check.py b/app/api/services/eligibility_check.py index c318d8c..ba9e2b7 100644 --- a/app/api/services/eligibility_check.py +++ b/app/api/services/eligibility_check.py @@ -1,4 +1,5 @@ from flask import session, jsonify +from app.models.loan import Loan from app.models.transaction_offers import TransactionOffer from app.utils.logger import logger from app.api.services.base_service import BaseService @@ -50,6 +51,12 @@ class EligibilityCheckService(BaseService): return ResponseHelper.error(result_description="Invalid Customer or Account") db.session.flush() + + # Determine Loan count + is_eligible = EligibilityCheckService.check_loan_limits(customer_id) + + if not is_eligible: + return ResponseHelper.error(result_description="Max loan count reached") # Call RACCheck response = SimbrellaIntegration.rac_check( @@ -58,7 +65,7 @@ class EligibilityCheckService(BaseService): transaction_id = transaction.transaction_id, ) - # this chck for error is not valid + # this chek for error is not valid if response.status_code != 200: return ResponseHelper.error(result_description="RACCheck failed") @@ -146,4 +153,33 @@ class EligibilityCheckService(BaseService): except Exception as e: logger.error(f"An error occurred: {str(e)}", exc_info=True) db.session.rollback() - return ResponseHelper.internal_server_error() \ No newline at end of file + return ResponseHelper.internal_server_error() + + + @staticmethod + def check_loan_limits(customer_id): + """ + Checks if a customer has exceeded the loan limits for given offer. + """ + loan = Loan.get_customer_last_loan(customer_id) + + if not loan: + return True + + offer_id = loan.offer_id[:5] + + offer = Offer.get_offer_by_id(offer_id) + if not offer: + logger.error(f"Offer not found for offer_id: {offer_id} (customer_id: {customer_id})") + return False + + daily_count = TransactionOffer.get_daily_loan_count(customer_id, offer_id) + + + logger.error(f"daily_count: {daily_count}, Max: {offer.max_daily_loans}") + + if offer.max_daily_loans is not None and daily_count >= offer.max_daily_loans: + return False + + + return True diff --git a/app/models/account.py b/app/models/account.py index 9836363..30774e7 100644 --- a/app/models/account.py +++ b/app/models/account.py @@ -27,7 +27,9 @@ class Account(db.Model): account = cls( id=id, customer_id=customer_id, - account_type=account_type + account_type=account_type, + created_at=datetime.now(timezone.utc), + updated_at=datetime.now(timezone.utc) ) try: diff --git a/app/models/charge.py b/app/models/charge.py index 076ab1f..91fa42c 100644 --- a/app/models/charge.py +++ b/app/models/charge.py @@ -57,7 +57,9 @@ class Charge(db.Model): code = code, percent = percent, description = description, - due = due_days + due = due_days, + created_at=datetime.now(timezone.utc), + updated_at=datetime.now(timezone.utc) ) db.session.add(charge_obj) diff --git a/app/models/customer.py b/app/models/customer.py index c795611..0103761 100644 --- a/app/models/customer.py +++ b/app/models/customer.py @@ -47,7 +47,13 @@ class Customer(db.Model): raise ValueError("Customer already exists") # Create the customer - customer = cls(id=id, msisdn=msisdn, country_code=country_code) + customer = cls( + id=id, + msisdn=msisdn, + country_code=country_code, + created_at=datetime.now(timezone.utc), + updated_at=datetime.now(timezone.utc) + ) try: db.session.add(customer) diff --git a/app/models/loan.py b/app/models/loan.py index 235e45c..fd0328e 100644 --- a/app/models/loan.py +++ b/app/models/loan.py @@ -109,7 +109,9 @@ class Loan(db.Model): due_date=due_date, tenor = tenor, status = status, - eligible_amount =eligible_amount + eligible_amount =eligible_amount, + created_at=datetime.now(timezone.utc), + updated_at=datetime.now(timezone.utc) ) try: diff --git a/app/models/loan_charge.py b/app/models/loan_charge.py index bdbd359..ce9ca22 100644 --- a/app/models/loan_charge.py +++ b/app/models/loan_charge.py @@ -63,7 +63,9 @@ class LoanCharge(db.Model): percent = percent, description = description, due = due_days, - due_date = now + timedelta(days=due_days) + due_date = now + timedelta(days=due_days), + created_at=datetime.now(timezone.utc), + updated_at=datetime.now(timezone.utc) ) db.session.add(charge_obj) diff --git a/app/models/loan_repayment_schedule.py b/app/models/loan_repayment_schedule.py index 78963c1..948b66a 100644 --- a/app/models/loan_repayment_schedule.py +++ b/app/models/loan_repayment_schedule.py @@ -45,7 +45,9 @@ class LoanRepaymentSchedule(db.Model): total_repayment_amount = round(loan.repayment_amount, 2), installment_amount=round(loan.installment_amount, 2), product_id = loan.product_id, - transaction_id = transaction_id + transaction_id = transaction_id, + created_at=datetime.now(timezone.utc), + updated_at=datetime.now(timezone.utc) ) db.session.add(schedule) diff --git a/app/models/offer.py b/app/models/offer.py index c1e32d2..a3250ae 100644 --- a/app/models/offer.py +++ b/app/models/offer.py @@ -83,7 +83,11 @@ class Offer(db.Model): "interest_rate": self.interest_rate, "management_rate": self.management_rate, "insurance_rate": self.insurance_rate, - "vat_rate": self.vat_rate + "vat_rate": self.vat_rate, + "maxDailyLoans": self.max_daily_loans, + "maxActiveLoans": self.max_active_loans, + "maxLifeLoans": self.max_life_loans + } def __repr__(self): diff --git a/app/models/rac_checks.py b/app/models/rac_checks.py index 1e74602..a4d56b5 100644 --- a/app/models/rac_checks.py +++ b/app/models/rac_checks.py @@ -25,7 +25,9 @@ class RACCheck(db.Model): customer_id = customer_id, account_id = account_id, transaction_id = transaction_id, - rac_response = data + rac_response = data, + created_at=datetime.now(timezone.utc), + updated_at=datetime.now(timezone.utc) ) try: diff --git a/app/models/repayment.py b/app/models/repayment.py index 2baa114..f9ef530 100644 --- a/app/models/repayment.py +++ b/app/models/repayment.py @@ -42,7 +42,9 @@ class Repayment(db.Model): customer_id=customer_id, loan_id=loan_id, product_id=product_id, - transaction_id = transaction_id + transaction_id = transaction_id, + created_at=datetime.now(timezone.utc), + updated_at=datetime.now(timezone.utc) ) try: diff --git a/app/models/transaction.py b/app/models/transaction.py index 581bfaf..f90c0da 100644 --- a/app/models/transaction.py +++ b/app/models/transaction.py @@ -38,7 +38,9 @@ class Transaction(db.Model): customer_id = customer_id, account_id = account_id, type = type, - channel = channel + channel = channel, + created_at=datetime.now(timezone.utc), + updated_at=datetime.now(timezone.utc) ) try: diff --git a/app/models/transaction_offers.py b/app/models/transaction_offers.py index 8b80b6c..d40fa4f 100644 --- a/app/models/transaction_offers.py +++ b/app/models/transaction_offers.py @@ -1,4 +1,5 @@ -from datetime import datetime, timezone +from datetime import datetime, timezone, timedelta +from app.api.enums.loan_status import LoanStatus from app.extensions import db from sqlalchemy.orm import relationship from sqlalchemy.sql import func @@ -58,7 +59,9 @@ class TransactionOffer(db.Model): max_amount=max_amount, eligible_amount=eligible_amount, product_id=product_id, - tenor=tenor + tenor=tenor, + created_at=datetime.now(timezone.utc), + updated_at=datetime.now(timezone.utc) ) db.session.add(transaction_offer) @@ -66,6 +69,43 @@ class TransactionOffer(db.Model): return transaction_offer + @classmethod + def get_lifetime_loan_count(cls, customer_id): + """ + Returns the total number of loans ever created for a customer. + """ + return cls.query.filter_by(customer_id=customer_id).count() + + @classmethod + def get_daily_loan_count(cls, customer_id, offer_id): + """ + Returns the count of loans created today for a customer. + """ + + start_of_day = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0) + end_of_day = start_of_day + timedelta(days=1) + + return cls.query.filter_by( + customer_id=customer_id, + offer_id=offer_id + ).filter( + cls.created_at >= start_of_day, + cls.created_at < end_of_day + ).count() + + + @classmethod + def get_latest_transaction_offer(cls, customer_id): + """ + Returns the most recent transaction offer for the given customer based on creation time. + """ + return cls.query.filter_by(customer_id=customer_id) \ + .order_by(cls.created_at.desc()) \ + .first() + + + + def to_dict(self): return { 'id': self.id, -- 2.34.1