feature/separacion-de-tax-id-de-rfc

This commit is contained in:
2026-06-02 09:05:29 -06:00
parent 08f99f102e
commit 619ef8d7d8
32 changed files with 358 additions and 163 deletions

View File

@@ -0,0 +1,79 @@
"""split rfc and tax_id in clients_and_providers
Separa el identificador fiscal en dos columnas:
- rfc: RFC mexicano (nacional)
- tax_id: identificador fiscal extranjero
Antes, ambos compartían la columna `rfc` discriminados por `type_nat_foreign`.
La migración mueve el valor de los extranjeros (type_nat_foreign='E') de `rfc` a
`tax_id` y deja `rfc` en NULL para esos registros. Los nacionales no se tocan.
Revision ID: b3c4d5e6f7a8
Revises: 506969b0a256
Create Date: 2026-06-02 10:00:00.000000
"""
import logging
from typing import Sequence, Union
import sqlalchemy as sa
from alembic import op
revision: str = "b3c4d5e6f7a8"
down_revision: Union[str, None] = "506969b0a256"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
logger = logging.getLogger("alembic.runtime.migration")
# Extranjero ⟺ type_nat_foreign empieza con 'E' (misma convención que DTOs/modelo/frontend).
_FOREIGN_PREDICATE = "UPPER(COALESCE(type_nat_foreign, '')) LIKE 'E%'"
def upgrade() -> None:
# 1) Nueva columna tax_id (nullable: un registro puede no tener identificador extranjero).
op.add_column(
"clients_and_providers",
sa.Column("tax_id", sa.String(length=30), nullable=True),
schema="a76",
)
conn = op.get_bind()
# 2) Conteo previo (visibilidad antes de mover datos; UPDATE precedido de SELECT COUNT).
to_move = conn.execute(
sa.text(
"SELECT COUNT(*) FROM a76.clients_and_providers "
f"WHERE {_FOREIGN_PREDICATE} AND rfc IS NOT NULL"
)
).scalar()
logger.info(
"split_rfc_tax_id: %s registros extranjeros con rfc serán movidos a tax_id",
to_move,
)
# 3) Mover rfc -> tax_id para extranjeros (idempotente por el guard tax_id IS NULL).
conn.execute(
sa.text(
"UPDATE a76.clients_and_providers SET tax_id = rfc "
f"WHERE {_FOREIGN_PREDICATE} AND tax_id IS NULL AND rfc IS NOT NULL"
)
)
# 4) Limpiar rfc en extranjeros (la columna rfc queda solo para RFC nacional).
conn.execute(
sa.text(
f"UPDATE a76.clients_and_providers SET rfc = NULL WHERE {_FOREIGN_PREDICATE}"
)
)
def downgrade() -> None:
# Reconsolidar: regresar el identificador extranjero a rfc antes de eliminar la columna.
conn = op.get_bind()
conn.execute(
sa.text(
"UPDATE a76.clients_and_providers SET rfc = tax_id "
f"WHERE {_FOREIGN_PREDICATE} AND rfc IS NULL AND tax_id IS NOT NULL"
)
)
op.drop_column("clients_and_providers", "tax_id", schema="a76")