#!/usr/bin/env python3 """Initialize workshop_permissions tenant_config for all existing tenants. Uses the same defaults defined in pos/blueprints/config_bp.py. Safe to run multiple times (it overwrites with defaults). Example: sudo -u postgres python3 scripts/migrate_workshop_permissions.py """ import json import os import sys import psycopg2 # Mirror of pos/blueprints/config_bp.py defaults _WORKSHOP_STATUSES = [ 'por_revisar', 'en_revision', 'revisada', 'cotizada', 'por_autorizar', 'autorizada', 'autorizacion_parcial', 'en_reparacion', 'reparada', 'por_entregar', 'entregado', 'por_enviar', 'enviado', 'por_facturar', 'facturada', 'por_recolectar', 'cancelada' ] _ALL_ACTIONS = [ 'create_order', 'edit_order', 'delete_order', 'assign_mechanic', 'add_items', 'add_labor', 'change_status', 'convert_to_sale', 'convert_to_remission', 'view_customer_data', 'view_prices', 'view_notes', ] _DEFAULT_WORKSHOP_PERMISSIONS = { 'owner': {'statuses': _WORKSHOP_STATUSES, 'actions': _ALL_ACTIONS}, 'admin': {'statuses': _WORKSHOP_STATUSES, 'actions': _ALL_ACTIONS}, 'manager': {'statuses': _WORKSHOP_STATUSES, 'actions': [a for a in _ALL_ACTIONS if a != 'delete_order']}, 'counter': {'statuses': _WORKSHOP_STATUSES, 'actions': [a for a in _ALL_ACTIONS if a != 'delete_order']}, 'cashier': {'statuses': _WORKSHOP_STATUSES, 'actions': [a for a in _ALL_ACTIONS if a not in ('delete_order', 'convert_to_sale')]}, 'workshop': { 'statuses': [s for s in _WORKSHOP_STATUSES if s not in ('por_entregar', 'entregado', 'por_enviar', 'enviado', 'por_recolectar')], 'actions': ['change_status', 'add_labor', 'view_notes'] }, 'mechanic': { 'statuses': ['por_revisar', 'en_revision', 'revisada', 'en_reparacion', 'reparada', 'autorizada', 'cancelada'], 'actions': ['change_status', 'add_labor', 'view_notes'] }, } def get_tenant_dbs(master_db='nexus_autoparts'): conn = psycopg2.connect(f"postgresql://postgres@/{master_db}") cur = conn.cursor() cur.execute("SELECT db_name FROM tenants WHERE is_active = true") dbs = [r[0] for r in cur.fetchall() if r[0]] cur.close(); conn.close() return dbs def migrate(db_name): conn = psycopg2.connect(f"postgresql://postgres@/{db_name}") cur = conn.cursor() cur.execute(""" INSERT INTO tenant_config (key, value) VALUES ('workshop_permissions', %s) ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value """, (json.dumps(_DEFAULT_WORKSHOP_PERMISSIONS),)) conn.commit() cur.close(); conn.close() return True def main(): dbs = get_tenant_dbs() print(f"Migrating {len(dbs)} tenant(s)...") for db in dbs: try: migrate(db) print(f" OK {db}") except Exception as e: print(f" ERR {db}: {e}") print("Done.") if __name__ == '__main__': main()