WIP: mover cambios desde development
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user