"""recurring habits attachments audit export-import Revision ID: 0003 Revises: 0002 """ import sqlalchemy as sa from alembic import op revision = "0003" down_revision = "0002" branch_labels = None depends_on = None def upgrade() -> None: bind = op.get_bind() dialect = bind.dialect.name op.add_column("tasks", sa.Column("external_id", sa.String(255), nullable=True)) if dialect == "sqlite": with op.batch_alter_table("tasks") as batch_op: batch_op.create_unique_constraint("uq_tasks_external_id", ["user_id", "external_id"]) else: op.create_unique_constraint("uq_tasks_external_id", "tasks", ["user_id", "external_id"]) op.add_column("sessions", sa.Column("ip_address", sa.String(64), nullable=True)) op.add_column("sessions", sa.Column("user_agent", sa.String(255), nullable=True)) op.create_table( "recurrence_templates", sa.Column("id", sa.Uuid(), primary_key=True), sa.Column("user_id", sa.Uuid(), sa.ForeignKey("users.id", ondelete="CASCADE"), nullable=False), sa.Column("task_id", sa.Uuid(), sa.ForeignKey("tasks.id", ondelete="CASCADE"), nullable=False, unique=True), sa.Column("rrule", sa.Text(), nullable=False), sa.Column("starts_at", sa.DateTime(timezone=True), nullable=False), sa.Column("ends_at", sa.DateTime(timezone=True), nullable=True), sa.Column("created_at", sa.DateTime(timezone=True), nullable=False), ) op.create_index("ix_recurrence_templates_user_id", "recurrence_templates", ["user_id"]) op.create_table( "recurrence_exceptions", sa.Column("id", sa.Uuid(), primary_key=True), sa.Column("template_id", sa.Uuid(), sa.ForeignKey("recurrence_templates.id", ondelete="CASCADE"), nullable=False), sa.Column("occurrence_at", sa.DateTime(timezone=True), nullable=False), sa.Column("title", sa.String(500), nullable=True), sa.Column("due_at", sa.DateTime(timezone=True), nullable=True), sa.Column("completed", sa.Boolean(), nullable=False), sa.Column("deleted", sa.Boolean(), nullable=False), sa.UniqueConstraint("template_id", "occurrence_at", name="uq_recurrence_exception"), ) op.create_index("ix_recurrence_exceptions_template_id", "recurrence_exceptions", ["template_id"]) op.create_table( "habits", sa.Column("id", sa.Uuid(), primary_key=True), sa.Column("user_id", sa.Uuid(), sa.ForeignKey("users.id", ondelete="CASCADE"), nullable=False), sa.Column("name", sa.String(200), nullable=False), sa.Column("kind", sa.String(16), nullable=False), sa.Column("target", sa.Float(), nullable=False), sa.Column("max_value", sa.Float(), nullable=True), sa.Column("schedule_type", sa.String(16), nullable=False), sa.Column("weekdays", sa.String(32), nullable=True), sa.Column("month_days", sa.String(100), nullable=True), sa.Column("interval_days", sa.Integer(), nullable=True), sa.Column("start_date", sa.Date(), nullable=False), sa.Column("archived_at", sa.DateTime(timezone=True), nullable=True), sa.Column("created_at", sa.DateTime(timezone=True), nullable=False), ) op.create_index("ix_habits_user_id", "habits", ["user_id"]) op.create_table( "habit_logs", sa.Column("id", sa.Uuid(), primary_key=True), sa.Column("habit_id", sa.Uuid(), sa.ForeignKey("habits.id", ondelete="CASCADE"), nullable=False), sa.Column("day", sa.Date(), nullable=False), sa.Column("value", sa.Float(), nullable=False), sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False), sa.UniqueConstraint("habit_id", "day", name="uq_habit_log_day"), ) op.create_index("ix_habit_logs_habit_id", "habit_logs", ["habit_id"]) op.create_table( "habit_pauses", sa.Column("id", sa.Uuid(), primary_key=True), sa.Column("habit_id", sa.Uuid(), sa.ForeignKey("habits.id", ondelete="CASCADE"), nullable=False), sa.Column("start_date", sa.Date(), nullable=False), sa.Column("end_date", sa.Date(), nullable=False), ) op.create_index("ix_habit_pauses_habit_id", "habit_pauses", ["habit_id"]) op.create_table( "attachments", sa.Column("id", sa.Uuid(), primary_key=True), sa.Column("user_id", sa.Uuid(), sa.ForeignKey("users.id", ondelete="CASCADE"), nullable=False), sa.Column("task_id", sa.Uuid(), sa.ForeignKey("tasks.id", ondelete="CASCADE"), nullable=False), sa.Column("filename", sa.String(255), nullable=False), sa.Column("storage_name", sa.String(255), nullable=False, unique=True), sa.Column("mime_type", sa.String(127), nullable=False), sa.Column("size", sa.Integer(), nullable=False), sa.Column("created_at", sa.DateTime(timezone=True), nullable=False), ) op.create_index("ix_attachments_user_id", "attachments", ["user_id"]) op.create_index("ix_attachments_task_id", "attachments", ["task_id"]) op.create_table( "audit_logs", sa.Column("id", sa.Uuid(), primary_key=True), sa.Column("user_id", sa.Uuid(), sa.ForeignKey("users.id", ondelete="CASCADE"), nullable=False), sa.Column("action", sa.String(32), nullable=False), sa.Column("entity_type", sa.String(32), nullable=False), sa.Column("entity_id", sa.Uuid(), nullable=True), sa.Column("details", sa.JSON(), nullable=False), sa.Column("created_at", sa.DateTime(timezone=True), nullable=False), ) op.create_index("ix_audit_logs_user_id", "audit_logs", ["user_id"]) def downgrade() -> None: op.drop_index("ix_audit_logs_user_id", table_name="audit_logs") op.drop_table("audit_logs") op.drop_index("ix_attachments_task_id", table_name="attachments") op.drop_index("ix_attachments_user_id", table_name="attachments") op.drop_table("attachments") op.drop_index("ix_habit_pauses_habit_id", table_name="habit_pauses") op.drop_table("habit_pauses") op.drop_index("ix_habit_logs_habit_id", table_name="habit_logs") op.drop_table("habit_logs") op.drop_index("ix_habits_user_id", table_name="habits") op.drop_table("habits") op.drop_index("ix_recurrence_exceptions_template_id", table_name="recurrence_exceptions") op.drop_table("recurrence_exceptions") op.drop_index("ix_recurrence_templates_user_id", table_name="recurrence_templates") op.drop_table("recurrence_templates") op.drop_column("sessions", "user_agent") op.drop_column("sessions", "ip_address") op.drop_constraint("uq_tasks_external_id", "tasks", type_="unique") op.drop_column("tasks", "external_id")