Merge branch 'master' of https://gitlab.chiefsoft.net/DigiFi/digifi-BankToProductCore
This commit is contained in:
@@ -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 = {
|
headers = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ from app.api.enums import TransactionType
|
|||||||
from app.api.integrations import SimbrellaIntegration
|
from app.api.integrations import SimbrellaIntegration
|
||||||
from app.extensions import db
|
from app.extensions import db
|
||||||
from app.models import Offer, RACCheck
|
from app.models import Offer, RACCheck
|
||||||
|
from app.api.services.offer_analysis import OfferAnalysis
|
||||||
|
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
|
||||||
@@ -78,39 +80,53 @@ class EligibilityCheckService(BaseService):
|
|||||||
return jsonify({
|
return jsonify({
|
||||||
"message": "Failed to save RACCheck."
|
"message": "Failed to save RACCheck."
|
||||||
}), 400
|
}), 400
|
||||||
|
# -----------------TIME FOR ANALYSIS TO REGISTER OFFER ----------------------
|
||||||
offers = Offer.get_all_offers()
|
# eligible_offers = []
|
||||||
|
try:
|
||||||
eligible_offers = []
|
eligible_offers = OfferAnalysis.decide_offer(
|
||||||
|
transaction_id=transactionId,
|
||||||
for offer in offers:
|
rac_check=rac_check,
|
||||||
# Determine an approved amount
|
validated_data=validated_data,
|
||||||
random_float = random.random() # temporary to play data
|
customer_id=customer_id
|
||||||
approved_amount = min(offer.max_amount, offer.max_amount * random_float) #temporary for now
|
|
||||||
approved_amount = round(approved_amount, 2)
|
|
||||||
|
|
||||||
transaction_offer = TransactionOffer.create_transaction_offer(
|
|
||||||
customer_id = customer.id,
|
|
||||||
transaction_id = transaction.transaction_id,
|
|
||||||
offer_id = offer.id,
|
|
||||||
min_amount = offer.min_amount,
|
|
||||||
max_amount = offer.max_amount,
|
|
||||||
eligible_amount = approved_amount,
|
|
||||||
product_id = offer.product_id,
|
|
||||||
tenor = offer.tenor
|
|
||||||
)
|
)
|
||||||
|
except ValueError as ve:
|
||||||
|
logger.error(str(ve))
|
||||||
|
return jsonify({
|
||||||
|
"message": str(ve)
|
||||||
|
}), 400
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
|
# s = Offer.get_all_offers()
|
||||||
|
|
||||||
# Visible offer ID: offer_id + padded(transaction_offer.id)
|
# eligible_offers = []
|
||||||
padded_id = str(transaction_offer.id).zfill(6)
|
|
||||||
public_offer_id = f"{offer.id}{padded_id}"
|
|
||||||
|
|
||||||
eligible_offers.append({
|
# for offer in offers:
|
||||||
"offerId": public_offer_id,
|
# # Determine an approved amount
|
||||||
"product_id": offer.product_id,
|
# random_float = random.random() # temporary to play data
|
||||||
"min_amount": offer.min_amount,
|
# approved_amount = min(offer.max_amount, offer.max_amount * random_float) #temporary for now
|
||||||
"max_amount": approved_amount,
|
# approved_amount = round(approved_amount, 2)
|
||||||
"tenor": offer.tenor
|
#
|
||||||
})
|
# transaction_offer = TransactionOffer.create_transaction_offer(
|
||||||
|
# customer_id = customer.id,
|
||||||
|
# transaction_id = transaction.transaction_id,
|
||||||
|
# offer_id = offer.id,
|
||||||
|
# min_amount = offer.min_amount,
|
||||||
|
# max_amount = offer.max_amount,
|
||||||
|
# eligible_amount = approved_amount,
|
||||||
|
# product_id = offer.product_id,
|
||||||
|
# tenor = offer.tenor
|
||||||
|
# )
|
||||||
|
#
|
||||||
|
# # Visible offer ID: offer_id + padded(transaction_offer.id)
|
||||||
|
# padded_id = str(transaction_offer.id).zfill(6)
|
||||||
|
# public_offer_id = f"{offer.id}{padded_id}"
|
||||||
|
#
|
||||||
|
# eligible_offers.append({
|
||||||
|
# "offerId": public_offer_id,
|
||||||
|
# "product_id": offer.product_id,
|
||||||
|
# "min_amount": offer.min_amount,
|
||||||
|
# "max_amount": approved_amount,
|
||||||
|
# "tenor": offer.tenor
|
||||||
|
# })
|
||||||
|
|
||||||
# Simulate processing
|
# Simulate processing
|
||||||
response_data = {
|
response_data = {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from app.models import Offer, TransactionOffer
|
from app.models import Offer, TransactionOffer
|
||||||
from app.models.loan import Loan
|
from app.models.loan import Loan
|
||||||
|
import random
|
||||||
import logging
|
import logging
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -30,8 +30,97 @@ class OfferAnalysis:
|
|||||||
if not offer:
|
if not offer:
|
||||||
raise ValueError("Invalid Offer.")
|
raise ValueError("Invalid Offer.")
|
||||||
original_transaction = transaction_id
|
original_transaction = transaction_id
|
||||||
# we can now find the origin transactions
|
|
||||||
customer_loan = Loan.get_customer_current_active_loan(customer_id)
|
|
||||||
|
|
||||||
|
|
||||||
return transaction_offer, offer, eligible_amount, original_transaction
|
return transaction_offer, offer, eligible_amount, original_transaction
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
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)
|
||||||
|
# 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
|
||||||
|
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}")
|
||||||
|
|
||||||
|
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)
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
|
||||||
|
offers = Offer.get_all_offers()
|
||||||
|
|
||||||
|
|
||||||
|
for offer in offers:
|
||||||
|
# Get approved amount
|
||||||
|
random_float = random.random() # temporary to play data
|
||||||
|
|
||||||
|
approved_amount = new_eligible_amount if new_eligible_amount > 0 else min(offer.max_amount, offer.max_amount * random_float)
|
||||||
|
approved_amount = round(approved_amount, 2)
|
||||||
|
|
||||||
|
transaction_offer = TransactionOffer.create_transaction_offer(
|
||||||
|
customer_id=customer_id,
|
||||||
|
transaction_id=transaction_id,
|
||||||
|
original_transaction=transaction_id,
|
||||||
|
offer_id=offer.id,
|
||||||
|
min_amount=offer.min_amount,
|
||||||
|
max_amount=offer.max_amount,
|
||||||
|
eligible_amount=approved_amount,
|
||||||
|
product_id=offer.product_id,
|
||||||
|
tenor=offer.tenor
|
||||||
|
)
|
||||||
|
|
||||||
|
# Visible offer ID: offer_id + padded(transaction_offer.id)
|
||||||
|
padded_id = str(transaction_offer.id).zfill(6)
|
||||||
|
public_offer_id = f"{offer.id}{padded_id}"
|
||||||
|
|
||||||
|
eligible_offers.append({
|
||||||
|
"offerId": public_offer_id,
|
||||||
|
"product_id": offer.product_id,
|
||||||
|
"min_amount": offer.min_amount,
|
||||||
|
"max_amount": approved_amount,
|
||||||
|
"tenor": offer.tenor
|
||||||
|
})
|
||||||
|
|
||||||
|
return eligible_offers
|
||||||
@@ -42,6 +42,7 @@ class ProvideLoanService(BaseService):
|
|||||||
offer_id = validated_data.get('offerId')
|
offer_id = validated_data.get('offerId')
|
||||||
amount = validated_data.get("requestedAmount")
|
amount = validated_data.get("requestedAmount")
|
||||||
product_id = validated_data.get("productId")
|
product_id = validated_data.get("productId")
|
||||||
|
channel = validated_data.get('channel')
|
||||||
|
|
||||||
customer = Customer.is_valid_customer(customer_id)
|
customer = Customer.is_valid_customer(customer_id)
|
||||||
|
|
||||||
@@ -108,7 +109,6 @@ class ProvideLoanService(BaseService):
|
|||||||
vat = charges["vat"]
|
vat = charges["vat"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Save the loan details
|
# Save the loan details
|
||||||
loan = Loan.create_loan(
|
loan = Loan.create_loan(
|
||||||
customer_id = customer_id,
|
customer_id = customer_id,
|
||||||
@@ -117,7 +117,7 @@ class ProvideLoanService(BaseService):
|
|||||||
product_id = offer.product_id,
|
product_id = offer.product_id,
|
||||||
collection_type = collection_type,
|
collection_type = collection_type,
|
||||||
transaction_id = validated_data.get('transactionId'),
|
transaction_id = validated_data.get('transactionId'),
|
||||||
original_transaction = validated_data.get('transactionId'),
|
original_transaction = transaction_offer.original_transaction,
|
||||||
initial_loan_amount = validated_data.get('requestedAmount'),
|
initial_loan_amount = validated_data.get('requestedAmount'),
|
||||||
upfront_fee = upfront_fee,
|
upfront_fee = upfront_fee,
|
||||||
repayment_amount = repayment_amount,
|
repayment_amount = repayment_amount,
|
||||||
@@ -125,7 +125,6 @@ class ProvideLoanService(BaseService):
|
|||||||
eligible_amount=eligible_amount,
|
eligible_amount=eligible_amount,
|
||||||
status = LoanStatus.ACTIVE,
|
status = LoanStatus.ACTIVE,
|
||||||
tenor = offer.tenor,
|
tenor = offer.tenor,
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if not loan:
|
if not loan:
|
||||||
@@ -135,7 +134,7 @@ class ProvideLoanService(BaseService):
|
|||||||
}), 400
|
}), 400
|
||||||
|
|
||||||
db.session.flush()
|
db.session.flush()
|
||||||
|
current_product_id = offer.product_id
|
||||||
schedule = LoanRepaymentSchedule.add_repayment_schedule(loan = loan, num_schedules = num_schedules, transaction_id = transaction_id)
|
schedule = LoanRepaymentSchedule.add_repayment_schedule(loan = loan, num_schedules = num_schedules, transaction_id = transaction_id)
|
||||||
|
|
||||||
|
|
||||||
@@ -147,7 +146,7 @@ class ProvideLoanService(BaseService):
|
|||||||
|
|
||||||
# charges = Charge.get_offer_charges(offer.id)
|
# charges = Charge.get_offer_charges(offer.id)
|
||||||
|
|
||||||
logger.info(f"{charges}")
|
# logger.info(f"{charges}")
|
||||||
|
|
||||||
loan_id = loan.id
|
loan_id = loan.id
|
||||||
|
|
||||||
@@ -160,6 +159,8 @@ class ProvideLoanService(BaseService):
|
|||||||
"message": "Invalid Customer or Account"
|
"message": "Invalid Customer or Account"
|
||||||
}), 400
|
}), 400
|
||||||
|
|
||||||
|
padded_loan_id = str(loan_id).zfill(9)
|
||||||
|
loanRef = f"LID{padded_loan_id}{channel}{current_product_id}"
|
||||||
|
|
||||||
response_data = {
|
response_data = {
|
||||||
"requestId": request_id,
|
"requestId": request_id,
|
||||||
@@ -167,6 +168,7 @@ class ProvideLoanService(BaseService):
|
|||||||
"customerId": customer_id,
|
"customerId": customer_id,
|
||||||
"accountId": account_id,
|
"accountId": account_id,
|
||||||
"msisdn": customer.msisdn,
|
"msisdn": customer.msisdn,
|
||||||
|
"loanRef": loanRef,
|
||||||
"resultCode": "00",
|
"resultCode": "00",
|
||||||
"resultDescription": "Successful"
|
"resultDescription": "Successful"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ class SelectOfferService(BaseService):
|
|||||||
"amount": amount,
|
"amount": amount,
|
||||||
"upfrontPayment": upfront_payment,
|
"upfrontPayment": upfront_payment,
|
||||||
"interestRate": offer.interest_rate,
|
"interestRate": offer.interest_rate,
|
||||||
"interestAmount": interest_amount,
|
"interestFee": interest_amount,
|
||||||
"managementRate": offer.management_rate,
|
"managementRate": offer.management_rate,
|
||||||
"managementFee": management["fee"],
|
"managementFee": management["fee"],
|
||||||
"insuranceRate": offer.insurance_rate,
|
"insuranceRate": offer.insurance_rate,
|
||||||
|
|||||||
+47
-12
@@ -6,6 +6,10 @@ from sqlalchemy.exc import IntegrityError
|
|||||||
from sqlalchemy.orm import relationship
|
from sqlalchemy.orm import relationship
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
import logging
|
||||||
|
from sqlalchemy import and_, or_, not_
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Loan(db.Model):
|
class Loan(db.Model):
|
||||||
@@ -36,6 +40,8 @@ class Loan(db.Model):
|
|||||||
created_at = db.Column(db.DateTime, default=datetime.now(timezone.utc))
|
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))
|
updated_at = db.Column(db.DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc))
|
||||||
eligible_amount = db.Column(db.Float, nullable=True, default=0.0)
|
eligible_amount = db.Column(db.Float, nullable=True, default=0.0)
|
||||||
|
disburse_date = db.Column(db.DateTime, nullable=True)
|
||||||
|
disburse_verify = db.Column(db.DateTime, nullable=True)
|
||||||
|
|
||||||
customer = relationship(
|
customer = relationship(
|
||||||
"Customer",
|
"Customer",
|
||||||
@@ -134,24 +140,53 @@ class Loan(db.Model):
|
|||||||
return loan
|
return loan
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_customer_current_active_loan(cls, customer_id):
|
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.
|
Get customer's active loans.
|
||||||
"""
|
"""
|
||||||
loan = cls.query.filter_by( customer_id = customer_id).first()
|
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:
|
if not loan:
|
||||||
loan = {
|
return None
|
||||||
"eligible_amount": 0,
|
# loan = {
|
||||||
"loan_amount": 0,
|
# "original_transaction":"",
|
||||||
"customer_id": customer_id,
|
# "eligible_amount": 0,
|
||||||
"transaction_id": "",
|
# "loan_amount": 0,
|
||||||
"resultDescription": "No Active Loan"
|
# "customer_id": customer_id,
|
||||||
}
|
# "transaction_id": "",
|
||||||
|
# "resultDescription": "No Active Loan"
|
||||||
logger.info(f" Active Loan ==>>>> {loan}")
|
# }
|
||||||
|
logger.info(f" get_customer_last_loan ==>>>> {loan}")
|
||||||
return loan
|
return loan
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_active_loans_by_original_transaction(cls, original_transaction_id):
|
||||||
|
"""
|
||||||
|
Get all active loans with the same original_transaction ID.
|
||||||
|
"""
|
||||||
|
|
||||||
|
active_loans = cls.query.filter_by(
|
||||||
|
original_transaction=original_transaction_id,
|
||||||
|
# status='active'
|
||||||
|
).all()
|
||||||
|
|
||||||
|
return active_loans
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def update_status(cls, loan_id, status):
|
def update_status(cls, loan_id, status):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ class TransactionOffer(db.Model):
|
|||||||
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
||||||
customer_id = db.Column(db.String(50), nullable=False)
|
customer_id = db.Column(db.String(50), nullable=False)
|
||||||
transaction_id = db.Column(db.String(50), nullable=False)
|
transaction_id = db.Column(db.String(50), nullable=False)
|
||||||
|
original_transaction = db.Column(db.String(50), nullable=True)
|
||||||
offer_id = db.Column(db.String(20), nullable=False)
|
offer_id = db.Column(db.String(20), nullable=False)
|
||||||
product_id = db.Column(db.String(20), nullable=True)
|
product_id = db.Column(db.String(20), nullable=True)
|
||||||
min_amount = db.Column(db.Float, nullable=False)
|
min_amount = db.Column(db.Float, nullable=False)
|
||||||
@@ -41,13 +42,14 @@ class TransactionOffer(db.Model):
|
|||||||
return transaction_offer
|
return transaction_offer
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_transaction_offer(cls, customer_id, transaction_id, offer_id, min_amount, max_amount, eligible_amount=None, product_id=None, tenor=None):
|
def create_transaction_offer(cls, customer_id, transaction_id, original_transaction, offer_id, min_amount, max_amount, eligible_amount=None, product_id=None, tenor=None):
|
||||||
"""
|
"""
|
||||||
Class method to create and save a TransactionOffer.
|
Class method to create and save a TransactionOffer.
|
||||||
"""
|
"""
|
||||||
transaction_offer = cls(
|
transaction_offer = cls(
|
||||||
customer_id=customer_id,
|
customer_id=customer_id,
|
||||||
transaction_id=transaction_id,
|
transaction_id=transaction_id,
|
||||||
|
original_transaction=original_transaction,
|
||||||
offer_id=offer_id,
|
offer_id=offer_id,
|
||||||
min_amount=min_amount,
|
min_amount=min_amount,
|
||||||
max_amount=max_amount,
|
max_amount=max_amount,
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"example": "Tr201712RK9232P115"
|
"example": "Tr201712RK9232P115"
|
||||||
},
|
},
|
||||||
|
"loanRef": {
|
||||||
|
"type": "string",
|
||||||
|
"example": "1620029887USSDAMPC"
|
||||||
|
},
|
||||||
"customerId": {
|
"customerId": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"example": "CN621868"
|
"example": "CN621868"
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
},
|
},
|
||||||
"productId": {
|
"productId": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"example": "2090"
|
"example": "3MPC"
|
||||||
},
|
},
|
||||||
"offerId": {
|
"offerId": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
},
|
},
|
||||||
"productId": {
|
"productId": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"example": "2030"
|
"example": "3MPC"
|
||||||
},
|
},
|
||||||
"amount": {
|
"amount": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
"format": "float",
|
"format": "float",
|
||||||
"example": 3.0
|
"example": 3.0
|
||||||
},
|
},
|
||||||
"interestAmount": {
|
"interestFee": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"format": "float",
|
"format": "float",
|
||||||
"example": 3000.00
|
"example": 3000.00
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
"""Migration on Sat May 10 09:54:34 UTC 2025
|
||||||
|
|
||||||
|
Revision ID: 173ea45db189
|
||||||
|
Revises: 3105abd795d4
|
||||||
|
Create Date: 2025-05-10 09:54:39.380499
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '173ea45db189'
|
||||||
|
down_revision = '3105abd795d4'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('transaction_offers', schema=None) as batch_op:
|
||||||
|
batch_op.add_column(sa.Column('original_transaction', sa.String(length=50), nullable=True))
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('transaction_offers', schema=None) as batch_op:
|
||||||
|
batch_op.drop_column('original_transaction')
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
"""Migration on Sat May 10 12:54:52 UTC 2025
|
||||||
|
|
||||||
|
Revision ID: 565bc3d0ba6e
|
||||||
|
Revises: 173ea45db189
|
||||||
|
Create Date: 2025-05-10 12:54:56.683215
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '565bc3d0ba6e'
|
||||||
|
down_revision = '173ea45db189'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('loans', schema=None) as batch_op:
|
||||||
|
batch_op.add_column(sa.Column('disburse_date', sa.DateTime(), nullable=True))
|
||||||
|
batch_op.add_column(sa.Column('disburse_verify', sa.DateTime(), nullable=True))
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('loans', schema=None) as batch_op:
|
||||||
|
batch_op.drop_column('disburse_verify')
|
||||||
|
batch_op.drop_column('disburse_date')
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
Reference in New Issue
Block a user