aboutsummaryrefslogtreecommitdiffstats
path: root/src/expense/model.py
blob: 2047cca1dce2f8bc57267aed0ddf1bf147bc5d1e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
from typing import List
import datetime

from flask_login import UserMixin
from sqlalchemy import Column, Float, Integer, String, ForeignKey, Text
from sqlalchemy.orm import Mapped, mapped_column, relationship

from .auth.password import PasswordHash, Password
from . import db

user_category = db.Table(
    "user_category_map",
    Column("user_id", Integer, ForeignKey("user.id"), primary_key=True),
    Column("category_id", Integer, ForeignKey("category.id"), primary_key=True),
)

class User(db.Model, UserMixin):
    """The table for Username and Password"""
    id: Mapped[int] = mapped_column(primary_key=True, init=False)
    name: Mapped[str] = mapped_column(String(64), unique=True, comment="The username")
    password: Mapped[PasswordHash] = mapped_column(Password(), comment="The password as a hash")
    expenses: Mapped[List["Expense"]] = relationship(
        back_populates="user",
        order_by="Expense.date",
        cascade="all, delete",
        init=False,
    )
    categories: Mapped[List["Category"]] = relationship(
        secondary=user_category, init=False,
    )


class Category(db.Model):
    """The List of categories, contains both user defined and predefined"""
    id: Mapped[int] = mapped_column(primary_key=True, init=False)
    name: Mapped[str] = mapped_column(String(256), nullable=False, unique=True)


class Expense(db.Model):
    """The list of expenses"""
    id: Mapped[int] = mapped_column(primary_key=True, init=False)
    user_id: Mapped[int] = mapped_column(ForeignKey("user.id"), init=False)
    user = relationship(User, back_populates="expenses")
    date: Mapped[datetime.date] = mapped_column()
    amount: Mapped[float] = mapped_column(Float(2))
    category_id: Mapped[int] = mapped_column(ForeignKey("category.id"), init=False)
    category: Mapped[Category] = relationship()
    description: Mapped[str] = mapped_column(Text(), default="")


def populate_table() -> None:
    """
    Create the initial entries for the table.
    Currently populates the Category table with predefined values
    """
    for cat in ["Misc", "Income"]:
        if db.session.scalars(
            db.select(Category).where(Category.name == cat)
        ).one_or_none():
            continue
        db.session.add(Category(name=cat)) # type: ignore

    db.session.commit()