diff --git a/backend/alembic/versions/e1f2a3b4c5d6_seed_sectors_for_existing_companies.py b/backend/alembic/versions/e1f2a3b4c5d6_seed_sectors_for_existing_companies.py new file mode 100644 index 00000000..1fee5b1b --- /dev/null +++ b/backend/alembic/versions/e1f2a3b4c5d6_seed_sectors_for_existing_companies.py @@ -0,0 +1,63 @@ +"""seed sectors for existing companies + +Siembra el catálogo de sectores PROSEC (a76.sectors) para todas las empresas +existentes. Los sectores son por empresa y solo se sembraban dentro de +_seed_company_data() al crear una empresa; las empresas que no pasaron por ese +flujo (BD recreada o creadas por otra vía) quedaban sin sectores y el selector +del frontend aparecía vacío. Idempotente: ON CONFLICT DO NOTHING. + +Revision ID: e1f2a3b4c5d6 +Revises: c8d9e0f1a2b3 +Create Date: 2026-06-02 14:00:00.000000 + +""" +from typing import Sequence, Union + +from alembic import op +from sqlalchemy import text +from sqlalchemy.orm import Session + +from api.v1.modules.a76.general_catalogs.sectors.seed import seed as sectors_seed + +revision: str = "e1f2a3b4c5d6" +down_revision: Union[str, None] = "c8d9e0f1a2b3" +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + def format_value(val): + if val is None or str(val).strip() == "" or str(val).upper() == "NONE": + return "NULL" + return f"'{str(val).replace(chr(39), chr(39) * 2)}'" + + bind = op.get_bind() + session = Session(bind=bind) + companies = session.execute( + text("SELECT tenant_id, id FROM a76.company WHERE deleted_at IS NULL") + ).fetchall() + + for tenant_id, company_id in companies: + values = ", ".join( + [ + f"({format_value(key)}, {format_value(description)}, {str(authorized).upper()}, {tenant_id}, {company_id})" + for key, description, authorized in sectors_seed + ] + ) + if values: + session.execute( + text( + f""" + INSERT INTO a76.sectors (key, description, authorized, tenant_id, company_id) + VALUES {values} + ON CONFLICT (key, tenant_id, company_id) DO NOTHING; + """ + ) + ) + session.commit() + + +def downgrade() -> None: + # Backfill de datos: no se eliminan sectores en el downgrade porque podrían + # haberse editado/agregado manualmente tras la siembra. No-op intencional. + pass