feat(db): add MonthState enum and lifecycle columns
state defaults to 'planning' (server default plus SQLAlchemy default). activated_at and closed_at are nullable timestamps that record when the month crossed each boundary. Alembic batch_alter_table handles the SQLite rewrite. MonthState is a Python string enum mapped to a non-native VARCHAR(16). Refs #15 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d040b7b66c
commit
eb7e47bcbe
2 changed files with 58 additions and 0 deletions
40
alembic/versions/a4ec4f8f6e9f_add_month_lifecycle_state.py
Normal file
40
alembic/versions/a4ec4f8f6e9f_add_month_lifecycle_state.py
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
"""add month lifecycle state
|
||||||
|
|
||||||
|
Revision ID: a4ec4f8f6e9f
|
||||||
|
Revises: ec804bdf366d
|
||||||
|
Create Date: 2026-04-17 12:59:25.811354
|
||||||
|
|
||||||
|
"""
|
||||||
|
from typing import Sequence, Union
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision: str = 'a4ec4f8f6e9f'
|
||||||
|
down_revision: Union[str, Sequence[str], None] = 'ec804bdf366d'
|
||||||
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
"""Upgrade schema."""
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('month', schema=None) as batch_op:
|
||||||
|
batch_op.add_column(sa.Column('state', sa.Enum('planning', 'active', 'closed', name='monthstate', native_enum=False, length=16), server_default='planning', nullable=False))
|
||||||
|
batch_op.add_column(sa.Column('activated_at', sa.DateTime(timezone=True), nullable=True))
|
||||||
|
batch_op.add_column(sa.Column('closed_at', sa.DateTime(timezone=True), nullable=True))
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
"""Downgrade schema."""
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('month', schema=None) as batch_op:
|
||||||
|
batch_op.drop_column('closed_at')
|
||||||
|
batch_op.drop_column('activated_at')
|
||||||
|
batch_op.drop_column('state')
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
@ -27,6 +27,12 @@ class Section(str, enum.Enum):
|
||||||
sinking_fund = "sinking_fund"
|
sinking_fund = "sinking_fund"
|
||||||
|
|
||||||
|
|
||||||
|
class MonthState(str, enum.Enum):
|
||||||
|
planning = "planning"
|
||||||
|
active = "active"
|
||||||
|
closed = "closed"
|
||||||
|
|
||||||
|
|
||||||
SECTION_LABELS: dict[Section, str] = {
|
SECTION_LABELS: dict[Section, str] = {
|
||||||
Section.income: "Incomes",
|
Section.income: "Incomes",
|
||||||
Section.fixed_bill: "Fixed Amount Bills",
|
Section.fixed_bill: "Fixed Amount Bills",
|
||||||
|
|
@ -86,6 +92,18 @@ class Month(Base):
|
||||||
|
|
||||||
id: Mapped[int] = mapped_column(primary_key=True)
|
id: Mapped[int] = mapped_column(primary_key=True)
|
||||||
year_month: Mapped[str] = mapped_column(String(7), nullable=False, unique=True)
|
year_month: Mapped[str] = mapped_column(String(7), nullable=False, unique=True)
|
||||||
|
state: Mapped[MonthState] = mapped_column(
|
||||||
|
Enum(MonthState, native_enum=False, length=16),
|
||||||
|
nullable=False,
|
||||||
|
default=MonthState.planning,
|
||||||
|
server_default=MonthState.planning.value,
|
||||||
|
)
|
||||||
|
activated_at: Mapped[datetime | None] = mapped_column(
|
||||||
|
DateTime(timezone=True), nullable=True
|
||||||
|
)
|
||||||
|
closed_at: Mapped[datetime | None] = mapped_column(
|
||||||
|
DateTime(timezone=True), nullable=True
|
||||||
|
)
|
||||||
created_at: Mapped[datetime] = mapped_column(
|
created_at: Mapped[datetime] = mapped_column(
|
||||||
DateTime(timezone=True), server_default=func.now(), nullable=False
|
DateTime(timezone=True), server_default=func.now(), nullable=False
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue