Files
2026-03-16 11:29:25 +01:00

181 lines
7.6 KiB
Python

from datetime import datetime, timezone
from app.extensions import db
from app.models.customer import Customer
from app.models.account import Account
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import relationship
from sqlalchemy import and_, or_, not_
from app.models import Customer
from app.utils.logger import logger
class Loan(db.Model):
__tablename__ = 'loans'
id = db.Column(
db.Integer,
primary_key=True,
autoincrement=True,
)
customer_id = db.Column(db.String(50), nullable=False)
transaction_id = db.Column(db.String(50), nullable=True)
original_transaction = db.Column(db.String(50), nullable=True)
account_id = db.Column(db.String(50), nullable=False)
offer_id = db.Column(db.String(20), nullable=False)
product_id = db.Column(db.String(20), nullable=True)
collection_type = db.Column(db.String(20), nullable=True)
current_loan_amount = db.Column(db.Float, nullable=True)
initial_loan_amount = db.Column(db.Float, nullable=False)
default_penalty_fee = db.Column(db.Float, default=0)
continuous_fee = db.Column(db.Float, default=0)
upfront_fee = db.Column(db.Float, nullable=True, default=0.0)
repayment_amount = db.Column(db.Float, nullable=True, default=0.0)
installment_amount = db.Column(db.Float, nullable=True, default=0.0)
status = db.Column(db.String(20), default='pending')
tenor = db.Column(db.Integer, nullable=True)
due_date = db.Column(db.DateTime, nullable=True)
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))
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)
disburse_result = db.Column(db.String(10), nullable=True)
disburse_description = db.Column(db.String(100), nullable=True)
verify_result = db.Column(db.String(10), nullable=True)
verify_description = db.Column(db.String(100), nullable=True)
reference = db.Column(db.String(50), nullable=True)
balance = db.Column(db.Float, nullable=True, default=0.0)
total_penal_charge = db.Column(db.Float, default=0.0)
last_penal_date = db.Column(db.DateTime, nullable=True)
customer = relationship(
"Customer",
primaryjoin="Customer.id == Loan.customer_id",
foreign_keys=[customer_id],
back_populates="loans",
)
@classmethod
def get_all_loans(cls, id=None, customer_id=None, account_id=None, status=None, tenor=None, offer_id=None,
product_id=None, start_date=None, end_date=None, due_before=None, due_after=None,
transaction_id=None, original_transaction=None, page=1, limit=20, recent_only= False):
"""
Get all loans with optional filtering
Args:
id (int, optional): Filter by loan ID
customer_id (str, optional): Filter by customer ID
account_id (str, optional): Filter by account ID
status (str, optional): Filter by loan status
tenor (str, optional): Filter by loan tenor
offer_id (str, optional): Filter by offer ID
product_id (str, optional): Filter by product ID
start_date (datetime, optional): Filter by start date (created_at)
end_date (datetime, optional): Filter by end date (created_at)
due_before (datetime, optional): Filter loans due before this date
due_after (datetime, optional): Filter loans due after this date
transaction_id (str, optional): Filter by transaction ID
original_transaction (str, optional): Filter by original transaction
Returns:
list: List of Loan objects
"""
query = cls.query
logger.info(f"Get all loan models from loans model cme back")
if recent_only:
query = query.order_by(cls.created_at.desc()).limit(10)
# Get total count before pagination
total_count = query.count()
else:
# Apply filters if provided
if id:
query = query.filter(cls.id == id)
if customer_id:
query = query.filter(cls.customer_id == customer_id)
if account_id:
query = query.filter(cls.account_id == account_id)
if status:
query = query.filter(cls.status == status)
if tenor:
query = query.filter(cls.tenor == tenor)
if offer_id:
query = query.filter(cls.offer_id == offer_id)
if product_id:
query = query.filter(cls.product_id == product_id)
if transaction_id:
query = query.filter(cls.transaction_id == transaction_id)
if original_transaction:
query = query.filter(cls.original_transaction == original_transaction)
if start_date:
query = query.filter(cls.created_at >= start_date)
if end_date:
query = query.filter(cls.created_at <= end_date)
if due_before:
query = query.filter(cls.due_date <= due_before)
if due_after:
query = query.filter(cls.due_date >= due_after)
# Order by created_at descending (newest first)
query = query.order_by(cls.created_at.desc())
# Get total count before pagination
total_count = query.count()
# Apply pagination
offset = (page - 1) * limit
query = query.limit(limit).offset(offset)
return query.all(), total_count
def to_dict(self):
"""
Convert the Loan object to a dictionary format for JSON serialization.
"""
return {
'id': self.id,
'customer_id': self.customer_id,
'account_id': self.account_id,
'transaction_id': self.transaction_id,
'eligible_amount': self.eligible_amount,
'original_transaction': self.original_transaction,
'offer_id': self.offer_id,
'initial_loan_amount': self.initial_loan_amount,
'current_loan_amount': self.current_loan_amount,
'status': self.status,
'tenor': self.tenor,
'product_id': self.product_id,
'default_penalty_fee': self.default_penalty_fee,
'continuous_fee': self.continuous_fee,
'upfront_fee': self.upfront_fee,
'repayment_amount': self.repayment_amount,
'installment_amount': self.installment_amount,
'due_date': self.due_date.isoformat() if self.due_date else None,
'created_at': self.created_at.isoformat() if self.created_at else None,
'updated_at': self.updated_at.isoformat() if self.updated_at else None,
'disburseResult': self.disburse_result,
'disburseDescription': self.disburse_description,
'verifyResult': self.verify_result,
'verifyDescription': self.verify_description,
'disburseDate': self.disburse_date.isoformat() if self.disburse_date else None,
'disburseVerify': self.disburse_verify.isoformat() if self.disburse_verify else None,
'reference': self.reference,
'balance': self.balance,
'totalPenalCharge': self.total_penal_charge,
'lastPenalDate': self.last_penal_date.isoformat() if self.last_penal_date else None,
}
def __repr__(self):
return f'<Loan {self.id}>'