Files
MermsCoreFlask/app/api/services/select_offer.py
T
CHIEFSOFT\ameye 987b7d6383 mercore starter
2025-06-22 20:45:07 -04:00

168 lines
7.2 KiB
Python

from flask import request, jsonify
from marshmallow import ValidationError
from app.api.helpers.response_helper import ResponseHelper
from app.api.services.base_service import BaseService
from app.api.enums import TransactionType
from app.models.transaction_offers import TransactionOffer
from app.utils.logger import logger
from app.api.schemas.select_offer import SelectOfferSchema
from app.extensions import db
from app.models import Offer
from datetime import date
from dateutil.relativedelta import relativedelta
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")
amount = validated_data.get("requestedAmount")
product_id = validated_data.get("productId")
transaction_offer_id = validated_data.get("offerId")
transaction_id = validated_data.get("transactionId")
request_id = validated_data.get("requestId")
offer_id = int(transaction_offer_id[5:]) # The last part is int
#"offerId": "SAL30001129",
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 ResponseHelper.error(result_description="Failed to log transaction.")
else:
return ResponseHelper.error(result_description="Invalid Customer or Account")
# Get the offer by product ID
offer = Offer.get_offer_by_product_id(product_id)
transaction_offer = TransactionOffer.get_transaction_offer(transaction_offer_id=offer_id)
if not transaction_offer:
logger.error(f"offer {offer_id} not found for customer {customer_id} and transaction {transaction_id}.")
return ResponseHelper.error(result_description="Offer not found.")
db.session.flush()
if amount < transaction_offer.min_amount:
logger.error(f"The amount {amount} is less than the minimum allowed offer amount {transaction_offer.min_amount}.")
return ResponseHelper.error(result_description="The amount is less than the minimum allowed offer amount.")
elif amount > transaction_offer.eligible_amount:
logger.error(f"The amount {amount} is greater than the eligible offer amount {transaction_offer.eligible_amount}.")
return ResponseHelper.error(result_description="The amount is greater than the eligible offer amount.")
charges = SelectOfferService.calculate_charges(offer, amount)
upfront_payment = charges["upfront_payment"]
total_amount = charges["total_amount"]
installment_amount = charges["installment_amount"]
interest = charges["interest"]
management = charges["management"]
insurance = charges["insurance"]
vat = charges["vat"]
repayment_amount = charges["repayment_amount"]
interest_amount = charges["interest_amount"]
# Calculate the repayment dates
tenor = offer.tenor
start_date = date.today()
# Convert tenor to months
months = offer.schedule # tenor // 30
recommended_repayment_dates = [
(start_date + relativedelta(months=i + 1)).isoformat()
for i in range(months)
]
offers = [
{
"offerId": transaction_offer_id,
"productId": product_id,
"amount": amount,
"upfrontPayment": upfront_payment,
"interestRate": offer.interest_rate,
"interestFee": interest_amount,
"managementRate": offer.management_rate,
"managementFee": management["fee"],
"insuranceRate": offer.insurance_rate,
"insuranceFee": insurance["fee"],
"VATRate": offer.vat_rate,
"VATAmount": vat["fee"],
"recommendedRepaymentDates": recommended_repayment_dates,
"repaymentAmount": repayment_amount,
"installmentAmount": installment_amount,
"totalRepaymentAmount": total_amount,
}
]
# "offerId": offer.id,
# "productId": product_id,
# "amount": amount,
# "upfrontPayment": upfront_payment,
# "interestRate": interest["rate"],
# "managementRate": management["rate"],
# "managementFee": management["fee"],
# "insuranceRate": insurance["rate"],
# "insuranceFee": insurance["fee"],
# "VATRate": vat["rate"],
# "VATAmount": vat["fee"],
# "recommendedRepaymentDates": recommended_repayment_dates,
# "installmentAmount": installment_amount,
# "totalRepaymentAmount": total_amount,
#
# Business logic - selecting an offer
response_data = {
"outstandingDebtAmount": 0,
"requestId": request_id,
"transactionId": transaction_id,
"customerId": customer_id,
"accountId": account_id,
"loan": offers,
}
db.session.commit()
return ResponseHelper.success(data=response_data)
except ValidationError as err:
logger.error(f"Validation Error: {getattr(err, 'messages', str(err))}")
db.session.rollback()
return ResponseHelper.unprocessable_entity(result_description="Validation exception")
except ValueError as err:
logger.error(f"{getattr(err, 'messages', str(err))}")
db.session.rollback()
return ResponseHelper.error(result_description=str(err))
except Exception as e:
logger.error(f"An error occurred: {str(e)}", exc_info=True)
db.session.rollback()
return ResponseHelper.internal_server_error()