Files

67 lines
2.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""phase43 — scheduled inspection day-of-week / day-of-month recurrence
Adds the recurrence-detail columns to `scheduled_inspections` so a weekly
schedule can name the weekdays it runs on (Mon/Wed/Fri) and a monthly schedule
can name either a day of the month ("the 15th") or an nth weekday ("the 2nd
Tuesday"):
weekdays VARCHAR(20) -- CSV of Python weekday ints, Mon=0, e.g. '0,2,4'
month_mode VARCHAR(20) -- 'day_of_month' | 'nth_weekday'
day_of_month SMALLINT -- 131, clamped to the month's last day
nth_week SMALLINT -- 15, or -1 for "last"
nth_weekday SMALLINT -- 06, Mon=0
All nullable with no backfill: existing phase36 rows keep NULLs and fall back to
the legacy "+7 days" / "same day next month" behaviour in
ScheduledInspection._add_interval(), so no schedule changes cadence on deploy.
`month_mode` is VARCHAR rather than ENUM so adding a recurrence style later
needs no 3-step MySQL ENUM migration (CLAUDE.md rule 3).
Uses INFORMATION_SCHEMA column-existence checks — safe to re-run.
"""
revision = 'phase43_sched_recurrence'
down_revision = 'phase42_internal_contact'
branch_labels = None
depends_on = None
from alembic import op
import sqlalchemy as sa
_COLUMNS = (
('weekdays', 'VARCHAR(20) NULL'),
('month_mode', 'VARCHAR(20) NULL'),
('day_of_month', 'SMALLINT NULL'),
('nth_week', 'SMALLINT NULL'),
('nth_weekday', 'SMALLINT NULL'),
)
def _column_exists(conn, table, column):
result = conn.execute(sa.text(
"SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS "
"WHERE TABLE_SCHEMA = DATABASE() "
"AND TABLE_NAME = :t AND COLUMN_NAME = :c"
), {"t": table, "c": column})
return result.scalar() > 0
def upgrade():
bind = op.get_bind()
for name, ddl in _COLUMNS:
if not _column_exists(bind, 'scheduled_inspections', name):
op.execute(sa.text(
f"ALTER TABLE scheduled_inspections ADD COLUMN {name} {ddl}"
))
def downgrade():
bind = op.get_bind()
for name, _ in reversed(_COLUMNS):
if _column_exists(bind, 'scheduled_inspections', name):
op.execute(sa.text(
f"ALTER TABLE scheduled_inspections DROP COLUMN {name}"
))