full adjustment

This commit is contained in:
2026-04-09 14:03:06 -07:00
parent 75ecb00a94
commit 092a7048d8
21 changed files with 416 additions and 118 deletions

View File

@@ -16,12 +16,12 @@ class EDOS(Base):
__tablename__="edos"
id = Column(Integer, primary_key=True, nullable=False)
numero = Column(Integer, nullable=False)
numero = Column(String(25), nullable=False)
razon_social = Column(String(100), nullable=False)
situacion = Column(SQLEnum(Situacion, name="situcion", create_type=False), nullable=False)
numero_definitivo = Column(String(60), nullable=False)
fecha_definitivo = Column(Date, nullable=True )
publicaccion_sat = Column(Date, nullable=True)
publicacion_sat = Column(Date, nullable=True)
numero_def_dof = Column(String(100), nullable=True)
fecha_def_dof = Column(Date, nullable=True)
publicacion_dof = Column(Date, nullable=True)

View File

@@ -13,7 +13,7 @@ async def import_csv(data: Dict[str, Any] = Body(..., example={"url": "http://ex
csv_url = data.get('url')
dry_run = data.get('dry_run', True)
dry_run = data.get('dry_run', False)
max_rows = data.get('max_rows')
if not csv_url:
@@ -26,6 +26,7 @@ async def import_csv(data: Dict[str, Any] = Body(..., example={"url": "http://ex
)
try:
result = XMACSVService.process_csv_from_url(
csv_url= csv_url,
dry_run=dry_run,

View File

@@ -16,7 +16,7 @@ class EdosUpload(BaseModel):
situacion : Situacion
numero_definitivo : str
fecha_definitivo : date
publicaccion_sat : date
publicacion_sat : date
numero_def_dof : str
fecha_def_dof : date
publicacion_dof : date

View File

@@ -4,71 +4,95 @@ from typing import Optional
from fastapi import HTTPException
from app.modules.edos.models import EDOS
from app.modules.edos.schema import EdosResponse, EdosUpload, messageResponse
from app.helpers.csv_mapper import CSVMapper
from app.helpers.db_adapter import DBAdapter
from app.helpers.extractCsv import CSVExtractor
class XMACSVService:
""" Orquester"""
"""Orchestrator: extract, map, adapt pipeline"""
@staticmethod
def process_csv_from_url(
csv_url: str,
dry_run: bool = False,
max_rows: int = None
) -> dict:
""" flow download and parsing, filter and adapt"""
) -> dict:
"""Flow: download CSV, parse, map to schema, insert into database"""
try:
# X - EXTRACT
print(f"📥 Descargando CSV: {csv_url}")
# =========================================================
# X - EXTRACT: Download and parse CSV
# =========================================================
print(f"Downloading CSV: {csv_url}")
# ✅ Ahora download_csv retorna (content, encoding)
content, encoding = CSVExtractor.download_csv(csv_url)
print(f" ✅ Descargado {len(content)} bytes, encoding: {encoding}")
print(f" Downloaded {len(content)} bytes, encoding: {encoding}")
# Debug: show first lines
print("First 10 lines of CSV:")
lines = content.split('\n')
for i, line in enumerate(lines[:10]):
print(f"Line {i}: {repr(line[:200])}")
# Parsear CSV
# Parse CSV to raw rows
raw_rows = CSVExtractor.read_csv(content)
print(f" Parseadas {len(raw_rows)} filas")
print(f" Parsed {len(raw_rows)} rows")
if not raw_rows:
return {
'total_extracted': 0,
'total_mapped': 0,
'inserted': 0,
'errors': ['No se encontraron datos en el CSV']
'dry_run': dry_run,
'errors': ['No data found in CSV']
}
# Mostrar columnas encontradas
print(f" 📋 Columnas: {list(raw_rows[0].keys())}")
print(f" Columns: {list(raw_rows[0].keys())}")
# M - MAP (si tienes mapper)
# Por ahora, usar datos crudos
mapped_rows = raw_rows
# =========================================================
# M - MAP: Transform CSV rows to database schema
# =========================================================
mapped_rows = CSVMapper.map_rows(raw_rows)
print(f" Mapped {len(mapped_rows)} rows to database schema")
if max_rows:
mapped_rows = mapped_rows[:max_rows]
print(f" 🔒 Limitado a {max_rows} filas")
print(f" Limited to {max_rows} rows")
# =========================================================
# A - ADAPT: Insert into database
# =========================================================
inserted_count = 0
errors = []
# A - ADAPT
if not dry_run:
print(f" 💾 Insertando {len(mapped_rows)} filas en BD")
# Aquí iría la inserción en BD
print(f" Inserting {len(mapped_rows)} rows into database")
adapter = DBAdapter()
result = adapter.insert_filtered_data(mapped_rows)
inserted_count = result.get('inserted', 0)
errors = result.get('errors', [])
print(f" Inserted: {inserted_count}")
print(f" Duplicates skipped: {result.get('duplicates_skiped', 0)}")
if errors:
print(f" Errors: {len(errors)}")
else:
print(f" DRY RUN - No data inserted")
# =========================================================
# Return response
# =========================================================
return {
'total_extracted': len(raw_rows),
'total_mapped': len(mapped_rows),
'inserted': len(mapped_rows) if not dry_run else 0,
'inserted': inserted_count,
'dry_run': dry_run,
'columns': list(raw_rows[0].keys()) if raw_rows else [],
'sample': raw_rows[:2] if raw_rows else []
'sample': mapped_rows[:2] if mapped_rows else [],
'errors': errors[:10] if errors else [] # Limit errors in response
}
except Exception as e:
print(f"Error: {str(e)}")
print(f"Error: {str(e)}")
import traceback
traceback.print_exc()
raise
raise