from datetime import datetime, timezone from app.extensions import db from sqlalchemy.exc import IntegrityError class LoanCharge(db.Model): __tablename__ = 'loan_charges' id = db.Column(db.Integer, primary_key=True, autoincrement=True) loan_id = db.Column(db.Integer, nullable=False) code = db.Column(db.String(50), nullable=False) amount = db.Column(db.Float, default=0.00) percent = db.Column(db.Float) description = db.Column(db.String(255)) due = db.Column(db.Integer) 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)) transaction_id = db.Column(db.String(50)) due_date = db.Column(db.DateTime) @classmethod def get_all_loan_charges(cls, loan_id=None, transaction_id=None, code=None, start_date=None, end_date=None, due_before=None, due_after=None, page=1, limit=20): """ Get all loan charges with optional filtering Args: loan_id (int, optional): Filter by loan ID transaction_id (int, optional): Filter by transaction ID code (str, optional): Filter by charge code 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 charges due before this date due_after (datetime, optional): Filter charges due after this date page (int, optional): Page number for pagination limit (int, optional): Number of items per page Returns: tuple: (list of LoanCharge objects, total count) """ query = cls.query # Apply filters if provided if loan_id: query = query.filter(cls.loan_id == loan_id) if transaction_id: query = query.filter(cls.transaction_id == transaction_id) if code: query = query.filter(cls.code == code) 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 LoanCharge object to a dictionary format for JSON serialization. """ return { 'loan_id': self.loan_id, 'code': self.code, 'amount': self.amount, 'percent': self.percent, 'description': self.description, 'due': self.due, 'transaction_id': self.transaction_id, '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 } def __repr__(self): return f''