"""Add notificationtypes.gracewindowminutes (post-expiry tail on the board). The shopfloor feed kept every ended notification on the board for a hardcoded 30 minutes, flagged resolved. A card with an 8:00 end time therefore sat there until 8:30, and in the carousel/grid/banner sections it did so with no visual sign it had ended at all. The tail is now per type and defaults to 0, so an end time means what it says; a type that wants an acknowledged tail opts in. Idempotent; downgrade drops the column. Revision ID: notifications0003grace Revises: notifications0002buidx """ from alembic import op import sqlalchemy as sa revision = 'notifications0003grace' down_revision = 'notifications0002buidx' branch_labels = None depends_on = None _TABLE = 'notificationtypes' _COLUMN = 'gracewindowminutes' def _column_names(insp, table): return {c['name'] for c in insp.get_columns(table)} def upgrade(): bind = op.get_bind() insp = sa.inspect(bind) if _TABLE not in insp.get_table_names(): return if _COLUMN not in _column_names(insp, _TABLE): op.add_column(_TABLE, sa.Column(_COLUMN, sa.Integer(), nullable=False, server_default='0')) def downgrade(): bind = op.get_bind() insp = sa.inspect(bind) if _TABLE not in insp.get_table_names(): return if _COLUMN in _column_names(insp, _TABLE): op.drop_column(_TABLE, _COLUMN)