mitlist/be/alembic/versions/295cb070f266_add_recurrence_pattern.py
mohamad 81577ac7e8 feat: Add Recurrence Pattern and Update Expense Schema
- Introduced a new `RecurrencePattern` model to manage recurrence details for expenses, allowing for daily, weekly, monthly, and yearly patterns.
- Updated the `Expense` model to include fields for recurrence management, such as `is_recurring`, `recurrence_pattern_id`, and `next_occurrence`.
- Modified the database schema to reflect these changes, including alterations to existing columns and the removal of obsolete fields.
- Enhanced the expense creation logic to accommodate recurring expenses and updated related CRUD operations accordingly.
- Implemented necessary migrations to ensure database integrity and support for the new features.
2025-05-23 21:01:49 +02:00

91 lines
4.8 KiB
Python

"""add_recurrence_pattern
Revision ID: 295cb070f266
Revises: 7cc1484074eb
Create Date: 2025-05-22 19:55:24.650524
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision: str = '295cb070f266'
down_revision: Union[str, None] = '7cc1484074eb'
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! ###
op.alter_column('expenses', 'next_occurrence',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
op.drop_index('ix_expenses_recurring_next_occurrence', table_name='expenses', postgresql_where='(is_recurring = true)')
op.drop_constraint('fk_expenses_recurrence_pattern_id', 'expenses', type_='foreignkey')
op.drop_constraint('fk_expenses_parent_expense_id', 'expenses', type_='foreignkey')
op.drop_column('expenses', 'recurrence_pattern_id')
op.drop_column('expenses', 'last_occurrence')
op.drop_column('expenses', 'parent_expense_id')
op.alter_column('recurrence_patterns', 'days_of_week',
existing_type=postgresql.JSON(astext_type=sa.Text()),
type_=sa.String(),
existing_nullable=True)
op.alter_column('recurrence_patterns', 'end_date',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
op.alter_column('recurrence_patterns', 'created_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=False)
op.alter_column('recurrence_patterns', 'updated_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=False)
op.create_index(op.f('ix_settlement_activities_created_by_user_id'), 'settlement_activities', ['created_by_user_id'], unique=False)
op.create_index(op.f('ix_settlement_activities_expense_split_id'), 'settlement_activities', ['expense_split_id'], unique=False)
op.create_index(op.f('ix_settlement_activities_id'), 'settlement_activities', ['id'], unique=False)
op.create_index(op.f('ix_settlement_activities_paid_by_user_id'), 'settlement_activities', ['paid_by_user_id'], unique=False)
# ### end Alembic commands ###
def downgrade() -> None:
"""Downgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.drop_index(op.f('ix_settlement_activities_paid_by_user_id'), table_name='settlement_activities')
op.drop_index(op.f('ix_settlement_activities_id'), table_name='settlement_activities')
op.drop_index(op.f('ix_settlement_activities_expense_split_id'), table_name='settlement_activities')
op.drop_index(op.f('ix_settlement_activities_created_by_user_id'), table_name='settlement_activities')
op.alter_column('recurrence_patterns', 'updated_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=False)
op.alter_column('recurrence_patterns', 'created_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=False)
op.alter_column('recurrence_patterns', 'end_date',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
op.alter_column('recurrence_patterns', 'days_of_week',
existing_type=sa.String(),
type_=postgresql.JSON(astext_type=sa.Text()),
existing_nullable=True)
op.add_column('expenses', sa.Column('parent_expense_id', sa.INTEGER(), autoincrement=False, nullable=True))
op.add_column('expenses', sa.Column('last_occurrence', postgresql.TIMESTAMP(), autoincrement=False, nullable=True))
op.add_column('expenses', sa.Column('recurrence_pattern_id', sa.INTEGER(), autoincrement=False, nullable=True))
op.create_foreign_key('fk_expenses_parent_expense_id', 'expenses', 'expenses', ['parent_expense_id'], ['id'], ondelete='SET NULL')
op.create_foreign_key('fk_expenses_recurrence_pattern_id', 'expenses', 'recurrence_patterns', ['recurrence_pattern_id'], ['id'], ondelete='SET NULL')
op.create_index('ix_expenses_recurring_next_occurrence', 'expenses', ['is_recurring', 'next_occurrence'], unique=False, postgresql_where='(is_recurring = true)')
op.alter_column('expenses', 'next_occurrence',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
# ### end Alembic commands ###