df1727be73
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
109 lines
4.5 KiB
Python
109 lines
4.5 KiB
Python
"""task: in_loop / at_close / fields, tipo 'check', tabella task_results (#53 #54 #55)
|
|
|
|
in_loop: il task fa parte del ciclo di produzione (prima: implicito dal tipo).
|
|
at_close: il task 'note' si compila alla fine produzione.
|
|
fields: campi extra del task 'note' (JSON).
|
|
task_results: esito registrato da un task 'check' (OK/NOK) o 'note' (done).
|
|
|
|
Revision ID: 018_task_loop_results
|
|
Revises: 017_user_pin
|
|
Create Date: 2026-10-07
|
|
|
|
"""
|
|
from typing import Sequence, Union
|
|
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
revision: str = '018_task_loop_results'
|
|
down_revision: Union[str, None] = '017_user_pin'
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
OLD_TYPES = ('note', 'measure', 'drawing', 'dxf_compare', 'camera_measure')
|
|
NEW_TYPES = OLD_TYPES + ('check',)
|
|
# stessi tipi di MEASURING_TASK_TYPES: fino a oggi erano l'unico ciclo possibile
|
|
LOOP_TYPES = ('measure', 'camera_measure', 'dxf_compare')
|
|
|
|
|
|
def upgrade() -> None:
|
|
with op.batch_alter_table('recipe_tasks') as batch:
|
|
batch.add_column(sa.Column(
|
|
'in_loop', sa.Boolean(), nullable=False, server_default=sa.false()))
|
|
batch.add_column(sa.Column(
|
|
'at_close', sa.Boolean(), nullable=False, server_default=sa.false()))
|
|
batch.add_column(sa.Column('fields', sa.JSON(), nullable=True))
|
|
# enum allargato come in 011: 'check' = Controllo OK/NOK
|
|
batch.alter_column(
|
|
'task_type',
|
|
existing_type=sa.Enum(*OLD_TYPES, name='task_type_enum'),
|
|
type_=sa.Enum(*NEW_TYPES, name='task_type_enum'),
|
|
existing_nullable=False,
|
|
existing_server_default='note',
|
|
)
|
|
|
|
# i task di misura erano gia' nel ciclo: lo restano
|
|
recipe_tasks = sa.table(
|
|
'recipe_tasks', sa.column('task_type', sa.String), sa.column('in_loop', sa.Boolean))
|
|
op.execute(
|
|
recipe_tasks.update()
|
|
.where(recipe_tasks.c.task_type.in_(LOOP_TYPES))
|
|
.values(in_loop=True)
|
|
)
|
|
|
|
op.create_table(
|
|
'task_results',
|
|
sa.Column('id', sa.Integer(), primary_key=True, autoincrement=True),
|
|
sa.Column('task_id', sa.Integer(),
|
|
sa.ForeignKey('recipe_tasks.id', ondelete='CASCADE'), nullable=False),
|
|
sa.Column('version_id', sa.Integer(),
|
|
sa.ForeignKey('recipe_versions.id'), nullable=False),
|
|
sa.Column('production_run_id', sa.Integer(),
|
|
sa.ForeignKey('production_runs.id', ondelete='SET NULL'), nullable=True),
|
|
sa.Column('user_id', sa.Integer(), sa.ForeignKey('users.id'), nullable=False),
|
|
sa.Column('outcome', sa.Enum('ok', 'nok', 'done', name='task_outcome_enum'),
|
|
nullable=False),
|
|
sa.Column('note', sa.Text(), nullable=True),
|
|
sa.Column('values', sa.JSON(), nullable=True),
|
|
sa.Column('attachments', sa.JSON(), nullable=True),
|
|
sa.Column('created_at', sa.DateTime(), nullable=False,
|
|
server_default=sa.func.now()),
|
|
mysql_engine='InnoDB',
|
|
mysql_charset='utf8mb4',
|
|
)
|
|
op.create_index('ix_task_results_task_id', 'task_results', ['task_id'])
|
|
op.create_index('ix_task_results_version_id', 'task_results', ['version_id'])
|
|
op.create_index(
|
|
'ix_task_results_production_run_id', 'task_results', ['production_run_id'])
|
|
|
|
|
|
def downgrade() -> None:
|
|
# il tipo 'check' non esiste prima di 018: se un task lo usa, tornare indietro
|
|
# lo lascerebbe con un valore fuori enum
|
|
bind = op.get_bind()
|
|
used = bind.execute(
|
|
sa.text("SELECT COUNT(*) FROM recipe_tasks WHERE task_type = 'check'")
|
|
).scalar()
|
|
if used:
|
|
raise RuntimeError(
|
|
f"Downgrade 018 impossibile: {used} task usano il tipo 'check'. "
|
|
"Cambiare il tipo o eliminare quei task prima di tornare indietro."
|
|
)
|
|
|
|
op.drop_index('ix_task_results_production_run_id', table_name='task_results')
|
|
op.drop_index('ix_task_results_version_id', table_name='task_results')
|
|
op.drop_index('ix_task_results_task_id', table_name='task_results')
|
|
op.drop_table('task_results')
|
|
|
|
with op.batch_alter_table('recipe_tasks') as batch:
|
|
batch.alter_column(
|
|
'task_type',
|
|
existing_type=sa.Enum(*NEW_TYPES, name='task_type_enum'),
|
|
type_=sa.Enum(*OLD_TYPES, name='task_type_enum'),
|
|
existing_nullable=False,
|
|
existing_server_default='note',
|
|
)
|
|
batch.drop_column('fields')
|
|
batch.drop_column('at_close')
|
|
batch.drop_column('in_loop')
|