from datetime import datetime, timezone from app.extensions import db from sqlalchemy.orm import relationship class Offer(db.Model): __tablename__ = 'offers' id = db.Column(db.String, primary_key=True) product_id = db.Column(db.String, nullable=False) min_amount = db.Column(db.Float, nullable=False) max_amount = db.Column(db.Float, nullable=False) tenor = db.Column(db.Integer, nullable=False) schedule = db.Column(db.Integer, nullable=True) interest_rate = db.Column(db.Float, default=3.0) management_rate = db.Column(db.Float, default=1.0) insurance_rate = db.Column(db.Float, default=1.0) vat_rate = db.Column(db.Float, default=7.5) list_order = db.Column(db.Integer, 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)) charges = relationship( "Charge", back_populates="offer", cascade="all, delete-orphan" ) @classmethod def get_all_offers(cls, id=None, product_id=None, start_date=None, end_date=None, page=1, limit=20): """ Get all offers with optional filtering Args: 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) page (int, optional): Page number for pagination limit (int, optional): Number of items per page Returns: tuple: (list of Offer objects, total count) """ query = cls.query # Apply filters if provided if id: query = query.filter(cls.id == id) if product_id: query = query.filter(cls.product_id == product_id) if start_date: query = query.filter(cls.created_at >= start_date) if end_date: query = query.filter(cls.created_at <= end_date) # Order by list_order ascending (if available) or created_at descending query = query.order_by(cls.list_order.asc(), 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 @classmethod def is_valid_offer(cls, offer_id): offer = cls.query.filter_by(id=str(offer_id)).first() if not offer: return False return offer def to_dict(self): """ Convert the Offer object to a dictionary format for JSON serialization. """ return { 'id': self.id, 'product_id': self.product_id, 'min_amount': self.min_amount, 'max_amount': self.max_amount, 'tenor': self.tenor, 'schedule': self.schedule, 'interest_rate': self.interest_rate, 'management_rate': self.management_rate, 'insurance_rate': self.insurance_rate, 'vat_rate': self.vat_rate, 'list_order': self.list_order, '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''