feature/layouts-csv-refact

This commit is contained in:
hreyes
2026-03-03 16:45:12 -07:00
parent 973298ccd9
commit 4c781b460a
81 changed files with 151 additions and 97 deletions

View File

@@ -5,7 +5,7 @@ Mismo patrón que parts y classes: upload → scan → status → commit.
from fastapi import APIRouter
from .imports.routes import router as imports_router
from api.v1.modules.a76.layouts_csv.boms.routes import router as imports_router
router = APIRouter()

View File

@@ -12,7 +12,7 @@ from api.v1.common.tenant_crud_routes import TenantCRUDRoutes, validate_access_t
from .dto import ClassCreateDTO, ClassCreateDTOFA, ClassResponseDTO, ClassResponseDTOFA, ClassUpdateDTO, ClassWithFADataResponse
from .service import ClassService
from .imports.routes import router as imports_router
from api.v1.modules.a76.layouts_csv.classes.routes import router as imports_router
# Create a new router for custom endpoints
router = APIRouter()

View File

@@ -20,7 +20,7 @@ from .dto import (
)
from .service import ClientProviderService
from .models import ClientProvider
from .imports.routes import router as imports_router
from api.v1.modules.a76.layouts_csv.clients_and_providers.routes import router as imports_router
# Create main router to add custom endpoints
router = APIRouter(prefix="/clients-providers")

View File

@@ -7,35 +7,35 @@ import io
from typing import Dict, List, Optional
# Importar configs de cada módulo
from api.v1.modules.a76.imports.template_config import (
from api.v1.modules.a76.layouts_csv.facturas.template_config import (
TEMPLATE_COLUMNS as IMPORTS_TEMPLATE_COLUMNS,
_resolve_template_columns as resolve_imports_template,
)
from api.v1.modules.a76.parts.imports.template_config import TEMPLATE_COLUMNS as PARTS_TEMPLATE_COLUMNS
from api.v1.modules.a76.boms.imports.template_config import TEMPLATE_COLUMNS as BOMS_TEMPLATE_COLUMNS
from api.v1.modules.a76.classes.imports.template_config import TEMPLATE_COLUMNS as CLASSES_TEMPLATE_COLUMNS
from api.v1.modules.a76.customs_brokers.imports.template_config import (
from api.v1.modules.a76.layouts_csv.parts.template_config import TEMPLATE_COLUMNS as PARTS_TEMPLATE_COLUMNS
from api.v1.modules.a76.layouts_csv.boms.template_config import TEMPLATE_COLUMNS as BOMS_TEMPLATE_COLUMNS
from api.v1.modules.a76.layouts_csv.classes.template_config import TEMPLATE_COLUMNS as CLASSES_TEMPLATE_COLUMNS
from api.v1.modules.a76.layouts_csv.customs_brokers.template_config import (
TEMPLATE_COLUMNS as CUSTOMS_BROKERS_TEMPLATE_COLUMNS,
)
from api.v1.modules.a76.clients_and_providers.imports.template_config import (
from api.v1.modules.a76.layouts_csv.clients_and_providers.template_config import (
TEMPLATE_COLUMNS as CLIENTS_PROVIDERS_TEMPLATE_COLUMNS,
)
from api.v1.modules.a76.general_catalogs.exchange_rate.imports.template_config import (
from api.v1.modules.a76.layouts_csv.exchange_rate.template_config import (
TEMPLATE_COLUMNS as EXCHANGE_RATE_TEMPLATE_COLUMNS,
)
from api.v1.modules.a76.general_catalogs.fractions.us_tariff_fractions.imports.template_config import (
from api.v1.modules.a76.layouts_csv.us_tariff_fractions.template_config import (
TEMPLATE_COLUMNS as US_TARIFF_FRACTIONS_TEMPLATE_COLUMNS,
)
from api.v1.modules.a76.pedmientos.imports.template_config import (
from api.v1.modules.a76.layouts_csv.pedmientos.template_config import (
TEMPLATE_COLUMNS as PEDIMENTOS_TEMPLATE_COLUMNS,
)
from api.v1.modules.a76.transportation.vehicles.imports.template_config import (
from api.v1.modules.a76.layouts_csv.vehicles.template_config import (
TEMPLATE_COLUMNS as VEHICLES_TEMPLATE_COLUMNS,
)
from api.v1.modules.a76.transportation.drivers.imports.template_config import (
from api.v1.modules.a76.layouts_csv.drivers.template_config import (
TEMPLATE_COLUMNS as DRIVERS_TEMPLATE_COLUMNS,
)
from api.v1.modules.a76.transportation.trailers.imports.template_config import (
from api.v1.modules.a76.layouts_csv.trailers.template_config import (
TEMPLATE_COLUMNS as TRAILERS_TEMPLATE_COLUMNS,
)

View File

@@ -1,2 +0,0 @@
# CSV import flow for Agentes Aduanales (Customs Brokers).
# Replicates the same two-phase flow as a76.imports: upload → scan → waiting_confirmation → commit.

View File

@@ -7,7 +7,7 @@ from core.security import get_current_user, validate_access_to_resource
from api.v1.common.tenant_crud_routes import TenantCRUDRoutes
from . import dto, services
from .imports.routes import router as imports_router
from ..layouts_csv.customs_brokers.routes import router as imports_router
router = APIRouter()

View File

@@ -35,7 +35,7 @@ from fastapi import APIRouter
custom_router = APIRouter(prefix="/exchange-rate", tags=[])
# CSV import: add to custom_router BEFORE including it in master, so /exchange-rate/imports/* is registered
from .imports.routes import router as imports_router
from api.v1.modules.a76.layouts_csv.exchange_rate.routes import router as imports_router
custom_router.include_router(imports_router, prefix="/imports", tags=["exchange_rate / csv_import"])
@custom_router.get("/test-ping")

View File

@@ -31,7 +31,7 @@ crud_router = TenantCRUDRoutes(
)
# Master router with prefix so all routes live under /us-tariff-fractions
from .imports.routes import router as imports_router
from api.v1.modules.a76.layouts_csv.us_tariff_fractions.routes import router as imports_router
main_router = APIRouter(prefix="/us-tariff-fractions", tags=["a76 / general catalogs / us tariff fractions"])
main_router.include_router(imports_router, prefix="/imports", tags=["us_tariff_fractions / csv_import"])
main_router.include_router(crud_router.router)

View File

@@ -0,0 +1 @@
# Lógica centralizada de cargas por CSV (routes, tasks, validaciones, template_config por proceso)

View File

@@ -14,6 +14,7 @@ from typing import Dict, Any
from core.celery_app import celery_app
from core.database import get_core_db
from core.paths import layout_path
from core.security import get_current_user, validate_access_to_resource
from .schemas import ImportJobResponse
@@ -78,7 +79,7 @@ async def upload_import_file(
raise HTTPException(status_code=500, detail="No se pudo encolar el archivo.")
try:
upload_dir = os.path.join(os.getcwd(), "uploads", "temp")
upload_dir = layout_path("imports", "temp")
os.makedirs(upload_dir, exist_ok=True)
with open(os.path.join(upload_dir, f"bom_{job_id}.csv"), "wb") as f:
f.write(contents)

View File

@@ -15,6 +15,7 @@ from typing import Dict, Any, Optional, List, Set
from core.celery_app import celery_app
from core.database import CoreSessionLocal
from core.paths import layout_path
from .template_config import row_from_template
@@ -33,7 +34,7 @@ def _get_redis():
def _worker_upload_dir() -> str:
return os.path.join(os.getcwd(), "uploads", "temp")
return layout_path("imports", "temp")
def _ensure_worker_has_file_from_redis(job_id: str) -> Optional[str]:
@@ -162,7 +163,7 @@ def scan_file(self, job_id: str, config: str = None):
return {"status": "failed", "error": "Archivo no encontrado (expirado o no subido). Sube de nuevo."}
_ensure_worker_has_meta_from_redis(job_id, file_path)
error_dir = os.path.join(os.path.dirname(file_path).replace("temp", "errors"), "")
error_dir = layout_path("imports", "errors")
os.makedirs(error_dir, exist_ok=True)
error_path = os.path.join(error_dir, f"bom_{job_id}.jsonl")
@@ -306,8 +307,7 @@ def insert_valid_rows(self, job_id: str):
else:
_ensure_worker_has_meta_from_redis(job_id, file_path)
base_dir = os.path.dirname(file_path)
error_dir = base_dir.replace("temp", "errors")
error_dir = layout_path("imports", "errors")
error_path = os.path.join(error_dir, f"bom_{job_id}.jsonl")
error_lines = set()

View File

@@ -14,6 +14,7 @@ from typing import Dict, Any
from core.celery_app import celery_app
from core.database import get_core_db
from core.paths import layout_path
from core.security import get_current_user, validate_access_to_resource
from .schemas import ImportJobResponse
@@ -78,7 +79,7 @@ async def upload_import_file(
raise HTTPException(status_code=500, detail="No se pudo encolar el archivo.")
try:
upload_dir = os.path.join(os.getcwd(), "uploads", "temp")
upload_dir = layout_path("imports", "temp")
os.makedirs(upload_dir, exist_ok=True)
with open(os.path.join(upload_dir, f"cls_{job_id}.csv"), "wb") as f:
f.write(contents)

View File

@@ -13,6 +13,7 @@ from typing import Dict, Any, Optional, List, Set
from core.celery_app import celery_app
from core.database import CoreSessionLocal
from core.paths import layout_path
from .template_config import row_from_template
@@ -31,7 +32,7 @@ def _get_redis():
def _worker_upload_dir() -> str:
return os.path.join(os.getcwd(), "uploads", "temp")
return layout_path("imports", "temp")
def _ensure_worker_has_file_from_redis(job_id: str) -> Optional[str]:
@@ -156,7 +157,7 @@ def scan_file(self, job_id: str, config: str = None):
return {"status": "failed", "error": "Archivo no encontrado (expirado o no subido). Sube de nuevo."}
_ensure_worker_has_meta_from_redis(job_id, file_path)
error_dir = os.path.join(os.path.dirname(file_path).replace("temp", "errors"), "")
error_dir = layout_path("imports", "errors")
os.makedirs(error_dir, exist_ok=True)
error_path = os.path.join(error_dir, f"cls_{job_id}.jsonl")
@@ -310,8 +311,7 @@ def insert_valid_rows(self, job_id: str):
else:
_ensure_worker_has_meta_from_redis(job_id, file_path)
base_dir = os.path.dirname(file_path)
error_dir = base_dir.replace("temp", "errors")
error_dir = layout_path("imports", "errors")
error_path = os.path.join(error_dir, f"cls_{job_id}.jsonl")
error_lines = set()

View File

@@ -14,6 +14,7 @@ from typing import Dict, Any
from core.celery_app import celery_app
from core.database import get_core_db
from core.paths import layout_path
from core.security import get_current_user, validate_access_to_resource
from .schemas import ImportJobResponse
@@ -81,7 +82,7 @@ async def upload_import_file(
raise HTTPException(status_code=500, detail="No se pudo encolar el archivo.")
try:
upload_dir = os.path.join(os.getcwd(), "uploads", "temp")
upload_dir = layout_path("imports", "temp")
os.makedirs(upload_dir, exist_ok=True)
with open(os.path.join(upload_dir, f"cp_{job_id}.csv"), "wb") as f:
f.write(contents)

View File

@@ -13,6 +13,7 @@ from typing import Dict, Any, Optional, List
from core.celery_app import celery_app
from core.database import CoreSessionLocal
from core.paths import layout_path
from .template_config import row_from_template
from api.v1.modules.a76.clients_and_providers.models import (
@@ -37,7 +38,7 @@ def _get_redis():
def _worker_upload_dir() -> str:
return os.path.join(os.getcwd(), "uploads", "temp")
return layout_path("imports", "temp")
def _ensure_worker_has_file_from_redis(job_id: str) -> Optional[str]:
@@ -165,7 +166,7 @@ def scan_file(self, job_id: str, config: str = None):
return {"status": "failed", "error": "Archivo no encontrado (expirado o no subido). Sube de nuevo."}
_ensure_worker_has_meta_from_redis(job_id, file_path)
error_dir = os.path.join(os.path.dirname(file_path).replace("temp", "errors"), "")
error_dir = layout_path("imports", "errors")
os.makedirs(error_dir, exist_ok=True)
error_path = os.path.join(error_dir, f"cp_{job_id}.jsonl")
@@ -290,8 +291,7 @@ def insert_valid_rows(self, job_id: str):
else:
_ensure_worker_has_meta_from_redis(job_id, file_path)
base_dir = os.path.dirname(file_path)
error_dir = base_dir.replace("temp", "errors")
error_dir = layout_path("imports", "errors")
error_path = os.path.join(error_dir, f"cp_{job_id}.jsonl")
error_lines = set()

View File

@@ -0,0 +1 @@
# layouts_csv.customs_brokers

View File

@@ -14,6 +14,7 @@ from typing import Dict, Any
from core.celery_app import celery_app
from core.database import get_core_db
from core.paths import layout_path
from core.security import get_current_user, validate_access_to_resource
from .schemas import ImportJobResponse
@@ -81,7 +82,7 @@ async def upload_import_file(
raise HTTPException(status_code=500, detail="No se pudo encolar el archivo.")
try:
upload_dir = os.path.join(os.getcwd(), "uploads", "temp")
upload_dir = layout_path("imports", "temp")
os.makedirs(upload_dir, exist_ok=True)
with open(os.path.join(upload_dir, f"cb_{job_id}.csv"), "wb") as f:
f.write(contents)

View File

@@ -13,6 +13,7 @@ from typing import Dict, Any, Optional, List
from core.celery_app import celery_app
from core.database import CoreSessionLocal
from core.paths import layout_path
from .template_config import row_from_template
@@ -32,7 +33,7 @@ def _get_redis():
def _worker_upload_dir() -> str:
return os.path.join(os.getcwd(), "uploads", "temp")
return layout_path("imports", "temp")
def _ensure_worker_has_file_from_redis(job_id: str) -> Optional[str]:
@@ -120,7 +121,7 @@ def scan_file(self, job_id: str, config: str = None):
return {"status": "failed", "error": "Archivo no encontrado (expirado o no subido). Sube de nuevo."}
_ensure_worker_has_meta_from_redis(job_id, file_path)
error_dir = os.path.join(os.path.dirname(file_path).replace("temp", "errors"), "")
error_dir = layout_path("imports", "errors")
os.makedirs(error_dir, exist_ok=True)
error_path = os.path.join(error_dir, f"cb_{job_id}.jsonl")
@@ -245,8 +246,7 @@ def insert_valid_rows(self, job_id: str):
else:
_ensure_worker_has_meta_from_redis(job_id, file_path)
base_dir = os.path.dirname(file_path)
error_dir = base_dir.replace("temp", "errors")
error_dir = layout_path("imports", "errors")
error_path = os.path.join(error_dir, f"cb_{job_id}.jsonl")
error_lines = set()

View File

@@ -15,6 +15,7 @@ from typing import Dict, Any
from core.celery_app import celery_app
from core.database import get_core_db
from core.paths import layout_path
from core.security import get_current_user, validate_access_to_resource
from .schemas import ImportJobResponse
@@ -81,7 +82,7 @@ async def upload_import_file(
raise HTTPException(status_code=500, detail="No se pudo encolar el archivo.")
try:
upload_dir = os.path.join(os.getcwd(), "uploads", "temp")
upload_dir = layout_path("imports", "temp")
os.makedirs(upload_dir, exist_ok=True)
with open(os.path.join(upload_dir, f"drv_{job_id}.csv"), "wb") as f:
f.write(contents)

View File

@@ -13,6 +13,7 @@ from typing import Dict, Any, Optional, List
from core.celery_app import celery_app
from core.database import CoreSessionLocal
from core.paths import layout_path
from .template_config import row_from_template
@@ -32,7 +33,7 @@ def _get_redis():
def _worker_upload_dir() -> str:
return os.path.join(os.getcwd(), "uploads", "temp")
return layout_path("imports", "temp")
def _ensure_worker_has_file_from_redis(job_id: str) -> Optional[str]:
@@ -281,7 +282,7 @@ def _do_scan(job_id: str, progress_callback: Optional[Any] = None) -> Dict[str,
return {"status": "failed", "error": "Archivo no encontrado (expirado o no subido). Sube de nuevo."}
_ensure_worker_has_meta_from_redis(job_id, file_path)
error_dir = os.path.join(os.path.dirname(file_path).replace("temp", "errors"), "")
error_dir = layout_path("imports", "errors")
os.makedirs(error_dir, exist_ok=True)
error_path = os.path.join(error_dir, f"drv_{job_id}.jsonl")
@@ -429,8 +430,7 @@ def _do_commit(job_id: str) -> Dict[str, Any]:
else:
_ensure_worker_has_meta_from_redis(job_id, file_path)
base_dir = os.path.dirname(file_path)
error_dir = base_dir.replace("temp", "errors")
error_dir = layout_path("imports", "errors")
error_path = os.path.join(error_dir, f"drv_{job_id}.jsonl")
error_lines = set()

View File

@@ -14,6 +14,7 @@ from typing import Dict, Any
from core.celery_app import celery_app
from core.database import get_core_db
from core.paths import layout_path
from core.security import get_current_user, validate_access_to_resource
from .schemas import ImportJobResponse
@@ -81,7 +82,7 @@ async def upload_import_file(
raise HTTPException(status_code=500, detail="No se pudo encolar el archivo.")
try:
upload_dir = os.path.join(os.getcwd(), "uploads", "temp")
upload_dir = layout_path("imports", "temp")
os.makedirs(upload_dir, exist_ok=True)
with open(os.path.join(upload_dir, f"er_{job_id}.csv"), "wb") as f:
f.write(contents)

View File

@@ -15,6 +15,7 @@ from typing import Dict, Any, Optional, List
from core.celery_app import celery_app
from core.database import CoreSessionLocal
from core.paths import layout_path
from .template_config import row_from_template
@@ -36,7 +37,7 @@ def _get_redis():
def _worker_upload_dir() -> str:
return os.path.join(os.getcwd(), "uploads", "temp")
return layout_path("imports", "temp")
def _ensure_worker_has_file_from_redis(job_id: str) -> Optional[str]:
@@ -150,7 +151,7 @@ def scan_file(self, job_id: str, config: str = None):
return {"status": "failed", "error": "Archivo no encontrado (expirado o no subido). Sube de nuevo."}
_ensure_worker_has_meta_from_redis(job_id, file_path)
error_dir = os.path.join(os.path.dirname(file_path).replace("temp", "errors"), "")
error_dir = layout_path("imports", "errors")
os.makedirs(error_dir, exist_ok=True)
error_path = os.path.join(error_dir, f"er_{job_id}.jsonl")
@@ -274,8 +275,7 @@ def insert_valid_rows(self, job_id: str):
else:
_ensure_worker_has_meta_from_redis(job_id, file_path)
base_dir = os.path.dirname(file_path)
error_dir = base_dir.replace("temp", "errors")
error_dir = layout_path("imports", "errors")
error_path = os.path.join(error_dir, f"er_{job_id}.jsonl")
error_lines = set()

View File

@@ -11,6 +11,7 @@ from typing import Optional, Literal, Dict, Any
from core.celery_app import celery_app
from core.config import settings
from core.database import get_core_db
from core.paths import layout_path
from core.security import get_current_user, validate_access_to_resource
from .tasks import (
@@ -88,7 +89,7 @@ async def upload_import_file(
# Optional: also write to local disk (e.g. for same-machine worker or debugging)
try:
upload_dir = os.path.join(os.getcwd(), "uploads", "temp")
upload_dir = layout_path("imports", "temp")
os.makedirs(upload_dir, exist_ok=True)
file_path = os.path.join(upload_dir, f"{job_id}.csv")
meta_path = os.path.join(upload_dir, f"{job_id}.meta.json")

View File

@@ -11,6 +11,7 @@ from typing import Dict, Any, Optional, List
from core.celery_app import celery_app
from core.database import CoreSessionLocal
from core.paths import layout_path
from .template_config import row_from_template
# Models are imported inside tasks to avoid circular dependencies and mapper initialization issues in the API process
@@ -37,7 +38,7 @@ def _get_redis():
def _worker_upload_dir() -> str:
"""Directory on the worker for temp CSV and meta (same structure as API, but local to worker)."""
return os.path.join(os.getcwd(), "uploads", "temp")
return layout_path("imports", "temp")
def _ensure_worker_has_file_from_redis(job_id: str) -> Optional[str]:
@@ -189,8 +190,9 @@ def scan_file(self, job_id: str, model_target: str, config: str = None):
_ensure_worker_has_meta_from_redis(job_id, file_path)
# 2. Setup Error Log
error_path = file_path.replace("temp", "errors").replace(".csv", ".jsonl")
os.makedirs(os.path.dirname(error_path), exist_ok=True)
error_dir = layout_path("imports", "errors")
os.makedirs(error_dir, exist_ok=True)
error_path = os.path.join(error_dir, f"{job_id}.jsonl")
total_rows = 0
error_count = 0
@@ -805,7 +807,8 @@ def insert_valid_rows(self, job_id: str, model_target: str):
from api.v1.modules.a76.items.line_descriptions.models import LineDescription
from api.v1.modules.a76.parts.models import Part
error_path = file_path.replace("temp", "errors").replace(".csv", ".jsonl")
error_dir = layout_path("imports", "errors")
error_path = os.path.join(error_dir, f"{job_id}.jsonl")
# 1. Load Error Line Numbers (from Redis if scan ran on another worker, else from file)
error_lines = set()

View File

@@ -14,6 +14,7 @@ from typing import Dict, Any
from core.celery_app import celery_app
from core.database import get_core_db
from core.paths import layout_path
from core.security import get_current_user, validate_access_to_resource
from .schemas import ImportJobResponse
@@ -78,7 +79,7 @@ async def upload_import_file(
raise HTTPException(status_code=500, detail="No se pudo encolar el archivo.")
try:
upload_dir = os.path.join(os.getcwd(), "uploads", "temp")
upload_dir = layout_path("imports", "temp")
os.makedirs(upload_dir, exist_ok=True)
with open(os.path.join(upload_dir, f"part_{job_id}.csv"), "wb") as f:
f.write(contents)

View File

@@ -14,6 +14,7 @@ from typing import Dict, Any, Optional, List, Set
from core.celery_app import celery_app
from core.database import CoreSessionLocal
from core.paths import layout_path
from .template_config import row_from_template
@@ -32,7 +33,7 @@ def _get_redis():
def _worker_upload_dir() -> str:
return os.path.join(os.getcwd(), "uploads", "temp")
return layout_path("imports", "temp")
def _ensure_worker_has_file_from_redis(job_id: str) -> Optional[str]:
@@ -183,7 +184,7 @@ def scan_file(self, job_id: str, config: str = None):
return {"status": "failed", "error": "Archivo no encontrado (expirado o no subido). Sube de nuevo."}
_ensure_worker_has_meta_from_redis(job_id, file_path)
error_dir = os.path.join(os.path.dirname(file_path).replace("temp", "errors"), "")
error_dir = layout_path("imports", "errors")
os.makedirs(error_dir, exist_ok=True)
error_path = os.path.join(error_dir, f"part_{job_id}.jsonl")
@@ -368,8 +369,7 @@ def insert_valid_rows(self, job_id: str):
else:
_ensure_worker_has_meta_from_redis(job_id, file_path)
base_dir = os.path.dirname(file_path)
error_dir = base_dir.replace("temp", "errors")
error_dir = layout_path("imports", "errors")
error_path = os.path.join(error_dir, f"part_{job_id}.jsonl")
error_lines = set()

View File

@@ -14,6 +14,7 @@ from typing import Dict, Any
from core.celery_app import celery_app
from core.database import get_core_db
from core.paths import layout_path
from core.security import get_current_user, validate_access_to_resource
from .schemas import ImportJobResponse
@@ -81,7 +82,7 @@ async def upload_import_file(
raise HTTPException(status_code=500, detail="No se pudo encolar el archivo.")
try:
upload_dir = os.path.join(os.getcwd(), "uploads", "temp")
upload_dir = layout_path("imports", "temp")
os.makedirs(upload_dir, exist_ok=True)
with open(os.path.join(upload_dir, f"ped_{job_id}.csv"), "wb") as f:
f.write(contents)

View File

@@ -15,6 +15,7 @@ from typing import Dict, Any, Optional, List, Set
from core.celery_app import celery_app
from core.database import CoreSessionLocal
from core.paths import layout_path
from .template_config import row_from_template
@@ -34,7 +35,7 @@ def _get_redis():
def _worker_upload_dir() -> str:
return os.path.join(os.getcwd(), "uploads", "temp")
return layout_path("imports", "temp")
def _ensure_worker_has_file_from_redis(job_id: str) -> Optional[str]:
@@ -243,7 +244,7 @@ def scan_file(self, job_id: str, config: str = None):
return {"status": "failed", "error": "Archivo no encontrado (expirado o no subido). Sube de nuevo."}
_ensure_worker_has_meta_from_redis(job_id, file_path)
error_dir = os.path.join(os.path.dirname(file_path).replace("temp", "errors"), "")
error_dir = layout_path("imports", "errors")
os.makedirs(error_dir, exist_ok=True)
error_path = os.path.join(error_dir, f"ped_{job_id}.jsonl")
@@ -381,8 +382,7 @@ def insert_valid_rows(self, job_id: str):
else:
_ensure_worker_has_meta_from_redis(job_id, file_path)
base_dir = os.path.dirname(file_path)
error_dir = base_dir.replace("temp", "errors")
error_dir = layout_path("imports", "errors")
error_path = os.path.join(error_dir, f"ped_{job_id}.jsonl")
error_lines = set()

View File

@@ -15,6 +15,7 @@ from typing import Dict, Any
from core.celery_app import celery_app
from core.database import get_core_db
from core.paths import layout_path
from core.security import get_current_user, validate_access_to_resource
from .schemas import ImportJobResponse
@@ -81,7 +82,7 @@ async def upload_import_file(
raise HTTPException(status_code=500, detail="No se pudo encolar el archivo.")
try:
upload_dir = os.path.join(os.getcwd(), "uploads", "temp")
upload_dir = layout_path("imports", "temp")
os.makedirs(upload_dir, exist_ok=True)
with open(os.path.join(upload_dir, f"trl_{job_id}.csv"), "wb") as f:
f.write(contents)

View File

@@ -14,6 +14,7 @@ from typing import Dict, Any, Optional, List
from core.celery_app import celery_app
from core.database import CoreSessionLocal
from core.paths import layout_path
from .template_config import row_from_template
@@ -33,7 +34,7 @@ def _get_redis():
def _worker_upload_dir() -> str:
return os.path.join(os.getcwd(), "uploads", "temp")
return layout_path("imports", "temp")
def _ensure_worker_has_file_from_redis(job_id: str) -> Optional[str]:
@@ -180,7 +181,7 @@ def _do_scan(job_id: str, progress_callback: Optional[Any] = None) -> Dict[str,
return {"status": "failed", "error": "Archivo no encontrado (expirado o no subido). Sube de nuevo."}
_ensure_worker_has_meta_from_redis(job_id, file_path)
error_dir = os.path.join(os.path.dirname(file_path).replace("temp", "errors"), "")
error_dir = layout_path("imports", "errors")
os.makedirs(error_dir, exist_ok=True)
error_path = os.path.join(error_dir, f"trl_{job_id}.jsonl")
@@ -328,8 +329,7 @@ def _do_commit(job_id: str) -> Dict[str, Any]:
else:
_ensure_worker_has_meta_from_redis(job_id, file_path)
base_dir = os.path.dirname(file_path)
error_dir = base_dir.replace("temp", "errors")
error_dir = layout_path("imports", "errors")
error_path = os.path.join(error_dir, f"trl_{job_id}.jsonl")
error_lines = set()

View File

@@ -14,6 +14,7 @@ from typing import Dict, Any
from core.celery_app import celery_app
from core.database import get_core_db
from core.paths import layout_path
from core.security import get_current_user, validate_access_to_resource
from .schemas import ImportJobResponse
@@ -81,7 +82,7 @@ async def upload_import_file(
raise HTTPException(status_code=500, detail="No se pudo encolar el archivo.")
try:
upload_dir = os.path.join(os.getcwd(), "uploads", "temp")
upload_dir = layout_path("imports", "temp")
os.makedirs(upload_dir, exist_ok=True)
with open(os.path.join(upload_dir, f"fa_{job_id}.csv"), "wb") as f:
f.write(contents)

View File

@@ -14,6 +14,7 @@ from typing import Dict, Any, Optional, List
from core.celery_app import celery_app
from core.database import CoreSessionLocal
from core.paths import layout_path
from .template_config import row_from_template
@@ -34,7 +35,7 @@ def _get_redis():
def _worker_upload_dir() -> str:
return os.path.join(os.getcwd(), "uploads", "temp")
return layout_path("imports", "temp")
def _ensure_worker_has_file_from_redis(job_id: str) -> Optional[str]:
@@ -157,7 +158,7 @@ def scan_file(self, job_id: str, config: str = None):
return {"status": "failed", "error": "Archivo no encontrado (expirado o no subido). Sube de nuevo."}
_ensure_worker_has_meta_from_redis(job_id, file_path)
error_dir = os.path.join(os.path.dirname(file_path).replace("temp", "errors"), "")
error_dir = layout_path("imports", "errors")
os.makedirs(error_dir, exist_ok=True)
error_path = os.path.join(error_dir, f"fa_{job_id}.jsonl")
@@ -290,8 +291,7 @@ def insert_valid_rows(self, job_id: str):
else:
_ensure_worker_has_meta_from_redis(job_id, file_path)
base_dir = os.path.dirname(file_path)
error_dir = base_dir.replace("temp", "errors")
error_dir = layout_path("imports", "errors")
error_path = os.path.join(error_dir, f"fa_{job_id}.jsonl")
error_lines = set()

View File

@@ -15,6 +15,7 @@ from typing import Dict, Any
from core.celery_app import celery_app
from core.database import get_core_db
from core.paths import layout_path
from core.security import get_current_user, validate_access_to_resource
from .schemas import ImportJobResponse
@@ -81,7 +82,7 @@ async def upload_import_file(
raise HTTPException(status_code=500, detail="No se pudo encolar el archivo.")
try:
upload_dir = os.path.join(os.getcwd(), "uploads", "temp")
upload_dir = layout_path("imports", "temp")
os.makedirs(upload_dir, exist_ok=True)
with open(os.path.join(upload_dir, f"veh_{job_id}.csv"), "wb") as f:
f.write(contents)

View File

@@ -15,6 +15,7 @@ from typing import Dict, Any, Optional, List
from core.celery_app import celery_app
from core.database import CoreSessionLocal
from core.paths import layout_path
from .template_config import row_from_template
@@ -34,7 +35,7 @@ def _get_redis():
def _worker_upload_dir() -> str:
return os.path.join(os.getcwd(), "uploads", "temp")
return layout_path("imports", "temp")
def _ensure_worker_has_file_from_redis(job_id: str) -> Optional[str]:
@@ -213,7 +214,7 @@ def _do_scan(
return {"status": "failed", "error": "Archivo no encontrado (expirado o no subido). Sube de nuevo."}
_ensure_worker_has_meta_from_redis(job_id, file_path)
error_dir = os.path.join(os.path.dirname(file_path).replace("temp", "errors"), "")
error_dir = layout_path("imports", "errors")
os.makedirs(error_dir, exist_ok=True)
error_path = os.path.join(error_dir, f"veh_{job_id}.jsonl")
@@ -404,8 +405,7 @@ def _do_commit(job_id: str) -> Dict[str, Any]:
else:
_ensure_worker_has_meta_from_redis(job_id, file_path)
base_dir = os.path.dirname(file_path)
error_dir = base_dir.replace("temp", "errors")
error_dir = layout_path("imports", "errors")
error_path = os.path.join(error_dir, f"veh_{job_id}.jsonl")
error_lines = set()

View File

@@ -8,7 +8,7 @@ from api.v1.common.tenant_crud_routes import TenantCRUDRoutes
from .dto import PartCreateDTO, PartResponseDTO, PartUpdateDTO
from .service import PartService
from .imports.routes import router as imports_router
from api.v1.modules.a76.layouts_csv.parts.routes import router as imports_router
router = APIRouter()

View File

@@ -31,7 +31,7 @@ from .routes.pedimento_rectification_origin import (
from .routes.pedimento_transport_means import router as pedimento_transport_means_router
from .routes.pedimento_validation import router as pedimento_validation_router
from .routes.pedimentos import router as pedimentos_router
from .imports.routes import router as pedimentos_imports_router
from api.v1.modules.a76.layouts_csv.pedmientos.routes import router as pedimentos_imports_router
router = APIRouter()

View File

@@ -14,7 +14,7 @@ from .items.routes import router as items_router
from .classes import router as classes_router
from .clients_and_providers import router as client_and_provider_router
from .imports.routes import router as imports_router
from .layouts_csv.facturas.routes import router as imports_router
from .csv_templates.routes import router as csv_templates_router
from .invoice_settings.routes import router as invoice_settings_router
from .item_presets.routes import router as item_presets_router

View File

@@ -8,7 +8,7 @@ from sqlalchemy.orm import Session
from .dto import DriverCreateDTO, DriverResponseDTO
from .models import Driver
from .services import DriverService
from .imports.routes import router as imports_router
from api.v1.modules.a76.layouts_csv.drivers.routes import router as imports_router
router = APIRouter(prefix="/drivers")

View File

@@ -4,7 +4,7 @@ from api.v1.common.tenant_crud_routes import TenantCRUDRoutes
from .dto import TrailerCreateDTO, TrailerResponseDTO, TrailerUpdateDTO
from .services import TrailerService
from .imports.routes import router as imports_router
from api.v1.modules.a76.layouts_csv.trailers.routes import router as imports_router
# Main router: trailers CRUD + CSV imports
router = APIRouter()

View File

@@ -4,7 +4,7 @@ from api.v1.common.tenant_crud_routes import TenantCRUDRoutes
from .dto import VehicleCreateDTO, VehicleResponseDTO, VehicleUpdateDTO
from .services import VehicleService
from .imports.routes import router as imports_router
from api.v1.modules.a76.layouts_csv.vehicles.routes import router as imports_router
# Main router: vehicles CRUD + CSV imports
router = APIRouter()