"""record who authorised an out-of-tolerance measurement The supervisor gate existed on screen and nowhere else: the modal opened, the credentials were checked, the modal closed, and nothing was written down. Nothing depended on the answer either, so a value outside tolerance could be left behind by dismissing the modal. These two columns are what the rule now stands on. A failed measurement with no supervisor on it is a measurement waiting for one, and while one is waiting the operator cannot move to the next quote. Existing rows are left null. Backfilling an authorisation that never happened would be inventing an audit record; the fails already in the database belong to production runs that are over, and nothing is waiting on them. Revision ID: 010_meas_authorisation Revises: 009_recipe_rules Create Date: 2026-07-28 """ from typing import Sequence, Union from alembic import op import sqlalchemy as sa revision: str = '010_meas_authorisation' down_revision: Union[str, None] = '009_recipe_rules' branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: with op.batch_alter_table('measurements') as batch: batch.add_column(sa.Column('supervisor_id', sa.Integer(), nullable=True)) batch.add_column(sa.Column('authorised_at', sa.DateTime(), nullable=True)) batch.create_foreign_key( 'fk_measurements_supervisor_id', 'users', ['supervisor_id'], ['id'], ) batch.create_index( 'ix_measurements_supervisor_id', ['supervisor_id'], ) def downgrade() -> None: with op.batch_alter_table('measurements') as batch: batch.drop_index('ix_measurements_supervisor_id') batch.drop_constraint('fk_measurements_supervisor_id', type_='foreignkey') batch.drop_column('authorised_at') batch.drop_column('supervisor_id')