class TransactionTag(db.Model, BaseModel): __tablename__ = "TransactionTags" tagID = db.Column(db.Integer, primary_key=True) name = db.Column(db.String, nullable=False) description = db.Column(db.String) categoryID = db.Column(db.Integer, db.ForeignKey("Categories.categoryID")) def __repr__(self): return "{} ({})".format(self.name, self.category.name)
class Category(db.Model, BaseModel): __tablename__ = "Categories" categoryID = db.Column(db.Integer, primary_key=True) name = db.Column(db.String, nullable=False) description = db.Column(db.String) tags = db.relationship("TransactionTag", backref="category") def __repr__(self): return self.name
class Account(db.Model, BaseModel): __tablename__ = "Accounts" accountID = db.Column(db.Integer, primary_key=True) name = db.Column(db.String, nullable=False) description = db.Column(db.String) isCredit = db.Column(db.Boolean, default=0, nullable=False) transactions = db.relationship("Transaction", backref="account") def __repr__(self): return "{} Account".format(self.name)
class AutoTagElement(db.Model, BaseModel): __tablename__ = "AutoTagElements" autoTagID = db.Column(db.Integer, primary_key=True, nullable=False) SearchString = db.Column("search_string", db.String, nullable=False) IsRegex = db.Column("isRegex", db.Boolean, nullable=False, default=0) tags = db.relationship("TransactionTag", secondary=AutoTagMapping) @hybrid_property def search_string(self): # TODO: Check werkzeug's cachedproperty decorator to see # if it can cover this use case. search_string = self.SearchString is_cached = getattr(self, "_search_string_cached", False) and \ self._search_string_cached.pattern == self.SearchString if self.isRegex and not is_cached: search_string = compile(search_string, IGNORECASE) self._search_string_cached = search_string elif self.isRegex: search_string = self._search_string_cached return search_string @search_string.setter def search_string(self, search_string): self.SearchString = search_string @hybrid_property def isRegex(self): return self.IsRegex @isRegex.setter def isRegex(self, val): self.IsRegex = 1 if val else 0 if self.IsRegex and isinstance(self.search_string, (str, unicode)): self.search_string = self.search_string else: self.search_string = self.search_string.pattern def __repr__(self): addenda = " (Regex)" if self.isRegex else "" search_string = getattr(self.search_string, "pattern", self.search_string) return "{} {}{}".format(search_string, self.tags, addenda) def matches(self, entry): search_string = self.search_string if self.isRegex: return (search_string.search(entry) is not None) else: return entry.count(search_string) > 0
class TransactionType(db.Model, BaseModel): __tablename__ = "TransactionTypes" transactionTypeID = db.Column(db.Integer, primary_key=True) name = db.Column(db.String, nullable=False) description = db.Column(db.String) isIncome = db.Column(db.Boolean, default=0, nullable=False) transactions = db.relationship("Transaction", backref="transaction_type") def __repr__(self): kind = "Income" if self.isIncome else "Spending" return "{} ({})".format(self.name, kind)
class Transaction(db.Model, BaseModel): __tablename__ = "Transactions" transactionID = db.Column(db.Integer, primary_key=True) amount = db.Column(db.Numeric, nullable=False) description = db.Column(db.String, nullable=False) transactionDate = db.Column(db.DateTime, nullable=False) transactionTypeID = db.Column( db.Integer, db.ForeignKey("TransactionTypes.transactionTypeID"), nullable=False) accountID = db.Column(db.Integer, db.ForeignKey("Accounts.accountID"), nullable=False) tags = db.relationship("TransactionTag", secondary=TransactionToTagMapping) def __repr__(self): return "{} for {} on {}".format(self.description, self.amount, self.transactionDate)
transactionTypeID = db.Column(db.Integer, primary_key=True) name = db.Column(db.String, nullable=False) description = db.Column(db.String) isIncome = db.Column(db.Boolean, default=0, nullable=False) transactions = db.relationship("Transaction", backref="transaction_type") def __repr__(self): kind = "Income" if self.isIncome else "Spending" return "{} ({})".format(self.name, kind) TransactionToTagMapping = db.Table( "TransactionsToTags", db.metadata, db.Column("transactionID", db.Integer, db.ForeignKey("Transactions.transactionID"), primary_key=True), db.Column("tagID", db.Integer, db.ForeignKey("TransactionTags.tagID"), primary_key=True)) class Transaction(db.Model, BaseModel): __tablename__ = "Transactions" transactionID = db.Column(db.Integer, primary_key=True) amount = db.Column(db.Numeric, nullable=False) description = db.Column(db.String, nullable=False) transactionDate = db.Column(db.DateTime, nullable=False) transactionTypeID = db.Column(
from base_model import BaseModel, db from re import compile, IGNORECASE from sqlalchemy.ext.hybrid import hybrid_property AutoTagMapping = db.Table( "AutoTagToTags", db.metadata, db.Column("autoTagID", db.Integer, db.ForeignKey("AutoTagElements.autoTagID"), primary_key=True), db.Column("tagID", db.Integer, db.ForeignKey("TransactionTags.tagID"), primary_key=True)) class AutoTagElement(db.Model, BaseModel): __tablename__ = "AutoTagElements" autoTagID = db.Column(db.Integer, primary_key=True, nullable=False) SearchString = db.Column("search_string", db.String, nullable=False) IsRegex = db.Column("isRegex", db.Boolean, nullable=False, default=0) tags = db.relationship("TransactionTag", secondary=AutoTagMapping) @hybrid_property def search_string(self): # TODO: Check werkzeug's cachedproperty decorator to see # if it can cover this use case. search_string = self.SearchString is_cached = getattr(self, "_search_string_cached", False) and \ self._search_string_cached.pattern == self.SearchString