"""add recurrence trigger modes Revision ID: 0016_recurrence_trigger_modes Revises: 0015_purge_operations """ import sqlalchemy as sa from alembic import op revision = "0016_recurrence_trigger_modes" down_revision = "0015_purge_operations" branch_labels = None depends_on = None def upgrade() -> None: with op.batch_alter_table("recurrence_templates") as batch_op: batch_op.alter_column("rrule", existing_type=sa.Text(), nullable=True) batch_op.add_column( sa.Column("trigger_mode", sa.String(length=32), nullable=False, server_default="scheduled") ) batch_op.add_column(sa.Column("after_completion_days", sa.Integer(), nullable=True)) batch_op.add_column(sa.Column("last_completed_at", sa.DateTime(timezone=True), nullable=True)) batch_op.create_check_constraint( "ck_recurrence_trigger_configuration", "(trigger_mode = 'scheduled' AND rrule IS NOT NULL AND after_completion_days IS NULL) " "OR (trigger_mode = 'after_completion' AND rrule IS NULL " "AND after_completion_days BETWEEN 1 AND 3650)", ) def downgrade() -> None: with op.batch_alter_table("recurrence_templates") as batch_op: batch_op.drop_constraint("ck_recurrence_trigger_configuration", type_="check") # Legacy schema requires an RRULE. Completion-relative rows have none, so # preserve them as a compatible daily interval rule before restoring NOT NULL. op.execute( "UPDATE recurrence_templates " "SET rrule = 'FREQ=DAILY;INTERVAL=' || after_completion_days " "WHERE trigger_mode = 'after_completion' AND rrule IS NULL" ) with op.batch_alter_table("recurrence_templates") as batch_op: batch_op.drop_column("last_completed_at") batch_op.drop_column("after_completion_days") batch_op.drop_column("trigger_mode") batch_op.alter_column("rrule", existing_type=sa.Text(), nullable=False)