79 lines
2.5 KiB
Python
79 lines
2.5 KiB
Python
"""
|
|
Category Model
|
|
|
|
SQLAlchemy model for transaction categories.
|
|
Handles categorization of financial transactions.
|
|
"""
|
|
|
|
from datetime import datetime
|
|
from app.extensions import db
|
|
|
|
|
|
class Category(db.Model):
|
|
"""
|
|
Category model for organizing transactions.
|
|
|
|
Attributes:
|
|
id (int): Primary key
|
|
name (str): Category name (unique)
|
|
description (str): Optional description
|
|
color (str): Hex color code for UI representation
|
|
is_active (bool): Whether category is active
|
|
created_at (datetime): Creation timestamp
|
|
"""
|
|
|
|
__tablename__ = 'categories'
|
|
|
|
# Primary key
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
|
|
# Category information
|
|
name = db.Column(db.String(100), nullable=False, unique=True)
|
|
description = db.Column(db.Text)
|
|
color = db.Column(db.String(7)) # Hex color code (#FFFFFF)
|
|
is_active = db.Column(db.Boolean, default=True, nullable=False)
|
|
|
|
# Timestamps
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
|
|
|
# Relationships
|
|
transactions = db.relationship('Transaction', backref='category', lazy=True)
|
|
|
|
def __repr__(self):
|
|
"""String representation of Category."""
|
|
return f'<Category {self.name}>'
|
|
|
|
def to_dict(self):
|
|
"""Convert category to dictionary for JSON serialization."""
|
|
return {
|
|
'id': self.id,
|
|
'name': self.name,
|
|
'description': self.description,
|
|
'color': self.color,
|
|
'is_active': self.is_active,
|
|
'created_at': self.created_at.isoformat() if self.created_at else None
|
|
}
|
|
|
|
def get_transaction_count(self):
|
|
"""Get transaction count without loading all transactions."""
|
|
from app.models.transaction import Transaction
|
|
return db.session.query(Transaction).filter_by(category_id=self.id).count()
|
|
|
|
@classmethod
|
|
def get_categories_with_counts(cls):
|
|
"""Get categories with transaction counts efficiently."""
|
|
from app.models.transaction import Transaction
|
|
return db.session.query(
|
|
cls,
|
|
db.func.count(Transaction.id).label('transaction_count')
|
|
).outerjoin(Transaction).group_by(cls.id).all()
|
|
|
|
@classmethod
|
|
def get_active_categories(cls):
|
|
"""Get all active categories."""
|
|
return cls.query.filter_by(is_active=True).all()
|
|
|
|
@classmethod
|
|
def find_by_name(cls, name):
|
|
"""Find category by name."""
|
|
return cls.query.filter_by(name=name).first()
|