Custom templates fix
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
from .transaction_type import TransactionType
|
||||
from .loan_status import LoanStatus
|
||||
from .settings_items_data import SettingsItemsData
|
||||
from .generatives_list import GenerativesList
|
||||
from .generatives_list import GenerativesList
|
||||
from .kafka_messages import KafkaMessage
|
||||
@@ -0,0 +1,5 @@
|
||||
from enum import Enum
|
||||
|
||||
class KafkaMessage(str, Enum):
|
||||
REFRESH_PRODUCT_SETTINGS = "REFRESH_PRODUCT_SETTINGS"
|
||||
FLUTTER_PAYMENT_RECEIVED = "FLUTTER_PAYMENT_RECEIVED"
|
||||
+110
-144
@@ -306,45 +306,45 @@ class BaseService:
|
||||
logger.info(f"Processing {cls.TRANSACTION_TYPE} request")
|
||||
return schema.load(data)
|
||||
|
||||
@classmethod
|
||||
def get_or_create_customer(cls, validated_data):
|
||||
|
||||
"""
|
||||
Check if a customer exists; if not, create one.
|
||||
"""
|
||||
# @classmethod
|
||||
# def get_or_create_customer(cls, validated_data):
|
||||
#
|
||||
# """
|
||||
# Check if a customer exists; if not, create one.
|
||||
# """
|
||||
#
|
||||
# customer = Customer.query.filter_by(id=validated_data.get("customerId")).first()
|
||||
# if not customer:
|
||||
# customer = Customer.create_customer(
|
||||
# id=validated_data.get("customerId"),
|
||||
# msisdn=validated_data.get("msisdn"),
|
||||
# country_code=validated_data.get("countryCode"),
|
||||
# account_id=validated_data.get("accountId"),
|
||||
# )
|
||||
# return customer
|
||||
|
||||
customer = Customer.query.filter_by(id=validated_data.get("customerId")).first()
|
||||
if not customer:
|
||||
customer = Customer.create_customer(
|
||||
id=validated_data.get("customerId"),
|
||||
msisdn=validated_data.get("msisdn"),
|
||||
country_code=validated_data.get("countryCode"),
|
||||
account_id=validated_data.get("accountId"),
|
||||
)
|
||||
return customer
|
||||
# @classmethod
|
||||
# def validate_account_ownership(cls, account_id, customer_id):
|
||||
# """
|
||||
# Check if the provided account belongs to the customer.
|
||||
# """
|
||||
# is_valid = Account.is_valid_account(account_id, customer_id)
|
||||
# return is_valid
|
||||
|
||||
@classmethod
|
||||
def validate_account_ownership(cls, account_id, customer_id):
|
||||
"""
|
||||
Check if the provided account belongs to the customer.
|
||||
"""
|
||||
is_valid = Account.is_valid_account(account_id, customer_id)
|
||||
return is_valid
|
||||
|
||||
@classmethod
|
||||
def log_transaction(cls, validated_data):
|
||||
"""
|
||||
Create a new transaction.
|
||||
"""
|
||||
channel = "USSD" if validated_data.get("channel") is None else validated_data.get("channel")
|
||||
|
||||
return Transaction.create_transaction(
|
||||
transaction_id = validated_data.get("transactionId"),
|
||||
customer_id = validated_data.get('customerId', None),
|
||||
account_id = validated_data.get("accountId", None),
|
||||
type = cls.TRANSACTION_TYPE,
|
||||
channel = channel,
|
||||
)
|
||||
# @classmethod
|
||||
# def log_transaction(cls, validated_data):
|
||||
# """
|
||||
# Create a new transaction.
|
||||
# """
|
||||
# channel = "USSD" if validated_data.get("channel") is None else validated_data.get("channel")
|
||||
#
|
||||
# return Transaction.create_transaction(
|
||||
# transaction_id = validated_data.get("transactionId"),
|
||||
# customer_id = validated_data.get('customerId', None),
|
||||
# account_id = validated_data.get("accountId", None),
|
||||
# type = cls.TRANSACTION_TYPE,
|
||||
# channel = channel,
|
||||
# )
|
||||
|
||||
@classmethod
|
||||
def async_send_settings_refresh_to_kafka(cls, settings_data, subscription_uid, topic):
|
||||
@@ -357,113 +357,79 @@ class BaseService:
|
||||
KafkaIntegration.send_loan_request(loan_data = loan_data, request_id = request_id, topic = topic)
|
||||
KafkaIntegration.flush()
|
||||
|
||||
|
||||
@classmethod
|
||||
def calculate_charges(cls, offer, amount):
|
||||
"""
|
||||
Calculates and returns the charges for the given offer and amount.
|
||||
|
||||
Args:
|
||||
offer (Offer): The offer object that contains the charges.
|
||||
amount (float): The requested loan amount.
|
||||
|
||||
Returns:
|
||||
dict: A dictionary containing the calculated charges.
|
||||
"""
|
||||
if not offer or not offer.charges:
|
||||
logger.error(f"No charges found for offer ID {offer.id}")
|
||||
return {"error": "No charges found for the offer"}
|
||||
|
||||
loan_charges = offer.charges
|
||||
tenor = offer.schedule # offer.tenor // 30 # Convert to months
|
||||
interest = cls.get_charge_detail(rates = offer.interest_rate, charges = loan_charges, code = "INTEREST", amount = amount)
|
||||
management = cls.get_charge_detail(rates = offer.management_rate, charges = loan_charges, code = "MGTFEE", amount = amount)
|
||||
insurance = cls.get_charge_detail(rates = offer.insurance_rate, charges = loan_charges, code = "INSURANCE", amount = amount)
|
||||
vat = cls.get_charge_detail(rates = offer.vat_rate, charges = loan_charges, code = "VAT", amount = amount, management_fee = management["fee"])
|
||||
|
||||
# Separate fees into upfront and postpaid
|
||||
upfront_fees = [
|
||||
fee["fee"]
|
||||
for fee in [interest, management, insurance, vat]
|
||||
if fee["due_days"] == 0
|
||||
]
|
||||
|
||||
postpaid_fees = [
|
||||
fee["fee"]
|
||||
for fee in [interest, management, insurance, vat]
|
||||
if fee["due_days"] != 0
|
||||
]
|
||||
vat_test = vat["fee"]
|
||||
logger.info(f"VAT fee == *************** : {vat_test}")
|
||||
|
||||
# Up-front payment: (only those fees due immediately i.e due_days == 0)
|
||||
# upfront_payment = sum(upfront_fees)
|
||||
if offer.schedule == 1:
|
||||
upfront_payment = vat["fee"] + management["fee"] + insurance["fee"] + interest["fee"]
|
||||
interest_amount = interest["fee"]
|
||||
repayment_amount = amount
|
||||
else:
|
||||
upfront_payment = vat["fee"] + insurance["fee"]+management["fee"]
|
||||
interest_amount = interest["fee"]*offer.schedule
|
||||
repayment_amount = amount + interest_amount
|
||||
#
|
||||
# @classmethod
|
||||
# def calculate_charges(cls, offer, amount):
|
||||
# """
|
||||
# Calculates and returns the charges for the given offer and amount.
|
||||
#
|
||||
# Args:
|
||||
# offer (Offer): The offer object that contains the charges.
|
||||
# amount (float): The requested loan amount.
|
||||
#
|
||||
# Returns:
|
||||
# dict: A dictionary containing the calculated charges.
|
||||
# """
|
||||
# if not offer or not offer.charges:
|
||||
# logger.error(f"No charges found for offer ID {offer.id}")
|
||||
# return {"error": "No charges found for the offer"}
|
||||
#
|
||||
# loan_charges = offer.charges
|
||||
# tenor = offer.schedule # offer.tenor // 30 # Convert to months
|
||||
# interest = cls.get_charge_detail(rates = offer.interest_rate, charges = loan_charges, code = "INTEREST", amount = amount)
|
||||
# management = cls.get_charge_detail(rates = offer.management_rate, charges = loan_charges, code = "MGTFEE", amount = amount)
|
||||
# insurance = cls.get_charge_detail(rates = offer.insurance_rate, charges = loan_charges, code = "INSURANCE", amount = amount)
|
||||
# vat = cls.get_charge_detail(rates = offer.vat_rate, charges = loan_charges, code = "VAT", amount = amount, management_fee = management["fee"])
|
||||
#
|
||||
# # Separate fees into upfront and postpaid
|
||||
# upfront_fees = [
|
||||
# fee["fee"]
|
||||
# for fee in [interest, management, insurance, vat]
|
||||
# if fee["due_days"] == 0
|
||||
# ]
|
||||
#
|
||||
# postpaid_fees = [
|
||||
# fee["fee"]
|
||||
# for fee in [interest, management, insurance, vat]
|
||||
# if fee["due_days"] != 0
|
||||
# ]
|
||||
# vat_test = vat["fee"]
|
||||
# logger.info(f"VAT fee == *************** : {vat_test}")
|
||||
#
|
||||
# # Up-front payment: (only those fees due immediately i.e due_days == 0)
|
||||
# # upfront_payment = sum(upfront_fees)
|
||||
# if offer.schedule == 1:
|
||||
# upfront_payment = vat["fee"] + management["fee"] + insurance["fee"] + interest["fee"]
|
||||
# interest_amount = interest["fee"]
|
||||
# repayment_amount = amount
|
||||
# else:
|
||||
# upfront_payment = vat["fee"] + insurance["fee"]+management["fee"]
|
||||
# interest_amount = interest["fee"]*offer.schedule
|
||||
# repayment_amount = amount + interest_amount
|
||||
#
|
||||
#
|
||||
# # Repayment amount: (principal + only those fees not due immediately i.e due_days != 0)
|
||||
# # repayment_amount = amount + (sum(postpaid_fees) * tenor)
|
||||
#
|
||||
# # Total amount: (upfront_payment + repayment_amount)
|
||||
# total_amount = upfront_payment + repayment_amount
|
||||
#
|
||||
# # Calculate the installment amount
|
||||
# installment_amount = repayment_amount / offer.schedule
|
||||
#
|
||||
# return {
|
||||
# "interest": interest,
|
||||
# "interest_amount": interest_amount,
|
||||
# "management": management,
|
||||
# "insurance": insurance,
|
||||
# "vat": vat,
|
||||
# "upfront_payment": round(upfront_payment, 2),
|
||||
# "repayment_amount": round(repayment_amount, 2),
|
||||
# "installment_amount": round(installment_amount, 2),
|
||||
# "total_amount": round(total_amount, 2)
|
||||
# }
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
# Repayment amount: (principal + only those fees not due immediately i.e due_days != 0)
|
||||
# repayment_amount = amount + (sum(postpaid_fees) * tenor)
|
||||
|
||||
# Total amount: (upfront_payment + repayment_amount)
|
||||
total_amount = upfront_payment + repayment_amount
|
||||
|
||||
# Calculate the installment amount
|
||||
installment_amount = repayment_amount / offer.schedule
|
||||
|
||||
return {
|
||||
"interest": interest,
|
||||
"interest_amount": interest_amount,
|
||||
"management": management,
|
||||
"insurance": insurance,
|
||||
"vat": vat,
|
||||
"upfront_payment": round(upfront_payment, 2),
|
||||
"repayment_amount": round(repayment_amount, 2),
|
||||
"installment_amount": round(installment_amount, 2),
|
||||
"total_amount": round(total_amount, 2)
|
||||
}
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_charge_detail(cls, rates, charges, code, amount, management_fee= 0.0):
|
||||
"""
|
||||
Get details for a specific charge code from a list of loan charges.
|
||||
|
||||
Returns default values if not found.
|
||||
"""
|
||||
fee = 0.0
|
||||
|
||||
if code == "VAT" and management_fee > 0:
|
||||
fee = management_fee * rates / 100
|
||||
else:
|
||||
fee = amount * rates / 100
|
||||
|
||||
return {
|
||||
"rate": rates,
|
||||
"fee": round(fee, 2),
|
||||
"due_days": 30,
|
||||
"code": code,
|
||||
"description" : "have no idea how to get this yet"
|
||||
}
|
||||
|
||||
# if charge.code == code:
|
||||
# if code == "VAT" and management_fee > 0:
|
||||
# fee = management_fee * rates / 100
|
||||
# else:
|
||||
# fee = amount * rates / 100
|
||||
#
|
||||
# return {
|
||||
# "rate": rates,
|
||||
# "fee": round(fee, 2),
|
||||
# "due_days": charge.due
|
||||
# }
|
||||
|
||||
# return {"rate": 0, "fee": 0, "due_days": 0}
|
||||
|
||||
|
||||
|
||||
@@ -1,60 +1,60 @@
|
||||
from flask import request, jsonify
|
||||
from app.api.helpers.response_helper import ResponseHelper
|
||||
# from flask import request, jsonify
|
||||
# from app.api.helpers.response_helper import ResponseHelper
|
||||
# # from app.api.services.base_service import BaseService
|
||||
# from marshmallow import ValidationError
|
||||
# from app.utils.logger import logger
|
||||
# # from app.api.schemas.customer_consent import CustomerConsentSchema
|
||||
# from app.api.services.base_service import BaseService
|
||||
from marshmallow import ValidationError
|
||||
from app.utils.logger import logger
|
||||
# from app.api.schemas.customer_consent import CustomerConsentSchema
|
||||
from app.api.services.base_service import BaseService
|
||||
from app.api.enums import TransactionType
|
||||
from app.extensions import db
|
||||
|
||||
|
||||
class CustomerConsentService(BaseService):
|
||||
TRANSACTION_TYPE = TransactionType.CUSTOMER_CONSENT
|
||||
|
||||
@staticmethod
|
||||
def process_request(data):
|
||||
"""
|
||||
Process the CustomerConsent request.
|
||||
|
||||
Args:
|
||||
data (dict): The request data.
|
||||
|
||||
Returns:
|
||||
dict: A standardized response.
|
||||
"""
|
||||
try:
|
||||
with db.session.begin():
|
||||
validated_data = CustomerConsentService.validate_data(data, CustomerConsentSchema())
|
||||
account_id = validated_data.get('accountId')
|
||||
customer_id = validated_data.get('customerId')
|
||||
|
||||
if(CustomerConsentService.validate_account_ownership(account_id = account_id, customer_id = customer_id)):
|
||||
|
||||
transaction = CustomerConsentService.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")
|
||||
|
||||
|
||||
db.session.commit()
|
||||
return ResponseHelper.success(result_description="Request is received")
|
||||
|
||||
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()
|
||||
# from app.api.enums import TransactionType
|
||||
# from app.extensions import db
|
||||
#
|
||||
#
|
||||
# class CustomerConsentService(BaseService):
|
||||
# TRANSACTION_TYPE = TransactionType.CUSTOMER_CONSENT
|
||||
#
|
||||
# @staticmethod
|
||||
# def process_request(data):
|
||||
# """
|
||||
# Process the CustomerConsent request.
|
||||
#
|
||||
# Args:
|
||||
# data (dict): The request data.
|
||||
#
|
||||
# Returns:
|
||||
# dict: A standardized response.
|
||||
# """
|
||||
# try:
|
||||
# with db.session.begin():
|
||||
# validated_data = CustomerConsentService.validate_data(data, CustomerConsentSchema())
|
||||
# account_id = validated_data.get('accountId')
|
||||
# customer_id = validated_data.get('customerId')
|
||||
#
|
||||
# if(CustomerConsentService.validate_account_ownership(account_id = account_id, customer_id = customer_id)):
|
||||
#
|
||||
# transaction = CustomerConsentService.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")
|
||||
#
|
||||
#
|
||||
# db.session.commit()
|
||||
# return ResponseHelper.success(result_description="Request is received")
|
||||
#
|
||||
# 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()
|
||||
@@ -2,7 +2,7 @@ from urllib import request
|
||||
|
||||
from flask import session, jsonify
|
||||
|
||||
from app.api.enums import SettingsItemsData
|
||||
from app.api.enums import SettingsItemsData,KafkaMessage
|
||||
from app.api.schemas.myproduct_set_template import MyProductSetTemplateSchema
|
||||
from app.utils.logger import logger
|
||||
from app.api.services.base_service import BaseService
|
||||
@@ -279,15 +279,7 @@ class MyProductsService(BaseService):
|
||||
# logger.info(f"Incoming MyProduct data ==>>>> {memberSubscription}")
|
||||
productDataStatus = memberSubscription.status
|
||||
product_subscription_uid = memberSubscription.uid
|
||||
# product_subscription_external_url = memberSubscription.external_url
|
||||
# product_subscription_internal_url = memberSubscription.internal_url
|
||||
|
||||
# result_data = {
|
||||
# "myproudct": {
|
||||
# "result": "Reveived under development ",
|
||||
# "message": "to be fixed"
|
||||
# }
|
||||
# }
|
||||
|
||||
for key in settings.keys():
|
||||
setting_value = settings[key]
|
||||
@@ -303,7 +295,7 @@ class MyProductsService(BaseService):
|
||||
}
|
||||
logger.error(f"Going for Thread ******************** ")
|
||||
thread = Thread(target=MyProductsService.async_send_settings_refresh_to_kafka,
|
||||
args=(response_data, subscription_uid, "REFRESH_PRODUCT_SETTINGS"))
|
||||
args=(response_data, subscription_uid, KafkaMessage.REFRESH_PRODUCT_SETTINGS))
|
||||
thread.start()
|
||||
logger.error(f"After the Thread ******************** ")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user