feature/layouts-csv-refact
This commit is contained in:
@@ -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()
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
1
backend/api/v1/modules/a76/layouts_csv/__init__.py
Normal file
1
backend/api/v1/modules/a76/layouts_csv/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# Lógica centralizada de cargas por CSV (routes, tasks, validaciones, template_config por proceso)
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
@@ -0,0 +1 @@
|
||||
# layouts_csv.customs_brokers
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
@@ -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")
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user