From cf608c34607254cd0d15aced09ea39b9430c4ec7 Mon Sep 17 00:00:00 2001 From: Deimos Date: Mon, 4 Nov 2019 22:00:12 -0700 Subject: [PATCH] Add table for storing financial info This adds a table that can store expenses, goals, and income entries. This will be used to be able to make the site's financials more visible. --- .../879588c5729d_add_financials_table.py | 49 +++++++++++++++++++ tildes/tildes/database_models.py | 1 + tildes/tildes/enums.py | 8 +++ tildes/tildes/models/financials.py | 31 ++++++++++++ 4 files changed, 89 insertions(+) create mode 100644 tildes/alembic/versions/879588c5729d_add_financials_table.py create mode 100644 tildes/tildes/models/financials.py diff --git a/tildes/alembic/versions/879588c5729d_add_financials_table.py b/tildes/alembic/versions/879588c5729d_add_financials_table.py new file mode 100644 index 0000000..342b28f --- /dev/null +++ b/tildes/alembic/versions/879588c5729d_add_financials_table.py @@ -0,0 +1,49 @@ +"""Add financials table + +Revision ID: 879588c5729d +Revises: fa14e9f5ebe5 +Create Date: 2019-11-05 19:50:13.973734 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = "879588c5729d" +down_revision = "fa14e9f5ebe5" +branch_labels = None +depends_on = None + + +def upgrade(): + op.create_table( + "financials", + sa.Column("entry_id", sa.Integer(), nullable=False), + sa.Column( + "entry_type", + postgresql.ENUM("EXPENSE", "GOAL", "INCOME", name="financialentrytype"), + nullable=False, + ), + sa.Column("description", sa.Text(), nullable=True), + sa.Column("amount", sa.Numeric(scale=2), nullable=False), + sa.Column("date_range", postgresql.DATERANGE(), nullable=False), + sa.Column( + "is_approximate", sa.Boolean(), server_default="false", nullable=False + ), + sa.PrimaryKeyConstraint("entry_id", name=op.f("pk_financials")), + ) + op.create_index( + "ix_financials_date_range_gist", + "financials", + ["date_range"], + unique=False, + postgresql_using="gist", + ) + + +def downgrade(): + op.drop_index("ix_financials_date_range_gist", table_name="financials") + op.drop_table("financials") + + op.execute("DROP TYPE financialentrytype") diff --git a/tildes/tildes/database_models.py b/tildes/tildes/database_models.py index 6a69829..f1b3d30 100644 --- a/tildes/tildes/database_models.py +++ b/tildes/tildes/database_models.py @@ -12,6 +12,7 @@ from tildes.models.comment import ( CommentNotification, CommentVote, ) +from tildes.models.financials import Financials from tildes.models.group import Group, GroupSubscription from tildes.models.log import Log from tildes.models.message import MessageConversation, MessageReply diff --git a/tildes/tildes/enums.py b/tildes/tildes/enums.py index e9dcef2..af440fa 100644 --- a/tildes/tildes/enums.py +++ b/tildes/tildes/enums.py @@ -80,6 +80,14 @@ class CommentLabelOption(enum.Enum): return None +class FinancialEntryType(enum.Enum): + """Enum for entry types in the Financials table.""" + + EXPENSE = enum.auto() + GOAL = enum.auto() + INCOME = enum.auto() + + class LogEventType(enum.Enum): """Enum for the types of events stored in logs.""" diff --git a/tildes/tildes/models/financials.py b/tildes/tildes/models/financials.py new file mode 100644 index 0000000..027188b --- /dev/null +++ b/tildes/tildes/models/financials.py @@ -0,0 +1,31 @@ +# Copyright (c) 2019 Tildes contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + +"""Contains the Financials class.""" + +from decimal import Decimal + +from psycopg2.extras import DateRange +from sqlalchemy import Boolean, Column, Index, Integer, Numeric, Text +from sqlalchemy.dialects.postgresql import DATERANGE, ENUM + +from tildes.enums import FinancialEntryType +from tildes.models import DatabaseModel + + +class Financials(DatabaseModel): + """Model holding information about the site's financials over time.""" + + __tablename__ = "financials" + + entry_id: int = Column(Integer, primary_key=True) + entry_type: FinancialEntryType = Column(ENUM(FinancialEntryType), nullable=False) + description: str = Column(Text) + amount: Decimal = Column(Numeric(scale=2), nullable=False) + date_range: DateRange = Column(DATERANGE, nullable=False) + is_approximate: bool = Column(Boolean, nullable=False, server_default="false") + + # Add a GiST index on the date_range column for range operators + __table_args__ = ( + Index("ix_financials_date_range_gist", date_range, postgresql_using="gist"), + )