fix/AS-prosec-revertir-boolean (#482)
prosec revertir boolean y uso de catalogo Reviewed-on: ADUANASOFT/anexo76#482 Co-authored-by: hreyes <hreyes@aduanasoft.com.mx> Co-committed-by: hreyes <hreyes@aduanasoft.com.mx>
This commit is contained in:
@@ -1,37 +0,0 @@
|
||||
"""company prosec boolean to integer
|
||||
|
||||
Revision ID: 506969b0a256
|
||||
Revises: a7b8c9d0e1f2
|
||||
Create Date: 2026-06-02 00:00:00.000000
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
|
||||
revision: str = "506969b0a256"
|
||||
down_revision: Union[str, None] = "a7b8c9d0e1f2"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# Convierte prosec de boolean a integer para almacenar el ID del sector PROSEC.
|
||||
# El default 'false' debe eliminarse antes de cambiar el tipo.
|
||||
op.execute("ALTER TABLE a76.company ALTER COLUMN prosec DROP DEFAULT")
|
||||
op.execute("ALTER TABLE a76.company ALTER COLUMN prosec DROP NOT NULL")
|
||||
op.execute(
|
||||
"ALTER TABLE a76.company ALTER COLUMN prosec TYPE integer USING prosec::int"
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.execute(
|
||||
"""
|
||||
ALTER TABLE a76.company
|
||||
ALTER COLUMN prosec TYPE boolean
|
||||
USING CASE WHEN prosec IS NULL OR prosec = 0 THEN false ELSE true END
|
||||
"""
|
||||
)
|
||||
op.execute("ALTER TABLE a76.company ALTER COLUMN prosec SET DEFAULT false")
|
||||
op.execute("ALTER TABLE a76.company ALTER COLUMN prosec SET NOT NULL")
|
||||
@@ -9,7 +9,7 @@ La migración mueve el valor de los extranjeros (type_nat_foreign='E') de `rfc`
|
||||
`tax_id` y deja `rfc` en NULL para esos registros. Los nacionales no se tocan.
|
||||
|
||||
Revision ID: b3c4d5e6f7a8
|
||||
Revises: 506969b0a256
|
||||
Revises: a7b8c9d0e1f2
|
||||
Create Date: 2026-06-02 10:00:00.000000
|
||||
|
||||
"""
|
||||
@@ -20,7 +20,7 @@ import sqlalchemy as sa
|
||||
from alembic import op
|
||||
|
||||
revision: str = "b3c4d5e6f7a8"
|
||||
down_revision: Union[str, None] = "506969b0a256"
|
||||
down_revision: Union[str, None] = "a7b8c9d0e1f2"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
@@ -26,9 +26,9 @@ class CompanyCreateDTO(BaseModel):
|
||||
program_number: Optional[str] = Field(
|
||||
None, max_length=40, description="Program number"
|
||||
)
|
||||
prosec: Optional[int] = Field(None, description="PROSEC")
|
||||
prosec: Optional[bool] = Field(False, description="Empresa con programa PROSEC")
|
||||
prosec_authorization: Optional[str] = Field(
|
||||
None, max_length=20, description="PROSEC authorization"
|
||||
None, max_length=20, description="Clave del sector PROSEC"
|
||||
)
|
||||
|
||||
# Identifiers
|
||||
@@ -250,6 +250,22 @@ class CompanyCreateDTO(BaseModel):
|
||||
raise ValueError("Date must be in DD/MM/YYYY format") from exc
|
||||
raise ValueError("Date must be in DD/MM/YYYY format")
|
||||
|
||||
@field_validator("prosec", mode="before")
|
||||
@classmethod
|
||||
def coerce_prosec_to_bool(cls, value):
|
||||
"""Coacciona prosec a booleano. Tolera valores heredados cuando la columna
|
||||
era entero (ID de sector): null/0/vacío → False, cualquier otro → True.
|
||||
Misma regla que el downgrade de la migración previa."""
|
||||
if value in (None, ""):
|
||||
return False
|
||||
if isinstance(value, bool):
|
||||
return value
|
||||
if isinstance(value, (int, float)):
|
||||
return value != 0
|
||||
if isinstance(value, str):
|
||||
return value.strip().lower() not in {"0", "false", "no", "off", ""}
|
||||
return bool(value)
|
||||
|
||||
@field_validator("annex30_modality", mode="before")
|
||||
@classmethod
|
||||
def validate_annex30_modality(cls, value):
|
||||
@@ -278,7 +294,7 @@ class CompanyResponseDTO(BaseModel):
|
||||
# Program information
|
||||
program: Optional[str] = None
|
||||
program_number: Optional[str] = None
|
||||
prosec: Optional[int] = None
|
||||
prosec: bool = False
|
||||
prosec_authorization: Optional[str] = None
|
||||
|
||||
# Identifiers
|
||||
@@ -317,6 +333,21 @@ class CompanyResponseDTO(BaseModel):
|
||||
created_at: datetime
|
||||
updated_at: Optional[datetime] = None
|
||||
|
||||
@field_validator("prosec", mode="before")
|
||||
@classmethod
|
||||
def coerce_prosec_to_bool(cls, value):
|
||||
"""Tolera datos heredados cuando la columna prosec era entero (ID de sector):
|
||||
null/0/vacío → False, cualquier otro → True."""
|
||||
if value in (None, ""):
|
||||
return False
|
||||
if isinstance(value, bool):
|
||||
return value
|
||||
if isinstance(value, (int, float)):
|
||||
return value != 0
|
||||
if isinstance(value, str):
|
||||
return value.strip().lower() not in {"0", "false", "no", "off", ""}
|
||||
return bool(value)
|
||||
|
||||
# --- Flattened Fields for Response ---
|
||||
# Sectores
|
||||
sector1: Optional[str] = None
|
||||
|
||||
@@ -39,7 +39,11 @@ class Company(Base, TimestampMixin):
|
||||
# Programa
|
||||
program: Mapped[Optional[str]] = mapped_column(String(7))
|
||||
program_number: Mapped[Optional[str]] = mapped_column(String(40))
|
||||
prosec: Mapped[Optional[int]] = mapped_column(Integer, nullable=True, default=None)
|
||||
# prosec: indica si la empresa cuenta con programa PROSEC (sí/no)
|
||||
prosec: Mapped[bool] = mapped_column(
|
||||
Boolean, nullable=False, default=False, server_default="false"
|
||||
)
|
||||
# prosec_authorization: clave del sector PROSEC (catálogo de sectores)
|
||||
prosec_authorization: Mapped[Optional[str]] = mapped_column(String(20))
|
||||
|
||||
# Sectores
|
||||
|
||||
Reference in New Issue
Block a user