Compare commits

...

12 Commits

Author SHA1 Message Date
VivianDee dee1edee40 Merge branch 'master' of https://gitlab.chiefsoft.net/DigiFi/digifi-BankToProductCore 2025-05-12 16:06:24 +01:00
CHIEFSOFT\ameye 746ca486da Fix data 2025-05-11 23:44:36 -04:00
CHIEFSOFT\ameye 3d81322515 Fix Intetrest Fee 2025-05-11 20:04:49 -04:00
CHIEFSOFT\ameye eeacffad9a Loan Reference added 2025-05-11 16:05:36 -04:00
CHIEFSOFT\ameye 11a239c67a Linked loan design 2025-05-10 20:08:27 -04:00
CHIEFSOFT\ameye 4ce0142ee0 Merge branch 'master' of https://gitlab.chiefsoft.net/DigiFi/digifi-BankToProductCore
# Conflicts:
#	app/models/loan.py
2025-05-10 11:18:37 -04:00
ameye c268c4d92b Merge branch 'define_offers' of DigiFi/digifi-BankToProductCore into master 2025-05-10 14:43:43 +00:00
ameye 89dd4bb191 Merge branch 'define_offers' of DigiFi/digifi-BankToProductCore into master 2025-05-10 14:35:14 +00:00
CHIEFSOFT\ameye b86bd3dece Fix ident 2025-05-10 10:06:14 -04:00
ameye a0a2c01a1c Merge branch 'define_offers' of DigiFi/digifi-BankToProductCore into master 2025-05-10 13:58:44 +00:00
VivianDee 17db2cf8f9 Merge branch 'master' of https://gitlab.chiefsoft.net/DigiFi/digifi-BankToProductCore 2025-05-10 08:53:09 +01:00
VivianDee f07866a884 [add]: transaction fix 2025-05-10 08:50:10 +01:00
10 changed files with 95 additions and 42 deletions
+1 -1
View File
@@ -35,7 +35,7 @@ class SimbrellaIntegration:
],
}
logger.info(f"This is PayLoad: {str(payload)}", exc_info=True)
# logger.info(f"This is PayLoad: {str(payload)}", exc_info=True)
headers = {
"Content-Type": "application/json",
+1 -1
View File
@@ -87,7 +87,7 @@ class EligibilityCheckService(BaseService):
transaction_id=transactionId,
rac_check=rac_check,
validated_data=validated_data,
customer=customer
customer_id=customer_id
)
except ValueError as ve:
logger.error(str(ve))
+43 -14
View File
@@ -34,34 +34,63 @@ class OfferAnalysis:
return transaction_offer, offer, eligible_amount, original_transaction
@staticmethod
def decide_offer(transaction_id, rac_check, validated_data, customer):
def decide_offer(transaction_id, rac_check, validated_data, customer_id):
eligible_offers = []
# if we have active offers - we have to feed off it
logger.info(f"LOOOOOOOOOOOOOOOOOO** {customer_id}")
# we can now find the origin transactions
# Find the last loan - it will have original_transaction
# last_customer_loan = Loan.get_customer_last_loan(customer.id)
last_customer_loan = Loan.get_customer_last_loan(customer_id)
# logger.info(f"{last_customer_loan}")
new_eligible_amount = 0
# if last_customer_loan:
# original_transaction = last_customer_loan.original_transaction or last_customer_loan.transaction_id
if last_customer_loan:
original_transaction = last_customer_loan.original_transaction or last_customer_loan.transaction_id
logger.info(f"transaction_id |-| original_transaction === > {transaction_id} {original_transaction}")
original_loan = Loan.get_customer_original_loan(customer_id, original_transaction)
if original_loan is not None:
logger.info(f"original_loan === > {original_loan}")
logger.info(f"loan_offer_id === > {original_loan.offer_id}")
# real_eligible_amount = last_customer_loan.eligible_amount
original_offer_id = str(original_loan.offer_id[:5]) # The last part is str
transaction_offer_id = int(original_loan.offer_id[5:]) # The last part is int
original_transaction_offer = TransactionOffer.is_valid_transaction_offer(transaction_offer_id, customer_id, original_loan.product_id)
# active_loans = Loan.get_active_loans_by_original_transaction(original_transaction)
active_loans = Loan.get_active_loans_by_original_transaction(original_transaction)
sum_active_loans = sum(loan.current_loan_amount for loan in active_loans)
logger.info(f"sum_active_loans === > {sum_active_loans}")
real_eligible_amount = original_loan.eligible_amount - sum_active_loans
# sum_active_loans = sum(loan.current_loan_amount for loan in active_loans)
# new_eligible_amount = max(real_eligible_amount - sum_active_loans, 0)
transaction_offer = TransactionOffer.create_transaction_offer(
customer_id=customer_id,
transaction_id=transaction_id,
original_transaction=original_transaction,
offer_id=original_offer_id,
min_amount=original_transaction_offer.min_amount,
max_amount=original_transaction_offer.max_amount,
eligible_amount=real_eligible_amount,
product_id=original_loan.product_id,
tenor=original_loan.tenor
)
# logger.info(f"Real eligible: {real_eligible_amount}, Sum of active: {sum_active_loans}, New eligible: {new_eligible_amount}")
# Visible offer ID: offer_id + padded(transaction_offer.id)
padded_id = str(transaction_offer.id).zfill(6)
public_offer_id = f"{original_offer_id}{padded_id}"
eligible_offers.append({
"offerId": public_offer_id,
"product_id": original_transaction_offer.product_id,
"min_amount": original_transaction_offer.min_amount,
"max_amount": real_eligible_amount,
"tenor": original_loan.tenor
})
return eligible_offers
# Construct eligible_offers
offers = Offer.get_all_offers()
eligible_offers = []
for offer in offers:
# Get approved amount
@@ -71,7 +100,7 @@ class OfferAnalysis:
approved_amount = round(approved_amount, 2)
transaction_offer = TransactionOffer.create_transaction_offer(
customer_id=customer.id,
customer_id=customer_id,
transaction_id=transaction_id,
original_transaction=transaction_id,
offer_id=offer.id,
+7 -2
View File
@@ -42,6 +42,7 @@ class ProvideLoanService(BaseService):
offer_id = validated_data.get('offerId')
amount = validated_data.get("requestedAmount")
product_id = validated_data.get("productId")
channel = validated_data.get('channel')
customer = Customer.is_valid_customer(customer_id)
@@ -80,6 +81,7 @@ class ProvideLoanService(BaseService):
# "message": "Invalid Offer."
# }), 400
# Log Transaction
transaction = ProvideLoanService.log_transaction(validated_data=validated_data)
@@ -132,7 +134,7 @@ class ProvideLoanService(BaseService):
}), 400
db.session.flush()
current_product_id = offer.product_id
schedule = LoanRepaymentSchedule.add_repayment_schedule(loan = loan, num_schedules = num_schedules, transaction_id = transaction_id)
@@ -156,7 +158,9 @@ class ProvideLoanService(BaseService):
return jsonify({
"message": "Invalid Customer or Account"
}), 400
padded_loan_id = str(loan_id).zfill(9)
loanRef = f"LID{padded_loan_id}{channel}{current_product_id}"
response_data = {
"requestId": request_id,
@@ -164,6 +168,7 @@ class ProvideLoanService(BaseService):
"customerId": customer_id,
"accountId": account_id,
"msisdn": customer.msisdn,
"loanRef": loanRef,
"resultCode": "00",
"resultDescription": "Successful"
}
+1 -1
View File
@@ -91,7 +91,7 @@ class SelectOfferService(BaseService):
"amount": amount,
"upfrontPayment": upfront_payment,
"interestRate": offer.interest_rate,
"interestAmount": interest_amount,
"interestFee": interest_amount,
"managementRate": offer.management_rate,
"managementFee": management["fee"],
"insuranceRate": offer.insurance_rate,
+30 -17
View File
@@ -7,6 +7,8 @@ from sqlalchemy.orm import relationship
from dateutil.relativedelta import relativedelta
from datetime import timedelta
import logging
from sqlalchemy import and_, or_, not_
logger = logging.getLogger(__name__)
@@ -137,27 +139,38 @@ class Loan(db.Model):
raise ValueError(f"Loan with ID {loan_id} does not exist or does not belong to customer {customer_id}.")
return loan
@classmethod
def get_customer_original_loan(cls, customer_id, original_transaction):
"""
Get customer's original loan offer.
"""
original_loan = cls.query.filter(and_( cls.customer_id ==customer_id, cls.original_transaction==original_transaction, cls.transaction_id==original_transaction )).first()
if not original_loan:
return None
logger.info(f" get_customer_original_loan ==>>>> {original_loan}")
return original_loan
@classmethod
def get_customer_last_loan(cls, customer_id):
"""
Get customer's active loans.
"""
logger.info(f"Find last loan for [customer_id] ==>>>> {customer_id}")
loan = cls.query.filter_by( customer_id = customer_id).first()
logger.info(f" Active Loan ==>>>> RESULT************************ AMEYE")
logger.info(f"get_customer_last_loan [customer_id] ==>>>> {customer_id}")
# loan = cls.query.filter_by( cls.customer_id == customer_id).first()
loan = cls.query.filter(and_( cls.customer_id ==customer_id, cls.status=='active')).first()
if not loan:
return None
loan = {
"eligible_amount": 0,
"loan_amount": 0,
"customer_id": customer_id,
"transaction_id": "",
"resultDescription": "No Active Loan"
}
logger.info(f" Active Loan ==>>>> RESULT*********************")
logger.info(f" Active Loan ==>>>> {loan}")
# loan = {
# "original_transaction":"",
# "eligible_amount": 0,
# "loan_amount": 0,
# "customer_id": customer_id,
# "transaction_id": "",
# "resultDescription": "No Active Loan"
# }
logger.info(f" get_customer_last_loan ==>>>> {loan}")
return loan
@classmethod
@@ -165,10 +178,10 @@ class Loan(db.Model):
"""
Get all active loans with the same original_transaction ID.
"""
active_loans = cls.query.filter_by(
original_transaction=original_transaction_id,
# status='active'
original_transaction=original_transaction_id,
# status='active'
).all()
return active_loans
+5 -3
View File
@@ -27,14 +27,16 @@ class TransactionOffer(db.Model):
)
@classmethod
def is_valid_transaction_offer(cls, offer_id, customer_id, product_id):
def is_valid_transaction_offer(cls, transaction_offer, customer_id, product_id):
transaction_offer = cls.query.filter_by(
id = str(offer_id),
id = transaction_offer,
customer_id = customer_id,
# product_id = product_id
product_id = product_id
# transaction_id = transaction_id,
).first()
if not transaction_offer:
return False
return transaction_offer
@@ -9,6 +9,10 @@
"type": "string",
"example": "Tr201712RK9232P115"
},
"loanRef": {
"type": "string",
"example": "1620029887USSDAMPC"
},
"customerId": {
"type": "string",
"example": "CN621868"
+1 -1
View File
@@ -28,7 +28,7 @@
},
"productId": {
"type": "string",
"example": "2090"
"example": "3MPC"
},
"offerId": {
"type": "string",
+2 -2
View File
@@ -28,7 +28,7 @@
},
"productId": {
"type": "string",
"example": "2030"
"example": "3MPC"
},
"amount": {
"type": "number",
@@ -49,7 +49,7 @@
"format": "float",
"example": 3.0
},
"interestAmount": {
"interestFee": {
"type": "number",
"format": "float",
"example": 3000.00