feature/custom-brokers-validaciones-new

This commit is contained in:
hreyes
2026-03-10 11:08:08 -06:00
parent a1c3b97375
commit 31cd249fd4
2 changed files with 50 additions and 0 deletions

View File

@@ -11,6 +11,16 @@ LICENSE_MAX = 4
RFC_MAX = 30
CURP_MAX = 19
# Formato RFC/CURP (paridad con flujo manual dashboard/customs_brokers)
RFC_PATTERN = re.compile(r"^[A-Z&Ñ]{3,4}\d{6}[A-Z0-9]{3}$", re.IGNORECASE)
# CURP: 18 caracteres (inicial, vocal, 2 letras, fecha, sexo, estado, 3 consonantes, homoclave)
CURP_PATTERN = re.compile(
r"^[A-Z][AEIOUX][A-Z]{2}\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])[HM]"
r"(AS|BC|BS|CC|CS|CH|CL|CM|DF|DG|GT|GR|HG|JC|MC|MN|MS|NT|NL|OC|PL|QT|QR|SP|SL|SR|TC|TS|TL|VZ|YN|ZS|NE)"
r"[B-DF-HJ-NP-TV-Z]{3}[0-9A-Z]\d$",
re.IGNORECASE,
)
def check_required_broker_key(row: Dict[str, Any], line_num: int) -> Optional[Dict[str, Any]]:
"""Col B: Clave de Agente Aduanal obligatoria, máx 5 caracteres."""
@@ -174,6 +184,38 @@ def check_curp_max(row: Dict[str, Any], line_num: int) -> Optional[Dict[str, Any
return None
def check_rfc_format(row: Dict[str, Any], line_num: int) -> Optional[Dict[str, Any]]:
"""Col E: RFC opcional; si tiene valor, debe cumplir formato RFC (ej. XAXX010101XXX)."""
val = (row.get("RFC") or "").strip()
if not val:
return None
if not RFC_PATTERN.match(val):
clave = (row.get("CLAVE") or "").strip()
return {
"line": line_num,
"col": "RFC",
"msg": "Error: (Col. E) El formato del RFC es inválido.",
"solution": "Capturar en la columna E un RFC con formato válido (ej. XAXX010101XXX).",
}
return None
def check_curp_format(row: Dict[str, Any], line_num: int) -> Optional[Dict[str, Any]]:
"""Col N: CURP/PERSONAL_ID opcional; si tiene valor, debe cumplir formato CURP de 18 caracteres."""
val = (row.get("PERSONAL_ID") or "").strip()
if not val:
return None
if not CURP_PATTERN.match(val):
clave = (row.get("CLAVE") or "").strip()
return {
"line": line_num,
"col": "PERSONAL_ID",
"msg": "Error: (Col. N) El formato de la CURP es inválido.",
"solution": "Capturar en la columna N un CURP con formato válido de 18 caracteres.",
}
return None
def check_pais_catalogo(
row: Dict[str, Any],
line_num: int,

View File

@@ -12,6 +12,8 @@ from ..common.common_validators import (
check_patente_obligatoria_si_mex,
check_rfc_max,
check_curp_max,
check_rfc_format,
check_curp_format,
check_pais_catalogo,
)
@@ -40,9 +42,15 @@ def validaciones_agente_aduanal(
if err:
return err
err = check_rfc_max(row, line_num)
if err:
return err
err = check_rfc_format(row, line_num)
if err:
return err
err = check_curp_max(row, line_num)
if err:
return err
err = check_curp_format(row, line_num)
if err:
return err
err = check_pais_catalogo(row, line_num, valid_country_m3)