Merge branch 'development' into feature/alembic-daf
This commit is contained in:
@@ -138,7 +138,7 @@ def review_classes(
|
||||
3a. If no class errors: validate fractions for ALL lines.
|
||||
3b. If class errors exist: add a CLASE error per invalid line and validate
|
||||
fractions only for those lines.
|
||||
4. If the invoice has not been reviewed by the company, flag lines whose
|
||||
4. If invoice logistics does not mark equipment_reviewed, flag lines whose
|
||||
class requires physical review (Class.physical_review == 1).
|
||||
"""
|
||||
# 1. Lines whose class is not assigned / not found in the catalog
|
||||
@@ -178,7 +178,7 @@ def review_classes(
|
||||
_validate_line_fraction(db, line, errors)
|
||||
|
||||
# 4. Physical review check
|
||||
if not invoice.compliance_mx.was_reviewed_by_company:
|
||||
if not (invoice.logistics and invoice.logistics.equipment_reviewed):
|
||||
review_required_lines = (
|
||||
db.query(LineItem)
|
||||
.join(Class, LineItem.class_id == Class.id)
|
||||
@@ -201,7 +201,7 @@ def review_classes(
|
||||
),
|
||||
solution=[
|
||||
f"Revisar el Equipo de la Partida: {line.line_number} "
|
||||
"y Asignar Como Revisado a Nivel Factura."
|
||||
"y marcar Equipo revisado en Continuación (logística) a nivel factura."
|
||||
],
|
||||
code="CLASE",
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@ Carga de conjuntos FK para validación de import CSV de transportistas.
|
||||
Clarion: GTransportista (ClaveTrans), GPaises (Pais_Ame), GEstados (Descripcion), relación Estado-País.
|
||||
"""
|
||||
from typing import Set, Tuple, Optional
|
||||
from sqlalchemy.orm import Session
|
||||
import logging
|
||||
|
||||
from core.database import CoreSessionLocal
|
||||
@@ -13,6 +14,7 @@ logger = logging.getLogger(__name__)
|
||||
def load_transportistas_fk_sets(
|
||||
tenant_id: Optional[int] = None,
|
||||
company_id: Optional[int] = None,
|
||||
db: Optional[Session] = None,
|
||||
) -> Tuple[
|
||||
Set[str],
|
||||
Set[str],
|
||||
@@ -32,50 +34,56 @@ def load_transportistas_fk_sets(
|
||||
state_descriptions_upper: Set[str] = set()
|
||||
state_country_set: Set[Tuple[str, str]] = set()
|
||||
|
||||
try:
|
||||
with CoreSessionLocal() as session:
|
||||
from api.v1.modules.a76.transportation.transporters.models import Transporter
|
||||
from api.v1.modules.public.reference_data.countries.models import Country
|
||||
from api.v1.modules.public.reference_data.states.models import State
|
||||
def _load(session: Session):
|
||||
from api.v1.modules.a76.transportation.transporters.models import Transporter
|
||||
from api.v1.modules.public.reference_data.countries.models import Country
|
||||
from api.v1.modules.public.reference_data.states.models import State
|
||||
|
||||
if tenant_id is not None and company_id is not None:
|
||||
for row in (
|
||||
session.query(Transporter.transporter_key)
|
||||
.filter(
|
||||
Transporter.tenant_id == tenant_id,
|
||||
Transporter.company_id == company_id,
|
||||
)
|
||||
.all()
|
||||
):
|
||||
if row[0] and (row[0] or "").strip():
|
||||
existing_transporter_keys.add((row[0] or "").strip().upper())
|
||||
|
||||
for row in session.query(Country.ame_key).all():
|
||||
if row[0]:
|
||||
valid_country_ame.add((row[0] or "").strip().upper())
|
||||
|
||||
for state in session.query(State).all():
|
||||
country = (
|
||||
session.query(Country)
|
||||
.filter(Country.m3_key == state.m3_key)
|
||||
.first()
|
||||
if tenant_id is not None and company_id is not None:
|
||||
for row in (
|
||||
session.query(Transporter.transporter_key)
|
||||
.filter(
|
||||
Transporter.tenant_id == tenant_id,
|
||||
Transporter.company_id == company_id,
|
||||
)
|
||||
ame = None
|
||||
if country and (country.ame_key or "").strip():
|
||||
ame = (country.ame_key or "").strip().upper()
|
||||
.all()
|
||||
):
|
||||
if row[0] and (row[0] or "").strip():
|
||||
existing_transporter_keys.add((row[0] or "").strip().upper())
|
||||
|
||||
desc = (state.description or "").strip()
|
||||
if desc:
|
||||
state_descriptions_upper.add(desc.upper())
|
||||
if ame:
|
||||
state_country_set.add((ame, desc.upper()))
|
||||
for row in session.query(Country.ame_key).all():
|
||||
if row[0]:
|
||||
valid_country_ame.add((row[0] or "").strip().upper())
|
||||
|
||||
mex_key = (state.mex_key or "").strip()
|
||||
if mex_key:
|
||||
mk = mex_key.upper()
|
||||
state_descriptions_upper.add(mk)
|
||||
if ame:
|
||||
state_country_set.add((ame, mk))
|
||||
for state in session.query(State).all():
|
||||
country = (
|
||||
session.query(Country)
|
||||
.filter(Country.m3_key == state.m3_key)
|
||||
.first()
|
||||
)
|
||||
ame = None
|
||||
if country and (country.ame_key or "").strip():
|
||||
ame = (country.ame_key or "").strip().upper()
|
||||
|
||||
desc = (state.description or "").strip()
|
||||
if desc:
|
||||
state_descriptions_upper.add(desc.upper())
|
||||
if ame:
|
||||
state_country_set.add((ame, desc.upper()))
|
||||
|
||||
mex_key = (state.mex_key or "").strip()
|
||||
if mex_key:
|
||||
mk = mex_key.upper()
|
||||
state_descriptions_upper.add(mk)
|
||||
if ame:
|
||||
state_country_set.add((ame, mk))
|
||||
|
||||
try:
|
||||
if db:
|
||||
_load(db)
|
||||
else:
|
||||
with CoreSessionLocal() as session:
|
||||
_load(session)
|
||||
|
||||
except Exception as e:
|
||||
logger.warning("Transportistas import: could not load FK sets: %s", e)
|
||||
|
||||
@@ -37,24 +37,31 @@ def validate_row_transporter(
|
||||
clave = (row.get("CLAVE TRANSPORTISTA") or "").strip().upper()
|
||||
use_partial = actualizar and bool(clave and clave in existing)
|
||||
|
||||
if not use_partial and clave and clave in existing:
|
||||
errors.append({
|
||||
"line": line_num,
|
||||
"col": "CLAVE TRANSPORTISTA",
|
||||
"msg": f"La clave '{row.get('CLAVE TRANSPORTISTA')}' ya existe en el catálogo."
|
||||
})
|
||||
|
||||
if use_partial:
|
||||
errors.extend(
|
||||
valida_parcial_transportistas(
|
||||
row,
|
||||
line_num,
|
||||
valid_country_ame=valid_country_ame,
|
||||
state_descriptions_upper=state_descriptions_upper,
|
||||
state_country_set=state_country_set,
|
||||
row,
|
||||
line_num,
|
||||
valid_country_ame=valid_country_ame,
|
||||
state_descriptions_upper=state_descriptions_upper,
|
||||
state_country_set=state_country_set,
|
||||
)
|
||||
)
|
||||
else:
|
||||
errors.extend(
|
||||
valida_toda_transportistas(
|
||||
row,
|
||||
line_num,
|
||||
valid_country_ame=valid_country_ame,
|
||||
state_descriptions_upper=state_descriptions_upper,
|
||||
state_country_set=state_country_set,
|
||||
row,
|
||||
line_num,
|
||||
valid_country_ame=valid_country_ame,
|
||||
state_descriptions_upper=state_descriptions_upper,
|
||||
state_country_set=state_country_set,
|
||||
)
|
||||
)
|
||||
return errors
|
||||
|
||||
@@ -277,6 +277,7 @@ def transporter_model_to_row(t) -> Dict[str, Any]:
|
||||
|
||||
|
||||
def validate_transporter_row_for_api(
|
||||
db: Session,
|
||||
tenant_id: int,
|
||||
company_id: int,
|
||||
row: Dict[str, Any],
|
||||
@@ -292,7 +293,7 @@ def validate_transporter_row_for_api(
|
||||
valid_country_ame,
|
||||
state_descriptions_upper,
|
||||
state_country_set,
|
||||
) = load_transportistas_fk_sets(tenant_id, company_id)
|
||||
) = load_transportistas_fk_sets(tenant_id, company_id, db=db)
|
||||
|
||||
clave = (row.get("CLAVE TRANSPORTISTA") or "").strip().upper()
|
||||
# existing set from loader is uppercased keys for this company
|
||||
|
||||
@@ -104,6 +104,7 @@ class TransporterService:
|
||||
"""Create a new transporter"""
|
||||
data = transporter_data.model_dump()
|
||||
validate_transporter_row_for_api(
|
||||
db,
|
||||
tenant_id,
|
||||
company_id,
|
||||
transporter_fields_to_csv_row(data),
|
||||
@@ -163,6 +164,7 @@ class TransporterService:
|
||||
}
|
||||
merged.update(update_data)
|
||||
validate_transporter_row_for_api(
|
||||
db,
|
||||
tenant_id,
|
||||
company_id,
|
||||
transporter_fields_to_csv_row(merged),
|
||||
|
||||
Reference in New Issue
Block a user