WIP: mover cambios desde development

This commit is contained in:
hreyes
2026-03-17 09:27:03 -06:00
parent 0bae0e4d13
commit 8a0c67d452
4 changed files with 1106 additions and 909 deletions

View File

@@ -5,6 +5,7 @@ Paridad Clarion: VALIDA_TODA_PARTES (obligatorios A, B, E salvo excepción RFC),
from typing import Dict, Any, Optional, Set
from ..common.common_validators import check_max_length, check_decimal
from decimal import Decimal, InvalidOperation
MSG_NUMPARTE_VACIO = (
@@ -108,9 +109,33 @@ def validate_row_types(row: Dict[str, Any], line_num: int) -> Optional[Dict[str,
err = check_decimal(row, "COSTOUNIT", line_num)
if err:
return err
# No negativos
raw = (row.get("COSTOUNIT") or "").strip()
if raw:
try:
if Decimal(raw) < 0:
return {
"line": line_num,
"col": "COSTOUNIT",
"msg": "Error: (Col. I) El Costo Unitario no puede ser negativo.",
}
except (InvalidOperation, ValueError):
# check_decimal already handles format; ignore here
pass
err = check_decimal(row, "PESOUNIT", line_num)
if err:
return err
raw = (row.get("PESOUNIT") or "").strip()
if raw:
try:
if Decimal(raw) < 0:
return {
"line": line_num,
"col": "PESOUNIT",
"msg": "Error: (Col. K) El Peso Unitario no puede ser negativo.",
}
except (InvalidOperation, ValueError):
pass
return None
@@ -292,6 +317,16 @@ def validate_row_sector(
"""Col P (Sector): si O=PROSEC entonces P obligatorio, empresa PROSEC, sector autorizado; si O≠PROSEC y P no vacío error."""
pref = (row.get("PREFERENCIA") or "").strip().upper()
sector = (row.get("SECTOR") or "").strip()
# Formato: solo A-Z/0-9 (sin espacios ni especiales), hasta 8
if sector:
s = sector.strip().upper()
# Alinear con modelo A76: solo dígitos, máx 8
if not (1 <= len(s) <= 8) or not s.isdigit():
return {
"line": line_num,
"col": "SECTOR",
"msg": "Error: (Col. P) El Sector contiene caracteres no permitidos. Use solo números (máx. 8 dígitos).",
}
if pref == "PROSEC":
if not sector:
return {

View File

@@ -1,13 +1,13 @@
from datetime import datetime
from decimal import Decimal
from typing import List, Optional
from typing import List, Optional, Literal
from pydantic import BaseModel, Field, ConfigDict
# --- SUB-DTO: DATOS ADUANALES (FaData) ---
class FaDataDTO(BaseModel):
origin_country: Optional[str] = None
sector: Optional[str] = None
fraction_type: Optional[str] = None
origin_country: Optional[str] = Field(default=None, pattern=r"^[A-Z]{3}$")
sector: Optional[str] = Field(default=None, pattern=r"^[0-9]{1,8}$")
fraction_type: Optional[Literal["GENERAL", "PROSEC", "ALADI", "TLCS"]] = None
model_config = ConfigDict(from_attributes=True)
@@ -70,11 +70,11 @@ class PartBase(BaseModel):
part_class: Optional[str] = None
unit_of_measure: Optional[str] = "PZ"
unit_cost: Optional[Decimal] = None
unit_cost: Optional[Decimal] = Field(default=None, ge=0)
currency_key: Optional[str] = None
currency_type: Optional[str] = None
unit_weight: Optional[Decimal] = None
unit_weight: Optional[Decimal] = Field(default=None, ge=0)
weight_type: Optional[str] = None
fraction: Optional[str] = None