From ff2df90dbe8f909a8f82f0ee7dd01d43f56d19e6 Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Fri, 9 Jan 2026 08:26:44 -0600 Subject: [PATCH 01/21] WIP: Guardando trabajo antes de actualizar con development --- backend/Dockerfile | 25 + .../importacion/facturas/mex/schemas.py | 78 ++ .../importacion/facturas/mex/service.py | 296 ++++++ .../reports/importacion/facturas/routes.py | 50 + .../importacion/facturas/tem/schemas.py | 0 .../importacion/facturas/tem/service.py | 0 .../facturas/templates/factura_mex_ver.html | 367 +++++++ .../facturas/templates/factura_tem_hor.html | 0 backend/requirements.txt | 3 + .../general_catalogs/ports/+page.svelte | 2 +- .../routes/dashboard/invoices/+page.svelte | 943 +++++++++--------- 11 files changed, 1315 insertions(+), 449 deletions(-) create mode 100644 backend/api/v1/modules/a76/reports/importacion/facturas/mex/schemas.py create mode 100644 backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py create mode 100644 backend/api/v1/modules/a76/reports/importacion/facturas/routes.py create mode 100644 backend/api/v1/modules/a76/reports/importacion/facturas/tem/schemas.py create mode 100644 backend/api/v1/modules/a76/reports/importacion/facturas/tem/service.py create mode 100644 backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_mex_ver.html create mode 100644 backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_tem_hor.html diff --git a/backend/Dockerfile b/backend/Dockerfile index cff9b109..89d5822d 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -9,6 +9,31 @@ RUN apt-get update && apt-get install -y \ curl \ && rm -rf /var/lib/apt/lists/* +# Instalar dependencias para wkhtmltopdf y reportes PDF +RUN apt-get update \ + && apt-get install -y \ + xvfb \ + fontconfig \ + fonts-dejavu-core \ + libfontconfig1 \ + libxrender1 \ + libxtst6 \ + libxi6 \ + libxrandr2 \ + ca-certificates \ + libjpeg62-turbo \ + libpng16-16 \ + && rm -rf /var/lib/apt/lists/* + +# Instalar wkhtmltopdf binario oficial con soporte para footers/headers +RUN curl -k -L -o /tmp/wkhtmltox.deb https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.bookworm_amd64.deb \ + && apt-get update \ + && apt-get install -y /tmp/wkhtmltox.deb \ + && rm /tmp/wkhtmltox.deb \ + && rm -rf /var/lib/apt/lists/* \ + && wkhtmltopdf --version + + # Copiar requirements COPY requirements.txt . diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/schemas.py b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/schemas.py new file mode 100644 index 00000000..a7e765e1 --- /dev/null +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/schemas.py @@ -0,0 +1,78 @@ +from decimal import Decimal +from typing import List, Optional, Union +from pydantic import BaseModel + +# Nota: Usamos Union[float, str] en los números para poder enviar +# strings formateados con comas (ej: "1,200.50") si lo deseamos, +# ya que tu HTML no tiene filtros de formato. + +class ClienteSchema(BaseModel): + header: str + nombre: str + direccion: str + num_exterior: str = "" + num_interior: str = "" + colonia: str = "" + codigo_postal: str + ciudad: str + estado: str + pais: str + tax_id: str + programa: str = "" + autorizacion: str = "" + +class FacturaSchema(BaseModel): + numero: str + fecha: str + tipo_cambio: float + moneda: str + # Campos de aduanas (Opcionales por si A76 aún no los tiene) + pedimento: str = "" + clave_pedimento: str = "" + remesa: str = "" + acuse_electronico: str = "" + agente_aduanal: str = "" + patente: str = "" + precinto: str = "" + regimen: str = "" + transportista: str = "" + scac: str = "" + caat: str = "" + incoterm: str = "" + transporte: str = "" + num_transporte: str = "" + placas: str = "" + aduana: str = "" + destino: str = "" + observaciones: str = "" + +class PartidaSchema(BaseModel): + numero_parte: str + descripcion: str + fraccion: str + origen: str + cantidad_importacion: Union[float, str] + unidad_medida: str + cantidad_bultos: int + clave_bultos: str + peso_neto: Union[float, str] + peso_bruto: Union[float, str] + valor_costo_unitario: Union[float, str] + valor_total: Union[float, str] + +class TotalesSchema(BaseModel): + cantidad_total: Union[float, str] + bultos_total: int + clave_bultos: str = "" + peso_neto_total: Union[float, str] + peso_bruto_total: Union[float, str] + valor_total_total: Union[float, str] + valor_total_dolares: Union[float, str] + +class FacturaImportacionCompleta(BaseModel): + cliente_proveedor: ClienteSchema + cliente_vendido: ClienteSchema + cliente_enviado: ClienteSchema + factura: FacturaSchema + partidas: List[PartidaSchema] + totales: TotalesSchema \ No newline at end of file diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py new file mode 100644 index 00000000..c188fe09 --- /dev/null +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py @@ -0,0 +1,296 @@ +import shutil +import pdfkit +from pathlib import Path +from decimal import Decimal +from typing import Tuple, List + +from jinja2 import Environment, FileSystemLoader, select_autoescape +from fastapi import HTTPException +from sqlalchemy.orm import Session + +# --- IMPORTACIONES DE TUS MODELOS (Asegúrate que las rutas sean correctas) --- +from api.v1.modules.a76.invoices.models import InvoiceHeader, InvoiceLogistics +from api.v1.modules.a76.items.models import ItemLines, LineQuantities, LineFinancials +from api.v1.modules.a76.clients.models import ( + ClientsAndProviders, + ClientsAndProvidersAddress, + ClientsAndProvidersPrograms +) +from api.v1.modules.a76.parts.models import Parts +from api.v1.modules.a76.pedimentos.models import Pedimentos +from api.v1.modules.a76.companies.models import Company # Tu empresa propia (Tenant) + +from .schemas import ( + ClienteSchema, PartidaSchema, TotalesSchema, + FacturaSchema, FacturaImportacionCompleta +) + +class FacturaImportacionMexService: + def __init__(self): + # Directorio de templates + self.template_dir = Path(__file__).parent.parent / "templates" + + self.jinja_env = Environment( + loader=FileSystemLoader(self.template_dir), + autoescape=select_autoescape(['html', 'xml']) + ) + self.template = self.jinja_env.get_template('factura_mex_ver.html') + + def _get_wkhtmltopdf_config(self): + path = shutil.which("wkhtmltopdf") + if not path: + common_paths = ["/usr/bin/wkhtmltopdf", "/usr/local/bin/wkhtmltopdf"] + for p in common_paths: + if Path(p).exists(): + path = p + break + if not path: + raise RuntimeError("wkhtmltopdf no encontrado.") + return pdfkit.configuration(wkhtmltopdf=path) + + def formatear_numero(self, valor, decimales: int = 2): + if valor is None: return 0.0 + try: + return round(float(valor), decimales) + except: return 0.0 + + def _obtener_datos_cliente(self, db: Session, client_id: int, rol: str) -> ClienteSchema: + """ + Busca en las 3 tablas de clientes (Main, Address, Programs) para armar el esquema. + """ + # 1. Tabla Principal + main = db.query(ClientsAndProviders).filter(ClientsAndProviders.id == client_id).first() + if not main: + return ClienteSchema( + header=rol, nombre="Desconocido", direccion="", codigo_postal="", + ciudad="", estado="", pais="", tax_id="" + ) + + # 2. Dirección + addr = db.query(ClientsAndProvidersAddress).filter(ClientsAndProvidersAddress.client_id == client_id).first() + + # 3. Programa / Tax ID + prog = db.query(ClientsAndProvidersPrograms).filter(ClientsAndProvidersPrograms.client_id == client_id).first() + + direccion_str = addr.streets if addr else "" + + return ClienteSchema( + header=rol, + nombre=main.name or main.short_name, + direccion=direccion_str, + num_exterior=addr.exterior_number if addr else "", + num_interior=addr.interior_number if addr else "", + colonia=addr.neighborhood if addr else "", + codigo_postal=addr.postal_code if addr else "", + ciudad=addr.city if addr else "", + estado=addr.state if addr else "", + pais=addr.country if addr else "MEX", + tax_id=prog.tax_id if prog else (main.rfc or ""), + programa="IMMEX" if prog and prog.program else "", + autorizacion=prog.program_number if prog else "" + ) + + def obtener_datos(self, db: Session, invoice_id: int) -> FacturaImportacionCompleta: + try: + # 1. CABECERA (InvoiceHeader) + header = db.query(InvoiceHeader).filter(InvoiceHeader.id == invoice_id).first() + if not header: + raise HTTPException(status_code=404, detail="Factura no encontrada") + + # 2. LOGÍSTICA (InvoiceLogistics) + logistics = db.query(InvoiceLogistics).filter(InvoiceLogistics.invoice_id == header.id).first() + + # 3. PEDIMENTO (Pedimentos) + # Intentamos buscar por relation_doc_id o asumimos una búsqueda por ID si existiera columna pedimento_id + # Si no hay link directo, buscamos el pedimento asociado al cliente/fecha (Lógica aproximada) + pedimento = None + if header.related_doc_id: + pedimento = db.query(Pedimentos).filter(Pedimentos.id == header.related_doc_id).first() + + # 4. ACTORES (Clientes/Proveedores) + # Importación: Proveedor = Externo (Client ID?), Importador = Nosotros (Company ID) + # Nota: Asumo que en invoice_header hay un campo 'client_id' para el proveedor externo. + # Si no existe en el modelo, revisa qué campo guarda el ID del proveedor. + proveedor_id = getattr(header, 'client_id', None) + + # --- PROVEEDOR (Extranjero) --- + if proveedor_id: + cliente_proveedor = self._obtener_datos_cliente(db, proveedor_id, "Proveedor / Supplier") + else: + # Fallback si no encontramos ID de proveedor + cliente_proveedor = ClienteSchema( + header="Proveedor", nombre="No Asignado", direccion="", codigo_postal="", ciudad="", estado="", pais="", tax_id="" + ) + + # --- IMPORTADOR (Vendido A - Tu Empresa) --- + # Usamos 'company_id' que viene en invoice_header + # Ojo: Si tu empresa también está en clients_and_providers, úsala. Si está en 'companies', mapea desde ahí. + # Aquí asumo que está en 'companies' como Tenant. + company = db.query(Company).filter(Company.id == header.company_id).first() + + cliente_vendido = ClienteSchema( + header="Importador / Consignatario", + nombre=company.name if company else "Mi Empresa", + direccion=company.address_street if company else "", # Ajustar nombres de col company + num_exterior=str(company.address_number) if company else "", + colonia=company.neighborhood if company else "", + codigo_postal=company.zip_code if company else "", + ciudad=company.city if company else "", + estado=company.state if company else "", + pais=company.country if company else "MEX", + tax_id=company.tax_id if company else "", + programa="IMMEX", + autorizacion=company.immex_program if company else "" + ) + + cliente_enviado = cliente_vendido + + # 5. MAPEO FACTURA + factura_schema = FacturaSchema( + numero=header.invoice_number, + fecha=str(header.invoice_date) if header.invoice_date else "", + tipo_cambio=float(pedimento.exchange_rate) if pedimento and pedimento.exchange_rate else 1.0, + moneda="USD", # O derivar de header.invoice_type o logistics + incoterm=logistics.incoterm if logistics else "", + observaciones=header.observation_es or header.observation_en or "", + + # Datos Pedimento + pedimento=pedimento.pedimento_number if pedimento else "", + clave_pedimento=pedimento.pedimento_code if pedimento else "", + regimen=pedimento.regime if pedimento else "", + + # Datos Transporte + transportista="", # logistics.carrier_id (habría que hacer join con tabla carriers) + transporte=logistics.transport_type if logistics else "", + num_transporte=logistics.trailer_num if logistics else "", + placas=logistics.license_plate if logistics else "", + aduana=pedimento.customs_office if pedimento else "", + + # Otros + remesa="", # No vi campo remesa en header + acuse_electronico="", + agente_aduanal="", # pedimento.license + patente=pedimento.license if pedimento else "", + precinto=logistics.seal_number if logistics else "", + destino=logistics.destination_goods if logistics else "" + ) + + # 6. PARTIDAS (JOIN item_lines + line_quantities + line_financials) + lines = db.query(ItemLines).filter(ItemLines.item_id == header.id).all() # Ojo: item_id suele ser invoice_id en header + + partidas_list = [] + + for line in lines: + # Datos Cuantitativos + qty = db.query(LineQuantities).filter(LineQuantities.item_line_id == line.id).first() + # Datos Financieros + fin = db.query(LineFinancials).filter(LineFinancials.item_line_id == line.id).first() + + # Parte Maestra (Si line.part_number es ID, buscamos. Si es string, usamos directo) + # Tu tabla dice 'part_number' es integer, asumo que es ID hacia tabla 'parts' + part_master = db.query(Parts).filter(Parts.id == line.part_number).first() + + # Construcción de valores + descripcion = part_master.description_spanish if part_master else "S/D" + fraccion = part_master.fraction if part_master else "" + + cantidad = float(qty.quantity) if qty else 0.0 + # Costo: Unitario Comercial USD + precio_unitario = float(fin.commercial_unit_cost) if fin else 0.0 + valor_total = float(fin.total_commercial_value) if fin else (cantidad * precio_unitario) + + # Pesos y Bultos (LineQuantities tiene todo esto, ¡genial!) + peso_n = float(qty.net_weight) if qty else 0.0 + peso_b = float(qty.gross_weight) if qty else 0.0 + bultos = int(qty.package_quantity) if qty and qty.package_quantity else 0 + clave_b = qty.package_key if qty else "" + + partidas_list.append(PartidaSchema( + numero_parte=part_master.part_number if part_master else str(line.part_number), + descripcion=descripcion, + fraccion=fraccion, + origen="MEX", # line.country_origin? o part_master + cantidad_importacion=self.formatear_numero(cantidad), + unidad_medida=qty.weight_unit if qty else "KG", # O qty.package_key + cantidad_bultos=bultos, + clave_bultos=clave_b, + peso_neto=self.formatear_numero(peso_n), + peso_bruto=self.formatear_numero(peso_b), + valor_costo_unitario=self.formatear_numero(precio_unitario), + valor_total=self.formatear_numero(valor_total) + )) + + # 7. TOTALES + totales = self.calcular_totales(partidas_list, Decimal(factura_schema.tipo_cambio)) + + return FacturaImportacionCompleta( + cliente_proveedor=cliente_proveedor, + cliente_vendido=cliente_vendido, + cliente_enviado=cliente_enviado, + factura=factura_schema, + partidas=partidas_list, + totales=totales + ) + + except Exception as e: + print(f"Error Service A76: {e}") + raise HTTPException(status_code=500, detail=f"Error procesando datos: {str(e)}") + + def calcular_totales(self, partidas: List[PartidaSchema], tipo_cambio: Decimal) -> TotalesSchema: + cant = sum(float(p.cantidad_importacion) for p in partidas) + valor = sum(float(p.valor_total) for p in partidas) + peso_n = sum(float(p.peso_neto) for p in partidas) + peso_b = sum(float(p.peso_bruto) for p in partidas) + bultos = sum(p.cantidad_bultos for p in partidas) + + # Obtener clave de bulto más común + claves = [p.clave_bultos for p in partidas if p.clave_bultos] + clave_comun = max(set(claves), key=claves.count) if claves else "" + + tc = float(tipo_cambio) if tipo_cambio else 1.0 + + return TotalesSchema( + cantidad_total=self.formatear_numero(cant), + bultos_total=bultos, + clave_bultos=clave_comun, + peso_neto_total=self.formatear_numero(peso_n), + peso_bruto_total=self.formatear_numero(peso_b), + valor_total_total=self.formatear_numero(valor), + valor_total_dolares=self.formatear_numero(valor / tc if tc > 0 else 0) + ) + + # --- GENERACIÓN --- + def generar_html(self, datos: FacturaImportacionCompleta) -> str: + context = { + 'cliente_proveedor': datos.cliente_proveedor.model_dump(), + 'cliente_vendido': datos.cliente_vendido.model_dump(), + 'cliente_enviado': datos.cliente_enviado.model_dump(), + 'factura': datos.factura.model_dump(), + 'partidas': [p.model_dump() for p in datos.partidas], + 'totales': datos.totales.model_dump() + } + return self.template.render(**context) + + def generar_pdf(self, html_content: str) -> bytes: + options = { + 'page-size': 'Letter', + 'margin-top': '0.75in', + 'margin-right': '0.75in', + 'margin-bottom': '1.00in', + 'margin-left': '0.75in', + 'encoding': "UTF-8", + 'enable-local-file-access': None + } + config = self._get_wkhtmltopdf_config() + return pdfkit.from_string(html_content, False, options=options, configuration=config) + + def generar_factura_completa(self, db: Session, invoice_id: int, formato: str = "pdf") -> Tuple[bytes, str, str]: + datos = self.obtener_datos(db, invoice_id) + html = self.generar_html(datos) + nombre = f"Factura_{datos.factura.numero}.{formato}" + + if formato == "html": + return html.encode('utf-8'), nombre, "text/html" + + pdf = self.generar_pdf(html) + return pdf, nombre, "application/pdf" \ No newline at end of file diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/routes.py b/backend/api/v1/modules/a76/reports/importacion/facturas/routes.py new file mode 100644 index 00000000..0638ea41 --- /dev/null +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/routes.py @@ -0,0 +1,50 @@ +from enum import Enum +from fastapi import APIRouter, Depends, Query, Response, HTTPException +from sqlalchemy.orm import Session +from core.database import get_db + +# Importamos el servicio mexicano +from .mex.service import FacturaImportacionMexService + +router = APIRouter() +servicio_mex = FacturaImportacionMexService() + +class TipoFactura(str, Enum): + mexicana = "mex" + # americana = "usa" + +class Formato(str, Enum): + html = "html" + pdf = "pdf" + +@router.get("/{invoice_id}/download") +async def descargar_factura( + invoice_id: int, + tipo: TipoFactura = Query(TipoFactura.mexicana), + formato: Formato = Query(Formato.pdf), + db: Session = Depends(get_db) +): + """ + Descargar Factura de Importación (A76) + """ + if tipo == TipoFactura.mexicana: + servicio = servicio_mex + else: + raise HTTPException(status_code=501, detail="Tipo de factura no implementado") + + try: + contenido, nombre, media_type = servicio.generar_factura_completa( + db=db, + invoice_id=invoice_id, + formato=formato.value + ) + + return Response( + content=contenido, + media_type=media_type, + headers={ + "Content-Disposition": f"attachment; filename={nombre}" + } + ) + except Exception as e: + raise HTTPException(status_code=500, detail=f"Error generando reporte: {str(e)}") \ No newline at end of file diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/tem/schemas.py b/backend/api/v1/modules/a76/reports/importacion/facturas/tem/schemas.py new file mode 100644 index 00000000..e69de29b diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/tem/service.py b/backend/api/v1/modules/a76/reports/importacion/facturas/tem/service.py new file mode 100644 index 00000000..e69de29b diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_mex_ver.html b/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_mex_ver.html new file mode 100644 index 00000000..eff919ee --- /dev/null +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_mex_ver.html @@ -0,0 +1,367 @@ + + + + + Factura Importacion Mexicana - {{ factura.numero }} + + + + +
+
+
+

Factura de Importacion

+
+

+
+
+

+


+
+
+
+
+
+

{{ cliente_proveedor.header }}

+

{{ cliente_proveedor.nombre }}

+

{{ cliente_proveedor.direccion }} + {% if cliente_proveedor.num_exterior %} Ext: {{ cliente_proveedor.num_exterior }}{% endif %} + {% if cliente_proveedor.num_interior %} Int: {{ cliente_proveedor.num_interior }}{% endif %} +

+

{{ cliente_proveedor.colonia }} {% if cliente_proveedor.codigo_postal %} CP: {{ cliente_proveedor.codigo_postal }}{% endif %}

+

{{ cliente_proveedor.ciudad }}, {{ cliente_proveedor.estado }}, {{ cliente_proveedor.pais }}

+

TAX ID: {{ cliente_proveedor.tax_id }} + {% if cliente_proveedor.programa and cliente_proveedor.programa != 'Ninguno' %} + {{ cliente_proveedor.programa }}: {{ cliente_proveedor.autorizacion }} + {% endif %} +

+


+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

FACTURA:

+
+

{{ factura.numero }}

+
+

Fecha:

+
+

{{ factura.fecha }}

+
+

T. Cambio:

+
+

{{ factura.tipo_cambio }}

+
+

Pedimento:

+
+

{{ factura.pedimento }}

+
+

Clave:

+
+

{{ factura.clave_pedimento }}

+
+

Remesa:

+
+

{{ factura.remesa }}

+
+

Acuse:

+
+

{{ factura.acuse_electronico or 'N/A' }}

+
+

Agente Aduanal:

+

{{ factura.agente_aduanal or '' }}

+
+

Patente: {{ factura.patente or '' }}

+
+ Regimen:{{ factura.regimen or '' }} + +

INCOTERM:

+

{{ factura.incoterm or '' }}

+
+ {% if factura.precinto %} +

Precinto: {{ factura.precinto }}

+ {% endif %} +
+

Aduana: {{ factura.aduana }}

+
+ {% if factura.destino %} +

Destino: {{ factura.destino }}

+ {% endif %} +
+
+
+ +
+
+

{{ cliente_vendido.header }}

+

{{ cliente_vendido.nombre }}

+

{{ cliente_vendido.direccion }} + {% if cliente_vendido.num_exterior %} Ext: {{ cliente_vendido.num_exterior }}{% endif %} + {% if cliente_vendido.num_interior %} Int: {{ cliente_vendido.num_interior }}{% endif %} +

+

{{ cliente_vendido.colonia }} {% if cliente_vendido.codigo_postal %} CP: {{ cliente_vendido.codigo_postal }}{% endif %}

+

{{ cliente_vendido.ciudad }}, {{ cliente_vendido.estado }}, {{ cliente_vendido.pais }}

+

RFC: {{ cliente_vendido.tax_id }} + {% if cliente_vendido.programa and cliente_vendido.programa != 'Ninguno' %} + {{ cliente_vendido.programa }}: {{ cliente_vendido.autorizacion }} + {% endif %} +

+
+ +
+

{{ cliente_enviado.header }}

+

{{ cliente_enviado.nombre }}

+

{{ cliente_enviado.direccion }} + {% if cliente_enviado.num_exterior %} Ext: {{ cliente_enviado.num_exterior }}{% endif %} + {% if cliente_enviado.num_interior %} Int: {{ cliente_enviado.num_interior }}{% endif %} +

+

{{ cliente_enviado.colonia }} {% if cliente_enviado.codigo_postal %} CP: {{ cliente_enviado.codigo_postal }}{% endif %}

+

{{ cliente_enviado.ciudad }}, {{ cliente_enviado.estado }}, {{ cliente_enviado.pais }}

+

RFC: {{ cliente_enviado.tax_id }}

+
+
+


+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {% for partida in partidas %} + + + + + + + + + + + + {% endfor %} + + + + + + + + + + + + + + + + + + + + + +

Transportista:

{{ factura.transportista }}

SCAC: {{ factura.scac }}

INCOTERM:

{{ factura.incoterm }}

+

Aduana: {{ factura.aduana }}

+


+

Transporte:

+

{{ factura.transporte }}: {{ factura.num_transporte }}

CAAT: {{ factura.caat }}

+

Placas: {{ factura.placas or 'N/A' }}

+



+

Línea

+
+

Número de Parte

+

Descripción

+
+

Comercial

+
+

Empaque

+
+

Peso (KGS)

+
+

Valores

+
+

Cantidad

+
+

U.M.

+
+

Tipo

+
+

Neto

+
+

Bruto

+
+

Unitario

+
+

Total

+
+

{{ loop.index }}

+
+

{{ partida.numero_parte }}

+

{{ partida.descripcion }}

+

Frac: {{ partida.fraccion }} / Orig: {{ partida.origen or 'MEX' }}

+
+

{{ partida.cantidad_importacion }}

+
+

{{ partida.unidad_medida }}

+
+

+ {% if partida.cantidad_bultos != 0 %}{{ partida.cantidad_bultos }}{% endif %} + {{ partida.clave_bultos }} +

+
+

{{ partida.peso_neto }}

+
+

{{ partida.peso_bruto }}

+
+

${{ partida.valor_costo_unitario }}

+
+

${{ partida.valor_total }}

+
+

+ Observaciones: + TOTALES +

+
+

{{ totales.cantidad_total }}

+
+

+ {% if totales.bultos_total != 0 %}{{ totales.bultos_total }}{% endif %} + {{ totales.clave_bultos or '' }} +

+
+

{{ totales.peso_neto_total }}

+
+

{{ totales.peso_bruto_total }}

+
+

${{ totales.valor_total_total }}

+
+

{{ factura.observaciones }}

+
+

+

{{ cliente_proveedor.nombre }}

+


+

Los valores expresados en esta factura son en: {{ factura.moneda }}

+
+


+

Normal Por Parte

+

Declaro bajo protesta de decir verdad que la información contenida en este documento es verdadera y me hago responsable de comprobar lo aquí declarado.

+
+ + \ No newline at end of file diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_tem_hor.html b/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_tem_hor.html new file mode 100644 index 00000000..e69de29b diff --git a/backend/requirements.txt b/backend/requirements.txt index 1e600ac7..d33317be 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -38,3 +38,6 @@ black==25.9.0 flake8==7.3.0 mypy==1.18.2 pylint==4.0.2 + +# reportes +Jinja2==3.1.6 diff --git a/frontend/src/routes/dashboard/general_catalogs/ports/+page.svelte b/frontend/src/routes/dashboard/general_catalogs/ports/+page.svelte index e14df2cc..c870f080 100644 --- a/frontend/src/routes/dashboard/general_catalogs/ports/+page.svelte +++ b/frontend/src/routes/dashboard/general_catalogs/ports/+page.svelte @@ -4,7 +4,7 @@ import { browser } from '$app/environment'; import { createColumns } from '$lib/components/dashboard/ports/columns'; import CreateEditDialog from '$lib/components/dashboard/ports/create-edit-dialog.svelte'; - import DataTable from '$lib/components/dashboard/units_of_measure/ace/data-table.svelte'; + import DataTable from '$lib/components/dashboard/general_catalogs/units_of_measure/ace/data-table.svelte'; import { Button } from '$lib/components/ui/button'; import { Input } from '$lib/components/ui/input'; import { Plus } from 'lucide-svelte'; diff --git a/frontend/src/routes/dashboard/invoices/+page.svelte b/frontend/src/routes/dashboard/invoices/+page.svelte index 93f23c50..6fd7fc9d 100644 --- a/frontend/src/routes/dashboard/invoices/+page.svelte +++ b/frontend/src/routes/dashboard/invoices/+page.svelte @@ -1,496 +1,543 @@
- -
-
-

Facturas

-

- Gestiona las facturas del sistema -

-
- -
+
+
+

Facturas

+

+ Gestiona las facturas del sistema +

+
+ +
- - - - Filtros - Filtra las facturas por diferentes criterios (los filtros se aplican automáticamente) - - -
-
- - -
+ + + Filtros + Filtra las facturas por diferentes criterios (los filtros se aplican automáticamente) + + +
+
+ + +
-
- - -
+
+ + +
-
- - -
+
+ + +
-
- - -
+
+ + +
-
- - -
-
-
-
+
+ + +
+
+
+
- - {#if error} - - - Error - {error} - - - {/if} + {#if error} + + + Error + {error} + + + {/if} - - - -
-
- Listado de Facturas - - Mostrando {allItems.length} de {totalItems} registros - -
- -
-
- - - - -
-
+ + +
+
+ Listado de Facturas + + Mostrando {allItems.length} de {totalItems} registros + +
+ +
+
+ + + +
+ \ No newline at end of file From 50ef340df85746a0824722be3a20100c0a81840f Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Fri, 9 Jan 2026 18:03:08 -0600 Subject: [PATCH 02/21] Se creo la rutina de creacion de reportes parcial --- .../importacion/facturas/mex/schemas.py | 32 +- .../importacion/facturas/mex/service.py | 291 +++++------- .../reports/importacion/facturas/routes.py | 57 +-- backend/api/v1/modules/a76/router.py | 10 + backend/api/v1/router.py | 3 + backend/requirements.txt | 1 + .../dashboard/a76/reports/reports-invoices.ts | 37 ++ .../components/dashboard/invoices/columns.ts | 446 +++++++++--------- .../invoices/data-table-actions.svelte | 117 ++--- .../routes/dashboard/invoices/+page.svelte | 53 +-- 10 files changed, 515 insertions(+), 532 deletions(-) create mode 100644 frontend/src/lib/api/dashboard/a76/reports/reports-invoices.ts diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/schemas.py b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/schemas.py index a7e765e1..e2f73cc3 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/schemas.py +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/schemas.py @@ -1,25 +1,29 @@ from decimal import Decimal from typing import List, Optional, Union -from pydantic import BaseModel +from pydantic import BaseModel, field_validator -# Nota: Usamos Union[float, str] en los números para poder enviar -# strings formateados con comas (ej: "1,200.50") si lo deseamos, -# ya que tu HTML no tiene filtros de formato. class ClienteSchema(BaseModel): header: str nombre: str - direccion: str - num_exterior: str = "" - num_interior: str = "" - colonia: str = "" - codigo_postal: str - ciudad: str - estado: str - pais: str + # Ponemos valor por defecto "" y permitimos que sea opcional + direccion: Optional[str] = "" + num_exterior: Optional[str] = "" + num_interior: Optional[str] = "" + colonia: Optional[str] = "" + codigo_postal: Optional[str] = "" + ciudad: Optional[str] = "" + estado: Optional[str] = "" + pais: Optional[str] = "" tax_id: str - programa: str = "" - autorizacion: str = "" + programa: Optional[str] = "" + autorizacion: Optional[str] = "" + + # Si llega un None, lo convertimos en "" automáticamente + @field_validator('direccion', 'nombre', mode='before') + @classmethod + def prevent_none(cls, v): + return v or "" class FacturaSchema(BaseModel): numero: str diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py index c188fe09..8f02cbd1 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py @@ -8,18 +8,22 @@ from jinja2 import Environment, FileSystemLoader, select_autoescape from fastapi import HTTPException from sqlalchemy.orm import Session -# --- IMPORTACIONES DE TUS MODELOS (Asegúrate que las rutas sean correctas) --- -from api.v1.modules.a76.invoices.models import InvoiceHeader, InvoiceLogistics -from api.v1.modules.a76.items.models import ItemLines, LineQuantities, LineFinancials -from api.v1.modules.a76.clients.models import ( - ClientsAndProviders, - ClientsAndProvidersAddress, - ClientsAndProvidersPrograms +# --- MODELOS --- +from api.v1.modules.a76.invoices.models import InvoiceHeader, InvoiceLogistics +from api.v1.modules.a76.items.line_financials.models import LineFinancial +from api.v1.modules.a76.items.line_quantities.models import LineQuantity +from api.v1.modules.a76.items.line_items.models import LineItem +from api.v1.modules.a76.clients_and_providers.models import ( + ClientProvider, + ClientProviderAddress, + ClientProviderPrograms ) -from api.v1.modules.a76.parts.models import Parts -from api.v1.modules.a76.pedimentos.models import Pedimentos -from api.v1.modules.a76.companies.models import Company # Tu empresa propia (Tenant) +from api.v1.modules.a76.parts.models import Part +from api.v1.modules.a76.pedmientos.models import Pedimentos +from api.v1.modules.a76.general_catalogs.company.models import Company +from api.v1.modules.a76.customs_brokers.models import CustomsBroker +# --- SCHEMAS --- from .schemas import ( ClienteSchema, PartidaSchema, TotalesSchema, FacturaSchema, FacturaImportacionCompleta @@ -27,9 +31,7 @@ from .schemas import ( class FacturaImportacionMexService: def __init__(self): - # Directorio de templates self.template_dir = Path(__file__).parent.parent / "templates" - self.jinja_env = Environment( loader=FileSystemLoader(self.template_dir), autoescape=select_autoescape(['html', 'xml']) @@ -37,14 +39,8 @@ class FacturaImportacionMexService: self.template = self.jinja_env.get_template('factura_mex_ver.html') def _get_wkhtmltopdf_config(self): - path = shutil.which("wkhtmltopdf") - if not path: - common_paths = ["/usr/bin/wkhtmltopdf", "/usr/local/bin/wkhtmltopdf"] - for p in common_paths: - if Path(p).exists(): - path = p - break - if not path: + path = shutil.which("wkhtmltopdf") or "/usr/local/bin/wkhtmltopdf" + if not Path(path).exists(): raise RuntimeError("wkhtmltopdf no encontrado.") return pdfkit.configuration(wkhtmltopdf=path) @@ -55,178 +51,152 @@ class FacturaImportacionMexService: except: return 0.0 def _obtener_datos_cliente(self, db: Session, client_id: int, rol: str) -> ClienteSchema: - """ - Busca en las 3 tablas de clientes (Main, Address, Programs) para armar el esquema. - """ - # 1. Tabla Principal - main = db.query(ClientsAndProviders).filter(ClientsAndProviders.id == client_id).first() + main = db.query(ClientProvider).filter(ClientProvider.id == client_id).first() if not main: return ClienteSchema( - header=rol, nombre="Desconocido", direccion="", codigo_postal="", - ciudad="", estado="", pais="", tax_id="" + header=rol, nombre="Desconocido", direccion="", tax_id="", + codigo_postal="", ciudad="", estado="", pais="MEX" ) - # 2. Dirección - addr = db.query(ClientsAndProvidersAddress).filter(ClientsAndProvidersAddress.client_id == client_id).first() - - # 3. Programa / Tax ID - prog = db.query(ClientsAndProvidersPrograms).filter(ClientsAndProvidersPrograms.client_id == client_id).first() + addr = db.query(ClientProviderAddress).filter(ClientProviderAddress.client_id == client_id).first() + prog = db.query(ClientProviderPrograms).filter(ClientProviderPrograms.client_id == client_id).first() - direccion_str = addr.streets if addr else "" - return ClienteSchema( header=rol, - nombre=main.name or main.short_name, - direccion=direccion_str, - num_exterior=addr.exterior_number if addr else "", - num_interior=addr.interior_number if addr else "", - colonia=addr.neighborhood if addr else "", - codigo_postal=addr.postal_code if addr else "", - ciudad=addr.city if addr else "", - estado=addr.state if addr else "", - pais=addr.country if addr else "MEX", - tax_id=prog.tax_id if prog else (main.rfc or ""), - programa="IMMEX" if prog and prog.program else "", + nombre=(main.name or main.short_name) or "S/N", + direccion=(addr.streets or "") if addr else "", + num_exterior=(addr.exterior_number or "") if addr else "", + num_interior=(addr.interior_number or "") if addr else "", + colonia=(addr.neighborhood or "") if addr else "", + codigo_postal=(addr.postal_code or "") if addr else "", + ciudad=(addr.city or "") if addr else "", + estado=(addr.state or "") if addr else "", + pais=(addr.country or "MEX") if addr else "MEX", + tax_id=prog.tax_id if (prog and prog.tax_id) else (getattr(main, 'rfc', "") or ""), + programa="IMMEX" if (prog and prog.program) else "", autorizacion=prog.program_number if prog else "" ) - def obtener_datos(self, db: Session, invoice_id: int) -> FacturaImportacionCompleta: + def obtener_datos(self, db: Session, invoice_id: int, company_id: int) -> FacturaImportacionCompleta: try: - # 1. CABECERA (InvoiceHeader) - header = db.query(InvoiceHeader).filter(InvoiceHeader.id == invoice_id).first() + # 1. Cabecera + header = db.query(InvoiceHeader).filter( + InvoiceHeader.id == invoice_id, + InvoiceHeader.company_id == company_id + ).first() if not header: raise HTTPException(status_code=404, detail="Factura no encontrada") - # 2. LOGÍSTICA (InvoiceLogistics) - logistics = db.query(InvoiceLogistics).filter(InvoiceLogistics.invoice_id == header.id).first() - - # 3. PEDIMENTO (Pedimentos) - # Intentamos buscar por relation_doc_id o asumimos una búsqueda por ID si existiera columna pedimento_id - # Si no hay link directo, buscamos el pedimento asociado al cliente/fecha (Lógica aproximada) - pedimento = None - if header.related_doc_id: - pedimento = db.query(Pedimentos).filter(Pedimentos.id == header.related_doc_id).first() - - # 4. ACTORES (Clientes/Proveedores) - # Importación: Proveedor = Externo (Client ID?), Importador = Nosotros (Company ID) - # Nota: Asumo que en invoice_header hay un campo 'client_id' para el proveedor externo. - # Si no existe en el modelo, revisa qué campo guarda el ID del proveedor. - proveedor_id = getattr(header, 'client_id', None) + # 2. Relaciones Críticas (Compliance y Logistics) + # Nota: Usamos la relación ORM 'compliance_mx' que definiste en el modelo + compliance = header.compliance_mx - # --- PROVEEDOR (Extranjero) --- + # Si logistics es una lista, tomamos el primero, si no, None + logistics = header.logistics[0] if header.logistics else None + + # Pedimento: Prioridad al de Compliance, si no, al de Header + pedimento_id = compliance.pedimento_id if (compliance and compliance.pedimento_id) else header.related_doc_id + pedimento = db.query(Pedimentos).filter(Pedimentos.id == pedimento_id).first() if pedimento_id else None + + # 3. Mapeo Actores (¡AQUÍ ESTABA EL DETALLE!) + + # A) Proveedor: Sacado de compliance.provider_id + proveedor_id = compliance.provider_id if compliance else None if proveedor_id: cliente_proveedor = self._obtener_datos_cliente(db, proveedor_id, "Proveedor / Supplier") else: - # Fallback si no encontramos ID de proveedor - cliente_proveedor = ClienteSchema( - header="Proveedor", nombre="No Asignado", direccion="", codigo_postal="", ciudad="", estado="", pais="", tax_id="" - ) + cliente_proveedor = ClienteSchema(header="Proveedor", nombre="No Asignado", direccion="", tax_id="", + codigo_postal="", ciudad="", estado="", pais="") - # --- IMPORTADOR (Vendido A - Tu Empresa) --- - # Usamos 'company_id' que viene en invoice_header - # Ojo: Si tu empresa también está en clients_and_providers, úsala. Si está en 'companies', mapea desde ahí. - # Aquí asumo que está en 'companies' como Tenant. + # B) Agente Aduanal: Sacado de compliance.customs_broker_id + nombre_agente = "" + if compliance and compliance.customs_broker_id: + broker = db.query(CustomsBroker).filter(CustomsBroker.id == compliance.customs_broker_id).first() + if broker: + nombre_agente = broker.name # Asumiendo que CustomsBroker tiene 'name' + + # C) Importador (Company) company = db.query(Company).filter(Company.id == header.company_id).first() - cliente_vendido = ClienteSchema( header="Importador / Consignatario", - nombre=company.name if company else "Mi Empresa", - direccion=company.address_street if company else "", # Ajustar nombres de col company - num_exterior=str(company.address_number) if company else "", - colonia=company.neighborhood if company else "", - codigo_postal=company.zip_code if company else "", - ciudad=company.city if company else "", - estado=company.state if company else "", - pais=company.country if company else "MEX", - tax_id=company.tax_id if company else "", - programa="IMMEX", - autorizacion=company.immex_program if company else "" + nombre=getattr(company, 'name', "Empresa Local"), + direccion="DOMICILIO FISCAL", + num_exterior="", + colonia="", + codigo_postal="", + ciudad="", + estado="", + pais="MEX", + tax_id=getattr(company, 'rfc', ""), + programa=getattr(company, 'program', "IMMEX"), + autorizacion=getattr(company, 'program_number', "") ) - cliente_enviado = cliente_vendido + # 4. Mapeo Factura + # Nota: Muchos datos vienen de 'compliance', no de 'header' + remesa_valor = str(compliance.remesa) if (compliance and compliance.remesa) else "" + acuse_valor = str(compliance.edocument) if (compliance and compliance.edocument) else "N/A" - # 5. MAPEO FACTURA factura_schema = FacturaSchema( - numero=header.invoice_number, + numero=header.invoice_number or "S/N", fecha=str(header.invoice_date) if header.invoice_date else "", tipo_cambio=float(pedimento.exchange_rate) if pedimento and pedimento.exchange_rate else 1.0, - moneda="USD", # O derivar de header.invoice_type o logistics + moneda=getattr(header, 'currency', "USD") or "USD", incoterm=logistics.incoterm if logistics else "", observaciones=header.observation_es or header.observation_en or "", - # Datos Pedimento + # Pedimento y Agente pedimento=pedimento.pedimento_number if pedimento else "", clave_pedimento=pedimento.pedimento_code if pedimento else "", regimen=pedimento.regime if pedimento else "", + patente=pedimento.license if pedimento else "", + agente_aduanal=nombre_agente, # Agregamos el nombre real - # Datos Transporte - transportista="", # logistics.carrier_id (habría que hacer join con tabla carriers) - transporte=logistics.transport_type if logistics else "", + # Transporte + transporte=str(logistics.transport_type.value) if (logistics and logistics.transport_type) else "", num_transporte=logistics.trailer_num if logistics else "", placas=logistics.license_plate if logistics else "", - aduana=pedimento.customs_office if pedimento else "", + transportista=logistics.carrier_id if logistics else "", # Si carrier_id es ID, aquí habría que buscar nombre # Otros - remesa="", # No vi campo remesa en header - acuse_electronico="", - agente_aduanal="", # pedimento.license - patente=pedimento.license if pedimento else "", + aduana=pedimento.customs_office if pedimento else "", precinto=logistics.seal_number if logistics else "", - destino=logistics.destination_goods if logistics else "" + destino=logistics.destination_goods if logistics else "", + remesa=remesa_valor, + acuse_electronico=acuse_valor ) - # 6. PARTIDAS (JOIN item_lines + line_quantities + line_financials) - lines = db.query(ItemLines).filter(ItemLines.item_id == header.id).all() # Ojo: item_id suele ser invoice_id en header - + # 5. Mapeo Partidas + lines = db.query(LineItem).filter(LineItem.item_id == header.id).all() partidas_list = [] for line in lines: - # Datos Cuantitativos - qty = db.query(LineQuantities).filter(LineQuantities.item_line_id == line.id).first() - # Datos Financieros - fin = db.query(LineFinancials).filter(LineFinancials.item_line_id == line.id).first() - - # Parte Maestra (Si line.part_number es ID, buscamos. Si es string, usamos directo) - # Tu tabla dice 'part_number' es integer, asumo que es ID hacia tabla 'parts' - part_master = db.query(Parts).filter(Parts.id == line.part_number).first() - - # Construcción de valores - descripcion = part_master.description_spanish if part_master else "S/D" - fraccion = part_master.fraction if part_master else "" - - cantidad = float(qty.quantity) if qty else 0.0 - # Costo: Unitario Comercial USD - precio_unitario = float(fin.commercial_unit_cost) if fin else 0.0 - valor_total = float(fin.total_commercial_value) if fin else (cantidad * precio_unitario) - - # Pesos y Bultos (LineQuantities tiene todo esto, ¡genial!) - peso_n = float(qty.net_weight) if qty else 0.0 - peso_b = float(qty.gross_weight) if qty else 0.0 - bultos = int(qty.package_quantity) if qty and qty.package_quantity else 0 - clave_b = qty.package_key if qty else "" + qty = db.query(LineQuantity).filter(LineQuantity.item_line_id == line.id).first() + fin = db.query(LineFinancial).filter(LineFinancial.item_line_id == line.id).first() + part_master = db.query(Part).filter(Part.id == line.part_number).first() partidas_list.append(PartidaSchema( - numero_parte=part_master.part_number if part_master else str(line.part_number), - descripcion=descripcion, - fraccion=fraccion, - origen="MEX", # line.country_origin? o part_master - cantidad_importacion=self.formatear_numero(cantidad), - unidad_medida=qty.weight_unit if qty else "KG", # O qty.package_key - cantidad_bultos=bultos, - clave_bultos=clave_b, - peso_neto=self.formatear_numero(peso_n), - peso_bruto=self.formatear_numero(peso_b), - valor_costo_unitario=self.formatear_numero(precio_unitario), - valor_total=self.formatear_numero(valor_total) + numero_parte=part_master.part_number if part_master else str(line.part_number or "S/N"), + descripcion=part_master.description_spanish if part_master else "S/D", + fraccion=part_master.fraction if part_master else "", + origen="MEX", + cantidad_importacion=self.formatear_numero(qty.quantity if qty else 0), + unidad_medida=qty.weight_unit if qty else "KG", + cantidad_bultos=int(qty.package_quantity) if qty and qty.package_quantity else 0, + clave_bultos=qty.package_key if qty else "", + peso_neto=self.formatear_numero(qty.net_weight if qty else 0), + peso_bruto=self.formatear_numero(qty.gross_weight if qty else 0), + valor_costo_unitario=self.formatear_numero(fin.commercial_unit_cost if fin else 0), + valor_total=self.formatear_numero(fin.total_commercial_value if fin else 0) )) - # 7. TOTALES + # 6. Totales totales = self.calcular_totales(partidas_list, Decimal(factura_schema.tipo_cambio)) return FacturaImportacionCompleta( cliente_proveedor=cliente_proveedor, cliente_vendido=cliente_vendido, - cliente_enviado=cliente_enviado, + cliente_enviado=cliente_vendido, factura=factura_schema, partidas=partidas_list, totales=totales @@ -237,16 +207,13 @@ class FacturaImportacionMexService: raise HTTPException(status_code=500, detail=f"Error procesando datos: {str(e)}") def calcular_totales(self, partidas: List[PartidaSchema], tipo_cambio: Decimal) -> TotalesSchema: - cant = sum(float(p.cantidad_importacion) for p in partidas) - valor = sum(float(p.valor_total) for p in partidas) - peso_n = sum(float(p.peso_neto) for p in partidas) - peso_b = sum(float(p.peso_bruto) for p in partidas) + cant = sum(p.cantidad_importacion for p in partidas) + valor = sum(p.valor_total for p in partidas) + peso_n = sum(p.peso_neto for p in partidas) + peso_b = sum(p.peso_bruto for p in partidas) bultos = sum(p.cantidad_bultos for p in partidas) - - # Obtener clave de bulto más común claves = [p.clave_bultos for p in partidas if p.clave_bultos] clave_comun = max(set(claves), key=claves.count) if claves else "" - tc = float(tipo_cambio) if tipo_cambio else 1.0 return TotalesSchema( @@ -259,8 +226,9 @@ class FacturaImportacionMexService: valor_total_dolares=self.formatear_numero(valor / tc if tc > 0 else 0) ) - # --- GENERACIÓN --- - def generar_html(self, datos: FacturaImportacionCompleta) -> str: + def generar_factura_completa(self, db: Session, invoice_id: int, company_id: int, formato: str = "pdf") -> Tuple[bytes, str, str]: + datos = self.obtener_datos(db, invoice_id, company_id) + context = { 'cliente_proveedor': datos.cliente_proveedor.model_dump(), 'cliente_vendido': datos.cliente_vendido.model_dump(), @@ -269,28 +237,17 @@ class FacturaImportacionMexService: 'partidas': [p.model_dump() for p in datos.partidas], 'totales': datos.totales.model_dump() } - return self.template.render(**context) - - def generar_pdf(self, html_content: str) -> bytes: - options = { - 'page-size': 'Letter', - 'margin-top': '0.75in', - 'margin-right': '0.75in', - 'margin-bottom': '1.00in', - 'margin-left': '0.75in', - 'encoding': "UTF-8", - 'enable-local-file-access': None - } - config = self._get_wkhtmltopdf_config() - return pdfkit.from_string(html_content, False, options=options, configuration=config) - - def generar_factura_completa(self, db: Session, invoice_id: int, formato: str = "pdf") -> Tuple[bytes, str, str]: - datos = self.obtener_datos(db, invoice_id) - html = self.generar_html(datos) + + html_content = self.template.render(**context) nombre = f"Factura_{datos.factura.numero}.{formato}" if formato == "html": - return html.encode('utf-8'), nombre, "text/html" + return html_content.encode('utf-8'), nombre, "text/html" - pdf = self.generar_pdf(html) + options = { + 'page-size': 'Letter', 'margin-top': '0.5in', 'margin-right': '0.5in', + 'margin-bottom': '0.5in', 'margin-left': '0.5in', 'encoding': "UTF-8", + 'enable-local-file-access': None + } + pdf = pdfkit.from_string(html_content, False, options=options, configuration=self._get_wkhtmltopdf_config()) return pdf, nombre, "application/pdf" \ No newline at end of file diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/routes.py b/backend/api/v1/modules/a76/reports/importacion/facturas/routes.py index 0638ea41..0049204e 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/routes.py +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/routes.py @@ -1,9 +1,10 @@ from enum import Enum +from typing import Dict, Any from fastapi import APIRouter, Depends, Query, Response, HTTPException from sqlalchemy.orm import Session -from core.database import get_db -# Importamos el servicio mexicano +from core.database import get_core_db +from core.security import get_current_user, validate_access_to_resource from .mex.service import FacturaImportacionMexService router = APIRouter() @@ -11,7 +12,6 @@ servicio_mex = FacturaImportacionMexService() class TipoFactura(str, Enum): mexicana = "mex" - # americana = "usa" class Formato(str, Enum): html = "html" @@ -20,31 +20,34 @@ class Formato(str, Enum): @router.get("/{invoice_id}/download") async def descargar_factura( invoice_id: int, + company_id: int = Query(..., description="ID de la empresa"), tipo: TipoFactura = Query(TipoFactura.mexicana), formato: Formato = Query(Formato.pdf), - db: Session = Depends(get_db) + db: Session = Depends(get_core_db), + current_user: Dict[str, Any] = Depends(get_current_user) ): - """ - Descargar Factura de Importación (A76) - """ - if tipo == TipoFactura.mexicana: - servicio = servicio_mex - else: - raise HTTPException(status_code=501, detail="Tipo de factura no implementado") + # Validar que el usuario tiene acceso a esta empresa + tenant_id = validate_access_to_resource(db, company_id, current_user) - try: - contenido, nombre, media_type = servicio.generar_factura_completa( - db=db, - invoice_id=invoice_id, - formato=formato.value - ) - - return Response( - content=contenido, - media_type=media_type, - headers={ - "Content-Disposition": f"attachment; filename={nombre}" - } - ) - except Exception as e: - raise HTTPException(status_code=500, detail=f"Error generando reporte: {str(e)}") \ No newline at end of file + if tipo == TipoFactura.mexicana: + try: + # Pasamos invoice_id Y company_id al servicio + contenido, nombre, media_type = servicio_mex.generar_factura_completa( + db=db, + invoice_id=invoice_id, + company_id=company_id, + formato=formato.value + ) + + return Response( + content=contenido, + media_type=media_type, + headers={ + "Content-Disposition": f"attachment; filename={nombre}", + "Access-Control-Expose-Headers": "Content-Disposition" + } + ) + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + else: + raise HTTPException(status_code=501, detail="Tipo no implementado") \ No newline at end of file diff --git a/backend/api/v1/modules/a76/router.py b/backend/api/v1/modules/a76/router.py index 95f5791a..4faae183 100644 --- a/backend/api/v1/modules/a76/router.py +++ b/backend/api/v1/modules/a76/router.py @@ -48,6 +48,9 @@ from .transportation.transporters.routes import router as transporters_router from .transportation.vehicles.routes import router as vehicles_router from api.v1.modules.public.reference_data.material_types.routes import router as material_types_router +# --- NUEVO IMPORT PARA REPORTES DE FACTURAS --- +from .reports.importacion.facturas.routes import router as invoices_reports_router + # Router principal router = APIRouter() @@ -114,3 +117,10 @@ router.include_router( prefix="/public/reference-data", tags=["Reference Data"] ) + +# --- REGISTRO DE RUTAS DE REPORTES --- +router.include_router( + invoices_reports_router, + prefix="/a76/reports/importacion/facturas", + tags=["a76 / reports"] +) \ No newline at end of file diff --git a/backend/api/v1/router.py b/backend/api/v1/router.py index 1a4a8c47..d9b4d517 100644 --- a/backend/api/v1/router.py +++ b/backend/api/v1/router.py @@ -12,6 +12,7 @@ from .modules.a24.router import router as a24_router from .modules.public.router import router as public_router from .modules.a24.router import router as a24_router + # Router principal router = APIRouter() @@ -29,3 +30,5 @@ router.include_router(a24_router) def status(): """Health check de la API""" return {"status": "ok", "version": "1.0.0", "api": "v1"} + + diff --git a/backend/requirements.txt b/backend/requirements.txt index d33317be..8ed4b755 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -41,3 +41,4 @@ pylint==4.0.2 # reportes Jinja2==3.1.6 +pdfkit==1.0.0 diff --git a/frontend/src/lib/api/dashboard/a76/reports/reports-invoices.ts b/frontend/src/lib/api/dashboard/a76/reports/reports-invoices.ts new file mode 100644 index 00000000..68ebafab --- /dev/null +++ b/frontend/src/lib/api/dashboard/a76/reports/reports-invoices.ts @@ -0,0 +1,37 @@ +// En invoices.ts + +// 1. Recuperamos la URL base del entorno (así funciona igual en local y en producción) +// Nota: El nombre 'VITE_API_URL' depende de cómo lo tengan en tu proyecto. +// A veces es import.meta.env.PUBLIC_API_URL +const BASE_URL = import.meta.env.VITE_API_URL || ''; + +export const invoicesReportsApi = { + // ... tus otros métodos ... + + downloadPdf: async (invoiceId: number, type: 'mex' | 'usa' = 'mex', companyId: number) => { + const params = new URLSearchParams({ + tipo: type, + formato: 'pdf', + company_id: companyId.toString() + }); + // 2. Usamos la variable, no el texto fijo + const endpoint = `${BASE_URL}/v1/a76/reports/importacion/facturas/${invoiceId}/download?${params.toString()}`; + + const token = localStorage.getItem('access_token'); + + const response = await fetch(endpoint, { + method: 'GET', + headers: { + 'Authorization': `Bearer ${token}`, + + } + }); + + if (!response.ok) { + const error = await response.json().catch(() => ({ detail: 'Error desconocido' })); + throw new Error(error.detail || 'Error al descargar'); + } + + return response.blob(); + }, +}; \ No newline at end of file diff --git a/frontend/src/lib/components/dashboard/invoices/columns.ts b/frontend/src/lib/components/dashboard/invoices/columns.ts index c087fae8..46802478 100644 --- a/frontend/src/lib/components/dashboard/invoices/columns.ts +++ b/frontend/src/lib/components/dashboard/invoices/columns.ts @@ -4,247 +4,241 @@ import { createRawSnippet } from "svelte"; import DataTableActions from "./data-table-actions.svelte"; import type { Invoice } from '$lib/api/dashboard/a76/invoices'; -/** - * Formatea un número como moneda MXN - */ +// ... (Tus funciones de formato formatCurrencyMXN, formatCurrencyUSD, formatDate, etc. se quedan igual) ... function formatCurrencyMXN(value?: number | null): string { - if (value === null || value === undefined) return '-'; - return new Intl.NumberFormat('es-MX', { - style: 'currency', - currency: 'MXN', - minimumFractionDigits: 2, - maximumFractionDigits: 2 - }).format(value); + if (value === null || value === undefined) return '-'; + return new Intl.NumberFormat('es-MX', { + style: 'currency', + currency: 'MXN', + minimumFractionDigits: 2, + maximumFractionDigits: 2 + }).format(value); } -/** - * Formatea un número como moneda USD - */ function formatCurrencyUSD(value?: number | null): string { - if (value === null || value === undefined) return '-'; - return new Intl.NumberFormat('es-MX', { - style: 'currency', - currency: 'USD', - minimumFractionDigits: 2, - maximumFractionDigits: 2 - }).format(value); + if (value === null || value === undefined) return '-'; + return new Intl.NumberFormat('es-MX', { + style: 'currency', + currency: 'USD', + minimumFractionDigits: 2, + maximumFractionDigits: 2 + }).format(value); } -/** - * Formatea una fecha - */ function formatDate(date?: string | null): string { - if (!date) return '-'; - return new Date(date).toLocaleDateString('es-MX', { - year: 'numeric', - month: '2-digit', - day: '2-digit' - }); + if (!date) return '-'; + return new Date(date).toLocaleDateString('es-MX', { + year: 'numeric', + month: '2-digit', + day: '2-digit' + }); } -/** - * Obtiene el color del badge según el tipo de operación - */ function getOperationTypeColor(type?: string | null): string { - if (!type) return 'bg-gray-100 text-gray-800'; - return type === 'imp' ? 'bg-blue-100 text-blue-800' : 'bg-green-100 text-green-800'; + if (!type) return 'bg-gray-100 text-gray-800'; + return type === 'imp' ? 'bg-blue-100 text-blue-800' : 'bg-green-100 text-green-800'; } -/** - * Obtiene el color del badge según el semáforo fiscal - */ function getTrafficLightColor(status?: string | null): string { - if (!status) return 'bg-gray-100 text-gray-800'; - - const statusLower = status.toLowerCase(); - if (statusLower.includes('verde') || statusLower === 'green') return 'bg-green-100 text-green-800'; - if (statusLower.includes('amarillo') || statusLower === 'yellow') return 'bg-yellow-100 text-yellow-800'; - if (statusLower.includes('rojo') || statusLower === 'red') return 'bg-red-100 text-red-800'; - - return 'bg-gray-100 text-gray-800'; + if (!status) return 'bg-gray-100 text-gray-800'; + + const statusLower = status.toLowerCase(); + if (statusLower.includes('verde') || statusLower === 'green') return 'bg-green-100 text-green-800'; + if (statusLower.includes('amarillo') || statusLower === 'yellow') return 'bg-yellow-100 text-yellow-800'; + if (statusLower.includes('rojo') || statusLower === 'red') return 'bg-red-100 text-red-800'; + + return 'bg-gray-100 text-gray-800'; } -export function createColumns(onSuccess?: () => void): ColumnDef[] { - return [ - { - accessorKey: "id", - header: "ID", - cell: ({ row }) => { - const idSnippet = createRawSnippet<[{ id: number }]>((getId) => { - const { id } = getId(); - return { - render: () => - `
#${id}
` - }; - }); - return renderSnippet(idSnippet, { id: row.original.id }); - } - }, - { - accessorKey: "operation_type", - header: "Operación", - cell: ({ row }) => { - const type = row.original.operation_type; - const colorClass = getOperationTypeColor(type); - const label = type === 'imp' ? 'IMP' : type === 'exp' ? 'EXP' : 'N/A'; - - const typeSnippet = createRawSnippet<[{ label: string; colorClass: string }]>((getType) => { - const { label, colorClass } = getType(); - return { - render: () => - ` - ${label} - ` - }; - }); - return renderSnippet(typeSnippet, { label, colorClass }); - } - }, - { - accessorKey: "invoice_type", - header: "Tipo", - cell: ({ row }) => { - const typeSnippet = createRawSnippet<[{ type?: string | null }]>((getType) => { - const { type } = getType(); - return { - render: () => - `
${type || '-'}
` - }; - }); - return renderSnippet(typeSnippet, { type: row.original.invoice_type }); - } - }, - { - accessorKey: "invoice_number", - header: "Número de Factura", - cell: ({ row }) => { - const numberSnippet = createRawSnippet<[{ number?: string | null }]>((getNumber) => { - const { number } = getNumber(); - return { - render: () => - `${number || 'N/A'}` - }; - }); - return renderSnippet(numberSnippet, { number: row.original.invoice_number }); - } - }, - { - accessorKey: "project_number", - header: "Proyecto", - cell: ({ row }) => { - const projectSnippet = createRawSnippet<[{ project?: string | null }]>((getProject) => { - const { project } = getProject(); - return { - render: () => - `
${project || '-'}
` - }; - }); - return renderSnippet(projectSnippet, { project: row.original.project_number }); - } - }, - { - accessorKey: "compliance_mx.pedimento", - header: "Pedimento", - cell: ({ row }) => { - const pedimento = row.original.compliance_mx?.pedimento; - - const pedimentoSnippet = createRawSnippet<[{ pedimento?: string | null }]>((getPedimento) => { - const { pedimento } = getPedimento(); - return { - render: () => - `
${pedimento || '-'}
` - }; - }); - return renderSnippet(pedimentoSnippet, { pedimento }); - } - }, - { - accessorKey: "financials.value_mn", - header: () => { - const headerSnippet = createRawSnippet(() => { - return { - render: () => `
Valor MN
` - }; - }); - return renderSnippet(headerSnippet, {}); - }, - cell: ({ row }) => { - const valueMN = row.original.financials?.value_mn; - - const valueSnippet = createRawSnippet<[{ value: string }]>((getValue) => { - const { value } = getValue(); - return { - render: () => - `
${value}
` - }; - }); - return renderSnippet(valueSnippet, { value: formatCurrencyMXN(valueMN) }); - } - }, - { - accessorKey: "financials.value_me", - header: () => { - const headerSnippet = createRawSnippet(() => { - return { - render: () => `
Valor ME
` - }; - }); - return renderSnippet(headerSnippet, {}); - }, - cell: ({ row }) => { - const valueME = row.original.financials?.value_me; - - const valueSnippet = createRawSnippet<[{ value: string }]>((getValue) => { - const { value } = getValue(); - return { - render: () => - `
${value}
` - }; - }); - return renderSnippet(valueSnippet, { value: formatCurrencyUSD(valueME) }); - } - }, - { - accessorKey: "traffic_light_status", - header: "Semáforo", - cell: ({ row }) => { - const status = row.original.traffic_light_status; - const colorClass = getTrafficLightColor(status); - - const statusSnippet = createRawSnippet<[{ status?: string | null; colorClass: string }]>((getStatus) => { - const { status, colorClass } = getStatus(); - return { - render: () => - ` - ${status || '-'} - ` - }; - }); - return renderSnippet(statusSnippet, { status, colorClass }); - } - }, - { - accessorKey: "invoice_date", - header: "Fecha Factura", - cell: ({ row }) => { - const dateSnippet = createRawSnippet<[{ date: string }]>((getDate) => { - const { date } = getDate(); - return { - render: () => - `
${date}
` - }; - }); - return renderSnippet(dateSnippet, { date: formatDate(row.original.invoice_date) }); - } - }, - { - id: "actions", - cell: ({ row }) => { - return renderComponent(DataTableActions, { invoice: row.original, onSuccess }); - } - } - ]; +// 1. MODIFICAMOS LA FIRMA DE LA FUNCIÓN AQUÍ ABAJO +export function createColumns( + onSuccess?: () => void, + onDownload?: (invoice: Invoice) => void // <--- AQUI AGREGAMOS EL ARGUMENTO +): ColumnDef[] { + return [ + { + accessorKey: "id", + header: "ID", + cell: ({ row }) => { + const idSnippet = createRawSnippet<[{ id: number }]>((getId) => { + const { id } = getId(); + return { + render: () => + `
#${id}
` + }; + }); + return renderSnippet(idSnippet, { id: row.original.id }); + } + }, + { + accessorKey: "operation_type", + header: "Operación", + cell: ({ row }) => { + const type = row.original.operation_type; + const colorClass = getOperationTypeColor(type); + const label = type === 'imp' ? 'IMP' : type === 'exp' ? 'EXP' : 'N/A'; + + const typeSnippet = createRawSnippet<[{ label: string; colorClass: string }]>((getType) => { + const { label, colorClass } = getType(); + return { + render: () => + ` + ${label} + ` + }; + }); + return renderSnippet(typeSnippet, { label, colorClass }); + } + }, + { + accessorKey: "invoice_type", + header: "Tipo", + cell: ({ row }) => { + const typeSnippet = createRawSnippet<[{ type?: string | null }]>((getType) => { + const { type } = getType(); + return { + render: () => + `
${type || '-'}
` + }; + }); + return renderSnippet(typeSnippet, { type: row.original.invoice_type }); + } + }, + { + accessorKey: "invoice_number", + header: "Número de Factura", + cell: ({ row }) => { + const numberSnippet = createRawSnippet<[{ number?: string | null }]>((getNumber) => { + const { number } = getNumber(); + return { + render: () => + `${number || 'N/A'}` + }; + }); + return renderSnippet(numberSnippet, { number: row.original.invoice_number }); + } + }, + { + accessorKey: "project_number", + header: "Proyecto", + cell: ({ row }) => { + const projectSnippet = createRawSnippet<[{ project?: string | null }]>((getProject) => { + const { project } = getProject(); + return { + render: () => + `
${project || '-'}
` + }; + }); + return renderSnippet(projectSnippet, { project: row.original.project_number }); + } + }, + { + accessorKey: "compliance_mx.pedimento", + header: "Pedimento", + cell: ({ row }) => { + const pedimento = row.original.compliance_mx?.pedimento_id; + + const pedimentoSnippet = createRawSnippet<[{ pedimento?: string | null }]>((getPedimento) => { + const { pedimento } = getPedimento(); + return { + render: () => + `
${pedimento || '-'}
` + }; + }); + return renderSnippet(pedimentoSnippet, { pedimento }); + } + }, + { + accessorKey: "financials.value_mn", + header: () => { + const headerSnippet = createRawSnippet(() => { + return { + render: () => `
Valor MN
` + }; + }); + return renderSnippet(headerSnippet, {}); + }, + cell: ({ row }) => { + const valueMN = row.original.financials?.value_mn; + + const valueSnippet = createRawSnippet<[{ value: string }]>((getValue) => { + const { value } = getValue(); + return { + render: () => + `
${value}
` + }; + }); + return renderSnippet(valueSnippet, { value: formatCurrencyMXN(valueMN) }); + } + }, + { + accessorKey: "financials.value_me", + header: () => { + const headerSnippet = createRawSnippet(() => { + return { + render: () => `
Valor ME
` + }; + }); + return renderSnippet(headerSnippet, {}); + }, + cell: ({ row }) => { + const valueME = row.original.financials?.value_me; + + const valueSnippet = createRawSnippet<[{ value: string }]>((getValue) => { + const { value } = getValue(); + return { + render: () => + `
${value}
` + }; + }); + return renderSnippet(valueSnippet, { value: formatCurrencyUSD(valueME) }); + } + }, + { + accessorKey: "traffic_light_status", + header: "Semáforo", + cell: ({ row }) => { + const status = row.original.traffic_light_status; + const colorClass = getTrafficLightColor(status); + + const statusSnippet = createRawSnippet<[{ status?: string | null; colorClass: string }]>((getStatus) => { + const { status, colorClass } = getStatus(); + return { + render: () => + ` + ${status || '-'} + ` + }; + }); + return renderSnippet(statusSnippet, { status, colorClass }); + } + }, + { + accessorKey: "invoice_date", + header: "Fecha Factura", + cell: ({ row }) => { + const dateSnippet = createRawSnippet<[{ date: string }]>((getDate) => { + const { date } = getDate(); + return { + render: () => + `
${date}
` + }; + }); + return renderSnippet(dateSnippet, { date: formatDate(row.original.invoice_date) }); + } + }, + { + id: "actions", + cell: ({ row }) => { + return renderComponent(DataTableActions, { + invoice: row.original, + onSuccess, + onDownload + }); + } + } + ]; } // Mantener compatibilidad hacia atrás -export const columns = createColumns(); +export const columns = createColumns(); \ No newline at end of file diff --git a/frontend/src/lib/components/dashboard/invoices/data-table-actions.svelte b/frontend/src/lib/components/dashboard/invoices/data-table-actions.svelte index bbb7a09f..3cd08d74 100644 --- a/frontend/src/lib/components/dashboard/invoices/data-table-actions.svelte +++ b/frontend/src/lib/components/dashboard/invoices/data-table-actions.svelte @@ -1,71 +1,80 @@ - - {#snippet child({ props })} - - {/snippet} - - - Acciones - - - showDetails = true}> - - Ver Detalles - + + {#snippet child({ props })} + + {/snippet} + + + Acciones + + + showDetails = true}> + + Ver Detalles + - - - Editar - + {#if onDownload} + onDownload(invoice)}> + + Descargar PDF + + {/if} - - showDelete = true} class="text-destructive"> - - Eliminar - - + + + Editar + + + + showDelete = true} class="text-destructive"> + + Eliminar + + - {#if showDetails} - showDetails = false} - /> + showDetails = false} + /> {/if} {#if showDelete} - showDelete = false} - {onSuccess} - /> + showDelete = false} + {onSuccess} + /> {/if} \ No newline at end of file diff --git a/frontend/src/routes/dashboard/invoices/+page.svelte b/frontend/src/routes/dashboard/invoices/+page.svelte index 6fd7fc9d..dc8f2d53 100644 --- a/frontend/src/routes/dashboard/invoices/+page.svelte +++ b/frontend/src/routes/dashboard/invoices/+page.svelte @@ -2,6 +2,7 @@ import { onMount } from 'svelte'; import { page } from '$app/stores'; import { invoicesApi, type Invoice, type OperationType } from '$lib/api/dashboard/a76/invoices'; + import { invoicesReportsApi } from '$lib/api/dashboard/a76/reports/reports-invoices'; import DataTable from '$lib/components/dashboard/invoices/data-table.svelte'; import { createColumns } from '$lib/components/dashboard/invoices/columns.js'; import * as Card from '$lib/components/ui/card'; @@ -11,7 +12,7 @@ import type { PageData } from './$types'; import { browser } from '$app/environment'; import { companyStore } from '$lib/stores/company.svelte'; - import { Plus, Filter, Trash2, RefreshCw } from 'lucide-svelte'; + import { Plus, RefreshCw } from 'lucide-svelte'; // IMPORTANTE: Asegúrate de tener instalada svelte-sonner para las notificaciones import { toast } from "svelte-sonner"; @@ -314,60 +315,24 @@ // --- NUEVA FUNCIÓN: DESCARGAR PDF --- async function handleDownloadPdf(invoice: any) { const toastId = toast.loading("Generando PDF..."); - try { - // Obtenemos el token del localStorage - const token = localStorage.getItem('access_token'); - if (!token) throw new Error('No hay sesión activa'); + // Llamada limpia + const blob = await invoicesReportsApi.downloadPdf(invoice.id, 'mex', companyStore.activeCompany.id); - // Determinar tipo: Si es importación (imp) -> mex, Si es exportación (exp) -> usa (o lo que definas) - // Por ahora hardcodeamos 'mex' como pediste - const tipo = 'mex'; - - const endpoint = `/api/v1/a76/reports/importacion/facturas/${invoice.id}/download?tipo=${tipo}&formato=pdf`; - - const response = await fetch(endpoint, { - method: 'GET', - headers: { - 'Authorization': `Bearer ${token}` - } - }); - - if (!response.ok) { - const errData = await response.json().catch(() => ({})); - throw new Error(errData.detail || 'Error al generar el reporte'); - } - - // Convertir respuesta a Blob - const blob = await response.blob(); + // Lógica de descarga (crear el link fantasma) const url = window.URL.createObjectURL(blob); - - // Crear link fantasma y descargar const a = document.createElement('a'); a.href = url; - - // Intentar usar nombre del header o fallback - const contentDisposition = response.headers.get('Content-Disposition'); - let fileName = `Factura_${invoice.invoice_number || invoice.id}.pdf`; - - if (contentDisposition) { - const match = contentDisposition.match(/filename="?([^"]+)"?/); - if (match && match[1]) fileName = match[1]; - } - - a.download = fileName; + a.download = `Factura_${invoice.invoice_number}.pdf`; document.body.appendChild(a); a.click(); - - // Limpieza window.URL.revokeObjectURL(url); document.body.removeChild(a); - - toast.success("Factura descargada", { id: toastId }); - } catch (error: any) { + toast.success("Descargado", { id: toastId }); + } catch (error) { console.error(error); - toast.error(error.message || "No se pudo descargar la factura", { id: toastId }); + toast.error("Error al descargar", { id: toastId }); } } From ce37aa77b21563d53d1480ee0221b578618255d7 Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Mon, 12 Jan 2026 16:29:07 -0600 Subject: [PATCH 03/21] Se edito el reporte de factura, se le puso las partidas, ademas se inicio todo el procedo de celery --- .../importacion/facturas/mex/schemas.py | 4 + .../importacion/facturas/mex/service.py | 174 ++++++++---------- .../a76/reports/importacion/facturas/task.py | 45 +++++ .../facturas/templates/factura_mex_ver.html | 4 + backend/core/celery_app.py | 24 +++ backend/requirements.txt | 5 + docker-compose.yml | 31 ++++ 7 files changed, 194 insertions(+), 93 deletions(-) create mode 100644 backend/api/v1/modules/a76/reports/importacion/facturas/task.py create mode 100644 backend/core/celery_app.py diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/schemas.py b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/schemas.py index e2f73cc3..a74709dc 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/schemas.py +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/schemas.py @@ -55,6 +55,10 @@ class PartidaSchema(BaseModel): descripcion: str fraccion: str origen: str + + advalorem:Optional[str] = "" + preferencia:Optional[str] = "" + cantidad_importacion: Union[float, str] unidad_medida: str cantidad_bultos: int diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py index 8f02cbd1..1e10d5d2 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py @@ -14,14 +14,16 @@ from api.v1.modules.a76.items.line_financials.models import LineFinancial from api.v1.modules.a76.items.line_quantities.models import LineQuantity from api.v1.modules.a76.items.line_items.models import LineItem from api.v1.modules.a76.clients_and_providers.models import ( - ClientProvider, - ClientProviderAddress, - ClientProviderPrograms + ClientProvider, ClientProviderAddress, ClientProviderPrograms ) from api.v1.modules.a76.parts.models import Part from api.v1.modules.a76.pedmientos.models import Pedimentos from api.v1.modules.a76.general_catalogs.company.models import Company from api.v1.modules.a76.customs_brokers.models import CustomsBroker +from api.v1.modules.a76.items.models import Item + +# --- MODELO DE FRACCIONES --- +from api.v1.modules.a76.general_catalogs.tariff_fractions.models import TariffFraction # --- SCHEMAS --- from .schemas import ( @@ -50,14 +52,16 @@ class FacturaImportacionMexService: return round(float(valor), decimales) except: return 0.0 + def _format_fraccion_fallback(self, fraccion_raw: str) -> str: + if not fraccion_raw or len(fraccion_raw) < 8: + return fraccion_raw + return f"{fraccion_raw[:4]}.{fraccion_raw[4:6]}.{fraccion_raw[6:]}" + def _obtener_datos_cliente(self, db: Session, client_id: int, rol: str) -> ClienteSchema: main = db.query(ClientProvider).filter(ClientProvider.id == client_id).first() if not main: - return ClienteSchema( - header=rol, nombre="Desconocido", direccion="", tax_id="", - codigo_postal="", ciudad="", estado="", pais="MEX" - ) - + return ClienteSchema(header=rol, nombre="Desconocido", direccion="", tax_id="", codigo_postal="", ciudad="", estado="", pais="MEX") + addr = db.query(ClientProviderAddress).filter(ClientProviderAddress.client_id == client_id).first() prog = db.query(ClientProviderPrograms).filter(ClientProviderPrograms.client_id == client_id).first() @@ -79,61 +83,32 @@ class FacturaImportacionMexService: def obtener_datos(self, db: Session, invoice_id: int, company_id: int) -> FacturaImportacionCompleta: try: - # 1. Cabecera - header = db.query(InvoiceHeader).filter( - InvoiceHeader.id == invoice_id, - InvoiceHeader.company_id == company_id - ).first() - if not header: - raise HTTPException(status_code=404, detail="Factura no encontrada") + header = db.query(InvoiceHeader).filter(InvoiceHeader.id == invoice_id, InvoiceHeader.company_id == company_id).first() + if not header: raise HTTPException(status_code=404, detail="Factura no encontrada") - # 2. Relaciones Críticas (Compliance y Logistics) - # Nota: Usamos la relación ORM 'compliance_mx' que definiste en el modelo compliance = header.compliance_mx - - # Si logistics es una lista, tomamos el primero, si no, None logistics = header.logistics[0] if header.logistics else None - - # Pedimento: Prioridad al de Compliance, si no, al de Header pedimento_id = compliance.pedimento_id if (compliance and compliance.pedimento_id) else header.related_doc_id pedimento = db.query(Pedimentos).filter(Pedimentos.id == pedimento_id).first() if pedimento_id else None - - # 3. Mapeo Actores (¡AQUÍ ESTABA EL DETALLE!) - # A) Proveedor: Sacado de compliance.provider_id proveedor_id = compliance.provider_id if compliance else None - if proveedor_id: - cliente_proveedor = self._obtener_datos_cliente(db, proveedor_id, "Proveedor / Supplier") - else: - cliente_proveedor = ClienteSchema(header="Proveedor", nombre="No Asignado", direccion="", tax_id="", - codigo_postal="", ciudad="", estado="", pais="") + cliente_proveedor = self._obtener_datos_cliente(db, proveedor_id, "Proveedor / Supplier") if proveedor_id else ClienteSchema(header="Proveedor", nombre="No Asignado", direccion="", tax_id="", codigo_postal="", ciudad="", estado="", pais="") - # B) Agente Aduanal: Sacado de compliance.customs_broker_id nombre_agente = "" if compliance and compliance.customs_broker_id: broker = db.query(CustomsBroker).filter(CustomsBroker.id == compliance.customs_broker_id).first() - if broker: - nombre_agente = broker.name # Asumiendo que CustomsBroker tiene 'name' + if broker: nombre_agente = broker.name - # C) Importador (Company) company = db.query(Company).filter(Company.id == header.company_id).first() cliente_vendido = ClienteSchema( header="Importador / Consignatario", nombre=getattr(company, 'name', "Empresa Local"), direccion="DOMICILIO FISCAL", - num_exterior="", - colonia="", - codigo_postal="", - ciudad="", - estado="", - pais="MEX", + num_exterior="", colonia="", codigo_postal="", ciudad="", estado="", pais="MEX", tax_id=getattr(company, 'rfc', ""), - programa=getattr(company, 'program', "IMMEX"), - autorizacion=getattr(company, 'program_number', "") + programa=getattr(company, 'program', "IMMEX"), autorizacion=getattr(company, 'program_number', "") ) - # 4. Mapeo Factura - # Nota: Muchos datos vienen de 'compliance', no de 'header' remesa_valor = str(compliance.remesa) if (compliance and compliance.remesa) else "" acuse_valor = str(compliance.edocument) if (compliance and compliance.edocument) else "N/A" @@ -144,30 +119,22 @@ class FacturaImportacionMexService: moneda=getattr(header, 'currency', "USD") or "USD", incoterm=logistics.incoterm if logistics else "", observaciones=header.observation_es or header.observation_en or "", - - # Pedimento y Agente pedimento=pedimento.pedimento_number if pedimento else "", clave_pedimento=pedimento.pedimento_code if pedimento else "", regimen=pedimento.regime if pedimento else "", patente=pedimento.license if pedimento else "", - agente_aduanal=nombre_agente, # Agregamos el nombre real - - # Transporte + agente_aduanal=nombre_agente, transporte=str(logistics.transport_type.value) if (logistics and logistics.transport_type) else "", num_transporte=logistics.trailer_num if logistics else "", placas=logistics.license_plate if logistics else "", - transportista=logistics.carrier_id if logistics else "", # Si carrier_id es ID, aquí habría que buscar nombre - - # Otros + transportista=logistics.carrier_id if logistics else "", aduana=pedimento.customs_office if pedimento else "", precinto=logistics.seal_number if logistics else "", destino=logistics.destination_goods if logistics else "", - remesa=remesa_valor, - acuse_electronico=acuse_valor + remesa=remesa_valor, acuse_electronico=acuse_valor ) - # 5. Mapeo Partidas - lines = db.query(LineItem).filter(LineItem.item_id == header.id).all() + lines = db.query(LineItem).join(Item, LineItem.item_id == Item.id).filter(Item.invoice_id == header.id).all() partidas_list = [] for line in lines: @@ -175,13 +142,54 @@ class FacturaImportacionMexService: fin = db.query(LineFinancial).filter(LineFinancial.item_line_id == line.id).first() part_master = db.query(Part).filter(Part.id == line.part_number).first() + desc_final = "S/D" + num_parte_final = str(line.part_number or "S/N") + fraccion_raw = "" + origen_final = "MEX" + + if part_master: + desc_final = part_master.description_spanish or part_master.description_english or "Sin Desc." + num_parte_final = part_master.part_number + fraccion_raw = part_master.fraction if part_master.fraction else "" + + # --- LÓGICA DE FRACCIÓN DESDE BASE DE DATOS --- + # Limpiar la fracción de la BD (quitar puntos y asegurar 8 dígitos) + fraccion_limpia = fraccion_raw.replace(".", "").strip() + if fraccion_limpia: + fraccion_limpia = fraccion_limpia[:8].zfill(8) + + # Consultar tabla tariff_fractions + fraccion_db = db.query(TariffFraction).filter(TariffFraction.code == fraccion_limpia).first() + + # Reglas de negocio solicitadas: + # 1. Preferencia default: "General" + # 2. AdValorem default: "0%" si no existe o es vacío + preferencia_txt = "General" + advalorem_txt = "0%" + fraccion_imprimir = fraccion_raw + + if fraccion_db: + # Si el valor en BD es None, "0", o vacío, dejarlo como "0%" o "EXENTO" + adv_db = fraccion_db.adv_impo + if adv_db and adv_db.strip() not in ["0", "0.0", "0.00", ""]: + advalorem_txt = adv_db if "%" in adv_db else f"{adv_db}%" + else: + advalorem_txt = "0%" # O podrías poner "EXENTO" si prefieres + + fraccion_imprimir = fraccion_db.fraction or fraccion_raw + else: + # Si no existe en la tabla, aplicamos el fallback visual de puntos + fraccion_imprimir = self._format_fraccion_fallback(fraccion_limpia) + partidas_list.append(PartidaSchema( - numero_parte=part_master.part_number if part_master else str(line.part_number or "S/N"), - descripcion=part_master.description_spanish if part_master else "S/D", - fraccion=part_master.fraction if part_master else "", - origen="MEX", + numero_parte=num_parte_final, + descripcion=desc_final, + fraccion=fraccion_imprimir, + origen=origen_final, + advalorem=advalorem_txt, + preferencia=preferencia_txt, cantidad_importacion=self.formatear_numero(qty.quantity if qty else 0), - unidad_medida=qty.weight_unit if qty else "KG", + unidad_medida=qty.weight_unit if qty else "PZA", cantidad_bultos=int(qty.package_quantity) if qty and qty.package_quantity else 0, clave_bultos=qty.package_key if qty else "", peso_neto=self.formatear_numero(qty.net_weight if qty else 0), @@ -190,21 +198,17 @@ class FacturaImportacionMexService: valor_total=self.formatear_numero(fin.total_commercial_value if fin else 0) )) - # 6. Totales totales = self.calcular_totales(partidas_list, Decimal(factura_schema.tipo_cambio)) return FacturaImportacionCompleta( - cliente_proveedor=cliente_proveedor, - cliente_vendido=cliente_vendido, - cliente_enviado=cliente_vendido, - factura=factura_schema, - partidas=partidas_list, - totales=totales + cliente_proveedor=cliente_proveedor, cliente_vendido=cliente_vendido, + cliente_enviado=cliente_vendido, factura=factura_schema, + partidas=partidas_list, totales=totales ) except Exception as e: print(f"Error Service A76: {e}") - raise HTTPException(status_code=500, detail=f"Error procesando datos: {str(e)}") + raise HTTPException(status_code=500, detail=f"Error: {str(e)}") def calcular_totales(self, partidas: List[PartidaSchema], tipo_cambio: Decimal) -> TotalesSchema: cant = sum(p.cantidad_importacion for p in partidas) @@ -214,40 +218,24 @@ class FacturaImportacionMexService: bultos = sum(p.cantidad_bultos for p in partidas) claves = [p.clave_bultos for p in partidas if p.clave_bultos] clave_comun = max(set(claves), key=claves.count) if claves else "" + if bultos > 1 and clave_comun and not clave_comun.endswith("S"): clave_comun += "S" tc = float(tipo_cambio) if tipo_cambio else 1.0 - return TotalesSchema( - cantidad_total=self.formatear_numero(cant), - bultos_total=bultos, - clave_bultos=clave_comun, - peso_neto_total=self.formatear_numero(peso_n), - peso_bruto_total=self.formatear_numero(peso_b), - valor_total_total=self.formatear_numero(valor), - valor_total_dolares=self.formatear_numero(valor / tc if tc > 0 else 0) + cantidad_total=self.formatear_numero(cant), bultos_total=bultos, clave_bultos=clave_comun, + peso_neto_total=self.formatear_numero(peso_n), peso_bruto_total=self.formatear_numero(peso_b), + valor_total_total=self.formatear_numero(valor), valor_total_dolares=self.formatear_numero(valor / tc if tc > 0 else 0) ) def generar_factura_completa(self, db: Session, invoice_id: int, company_id: int, formato: str = "pdf") -> Tuple[bytes, str, str]: datos = self.obtener_datos(db, invoice_id, company_id) - context = { - 'cliente_proveedor': datos.cliente_proveedor.model_dump(), - 'cliente_vendido': datos.cliente_vendido.model_dump(), - 'cliente_enviado': datos.cliente_enviado.model_dump(), - 'factura': datos.factura.model_dump(), - 'partidas': [p.model_dump() for p in datos.partidas], - 'totales': datos.totales.model_dump() + 'cliente_proveedor': datos.cliente_proveedor.model_dump(), 'cliente_vendido': datos.cliente_vendido.model_dump(), + 'cliente_enviado': datos.cliente_enviado.model_dump(), 'factura': datos.factura.model_dump(), + 'partidas': [p.model_dump() for p in datos.partidas], 'totales': datos.totales.model_dump() } - html_content = self.template.render(**context) nombre = f"Factura_{datos.factura.numero}.{formato}" - - if formato == "html": - return html_content.encode('utf-8'), nombre, "text/html" - - options = { - 'page-size': 'Letter', 'margin-top': '0.5in', 'margin-right': '0.5in', - 'margin-bottom': '0.5in', 'margin-left': '0.5in', 'encoding': "UTF-8", - 'enable-local-file-access': None - } + if formato == "html": return html_content.encode('utf-8'), nombre, "text/html" + options = {'page-size': 'Letter', 'margin-top': '0.5in', 'margin-right': '0.5in', 'margin-bottom': '0.5in', 'margin-left': '0.5in', 'encoding': "UTF-8", 'enable-local-file-access': None} pdf = pdfkit.from_string(html_content, False, options=options, configuration=self._get_wkhtmltopdf_config()) return pdf, nombre, "application/pdf" \ No newline at end of file diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/task.py b/backend/api/v1/modules/a76/reports/importacion/facturas/task.py new file mode 100644 index 00000000..d16988bb --- /dev/null +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/task.py @@ -0,0 +1,45 @@ +import base64 +import logging +from core.celery_app import celery_app +from core.database import CoreSessionLocal +from .mex.service import FacturaImportacionMexService + +logger = logging.getLogger(__name__) + +@celery_app.task(name="generar_pdf_factura_async") +def generar_pdf_factura_async(invoice_id: int, company_id: int): + """ + Esta tarea la ejecuta el Worker. No usa FastAPI, usa directamente SQLAlchemy. + """ + # 1. Abrimos conexión a la DB + db = CoreSessionLocal() + try: + logger.info(f"Worker procesando factura {invoice_id}...") + + # 2. Instanciamos el servicio de reportes + service = FacturaImportacionMexService() + + # 3. Generamos los bytes del PDF + pdf_bytes, nombre, media_type = service.generar_factura_completa( + db=db, + invoice_id=invoice_id, + company_id=company_id + ) + + # 4. Codificamos a base64 para que viaje seguro por Valkey + pdf_base64 = base64.b64encode(pdf_bytes).decode('utf-8') + + return { + "status": "success", + "file_name": nombre, + "content": pdf_base64, + "media_type": media_type + } + + except Exception as e: + logger.error(f"Error en Celery Worker: {str(e)}") + return {"status": "error", "message": str(e)} + + finally: + # 5. MUY IMPORTANTE: Cerramos la conexión para no saturar Postgres + db.close() \ No newline at end of file diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_mex_ver.html b/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_mex_ver.html index eff919ee..7d5cf1d9 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_mex_ver.html +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_mex_ver.html @@ -285,6 +285,10 @@

{{ partida.numero_parte }}

{{ partida.descripcion }}

Frac: {{ partida.fraccion }} / Orig: {{ partida.origen or 'MEX' }}

+

+ {% if partida.advalorem %}ADV: {{ partida.advalorem }}{% endif %} + {% if partida.preferencia %} / PREF: {{ partida.preferencia }}{% endif %} +

{{ partida.cantidad_importacion }}

diff --git a/backend/core/celery_app.py b/backend/core/celery_app.py new file mode 100644 index 00000000..520248ce --- /dev/null +++ b/backend/core/celery_app.py @@ -0,0 +1,24 @@ +import os +from celery import Celery + +valkey_url = os.getenv("VALKEY_URL", "redis://localhost:6379/0") + +celery_app = Celery( + "anexo76_tasks", + broker=valkey_url, + backend=valkey_url, + include=["api.v1.modules.a76.reports.importacion.facturas.task"] # Ruta al módulo donde están las tareas +) + +# Configuraciones adicionales +celery_app.conf.update( + task_track_started=True, + task_serializer="json", + accept_content=["json"], + result_serializer="json", + timezone="America/Mexico_City", + enable_utc=True, +) + +if __name__ == "__main__": + celery_app.start() \ No newline at end of file diff --git a/backend/requirements.txt b/backend/requirements.txt index 8ed4b755..ff7a7cfa 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -42,3 +42,8 @@ pylint==4.0.2 # reportes Jinja2==3.1.6 pdfkit==1.0.0 + +# Desarrollo en seguno plano +celery==5.3.6 +redis==5.0.1 +flower==2.0.1 \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 655340d1..bbca1665 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -250,6 +250,37 @@ services: memory: 1G reservations: memory: 512M +# celery + celery_worker: + build: ./backend + container_name: a76_worker + command: celery -A core.celery_app worker --loglevel=info + environment: + - VALKEY_URL=redis://valkey:6379/0 + depends_on: + - backend + - valkey + valkey: + image: valkey/valkey:7.2 + container_name: a76_valkey + restart: always + ports: + - "6379:6379" + networks: + - backend-net + + flower: + image: mher/flower + container_name: a76_flower + command: celery -A core.celery_app flower + ports: + - "5555:5555" + environment: + - CELERY_BROKER_URL=redis://valkey:6379/0 + depends_on: + - valkey + networks: + - backend-net volumes: postgres_app_data: From 6214973eafaa01d2e884783d0b1f57a65e0b0821 Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Tue, 13 Jan 2026 11:27:58 -0600 Subject: [PATCH 04/21] Implementacion de celery y problemas con relacioines --- .../importacion/facturas/mex/service.py | 11 +-- .../reports/importacion/facturas/routes.py | 66 ++++++------- .../a76/reports/importacion/facturas/task.py | 1 + backend/core/celery_app.py | 3 +- backend/core/middleware.py | 67 ++++--------- docker-compose.yml | 3 + .../dashboard/a76/reports/reports-invoices.ts | 46 +++++---- .../routes/dashboard/invoices/+page.svelte | 98 ++++++++++++++----- 8 files changed, 156 insertions(+), 139 deletions(-) diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py index 1e10d5d2..e07807f8 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py @@ -152,8 +152,7 @@ class FacturaImportacionMexService: num_parte_final = part_master.part_number fraccion_raw = part_master.fraction if part_master.fraction else "" - # --- LÓGICA DE FRACCIÓN DESDE BASE DE DATOS --- - # Limpiar la fracción de la BD (quitar puntos y asegurar 8 dígitos) + fraccion_limpia = fraccion_raw.replace(".", "").strip() if fraccion_limpia: fraccion_limpia = fraccion_limpia[:8].zfill(8) @@ -161,9 +160,7 @@ class FacturaImportacionMexService: # Consultar tabla tariff_fractions fraccion_db = db.query(TariffFraction).filter(TariffFraction.code == fraccion_limpia).first() - # Reglas de negocio solicitadas: - # 1. Preferencia default: "General" - # 2. AdValorem default: "0%" si no existe o es vacío + preferencia_txt = "General" advalorem_txt = "0%" fraccion_imprimir = fraccion_raw @@ -178,7 +175,7 @@ class FacturaImportacionMexService: fraccion_imprimir = fraccion_db.fraction or fraccion_raw else: - # Si no existe en la tabla, aplicamos el fallback visual de puntos + fraccion_imprimir = self._format_fraccion_fallback(fraccion_limpia) partidas_list.append(PartidaSchema( @@ -220,7 +217,7 @@ class FacturaImportacionMexService: clave_comun = max(set(claves), key=claves.count) if claves else "" if bultos > 1 and clave_comun and not clave_comun.endswith("S"): clave_comun += "S" tc = float(tipo_cambio) if tipo_cambio else 1.0 - return TotalesSchema( + return TotalesSchema( cantidad_total=self.formatear_numero(cant), bultos_total=bultos, clave_bultos=clave_comun, peso_neto_total=self.formatear_numero(peso_n), peso_bruto_total=self.formatear_numero(peso_b), valor_total_total=self.formatear_numero(valor), valor_total_dolares=self.formatear_numero(valor / tc if tc > 0 else 0) diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/routes.py b/backend/api/v1/modules/a76/reports/importacion/facturas/routes.py index 0049204e..4feb8f8f 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/routes.py +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/routes.py @@ -2,52 +2,44 @@ from enum import Enum from typing import Dict, Any from fastapi import APIRouter, Depends, Query, Response, HTTPException from sqlalchemy.orm import Session - +from celery.result import AsyncResult +from core.celery_app import celery_app from core.database import get_core_db from core.security import get_current_user, validate_access_to_resource from .mex.service import FacturaImportacionMexService +from .task import generar_pdf_factura_async router = APIRouter() servicio_mex = FacturaImportacionMexService() -class TipoFactura(str, Enum): - mexicana = "mex" +@router.get("/tasks/{task_id}") +async def get_task_status( + task_id: str, + current_user: Dict[str, Any] = Depends(get_current_user), + db: Session = Depends(get_core_db) +): + task_result = AsyncResult(task_id, app=celery_app) -class Formato(str, Enum): - html = "html" - pdf = "pdf" + response = { + "task_id": task_id, + "state": task_result.state, + "result": None + } -@router.get("/{invoice_id}/download") -async def descargar_factura( + if task_result.state == 'FAILURE': + response["result"] = str(task_result.result) + elif task_result.state == 'SUCCESS': + response["result"] = task_result.result + + return response + +@router.post("/{invoice_id}/download-async") +async def trigger_descarga_factura( invoice_id: int, company_id: int = Query(..., description="ID de la empresa"), - tipo: TipoFactura = Query(TipoFactura.mexicana), - formato: Formato = Query(Formato.pdf), - db: Session = Depends(get_core_db), - current_user: Dict[str, Any] = Depends(get_current_user) + current_user: Dict[str, Any] = Depends(get_current_user), + db: Session = Depends(get_core_db) ): - # Validar que el usuario tiene acceso a esta empresa - tenant_id = validate_access_to_resource(db, company_id, current_user) - - if tipo == TipoFactura.mexicana: - try: - # Pasamos invoice_id Y company_id al servicio - contenido, nombre, media_type = servicio_mex.generar_factura_completa( - db=db, - invoice_id=invoice_id, - company_id=company_id, - formato=formato.value - ) - - return Response( - content=contenido, - media_type=media_type, - headers={ - "Content-Disposition": f"attachment; filename={nombre}", - "Access-Control-Expose-Headers": "Content-Disposition" - } - ) - except Exception as e: - raise HTTPException(status_code=500, detail=str(e)) - else: - raise HTTPException(status_code=501, detail="Tipo no implementado") \ No newline at end of file + validate_access_to_resource(db, company_id, current_user) + task = generar_pdf_factura_async.delay(invoice_id, company_id) + return {"task_id": task.id, "message": "Generación iniciada"} \ No newline at end of file diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/task.py b/backend/api/v1/modules/a76/reports/importacion/facturas/task.py index d16988bb..1b859965 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/task.py +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/task.py @@ -2,6 +2,7 @@ import base64 import logging from core.celery_app import celery_app from core.database import CoreSessionLocal + from .mex.service import FacturaImportacionMexService logger = logging.getLogger(__name__) diff --git a/backend/core/celery_app.py b/backend/core/celery_app.py index 520248ce..8b95558f 100644 --- a/backend/core/celery_app.py +++ b/backend/core/celery_app.py @@ -1,7 +1,8 @@ import os from celery import Celery -valkey_url = os.getenv("VALKEY_URL", "redis://localhost:6379/0") + +valkey_url = os.getenv("VALKEY_URL", "redis://valkey:6379/0") celery_app = Celery( "anexo76_tasks", diff --git a/backend/core/middleware.py b/backend/core/middleware.py index f5d0df8a..695fd79c 100644 --- a/backend/core/middleware.py +++ b/backend/core/middleware.py @@ -1,83 +1,54 @@ -""" -Middleware personalizado para Anexo76 -- Validación de licencias -- Gestión de multi-tenancy -- Logging de requests -""" - import logging import time from typing import Callable - -from fastapi import HTTPException, Request +from fastapi import HTTPException, Request, Response from starlette.middleware.base import BaseHTTPMiddleware - from .config import settings from .database import CoreSessionLocal from .security import get_tenant_from_token, verify_token logger = logging.getLogger(__name__) - class TenantMiddleware(BaseHTTPMiddleware): - """ - Middleware para identificar y validar el tenant en cada request - """ - async def dispatch(self, request: Request, call_next: Callable): - # Rutas públicas que no requieren tenant - # Permitir acceso sin autenticación a rutas de documentación y salud - doc_prefixes = ["/api/redoc", "/api/openapi.json"] + # No validamos token, no buscamos tenant. + # Esto permite que CORSMiddleware haga su trabajo. + if request.method == "OPTIONS": + return await call_next(request) + + # 2. Definición de rutas (tal cual las tenías) + doc_prefixes = ["/api/redoc", "/api/openapi.json", "/api/docs"] public_prefixes = ["/api/v1/auth", "/api/v1/status", "/api/health", "/api/"] - path = request.url.path - # Permitir cualquier subruta de docs/redoc/openapi.json (por ejemplo, /api/docs, /api/docs/, /api/docs/oauth2-redirect) - if any( - path == prefix or path.startswith(prefix + "/") for prefix in doc_prefixes - ): + + # 3. Bypass para rutas públicas y docs + if any(path == prefix or path.startswith(prefix + "/") for prefix in doc_prefixes): return await call_next(request) - # Permitir rutas públicas exactas o con prefijo - if any( - path == prefix or (prefix != "/" and path.startswith(prefix)) - for prefix in public_prefixes - ): + + if any(path == prefix or (prefix != "/" and path.startswith(prefix)) for prefix in public_prefixes): return await call_next(request) - # Extraer token y obtener tenant + # 4. Validación estricta de Token (solo para lo que no es público ni OPTIONS) auth_header = request.headers.get("Authorization") - if not auth_header or not auth_header.startswith("Bearer "): raise HTTPException( - status_code=401, detail="Missing or invalid authorization header" + status_code=401, + detail="Missing or invalid authorization header" ) token = auth_header.split(" ")[1] - try: user_info = verify_token(token) tenant_id = get_tenant_from_token(user_info) - - # ⚠️ NOTA: tenant_id puede ser None para usuarios SSO que aún no tienen tenant asignado - # En ese caso, el endpoint específico deberá manejarlo - if not tenant_id: - logger.warning( - f"⚠️ Token sin tenant_id para usuario: {user_info.get('sub', 'unknown')}" - ) - # No lanzamos error aquí, dejamos que el endpoint decida qué hacer - - # Agregar tenant_id al state del request (puede ser None) + request.state.tenant_id = tenant_id request.state.user_info = user_info - - except HTTPException: - # Re-lanzar HTTPException directamente - raise except Exception as e: logger.error(f"❌ Tenant validation error: {str(e)}") raise HTTPException(status_code=401, detail="Invalid authentication") - response = await call_next(request) - return response + # 5. Continuar con la petición real + return await call_next(request) class LicenseValidationMiddleware(BaseHTTPMiddleware): diff --git a/docker-compose.yml b/docker-compose.yml index bbca1665..c3425493 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -260,6 +260,9 @@ services: depends_on: - backend - valkey + networks: + - backend-net + valkey: image: valkey/valkey:7.2 container_name: a76_valkey diff --git a/frontend/src/lib/api/dashboard/a76/reports/reports-invoices.ts b/frontend/src/lib/api/dashboard/a76/reports/reports-invoices.ts index 68ebafab..33c619f7 100644 --- a/frontend/src/lib/api/dashboard/a76/reports/reports-invoices.ts +++ b/frontend/src/lib/api/dashboard/a76/reports/reports-invoices.ts @@ -1,37 +1,35 @@ -// En invoices.ts -// 1. Recuperamos la URL base del entorno (así funciona igual en local y en producción) -// Nota: El nombre 'VITE_API_URL' depende de cómo lo tengan en tu proyecto. -// A veces es import.meta.env.PUBLIC_API_URL const BASE_URL = import.meta.env.VITE_API_URL || ''; export const invoicesReportsApi = { - // ... tus otros métodos ... - - downloadPdf: async (invoiceId: number, type: 'mex' | 'usa' = 'mex', companyId: number) => { - const params = new URLSearchParams({ - tipo: type, - formato: 'pdf', - company_id: companyId.toString() - }); - // 2. Usamos la variable, no el texto fijo - const endpoint = `${BASE_URL}/v1/a76/reports/importacion/facturas/${invoiceId}/download?${params.toString()}`; - - const token = localStorage.getItem('access_token'); + + triggerPdfGeneration: async (invoiceId: number, companyId: number) => { + const params = new URLSearchParams({ company_id: companyId.toString() }); + const endpoint = `${BASE_URL}/v1/a76/reports/importacion/facturas/${invoiceId}/download-async?${params.toString()}`; + const token = localStorage.getItem('access_token'); const response = await fetch(endpoint, { - method: 'GET', + method: 'POST', headers: { 'Authorization': `Bearer ${token}`, - + 'Content-Type': 'application/json' } }); - if (!response.ok) { - const error = await response.json().catch(() => ({ detail: 'Error desconocido' })); - throw new Error(error.detail || 'Error al descargar'); - } - - return response.blob(); + if (!response.ok) throw new Error('Error al iniciar la generación'); + return await response.json(); }, + + getTaskStatus: async (taskId: string) => { + const endpoint = `${BASE_URL}/v1/a76/reports/importacion/facturas/tasks/${taskId}`; + + const token = localStorage.getItem('access_token'); + const response = await fetch(endpoint, { + method: 'GET', + headers: { 'Authorization': `Bearer ${token}` } + }); + + if (!response.ok) throw new Error('Error al consultar estado'); + return await response.json(); + } }; \ No newline at end of file diff --git a/frontend/src/routes/dashboard/invoices/+page.svelte b/frontend/src/routes/dashboard/invoices/+page.svelte index dc8f2d53..51212163 100644 --- a/frontend/src/routes/dashboard/invoices/+page.svelte +++ b/frontend/src/routes/dashboard/invoices/+page.svelte @@ -312,29 +312,83 @@ } } - // --- NUEVA FUNCIÓN: DESCARGAR PDF --- - async function handleDownloadPdf(invoice: any) { - const toastId = toast.loading("Generando PDF..."); - try { - // Llamada limpia - const blob = await invoicesReportsApi.downloadPdf(invoice.id, 'mex', companyStore.activeCompany.id); - - // Lógica de descarga (crear el link fantasma) - const url = window.URL.createObjectURL(blob); - const a = document.createElement('a'); - a.href = url; - a.download = `Factura_${invoice.invoice_number}.pdf`; - document.body.appendChild(a); - a.click(); - window.URL.revokeObjectURL(url); - document.body.removeChild(a); - - toast.success("Descargado", { id: toastId }); - } catch (error) { - console.error(error); - toast.error("Error al descargar", { id: toastId }); - } + // Utilidad para convertir Base64 a Blob +function base64ToBlob(base64: string, type: string) { + const binStr = atob(base64); + const len = binStr.length; + const arr = new Uint8Array(len); + for (let i = 0; i < len; i++) { + arr[i] = binStr.charCodeAt(i); } + return new Blob([arr], { type: type }); +} + +async function handleDownloadPdf(invoice: any) { + const toastId = toast.loading("Iniciando generación de PDF..."); + + try { + // 1. Trigger: Iniciar la tarea en Celery + const { task_id } = await invoicesReportsApi.triggerPdfGeneration( + invoice.id, + companyStore.activeCompany.id + ); + + toast.loading("Procesando PDF en segundo plano...", { id: toastId }); + + // 2. Polling: Loop para verificar estado + let intentos = 0; + const maxIntentos = 30; // Timeout de seguridad (aprox 60 segs) + + const interval = setInterval(async () => { + intentos++; + try { + const statusData = await invoicesReportsApi.getTaskStatus(task_id); + + if (statusData.state === 'SUCCESS') { + clearInterval(interval); + + const result = statusData.result; // Tu dict del backend + + if (result.status === 'success') { + // 3. Convertir Base64 a Blob y Descargar + const blob = base64ToBlob(result.content, result.media_type); + + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = result.file_name; // Nombre que viene del worker + document.body.appendChild(a); + a.click(); + window.URL.revokeObjectURL(url); + document.body.removeChild(a); + + toast.success("PDF Descargado", { id: toastId }); + } else { + toast.error("Error al generar el archivo", { id: toastId }); + } + } + else if (statusData.state === 'FAILURE') { + clearInterval(interval); + toast.error("Falló la generación del PDF", { id: toastId }); + } + else if (intentos >= maxIntentos) { + clearInterval(interval); + toast.error("Tiempo de espera agotado", { id: toastId }); + } + // Si es PENDING o STARTED, el intervalo continúa... + + } catch (err) { + console.error(err); + clearInterval(interval); // Detener en caso de error de red + toast.error("Error de conexión", { id: toastId }); + } + }, 2000); // Consultar cada 2 segundos + + } catch (error) { + console.error(error); + toast.error("No se pudo iniciar la descarga", { id: toastId }); + } +} function handleCreateClick() { const params = new URLSearchParams(window.location.search); From 0c43c252a4f95b1cb3493ba02155ef4bad6c8c7e Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Tue, 13 Jan 2026 14:22:15 -0600 Subject: [PATCH 05/21] Se completo la integracion del celery en la creacion de reportes --- backend/api/v1/modules/a76/classes/models.py | 5 ++-- .../units_of_measure/models.py | 4 +++ .../v1/modules/a76/items/line_items/models.py | 17 ++++++----- .../a76/reports/importacion/facturas/task.py | 8 ++++-- backend/api/v1/modules/core/tenants/models.py | 3 +- .../components/dashboard/invoices/columns.ts | 28 +++++++++++-------- 6 files changed, 39 insertions(+), 26 deletions(-) diff --git a/backend/api/v1/modules/a76/classes/models.py b/backend/api/v1/modules/a76/classes/models.py index 58459b11..e97a2f80 100644 --- a/backend/api/v1/modules/a76/classes/models.py +++ b/backend/api/v1/modules/a76/classes/models.py @@ -17,10 +17,11 @@ from sqlalchemy import ( ) from sqlalchemy.orm import Mapped, mapped_column, relationship +from api.v1.modules.public.reference_data.material_types.models import MaterialType +from api.v1.modules.a76.general_catalogs.units_of_measure.models import UnitOfMeasure + if TYPE_CHECKING: from api.v1.modules.a76.parts.models import Part - from api.v1.modules.public.reference_data.material_types.models import MaterialType - from api.v1.modules.a76.general_catalogs.units_of_measure.models import UnitOfMeasure class Class(Base, TenantScopedMixin, TimestampMixin): diff --git a/backend/api/v1/modules/a76/general_catalogs/units_of_measure/models.py b/backend/api/v1/modules/a76/general_catalogs/units_of_measure/models.py index d33b82b6..8bf32a30 100644 --- a/backend/api/v1/modules/a76/general_catalogs/units_of_measure/models.py +++ b/backend/api/v1/modules/a76/general_catalogs/units_of_measure/models.py @@ -12,6 +12,10 @@ from sqlalchemy.orm import Mapped, mapped_column, relationship from api.v1.common.base_models import TenantScopedMixin, TimestampMixin from core.database import Base +# Import models referenced by TenantScopedMixin (Tenant, Company) to ensure they are loaded +from api.v1.modules.core.tenants.models import Tenant +from api.v1.modules.a76.general_catalogs.company.models import Company + # 1. GUniMedACE diff --git a/backend/api/v1/modules/a76/items/line_items/models.py b/backend/api/v1/modules/a76/items/line_items/models.py index ad85b357..8d9fefad 100644 --- a/backend/api/v1/modules/a76/items/line_items/models.py +++ b/backend/api/v1/modules/a76/items/line_items/models.py @@ -5,6 +5,9 @@ from sqlalchemy.orm import Mapped, mapped_column, relationship from api.v1.common.base_models import TenantScopedMixin, TimestampMixin from core.database import Base +from api.v1.modules.a76.classes.models import Class +from api.v1.modules.a76.general_catalogs.units_of_measure.models import UnitOfMeasure + if TYPE_CHECKING: from ..models import Item from ..line_financials.models import LineFinancial @@ -12,10 +15,6 @@ if TYPE_CHECKING: from ..line_customs.models import LineCustom from ..line_descriptions.models import LineDescription from ..line_references.models import LineReference - from api.v1.modules.a76.classes.models import Class - from api.v1.modules.a76.general_catalogs.units_of_measure.models import ( - UnitOfMeasure, - ) from api.v1.modules.a24.fa.fa_item_lines.models import FaLineItem @@ -35,14 +34,14 @@ class LineItem(Base, TenantScopedMixin, TimestampMixin): line_number: Mapped[int] = mapped_column(Integer) # LINEAIMPO/LINEAEXPO/LINEA # Part identification - part_number_id: Mapped[Optional[str]] = mapped_column( + part_number: Mapped[Optional[str]] = mapped_column( ForeignKey("a76.parts.id") ) # NUMPARTE - component_part_number_id: Mapped[Optional[str]] = mapped_column( + component_part_number: Mapped[Optional[str]] = mapped_column( ForeignKey("a76.parts.id") ) # NUMPARTECOM - class_id: Mapped[Optional[str]] = mapped_column( - ForeignKey("a76.classes.id") + class_code: Mapped[Optional[str]] = mapped_column( + ForeignKey("a76.classes.class_code") ) # CLASE # Unit of measure @@ -173,7 +172,7 @@ class LineItem(Base, TenantScopedMixin, TimestampMixin): back_populates="line", cascade="all, delete-orphan", uselist=False ) class_info: Mapped[Optional["Class"]] = relationship( - foreign_keys=[class_id], viewonly=True + foreign_keys=[class_code], viewonly=True ) unit_of_measure_info: Mapped[Optional["UnitOfMeasure"]] = relationship( foreign_keys=[unit_of_measure], viewonly=True diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/task.py b/backend/api/v1/modules/a76/reports/importacion/facturas/task.py index 1b859965..a4059f34 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/task.py +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/task.py @@ -1,14 +1,15 @@ import base64 import logging from core.celery_app import celery_app +from celery import current_task, states from core.database import CoreSessionLocal from .mex.service import FacturaImportacionMexService logger = logging.getLogger(__name__) -@celery_app.task(name="generar_pdf_factura_async") -def generar_pdf_factura_async(invoice_id: int, company_id: int): +@celery_app.task(name="generar_pdf_factura_async", bind=True) +def generar_pdf_factura_async(self, invoice_id: int, company_id: int): """ Esta tarea la ejecuta el Worker. No usa FastAPI, usa directamente SQLAlchemy. """ @@ -19,6 +20,9 @@ def generar_pdf_factura_async(invoice_id: int, company_id: int): # 2. Instanciamos el servicio de reportes service = FacturaImportacionMexService() + + # Update state to PROCESSING + self.update_state(state='PROCESSING', meta={'current': 1, 'total': 1, 'status': 'Generating PDF...'}) # 3. Generamos los bytes del PDF pdf_bytes, nombre, media_type = service.generar_factura_completa( diff --git a/backend/api/v1/modules/core/tenants/models.py b/backend/api/v1/modules/core/tenants/models.py index e76fd34e..579db1e7 100644 --- a/backend/api/v1/modules/core/tenants/models.py +++ b/backend/api/v1/modules/core/tenants/models.py @@ -12,8 +12,7 @@ from sqlalchemy import Enum as SQLEnum from sqlalchemy import Integer, String, Text from sqlalchemy.orm import Mapped, relationship -if TYPE_CHECKING: - from api.v1.modules.core.user_tenant.models import UserTenant +from api.v1.modules.core.user_tenant.models import UserTenant class TenantType(enum.Enum): diff --git a/frontend/src/lib/components/dashboard/invoices/columns.ts b/frontend/src/lib/components/dashboard/invoices/columns.ts index aef1f484..7a22bac0 100644 --- a/frontend/src/lib/components/dashboard/invoices/columns.ts +++ b/frontend/src/lib/components/dashboard/invoices/columns.ts @@ -13,7 +13,10 @@ function formatDate(date?: string | null): string { }); } -export function createColumns(onSuccess?: () => void): ColumnDef[] { +export function createColumns( + onSuccess?: () => void, + onDownload?: (invoice: Invoice) => void +): ColumnDef[] { return [ { accessorKey: "operation_type", @@ -29,8 +32,8 @@ export function createColumns(onSuccess?: () => void): ColumnDef[] { return { render: () => ` - ${label} - ` + ${label} + ` }; }); return renderSnippet(operationSnippet, { type: operationType }); @@ -149,7 +152,6 @@ export function createColumns(onSuccess?: () => void): ColumnDef[] { accessorKey: "total_items", header: "Total Partidas", cell: ({ row }) => { - // El total de items viene del conteo de details const totalItems = row.original.details?.length || 0; const itemsSnippet = createRawSnippet<[{ total: number }]>((getTotal) => { @@ -198,7 +200,6 @@ export function createColumns(onSuccess?: () => void): ColumnDef[] { accessorKey: "logistics.weight_type", header: "Tipo Peso", cell: ({ row }) => { - // weight_type está en logistics que es un array, tomamos el primer elemento const weightType = row.original.logistics?.weight_type; const weightSnippet = createRawSnippet<[{ type?: string | null }]>((getType) => { @@ -224,8 +225,8 @@ export function createColumns(onSuccess?: () => void): ColumnDef[] { return { render: () => ` - ${label} - ` + ${label} + ` }; }); return renderSnippet(updatedSnippet, { isUpdated }); @@ -244,8 +245,8 @@ export function createColumns(onSuccess?: () => void): ColumnDef[] { return { render: () => ` - ${label} - ` + ${label} + ` }; }); return renderSnippet(mixedSnippet, { isMixed }); @@ -267,14 +268,19 @@ export function createColumns(onSuccess?: () => void): ColumnDef[] { return renderSnippet(relDocSnippet, { relDoc }); } }, + // 2. MODIFICAMOS AQUÍ: Pasamos onDownload al componente { id: "actions", cell: ({ row }) => { - return renderComponent(DataTableActions, { invoice: row.original, onSuccess }); + return renderComponent(DataTableActions, { + invoice: row.original, + onSuccess, + onDownload + }); } } ]; } -// Mantener compatibilidad hacia atrás + export const columns = createColumns(); \ No newline at end of file From e16eafec1b4865ce2ee28b03e52a460fcc82dd27 Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Tue, 13 Jan 2026 18:05:59 -0600 Subject: [PATCH 06/21] Se esta disenando mejor la parte de partes --- .../v1/modules/a76/items/line_items/models.py | 17 +- .../modales/client-selector-dialog.svelte | 17 +- .../modales/country-selector-dialog.svelte | 145 ++++++ .../modales/currency-selector-dialog.svelte | 138 +++++ .../modales/fraction-selector-dialog.svelte | 155 ++++++ .../goods/modales/unit-measure-dialog.svelte | 8 +- .../goods/parts/class-selector-dialog.svelte | 18 +- .../dashboard/goods/parts/partForm.svelte | 260 +++++++--- .../routes/dashboard/goods/parts/+page.svelte | 479 ++++++++++++------ .../dashboard/goods/parts/+page.svelte.backup | 184 +++++++ 10 files changed, 1135 insertions(+), 286 deletions(-) create mode 100644 frontend/src/lib/components/dashboard/goods/modales/country-selector-dialog.svelte create mode 100644 frontend/src/lib/components/dashboard/goods/modales/currency-selector-dialog.svelte create mode 100644 frontend/src/lib/components/dashboard/goods/modales/fraction-selector-dialog.svelte create mode 100644 frontend/src/routes/dashboard/goods/parts/+page.svelte.backup diff --git a/backend/api/v1/modules/a76/items/line_items/models.py b/backend/api/v1/modules/a76/items/line_items/models.py index 8d9fefad..5669287c 100644 --- a/backend/api/v1/modules/a76/items/line_items/models.py +++ b/backend/api/v1/modules/a76/items/line_items/models.py @@ -1,6 +1,6 @@ from decimal import Decimal from typing import Optional, TYPE_CHECKING -from sqlalchemy import Boolean, String, Integer, Numeric, SmallInteger, ForeignKey +from sqlalchemy import Boolean, String, Integer, Numeric, SmallInteger, ForeignKey, ForeignKeyConstraint from sqlalchemy.orm import Mapped, mapped_column, relationship from api.v1.common.base_models import TenantScopedMixin, TimestampMixin from core.database import Base @@ -25,9 +25,14 @@ class LineItem(Base, TenantScopedMixin, TimestampMixin): """ __tablename__ = "item_lines" - __table_args__ = { - "schema": "a76", - } + __table_args__ = ( + ForeignKeyConstraint( + ["class_code", "tenant_id", "company_id"], + ["a76.classes.class_code", "a76.classes.tenant_id", "a76.classes.company_id"], + name="fk_item_lines_class" + ), + {"schema": "a76"}, + ) id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) item_id: Mapped[int] = mapped_column(ForeignKey("a76.items.id")) @@ -40,9 +45,7 @@ class LineItem(Base, TenantScopedMixin, TimestampMixin): component_part_number: Mapped[Optional[str]] = mapped_column( ForeignKey("a76.parts.id") ) # NUMPARTECOM - class_code: Mapped[Optional[str]] = mapped_column( - ForeignKey("a76.classes.class_code") - ) # CLASE + class_code: Mapped[Optional[str]] = mapped_column(String(8)) # CLASE # Unit of measure unit_of_measure: Mapped[Optional[str]] = mapped_column( diff --git a/frontend/src/lib/components/dashboard/goods/modales/client-selector-dialog.svelte b/frontend/src/lib/components/dashboard/goods/modales/client-selector-dialog.svelte index fadd2e9a..ed216be2 100644 --- a/frontend/src/lib/components/dashboard/goods/modales/client-selector-dialog.svelte +++ b/frontend/src/lib/components/dashboard/goods/modales/client-selector-dialog.svelte @@ -109,12 +109,14 @@ RFC Razón Social Estado - Acción {#each filteredClients as client} - + handleSelect(client)} + > {client.id} {client.rfc} @@ -138,17 +140,6 @@ {/if} - - - {/each} diff --git a/frontend/src/lib/components/dashboard/goods/modales/country-selector-dialog.svelte b/frontend/src/lib/components/dashboard/goods/modales/country-selector-dialog.svelte new file mode 100644 index 00000000..0eb36ab2 --- /dev/null +++ b/frontend/src/lib/components/dashboard/goods/modales/country-selector-dialog.svelte @@ -0,0 +1,145 @@ + + + + + + Seleccionar País + + Seleccione el país de origen del catálogo. + + + +
+ + +
+ +
+ {#if loading} +
+ +

Cargando catálogo...

+
+ {:else if filteredItems.length === 0} +
+

No se encontraron países.

+
+ {:else} + + + + M3 + MEX + AME + Descripción ES + Description EN + + + + {#each filteredItems as item} + handleSelect(item)} + > + +
+ + + {item.m3_key} + +
+
+ + {item.mex_key} + + + {item.ame_key} + + + {item.description_es} + + + {item.description_en} + +
+ {/each} +
+
+ {/if} +
+ + +
+ {filteredItems.length} registros encontrados +
+ +
+
+
diff --git a/frontend/src/lib/components/dashboard/goods/modales/currency-selector-dialog.svelte b/frontend/src/lib/components/dashboard/goods/modales/currency-selector-dialog.svelte new file mode 100644 index 00000000..2325fe34 --- /dev/null +++ b/frontend/src/lib/components/dashboard/goods/modales/currency-selector-dialog.svelte @@ -0,0 +1,138 @@ + + + + + + Seleccionar Moneda + + Seleccione el tipo de moneda del catálogo. + + + +
+ + +
+ +
+ {#if loading} +
+ +

Cargando catálogo...

+
+ {:else if filteredItems.length === 0} +
+

No se encontraron monedas.

+
+ {:else} + + + + Código + País + Factor Conversión + + + + {#each filteredItems as item} + handleSelect(item)} + > + +
+ + + {item.currency_type_code} + +
+
+ + {item.country_key || '-'} + + + {item.conversion_factor?.toFixed(4) || '-'} + +
+ {/each} +
+
+ {/if} +
+ + +
+ {filteredItems.length} registros encontrados +
+ +
+
+
diff --git a/frontend/src/lib/components/dashboard/goods/modales/fraction-selector-dialog.svelte b/frontend/src/lib/components/dashboard/goods/modales/fraction-selector-dialog.svelte new file mode 100644 index 00000000..56db8e62 --- /dev/null +++ b/frontend/src/lib/components/dashboard/goods/modales/fraction-selector-dialog.svelte @@ -0,0 +1,155 @@ + + + + + + Seleccionar Fracción Arancelaria + + Seleccione la fracción arancelaria del catálogo de clases. + + + +
+ + +
+ +
+ {#if loading} +
+ +

Cargando catálogo...

+
+ {:else if uniqueFractions.length === 0} +
+

No se encontraron fracciones.

+
+ {:else} + + + + Fracción + Descripción + Clase + + + + {#each uniqueFractions as item} + handleSelect(item)} + > + +
+ + + {item.fraction} + +
+
+ + {item.description || '-'} + + + + {item.class_code} + + +
+ {/each} +
+
+ {/if} +
+ + +
+ {uniqueFractions.length} fracciones únicas encontradas +
+ +
+
+
diff --git a/frontend/src/lib/components/dashboard/goods/modales/unit-measure-dialog.svelte b/frontend/src/lib/components/dashboard/goods/modales/unit-measure-dialog.svelte index 0deb485c..2520f8b6 100644 --- a/frontend/src/lib/components/dashboard/goods/modales/unit-measure-dialog.svelte +++ b/frontend/src/lib/components/dashboard/goods/modales/unit-measure-dialog.svelte @@ -116,7 +116,6 @@ Código Descripción - @@ -129,7 +128,7 @@ {:else} {#each items as item} handleSelect(item)} > {item.code} @@ -141,11 +140,6 @@ {/if} - - - {/each} {/if} diff --git a/frontend/src/lib/components/dashboard/goods/parts/class-selector-dialog.svelte b/frontend/src/lib/components/dashboard/goods/parts/class-selector-dialog.svelte index 5d03286a..04a8ce34 100644 --- a/frontend/src/lib/components/dashboard/goods/parts/class-selector-dialog.svelte +++ b/frontend/src/lib/components/dashboard/goods/parts/class-selector-dialog.svelte @@ -110,12 +110,14 @@ Clave Descripción UM - Acción {#each filteredItems as item} - + handleSelect(item)} + > {item.class_code} @@ -137,18 +139,6 @@ {item.unit_of_measure || '-'} - - - - {/each} diff --git a/frontend/src/lib/components/dashboard/goods/parts/partForm.svelte b/frontend/src/lib/components/dashboard/goods/parts/partForm.svelte index db5d7d67..185623d6 100644 --- a/frontend/src/lib/components/dashboard/goods/parts/partForm.svelte +++ b/frontend/src/lib/components/dashboard/goods/parts/partForm.svelte @@ -9,7 +9,9 @@ import * as Tabs from '$lib/components/ui/tabs'; import * as Card from '$lib/components/ui/card'; import * as Select from "$lib/components/ui/select"; - import { Switch } from "$lib/components/ui/switch"; + import { Switch } from "$lib/components/ui/switch"; + import { Separator } from '$lib/components/ui/separator'; + import { Badge } from '$lib/components/ui/badge'; // Iconos import { @@ -30,6 +32,9 @@ import ClassSelectorDialog from '$lib/components/dashboard/goods/parts/class-selector-dialog.svelte'; import MaterialTypeSelectorDialog from '$lib/components/dashboard/goods/modales/material-type-selector-dialog.svelte'; import UnitMeasureSelectorDialog from '$lib/components/dashboard/goods/modales/unit-measure-dialog.svelte'; + import CurrencySelectorDialog from '$lib/components/dashboard/goods/modales/currency-selector-dialog.svelte'; + import CountrySelectorDialog from '$lib/components/dashboard/goods/modales/country-selector-dialog.svelte'; + import FractionSelectorDialog from '$lib/components/dashboard/goods/modales/fraction-selector-dialog.svelte'; // --- PROPS --- let { partId = null, formType = 'inv' }: { partId?: number | null, formType?: 'inv' | 'fa' } = $props(); @@ -40,6 +45,7 @@ let loading = $state(false); let error = $state(null); + let activeTab = $state('general'); // Estado Modales let showClientModal = $state(false); @@ -47,11 +53,16 @@ let showMaterialModal = $state(false); let showUOMModal = $state(false); let showAltUOMModal = $state(false); + let showCurrencyModal = $state(false); + let showCountryModal = $state(false); + let showFractionModal = $state(false); // Descripciones Visuales let selectedClientName = $state(""); let selectedClientStatus = $state(true); let selectedClassDesc = $state(""); + let selectedCurrencyName = $state(""); + let selectedCountryName = $state(""); let selectedMaterialDesc = $state(""); // Estado Formulario @@ -60,13 +71,14 @@ part_number: '', description_spanish: '', description_english: '', - part_class: '', + part_class: '', material_type: '', unit_of_measure: 'PZ', unit_weight: 0, weight_type: 'KG', unit_cost: 0, - currency_key: 'USD', + currency_type: '', + currency_key: null, added_value: 0, value_added_type: 'USD', us_fraction: '', @@ -180,6 +192,13 @@ function handleMaterialSelect(item: any) { formData.material_type = item.key; selectedMaterialDesc = item.description; } function handleUOMSelect(item: any) { formData.unit_of_measure = item.code; } function handleAltUOMSelect(item: any) { formData.alternate_unit_measure = item.code; } + function handleCurrencySelect(currency: any) { + formData.currency_type = ''; // Catálogo no usa currency_type + formData.currency_key = currency.currency_type_code; + selectedCurrencyName = currency.currency_type_code; + } + function handleCountrySelect(country: any) { formData.origin_country = country.m3_key; selectedCountryName = country.description_es; } + function handleFractionSelect(item: any) { formData.fraction = item.fraction; } // --- SUBMIT --- async function handleSubmit() { @@ -192,51 +211,83 @@ loading = true; try { // Construimos el payload. - // Si es FA, inyectamos el objeto fa_data anidado. let commonData: any = { ...formData }; + // Si currency_key está vacío o es el default, ponerlo en null + if (!commonData.currency_key || commonData.currency_key === 'USD') { + commonData.currency_key = null; + } + if (formType === 'fa') { + // Crear fa_data con los campos específicos de FA commonData.fa_data = { sector: formData.sector, fraction_type: formData.fraction_type, origin_country: formData.origin_country }; + // IMPORTANTE: Eliminar estos campos del nivel raíz para evitar duplicados + delete commonData.sector; + delete commonData.fraction_type; + delete commonData.origin_country; } + // DEBUG: Ver qué se está enviando + console.log('Payload que se enviará:', JSON.stringify(commonData, null, 2)); + console.log('client_id:', formData.client_id); + console.log('selectedClientName:', selectedClientName); + if (isEdit && partId) { await partsApi.update(partId, commonData, activeCompanyId); } else { - await partsApi.create({ ...commonData, company_id: activeCompanyId }, activeCompanyId); + const result = await partsApi.create({ ...commonData, company_id: activeCompanyId }, activeCompanyId); + console.log('Resultado de creación:', result); + if (result.error) { + console.error('Error del backend:', result.error); + error = result.error; + return; + } } goto('/dashboard/goods/parts'); - } catch (e: any) { error = e.message || 'Error al guardar'; } finally { loading = false; } + } catch (e: any) { + console.error('Error completo:', e); + error = e.message || 'Error al guardar'; + } finally { loading = false; } } -
-
- -
-

{title}

+
+
+
+
+ +

{title}

+ + {isEdit ? "Editar" : "Nueva"} + +

- {formType === 'fa' ? 'Gestión de Activos Fijos (Q-Partes)' : 'Gestión detallada de números de parte (S-Partes).'} + {formType === 'fa' ? 'Activo Fijo' : 'Inventario'}

+ + {#if error}
⚠️ {error}
{/if} +
+ {#if formType === 'fa'}
{ e.preventDefault(); handleSubmit(); }} class="space-y-6"> - +
@@ -250,10 +301,9 @@
- showClientModal = true} class="cursor-pointer font-mono" placeholder="Seleccione..."/> + showClientModal = true} class="cursor-pointer" placeholder="Seleccione..."/>
- {#if selectedClientName}
{selectedClientName}
{/if}
@@ -288,7 +338,10 @@
- +
+ showCountryModal = true} class="cursor-pointer" placeholder="Seleccione..."/> + +
@@ -303,15 +356,23 @@
- - - {formData.currency_key} - - Extranjera (USD) - Nacional (MXN) - Euros (EUR) - - + +
+
+ + +
+ +
@@ -334,7 +395,10 @@
- +
+ showFractionModal = true} class="cursor-pointer" placeholder="Seleccione..."/> + +
@@ -408,32 +472,16 @@
- - Generales - Continuación 1 - Continuación 2 - - - -
-
- - -
-
{:else}
{ e.preventDefault(); handleSubmit(); }} class="space-y-6"> - +
@@ -492,7 +540,10 @@
- +
+ showCountryModal = true} class="cursor-pointer" placeholder="Seleccione..."/> + +
@@ -513,15 +564,23 @@

Costos, valores y peso unitario

- - - {formData.currency_key} - - Dólares (USD) - Pesos (MXN) - Euros (EUR) - - + +
+
+ + +
+ +
@@ -617,14 +676,13 @@
- showClientModal = true}/> + showClientModal = true}/>
{#if selectedClientName} -
- {selectedClientName} - {#if selectedClientStatus} Activo{:else} Inactivo{/if} +
+ {#if selectedClientStatus} Activo{:else} Inactivo{/if}
{/if}
@@ -647,7 +705,10 @@
- +
+ showFractionModal = true} class="cursor-pointer" placeholder="Seleccione..."/> + +
@@ -674,27 +735,71 @@
- - - - - - - -
-
- - -
-
{/if} +
+
+ +
+
+ +
+ {#if formType === 'fa'} + + + + General + + + + Continuación 1 + + + + Continuación 2 + + + {:else} + + + + General + + + + Opciones + + + + Opcionales 2 + + + + Otros + + + {/if} +
+
+ +
+ + +
+
@@ -702,6 +807,9 @@ + + + \ No newline at end of file + +
+
+ + +
+ + + General + + + Contacto + + + Dirección + + +
+
+ + +
+ + +
+
+
\ No newline at end of file From 0a02a3e91278e41a7cd0d3a9cb6fdeee5feefc9a Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Thu, 15 Jan 2026 13:20:34 -0600 Subject: [PATCH 08/21] Se mejoro el disenio de partes, se genero la informacion mas precisa en los reportes y se carga el logo en las instanacias de las empresas --- .../api/v1/modules/a24/fa/fa_parts/models.py | 2 +- .../v1/modules/a24/inv/inv_parts/models.py | 2 +- backend/api/v1/modules/a76/classes/models.py | 2 +- .../a76/general_catalogs/company/models.py | 2 +- .../a76/general_catalogs/company/routes.py | 101 ++- .../units_of_measure/service.py | 37 +- backend/api/v1/modules/a76/parts/models.py | 8 +- .../importacion/facturas/mex/service.py | 78 +- .../reports/importacion/facturas/routes.py | 7 +- .../a76/reports/importacion/facturas/task.py | 8 +- .../importacion/facturas/tem/schemas.py | 0 .../importacion/facturas/tem/service.py | 0 .../facturas/templates/factura_mex_ver.html | 691 ++++++++++++------ .../facturas/templates/factura_tem_hor.html | 0 .../reference_data/containers/models.py | 4 +- .../reference_data/material_types/models.py | 2 +- backend/app_data/logos/1/AS.png | Bin 0 -> 12017 bytes backend/app_data/logos/1/Agenda.png | Bin 0 -> 56276 bytes .../1/a519dfd146c1bd477bcd841afe02d7de.jpg | Bin 0 -> 40590 bytes backend/app_data/logos/1/footer.png | Bin 0 -> 72609 bytes backend/app_data/logos/1/logo2.jpg | Bin 0 -> 65870 bytes backend/app_data/logos/company_1_logo.png | Bin 0 -> 12017 bytes frontend/src/lib/api.ts | 49 +- .../lib/api/dashboard/a76/customs-brokers.ts | 4 +- .../dashboard/a76/general_catalogs/company.ts | 17 + .../general_catalogs/multi-currency-types.ts | 20 +- frontend/src/lib/api/dashboard/a76/parts.ts | 34 +- .../modales/client-selector-dialog.svelte | 11 +- .../modales/country-selector-dialog.svelte | 20 +- .../modales/currency-selector-dialog.svelte | 63 +- .../modales/fraction-selector-dialog.svelte | 89 +-- .../dashboard/goods/parts/partForm.svelte | 50 +- .../components/dashboard/invoices/columns.ts | 33 +- .../invoices/data-table-actions.svelte | 12 +- .../dashboard/invoices/data-table.svelte | 25 +- .../invoices/download-invoice-button.svelte | 90 +++ .../invoices/pdf-progress-dialog.svelte | 125 ++++ .../components/sidebar/team-switcher.svelte | 4 +- .../src/lib/components/ui/progress/index.ts | 2 + .../components/ui/progress/progress.svelte | 27 + frontend/src/lib/server/api.ts | 28 +- .../edit/[[id]]/+page.svelte | 143 +++- .../routes/dashboard/goods/parts/+page.svelte | 77 +- .../routes/dashboard/invoices/+page.svelte | 184 +++-- 44 files changed, 1536 insertions(+), 515 deletions(-) delete mode 100644 backend/api/v1/modules/a76/reports/importacion/facturas/tem/schemas.py delete mode 100644 backend/api/v1/modules/a76/reports/importacion/facturas/tem/service.py delete mode 100644 backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_tem_hor.html create mode 100644 backend/app_data/logos/1/AS.png create mode 100644 backend/app_data/logos/1/Agenda.png create mode 100644 backend/app_data/logos/1/a519dfd146c1bd477bcd841afe02d7de.jpg create mode 100644 backend/app_data/logos/1/footer.png create mode 100644 backend/app_data/logos/1/logo2.jpg create mode 100644 backend/app_data/logos/company_1_logo.png create mode 100644 frontend/src/lib/components/dashboard/invoices/download-invoice-button.svelte create mode 100644 frontend/src/lib/components/dashboard/invoices/pdf-progress-dialog.svelte create mode 100644 frontend/src/lib/components/ui/progress/index.ts create mode 100644 frontend/src/lib/components/ui/progress/progress.svelte diff --git a/backend/api/v1/modules/a24/fa/fa_parts/models.py b/backend/api/v1/modules/a24/fa/fa_parts/models.py index ba5bbe75..ad813d8e 100644 --- a/backend/api/v1/modules/a24/fa/fa_parts/models.py +++ b/backend/api/v1/modules/a24/fa/fa_parts/models.py @@ -29,7 +29,7 @@ class FaPart(Base, TenantScopedMixin, TimestampMixin): ForeignKeyConstraint( ["id"], ["a76.parts.id"], name="fk_fa_partes_master" ), - {"schema": "a24"}, + {"schema": "a24", "extend_existing": True}, ) # El ID hereda el valor de la tabla parts diff --git a/backend/api/v1/modules/a24/inv/inv_parts/models.py b/backend/api/v1/modules/a24/inv/inv_parts/models.py index 467bbc2c..5e8c76e2 100644 --- a/backend/api/v1/modules/a24/inv/inv_parts/models.py +++ b/backend/api/v1/modules/a24/inv/inv_parts/models.py @@ -32,7 +32,7 @@ class InvPart(Base, TenantScopedMixin, TimestampMixin): ForeignKeyConstraint( ["id"], ["a76.parts.id"], name="fk_inv_partes_master" ), - {"schema": "a24"}, + {"schema": "a24", "extend_existing": True}, ) # Relación 1:1 - El ID es el mismo de la tabla maestra diff --git a/backend/api/v1/modules/a76/classes/models.py b/backend/api/v1/modules/a76/classes/models.py index e97a2f80..a5288980 100644 --- a/backend/api/v1/modules/a76/classes/models.py +++ b/backend/api/v1/modules/a76/classes/models.py @@ -48,7 +48,7 @@ class Class(Base, TenantScopedMixin, TimestampMixin): "class_code", name="uq_classes_tenant_company_code", ), - {"schema": "a76"}, + {"schema": "a76", "extend_existing": True}, ) id: Mapped[int] = mapped_column(Integer, primary_key=True) diff --git a/backend/api/v1/modules/a76/general_catalogs/company/models.py b/backend/api/v1/modules/a76/general_catalogs/company/models.py index b291dbb5..a7e5e1ef 100644 --- a/backend/api/v1/modules/a76/general_catalogs/company/models.py +++ b/backend/api/v1/modules/a76/general_catalogs/company/models.py @@ -26,7 +26,7 @@ class Company(Base, TimestampMixin): __tablename__ = "company" #GEmpresa __table_args__ = ( PrimaryKeyConstraint("id", name="company_pkey"), - {"schema": "a76"}, + {"schema": "a76", "extend_existing": True}, ) # Primary key diff --git a/backend/api/v1/modules/a76/general_catalogs/company/routes.py b/backend/api/v1/modules/a76/general_catalogs/company/routes.py index 294ff490..7bbad040 100644 --- a/backend/api/v1/modules/a76/general_catalogs/company/routes.py +++ b/backend/api/v1/modules/a76/general_catalogs/company/routes.py @@ -3,8 +3,12 @@ Rutas para gestión de empresa """ from typing import List, Optional +import os +import shutil +from pathlib import Path -from fastapi import APIRouter, Depends, HTTPException, status +from fastapi import APIRouter, Depends, HTTPException, status, File, UploadFile +from fastapi.responses import FileResponse from sqlalchemy.orm import Session from core.database import get_core_db @@ -298,11 +302,98 @@ async def update_company( return CompanyResponseDTO.model_validate(updated_company) -@router.delete( - "/{company_id}", - status_code=status.HTTP_204_NO_CONTENT, - summary="Delete company", + return CompanyResponseDTO.model_validate(updated_company) + + +@router.post( + "/{company_id}/upload-logo", + response_model=dict, + summary="Upload company logo", ) +async def upload_company_logo( + company_id: int, + file: UploadFile = File(...), + db: Session = Depends(get_core_db), + current_user: dict = Depends(get_current_user), +): + """Upload logo for a company""" + tenant_id = current_user.get("tenant_id") + if not tenant_id: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Tenant ID not found in user data", + ) + + # 1. Verify company exists + company = CompanyService.get_by_id(db, company_id, tenant_id, 0) + if not company: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="Company not found", + ) + + # 2. Define upload path + # Use a persistent path: 'app_data/logos/{company_id}' + upload_dir = Path(f"app_data/logos/{company_id}") + upload_dir.mkdir(parents=True, exist_ok=True) + + # 3. Save file + # Preserve original filename + filename = file.filename or "logo.png" + file_path = upload_dir / filename + + try: + # Check if file exists and remove it to avoid accumulation if needed, + # or just overwrite (shutil.copyfileobj overwrites) + with open(file_path, "wb") as buffer: + shutil.copyfileobj(file.file, buffer) + except Exception as e: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"Could not save file: {e}", + ) + + # 4. Returns the absolute path keys + abs_path = str(file_path.absolute()) + + return {"path": abs_path} + + +@router.get( + "/{company_id}/logo/image", + summary="Get company logo image", +) +@router.get( + "/{company_id}/logo/image", + summary="Get company logo image", +) +async def get_company_logo_image( + company_id: int, + db: Session = Depends(get_core_db), + # Public endpoint to allow tags to load the image without custom headers +): + """Serve the company logo image file""" + # Security: In a stricter environment, we would use a signed short-lived URL + # or cookie-based auth. For now, checking if company exists is sufficient. + + # We find the company ignoring tenant checks for the image serving + # (Logos are generally considered semi-public assets in this context) + company = db.query(Company).filter(Company.id == company_id).first() + + if not company or not company.logo: + raise HTTPException(status_code=404, detail="Logo not found") + + file_path = Path(company.logo) + if not file_path.exists(): + # Fallback for old paths or moved files + # Check if it exists in the 'standard' location even if DB thinks otherwise + standard_path = Path(f"app_data/logos/{company_id}") / file_path.name + if standard_path.exists(): + return FileResponse(standard_path) + + raise HTTPException(status_code=404, detail="Logo file not found on server") + + return FileResponse(file_path) async def delete_company( company_id: int, db: Session = Depends(get_core_db), diff --git a/backend/api/v1/modules/a76/general_catalogs/units_of_measure/service.py b/backend/api/v1/modules/a76/general_catalogs/units_of_measure/service.py index 19304472..f032f76e 100644 --- a/backend/api/v1/modules/a76/general_catalogs/units_of_measure/service.py +++ b/backend/api/v1/modules/a76/general_catalogs/units_of_measure/service.py @@ -34,10 +34,13 @@ class BaseService: limit: int = 100, filters: Optional[Dict[str, Any]] = None, ) -> Tuple[List[Any], int]: - query = db.query(cls.model).filter( - cls.model.tenant_id == tenant_id, - cls.model.company_id == company_id, - ) + query = db.query(cls.model) + + if hasattr(cls.model, "tenant_id"): + query = query.filter(cls.model.tenant_id == tenant_id) + + if hasattr(cls.model, "company_id"): + query = query.filter(cls.model.company_id == company_id) if filters: if filters.get("code"): @@ -56,11 +59,15 @@ class BaseService: def get_by_id( cls, db: Session, id: int, tenant_id: int, company_id: int ) -> Optional[Any]: - return db.query(cls.model).filter( - cls.model.id == id, - cls.model.tenant_id == tenant_id, - cls.model.company_id == company_id, - ).first() + query = db.query(cls.model).filter(cls.model.id == id) + + if hasattr(cls.model, "tenant_id"): + query = query.filter(cls.model.tenant_id == tenant_id) + + if hasattr(cls.model, "company_id"): + query = query.filter(cls.model.company_id == company_id) + + return query.first() @classmethod def create( @@ -70,9 +77,15 @@ class BaseService: tenant_id: int, company_id: int, ) -> Any: - db_obj = cls.model( - **data.model_dump(), tenant_id=tenant_id, company_id=company_id - ) + create_kwargs = data.model_dump() + + if hasattr(cls.model, "tenant_id"): + create_kwargs["tenant_id"] = tenant_id + + if hasattr(cls.model, "company_id"): + create_kwargs["company_id"] = company_id + + db_obj = cls.model(**create_kwargs) db.add(db_obj) db.commit() db.refresh(db_obj) diff --git a/backend/api/v1/modules/a76/parts/models.py b/backend/api/v1/modules/a76/parts/models.py index db56d294..42e1d6ed 100644 --- a/backend/api/v1/modules/a76/parts/models.py +++ b/backend/api/v1/modules/a76/parts/models.py @@ -22,14 +22,16 @@ from sqlalchemy import ( # Importante usar relationship y Mapped from sqlalchemy.orm import Mapped, mapped_column, relationship +from api.v1.modules.public.reference_data.currency_types.models import CurrencyType +from api.v1.modules.a24.fa.fa_parts.models import FaPart +from api.v1.modules.a24.inv.inv_parts.models import InvPart + + if TYPE_CHECKING: from api.v1.modules.a76.classes.models import Class - from api.v1.modules.public.reference_data.currency_types.models import CurrencyType from api.v1.modules.a76.general_catalogs.units_of_measure.models import ( UnitOfMeasure, ) - from api.v1.modules.a24.fa.fa_parts.models import FaPart - from api.v1.modules.a24.inv.inv_parts.models import InvPart class Part(Base, TenantScopedMixin, TimestampMixin): diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py index e07807f8..69d502f4 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py @@ -1,8 +1,9 @@ import shutil +import base64 import pdfkit from pathlib import Path from decimal import Decimal -from typing import Tuple, List +from typing import Tuple, List, Callable, Optional from jinja2 import Environment, FileSystemLoader, select_autoescape from fastapi import HTTPException @@ -81,16 +82,19 @@ class FacturaImportacionMexService: autorizacion=prog.program_number if prog else "" ) - def obtener_datos(self, db: Session, invoice_id: int, company_id: int) -> FacturaImportacionCompleta: + def obtener_datos(self, db: Session, invoice_id: int, company_id: int, progress_callback: Optional[Callable] = None) -> FacturaImportacionCompleta: try: + if progress_callback: progress_callback(10, "Buscando factura...") header = db.query(InvoiceHeader).filter(InvoiceHeader.id == invoice_id, InvoiceHeader.company_id == company_id).first() if not header: raise HTTPException(status_code=404, detail="Factura no encontrada") compliance = header.compliance_mx - logistics = header.logistics[0] if header.logistics else None + logistics = header.logistics if header.logistics else None + if progress_callback: progress_callback(20, "Obteniendo datos de pedimento...") pedimento_id = compliance.pedimento_id if (compliance and compliance.pedimento_id) else header.related_doc_id pedimento = db.query(Pedimentos).filter(Pedimentos.id == pedimento_id).first() if pedimento_id else None + if progress_callback: progress_callback(30, "Obteniendo cliente y proveedor...") proveedor_id = compliance.provider_id if compliance else None cliente_proveedor = self._obtener_datos_cliente(db, proveedor_id, "Proveedor / Supplier") if proveedor_id else ClienteSchema(header="Proveedor", nombre="No Asignado", direccion="", tax_id="", codigo_postal="", ciudad="", estado="", pais="") @@ -112,28 +116,35 @@ class FacturaImportacionMexService: remesa_valor = str(compliance.remesa) if (compliance and compliance.remesa) else "" acuse_valor = str(compliance.edocument) if (compliance and compliance.edocument) else "N/A" + patente_val = "" + if pedimento and pedimento.license: + patente_val = pedimento.license + elif 'broker' in locals() and broker and broker.license: + patente_val = broker.license + factura_schema = FacturaSchema( numero=header.invoice_number or "S/N", fecha=str(header.invoice_date) if header.invoice_date else "", tipo_cambio=float(pedimento.exchange_rate) if pedimento and pedimento.exchange_rate else 1.0, moneda=getattr(header, 'currency', "USD") or "USD", - incoterm=logistics.incoterm if logistics else "", + incoterm=(logistics.incoterm or "") if logistics else "", observaciones=header.observation_es or header.observation_en or "", pedimento=pedimento.pedimento_number if pedimento else "", clave_pedimento=pedimento.pedimento_code if pedimento else "", regimen=pedimento.regime if pedimento else "", - patente=pedimento.license if pedimento else "", + patente=patente_val, agente_aduanal=nombre_agente, - transporte=str(logistics.transport_type.value) if (logistics and logistics.transport_type) else "", - num_transporte=logistics.trailer_num if logistics else "", - placas=logistics.license_plate if logistics else "", - transportista=logistics.carrier_id if logistics else "", + transporte=str(logistics.transport_type) if (logistics and logistics.transport_type) else "", + num_transporte=(logistics.trailer_num or "") if logistics else "", + placas=(logistics.license_plate or "") if logistics else "", + transportista=(logistics.carrier_id or "") if logistics else "", aduana=pedimento.customs_office if pedimento else "", - precinto=logistics.seal_number if logistics else "", - destino=logistics.destination_goods if logistics else "", + precinto=(logistics.seal_number or "") if logistics else "", + destino=(logistics.destination_goods or "") if logistics else "", remesa=remesa_valor, acuse_electronico=acuse_valor ) - + + if progress_callback: progress_callback(50, "Procesando partidas...") lines = db.query(LineItem).join(Item, LineItem.item_id == Item.id).filter(Item.invoice_id == header.id).all() partidas_list = [] @@ -223,16 +234,53 @@ class FacturaImportacionMexService: valor_total_total=self.formatear_numero(valor), valor_total_dolares=self.formatear_numero(valor / tc if tc > 0 else 0) ) - def generar_factura_completa(self, db: Session, invoice_id: int, company_id: int, formato: str = "pdf") -> Tuple[bytes, str, str]: - datos = self.obtener_datos(db, invoice_id, company_id) + def generar_factura_completa(self, db: Session, invoice_id: int, company_id: int, formato: str = "pdf", progress_callback: Optional[Callable] = None) -> Tuple[bytes, str, str]: + if progress_callback: progress_callback(5, "Iniciando servicio de reporte...") + datos = self.obtener_datos(db, invoice_id, company_id, progress_callback) + + if progress_callback: progress_callback(80, "Renderizando plantilla...") + + # LOGO LOGIC + logo_b64 = None + try: + # Fetch company to get logo path + # We use the passed company_id which corresponds to the active company + comp_logo = db.query(Company).filter(Company.id == company_id).first() + if comp_logo and comp_logo.logo: + p = Path(comp_logo.logo) + + # Logic robusta de búsqueda (igual que en routes.py) + target_path = p + if not target_path.exists(): + # Intentar en la ruta estándar: app_data/logos/{id}/{nombre} + # Esto cubre el caso donde solo se guardó el nombre del archivo o la ruta absoluta cambió + fallback = Path(f"app_data/logos/{company_id}") / p.name + if fallback.exists(): + target_path = fallback + + if target_path.exists(): + with open(target_path, "rb") as image_file: + encoded_string = base64.b64encode(image_file.read()).decode('utf-8') + # Detect MIME type loosely + mime = "image/png" + if target_path.suffix.lower() in ['.jpg', '.jpeg']: mime = "image/jpeg" + logo_b64 = f"data:{mime};base64,{encoded_string}" + except Exception as e: + print(f"Error loading logo: {e}") + context = { 'cliente_proveedor': datos.cliente_proveedor.model_dump(), 'cliente_vendido': datos.cliente_vendido.model_dump(), 'cliente_enviado': datos.cliente_enviado.model_dump(), 'factura': datos.factura.model_dump(), - 'partidas': [p.model_dump() for p in datos.partidas], 'totales': datos.totales.model_dump() + 'partidas': [p.model_dump() for p in datos.partidas], 'totales': datos.totales.model_dump(), + 'logo_b64': logo_b64 } html_content = self.template.render(**context) nombre = f"Factura_{datos.factura.numero}.{formato}" if formato == "html": return html_content.encode('utf-8'), nombre, "text/html" + + if progress_callback: progress_callback(90, "Generando PDF final...") options = {'page-size': 'Letter', 'margin-top': '0.5in', 'margin-right': '0.5in', 'margin-bottom': '0.5in', 'margin-left': '0.5in', 'encoding': "UTF-8", 'enable-local-file-access': None} pdf = pdfkit.from_string(html_content, False, options=options, configuration=self._get_wkhtmltopdf_config()) + + if progress_callback: progress_callback(100, "Completado") return pdf, nombre, "application/pdf" \ No newline at end of file diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/routes.py b/backend/api/v1/modules/a76/reports/importacion/facturas/routes.py index 4feb8f8f..f7c0d72d 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/routes.py +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/routes.py @@ -23,13 +23,16 @@ async def get_task_status( response = { "task_id": task_id, "state": task_result.state, - "result": None + "result": None, + "info": None } if task_result.state == 'FAILURE': response["result"] = str(task_result.result) elif task_result.state == 'SUCCESS': response["result"] = task_result.result + elif task_result.state == 'PROCESSING': + response["info"] = task_result.info return response @@ -42,4 +45,4 @@ async def trigger_descarga_factura( ): validate_access_to_resource(db, company_id, current_user) task = generar_pdf_factura_async.delay(invoice_id, company_id) - return {"task_id": task.id, "message": "Generación iniciada"} \ No newline at end of file + return {"task_id": task.id, "message": "Generación iniciada"} \ No newline at end of file diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/task.py b/backend/api/v1/modules/a76/reports/importacion/facturas/task.py index a4059f34..7b7e9783 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/task.py +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/task.py @@ -22,13 +22,17 @@ def generar_pdf_factura_async(self, invoice_id: int, company_id: int): service = FacturaImportacionMexService() # Update state to PROCESSING - self.update_state(state='PROCESSING', meta={'current': 1, 'total': 1, 'status': 'Generating PDF...'}) + self.update_state(state='PROCESSING', meta={'current': 5, 'total': 100, 'status': 'Iniciando generación...'}) + def progress_callback(progress: int, status: str): + self.update_state(state='PROCESSING', meta={'current': progress, 'total': 100, 'status': status}) + # 3. Generamos los bytes del PDF pdf_bytes, nombre, media_type = service.generar_factura_completa( db=db, invoice_id=invoice_id, - company_id=company_id + company_id=company_id, + progress_callback=progress_callback ) # 4. Codificamos a base64 para que viaje seguro por Valkey diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/tem/schemas.py b/backend/api/v1/modules/a76/reports/importacion/facturas/tem/schemas.py deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/tem/service.py b/backend/api/v1/modules/a76/reports/importacion/facturas/tem/service.py deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_mex_ver.html b/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_mex_ver.html index 7d5cf1d9..d73740b6 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_mex_ver.html +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_mex_ver.html @@ -1,79 +1,308 @@ + Factura Importacion Mexicana - {{ factura.numero }}
-
-

Factura de Importacion

-
-

+
+

Factura de Importacion

+
+

-

-


+

+


-
-
+
+
+ {% if logo_b64 %} +
+ +
+ {% endif %}

{{ cliente_proveedor.header }}

{{ cliente_proveedor.nombre }}

-

{{ cliente_proveedor.direccion }} - {% if cliente_proveedor.num_exterior %} Ext: {{ cliente_proveedor.num_exterior }}{% endif %} - {% if cliente_proveedor.num_interior %} Int: {{ cliente_proveedor.num_interior }}{% endif %} +

{{ cliente_proveedor.direccion }} + {% if cliente_proveedor.num_exterior %} Ext: {{ cliente_proveedor.num_exterior }}{% endif %} + {% if cliente_proveedor.num_interior %} Int: {{ cliente_proveedor.num_interior }}{% endif %}

-

{{ cliente_proveedor.colonia }} {% if cliente_proveedor.codigo_postal %} CP: {{ cliente_proveedor.codigo_postal }}{% endif %}

+

{{ cliente_proveedor.colonia }} {% if cliente_proveedor.codigo_postal %} CP: {{ + cliente_proveedor.codigo_postal }}{% endif %}

{{ cliente_proveedor.ciudad }}, {{ cliente_proveedor.estado }}, {{ cliente_proveedor.pais }}

-

TAX ID: {{ cliente_proveedor.tax_id }} - {% if cliente_proveedor.programa and cliente_proveedor.programa != 'Ninguno' %} - {{ cliente_proveedor.programa }}: {{ cliente_proveedor.autorizacion }} - {% endif %} +

TAX ID: {{ cliente_proveedor.tax_id }} + {% if cliente_proveedor.programa and cliente_proveedor.programa != 'Ninguno' %} + {{ cliente_proveedor.programa }}: {{ cliente_proveedor.autorizacion }} + {% endif %}


@@ -82,151 +311,178 @@
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

FACTURA:

-
-

{{ factura.numero }}

-
-

Fecha:

-
-

{{ factura.fecha }}

-
-

T. Cambio:

-
-

{{ factura.tipo_cambio }}

-
-

Pedimento:

-
-

{{ factura.pedimento }}

-
-

Clave:

-
-

{{ factura.clave_pedimento }}

-
-

Remesa:

-
-

{{ factura.remesa }}

-
-

Acuse:

-
-

{{ factura.acuse_electronico or 'N/A' }}

-
-

Agente Aduanal:

-

{{ factura.agente_aduanal or '' }}

-
-

Patente: {{ factura.patente or '' }}

-
- Regimen:{{ factura.regimen or '' }} - -

INCOTERM:

-

{{ factura.incoterm or '' }}

-
- {% if factura.precinto %} -

Precinto: {{ factura.precinto }}

- {% endif %} -
-

Aduana: {{ factura.aduana }}

-
- {% if factura.destino %} -

Destino: {{ factura.destino }}

- {% endif %} -
-
+ + +

FACTURA:

+ + +

{{ factura.numero }}

+ + + + +

Fecha:

+ + +

{{ factura.fecha }}

+ + +

T. Cambio:

+ + +

{{ factura.tipo_cambio }}

+ + + + +

Pedimento:

+ + +

{{ factura.pedimento }}

+ + +

Clave:

+ + +

{{ factura.clave_pedimento }}

+ + + + +

Remesa:

+ + +

{{ factura.remesa }}

+ + +

Acuse:

+ + +

{{ factura.acuse_electronico or 'N/A' }}

+ + + + +

Agente Aduanal:

+

{{ factura.agente_aduanal or '' }}

+ + + + +

Patente: {{ factura.patente or '' }}

+ + + Regimen:{{ + factura.regimen or '' }} + + +

INCOTERM:

+

{{ factura.incoterm or '' }}

+ + + + + {% if factura.precinto %} +

Precinto: {{ factura.precinto }}

+ {% endif %} + + +

Aduana: {{ factura.aduana }}

+ + + {% if factura.destino %} +

Destino: {{ factura.destino }}

+ {% endif %} + + + + +

{{ cliente_vendido.header }}

{{ cliente_vendido.nombre }}

-

{{ cliente_vendido.direccion }} - {% if cliente_vendido.num_exterior %} Ext: {{ cliente_vendido.num_exterior }}{% endif %} - {% if cliente_vendido.num_interior %} Int: {{ cliente_vendido.num_interior }}{% endif %} +

{{ cliente_vendido.direccion }} + {% if cliente_vendido.num_exterior %} Ext: {{ cliente_vendido.num_exterior }}{% endif %} + {% if cliente_vendido.num_interior %} Int: {{ cliente_vendido.num_interior }}{% endif %}

-

{{ cliente_vendido.colonia }} {% if cliente_vendido.codigo_postal %} CP: {{ cliente_vendido.codigo_postal }}{% endif %}

-

{{ cliente_vendido.ciudad }}, {{ cliente_vendido.estado }}, {{ cliente_vendido.pais }}

-

RFC: {{ cliente_vendido.tax_id }} - {% if cliente_vendido.programa and cliente_vendido.programa != 'Ninguno' %} - {{ cliente_vendido.programa }}: {{ cliente_vendido.autorizacion }} - {% endif %} +

{{ cliente_vendido.colonia }} {% if cliente_vendido.codigo_postal %} CP: {{ + cliente_vendido.codigo_postal }}{% endif %}

+

{{ cliente_vendido.ciudad }}, {{ cliente_vendido.estado }}, {{ cliente_vendido.pais }} +

+

RFC: {{ cliente_vendido.tax_id }} + {% if cliente_vendido.programa and cliente_vendido.programa != 'Ninguno' %} + {{ cliente_vendido.programa }}: {{ cliente_vendido.autorizacion }} + {% endif %}

{{ cliente_enviado.header }}

{{ cliente_enviado.nombre }}

-

{{ cliente_enviado.direccion }} - {% if cliente_enviado.num_exterior %} Ext: {{ cliente_enviado.num_exterior }}{% endif %} - {% if cliente_enviado.num_interior %} Int: {{ cliente_enviado.num_interior }}{% endif %} +

{{ cliente_enviado.direccion }} + {% if cliente_enviado.num_exterior %} Ext: {{ cliente_enviado.num_exterior }}{% endif %} + {% if cliente_enviado.num_interior %} Int: {{ cliente_enviado.num_interior }}{% endif %} +

+

{{ cliente_enviado.colonia }} {% if cliente_enviado.codigo_postal %} CP: {{ + cliente_enviado.codigo_postal }}{% endif %}

+

{{ cliente_enviado.ciudad }}, {{ cliente_enviado.estado }}, {{ cliente_enviado.pais }}

-

{{ cliente_enviado.colonia }} {% if cliente_enviado.codigo_postal %} CP: {{ cliente_enviado.codigo_postal }}{% endif %}

-

{{ cliente_enviado.ciudad }}, {{ cliente_enviado.estado }}, {{ cliente_enviado.pais }}

RFC: {{ cliente_enviado.tax_id }}


- - +
+ - - - - - + + + + + - + - - + + + - - + + @@ -273,51 +529,51 @@

Total

- - + + {% for partida in partidas %} - - - - - - - - - - - - {% endfor %} + + + + + + + + + + + + {% endfor %} - + @@ -355,17 +611,20 @@

{{ cliente_proveedor.nombre }}


-

Los valores expresados en esta factura son en: {{ factura.moneda }}

+

Los valores expresados en esta factura + son en: {{ factura.moneda }}

- + - - -

Transportista:

{{ factura.transportista }}

SCAC: {{ factura.scac }}

INCOTERM:

{{ factura.incoterm }}

+

Transportista:

+
+

{{ factura.transportista }}

+
+

SCAC: {{ factura.scac }}

+
+

INCOTERM:

+
+

{{ factura.incoterm }}

+

Aduana: {{ factura.aduana }}


+


+

Transporte:

-

{{ factura.transporte }}: {{ factura.num_transporte }}

CAAT: {{ factura.caat }}

+

{{ factura.transporte }}: {{ factura.num_transporte }}

+
+

CAAT: {{ factura.caat }}

+

Placas: {{ factura.placas or 'N/A' }}



+


+
+


+
-

{{ loop.index }}

-
-

{{ partida.numero_parte }}

-

{{ partida.descripcion }}

-

Frac: {{ partida.fraccion }} / Orig: {{ partida.origen or 'MEX' }}

-

- {% if partida.advalorem %}ADV: {{ partida.advalorem }}{% endif %} - {% if partida.preferencia %} / PREF: {{ partida.preferencia }}{% endif %} -

-
-

{{ partida.cantidad_importacion }}

-
-

{{ partida.unidad_medida }}

-
-

- {% if partida.cantidad_bultos != 0 %}{{ partida.cantidad_bultos }}{% endif %} - {{ partida.clave_bultos }} -

-
-

{{ partida.peso_neto }}

-
-

{{ partida.peso_bruto }}

-
-

${{ partida.valor_costo_unitario }}

-
-

${{ partida.valor_total }}

-
+

{{ loop.index }}

+
+

{{ partida.numero_parte }}

+

{{ partida.descripcion }}

+

Frac: {{ partida.fraccion }} / Orig: {{ partida.origen or 'MEX' }}

+

+ {% if partida.advalorem %}ADV: {{ partida.advalorem }}{% endif %} + {% if partida.preferencia %} / PREF: {{ partida.preferencia }}{% endif %} +

+
+

{{ partida.cantidad_importacion }}

+
+

{{ partida.unidad_medida }}

+
+

+ {% if partida.cantidad_bultos != 0 %}{{ partida.cantidad_bultos }}{% endif %} + {{ partida.clave_bultos }} +

+
+

{{ partida.peso_neto }}

+
+

{{ partida.peso_bruto }}

+
+

${{ partida.valor_costo_unitario }}

+
+

${{ partida.valor_total }}

+
@@ -332,7 +588,7 @@

- {% if totales.bultos_total != 0 %}{{ totales.bultos_total }}{% endif %} + {% if totales.bultos_total != 0 %}{{ totales.bultos_total }}{% endif %} {{ totales.clave_bultos or '' }}

-


+


Normal Por Parte

-

Declaro bajo protesta de decir verdad que la información contenida en este documento es verdadera y me hago responsable de comprobar lo aquí declarado.

+

Declaro bajo protesta de decir verdad que la información contenida en + este documento es verdadera y me hago responsable de comprobar lo aquí declarado.

+ + + + \ No newline at end of file diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_tem_hor.html b/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_tem_hor.html deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/api/v1/modules/public/reference_data/containers/models.py b/backend/api/v1/modules/public/reference_data/containers/models.py index b8d3c630..c6081c34 100644 --- a/backend/api/v1/modules/public/reference_data/containers/models.py +++ b/backend/api/v1/modules/public/reference_data/containers/models.py @@ -7,11 +7,11 @@ class Container(Base): __tablename__ = "containers" # GContenedores __table_args__ = ( PrimaryKeyConstraint("key", name="containers_pkey"), - {"schema": "public", "extend_existing": True}, # opcional + {"extend_existing": True}, # opcional ) key: Mapped[str] = mapped_column( - String(3), nullable=False + String(3), primary_key=True, nullable=False ) # mantiene ceros iniciales description: Mapped[str] = mapped_column( String(500), nullable=False diff --git a/backend/api/v1/modules/public/reference_data/material_types/models.py b/backend/api/v1/modules/public/reference_data/material_types/models.py index 04fa9478..5862649a 100644 --- a/backend/api/v1/modules/public/reference_data/material_types/models.py +++ b/backend/api/v1/modules/public/reference_data/material_types/models.py @@ -11,7 +11,7 @@ class MaterialType(Base): ) key: Mapped[str] = mapped_column( - String(10), nullable=False) # clave del material + String(10), primary_key=True, nullable=False) # clave del material type: Mapped[str] = mapped_column(String(15), nullable=False) # tipo description: Mapped[str] = mapped_column( String(256), nullable=False diff --git a/backend/app_data/logos/1/AS.png b/backend/app_data/logos/1/AS.png new file mode 100644 index 0000000000000000000000000000000000000000..0ac0a67985f7b020d10613f2a3357fbc14f66cf6 GIT binary patch literal 12017 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 O09h#|$trQ9!2bZMI!qw| literal 0 HcmV?d00001 diff --git a/backend/app_data/logos/1/Agenda.png b/backend/app_data/logos/1/Agenda.png new file mode 100644 index 0000000000000000000000000000000000000000..e7b87dfd41b18d836b1a249b10cb42cac0bfd694 GIT binary patch literal 56276 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 literal 0 HcmV?d00001 diff --git a/backend/app_data/logos/1/a519dfd146c1bd477bcd841afe02d7de.jpg b/backend/app_data/logos/1/a519dfd146c1bd477bcd841afe02d7de.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5723bd91cabc7ff6bf568785a1290c2d5ec2dd21 GIT binary patch literal 40590 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 YS-ArL04ubo`k;Z~#p2@s0N}s>*@Cw8hX4Qo literal 0 HcmV?d00001 diff --git a/backend/app_data/logos/1/footer.png b/backend/app_data/logos/1/footer.png new file mode 100644 index 0000000000000000000000000000000000000000..bd1967bd078907220a2e9478c8882229da649db5 GIT binary patch literal 72609 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 literal 0 HcmV?d00001 diff --git a/backend/app_data/logos/company_1_logo.png b/backend/app_data/logos/company_1_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0ac0a67985f7b020d10613f2a3357fbc14f66cf6 GIT binary patch literal 12017 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 O09h#|$trQ9!2bZMI!qw| literal 0 HcmV?d00001 diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 5d863da1..6f625e19 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -45,7 +45,7 @@ async function refreshToken(): Promise { if (!browser) return null; let refreshTokenValue = localStorage.getItem('refresh_token'); - + // Si no está en localStorage, intentar obtenerlo de las cookies if (!refreshTokenValue) { const getCookie = (name: string): string | null => { @@ -54,18 +54,18 @@ async function refreshToken(): Promise { if (parts.length === 2) return parts.pop()?.split(';').shift() || null; return null; }; - + refreshTokenValue = getCookie('refresh_token'); - if (refreshTokenValue) { + if (refreshTokenValue) { localStorage.setItem('refresh_token', refreshTokenValue); } } - + if (!refreshTokenValue) { console.error('❌ [API] No hay refresh token disponible'); return null; - } - + } + try { const response = await fetch(`${API_BASE_URL}/v1/auth/refresh`, { method: 'POST', @@ -93,25 +93,25 @@ async function refreshToken(): Promise { return null; } - const data = await response.json(); + const data = await response.json(); // Guardar los nuevos tokens if (data.access_token) { localStorage.setItem('access_token', data.access_token); - + if (data.refresh_token) { localStorage.setItem('refresh_token', data.refresh_token); } - + // Actualizar también las cookies const isSecure = window.location.protocol === 'https:'; const secureFlag = isSecure ? '; Secure' : ''; - + document.cookie = `access_token=${data.access_token}; path=/; max-age=${60 * 60 * 24 * 7}; SameSite=Lax${secureFlag}`; if (data.refresh_token) { document.cookie = `refresh_token=${data.refresh_token}; path=/; max-age=${60 * 60 * 24 * 30}; SameSite=Lax${secureFlag}`; } - + // Actualizar el authStore si está disponible try { const { authStore } = await import('./auth'); @@ -120,7 +120,7 @@ async function refreshToken(): Promise { // Si no se puede importar authStore, no es crítico console.warn('⚠️ [API] No se pudo actualizar authStore:', e); } - + return data.access_token; } @@ -140,7 +140,7 @@ async function fetchApi( retryCount = 0 ): Promise> { // Si ya estamos refrescando el token, esperar - if (isRefreshing && retryCount === 0) { + if (isRefreshing && retryCount === 0) { return new Promise((resolve) => { subscribeTokenRefresh((newToken) => { resolve(fetchApi(endpoint, options, 1)); @@ -149,16 +149,20 @@ async function fetchApi( } const token = getToken(); - + if (!token && !endpoint.includes('/auth/login')) { console.warn('⚠️ [API] No hay token disponible para', endpoint); } const headers: Record = { - 'Content-Type': 'application/json', ...((options.headers as Record) || {}) }; + // Only set Content-Type to application/json if not already set and body is not FormData + if (!headers['Content-Type'] && !(options.body instanceof FormData)) { + headers['Content-Type'] = 'application/json'; + } + if (token) { headers['Authorization'] = `Bearer ${token}`; } @@ -171,7 +175,7 @@ async function fetchApi( }); // Si recibimos 401 o 403 y no es el endpoint de refresh, intentar refrescar el token - if ((response.status === 401 || response.status === 403) && !endpoint.includes('/auth/refresh') && retryCount === 0) { + if ((response.status === 401 || response.status === 403) && !endpoint.includes('/auth/refresh') && retryCount === 0) { isRefreshing = true; try { @@ -226,7 +230,7 @@ async function fetchApi( // Errores de validación de FastAPI (con detail) else if (data.detail) { let errorMessage = 'Error de validación: '; - + // FastAPI devuelve errores de validación en data.detail como array if (Array.isArray(data.detail)) { const errors = data.detail.map((err: any) => { @@ -239,14 +243,14 @@ async function fetchApi( } else { errorMessage += JSON.stringify(data.detail); } - + return { error: errorMessage, status: response.status }; } } - + return { error: data.message || data.detail || 'Error en la petición', status: response.status @@ -281,7 +285,7 @@ export const api = { method: 'PUT', body: JSON.stringify(body) }), - + patch: (endpoint: string, body: any) => fetchApi(endpoint, { method: 'PATCH', @@ -314,5 +318,8 @@ export const api = { myLicense: () => api.get('/v1/licenses/my-license'), usage: (tenantId: number) => api.get(`/v1/licenses/usage/${tenantId}`), validate: (tenantId: number) => api.get(`/v1/licenses/validate/${tenantId}`) - } + }, + + // Generic request for custom needs (like file uploads) + request: (endpoint: string, options: RequestInit = {}) => fetchApi(endpoint, options) }; diff --git a/frontend/src/lib/api/dashboard/a76/customs-brokers.ts b/frontend/src/lib/api/dashboard/a76/customs-brokers.ts index f90c3404..76b7e33e 100644 --- a/frontend/src/lib/api/dashboard/a76/customs-brokers.ts +++ b/frontend/src/lib/api/dashboard/a76/customs-brokers.ts @@ -87,7 +87,7 @@ export interface CreateCustomsBrokerData { */ export const customsBrokersApi = { list: (companyId: string) => { - return api.get(`/v1/a76/customs-brokers/?company_id=${companyId}`); + return api.get(`/v1/a76/customs-brokers?company_id=${companyId}`); }, get: (brokerKey: string, companyId: string) => { @@ -95,7 +95,7 @@ export const customsBrokersApi = { }, create: (data: CreateCustomsBrokerData, companyId: string) => { - return api.post(`/v1/a76/customs-brokers/?company_id=${companyId}`, data); + return api.post(`/v1/a76/customs-brokers?company_id=${companyId}`, data); }, update: (brokerKey: string, data: CreateCustomsBrokerData, companyId: string) => { diff --git a/frontend/src/lib/api/dashboard/a76/general_catalogs/company.ts b/frontend/src/lib/api/dashboard/a76/general_catalogs/company.ts index d31e6aba..82add8d4 100644 --- a/frontend/src/lib/api/dashboard/a76/general_catalogs/company.ts +++ b/frontend/src/lib/api/dashboard/a76/general_catalogs/company.ts @@ -25,6 +25,13 @@ export interface Company { order_format_type?: string | null; ctpat_svi?: string | null; trusted_exporter_number?: string | null; + logo?: string | null; + previous_code?: number | null; + client_name?: string | null; + subassembly_mode?: string | null; + inter_db_name?: string | null; + prevalidator_key?: string | null; + seventh_amendment?: boolean; created_at: string | null; updated_at: string | null; } @@ -113,3 +120,13 @@ export async function updateCompany(id: number, data: CompanyUpdate): Promise> { return await api.delete(`/v1/a76/company/${id}`); } + +export async function uploadCompanyLogo(id: number, file: File): Promise> { + const formData = new FormData(); + formData.append('file', file); + // Use api.request to pass FormData directly without JSON.stringify + return await api.request(`/v1/a76/company/${id}/upload-logo`, { + method: 'POST', + body: formData + }); +} diff --git a/frontend/src/lib/api/dashboard/a76/general_catalogs/multi-currency-types.ts b/frontend/src/lib/api/dashboard/a76/general_catalogs/multi-currency-types.ts index a624e361..fb415397 100644 --- a/frontend/src/lib/api/dashboard/a76/general_catalogs/multi-currency-types.ts +++ b/frontend/src/lib/api/dashboard/a76/general_catalogs/multi-currency-types.ts @@ -1,5 +1,11 @@ import { api } from '$lib/api'; -import type { PaginatedResponse } from '$lib/types'; + +export interface PaginatedResponse { + page: number; + page_size: number; + total: number; + total_pages: number; +} export interface MultiCurrencyType { id: number; @@ -29,11 +35,13 @@ export interface MultiCurrencyTypeListResponse extends PaginatedResponse { items: MultiCurrencyType[]; } +import type { ApiResponse } from '$lib/api'; + export async function getMultiCurrencyTypes( companyId: number, page?: number, pageSize?: number -): Promise { +): Promise> { const params = new URLSearchParams({ company_id: companyId.toString() }); if (page) params.append('page', page.toString()); if (pageSize) params.append('page_size', pageSize.toString()); @@ -44,7 +52,7 @@ export async function getMultiCurrencyTypes( export async function getMultiCurrencyType( multiCurrencyTypeId: number, companyId: number -): Promise { +): Promise> { const params = new URLSearchParams({ company_id: companyId.toString() }); return api.get(`/v1/a76/multi-currency-types/${multiCurrencyTypeId}?${params.toString()}`); } @@ -52,7 +60,7 @@ export async function getMultiCurrencyType( export async function createMultiCurrencyType( data: MultiCurrencyTypeCreate, companyId: number -): Promise { +): Promise> { const params = new URLSearchParams({ company_id: companyId.toString() }); return api.post(`/v1/a76/multi-currency-types/?${params.toString()}`, data); } @@ -61,7 +69,7 @@ export async function updateMultiCurrencyType( multiCurrencyTypeId: number, data: MultiCurrencyTypeUpdate, companyId: number -): Promise { +): Promise> { const params = new URLSearchParams({ company_id: companyId.toString() }); return api.put( `/v1/a76/multi-currency-types/${multiCurrencyTypeId}?${params.toString()}`, @@ -72,7 +80,7 @@ export async function updateMultiCurrencyType( export async function deleteMultiCurrencyType( multiCurrencyTypeId: number, companyId: number -): Promise { +): Promise> { const params = new URLSearchParams({ company_id: companyId.toString() }); return api.delete(`/v1/a76/multi-currency-types/${multiCurrencyTypeId}?${params.toString()}`); } \ No newline at end of file diff --git a/frontend/src/lib/api/dashboard/a76/parts.ts b/frontend/src/lib/api/dashboard/a76/parts.ts index 88538db8..492c93ea 100644 --- a/frontend/src/lib/api/dashboard/a76/parts.ts +++ b/frontend/src/lib/api/dashboard/a76/parts.ts @@ -55,24 +55,24 @@ export interface Part { tenant_id: number; company_id: number; client_id: number; - + // Identificación part_number: string; commercial_part_number: string | null; - + // Descripciones y Clase description_spanish: string | null; description_english: string | null; part_class: string | null; - unit_of_measure: string | null; - + unit_of_measure: string | null; + // Costos y Pesos unit_cost: number | null; currency_key: string | null; currency_type: string | null; unit_weight: number | null; weight_type: string | null; - + // Regulatorio fraction: string | null; us_fraction: string | null; @@ -82,14 +82,14 @@ export interface Part { eccn: string | null; export_code: string | null; exclusion_symbol: string | null; - + // Estado y Media is_active: boolean; part_photo: string | null; created_at: string; updated_at: string; - + fa_data?: FaData | null; inv_data?: InvData | null; } @@ -99,7 +99,7 @@ export interface PartCreate extends Omit {} +export interface PartUpdate extends Partial { } export interface PartListResponse { @@ -112,20 +112,20 @@ export interface PartListResponse { export const partsApi = { - list: (params: { - company_id: number; - page?: number; - page_size?: number; - q?: string + list: (params: { + company_id: number; + page?: number; + page_size?: number; + q?: string }) => { const { company_id, page = 1, page_size = 50, q = '' } = params; const skip = (page - 1) * page_size; - + const query = new URLSearchParams({ company_id: company_id.toString(), skip: skip.toString(), limit: page_size.toString(), - description: q + description: q }); return api.get(`/v1/a76/parts/?${query.toString()}`); @@ -140,11 +140,11 @@ export const partsApi = { }, update: (id: number, data: PartUpdate, company_id: number) => { - return api.put(`/v1/a76/parts/${id}?company_id=${company_id}`, data); + return api.put(`/v1/a76/parts/${id}/?company_id=${company_id}`, data); }, delete: (id: number, company_id: number) => { - return api.delete(`/v1/a76/parts/${id}?company_id=${company_id}`); + return api.delete(`/v1/a76/parts/${id}/?company_id=${company_id}`); } }; \ No newline at end of file diff --git a/frontend/src/lib/components/dashboard/goods/modales/client-selector-dialog.svelte b/frontend/src/lib/components/dashboard/goods/modales/client-selector-dialog.svelte index ed216be2..c6a45fce 100644 --- a/frontend/src/lib/components/dashboard/goods/modales/client-selector-dialog.svelte +++ b/frontend/src/lib/components/dashboard/goods/modales/client-selector-dialog.svelte @@ -24,9 +24,10 @@ // Filtro reactivo local let filteredClients = $derived( clients.filter(c => - c.name.toLowerCase().includes(searchTerm.toLowerCase()) || + (c.client_or_provider === 'client' || c.client_or_provider === 'both') && + (c.name.toLowerCase().includes(searchTerm.toLowerCase()) || c.rfc.toLowerCase().includes(searchTerm.toLowerCase()) || - c.id.toString().includes(searchTerm) + c.id.toString().includes(searchTerm)) ) ); @@ -42,10 +43,8 @@ loading = true; try { - // Petición a la API - const res = await clientsProvidersApi.list(companyStore.activeCompany.id, 1, 100, { - type: 'client' - }); + // Petición a la API - Traer todos para filtrar localmente + const res = await clientsProvidersApi.list(companyStore.activeCompany.id, 1, 1000); // Normalización de respuesta const responseData = (res as any).data || res; diff --git a/frontend/src/lib/components/dashboard/goods/modales/country-selector-dialog.svelte b/frontend/src/lib/components/dashboard/goods/modales/country-selector-dialog.svelte index 27cea07f..27943e6b 100644 --- a/frontend/src/lib/components/dashboard/goods/modales/country-selector-dialog.svelte +++ b/frontend/src/lib/components/dashboard/goods/modales/country-selector-dialog.svelte @@ -5,6 +5,7 @@ import * as Table from "$lib/components/ui/table"; import { Search, Loader2, Globe } from "lucide-svelte"; import { countriesApi, type Country } from "$lib/api/dashboard/refrence_data/countries"; + import { toast } from "svelte-sonner"; // --- PROPS --- let { @@ -33,6 +34,7 @@ // Cargar datos al abrir $effect(() => { + console.log("CountrySelectorDialog: open changed", open); if (open) { loadCountries(); } @@ -40,10 +42,17 @@ async function loadCountries() { loading = true; - console.log("Cargando países..."); + console.log("CountrySelectorDialog: loading countries..."); try { - const response = await countriesApi.list(1, 300); + // FIX: Reducir tamaño de página para evitar timeouts y manejo de errores + const response = await countriesApi.list(1, 100); console.log("Respuesta países FULL:", response); + + if (response.error) { + console.error("Error API:", response.error); + toast.error(`Error al cargar países: ${response.error}`); + return; + } // Caso 1: Estructura esperada { data: { items: [...] } } if (response.data?.items && Array.isArray(response.data.items)) { @@ -69,16 +78,19 @@ loaded = true; } else { console.warn("Estructura de datos no reconocida en countriesApi.list:", response.data); + toast.error("Formato de datos de países no reconocido"); } } else { console.warn("No se encontraron países o formato incorrecto:", response); + toast.error("No se encontraron países"); } console.log(`Países cargados: ${items.length}`); - } catch (e) { - console.error("Error cargando países:", e); + } catch (e: any) { + console.error("Error cargando países (excepción):", e); + toast.error(`Excepción al cargar países: ${e.message || e}`); } finally { loading = false; } diff --git a/frontend/src/lib/components/dashboard/goods/modales/currency-selector-dialog.svelte b/frontend/src/lib/components/dashboard/goods/modales/currency-selector-dialog.svelte index 2325fe34..4add0b4a 100644 --- a/frontend/src/lib/components/dashboard/goods/modales/currency-selector-dialog.svelte +++ b/frontend/src/lib/components/dashboard/goods/modales/currency-selector-dialog.svelte @@ -3,9 +3,9 @@ import { Input } from "$lib/components/ui/input"; import * as Dialog from "$lib/components/ui/dialog"; import * as Table from "$lib/components/ui/table"; + import { toast } from "svelte-sonner"; import { Search, Loader2, DollarSign } from "lucide-svelte"; - import { getMultiCurrencyTypes, type MultiCurrencyType } from "$lib/api/dashboard/a76/general_catalogs/multi-currency-types"; - import { companyStore } from "$lib/stores/company.svelte"; + import { currencyTypesApi, type CurrencyType } from "$lib/api/dashboard/refrence_data/currency_types"; // --- PROPS --- let { @@ -13,11 +13,11 @@ onSelect }: { open: boolean, - onSelect: (item: MultiCurrencyType) => void + onSelect: (item: CurrencyType) => void } = $props(); // --- ESTADO --- - let items = $state([]); + let items = $state([]); let loading = $state(false); let searchTerm = $state(""); let loaded = $state(false); @@ -25,39 +25,50 @@ // Filtro local let filteredItems = $derived( items.filter(i => - (i.currency_type_code || "").toLowerCase().includes(searchTerm.toLowerCase()) || - (i.country_key || "").toLowerCase().includes(searchTerm.toLowerCase()) + (i.code || "").toLowerCase().includes(searchTerm.toLowerCase()) || + (i.currency_name || "").toLowerCase().includes(searchTerm.toLowerCase()) || + (i.country_description || "").toLowerCase().includes(searchTerm.toLowerCase()) ) ); // Cargar datos al abrir $effect(() => { - if (open && !loaded && companyStore.activeCompany?.id) { + if (open && !loaded) { loadCurrencies(); } }); async function loadCurrencies() { - if (!companyStore.activeCompany?.id) return; - loading = true; + console.log("CurrencySelectorDialog: loading currencies (public)..."); try { - const response = await getMultiCurrencyTypes(companyStore.activeCompany.id, 1, 100); + // FIX: Usar API pública, sin company_id + const response = await currencyTypesApi.list(1, 100); + console.log("Respuesta Monedas Public FULL:", response); - if (response?.items) { - items = response.items; - loaded = true; - } else { - console.warn("No se encontraron monedas:", response); + if (response.error) { + console.error("CurrencySelectorDialog Error:", response.error); + toast.error(`Error al cargar monedas: ${response.error}`); + return; } - } catch (e) { + + if (response.data?.items) { + items = response.data.items; + loaded = true; + console.log("CurrencySelectorDialog: loaded items", items.length); + } else { + console.warn("No se encontraron monedas (public):", response); + toast.error("No se encontraron monedas"); + } + } catch (e: any) { console.error("Error cargando monedas:", e); + toast.error(`Excepción al cargar monedas: ${e.message || e}`); } finally { loading = false; } } - function handleSelect(item: MultiCurrencyType) { + function handleSelect(item: CurrencyType) { if (onSelect) onSelect(item); open = false; } @@ -68,7 +79,7 @@ Seleccionar Moneda - Seleccione el tipo de moneda del catálogo. + Seleccione el tipo de moneda del catálogo público. @@ -76,7 +87,7 @@ @@ -96,9 +107,9 @@ - Código - País - Factor Conversión + Código + Moneda + País @@ -111,15 +122,15 @@

- {item.currency_type_code} + {item.code}
- {item.country_key || '-'} + {item.currency_name} - - {item.conversion_factor?.toFixed(4) || '-'} + + {item.country_description || '-'} {/each} diff --git a/frontend/src/lib/components/dashboard/goods/modales/fraction-selector-dialog.svelte b/frontend/src/lib/components/dashboard/goods/modales/fraction-selector-dialog.svelte index 56db8e62..ea9819ed 100644 --- a/frontend/src/lib/components/dashboard/goods/modales/fraction-selector-dialog.svelte +++ b/frontend/src/lib/components/dashboard/goods/modales/fraction-selector-dialog.svelte @@ -3,8 +3,9 @@ import { Input } from "$lib/components/ui/input"; import * as Dialog from "$lib/components/ui/dialog"; import * as Table from "$lib/components/ui/table"; + import { toast } from "svelte-sonner"; import { Search, Loader2, Hash } from "lucide-svelte"; - import { classesApi, type A76Class } from "$lib/api/dashboard/a76/classes"; + import { getTariffFractions, type TariffFraction } from "$lib/api/dashboard/a76/general_catalogs/tariff-fractions"; import { companyStore } from "$lib/stores/company.svelte"; // --- PROPS --- @@ -13,32 +14,23 @@ onSelect }: { open: boolean, - onSelect: (item: { fraction: string; description: string; class_code: string }) => void + onSelect: (item: TariffFraction) => void } = $props(); // --- ESTADO --- - let classes = $state([]); + let items = $state([]); let loading = $state(false); let searchTerm = $state(""); let loaded = $state(false); - // Extraer fracciones únicas - let uniqueFractions = $derived( - Array.from(new Set(classes.map(c => c.fraction))) - .filter(f => f && f.trim()) - .map(fraction => { - const cls = classes.find(c => c.fraction === fraction); - return { - fraction, - description: cls?.description_es || '', - class_code: cls?.class_code || '' - }; - }) - .filter(item => - item.fraction.toLowerCase().includes(searchTerm.toLowerCase()) || - item.description.toLowerCase().includes(searchTerm.toLowerCase()) || - item.class_code.toLowerCase().includes(searchTerm.toLowerCase()) - ) + // Filtro local + let filteredItems = $derived( + items.filter(i => + (i.fraction || "").includes(searchTerm) || + (i.description || "").toLowerCase().includes(searchTerm.toLowerCase()) || + (i.nico || "").includes(searchTerm) || + (i.code || "").toLowerCase().includes(searchTerm.toLowerCase()) + ) ); // Cargar datos al abrir @@ -49,41 +41,48 @@ }); async function loadFractions() { - if (!companyStore.activeCompany?.id) return; + if (!companyStore.activeCompany?.id) { + toast.error("No hay empresa seleccionada"); + return; + } loading = true; try { - const response = await classesApi.list({ - company_id: companyStore.activeCompany.id, - page: 1, - page_size: 1000 - }); + const response = await getTariffFractions(1, 1000, companyStore.activeCompany.id); + if (response.error) { + console.error("Error al cargar fracciones:", response.error); + toast.error(`Error: ${response.error}`); + return; + } + if (response.data?.items) { - classes = response.data.items; + items = response.data.items; loaded = true; } else { - console.warn("No se encontraron clases:", response); + console.warn("No se encontraron fracciones:", response); + toast.info("No se encontraron fracciones registradas"); } - } catch (e) { - console.error("Error cargando fracciones:", e); + } catch (e: any) { + console.error("Excepción cargando fracciones:", e); + toast.error(`Error de conexión: ${e.message || e}`); } finally { loading = false; } } - function handleSelect(item: { fraction: string; description: string; class_code: string }) { + function handleSelect(item: TariffFraction) { if (onSelect) onSelect(item); open = false; } - + Seleccionar Fracción Arancelaria - Seleccione la fracción arancelaria del catálogo de clases. + Seleccione la fracción arancelaria del catálogo. @@ -91,7 +90,7 @@ @@ -103,7 +102,7 @@

Cargando catálogo...

- {:else if uniqueFractions.length === 0} + {:else if filteredItems.length === 0}

No se encontraron fracciones.

@@ -111,17 +110,21 @@ - Fracción + Código + Fracción + NICO Descripción - Clase - {#each uniqueFractions as item} + {#each filteredItems as item} handleSelect(item)} > + + {item.code} +
@@ -130,14 +133,12 @@
+ + {item.nico || '-'} + {item.description || '-'} - - - {item.class_code} - -
{/each}
@@ -147,7 +148,7 @@
- {uniqueFractions.length} fracciones únicas encontradas + {filteredItems.length} registros encontrados
diff --git a/frontend/src/lib/components/dashboard/goods/parts/partForm.svelte b/frontend/src/lib/components/dashboard/goods/parts/partForm.svelte index f88b9461..99c13fe4 100644 --- a/frontend/src/lib/components/dashboard/goods/parts/partForm.svelte +++ b/frontend/src/lib/components/dashboard/goods/parts/partForm.svelte @@ -19,6 +19,7 @@ FileText, Settings, Image as ImageIcon, FolderSearch, UserCheck, CheckCircle2, XCircle, Tag, Layers, Scale, Info, Briefcase, ShieldCheck, Globe } from 'lucide-svelte'; + import { toast } from "svelte-sonner"; // Stores & APIs import { companyStore } from '$lib/stores/company.svelte'; @@ -78,7 +79,7 @@ weight_type: 'KG', unit_cost: 0, currency_type: '', - currency_key: null, + currency_key: null as string | null, added_value: 0, value_added_type: 'USD', us_fraction: '', @@ -144,6 +145,10 @@ sector: d.fa_data?.sector || '', fraction_type: d.fa_data?.fraction_type || '' }; + // Ensure currency_type is mapped correctly if coming from DB (optional, depending on DB values) + if (d.currency_key === 'MXN') formData.currency_type = 'NA'; + else if (d.currency_key === 'USD') formData.currency_type = 'EX'; + if (d.client_id) await fetchClientName(d.client_id, companyId); if (d.part_class) await fetchClassDesc(d.part_class, companyId); if (d.inv_data?.material_type) await fetchMaterialName(d.inv_data.material_type); @@ -151,6 +156,18 @@ } catch (e) { console.error(e); } finally { loading = false; } } + // --- EFECTOS REACTIVOS --- + $effect(() => { + // Auto-set currency based on type selection + if (formData.currency_type === 'NA') { + formData.currency_key = 'MXN'; + selectedCurrencyName = 'MXN'; + } else if (formData.currency_type === 'EX') { + formData.currency_key = 'USD'; + selectedCurrencyName = 'USD'; + } + }); + // --- HELPERS VISUALES --- async function fetchClientName(clientId: number, companyId: number) { try { @@ -192,11 +209,17 @@ function handleUOMSelect(item: any) { formData.unit_of_measure = item.code; } function handleAltUOMSelect(item: any) { formData.alternate_unit_measure = item.code; } function handleCurrencySelect(currency: any) { - formData.currency_type = ''; - formData.currency_key = currency.currency_type_code; - selectedCurrencyName = currency.currency_type_code; + formData.currency_type = ''; // Reset type legacy field + // FIX: Usar 'code' de la API pública currency_types + const code = currency.code || currency.currency_type_code; + formData.currency_key = code; + selectedCurrencyName = code; + } + function handleCountrySelect(country: any) { + // FIX: Asegurar que se asigna la clave correcta + formData.origin_country = country.m3_key || country.country_key; + selectedCountryName = country.description_es; } - function handleCountrySelect(country: any) { formData.origin_country = country.m3_key; selectedCountryName = country.description_es; } function handleFractionSelect(item: any) { formData.fraction = item.fraction; } // --- SUBMIT --- @@ -224,15 +247,28 @@ delete commonData.origin_country; } + console.log("Submitting Part Data:", { + isEdit, + partId, + commonData + }); + if (isEdit && partId) { - await partsApi.update(partId, commonData, activeCompanyId); + // TODO: Verify partId is number/string as expected + const res = await partsApi.update(Number(partId), commonData, activeCompanyId); + console.log("Update Response:", res); + if (res.error) throw new Error(res.error); } else { const result = await partsApi.create({ ...commonData, company_id: activeCompanyId }, activeCompanyId); + console.log("Create Response:", result); if (result.error) { error = result.error; return; } } + toast.success(isEdit ? "Parte actualizada" : "Parte creada"); goto('/dashboard/goods/parts'); } catch (e: any) { + console.error("Submit Error:", e); error = e.message || 'Error al guardar'; + toast.error(error); } finally { loading = false; } } @@ -527,7 +563,7 @@
- showClassModal = true}/> +
diff --git a/frontend/src/lib/components/dashboard/invoices/columns.ts b/frontend/src/lib/components/dashboard/invoices/columns.ts index 7a22bac0..ead71f11 100644 --- a/frontend/src/lib/components/dashboard/invoices/columns.ts +++ b/frontend/src/lib/components/dashboard/invoices/columns.ts @@ -14,10 +14,36 @@ function formatDate(date?: string | null): string { } export function createColumns( - onSuccess?: () => void, - onDownload?: (invoice: Invoice) => void + onSuccess?: () => void ): ColumnDef[] { return [ + // 0. NUEVA COLUMNA: Checkbox visual (el estado real lo maneja la opacidad) + { + id: "select", + header: ({ table }) => { + return renderSnippet( + createRawSnippet(() => ({ + render: () => `
` + })) + ); + }, + cell: ({ row }) => { + const isSelected = row.getIsSelected(); + + const checkboxSnippet = createRawSnippet<[{ selected: boolean }]>((getProps) => { + const { selected } = getProps(); + return { + render: () => `
+ +
` + }; + }); + + return renderSnippet(checkboxSnippet, { selected: isSelected }); + }, + enableSorting: false, + enableHiding: false, + }, { accessorKey: "operation_type", header: "Operación", @@ -274,8 +300,7 @@ export function createColumns( cell: ({ row }) => { return renderComponent(DataTableActions, { invoice: row.original, - onSuccess, - onDownload + onSuccess }); } } diff --git a/frontend/src/lib/components/dashboard/invoices/data-table-actions.svelte b/frontend/src/lib/components/dashboard/invoices/data-table-actions.svelte index 3cd08d74..6144ee75 100644 --- a/frontend/src/lib/components/dashboard/invoices/data-table-actions.svelte +++ b/frontend/src/lib/components/dashboard/invoices/data-table-actions.svelte @@ -3,19 +3,17 @@ import { Button } from '$lib/components/ui/button'; import * as DropdownMenu from '$lib/components/ui/dropdown-menu'; // 1. Agregamos FileDown a los imports - import { Ellipsis, Eye, Pencil, Trash2, FileDown } from 'lucide-svelte'; + import { Ellipsis, Eye, Pencil, Trash2 } from 'lucide-svelte'; import DetailsDialog from './details-dialog.svelte'; import DeleteDialog from './delete-dialog.svelte'; interface Props { invoice: Invoice; onSuccess?: () => void; - // 2. Definimos la nueva prop (opcional para que no rompa si no se pasa) - onDownload?: (invoice: Invoice) => void; } // 3. Desestructuramos onDownload de los props - let { invoice, onSuccess, onDownload }: Props = $props(); + let { invoice, onSuccess }: Props = $props(); let showDetails = $state(false); let showDelete = $state(false); @@ -44,12 +42,6 @@ Ver Detalles - {#if onDownload} - onDownload(invoice)}> - - Descargar PDF - - {/if} diff --git a/frontend/src/lib/components/dashboard/invoices/data-table.svelte b/frontend/src/lib/components/dashboard/invoices/data-table.svelte index ef98de23..10c61ad2 100644 --- a/frontend/src/lib/components/dashboard/invoices/data-table.svelte +++ b/frontend/src/lib/components/dashboard/invoices/data-table.svelte @@ -13,6 +13,9 @@ loading: boolean; hasMore: boolean; loadMore: () => void; + // Props para selección + selectedId?: number | null; + onRowClick?: (row: TData) => void; }; let { @@ -20,7 +23,9 @@ columns, loading, hasMore, - loadMore + loadMore, + selectedId = null, + onRowClick }: DataTableProps = $props(); const table = createSvelteTable({ @@ -28,7 +33,17 @@ return data; }, columns, - getCoreRowModel: getCoreRowModel() + getCoreRowModel: getCoreRowModel(), + getRowId: (row: any) => row.id?.toString(), // Usar ID para identificar filas + state: { + get rowSelection() { + // Mapear el ID seleccionado al formato que espera TanStack Table + return selectedId ? { [selectedId]: true } : {}; + } + }, + enableRowSelection: true, + enableMultiRowSelection: false, // Solo permitir una selección a la vez + // No necesitamos onRowSelectionChange porque controlamos el estado desde fuera }); let scrollContainer = $state(); @@ -80,7 +95,11 @@ {#each table.getRowModel().rows as row (row.id)} - + onRowClick && onRowClick(row.original)} + > {#each row.getVisibleCells() as cell (cell.id)} + import { Button } from '$lib/components/ui/button'; + import { FileDown, LoaderCircle } from 'lucide-svelte'; + import { toast } from 'svelte-sonner'; + import { invoicesReportsApi } from '$lib/api/dashboard/a76/reports/reports-invoices'; + + export let invoiceId: number; + export let companyId: number; + + let processing = false; + + async function startDownload() { + if (processing) return; + + processing = true; + const toastId = toast.loading('Iniciando generación de PDF...'); + + try { + const { task_id } = await invoicesReportsApi.triggerPdfGeneration(invoiceId, companyId); + + const pollInterval = setInterval(async () => { + try { + const statusData = await invoicesReportsApi.getTaskStatus(task_id); + + if (statusData.state === 'SUCCESS') { + clearInterval(pollInterval); + toast.success('Factura generada correctamente', { id: toastId }); + + const { content, file_name, media_type } = statusData.result; + downloadBase64File(content, media_type, file_name); + + processing = false; + + } else if (statusData.state === 'FAILURE') { + clearInterval(pollInterval); + throw new Error(statusData.result || 'Error desconocido'); + + } else if (statusData.state === 'PROCESSING') { + const meta = statusData.result; + if (meta && typeof meta === 'object') { + const current = meta.current || 0; + const total = meta.total || 100; + const progress = Math.round((current / total) * 100); + // Update toast with progress + toast.loading(`Generando PDF: ${progress}%`, { + id: toastId, + description: meta.status || 'Procesando...' + }); + } + } + } catch (err: any) { + clearInterval(pollInterval); + handleError(err, toastId); + } + }, 1000); + + } catch (err: any) { + handleError(err, toastId); + } + } + + function handleError(err: any, toastId: string | number) { + processing = false; + console.error(err); + toast.error('Error al generar PDF: ' + (err.message || 'Error desconocido'), { id: toastId }); + } + + function downloadBase64File(base64Data: string, contentType: string, fileName: string) { + const linkSource = `data:${contentType};base64,${base64Data}`; + const downloadLink = document.createElement("a"); + downloadLink.href = linkSource; + downloadLink.download = fileName; + downloadLink.click(); + } + + + diff --git a/frontend/src/lib/components/dashboard/invoices/pdf-progress-dialog.svelte b/frontend/src/lib/components/dashboard/invoices/pdf-progress-dialog.svelte new file mode 100644 index 00000000..d774b867 --- /dev/null +++ b/frontend/src/lib/components/dashboard/invoices/pdf-progress-dialog.svelte @@ -0,0 +1,125 @@ + + + + + + Generando PDF + + Por favor espere mientras se genera su documento. + + + +
+
+ {statusMessage} + {progress}% +
+ + + +
+ {#if isComplete} +
+ + Listo para descargar +
+ {:else if hasError} +
+ + Ocurrió un error +
+ {:else} +
+ +
+ {/if} +
+
+ + + {#if hasError} + + {/if} + +
+
diff --git a/frontend/src/lib/components/sidebar/team-switcher.svelte b/frontend/src/lib/components/sidebar/team-switcher.svelte index c57880c1..7916a006 100644 --- a/frontend/src/lib/components/sidebar/team-switcher.svelte +++ b/frontend/src/lib/components/sidebar/team-switcher.svelte @@ -26,7 +26,7 @@ > {#if companyStore.activeCompany?.logo} {companyStore.activeCompany.name} @@ -75,7 +75,7 @@
{#if company.logo} {company.name} diff --git a/frontend/src/lib/components/ui/progress/index.ts b/frontend/src/lib/components/ui/progress/index.ts new file mode 100644 index 00000000..0477d4ff --- /dev/null +++ b/frontend/src/lib/components/ui/progress/index.ts @@ -0,0 +1,2 @@ + +export { default as Progress } from "./progress.svelte"; diff --git a/frontend/src/lib/components/ui/progress/progress.svelte b/frontend/src/lib/components/ui/progress/progress.svelte new file mode 100644 index 00000000..1a45e279 --- /dev/null +++ b/frontend/src/lib/components/ui/progress/progress.svelte @@ -0,0 +1,27 @@ + + +
+
+
diff --git a/frontend/src/lib/server/api.ts b/frontend/src/lib/server/api.ts index d40b5594..94ceeb78 100644 --- a/frontend/src/lib/server/api.ts +++ b/frontend/src/lib/server/api.ts @@ -12,19 +12,19 @@ import { redirect, type Cookies } from '@sveltejs/kit'; export function getServerApiUrl(): string { // Primero intentar con INTERNAL_API_URL (para llamadas server-side en Docker) let apiUrl = process.env.INTERNAL_API_URL; - + // Si no está definida, usar VITE_API_URL del entorno runtime (no import.meta.env) if (!apiUrl) { apiUrl = process.env.VITE_API_URL; } - + // Como último recurso, usar el valor de build-time if (!apiUrl) { apiUrl = import.meta.env.VITE_API_URL; // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend').replace('anexo76-dev.aduanasoft.com', 'backend'); } - + // Normalizar la URL: asegurar que termine con '/' return apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; } @@ -43,8 +43,8 @@ export function getAuthTokens(cookies: Cookies) { * Establece los tokens de autenticación en las cookies */ export function setAuthTokens( - cookies: Cookies, - accessToken: string, + cookies: Cookies, + accessToken: string, refreshToken?: string ) { cookies.set('access_token', accessToken, { @@ -54,7 +54,7 @@ export function setAuthTokens( secure: process.env.NODE_ENV === 'production', maxAge: 60 * 60 * 24 * 7 // 7 días }); - + if (refreshToken) { cookies.set('refresh_token', refreshToken, { path: '/', @@ -95,7 +95,7 @@ export async function refreshAccessToken( fetch: typeof globalThis.fetch ): Promise { const { refreshToken } = getAuthTokens(cookies); - + if (!refreshToken) { return null; } @@ -115,10 +115,10 @@ export async function refreshAccessToken( } const data = await response.json(); - + // Actualizar las cookies con los nuevos tokens setAuthTokens(cookies, data.access_token, data.refresh_token); - + return data.access_token; } catch (error) { console.error('🔄 [API] Error al refrescar token:', error); @@ -210,9 +210,9 @@ export async function authenticatedFetch( if (error && typeof error === 'object' && 'status' in error && 'location' in error) { throw error; } - + console.error('🔴 [API] Error en authenticatedFetch:', endpoint, error); - + // Retornar una respuesta de error simulada en lugar de lanzar return new Response(JSON.stringify({ error: 'Network error', details: String(error) }), { status: 500, @@ -253,14 +253,14 @@ export async function validateAuth( if (error && typeof error === 'object' && 'status' in error && 'location' in error) { throw error; } - + console.error('🔐 [API] Error validando autenticación:', error); - + if (redirectOnFail) { clearAuthTokens(cookies); throw redirect(303, redirectOnFail); } - + return null; } } diff --git a/frontend/src/routes/dashboard/general_catalogs/company_information/edit/[[id]]/+page.svelte b/frontend/src/routes/dashboard/general_catalogs/company_information/edit/[[id]]/+page.svelte index 36d0cfa7..cefe2d0d 100644 --- a/frontend/src/routes/dashboard/general_catalogs/company_information/edit/[[id]]/+page.svelte +++ b/frontend/src/routes/dashboard/general_catalogs/company_information/edit/[[id]]/+page.svelte @@ -11,9 +11,11 @@ createCompany, updateCompany, getCompany, // Asumiendo que esta función existe en tu API + uploadCompanyLogo, type Company } from '$lib/api/dashboard/a76/general_catalogs/company'; - import { ArrowLeft, LoaderCircle, Save } from 'lucide-svelte'; + import { ArrowLeft, LoaderCircle, Save, Upload } from 'lucide-svelte'; + import { companyStore } from '$lib/stores/company.svelte'; // 1. Lógica de Navegación y Modo const id = $derived($page.params.id); @@ -21,9 +23,10 @@ const title = $derived(isEdit ? "Editar Empresa" : "Nueva Empresa"); let loading = $state(false); + let uploading = $state(false); let error = $state(null); - // 2. Estado Inicial (Reset) + // ... (Initial Data) ... const initialData = { name: '', rfc: '', @@ -43,12 +46,20 @@ is_service_company: false, order_format_type: '', ctpat_svi: '', - trusted_exporter_number: '' + trusted_exporter_number: '', + logo: '', + previous_code: 0, + client_name: '', + subassembly_mode: '', + broker_company: '', + inter_db_name: '', + prevalidator_key: '', + seventh_amendment: false }; let formData = $state({ ...initialData }); - // 3. Efecto para "Heredar" datos o Limpiar + // ... (Fetch Data) ... $effect(() => { if (isEdit) { fetchData(id); @@ -61,7 +72,6 @@ async function fetchData(companyId: string) { loading = true; try { - // Nota: Aquí usamos tu API para traer la info de una sola empresa const response = await getCompany(Number(companyId)); if (response.data) { const item = response.data; @@ -84,7 +94,15 @@ is_service_company: item.is_service_company || false, order_format_type: item.order_format_type || '', ctpat_svi: item.ctpat_svi || '', - trusted_exporter_number: item.trusted_exporter_number || '' + trusted_exporter_number: item.trusted_exporter_number || '', + logo: item.logo || '', + previous_code: item.previous_code || 0, + client_name: item.client_name || '', + subassembly_mode: item.subassembly_mode || '', + broker_company: item.broker_company || '', + inter_db_name: item.inter_db_name || '', + prevalidator_key: item.prevalidator_key || '', + seventh_amendment: item.seventh_amendment || false }; } } catch (e) { @@ -96,6 +114,31 @@ const clean = (value: any) => (typeof value === 'string' ? value.trim() || null : value); + async function handleFileSelect(e: Event) { + const input = e.target as HTMLInputElement; + if (!input.files || input.files.length === 0) return; + + const file = input.files[0]; + if (!isEdit) { + alert("Primero debes guardar la empresa antes de subir un logo."); + return; + } + + uploading = true; + try { + const res = await uploadCompanyLogo(Number(id), file); + if (res.data) { + formData.logo = res.data.path; + } else if (res.error) { + alert("Error al subir imagen: " + res.error); + } + } catch (err) { + alert("Error al intentar subir la imagen"); + } finally { + uploading = false; + } + } + async function handleSubmit() { error = null; loading = true; @@ -122,7 +165,15 @@ manufacturer_id: clean(formData.manufacturer_id), order_format_type: clean(formData.order_format_type), ctpat_svi: clean(formData.ctpat_svi), - trusted_exporter_number: clean(formData.trusted_exporter_number) + trusted_exporter_number: clean(formData.trusted_exporter_number), + logo: clean(formData.logo), + previous_code: Number(formData.previous_code) || 0, + client_name: clean(formData.client_name), + subassembly_mode: clean(formData.subassembly_mode), + broker_company: clean(formData.broker_company), + inter_db_name: clean(formData.inter_db_name), + prevalidator_key: clean(formData.prevalidator_key), + seventh_amendment: formData.seventh_amendment }; const response = isEdit @@ -131,6 +182,27 @@ if (response.error) throw new Error(response.error); + // Update global store if we are editing the active company + if (response.data) { + const updatedComp = response.data; + // We verify if we are editing the currently active company + if (companyStore.activeCompany?.id === updatedComp.id) { + // We update the store. + // IMPORTANT: To force image refresh, we might need a cache buster in the sidebar, + // but updating the store object is Step 1. + companyStore.setActiveCompany({ + id: updatedComp.id, + name: updatedComp.name || '', + rfc: updatedComp.rfc || '', + logo: updatedComp.logo || '', + tenant_id: updatedComp.tenant_id + }); + + // Force reload of company list to ensure integrity + companyStore.loadCompanies(); + } + } + goto('/dashboard/general_catalogs/company_information'); } catch (e: any) { error = e.message || 'Error al guardar'; @@ -181,6 +253,37 @@
+
+
+ +
+ + {#if isEdit} +
+ + +
+ {/if} +
+

Sube una imagen para obtener su ruta local.

+
+
+ + +
+
@@ -204,6 +307,16 @@
+
+
+ + +
+
+ + +
+
@@ -243,8 +356,24 @@
+
+ + +
+
+ + +
+
+ + +
+
+ + +
diff --git a/frontend/src/routes/dashboard/goods/parts/+page.svelte b/frontend/src/routes/dashboard/goods/parts/+page.svelte index b77fd732..32938329 100644 --- a/frontend/src/routes/dashboard/goods/parts/+page.svelte +++ b/frontend/src/routes/dashboard/goods/parts/+page.svelte @@ -5,10 +5,12 @@ import { Plus, RefreshCw, Package } from 'lucide-svelte'; import { toast } from 'svelte-sonner'; import { partsApi, type Part } from '$lib/api/dashboard/a76/parts'; + import { clientsProvidersApi } from '$lib/api/dashboard/a76/clients-providers'; import { companyStore } from '$lib/stores/company.svelte'; // Estado de la lista de partes let parts = $state([]); + let clientsMap = $state>({}); // Mapa ID -> Nombre let selectedPart = $state(null); let isLoading = $state(false); let searchPartNumber = $state(''); @@ -28,9 +30,11 @@ (p.description_spanish?.toLowerCase().includes(searchDescription.toLowerCase()) ?? false) || (p.description_english?.toLowerCase().includes(searchDescription.toLowerCase()) ?? false); - // Filtro por cliente + // Filtro por cliente (Busca en nombre o ID) + const clientName = clientsMap[p.client_id] || ''; const matchesClient = !searchClient || - (p.client_id?.toString().includes(searchClient) ?? false); + (p.client_id?.toString().includes(searchClient) ?? false) || + clientName.toLowerCase().includes(searchClient.toLowerCase()); // Filtro por clase const matchesClass = !searchClass || @@ -44,10 +48,40 @@ $effect(() => { const companyId = companyStore.activeCompany?.id; if (companyId) { - loadParts(); + loadData(); } }); + async function loadData() { + await Promise.all([loadParts(), loadClients()]); + } + + async function loadClients() { + const companyId = companyStore.activeCompany?.id; + if (!companyId) return; + + try { + // Fetch all clients/providers to ensure we map "both" types as well + const response = await clientsProvidersApi.list( + companyId, + 1, + 1000 + ); + + const data = (response as any).data || response; + const items = data.items || []; + + const map: Record = {}; + items.forEach((c: any) => { + map[c.id] = c.name; + }); + clientsMap = map; + + } catch (e) { + console.error("Error cargando clientes:", e); + } + } + async function loadParts() { const companyId = companyStore.activeCompany?.id; if (!companyId) { @@ -78,17 +112,35 @@ } async function handleRefresh() { - await loadParts(); + await loadData(); toast.success('Partes actualizadas'); } - function handleDelete() { + + async function handleDelete() { if (!selectedPart) { toast.error('Selecciona una parte para borrar'); return; } - // TODO: Implementar eliminación - toast.info('Función de eliminación pendiente'); + + const confirmed = window.confirm(`¿Estás seguro de que deseas eliminar la parte ${selectedPart.part_number}? Esta acción no se puede deshacer.`); + if (!confirmed) return; + + isLoading = true; + try { + const companyId = companyStore.activeCompany?.id; + if (!companyId) return; + + await partsApi.delete(selectedPart.id, companyId); + toast.success('Parte eliminada exitosamente'); + selectedPart = null; + await loadData(); + } catch (e) { + console.error("Error al eliminar:", e); + toast.error('Error al eliminar la parte'); + } finally { + isLoading = false; + } } @@ -135,7 +187,7 @@
@@ -215,7 +267,12 @@ {part.description_spanish || ''} - {part.client_id || '-'} + +
+ {clientsMap[part.client_id] || 'Cargando...'} + ID: {part.client_id} +
+ {#if part.part_class} @@ -263,7 +320,7 @@
- {selectedPart.client_id || '-'} + {clientsMap[selectedPart.client_id] || selectedPart.client_id}
diff --git a/frontend/src/routes/dashboard/invoices/+page.svelte b/frontend/src/routes/dashboard/invoices/+page.svelte index 51212163..90031480 100644 --- a/frontend/src/routes/dashboard/invoices/+page.svelte +++ b/frontend/src/routes/dashboard/invoices/+page.svelte @@ -12,10 +12,11 @@ import type { PageData } from './$types'; import { browser } from '$app/environment'; import { companyStore } from '$lib/stores/company.svelte'; - import { Plus, RefreshCw } from 'lucide-svelte'; + import { Plus, RefreshCw, FileDown, RotateCcw } from 'lucide-svelte'; // IMPORTANTE: Asegúrate de tener instalada svelte-sonner para las notificaciones import { toast } from "svelte-sonner"; + import PdfProgressDialog from '$lib/components/dashboard/invoices/pdf-progress-dialog.svelte'; // Los datos iniciales vienen del servidor let { data }: { data: PageData } = $props(); @@ -151,6 +152,24 @@ let loading = $state(false); let hasMore = $derived(allItems.length < totalItems); let error = $state(data.error || null); + + // Estado para selección de fila + let selectedInvoiceId = $state(null); + + function handleRowClick(invoice: Invoice) { + // Si ya está seleccionado, lo deseleccionamos (opcional, si queremos permitir toggle) + // O simplemente lo seleccionamos. Aquí implemento toggle. + if (selectedInvoiceId === invoice.id) { + selectedInvoiceId = null; + } else { + selectedInvoiceId = invoice.id; + } + console.log('Selected Invoice ID:', selectedInvoiceId); + } + + const selectedInvoice = $derived( + selectedInvoiceId ? allItems.find(i => i.id === selectedInvoiceId) : null + ); async function loadMore() { if (loading || !hasMore) return; @@ -312,83 +331,72 @@ } } + // Estado para el diálogo de progreso + let showProgressDialog = $state(false); + let currentTaskId = $state(null); + // Utilidad para convertir Base64 a Blob -function base64ToBlob(base64: string, type: string) { - const binStr = atob(base64); - const len = binStr.length; - const arr = new Uint8Array(len); - for (let i = 0; i < len; i++) { - arr[i] = binStr.charCodeAt(i); + function base64ToBlob(base64: string, type: string) { + const binStr = atob(base64); + const len = binStr.length; + const arr = new Uint8Array(len); + for (let i = 0; i < len; i++) { + arr[i] = binStr.charCodeAt(i); + } + return new Blob([arr], { type: type }); } - return new Blob([arr], { type: type }); -} -async function handleDownloadPdf(invoice: any) { - const toastId = toast.loading("Iniciando generación de PDF..."); - - try { - // 1. Trigger: Iniciar la tarea en Celery - const { task_id } = await invoicesReportsApi.triggerPdfGeneration( - invoice.id, - companyStore.activeCompany.id - ); + async function handleDownloadPdf(invoice: any) { + if (!companyStore.activeCompany) { + toast.error("No hay empresa seleccionada"); + return; + } - toast.loading("Procesando PDF en segundo plano...", { id: toastId }); + try { + // 1. Trigger: Iniciar la tarea en Celery + const { task_id } = await invoicesReportsApi.triggerPdfGeneration( + invoice.id, + companyStore.activeCompany.id + ); - // 2. Polling: Loop para verificar estado - let intentos = 0; - const maxIntentos = 30; // Timeout de seguridad (aprox 60 segs) - - const interval = setInterval(async () => { - intentos++; - try { - const statusData = await invoicesReportsApi.getTaskStatus(task_id); + // 2. Abrir diálogo de progreso + currentTaskId = task_id; + showProgressDialog = true; - if (statusData.state === 'SUCCESS') { - clearInterval(interval); - - const result = statusData.result; // Tu dict del backend - - if (result.status === 'success') { - // 3. Convertir Base64 a Blob y Descargar - const blob = base64ToBlob(result.content, result.media_type); - - const url = window.URL.createObjectURL(blob); - const a = document.createElement('a'); - a.href = url; - a.download = result.file_name; // Nombre que viene del worker - document.body.appendChild(a); - a.click(); - window.URL.revokeObjectURL(url); - document.body.removeChild(a); + } catch (error) { + console.error(error); + toast.error("No se pudo iniciar la descarga"); + } + } - toast.success("PDF Descargado", { id: toastId }); - } else { - toast.error("Error al generar el archivo", { id: toastId }); - } - } - else if (statusData.state === 'FAILURE') { - clearInterval(interval); - toast.error("Falló la generación del PDF", { id: toastId }); - } - else if (intentos >= maxIntentos) { - clearInterval(interval); - toast.error("Tiempo de espera agotado", { id: toastId }); - } - // Si es PENDING o STARTED, el intervalo continúa... - - } catch (err) { - console.error(err); - clearInterval(interval); // Detener en caso de error de red - toast.error("Error de conexión", { id: toastId }); + function onPdfComplete(result: any) { + // Esta función se llama cuando el diálogo reporta SUCCESS + try { + if (result.status === 'success') { + const blob = base64ToBlob(result.content, result.media_type); + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = result.file_name; + document.body.appendChild(a); + a.click(); + window.URL.revokeObjectURL(url); + document.body.removeChild(a); + toast.success("PDF Descargado exitosamente"); + } else { + toast.error("El worker reportó un error: " + (result.message || "Desconocido")); } - }, 2000); // Consultar cada 2 segundos - - } catch (error) { - console.error(error); - toast.error("No se pudo iniciar la descarga", { id: toastId }); + } catch (e) { + console.error("Error al procesar descarga:", e); + toast.error("Error al procesar el archivo descargado"); + } finally { + // Cerrar diálogo después de un breve momento + setTimeout(() => { + showProgressDialog = false; + currentTaskId = null; + }, 1000); + } } -} function handleCreateClick() { const params = new URLSearchParams(window.location.search); @@ -443,8 +451,13 @@ async function handleDownloadPdf(invoice: any) { ); }); + function closeProgressDialog() { + showProgressDialog = false; + currentTaskId = null; + } + // --- AQUÍ PASAMOS LA FUNCIÓN DE DESCARGA A LAS COLUMNAS --- - const columns = createColumns(handleSuccess, handleDownloadPdf); + const columns = createColumns(handleSuccess);
@@ -556,7 +569,38 @@ async function handleDownloadPdf(invoice: any) { {loading} {hasMore} {loadMore} + selectedId={selectedInvoiceId} + onRowClick={handleRowClick} /> + + + + + +
+
+ +
+ + + +
+
+
\ No newline at end of file From 606d5c11402dba2c702feff686d4493ebaf34c6b Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Thu, 15 Jan 2026 19:25:16 +0000 Subject: [PATCH 09/21] Eliminando carpeta basura --- backend/app_data/logos/company_1_logo.png | Bin 12017 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 backend/app_data/logos/company_1_logo.png diff --git a/backend/app_data/logos/company_1_logo.png b/backend/app_data/logos/company_1_logo.png deleted file mode 100644 index 0ac0a67985f7b020d10613f2a3357fbc14f66cf6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12017 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 O09h#|$trQ9!2bZMI!qw| From d02b0dc7032ddcb73d0127cf1a834ee96f7b3d60 Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Thu, 15 Jan 2026 19:27:25 +0000 Subject: [PATCH 10/21] Eliminar backend/app_data/logos/1/AS.png --- backend/app_data/logos/1/AS.png | Bin 12017 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 backend/app_data/logos/1/AS.png diff --git a/backend/app_data/logos/1/AS.png b/backend/app_data/logos/1/AS.png deleted file mode 100644 index 0ac0a67985f7b020d10613f2a3357fbc14f66cf6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12017 zcmcIqRZv_(lzoFvumHhzkO09UxDFN^f_rec;2s7T+#$F-!99Us3GTrig1ZN|Wj}Xo zxAtpq)q7pt)u+4fyWO`=^*iAom83DzNYDTPz?7AdR0RM~+{?oZMto^mu*N@qDUdA1 z6vY6bHWvNC82P0RF_lqO1ORV30D!>(;O?afwhI7m>;SND1ONi506_RTvqeSdWuVrN z3hGiX9sXYpgaUqriSwF>0+)=Ih>nAV;XMW(G2$x>YHmpuSp$Au7YQr4taH2uyi_~9 zN-w6tEVI`ZIwUDlsrxWZzV8^!r)alE?=RH z>Ls*@SM*G^s9YtoOGjsy0@L%7`PE^|Sdg>u6Iv&|Vie@nw8xRRmH8ZlO3A{ZXpAMM zuUWE$tKuS+JI9$eiA+pmSFb@cP|Gu@4$?@RC~ zT~(FTKoix+(K!qdaZyC?7_n=oQ7fxh z4Kx(?=XGniZVKowoy9LD&{wv3tf<9EPZSb`_UWytPNbP76qyZpJ@nkdh!qfbdreX5 zm*#WZ=LAOA$3~xI>&|(YGd z4``8s81IDy{J{Wkget-qir6|Qzhg-@%2!)|vqcCuHHmIQK}vCSEXNGM_9KV9QS}ye zI)E0QmpY3Ec|)A+LidwlQA0Uc@gxZE3>#j>)t&zx8yM|2$6!?E<^|#QCAYqSdfOg~ zp>~zR*dxrVf4+XVpCsnp`hqe7>yEF(gkYEw_F*}I;R=h0@j@X=6b_4f=1W{x4biaf zgcp33CIJCr6QCb7-p^B zLgK5ob3|dmx*(j=??oNotui9r0-U`Sy?>OH;$s8c!^#O{6RfZ>CN!MNCBG>=nJ-=% z=x}#x{rxvJ--(UX-$lPwvej@w#)e8{97MYUa2|K6wm_cGY7j5fZv_3YkL{UWvN3Gj zSdw|m4p;9rK_H^-1_BiUWbvLtVcFUPf&=HuSbcQ3?$xlm_pQ)k{%HE7yS~%Dx(he< zud%lFxp&wRO?gyumhm+lar#pYSYdL}Az>l-OzEsCdsC4kIQc2R-{)~-$GME#l*>c7 z4k0-uVenq)?u{&YT)g5K^8)Es2|W*i&HkHrluKs4Dz>mcA-pk|MG}y&wKUY7sb5sv zNWjKyG`28^oR=ig=RdTSs#&f}Plf2iV|L=viqxpAEKHOK}b8RBXX zE)ee+eavYSS8|S)O8+-m%^6SttSxYX49rbI$C}EN>|O*zqMno}1Bolw8dK@XHsPNY zRe0W|jpqc=RDjGnV{Gg&;7{uM>N4cSa$BCGR+Aru)!t$+L@bg3Mu|t&t{EBB$WjV@ zC)#Dr1YzP#hcX8k;G-R^hylizu>-(VLy%eEERxCB`y5qoLfhC$v z#sG6uO_Xm>G-J@nBZ8JK3cbq${)8WKDJTds_qtQJ|6_KQPiD?uyMj9ZGUYr*1N+VQ zn2y&PzR^O=>;00XUyUOEF1E+8-|QgL?T!FF)`~={Y+D!7Zyut>i=3ZYG)##i3d7m7#PJJiW)@MZx7YfMPy9Y8@j7;eJ)sz6j-2& z#GE1;)nE^V52kac&@%a>G(vYji{NvvV1tDTqb~0h3u#U(vxZspYaxJzZFj=bUNf=G$V06#E%R(34d=PI3H*H? zGtIr}_4VBwWsGf(C}8gMf1Nu~hh)=0-fZ$pDG6Bk+;uSf$}_4e8cgn!d%)m~^Dp1# z=>zP~DpOX)oBRl7jaM=b;?1SFV1qa*)Hu2`0&+tE3>nfBedNk-_M2A`S-?1%Qku97 z8^%`wNLi9{l@^d!#_tk;rN7&7(5B9H#6cgUr8>ew7_tmkvNGjeYo6<2)*zNS?h#i9 z!Lz-aD>?t&Wp#vGD5jm&HS!m!eH>wtpf6yBZAN8{VzLm*i4j3}a~5@xu^0HZ5C-^T z`zRb)CNjo;Y~|AjCrr5i>X|;ZM}R*uXZaqjMRjOf0s}>>-Dr?0_4D(Uqp%u0XWr&_ zv3h3`sN-mh`nCa^6L?JMt*@|kokD#dwHf9tL3th+0;%Y5rPqY)J7`5M%kuc=I~3$| ztY+W#->84udACH>K^OB$53hj<9V|SN-Hj}Ml7V(!57{~MG$6rQ*g9RZR`R{$zED<2 zm$XbNdRa^i1V4MK=uFUtJT8;)uPFugol52dW=Zq!dRD>%)1Paj84sD2$efmJOuRro z31$u#C7L-xp6F+vVNgQ-QqsD|4+X-E6)wXfEmU|FywD)u9jfne^F!77L-H%ylIR@* zQkiBQ;M(+Pw9Ms7aXP7M24NtYLPHvkq1l>TpF7OLU9*bhFnG8mfrY z(91hQ&twbxyCkAB_%`3P-%P*$%Yf9Msoq7Bi^6%R^N{gx6zYUxUfRiHXSL{6&gyhq z*k%*XBw`NJz0v&dOhhi-zBzoTGtA0;xruK|-|O^>w~Fe^MaK4jCQ+6WzdeLGeG9${ zosw<2sU8C5{aHj~Jv)*x6P}K|@uX2)-6gIjcnI_}*89AlVw=55jef9CDu0H~2zpsh zZk%CXeN^xRFl1U+GMD=IE_GY!9)D?qeiQ3Joi)P04TMWnY9WP1L74I1yQx{}>f#iqdC?vnxKy}!KV zZTP8EF}d|7gwG7zw)gc56)U#A>PO^Ys4}aGYy>wK{|U1e@4@5>`+@8Z+yL!2a$toV zq~RDtn>TZFLD2QhSy9)}p<)leC0upn-w?AQ0+m?yhr$J^F;X=)N(OxA0y#EcE7QJ} zw~6J#d3EagkP0kvCP+i=#wLR0)h{Dh&T+h8L#MAZ2PGxC24wJEvI}N?XFnOMS`Etm~njG);-| z&q*J|^H_QQj?g8r4zwj(c3^mIJP2j$DmcWNq{n~6{LI?4Z!t2nTv*3%$`=xq)N7-?Cl^LlX4qZJ zGv46gE!&1Qe5tBu{*44g)vjCr!kgwNBT=$LWtoT>ja5NN+i-NV-jNZf-(&`S?Z${~ zR9XZ-_HSm9!g$R^O%va;56qHJlm5()$IJj!>?p7WW;$6+`YWS{N95(K$@{Mh=oO}y zfH0~v@9@`$$u3Nmhd%}d2#rVeYZ)O{y@=wd8$U9}Iee6=PW~+@(&@8y$2pZFn+)Fy z>iqdrx)IPk%Db91(D-w7Vq61y{>=~#e3a?4n-sqbN?_5URy*gD=d}!ECm~&RJ zn!bZwgd|OX<6(cP$$BkWs~jY_U5Xf6fEWL?<3a!E)jZd_{NhZRXM4Bm2tjD@5mG)g zS88kEF=@r;GRq`ohTLd_X^~C+2*>7{G89!S$7UqXO)c?r@?OOZFhf<2tj0VNmR83_ zO0w9$AzUT;gcaWvY8?!;rtZk!IHnHYrrxOI7p=W}W`c z&;Ia_(h&{m71OteLgc&$dD^cgmM!$FUf3*WQ`m(ks5ZxZ9_X|`K^>55?&&fnJD;rIr)5*`-F?f5^A)hD>u z1e9LqoZ=4j$a2=Swce!gLelXF61_M$9+?EET@GM?AdI z;p8!b8T7hI_a^x{)xFTU9+c%%G4QI0sm%95|&_i!%P6+wslzS-p$g$-ck37!!SdxLEyi+)UWs z*f%el?-+%ohnW%PO9TBl_vCUpqp8d3;@BU((|+ODe(z}bFm&SgT>Z&=uPEiyUHOUs zNwwj_uh;(nPOfy1$83n=ODD94H~iV&gdJDr30l~C>B?lJWG<14K4thnpI?7DpVYdN zKd;Yu3e8#dy=)93ecSWafrpIK(m&GP2i}%*h#LU$CpT}O!TS|ta<|sI`f&96X@jX_ zZfC$aVX5Wuj?}T;?PFA|e8$a+L@zqB1Tnfcam|KX3Rtpfmb2PcAzt-vE%^E0x&L<8 z-0JFThs#%5*#uh0Ro@*4V_+HcpJwxI0)OYx!=Fl!^(=8&%d$ozN6x0{`;LbzkB;Z^ zM-u)|fNa8Ib;p_RCpZ2BHZp)o#3!b45N!l^@E30ic<&SjEa)`1C zs2yM4^U4QarnegvT=uzHL;2dI!}yalKvbaeLD-w*oCX!Gf7lP_g3nte_amFe6fy}* zKG!(W-9))q!xlj_^sJa+gIs%`WGrptNA(AFqWi>)W+{BeIv&a&AKe0I2aYmMj>h9h zxlxMeR@ub0P{T$yRfff1z46Eijm-s^5XTyXHwLF(5b6KKs79W9|e+=KSxI zs7g?Q0V$+ndj=%f#7e3`9@%_h+GBbmy?Q_YMGKmsS1r1rm(q`ql21G`0Xls9SQy=Y zx8;9-|2X43h@3!sEyAy@W@}&!iGn7N*mBV(Rmf;tN|w3{uHKDQFI>#|`+il&zWrxp zK0kc`f{!~bZdU4Y*T-L$JezD8ww<0c*`Ch%C#Vku@oE+?_sk-IX};Sz(Ljs1GSnV* z)-_zOgHvXI)jpqA;L123%;soty;_libUD*T`u8UNWIT665XB4K*msvL@4k%nKaFgJ zsoPY%?6u9OWepEWS4>;j1K=jSKRP&NW|}v)gSr#S&^qa4P+$4NLP}@c7qGjP)I#r;TT{1wPWb6zK3!-uVf*}e zIh}5q;d_x+i&|~P9ZUvsG!1ln%*GlZ?acK4kWO$&gx$I}a$HcD9^Ddi@_CyefDiZ5 z@aLlUJ9Zc!so@v5<4(~kYbb@NyzW4o^fda_e$YE%LHbCFIhw>fUey(HG1<9gJg27G zM;dgAr<KK zzxWgkR-IsB&wL2SjK!5o1NlDD+or`{m|-?wt4zN_`-y1Q-O^qkkDAA7O1J9ml(l!Z zC0m#5>-mvG${jUKF4ZTDr|BB;M|*3)4Cpg zMew+{CR^9!>z2|XIY$o3T))Ole{KFQd9^X-orpnSdNl#f(7WF?)ISlCXf0|l@7xUx zP!yl;4L`BQ(t16zemAlUg?%2y*Y|NtmBN4St8PkoDn;w|uZ!Yf6vTjkFBmZ#n;eYE z7rMz&{yFxVr-9n6y$kw-RB~qVHZ#lrc4b~lV7RZ3&|tfOk-XBwbDHoclH?YbzYg1e zhJA_e#v#`TXI5q=rPfEjHW$yEo4uzOo3wm6uE&(0v;Bsk4@xxct%@Pr0*i^sbdSgP z^nLSHBbKpVT-ljfWaQ-J!anDp{h!yyd!ff|z2VwJ>vF|K-WH}`6So3#%9;|aRbnMM zUxJF+bI_`2uW~;vauF7XA#U_GU%pgw4yKyUfWX)Zbdkg_Y$=h!KWwheyL;05-;}x|ZejsC{L&TVx#B+8e^qQszQOvbs?9&l z3LIQFl0rN{;Pi7n3$KxDa!dQtr&N-dQ0x9U4vCmV`+~J z5W%(wSoq7<1X4O5yjOpwV2uuJY-ui75~i3K_4SgB*5Y?9| z#UiwL97XwwsmqG_+9nPq)GJf;*%(~Oo zGAhE47MfyVNkxjgw(DMPUQ*r8s;7HkdvC;y@$XgHGf~v7u&hvGN{(id@C(2O{&^_ z>7+P6Tm=Fde{>^B>T9IY$&P$gcxcH%szWK_>*?$Hbhx?uVw;=u_4P?YKJLyFu$fBb zYEo>#TyxFdOK3UDQUjV`S#k+w9aXg>?DIHYYIgB`I5kPS^YcDC{dY6EmdG|XrWEre ziin_H@lmhWiUl%o+lA5-8H$OvPmxVQneCFNFAsrzz?c3aaIOnYxVYnY_MB-LK3k(I zVO;k{0R3Sk2tN${hMbT&jmz&~W?7ujI6IynwPX*-k#@&16{q6gDjbx5Q!h|P-nlmgA4|?>(-9z z(7~j|@mr_236mFzmWC9DT#F}a4u=`Ygs8JP;2iLV-GI4nHdcpAoKO|nai3u(S(cyI z&e_J~g7`fG%8V zbZqQ4d8YL?5EM_>^PY{#l2(n?v&7%-WiBgZUc>Th3xnLq zzb_l*oK`DtXG$;;>*;qwW0le6FCr)VLU*>LZg3pM$uAjnYt%PEj8$K zgsjMzMZMhJpL!AnzmbXDu4kqc+hCaKpy2&IKtrk-a$x;v!(hvO?nAuK^hV@IsG`P< zpqrk%J7s^FpoH=3{6U>C-={A-Y0g!c??^5epH*l5Z%6=RZZ>m!kQ=+w>f1sxvs!{b$Ja1_csz735o+ILor=wIYHHBn()vLGMY33PgrTL| z&wFhv8=QOo-f~hw%Y1mqZR(i11b(l4vn@ZQJZf8@!WM~jUfP^-+(;i>u|X z;s}5H8gctez|d^o*W$ZR7MFe`9CIPX;;iTAGV{zBo30yD>mx;V&^$NNZ-IxRR*KOk zt<^(#UzfY|J_~88MpM^M9%!myN#xt@iE~lksesWk##bhd>}`+L@+Z~%Utbo7q=Okj zUKbL8dg4IA&hOv_QJs-%J_k?OBAU6?&@OK%{B1iD{QjMwbKOqG_f$-O(aWL_mOJ>f z23MoV(W&|3{nLZ;qKoHzhUe;&w+>d-5f3&T31nNawiL^laThI<*kEiiv$|v#ktu5L zlfQyGH`$ctopo-5;HSyyeLulp0K>iV+S9F`fEC;M)q(RDM+VB8_U7L zQmX$LA)b6!b?@SsByP}s1~cHVT}12ERgqWgK$~b^W80=XHW-H&wGPed$gieqLcq}v z$;v$;Ps>ALQ=^G$D@iITXacW)KX*6i^=t#Aj|H=TFu$)c%f6a3&a1gWdXcQ(h9#kq z)0Xsob168DoitNuup$>j5Tnr73OWt91Q~~F)Hl`pP*yh*d8sxgWi>{#sA(6rkDqFM z3T01F!e{Gt_L*0q>CyJm{XX+Y`yqFL<3b_w^@(%jwL3a^qh>ck0ij$!=22gr|8&;S zZO^n8vw#2Qm@YJ1-yGu1pRaUN-CdTv!3Xl(>UeDS^UhlRxAtlh*4jKfmv86o_JxTP*8o{>c-*hMFiXcaJCj}q4k~?%zT2wC8JYimm{8*01i5@Spx7{oVp@s~5OY6I#!muielh0hH5#x58(Ip$3e@y=!!shgSi;Ul{;jJ*Q=pjxE7L-rAfmk9y$rO|NYOJi1 zp>hjL#NK>~JEfb10RaG1FJ-$A(9P6s?OS|qf1NCPc0@g> zdntO}$D(p$M!bZ3Jv%^F!CxeE*q}V$$A`615dzLXFC%2JzcIm=0i~nfLL?s; zp(EUZe4dS7TU|JAr@Y9UkFP~a3{Ln%$`K^d3vP*MDwJ6aKdnY!wAt&#ZIvZF)wj($ z@Z`{r9SgA_czwPoXzSfU)Mv%!4|^E+%twahD%|j|F6Fdi_a{|iLH$Og z*32ni;_(bvYMfT{^7GZv`s7E?obqF@R{R1ewq~I?YQe|TP%XkRxVyY zonDP7fBNZDKz4nd)HwYs8D^D?0_o{)YD-0;L4xsORF^uur#3_MSNdzNdHm(yXdmy1 z|IPFP`t5#~;p)SUq3E4=>?6_y%CGRFQEaX8UNI71%}UG-gWrGbI=eE;GL|IY-10V` z-C8=bY}N-MJ|U4i{6ku-qpBYcVW7hSL09p>5PO@cVO+=J0!+vJi0wPjb}HW+`+9ol zn|eq+ii6deN+s*@aDY*o=SF1&V8FS4nUMDRe`R_6HZN9Eh7zw$NXl zVc3?LPOWXAM-X|js1w!}`fzkaiz6Xk={5kVEwDKQy%Z> zwCaYZ29!d6>{ILIC0906TMP2yGznm7Q?@8!zQGMf)PWgb_ryvfgC;`6*u`ry0&95E zN6B=hST76h`QAGft}T0U8{U-uTpq(<&~3ToJlS&tRTwt^!#~kzJfMjP6OJ z;nOxBsD@m?E|DGUo(EGo`?U77p}nTA#Ly`Q9%+QYs=D`9!)iJSmNsB2^_FNoZeAyO zpOVGxKiUk0@JSC`b_8tKNz%Vu%P=k}9lIWJqJUfmMgTl7S}ZE_TrX)yZVJFTbh|A% zl&WbMA`(zW;$a{zDY3mAi|QbJDV*HTig*46)Yx3~#h*T=y>N>tsN!=cdJbbgEzGPEN$6!41(`^wZ%4=Hc@Fs&AlQ33to6pC)xS`32W7)kxLs({uc zo6onGg85f)cEe=+e02W(rABb?b# zk&P})lkq(<-1u**1-m4W+tSYbq4-T%AW>ROhUP5QyUz-iD!U;i@zx*aMc#0olTSt! zi-W?}H$CzSe(jT3k?bb+yZTBI=@!3FB-BdhkJO_cS4D|0LVzsCD!flehdrht0J(}Z zlTqTquOu^&ae>@#-1vAyG4?|w)Bv+?3~@LDVB}u~S7PX7NJRr+z3ryy$zdP>6Hyk8 zy7=iAD6R8rp}X{VMPdN1BZQnvO4}4IgGwaW4Q9@e)V)(LJ|e267icoYRz?CoM_Uni zcH=|q5BYd7EahZqx~gkzF(4S{__J%v&0UoP=rZ3XR!n~??}B5oy!McfqZgoqSp$O@}xVt;g+cF5@g8G(~Zsx zYRovRH(gE`h5+|8VT42!gdJ=SewXwX-mL=AE)oSecye$=y+b(k*|xL5)&f3a(oi=s zb;6N|0NRYy_N{m*G7vwEF=lp$)naK2@sVT${W6^-En`HO4oAfNGZ$`21U)x#!HB?r z;}SKcv+&t487DW-@&KkDK4*$w(9=`%a_`>>p+?}Encx)z<|5j{VI{P5`H(Pp6kzn% zO9BLcM}-Tsc=HOXx5sP%g1#}a<%h^bDcS@=;yn?OJe68;05lWMJ}YsP^)f4?K9jp% zTo_3=6~eDrQ)yM4D49bhusS9I^dq*k01Q_}c#(GOqKh4)gb`-bBQirqjR2XB^^?K} z6lHTk{l)Y}mPI!LA;{SC5D^rv({*fsj)NliTRl zs#8}OUYk*5{Da35%!Zj50(jjxD4m*iHh>kuJpwG_SehK?P0-(x$I19co7Jxf#6H&L z1Os}Fb~-I>Ay|NE2F7;ewJwp{i0oohh*KDp+e98&8zHSk*nM1xhoh7BiqGc>i7DGQ zohOz&0KMCQY&bC5GZ1>NfDGWpMuDJi6O(AQLaC#KhDJDG=Yf0|f*E?X)r($$4G999xF_2WY$ef0xm~(g@)OCBSYB3G5420aOivr zGJ5ez41grCXRRm8HHymw3{M*C+LtQ_m}OUV2wbIe?tlB)X6O0i<}A)Z@f%5`RM*Sy z##UA3B)9|6}$VdZu z5j^V%j%j%8hbD7|FcNE0bv>R&v>x%Hz?;+zqpilVZ()gChoZ1*a{Mj%1{0)o^q zm=6O}IrXpC8xF^**sUKM?E)3RYnQ z;VjLe0s-6-NTTi&NsK%jVr7#2(5YZCf-w`w=XG#AK_0XHFhdC=LlYgO)+YF zaSR9@j8^*8CJza$S5?@Pk&6Td`-`Imkj?%Qd;i#FCNK79QA;ibkZ!+)OJB^XGr_{l z)}~%52}wctoN}qAV>i57B-3b+a*59rq^#_EMJy1+jLD2?643Q2HqquL zE$Sg4Ag+fKQ5B*wK_IxCePClZ{sg`V7G$cP!REF|H!#8In*;@OI`I4r!UkfBl=On&L7muI-VXu?LLun#Z z1_6S#2&gI~@`jyPI7XNmRj}iIbf) zBe2_UOgb(!Eg4Xb028Rk13Ig?QJ`J@O$BS+=@5WOy6Fflci0#6tIk(BNRR-xJx$#9 zFCu6vDksn>L;?Z0!X*KK`9p|35+V|CH{4)vIW71hm9NPjQ_>cID6n`ZG0C)BFE$a& zF#PT^h(#_i9@H}g z*ZyAN!u!03wYF+k8P=@5ItJd}BJXx+9r2`h))qMXN=eEg8Cr`bqGTrm{@jbJW^ zakZX4Y;m2^G1Rq&)#o*=y-}Tft}H_UAd1Nv*b|}>>CCo~l++sXQc`<897Zpa?93JZ zM@kqWuVgwio2~oVe)hb-T8h6x{}ecad1#Omn{jAJ>U7;B5>@Yk643bcWadUyI9ONl zY976qaAYgFF6EbucGS}PbFpKSFGvx%;~e^FqLWAzFQ|3zOr^mgbOF|Kx- zQ;sSn|3v`&)>TT|)y&w{T)@=X{G|Xm**Upc*!fx5In_CM1vohcI5?Tu*#+3yZ|R!$ z{tLj~(ahSy>wgD?`Cw_h0Equ{1~o?uR}W)nb3n|@(Zn1gYj136u4-;<=H)bC{-Q$% O09h#|$trQ9!2bZMI!qw| From f8178787428d4f1723ec5e80e3db6ce7c151ec81 Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Thu, 15 Jan 2026 19:27:32 +0000 Subject: [PATCH 11/21] Eliminar backend/app_data/logos/1/Agenda.png --- backend/app_data/logos/1/Agenda.png | Bin 56276 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 backend/app_data/logos/1/Agenda.png diff --git a/backend/app_data/logos/1/Agenda.png b/backend/app_data/logos/1/Agenda.png deleted file mode 100644 index e7b87dfd41b18d836b1a249b10cb42cac0bfd694..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56276 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 From 32123ec51166dde065811aa0be34b2b11aecf109 Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Thu, 15 Jan 2026 19:27:37 +0000 Subject: [PATCH 12/21] Eliminar backend/app_data/logos/1/a519dfd146c1bd477bcd841afe02d7de.jpg --- .../1/a519dfd146c1bd477bcd841afe02d7de.jpg | Bin 40590 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 backend/app_data/logos/1/a519dfd146c1bd477bcd841afe02d7de.jpg diff --git a/backend/app_data/logos/1/a519dfd146c1bd477bcd841afe02d7de.jpg b/backend/app_data/logos/1/a519dfd146c1bd477bcd841afe02d7de.jpg deleted file mode 100644 index 5723bd91cabc7ff6bf568785a1290c2d5ec2dd21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40590 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 YS-ArL04ubo`k;Z~#p2@s0N}s>*@Cw8hX4Qo From 8fcff2ad0883130a3beaa9c2c0ca68528747fb3d Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Thu, 15 Jan 2026 19:27:42 +0000 Subject: [PATCH 13/21] Eliminar backend/app_data/logos/1/footer.png --- backend/app_data/logos/1/footer.png | Bin 72609 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 backend/app_data/logos/1/footer.png diff --git a/backend/app_data/logos/1/footer.png b/backend/app_data/logos/1/footer.png deleted file mode 100644 index bd1967bd078907220a2e9478c8882229da649db5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72609 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 GfBb* Date: Thu, 15 Jan 2026 19:27:47 +0000 Subject: [PATCH 14/21] Eliminar backend/app_data/logos/1/logo2.jpg --- backend/app_data/logos/1/logo2.jpg | Bin 65870 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 backend/app_data/logos/1/logo2.jpg diff --git a/backend/app_data/logos/1/logo2.jpg b/backend/app_data/logos/1/logo2.jpg deleted file mode 100644 index e676a7001bd6e7084a66272eba7d3418fa587ac4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65870 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 From 5b08158d55b5487f8b845019392a55aedfec3c77 Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Thu, 15 Jan 2026 15:46:30 -0600 Subject: [PATCH 15/21] Se arreglo el problema de la columna --- .gitignore | 1 + .../dashboard/clients_and_providers/data-table.svelte | 2 +- .../src/lib/components/dashboard/goods/parts/data-table.svelte | 2 +- .../src/lib/components/dashboard/invoices/data-table.svelte | 2 +- .../dashboard/invoices/edit/items/items-tab-form.svelte | 2 +- .../src/lib/components/dashboard/pedimentos/data-table.svelte | 2 +- .../dashboard/pedimentos/edit/digitization-tab-form.svelte | 2 +- .../reference_data/code_pedimento_regimens/data-table.svelte | 2 +- .../dashboard/reference_data/containers/data-table.svelte | 2 +- .../dashboard/reference_data/countries/data-table.svelte | 2 +- .../dashboard/reference_data/currency_types/data-table.svelte | 2 +- .../dashboard/reference_data/customs_sections/data-table.svelte | 2 +- .../reference_data/customs_warehouses/data-table.svelte | 2 +- .../dashboard/reference_data/incoterms/data-table.svelte | 2 +- .../dashboard/reference_data/invoice_types/data-table.svelte | 2 +- .../dashboard/reference_data/material_types/data-table.svelte | 2 +- .../dashboard/reference_data/payment_methods/data-table.svelte | 2 +- .../dashboard/reference_data/pedimento_codes/data-table.svelte | 2 +- .../reference_data/pedimento_regimens/data-table.svelte | 2 +- .../dashboard/reference_data/sectors/data-table.svelte | 2 +- .../dashboard/reference_data/states/data-table.svelte | 2 +- .../dashboard/reference_data/transport_modes/data-table.svelte | 2 +- .../dashboard/reference_data/transport_types/data-table.svelte | 2 +- .../reference_data/valuation_methods/data-table.svelte | 2 +- frontend/src/lib/components/dashboard/seal/data-table.svelte | 2 +- frontend/src/lib/components/ui/table/table-head.svelte | 2 +- 26 files changed, 26 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index 17d85cdc..95a62a5b 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ logs/ .pytest_cache/ .coverage htmlcov/ +backend/app_data/ # Node (para frontend) node_modules/ diff --git a/frontend/src/lib/components/dashboard/clients_and_providers/data-table.svelte b/frontend/src/lib/components/dashboard/clients_and_providers/data-table.svelte index ef98de23..4c448e3d 100644 --- a/frontend/src/lib/components/dashboard/clients_and_providers/data-table.svelte +++ b/frontend/src/lib/components/dashboard/clients_and_providers/data-table.svelte @@ -62,7 +62,7 @@

- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/goods/parts/data-table.svelte b/frontend/src/lib/components/dashboard/goods/parts/data-table.svelte index ef98de23..4c448e3d 100644 --- a/frontend/src/lib/components/dashboard/goods/parts/data-table.svelte +++ b/frontend/src/lib/components/dashboard/goods/parts/data-table.svelte @@ -62,7 +62,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/invoices/data-table.svelte b/frontend/src/lib/components/dashboard/invoices/data-table.svelte index 10c61ad2..d549b5a2 100644 --- a/frontend/src/lib/components/dashboard/invoices/data-table.svelte +++ b/frontend/src/lib/components/dashboard/invoices/data-table.svelte @@ -77,7 +77,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/invoices/edit/items/items-tab-form.svelte b/frontend/src/lib/components/dashboard/invoices/edit/items/items-tab-form.svelte index d354044a..de9dd55e 100644 --- a/frontend/src/lib/components/dashboard/invoices/edit/items/items-tab-form.svelte +++ b/frontend/src/lib/components/dashboard/invoices/edit/items/items-tab-form.svelte @@ -376,7 +376,7 @@ class="max-h-[500px] overflow-auto border rounded-md" > - + Línea P/S diff --git a/frontend/src/lib/components/dashboard/pedimentos/data-table.svelte b/frontend/src/lib/components/dashboard/pedimentos/data-table.svelte index ef98de23..4c448e3d 100644 --- a/frontend/src/lib/components/dashboard/pedimentos/data-table.svelte +++ b/frontend/src/lib/components/dashboard/pedimentos/data-table.svelte @@ -62,7 +62,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/pedimentos/edit/digitization-tab-form.svelte b/frontend/src/lib/components/dashboard/pedimentos/edit/digitization-tab-form.svelte index 52646ac0..2194b826 100644 --- a/frontend/src/lib/components/dashboard/pedimentos/edit/digitization-tab-form.svelte +++ b/frontend/src/lib/components/dashboard/pedimentos/edit/digitization-tab-form.svelte @@ -591,7 +591,7 @@ {:else}
- + Código Descripción diff --git a/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/data-table.svelte b/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/data-table.svelte index ef98de23..4c448e3d 100644 --- a/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/data-table.svelte +++ b/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/data-table.svelte @@ -62,7 +62,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/reference_data/containers/data-table.svelte b/frontend/src/lib/components/dashboard/reference_data/containers/data-table.svelte index ef98de23..4c448e3d 100644 --- a/frontend/src/lib/components/dashboard/reference_data/containers/data-table.svelte +++ b/frontend/src/lib/components/dashboard/reference_data/containers/data-table.svelte @@ -62,7 +62,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/reference_data/countries/data-table.svelte b/frontend/src/lib/components/dashboard/reference_data/countries/data-table.svelte index ef98de23..4c448e3d 100644 --- a/frontend/src/lib/components/dashboard/reference_data/countries/data-table.svelte +++ b/frontend/src/lib/components/dashboard/reference_data/countries/data-table.svelte @@ -62,7 +62,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/reference_data/currency_types/data-table.svelte b/frontend/src/lib/components/dashboard/reference_data/currency_types/data-table.svelte index ef98de23..4c448e3d 100644 --- a/frontend/src/lib/components/dashboard/reference_data/currency_types/data-table.svelte +++ b/frontend/src/lib/components/dashboard/reference_data/currency_types/data-table.svelte @@ -62,7 +62,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/reference_data/customs_sections/data-table.svelte b/frontend/src/lib/components/dashboard/reference_data/customs_sections/data-table.svelte index ef98de23..4c448e3d 100644 --- a/frontend/src/lib/components/dashboard/reference_data/customs_sections/data-table.svelte +++ b/frontend/src/lib/components/dashboard/reference_data/customs_sections/data-table.svelte @@ -62,7 +62,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/reference_data/customs_warehouses/data-table.svelte b/frontend/src/lib/components/dashboard/reference_data/customs_warehouses/data-table.svelte index ef98de23..4c448e3d 100644 --- a/frontend/src/lib/components/dashboard/reference_data/customs_warehouses/data-table.svelte +++ b/frontend/src/lib/components/dashboard/reference_data/customs_warehouses/data-table.svelte @@ -62,7 +62,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/reference_data/incoterms/data-table.svelte b/frontend/src/lib/components/dashboard/reference_data/incoterms/data-table.svelte index ef98de23..4c448e3d 100644 --- a/frontend/src/lib/components/dashboard/reference_data/incoterms/data-table.svelte +++ b/frontend/src/lib/components/dashboard/reference_data/incoterms/data-table.svelte @@ -62,7 +62,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/reference_data/invoice_types/data-table.svelte b/frontend/src/lib/components/dashboard/reference_data/invoice_types/data-table.svelte index ef98de23..4c448e3d 100644 --- a/frontend/src/lib/components/dashboard/reference_data/invoice_types/data-table.svelte +++ b/frontend/src/lib/components/dashboard/reference_data/invoice_types/data-table.svelte @@ -62,7 +62,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/reference_data/material_types/data-table.svelte b/frontend/src/lib/components/dashboard/reference_data/material_types/data-table.svelte index ef98de23..4c448e3d 100644 --- a/frontend/src/lib/components/dashboard/reference_data/material_types/data-table.svelte +++ b/frontend/src/lib/components/dashboard/reference_data/material_types/data-table.svelte @@ -62,7 +62,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/reference_data/payment_methods/data-table.svelte b/frontend/src/lib/components/dashboard/reference_data/payment_methods/data-table.svelte index ef98de23..4c448e3d 100644 --- a/frontend/src/lib/components/dashboard/reference_data/payment_methods/data-table.svelte +++ b/frontend/src/lib/components/dashboard/reference_data/payment_methods/data-table.svelte @@ -62,7 +62,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/reference_data/pedimento_codes/data-table.svelte b/frontend/src/lib/components/dashboard/reference_data/pedimento_codes/data-table.svelte index ef98de23..4c448e3d 100644 --- a/frontend/src/lib/components/dashboard/reference_data/pedimento_codes/data-table.svelte +++ b/frontend/src/lib/components/dashboard/reference_data/pedimento_codes/data-table.svelte @@ -62,7 +62,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/reference_data/pedimento_regimens/data-table.svelte b/frontend/src/lib/components/dashboard/reference_data/pedimento_regimens/data-table.svelte index ef98de23..4c448e3d 100644 --- a/frontend/src/lib/components/dashboard/reference_data/pedimento_regimens/data-table.svelte +++ b/frontend/src/lib/components/dashboard/reference_data/pedimento_regimens/data-table.svelte @@ -62,7 +62,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/reference_data/sectors/data-table.svelte b/frontend/src/lib/components/dashboard/reference_data/sectors/data-table.svelte index ef98de23..4c448e3d 100644 --- a/frontend/src/lib/components/dashboard/reference_data/sectors/data-table.svelte +++ b/frontend/src/lib/components/dashboard/reference_data/sectors/data-table.svelte @@ -62,7 +62,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/reference_data/states/data-table.svelte b/frontend/src/lib/components/dashboard/reference_data/states/data-table.svelte index ef98de23..4c448e3d 100644 --- a/frontend/src/lib/components/dashboard/reference_data/states/data-table.svelte +++ b/frontend/src/lib/components/dashboard/reference_data/states/data-table.svelte @@ -62,7 +62,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/reference_data/transport_modes/data-table.svelte b/frontend/src/lib/components/dashboard/reference_data/transport_modes/data-table.svelte index ef98de23..4c448e3d 100644 --- a/frontend/src/lib/components/dashboard/reference_data/transport_modes/data-table.svelte +++ b/frontend/src/lib/components/dashboard/reference_data/transport_modes/data-table.svelte @@ -62,7 +62,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/reference_data/transport_types/data-table.svelte b/frontend/src/lib/components/dashboard/reference_data/transport_types/data-table.svelte index ef98de23..4c448e3d 100644 --- a/frontend/src/lib/components/dashboard/reference_data/transport_types/data-table.svelte +++ b/frontend/src/lib/components/dashboard/reference_data/transport_types/data-table.svelte @@ -62,7 +62,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/reference_data/valuation_methods/data-table.svelte b/frontend/src/lib/components/dashboard/reference_data/valuation_methods/data-table.svelte index 5b6be70f..4c84570d 100644 --- a/frontend/src/lib/components/dashboard/reference_data/valuation_methods/data-table.svelte +++ b/frontend/src/lib/components/dashboard/reference_data/valuation_methods/data-table.svelte @@ -63,7 +63,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/dashboard/seal/data-table.svelte b/frontend/src/lib/components/dashboard/seal/data-table.svelte index 7f02c1cc..2438370f 100644 --- a/frontend/src/lib/components/dashboard/seal/data-table.svelte +++ b/frontend/src/lib/components/dashboard/seal/data-table.svelte @@ -63,7 +63,7 @@
- + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} {#each headerGroup.headers as header (header.id)} diff --git a/frontend/src/lib/components/ui/table/table-head.svelte b/frontend/src/lib/components/ui/table/table-head.svelte index e9dd2378..c7c5e7ec 100644 --- a/frontend/src/lib/components/ui/table/table-head.svelte +++ b/frontend/src/lib/components/ui/table/table-head.svelte @@ -14,7 +14,7 @@ bind:this={ref} data-slot="table-head" class={cn( - "text-foreground h-10 whitespace-nowrap bg-clip-padding px-2 text-left align-middle font-medium [&:has([role=checkbox])]:pr-0", + "text-foreground h-10 whitespace-nowrap px-2 text-left align-middle font-medium [&:has([role=checkbox])]:pr-0 bg-background", className )} {...restProps} From 238d728305c842385e20571831a8e9ac2328de18 Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Thu, 15 Jan 2026 18:03:06 -0600 Subject: [PATCH 16/21] Puliendo reporte y disenio de partes --- .../importacion/facturas/mex/service.py | 19 +++++++++++++++-- .../dashboard/goods/parts/partForm.svelte | 21 ++++++++++--------- frontend/src/routes/dashboard/goods/+page.ts | 5 +++++ 3 files changed, 33 insertions(+), 12 deletions(-) create mode 100644 frontend/src/routes/dashboard/goods/+page.ts diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py index 69d502f4..bd0cd750 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py @@ -104,7 +104,8 @@ class FacturaImportacionMexService: if broker: nombre_agente = broker.name company = db.query(Company).filter(Company.id == header.company_id).first() - cliente_vendido = ClienteSchema( + # Datos Default (Company/Importer) - Used for fallback or Right Side (Enviado A) + cliente_default = ClienteSchema( header="Importador / Consignatario", nombre=getattr(company, 'name', "Empresa Local"), direccion="DOMICILIO FISCAL", @@ -113,6 +114,20 @@ class FacturaImportacionMexService: programa=getattr(company, 'program', "IMMEX"), autorizacion=getattr(company, 'program_number', "") ) + # Left Side Logic (Consignatario / Sold To) + cliente_vendido = cliente_default + if compliance and compliance.sold_to_id: + # Clean header: "vendido_a" -> "VENDIDO A" + raw_header = compliance.sold_to_header or "CONSIGNATARIO" + clean_header = raw_header.replace("_", " ").upper() + + # Fetch client data + cliente_vendido = self._obtener_datos_cliente(db, compliance.sold_to_id, clean_header) + + # Right Side Logic (Enviado A) - Currently keeping default/company info as requested "solo la izquierda" + # If standard logic dictates this should be Shipped To, we could add that later. + cliente_enviado = cliente_default + remesa_valor = str(compliance.remesa) if (compliance and compliance.remesa) else "" acuse_valor = str(compliance.edocument) if (compliance and compliance.edocument) else "N/A" @@ -210,7 +225,7 @@ class FacturaImportacionMexService: return FacturaImportacionCompleta( cliente_proveedor=cliente_proveedor, cliente_vendido=cliente_vendido, - cliente_enviado=cliente_vendido, factura=factura_schema, + cliente_enviado=cliente_enviado, factura=factura_schema, partidas=partidas_list, totales=totales ) diff --git a/frontend/src/lib/components/dashboard/goods/parts/partForm.svelte b/frontend/src/lib/components/dashboard/goods/parts/partForm.svelte index 99c13fe4..c82acb6d 100644 --- a/frontend/src/lib/components/dashboard/goods/parts/partForm.svelte +++ b/frontend/src/lib/components/dashboard/goods/parts/partForm.svelte @@ -143,7 +143,8 @@ part_photo: d.part_photo || '', is_active: d.is_active ?? true, sector: d.fa_data?.sector || '', - fraction_type: d.fa_data?.fraction_type || '' + fraction_type: d.fa_data?.fraction_type || '', + currency_type: '' // Initialize to match type }; // Ensure currency_type is mapped correctly if coming from DB (optional, depending on DB values) if (d.currency_key === 'MXN') formData.currency_type = 'NA'; @@ -383,25 +384,25 @@
- $ - + $ +
+
-
-
@@ -439,11 +440,11 @@
- +
- +
diff --git a/frontend/src/routes/dashboard/goods/+page.ts b/frontend/src/routes/dashboard/goods/+page.ts new file mode 100644 index 00000000..3f5e9320 --- /dev/null +++ b/frontend/src/routes/dashboard/goods/+page.ts @@ -0,0 +1,5 @@ +import { redirect } from '@sveltejs/kit'; + +export const load = () => { + throw redirect(302, '/dashboard/goods/parts'); +}; From 210f2d85d87e955b4b9d47c93712b53a18e58501 Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Fri, 16 Jan 2026 13:18:34 -0600 Subject: [PATCH 17/21] fix(reports): update invoice headers, pedimento formatting and value priority --- .../importacion/facturas/mex/schemas.py | 7 + .../importacion/facturas/mex/service.py | 129 +++++++++++++++--- .../facturas/templates/factura_mex_ver.html | 28 +++- 3 files changed, 137 insertions(+), 27 deletions(-) diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/schemas.py b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/schemas.py index a74709dc..9d4455b8 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/schemas.py +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/schemas.py @@ -18,6 +18,9 @@ class ClienteSchema(BaseModel): tax_id: str programa: Optional[str] = "" autorizacion: Optional[str] = "" + prosec: Optional[str] = "" + reg_emp: Optional[str] = "" + cert: Optional[str] = "" # Si llega un None, lo convertimos en "" automáticamente @field_validator('direccion', 'nombre', mode='before') @@ -46,6 +49,10 @@ class FacturaSchema(BaseModel): transporte: str = "" num_transporte: str = "" placas: str = "" + placas_remolque: str = "" + licencia_conductor: str = "" + caat: str = "" + scac: str = "" aduana: str = "" destino: str = "" observaciones: str = "" diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py index bd0cd750..f8f37a6a 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py @@ -23,6 +23,12 @@ from api.v1.modules.a76.general_catalogs.company.models import Company from api.v1.modules.a76.customs_brokers.models import CustomsBroker from api.v1.modules.a76.items.models import Item +# --- TRANSPORTATION MODELS --- +from api.v1.modules.a76.transportation.transporters.models import Transporter +from api.v1.modules.a76.transportation.vehicles.models import Vehicle +from api.v1.modules.a76.transportation.trailers.models import Trailer +from api.v1.modules.a76.transportation.drivers.models import Driver + # --- MODELO DE FRACCIONES --- from api.v1.modules.a76.general_catalogs.tariff_fractions.models import TariffFraction @@ -79,7 +85,12 @@ class FacturaImportacionMexService: pais=(addr.country or "MEX") if addr else "MEX", tax_id=prog.tax_id if (prog and prog.tax_id) else (getattr(main, 'rfc', "") or ""), programa="IMMEX" if (prog and prog.program) else "", - autorizacion=prog.program_number if prog else "" + autorizacion=prog.program_number if prog else "", + prosec=prog.prosec_authorization if (prog and prog.prosec and prog.prosec_authorization) else "", + reg_emp=prog.val_certified_company_registry if (prog and hasattr(prog, 'val_certified_company_registry')) else ( + prog.certified_company_registry if (prog and prog.certified_company_registry) else "" + ), + cert=prog.is_certified_company if (prog and prog.is_certified_company) else "" ) def obtener_datos(self, db: Session, invoice_id: int, company_id: int, progress_callback: Optional[Callable] = None) -> FacturaImportacionCompleta: @@ -90,13 +101,14 @@ class FacturaImportacionMexService: compliance = header.compliance_mx logistics = header.logistics if header.logistics else None + financials = header.financials if header.financials else None if progress_callback: progress_callback(20, "Obteniendo datos de pedimento...") pedimento_id = compliance.pedimento_id if (compliance and compliance.pedimento_id) else header.related_doc_id pedimento = db.query(Pedimentos).filter(Pedimentos.id == pedimento_id).first() if pedimento_id else None if progress_callback: progress_callback(30, "Obteniendo cliente y proveedor...") proveedor_id = compliance.provider_id if compliance else None - cliente_proveedor = self._obtener_datos_cliente(db, proveedor_id, "Proveedor / Supplier") if proveedor_id else ClienteSchema(header="Proveedor", nombre="No Asignado", direccion="", tax_id="", codigo_postal="", ciudad="", estado="", pais="") + cliente_proveedor = self._obtener_datos_cliente(db, proveedor_id, "Proveedor / supplier:") if proveedor_id else ClienteSchema(header="Proveedor", nombre="No Asignado", direccion="", tax_id="", codigo_postal="", ciudad="", estado="", pais="") nombre_agente = "" if compliance and compliance.customs_broker_id: @@ -106,7 +118,7 @@ class FacturaImportacionMexService: company = db.query(Company).filter(Company.id == header.company_id).first() # Datos Default (Company/Importer) - Used for fallback or Right Side (Enviado A) cliente_default = ClienteSchema( - header="Importador / Consignatario", + header="Importador / consignatario:", nombre=getattr(company, 'name', "Empresa Local"), direccion="DOMICILIO FISCAL", num_exterior="", colonia="", codigo_postal="", ciudad="", estado="", pais="MEX", @@ -117,16 +129,19 @@ class FacturaImportacionMexService: # Left Side Logic (Consignatario / Sold To) cliente_vendido = cliente_default if compliance and compliance.sold_to_id: - # Clean header: "vendido_a" -> "VENDIDO A" raw_header = compliance.sold_to_header or "CONSIGNATARIO" - clean_header = raw_header.replace("_", " ").upper() - - # Fetch client data + clean_header = raw_header.replace("_", " ").capitalize() + ":" cliente_vendido = self._obtener_datos_cliente(db, compliance.sold_to_id, clean_header) - # Right Side Logic (Enviado A) - Currently keeping default/company info as requested "solo la izquierda" - # If standard logic dictates this should be Shipped To, we could add that later. + # Right Side Logic (Enviado A / Shipped To) cliente_enviado = cliente_default + if compliance and compliance.shipped_to_id: + # Clean header: "enviado_a" -> "Enviado a:" + raw_header_shipped = compliance.shipped_to_header or "DESTINATARIO" + clean_header_shipped = raw_header_shipped.replace("_", " ").capitalize() + ":" + + # Fetch client data + cliente_enviado = self._obtener_datos_cliente(db, compliance.shipped_to_id, clean_header_shipped) remesa_valor = str(compliance.remesa) if (compliance and compliance.remesa) else "" acuse_valor = str(compliance.edocument) if (compliance and compliance.edocument) else "N/A" @@ -137,23 +152,75 @@ class FacturaImportacionMexService: elif 'broker' in locals() and broker and broker.license: patente_val = broker.license + + # --- Transport Data Fetching --- + transporte_txt = str(logistics.transport_type) if (logistics and logistics.transport_type) else "" + num_transporte_val = (logistics.trailer_num or "") if logistics else "" + + # Init values + placas_val = (logistics.license_plate or "") if logistics else "" # Placas Tracto + placas_remolque_val = "" + transportista_val = (logistics.carrier_id or "") if logistics else "" + caat_val = "" + scac_val = "" + licencia_cond_val = "" + + if logistics: + # 1. Transporter (CAAT / SCAC) + if logistics.carrier_id: + transporter_obj = db.query(Transporter).filter(Transporter.transporter_key == logistics.carrier_id).first() + if transporter_obj: + caat_val = transporter_obj.caat_code or "" + scac_val = transporter_obj.transport_code or "" # Mapping transport_code to SCAC + transportista_val = transporter_obj.name or logistics.carrier_id + + # 2. Vehicle (Placas Tracto) - Try transport_id first + if logistics.transport_id: + veh_obj = db.query(Vehicle).filter(Vehicle.vehicle_key == logistics.transport_id).first() + if veh_obj: + placas_val = veh_obj.plate_number or placas_val + elif logistics.vehicle_num: # Fallback to vehicle_num if populated and transport_id failed/empty + veh_obj = db.query(Vehicle).filter(Vehicle.vehicle_key == logistics.vehicle_num).first() + if veh_obj: + placas_val = veh_obj.plate_number or placas_val + + # 3. Trailer (Placas Remolque) + if logistics.trailer_num: + trl_obj = db.query(Trailer).filter(Trailer.trailer_number == logistics.trailer_num).first() + if trl_obj: + placas_remolque_val = trl_obj.plate_number or "" + + # 4. Driver (License) + if logistics.carrier_id and logistics.driver_name: + # Attempt to find driver by name + carrier + drv_obj = db.query(Driver).filter( + Driver.transporter_key == logistics.carrier_id, + Driver.driver_name == logistics.driver_name + ).first() + if drv_obj: + licencia_cond_val = drv_obj.license_number or "" + factura_schema = FacturaSchema( numero=header.invoice_number or "S/N", fecha=str(header.invoice_date) if header.invoice_date else "", - tipo_cambio=float(pedimento.exchange_rate) if pedimento and pedimento.exchange_rate else 1.0, + tipo_cambio=float(financials.exchange_rate) if (financials and financials.exchange_rate) else (float(pedimento.exchange_rate) if pedimento and pedimento.exchange_rate else 1.0), moneda=getattr(header, 'currency', "USD") or "USD", incoterm=(logistics.incoterm or "") if logistics else "", observaciones=header.observation_es or header.observation_en or "", - pedimento=pedimento.pedimento_number if pedimento else "", + pedimento=f"{pedimento.year} {pedimento.customs_office[:2] if pedimento.customs_office else ''} {pedimento.license} {pedimento.pedimento_number}" if pedimento else "", clave_pedimento=pedimento.pedimento_code if pedimento else "", - regimen=pedimento.regime if pedimento else "", + regimen=header.document_type or "", patente=patente_val, agente_aduanal=nombre_agente, - transporte=str(logistics.transport_type) if (logistics and logistics.transport_type) else "", - num_transporte=(logistics.trailer_num or "") if logistics else "", - placas=(logistics.license_plate or "") if logistics else "", - transportista=(logistics.carrier_id or "") if logistics else "", - aduana=pedimento.customs_office if pedimento else "", + transporte=transporte_txt, + num_transporte=num_transporte_val, + placas=placas_val, + placas_remolque=placas_remolque_val, + transportista=transportista_val, + caat=caat_val, + scac=scac_val, + licencia_conductor=licencia_cond_val, + aduana=compliance.aduana if (compliance and compliance.aduana) else (pedimento.customs_office[:2] if (pedimento and pedimento.customs_office) else ""), precinto=(logistics.seal_number or "") if logistics else "", destino=(logistics.destination_goods or "") if logistics else "", remesa=remesa_valor, acuse_electronico=acuse_valor @@ -197,13 +264,33 @@ class FacturaImportacionMexService: if adv_db and adv_db.strip() not in ["0", "0.0", "0.00", ""]: advalorem_txt = adv_db if "%" in adv_db else f"{adv_db}%" else: - advalorem_txt = "0%" # O podrías poner "EXENTO" si prefieres + advalorem_txt = "0%" fraccion_imprimir = fraccion_db.fraction or fraccion_raw else: fraccion_imprimir = self._format_fraccion_fallback(fraccion_limpia) + # Logic to determine values - Prioritize Specific Currency Columns + v_unitario = 0.0 + v_total = 0.0 + + if fin: + is_mxn = (factura_schema.moneda == 'MXN') + + # 1. Try Specific Currency Columns First + if is_mxn: + v_unitario = fin.unit_cost_commercial_mxn or 0.0 + v_total = fin.value_commercial_mxn or 0.0 + else: + v_unitario = fin.unit_cost_commercial_usd or 0.0 + v_total = fin.value_commercial_usd or 0.0 + + # 2. Fallback to Generic if Specific is 0 + if v_unitario == 0 or v_total == 0: + v_unitario = fin.commercial_unit_cost or 0.0 + v_total = fin.total_commercial_value or 0.0 + partidas_list.append(PartidaSchema( numero_parte=num_parte_final, descripcion=desc_final, @@ -217,8 +304,8 @@ class FacturaImportacionMexService: clave_bultos=qty.package_key if qty else "", peso_neto=self.formatear_numero(qty.net_weight if qty else 0), peso_bruto=self.formatear_numero(qty.gross_weight if qty else 0), - valor_costo_unitario=self.formatear_numero(fin.commercial_unit_cost if fin else 0), - valor_total=self.formatear_numero(fin.total_commercial_value if fin else 0) + valor_costo_unitario=self.formatear_numero(v_unitario), + valor_total=self.formatear_numero(v_total) )) totales = self.calcular_totales(partidas_list, Decimal(factura_schema.tipo_cambio)) @@ -259,7 +346,7 @@ class FacturaImportacionMexService: logo_b64 = None try: # Fetch company to get logo path - # We use the passed company_id which corresponds to the active company + comp_logo = db.query(Company).filter(Company.id == company_id).first() if comp_logo and comp_logo.logo: p = Path(comp_logo.logo) diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_mex_ver.html b/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_mex_ver.html index d73740b6..9a7479e5 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_mex_ver.html +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_mex_ver.html @@ -418,6 +418,11 @@ {{ cliente_vendido.programa }}: {{ cliente_vendido.autorizacion }} {% endif %}

+

+ {% if cliente_vendido.prosec %}PROSEC: {{ cliente_vendido.prosec }} {% endif %} + {% if cliente_vendido.reg_emp %}REG EMP: {{ cliente_vendido.reg_emp }} {% endif %} + {% if cliente_vendido.cert %}CERT: {{ cliente_vendido.cert }}{% endif %} +

@@ -431,7 +436,16 @@ cliente_enviado.codigo_postal }}{% endif %}

{{ cliente_enviado.ciudad }}, {{ cliente_enviado.estado }}, {{ cliente_enviado.pais }}

-

RFC: {{ cliente_enviado.tax_id }}

+

RFC: {{ cliente_enviado.tax_id }} + {% if cliente_enviado.programa and cliente_enviado.programa != 'Ninguno' %} + {{ cliente_enviado.programa }}: {{ cliente_enviado.autorizacion }} + {% endif %} +

+

+ {% if cliente_enviado.prosec %}PROSEC: {{ cliente_enviado.prosec }} {% endif %} + {% if cliente_enviado.reg_emp %}REG EMP: {{ cliente_enviado.reg_emp }} {% endif %} + {% if cliente_enviado.cert %}CERT: {{ cliente_enviado.cert }}{% endif %} +


@@ -456,7 +470,8 @@

{{ factura.incoterm }}

- From c5ea8d5868e62f69e275071811c1f4bfa78a9274 Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Fri, 16 Jan 2026 14:14:48 -0600 Subject: [PATCH 18/21] Se quito el id de partes y se quito el sticky de las tablas --- .../goods/classes/forms/FixedAssetClassForm.svelte | 14 +++++++------- .../goods/modales/client-selector-dialog.svelte | 2 +- .../modales/material-type-selector-dialog.svelte | 2 +- .../dashboard/clients_and_providers/+page.svelte | 2 +- .../routes/dashboard/customs_brokers/+page.svelte | 2 +- .../general_catalogs/tariff-fractions/+page.svelte | 2 +- .../goods/fixed-asset-classes/+page.svelte | 2 +- .../src/routes/dashboard/goods/parts/+page.svelte | 3 +-- 8 files changed, 14 insertions(+), 15 deletions(-) diff --git a/frontend/src/lib/components/dashboard/goods/classes/forms/FixedAssetClassForm.svelte b/frontend/src/lib/components/dashboard/goods/classes/forms/FixedAssetClassForm.svelte index e4b4fb5e..06bcd2d0 100644 --- a/frontend/src/lib/components/dashboard/goods/classes/forms/FixedAssetClassForm.svelte +++ b/frontend/src/lib/components/dashboard/goods/classes/forms/FixedAssetClassForm.svelte @@ -832,7 +832,7 @@
-

Aduana: {{ factura.aduana }}

+

Aduana: {{ factura.aduana }} / Ped: {{ factura.pedimento }}


@@ -473,15 +488,16 @@

CAAT: {{ factura.caat }}

-

Placas: {{ factura.placas or 'N/A' }}

+

Placas: {{ factura.placas or '' }} / Rem: {{ factura.placas_remolque or + '' }}

-


+
+

Chofer/Licencia:

-


+

{{ factura.licencia_conductor or 'N/A' }}

- + @@ -876,7 +876,7 @@
Clave Descripción
- + @@ -924,7 +924,7 @@
Código Descripción
- + @@ -982,7 +982,7 @@
Fracción NICO
- + @@ -1042,7 +1042,7 @@
Código Prefijo
- + @@ -1098,7 +1098,7 @@
Fracción Descripción
- + @@ -1152,7 +1152,7 @@
Clave FDA Descripción
- + diff --git a/frontend/src/lib/components/dashboard/goods/modales/client-selector-dialog.svelte b/frontend/src/lib/components/dashboard/goods/modales/client-selector-dialog.svelte index c6a45fce..2b7f0e75 100644 --- a/frontend/src/lib/components/dashboard/goods/modales/client-selector-dialog.svelte +++ b/frontend/src/lib/components/dashboard/goods/modales/client-selector-dialog.svelte @@ -102,7 +102,7 @@ {:else}
Código Descripción
- + diff --git a/frontend/src/lib/components/dashboard/goods/modales/material-type-selector-dialog.svelte b/frontend/src/lib/components/dashboard/goods/modales/material-type-selector-dialog.svelte index 5fa0974f..3e03b975 100644 --- a/frontend/src/lib/components/dashboard/goods/modales/material-type-selector-dialog.svelte +++ b/frontend/src/lib/components/dashboard/goods/modales/material-type-selector-dialog.svelte @@ -93,7 +93,7 @@ {:else}
ID RFC
- + diff --git a/frontend/src/routes/dashboard/clients_and_providers/+page.svelte b/frontend/src/routes/dashboard/clients_and_providers/+page.svelte index b548154b..e0551f6d 100644 --- a/frontend/src/routes/dashboard/clients_and_providers/+page.svelte +++ b/frontend/src/routes/dashboard/clients_and_providers/+page.svelte @@ -204,7 +204,7 @@
Clave Descripción
- + diff --git a/frontend/src/routes/dashboard/customs_brokers/+page.svelte b/frontend/src/routes/dashboard/customs_brokers/+page.svelte index 69695727..a1a68f0b 100644 --- a/frontend/src/routes/dashboard/customs_brokers/+page.svelte +++ b/frontend/src/routes/dashboard/customs_brokers/+page.svelte @@ -178,7 +178,7 @@
# RFC
- + diff --git a/frontend/src/routes/dashboard/general_catalogs/tariff-fractions/+page.svelte b/frontend/src/routes/dashboard/general_catalogs/tariff-fractions/+page.svelte index 337aaa4d..370eab1c 100644 --- a/frontend/src/routes/dashboard/general_catalogs/tariff-fractions/+page.svelte +++ b/frontend/src/routes/dashboard/general_catalogs/tariff-fractions/+page.svelte @@ -122,7 +122,7 @@
- + Código Fracción diff --git a/frontend/src/routes/dashboard/goods/fixed-asset-classes/+page.svelte b/frontend/src/routes/dashboard/goods/fixed-asset-classes/+page.svelte index 8a8acf8d..f6d5f3a2 100644 --- a/frontend/src/routes/dashboard/goods/fixed-asset-classes/+page.svelte +++ b/frontend/src/routes/dashboard/goods/fixed-asset-classes/+page.svelte @@ -498,7 +498,7 @@
Patente Nombre
- +
diff --git a/frontend/src/routes/dashboard/goods/parts/+page.svelte b/frontend/src/routes/dashboard/goods/parts/+page.svelte index 32938329..ea3f4bb0 100644 --- a/frontend/src/routes/dashboard/goods/parts/+page.svelte +++ b/frontend/src/routes/dashboard/goods/parts/+page.svelte @@ -221,7 +221,7 @@
- +
@@ -270,7 +270,6 @@
{clientsMap[part.client_id] || 'Cargando...'} - ID: {part.client_id}
From 53f3915de238a3c86a5b13c8189e720942726d70 Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Fri, 16 Jan 2026 15:47:04 -0600 Subject: [PATCH 19/21] Se mejor el estilo del reporte, ademas de que se corrigio el id en partes --- .../importacion/facturas/templates/factura_mex_ver.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_mex_ver.html b/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_mex_ver.html index 9a7479e5..ade499e4 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_mex_ver.html +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/templates/factura_mex_ver.html @@ -285,11 +285,11 @@
{% if logo_b64 %} -
+
{% endif %} -
+

{{ cliente_proveedor.header }}

{{ cliente_proveedor.nombre }}

{{ cliente_proveedor.direccion }} From 3d39360f9c23ced824feed48076f6ca877113ea9 Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Wed, 21 Jan 2026 09:47:28 -0600 Subject: [PATCH 20/21] Se introdujo el sistema de consolidados --- .../importacion/consolidados/mex/schemas.py | 97 +++ .../importacion/consolidados/mex/service.py | 565 ++++++++++++++++++ .../importacion/consolidados/routes.py | 48 ++ .../reports/importacion/consolidados/task.py | 52 ++ .../consolidados/templates/cons_mex_ver.html | 535 +++++++++++++++++ .../importacion/facturas/mex/service.py | 33 +- .../a76/reports/importacion/facturas/task.py | 4 +- backend/api/v1/modules/a76/router.py | 7 + backend/core/celery_app.py | 5 +- debug_values.py | 76 +++ .../a76/reports/reports-consolidated.ts | 35 ++ .../us-fraction-selector-dialog.svelte | 146 +++++ .../dashboard/goods/parts/partForm.svelte | 14 +- .../invoices/pdf-progress-dialog.svelte | 7 +- frontend/src/lib/stores/company.svelte.ts | 36 +- .../routes/dashboard/invoices/+page.svelte | 39 +- reinicio.sh | 5 + 17 files changed, 1666 insertions(+), 38 deletions(-) create mode 100644 backend/api/v1/modules/a76/reports/importacion/consolidados/mex/schemas.py create mode 100644 backend/api/v1/modules/a76/reports/importacion/consolidados/mex/service.py create mode 100644 backend/api/v1/modules/a76/reports/importacion/consolidados/routes.py create mode 100644 backend/api/v1/modules/a76/reports/importacion/consolidados/task.py create mode 100644 backend/api/v1/modules/a76/reports/importacion/consolidados/templates/cons_mex_ver.html create mode 100644 debug_values.py create mode 100644 frontend/src/lib/api/dashboard/a76/reports/reports-consolidated.ts create mode 100644 frontend/src/lib/components/dashboard/goods/modales/us-fraction-selector-dialog.svelte create mode 100755 reinicio.sh diff --git a/backend/api/v1/modules/a76/reports/importacion/consolidados/mex/schemas.py b/backend/api/v1/modules/a76/reports/importacion/consolidados/mex/schemas.py new file mode 100644 index 00000000..003af79d --- /dev/null +++ b/backend/api/v1/modules/a76/reports/importacion/consolidados/mex/schemas.py @@ -0,0 +1,97 @@ +from decimal import Decimal +from typing import List, Optional, Union +from pydantic import BaseModel, field_validator + + +class ClienteSchema(BaseModel): + header: str + nombre: str + # Ponemos valor por defecto "" y permitimos que sea opcional + direccion: Optional[str] = "" + num_exterior: Optional[str] = "" + num_interior: Optional[str] = "" + colonia: Optional[str] = "" + codigo_postal: Optional[str] = "" + ciudad: Optional[str] = "" + estado: Optional[str] = "" + pais: Optional[str] = "" + tax_id: str + programa: Optional[str] = "" + autorizacion: Optional[str] = "" + prosec: Optional[str] = "" + reg_emp: Optional[str] = "" + cert: Optional[str] = "" + + # Si llega un None, lo convertimos en "" automáticamente + @field_validator('direccion', 'nombre', mode='before') + @classmethod + def prevent_none(cls, v): + return v or "" + +class FacturaSchema(BaseModel): + numero: str + fecha: str + tipo_cambio: float + moneda: str + # Campos de aduanas (Opcionales por si A76 aún no los tiene) + pedimento: str = "" + clave_pedimento: str = "" + remesa: str = "" + acuse_electronico: str = "" + representante_legal: str = "" + nombre_empresa: str = "" + agente_aduanal: str = "" + patente: str = "" + precinto: str = "" + regimen: str = "" + transportista: str = "" + scac: str = "" + caat: str = "" + incoterm: str = "" + transporte: str = "" + num_transporte: str = "" + placas: str = "" + placas_remolque: str = "" + licencia_conductor: str = "" + caat: str = "" + scac: str = "" + aduana: str = "" + destino: str = "" + observaciones: str = "" + +class PartidaSchema(BaseModel): + numero_parte: str + descripcion: str + fraccion: str + origen: str + + advalorem:Optional[str] = "" + preferencia:Optional[str] = "" + + cantidad_importacion: Union[float, str] + unidad_medida: str + cantidad_bultos: int + clave_bultos: str + peso_neto: Union[float, str] + peso_bruto: Union[float, str] + valor_costo_unitario: Union[float, str] + valor_total: Union[float, str] + valor_estimado: Union[float, str] = "0.00" + +class TotalesSchema(BaseModel): + cantidad_total: Union[float, str] + bultos_total: int + clave_bultos: str = "" + peso_neto_total: Union[float, str] + peso_bruto_total: Union[float, str] + valor_total_total: Union[float, str] + valor_total_dolares: Union[float, str] + valor_estimado_total: Union[float, str] = "0.00" + +class FacturaImportacionCompleta(BaseModel): + cliente_proveedor: ClienteSchema + cliente_vendido: ClienteSchema + cliente_enviado: ClienteSchema + factura: FacturaSchema + partidas: List[PartidaSchema] + totales: TotalesSchema diff --git a/backend/api/v1/modules/a76/reports/importacion/consolidados/mex/service.py b/backend/api/v1/modules/a76/reports/importacion/consolidados/mex/service.py new file mode 100644 index 00000000..6bfab155 --- /dev/null +++ b/backend/api/v1/modules/a76/reports/importacion/consolidados/mex/service.py @@ -0,0 +1,565 @@ +import shutil +import base64 +import pdfkit +from pathlib import Path +from decimal import Decimal +from typing import Tuple, List, Callable, Optional + +from jinja2 import Environment, FileSystemLoader, select_autoescape +from fastapi import HTTPException +from sqlalchemy.orm import Session + +# --- MODELOS --- +from api.v1.modules.a76.invoices.models import InvoiceHeader, InvoiceLogistics, InvoiceComplianceMx +from api.v1.modules.a76.items.line_financials.models import LineFinancial +from api.v1.modules.a76.items.line_quantities.models import LineQuantity +from api.v1.modules.a76.items.line_items.models import LineItem +from api.v1.modules.a76.clients_and_providers.models import ( + ClientProvider, ClientProviderAddress, ClientProviderPrograms +) +from api.v1.modules.a76.parts.models import Part +from api.v1.modules.a76.pedmientos.models import Pedimentos +from api.v1.modules.a76.general_catalogs.company.models import Company +from api.v1.modules.a76.customs_brokers.models import CustomsBroker +from api.v1.modules.a76.items.models import Item + +# --- TRANSPORTATION MODELS --- +from api.v1.modules.a76.transportation.transporters.models import Transporter +from api.v1.modules.a76.transportation.vehicles.models import Vehicle +from api.v1.modules.a76.transportation.trailers.models import Trailer +from api.v1.modules.a76.transportation.drivers.models import Driver + +# --- MODELO DE FRACCIONES --- +from api.v1.modules.a76.general_catalogs.tariff_fractions.models import TariffFraction + +# --- SCHEMAS --- +from .schemas import ( + ClienteSchema, PartidaSchema, TotalesSchema, + FacturaSchema, FacturaImportacionCompleta +) + +class ConsolidadoImportacionMexService: + def __init__(self): + self.template_dir = Path(__file__).parent.parent / "templates" + self.jinja_env = Environment( + loader=FileSystemLoader(self.template_dir), + autoescape=select_autoescape(['html', 'xml']) + ) + self.template = self.jinja_env.get_template('cons_mex_ver.html') + + def _get_wkhtmltopdf_config(self): + path = shutil.which("wkhtmltopdf") or "/usr/local/bin/wkhtmltopdf" + if not Path(path).exists(): + raise RuntimeError("wkhtmltopdf no encontrado.") + return pdfkit.configuration(wkhtmltopdf=path) + + def formatear_numero(self, valor, decimales: int = 2): + if valor is None: return 0.0 + try: + return round(float(valor), decimales) + except: return 0.0 + + def _format_fraccion_fallback(self, fraccion_raw: str) -> str: + if not fraccion_raw or len(fraccion_raw) < 8: + return fraccion_raw + return f"{fraccion_raw[:4]}.{fraccion_raw[4:6]}.{fraccion_raw[6:]}" + + def _obtener_datos_cliente(self, db: Session, client_id: int, rol: str) -> ClienteSchema: + main = db.query(ClientProvider).filter(ClientProvider.id == client_id).first() + if not main: + return ClienteSchema(header=rol, nombre="Desconocido", direccion="", tax_id="", codigo_postal="", ciudad="", estado="", pais="MEX") + + addr = db.query(ClientProviderAddress).filter(ClientProviderAddress.client_id == client_id).first() + prog = db.query(ClientProviderPrograms).filter(ClientProviderPrograms.client_id == client_id).first() + + return ClienteSchema( + header=rol, + nombre=(main.name or main.short_name) or "S/N", + direccion=(addr.streets or "") if addr else "", + num_exterior=(addr.exterior_number or "") if addr else "", + num_interior=(addr.interior_number or "") if addr else "", + colonia=(addr.neighborhood or "") if addr else "", + codigo_postal=(addr.postal_code or "") if addr else "", + ciudad=(addr.city or "") if addr else "", + estado=(addr.state or "") if addr else "", + pais=(addr.country or "MEX") if addr else "MEX", + tax_id=prog.tax_id if (prog and prog.tax_id) else (getattr(main, 'rfc', "") or ""), + programa="IMMEX" if (prog and prog.program) else "", + autorizacion=prog.program_number if prog else "", + prosec=prog.prosec_authorization if (prog and prog.prosec and prog.prosec_authorization) else "", + reg_emp=prog.val_certified_company_registry if (prog and hasattr(prog, 'val_certified_company_registry')) else ( + prog.certified_company_registry if (prog and prog.certified_company_registry) else "" + ), + cert=prog.is_certified_company if (prog and prog.is_certified_company) else "" + ) + + def obtener_datos(self, db: Session, invoice_id: int, company_id: int, progress_callback: Optional[Callable] = None) -> FacturaImportacionCompleta: + try: + if progress_callback: progress_callback(10, "Buscando factura...") + header = db.query(InvoiceHeader).filter(InvoiceHeader.id == invoice_id, InvoiceHeader.company_id == company_id).first() + if not header: raise HTTPException(status_code=404, detail="Factura no encontrada") + + compliance = header.compliance_mx + logistics = header.logistics if header.logistics else None + financials = header.financials if header.financials else None + if progress_callback: progress_callback(20, "Obteniendo datos de pedimento...") + pedimento_id = compliance.pedimento_id if (compliance and compliance.pedimento_id) else header.related_doc_id + pedimento = db.query(Pedimentos).filter(Pedimentos.id == pedimento_id).first() if pedimento_id else None + + if progress_callback: progress_callback(30, "Obteniendo cliente y proveedor...") + proveedor_id = compliance.provider_id if compliance else None + cliente_proveedor = self._obtener_datos_cliente(db, proveedor_id, "Proveedor / supplier:") if proveedor_id else ClienteSchema(header="Proveedor", nombre="No Asignado", direccion="", tax_id="", codigo_postal="", ciudad="", estado="", pais="") + + nombre_agente = "" + if compliance and compliance.customs_broker_id: + broker = db.query(CustomsBroker).filter(CustomsBroker.id == compliance.customs_broker_id).first() + if broker: nombre_agente = broker.name + + company = db.query(Company).filter(Company.id == header.company_id).first() + # Datos Default (Company/Importer) - Used for fallback or Right Side (Enviado A) + # Default Header (Company) + cliente_default = ClienteSchema( + header="Importer / Consignee:", + nombre=getattr(company, 'name', "Empresa Local"), + direccion="DOMICILIO FISCAL", + num_exterior="", colonia="", codigo_postal="", ciudad="", estado="", pais="MEX", + tax_id=getattr(company, 'rfc', ""), + programa=getattr(company, 'program', "IMMEX"), autorizacion=getattr(company, 'program_number', "") + ) + + # Left Side Logic (Consignatario / Sold To) + cliente_vendido = cliente_default + if compliance and compliance.sold_to_id: + # Map known headers or default to Sold To / Vendido a + raw = (compliance.sold_to_header or "").upper() + if "CONSIGN" in raw: + clean_header = "Consignee / Consignatario:" + else: + clean_header = "Sold To / Vendido a:" + + cliente_vendido = self._obtener_datos_cliente(db, compliance.sold_to_id, clean_header) + + # Right Side Logic (Enviado A / Shipped To) + cliente_enviado = cliente_default + if compliance and compliance.shipped_to_id: + # Map to Shipped To / Enviado a + clean_header_shipped = "Shipped To / Enviado a:" + + # Fetch client data + cliente_enviado = self._obtener_datos_cliente(db, compliance.shipped_to_id, clean_header_shipped) + + remesa_valor = str(compliance.remesa) if (compliance and compliance.remesa) else "" + acuse_valor = str(compliance.edocument) if (compliance and compliance.edocument) else "N/A" + + patente_val = "" + if pedimento and pedimento.license: + patente_val = pedimento.license + elif 'broker' in locals() and broker and broker.license: + patente_val = broker.license + + + # --- Transport Data Fetching --- + transporte_txt = str(logistics.transport_type) if (logistics and logistics.transport_type) else "" + num_transporte_val = (logistics.trailer_num or "") if logistics else "" + + # Init values + placas_val = (logistics.license_plate or "") if logistics else "" # Placas Tracto + placas_remolque_val = "" + transportista_val = (logistics.carrier_id or "") if logistics else "" + caat_val = "" + scac_val = "" + licencia_cond_val = "" + + if logistics: + # 1. Transporter (CAAT / SCAC) + if logistics.carrier_id: + transporter_obj = db.query(Transporter).filter(Transporter.transporter_key == logistics.carrier_id).first() + if transporter_obj: + caat_val = transporter_obj.caat_code or "" + scac_val = transporter_obj.transport_code or "" # Mapping transport_code to SCAC + transportista_val = transporter_obj.name or logistics.carrier_id + + # 2. Vehicle (Placas Tracto) - Try transport_id first + if logistics.transport_id: + veh_obj = db.query(Vehicle).filter(Vehicle.vehicle_key == logistics.transport_id).first() + if veh_obj: + placas_val = veh_obj.plate_number or placas_val + elif logistics.vehicle_num: # Fallback to vehicle_num if populated and transport_id failed/empty + veh_obj = db.query(Vehicle).filter(Vehicle.vehicle_key == logistics.vehicle_num).first() + if veh_obj: + placas_val = veh_obj.plate_number or placas_val + + # 3. Trailer (Placas Remolque) + if logistics.trailer_num: + trl_obj = db.query(Trailer).filter(Trailer.trailer_number == logistics.trailer_num).first() + if trl_obj: + placas_remolque_val = trl_obj.plate_number or "" + + # 4. Driver (License) + if logistics.carrier_id and logistics.driver_name: + # Attempt to find driver by name + carrier + drv_obj = db.query(Driver).filter( + Driver.transporter_key == logistics.carrier_id, + Driver.driver_name == logistics.driver_name + ).first() + if drv_obj: + licencia_cond_val = drv_obj.license_number or "" + + factura_schema = FacturaSchema( + numero=header.invoice_number or "S/N", + fecha=str(header.invoice_date) if header.invoice_date else "", + tipo_cambio=float(financials.exchange_rate) if (financials and financials.exchange_rate) else (float(pedimento.exchange_rate) if pedimento and pedimento.exchange_rate else 1.0), + moneda=getattr(header, 'currency', "USD") or "USD", + incoterm=(logistics.incoterm or "") if logistics else "", + observaciones=header.observation_es or header.observation_en or "", + pedimento=f"{pedimento.year} {pedimento.customs_office[:2] if pedimento.customs_office else ''} {pedimento.license} {pedimento.pedimento_number}" if pedimento else "", + clave_pedimento=pedimento.pedimento_code if pedimento else "", + regimen=header.document_type or "", + patente=patente_val, + agente_aduanal=nombre_agente, + transporte=transporte_txt, + num_transporte=num_transporte_val, + placas=placas_val, + placas_remolque=placas_remolque_val, + transportista=transportista_val, + caat=caat_val, + scac=scac_val, + licencia_conductor=licencia_cond_val, + aduana=compliance.aduana if (compliance and compliance.aduana) else (pedimento.customs_office[:2] if (pedimento and pedimento.customs_office) else ""), + precinto=(logistics.seal_number or "") if logistics else "", + destino=(logistics.destination_goods or "") if logistics else "", + remesa=remesa_valor, acuse_electronico=acuse_valor, + representante_legal=getattr(company, 'responsible', "") or "", + nombre_empresa=getattr(company, 'name', "") or "" + ) + + if progress_callback: progress_callback(50, "Procesando partidas...") + + # --- Fetch Lines from SINGLE Invoice (Requested Scope Change) --- + # User requested to ONLY report items from the specific selected invoice, + # NOT consolidating all invoices from the same Pedimento. + target_invoice_ids = [header.id] + + lines = db.query(LineItem).join(Item, LineItem.item_id == Item.id).filter( + Item.invoice_id.in_(target_invoice_ids) + ).all() + + partidas_list = [] + + # --- AGGREGATION LOGIC (Refactoring based on Clarion) --- + from collections import defaultdict + # Key: (us_fraction_code, origin_country) + # Value: Object with accumulated fields + aggregated_data = defaultdict(lambda: { + "qty": 0.0, + "net_weight_kgs": 0.0, + "gross_weight_kgs": 0.0, + "total_value": 0.0, + "est_total_value": 0.0, + "description": "", + "advalorem_txt": "0%", + "unit_measure": "PZA", # Placeholder, takes first one found + "hts_code_print": "", + "part_number_display": "CONSOLIDADO" + }) + + # Pre-fetch US Tariff Fractions for efficiency if possible, or query inside loop (caching recommended) + # For simplicity in this step, we query inside or rely on Part data. + # Ideally fetch USTariffFraction from DB based on Part.us_fraction + + from api.v1.modules.a76.general_catalogs.us_tariff_fractions.models import USTariffFraction + + for line in lines: + qty = db.query(LineQuantity).filter(LineQuantity.item_line_id == line.id).first() + fin = db.query(LineFinancial).filter(LineFinancial.item_line_id == line.id).first() + part_master = db.query(Part).filter(Part.id == line.part_number).first() + + # --- Resolver Identificadores --- + us_fraction_raw = "" + origin_final = "MEX" + + if part_master: + origin_final = part_master.fa_data.origin_country if (part_master.fa_data and part_master.fa_data.origin_country) else "MEX" + us_fraction_raw = part_master.us_fraction if part_master.us_fraction else "" + + # Cleaning Fraction + us_frac_clean = us_fraction_raw.strip() + + # Key for aggregation + agg_key = (us_frac_clean, origin_final) + + # --- Weights & Qty --- + # --- Optimización: Cargar Facturas en Memoria (Evitar N+1 y arreglar AttributeError) --- + # Pre-fetch invoices explicitly since line.item.invoice relationship might not exist + invoices_list = db.query(InvoiceHeader).filter(InvoiceHeader.id.in_(target_invoice_ids)).all() + invoice_map = {inv.id: inv for inv in invoices_list} + + for line in lines: + qty = db.query(LineQuantity).filter(LineQuantity.item_line_id == line.id).first() + fin = db.query(LineFinancial).filter(LineFinancial.item_line_id == line.id).first() + part_master = db.query(Part).filter(Part.id == line.part_number).first() + # --- Weights & Qty --- + q_line = float(qty.quantity) if (qty and qty.quantity) else 0.0 + nw_line = float(qty.net_weight) if qty else 0.0 + gw_line = float(qty.gross_weight) if qty else 0.0 + + # --- Multi-Currency Normalization Logic --- + # Determine Line Currency context + # Use manual lookup instead of specific attribute + invoice_id = line.item.invoice_id if line.item else None + line_invoice = invoice_map.get(invoice_id) if invoice_id else None + + line_currency_is_mxn = False + line_exchange_rate = 1.0 + + if line_invoice and line_invoice.financials: + # Check explicit currency string AND code + curr_desc = str(line_invoice.financials.currency or "").upper() + curr_code = str(line_invoice.financials.currency_type or "").upper() + + # Logic: It is MXN if description says PESO/MX or code is MXN/MN + is_mx_desc = ("MX" in curr_desc or "PESO" in curr_desc) + is_mx_code = ("MXN" in curr_code or "MN" == curr_code) + + # But if code allows clarifying USD, prioritize that + is_usd_code = ("USD" in curr_code) + + if is_usd_code: + line_currency_is_mxn = False + elif is_mx_code or is_mx_desc: + line_currency_is_mxn = True + else: + line_currency_is_mxn = False # Default to Foreign/USD if unsure + + line_exchange_rate = float(line_invoice.financials.exchange_rate or 1.0) + + # Target Report Currency + report_is_mxn = (factura_schema.moneda == 'MXN') + + # DEBUG LOGGING + if line_invoice: + print(f"DEBUG: Line {line.id} - Inv {line_invoice.id} - CurrDesc: '{curr_desc}' Code: '{curr_code}' - Rate: {line_exchange_rate}") + print(f"DEBUG: Is MXN Context? {line_currency_is_mxn}. Report is MXN? {report_is_mxn}") + + # --- Get Financials for Line (Raw) --- + v_total_raw = 0.0 + v_unitario_raw = 0.0 + + if fin: + # NEW PRIORITY LOGIC (To avoid Inflation from dirty Customs Unit Cost) + # Priority 1: Use 'fin.value_usd' if it exists and > 0. + # Priority 2: Use 'fin.total_commercial_value' if it exists and > 0. + # Priority 3: Calculate using 'fin.unit_cost_commercial_usd' * 'q_line'. + # Priority 4: Only use 'fin.unit_cost_usd' * 'q_line' if commercial data is also missing. + + val_usd = float(fin.value_usd or 0.0) + total_comm = float(fin.total_commercial_value or 0.0) + unit_comm_usd = float(fin.unit_cost_commercial_usd or 0.0) + unit_usd = float(fin.unit_cost_usd or 0.0) + + # 1. Direct Total: Custom Value (Best case) + if val_usd > 0: + v_total_raw = val_usd + + # 2. Direct Total: Commercial Total + elif total_comm > 0: + # Convert if invoice currency is MXN + if line_currency_is_mxn and line_exchange_rate > 0: + v_total_raw = total_comm / line_exchange_rate + else: + v_total_raw = total_comm + + # 3. Calc from Commercial Unit Cost (Safe Fallback) + elif unit_comm_usd > 0 and q_line > 0: + v_total_raw = unit_comm_usd * q_line + + # 4. Calc from Customs Unit Cost (Unknown Risk - Last Resort) + elif unit_usd > 0 and q_line > 0: + v_total_raw = unit_usd * q_line + + else: + v_total_raw = 0.0 + + # NOTE: v_unitario_raw is left as 0.0 here. + # It will be calculated in the 'Calculation Gap Fill' block below: + # v_unitario_raw = v_total_raw / q_line + # This guarantees consistency and avoids the inflated unit cost record (198.00). + + # --- Calculation Gap Fill (Raw) --- + if q_line > 0: + if v_total_raw == 0 and v_unitario_raw > 0: + v_total_raw = v_unitario_raw * q_line + if v_unitario_raw == 0 and v_total_raw > 0: + v_unitario_raw = v_total_raw / q_line + + # --- Conversion to Report Currency (DISABLED TEMPORARILY) --- + # User confirms all are USD. Forcing direct sum to avoid logic errors in detection. + v_total_line = v_total_raw + v_unitario_line = v_unitario_raw + + # if report_is_mxn and not line_currency_is_mxn: + # # USD -> MXN + # v_total_line = v_total_raw * line_exchange_rate + # v_unitario_line = v_unitario_raw * line_exchange_rate + # elif not report_is_mxn and line_currency_is_mxn: + # # MXN -> USD + # if line_exchange_rate > 0: + # v_total_line = v_total_raw / line_exchange_rate + # v_unitario_line = v_unitario_raw / line_exchange_rate + # else: + # v_total_line = 0.0 + # v_unitario_line = 0.0 + + print(f"DEBUG: ValRaw: {v_total_raw} -> ValFinal: {v_total_line}") + + # --- Resolve Fraction Details (Description & Rate) --- + # Only if this is the first time we see this key (or overwrite, doesn't matter much as they should be same for same HTS) + # We check if we already have description set to avoid re-querying if we want optimization, + # but relying on DB query per distinct fraction is safer. + + current_agg = aggregated_data[agg_key] + + if not current_agg["description"]: + us_frac_db = db.query(USTariffFraction).filter(USTariffFraction.code == us_frac_clean).first() + if us_frac_db: + current_agg["description"] = us_frac_db.description or "Sin Descripción" + # Parse AdValorem from DB if available, else 0 ?? + # Creating logical placeholder. The provided Clarion code used `FraAme.Adv` + adv_val = us_frac_db.ad_valorem # Assuming field exists based on viewing file later? + # Wait, in us-tariff-fractions.ts I saw `ad_valorem: number | null`. + current_agg["advalorem_txt"] = f"{adv_val}%" if adv_val is not None else "0%" + else: + current_agg["description"] = part_master.description_spanish if part_master else "S/D" + + current_agg["hts_code_print"] = us_frac_clean + current_agg["unit_measure"] = qty.weight_unit if qty else "KGS" # Default to first found + + # --- Calculate Estimated Tax for this Line --- + rate = 0.0 + try: + clean_adv = current_agg["advalorem_txt"].replace("%", "").strip() + rate = float(clean_adv) / 100.0 + except: rate = 0.0 + + v_est_line = v_total_line * rate + + # --- Accumulate --- + current_agg["qty"] += q_line + current_agg["net_weight_kgs"] += nw_line + current_agg["gross_weight_kgs"] += gw_line + current_agg["total_value"] += v_total_line + current_agg["est_total_value"] += v_est_line + + + # --- Convert Aggregated Data to Schema List --- + partidas_list = [] + + for (hts, origin), data in aggregated_data.items(): + + # Calculate Unit Price based on Total Value / Total Qty + unit_price = 0.0 + if data["qty"] > 0: + unit_price = data["total_value"] / data["qty"] + + partidas_list.append(PartidaSchema( + numero_parte="VARIOS", # Or empty + descripcion=data["description"], + fraccion=data["hts_code_print"], + origen=origin, + advalorem=data["advalorem_txt"], + preferencia="General", + cantidad_importacion=self.formatear_numero(data["qty"]), + unidad_medida=data["unit_measure"], + cantidad_bultos=0, # Summing bultos might be tricky if not homogeneous, check logic later + clave_bultos="", + peso_neto=self.formatear_numero(data["net_weight_kgs"]), + peso_bruto=self.formatear_numero(data["gross_weight_kgs"]), + valor_costo_unitario=self.formatear_numero(unit_price), + valor_total=self.formatear_numero(data["total_value"]), + valor_estimado=self.formatear_numero(data["est_total_value"]) + )) + + # Sort by Fraction (HTS Code) + partidas_list.sort(key=lambda x: x.fraccion) + + totales = self.calcular_totales(partidas_list, Decimal(factura_schema.tipo_cambio)) + + return FacturaImportacionCompleta( + cliente_proveedor=cliente_proveedor, cliente_vendido=cliente_vendido, + cliente_enviado=cliente_enviado, factura=factura_schema, + partidas=partidas_list, totales=totales + ) + + except Exception as e: + print(f"Error Service A76: {e}") + raise HTTPException(status_code=500, detail=f"Error: {str(e)}") + + def calcular_totales(self, partidas: List[PartidaSchema], tipo_cambio: Decimal) -> TotalesSchema: + cant = sum(p.cantidad_importacion for p in partidas) + valor = sum(p.valor_total for p in partidas) + peso_n = sum(p.peso_neto for p in partidas) + peso_b = sum(p.peso_bruto for p in partidas) + bultos = sum(p.cantidad_bultos for p in partidas) + claves = [p.clave_bultos for p in partidas if p.clave_bultos] + clave_comun = max(set(claves), key=claves.count) if claves else "" + if bultos > 1 and clave_comun and not clave_comun.endswith("S"): clave_comun += "S" + v_est = sum(p.valor_estimado for p in partidas if isinstance(p.valor_estimado, (int, float, Decimal))) + + tc = float(tipo_cambio) if tipo_cambio else 1.0 + return TotalesSchema( + cantidad_total=self.formatear_numero(cant), bultos_total=bultos, clave_bultos=clave_comun, + peso_neto_total=self.formatear_numero(peso_n), peso_bruto_total=self.formatear_numero(peso_b), + valor_total_total=self.formatear_numero(valor), valor_total_dolares=self.formatear_numero(valor / tc if tc > 0 else 0), + valor_estimado_total=self.formatear_numero(v_est) + ) + + def generar_factura_completa(self, db: Session, invoice_id: int, company_id: int, formato: str = "pdf", progress_callback: Optional[Callable] = None) -> Tuple[bytes, str, str]: + if progress_callback: progress_callback(5, "Iniciando servicio de reporte...") + datos = self.obtener_datos(db, invoice_id, company_id, progress_callback) + + if progress_callback: progress_callback(80, "Renderizando plantilla...") + + # LOGO LOGIC + logo_b64 = None + try: + # Fetch company to get logo path + + comp_logo = db.query(Company).filter(Company.id == company_id).first() + if comp_logo and comp_logo.logo: + p = Path(comp_logo.logo) + + # Logic robusta de búsqueda (igual que en routes.py) + target_path = p + if not target_path.exists(): + # Intentar en la ruta estándar: app_data/logos/{id}/{nombre} + # Esto cubre el caso donde solo se guardó el nombre del archivo o la ruta absoluta cambió + fallback = Path(f"app_data/logos/{company_id}") / p.name + if fallback.exists(): + target_path = fallback + + if target_path.exists(): + with open(target_path, "rb") as image_file: + encoded_string = base64.b64encode(image_file.read()).decode('utf-8') + # Detect MIME type loosely + mime = "image/png" + if target_path.suffix.lower() in ['.jpg', '.jpeg']: mime = "image/jpeg" + logo_b64 = f"data:{mime};base64,{encoded_string}" + except Exception as e: + print(f"Error loading logo: {e}") + + context = { + 'cliente_proveedor': datos.cliente_proveedor.model_dump(), 'cliente_vendido': datos.cliente_vendido.model_dump(), + 'cliente_enviado': datos.cliente_enviado.model_dump(), 'factura': datos.factura.model_dump(), + 'partidas': [p.model_dump() for p in datos.partidas], 'totales': datos.totales.model_dump(), + 'logo_b64': logo_b64 + } + html_content = self.template.render(**context) + nombre = f"Consolidado_{datos.factura.numero}.{formato}" + if formato == "html": return html_content.encode('utf-8'), nombre, "text/html" + + if progress_callback: progress_callback(90, "Generando PDF final...") + options = {'page-size': 'Letter', 'margin-top': '0.5in', 'margin-right': '0.5in', 'margin-bottom': '0.5in', 'margin-left': '0.5in', 'encoding': "UTF-8", 'enable-local-file-access': None} + pdf = pdfkit.from_string(html_content, False, options=options, configuration=self._get_wkhtmltopdf_config()) + + if progress_callback: progress_callback(100, "Completado") + return pdf, nombre, "application/pdf" diff --git a/backend/api/v1/modules/a76/reports/importacion/consolidados/routes.py b/backend/api/v1/modules/a76/reports/importacion/consolidados/routes.py new file mode 100644 index 00000000..5254cfe4 --- /dev/null +++ b/backend/api/v1/modules/a76/reports/importacion/consolidados/routes.py @@ -0,0 +1,48 @@ +from enum import Enum +from typing import Dict, Any +from fastapi import APIRouter, Depends, Query, Response, HTTPException +from sqlalchemy.orm import Session +from celery.result import AsyncResult +from core.celery_app import celery_app +from core.database import get_core_db +from core.security import get_current_user, validate_access_to_resource +from .mex.service import ConsolidadoImportacionMexService +from .task import generar_pdf_consolidado_async + +router = APIRouter() +servicio_mex = ConsolidadoImportacionMexService() + +@router.get("/tasks/{task_id}") +async def get_task_status( + task_id: str, + current_user: Dict[str, Any] = Depends(get_current_user), + db: Session = Depends(get_core_db) +): + task_result = AsyncResult(task_id, app=celery_app) + + response = { + "task_id": task_id, + "state": task_result.state, + "result": None, + "info": None + } + + if task_result.state == 'FAILURE': + response["result"] = str(task_result.result) + elif task_result.state == 'SUCCESS': + response["result"] = task_result.result + elif task_result.state == 'PROCESSING': + response["info"] = task_result.info + + return response + +@router.post("/{invoice_id}/download-async") +async def trigger_descarga_consolidado( + invoice_id: int, + company_id: int = Query(..., description="ID de la empresa"), + current_user: Dict[str, Any] = Depends(get_current_user), + db: Session = Depends(get_core_db) +): + validate_access_to_resource(db, company_id, current_user) + task = generar_pdf_consolidado_async.delay(invoice_id, company_id) + return {"task_id": task.id, "message": "Generación iniciada"} diff --git a/backend/api/v1/modules/a76/reports/importacion/consolidados/task.py b/backend/api/v1/modules/a76/reports/importacion/consolidados/task.py new file mode 100644 index 00000000..23e680c1 --- /dev/null +++ b/backend/api/v1/modules/a76/reports/importacion/consolidados/task.py @@ -0,0 +1,52 @@ +import base64 +import logging +from core.celery_app import celery_app +from celery import current_task, states +from core.database import CoreSessionLocal + +from .mex.service import ConsolidadoImportacionMexService + +logger = logging.getLogger(__name__) + +@celery_app.task(name="generar_pdf_consolidado_async", bind=True) +def generar_pdf_consolidado_async(self, invoice_id: int, company_id: int): + + # 1. Abrimos conexión a la DB + db = CoreSessionLocal() + try: + logger.info(f"Worker procesando consolidado {invoice_id}...") + + # 2. Instanciamos el servicio de reportes + service = ConsolidadoImportacionMexService() + + # Update state to PROCESSING + self.update_state(state='PROCESSING', meta={'current': 5, 'total': 100, 'status': 'Iniciando generación...'}) + + def progress_callback(progress: int, status: str): + self.update_state(state='PROCESSING', meta={'current': progress, 'total': 100, 'status': status}) + + # 3. Generamos los bytes del PDF + pdf_bytes, nombre, media_type = service.generar_factura_completa( + db=db, + invoice_id=invoice_id, + company_id=company_id, + progress_callback=progress_callback + ) + + # 4. Codificamos a base64 para que viaje seguro por Valkey + pdf_base64 = base64.b64encode(pdf_bytes).decode('utf-8') + + return { + "status": "success", + "file_name": nombre, + "content": pdf_base64, + "media_type": media_type + } + + except Exception as e: + logger.error(f"Error en Celery Worker: {str(e)}") + return {"status": "error", "message": str(e)} + + finally: + # 5. MUY IMPORTANTE: Cerramos la conexión para no saturar Postgres + db.close() diff --git a/backend/api/v1/modules/a76/reports/importacion/consolidados/templates/cons_mex_ver.html b/backend/api/v1/modules/a76/reports/importacion/consolidados/templates/cons_mex_ver.html new file mode 100644 index 00000000..17f4051a --- /dev/null +++ b/backend/api/v1/modules/a76/reports/importacion/consolidados/templates/cons_mex_ver.html @@ -0,0 +1,535 @@ + + + + + + Consolidado Importacion Mexicana - {{ factura.numero }} + + + + +

+
+
+

HTS Code / Fracción Americana (temporal)

+
+

+
+
+

+


+
+
+
+
+ {% if logo_b64 %} +
+ +
+ {% endif %} +
+

{{ cliente_proveedor.header }}

+

{{ cliente_proveedor.nombre }}

+

{{ cliente_proveedor.direccion }} + {% if cliente_proveedor.num_exterior %} Ext: {{ cliente_proveedor.num_exterior }}{% endif %} + {% if cliente_proveedor.num_interior %} Int: {{ cliente_proveedor.num_interior }}{% endif %} +

+

{{ cliente_proveedor.colonia }} {% if cliente_proveedor.codigo_postal %} CP: {{ + cliente_proveedor.codigo_postal }}{% endif %}

+

{{ cliente_proveedor.ciudad }}, {{ cliente_proveedor.estado }}, {{ cliente_proveedor.pais }}

+

TAX ID: {{ cliente_proveedor.tax_id }} + {% if cliente_proveedor.programa and cliente_proveedor.programa != 'Ninguno' %} + {{ cliente_proveedor.programa }}: {{ cliente_proveedor.autorizacion }} + {% endif %} +

+


+
+
+ +
+ + + + + + + + + + + + + + + +
+

Invoice No. / Num. Factura:

+
+

{{ factura.numero }}

+
+

Date / Fecha:

+
+

{{ factura.fecha }}

+
+

Rate / Cambio:

+
+

{{ factura.tipo_cambio }}

+
+
+
+ +
+
+

{{ cliente_vendido.header }}

+

{{ cliente_vendido.nombre }}

+

{{ cliente_vendido.direccion }} + {% if cliente_vendido.num_exterior %} Ext: {{ cliente_vendido.num_exterior }}{% endif %} + {% if cliente_vendido.num_interior %} Int: {{ cliente_vendido.num_interior }}{% endif %} +

+

{{ cliente_vendido.colonia }} {% if cliente_vendido.codigo_postal %} CP: {{ + cliente_vendido.codigo_postal }}{% endif %}

+

{{ cliente_vendido.ciudad }}, {{ cliente_vendido.estado }}, {{ cliente_vendido.pais }} +

+

RFC: {{ cliente_vendido.tax_id }} + {% if cliente_vendido.programa and cliente_vendido.programa != 'Ninguno' %} + {{ cliente_vendido.programa }}: {{ cliente_vendido.autorizacion }} + {% endif %} +

+

+ {% if cliente_vendido.prosec %}PROSEC: {{ cliente_vendido.prosec }} {% endif %} + {% if cliente_vendido.reg_emp %}REG EMP: {{ cliente_vendido.reg_emp }} {% endif %} + {% if cliente_vendido.cert %}CERT: {{ cliente_vendido.cert }}{% endif %} +

+
+ +
+

{{ cliente_enviado.header }}

+

{{ cliente_enviado.nombre }}

+

{{ cliente_enviado.direccion }} + {% if cliente_enviado.num_exterior %} Ext: {{ cliente_enviado.num_exterior }}{% endif %} + {% if cliente_enviado.num_interior %} Int: {{ cliente_enviado.num_interior }}{% endif %} +

+

{{ cliente_enviado.colonia }} {% if cliente_enviado.codigo_postal %} CP: {{ + cliente_enviado.codigo_postal }}{% endif %}

+

{{ cliente_enviado.ciudad }}, {{ cliente_enviado.estado }}, {{ cliente_enviado.pais }} +

+

RFC: {{ cliente_enviado.tax_id }} + {% if cliente_enviado.programa and cliente_enviado.programa != 'Ninguno' %} + {{ cliente_enviado.programa }}: {{ cliente_enviado.autorizacion }} + {% endif %} +

+

+ {% if cliente_enviado.prosec %}PROSEC: {{ cliente_enviado.prosec }} {% endif %} + {% if cliente_enviado.reg_emp %}REG EMP: {{ cliente_enviado.reg_emp }} {% endif %} + {% if cliente_enviado.cert %}CERT: {{ cliente_enviado.cert }}{% endif %} +

+
+
+


+
+ + + + + + + + + + + + + + + + + {% for partida in partidas %} + + + + + + + + + + + + + {% endfor %} + + + + + + + + + + + + + + + + + + + + + + +
+

HTS Code / Fracción Americana (temporal) +

+
+

Country

+
+

Comm. Qty

+
+

Unit

+
+

Weight (KGS)

+
+
+

Net

+
+
+

Gross

+
+
+
+

Dutiable Values

+
+
+

Unit

+
+
+

Totals

+
+
+
+

Rate

+
+

Est. Duties

+
+

{{ partida.fraccion }}

+
+

{{ partida.origen or 'MEX' }}

+
+

{{ partida.cantidad_importacion }}

+
+

{{ partida.unidad_medida }}

+
+

{{ partida.peso_neto }}

+
+

{{ partida.peso_bruto }}

+
+

${{ partida.valor_costo_unitario }}

+
+

${{ partida.valor_total }}

+
+

{{ partida.advalorem }}

+
+

${{ partida.valor_estimado }}

+
+

+ TOTALS +

+
+

{{ totales.cantidad_total }}

+
+

+ {% if totales.bultos_total != 0 %}{{ totales.bultos_total }}{% endif %} + {{ totales.clave_bultos or '' }} +

+
+

{{ totales.peso_neto_total }}

+
+

{{ totales.peso_bruto_total }}

+
+ + +

${{ totales.valor_total_total }}

+
+ + +

${{ totales.valor_estimado_total }}

+
+

{{ factura.observaciones }}

+
+

+

{{ factura.representante_legal }}

+

{{ factura.nombre_empresa }}

+


+
+


+

Normal Por Parte

+

Declaro bajo protesta de decir verdad que la información contenida en + este documento es verdadera y me hago responsable de comprobar lo aquí declarado.

+
+ + + \ No newline at end of file diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py index f8f37a6a..200a3942 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/mex/service.py @@ -244,6 +244,10 @@ class FacturaImportacionMexService: desc_final = part_master.description_spanish or part_master.description_english or "Sin Desc." num_parte_final = part_master.part_number fraccion_raw = part_master.fraction if part_master.fraction else "" + + # Fetch Origin from Master Catalog (FaPart) + if part_master.fa_data and part_master.fa_data.origin_country: + origen_final = part_master.fa_data.origin_country fraccion_limpia = fraccion_raw.replace(".", "").strip() @@ -280,16 +284,27 @@ class FacturaImportacionMexService: # 1. Try Specific Currency Columns First if is_mxn: - v_unitario = fin.unit_cost_commercial_mxn or 0.0 - v_total = fin.value_commercial_mxn or 0.0 + v_unitario = float(fin.unit_cost_commercial_mxn or 0.0) + v_total = float(fin.value_commercial_mxn or 0.0) else: - v_unitario = fin.unit_cost_commercial_usd or 0.0 - v_total = fin.value_commercial_usd or 0.0 + v_unitario = float(fin.unit_cost_commercial_usd or 0.0) + v_total = float(fin.value_commercial_usd or 0.0) - # 2. Fallback to Generic if Specific is 0 - if v_unitario == 0 or v_total == 0: - v_unitario = fin.commercial_unit_cost or 0.0 - v_total = fin.total_commercial_value or 0.0 + # 2. Fallback to Generic independently if Specific is 0 + if not v_unitario: + v_unitario = float(fin.commercial_unit_cost or 0.0) + + if not v_total: + v_total = float(fin.total_commercial_value or 0.0) + + # 3. Calculate from Quantity if still missing + cantidad = float(qty.quantity) if (qty and qty.quantity) else 0.0 + + if cantidad > 0: + if v_unitario > 0 and v_total == 0: + v_total = v_unitario * cantidad + elif v_total > 0 and v_unitario == 0: + v_unitario = v_total / cantidad partidas_list.append(PartidaSchema( numero_parte=num_parte_final, @@ -301,7 +316,7 @@ class FacturaImportacionMexService: cantidad_importacion=self.formatear_numero(qty.quantity if qty else 0), unidad_medida=qty.weight_unit if qty else "PZA", cantidad_bultos=int(qty.package_quantity) if qty and qty.package_quantity else 0, - clave_bultos=qty.package_key if qty else "", + clave_bultos=(qty.package_key or "") if qty else "", peso_neto=self.formatear_numero(qty.net_weight if qty else 0), peso_bruto=self.formatear_numero(qty.gross_weight if qty else 0), valor_costo_unitario=self.formatear_numero(v_unitario), diff --git a/backend/api/v1/modules/a76/reports/importacion/facturas/task.py b/backend/api/v1/modules/a76/reports/importacion/facturas/task.py index 7b7e9783..6cdf1342 100644 --- a/backend/api/v1/modules/a76/reports/importacion/facturas/task.py +++ b/backend/api/v1/modules/a76/reports/importacion/facturas/task.py @@ -10,9 +10,7 @@ logger = logging.getLogger(__name__) @celery_app.task(name="generar_pdf_factura_async", bind=True) def generar_pdf_factura_async(self, invoice_id: int, company_id: int): - """ - Esta tarea la ejecuta el Worker. No usa FastAPI, usa directamente SQLAlchemy. - """ + # 1. Abrimos conexión a la DB db = CoreSessionLocal() try: diff --git a/backend/api/v1/modules/a76/router.py b/backend/api/v1/modules/a76/router.py index 4faae183..24220d6d 100644 --- a/backend/api/v1/modules/a76/router.py +++ b/backend/api/v1/modules/a76/router.py @@ -50,6 +50,7 @@ from api.v1.modules.public.reference_data.material_types.routes import router as # --- NUEVO IMPORT PARA REPORTES DE FACTURAS --- from .reports.importacion.facturas.routes import router as invoices_reports_router +from .reports.importacion.consolidados.routes import router as consolidated_reports_router # Router principal @@ -123,4 +124,10 @@ router.include_router( invoices_reports_router, prefix="/a76/reports/importacion/facturas", tags=["a76 / reports"] +) + +router.include_router( + consolidated_reports_router, + prefix="/a76/reports/importacion/consolidados", + tags=["a76 / reports"] ) \ No newline at end of file diff --git a/backend/core/celery_app.py b/backend/core/celery_app.py index 8b95558f..c118db31 100644 --- a/backend/core/celery_app.py +++ b/backend/core/celery_app.py @@ -8,7 +8,10 @@ celery_app = Celery( "anexo76_tasks", broker=valkey_url, backend=valkey_url, - include=["api.v1.modules.a76.reports.importacion.facturas.task"] # Ruta al módulo donde están las tareas + include=[ + "api.v1.modules.a76.reports.importacion.facturas.task", + "api.v1.modules.a76.reports.importacion.consolidados.task" + ] # Ruta al módulo donde están las tareas ) # Configuraciones adicionales diff --git a/debug_values.py b/debug_values.py new file mode 100644 index 00000000..337140ee --- /dev/null +++ b/debug_values.py @@ -0,0 +1,76 @@ +from sqlalchemy import create_engine, text +from sqlalchemy.orm import sessionmaker +from api.v1.modules.a76.items.line_items.models import LineItem +from api.v1.modules.a76.items.line_quantities.models import LineQuantity +from api.v1.modules.a76.items.line_financials.models import LineFinancial +from api.v1.modules.a76.parts.models import Part +from api.v1.modules.a76.invoices.models import InvoiceHeader +from api.v1.modules.a76.pedmientos.models import Pedimentos + +# Setup DB (Adjust connection string if needed, checking environment assumption) +# Assuming local connection string or deriving from environment/config +# For this environment, I'll attempt a standard connection or reuse existing if possible. +# Since I cannot easily import 'db' from main app without setup, I will rely on standard raw SQL or simple ORM setup if I can import 'Session'. +# Using the imports available in the user's file. + +import sys +sys.path.append('/home/josmar/dev/anexo76/backend') + +from core.database import CoreSessionLocal + +# Manual Session creation +db = CoreSessionLocal() + +try: + # 1. Find the lines matching the description (Qty 1500 + HTS) + # The user said HTS: 2710190650 + # Qty: 1500 + + print("--- SEARCHING FOR LINES ---") + + # We look for lines with quantity 1500 first + candidates = db.query(LineItem).join(LineQuantity).filter( + LineQuantity.quantity == 1500 + ).all() + + found = False + for line in candidates: + part = db.query(Part).filter(Part.id == line.part_number).first() + fin = db.query(LineFinancial).filter(LineFinancial.item_line_id == line.id).first() + inv = db.query(InvoiceHeader).filter(InvoiceHeader.id == line.item.invoice_id).first() if line.item else None + + us_frac = part.us_fraction if part else "N/A" + + # Check fraction match (loose match) + if "2710190650" in us_frac.replace(".","").replace(" ",""): + found = True + print(f"\nMATCH FOUND: Line ID {line.id} - Invoice {inv.invoice_number if inv else 'N/A'}") + print(f"HTS: {us_frac}") + print(f"Qty: {1500}") + print(f"Inv Currency: {inv.financials.currency} / {inv.financials.currency_type} Rate: {inv.financials.exchange_rate}") + + print("\nFINANCIALS:") + if fin: + print(f" value_usd: {fin.value_usd}") + print(f" value_mxn: {fin.value_mxn}") + print(f" value_commercial_usd: {fin.value_commercial_usd}") + print(f" value_commercial_mxn: {fin.value_commercial_mxn}") + print(f" unit_cost_usd: {fin.unit_cost_usd}") + print(f" unit_cost_commercial_usd: {fin.unit_cost_commercial_usd}") + print(f" unit_cost_mxn: {fin.unit_cost_mxn}") + + # Check calculation hypothesis + val_usd = float(fin.value_usd or 0) + val_mxn = float(fin.value_mxn or 0) + rate = float(inv.financials.exchange_rate or 1) + + print(f"\n If using ValueMXN/Rate: {val_mxn} / {rate} = {val_mxn/rate}") + print(f" If using Max(MXN, USD): {max(val_mxn, val_usd)}") + else: + print(" No Financials found.") + + if not found: + print("No matching line (1500 qty, HTS 2710190650) found.") + +finally: + db.close() diff --git a/frontend/src/lib/api/dashboard/a76/reports/reports-consolidated.ts b/frontend/src/lib/api/dashboard/a76/reports/reports-consolidated.ts new file mode 100644 index 00000000..9e6c171a --- /dev/null +++ b/frontend/src/lib/api/dashboard/a76/reports/reports-consolidated.ts @@ -0,0 +1,35 @@ + +const BASE_URL = import.meta.env.VITE_API_URL || ''; + +export const consolidatedReportsApi = { + + triggerPdfGeneration: async (invoiceId: number, companyId: number) => { + const params = new URLSearchParams({ company_id: companyId.toString() }); + const endpoint = `${BASE_URL}/v1/a76/reports/importacion/consolidados/${invoiceId}/download-async?${params.toString()}`; + + const token = localStorage.getItem('access_token'); + const response = await fetch(endpoint, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + } + }); + + if (!response.ok) throw new Error('Error al iniciar la generación del consolidado'); + return await response.json(); + }, + + getTaskStatus: async (taskId: string) => { + const endpoint = `${BASE_URL}/v1/a76/reports/importacion/consolidados/tasks/${taskId}`; + + const token = localStorage.getItem('access_token'); + const response = await fetch(endpoint, { + method: 'GET', + headers: { 'Authorization': `Bearer ${token}` } + }); + + if (!response.ok) throw new Error('Error al consultar estado del consolidado'); + return await response.json(); + } +}; diff --git a/frontend/src/lib/components/dashboard/goods/modales/us-fraction-selector-dialog.svelte b/frontend/src/lib/components/dashboard/goods/modales/us-fraction-selector-dialog.svelte new file mode 100644 index 00000000..1f514190 --- /dev/null +++ b/frontend/src/lib/components/dashboard/goods/modales/us-fraction-selector-dialog.svelte @@ -0,0 +1,146 @@ + + + + + + Seleccionar Fracción Americana + + Seleccione la fracción arancelaria (HTS) del catálogo. + + + +
+ + +
+ +
+ {#if loading} +
+ +

Cargando catálogo...

+
+ {:else if filteredItems.length === 0} +
+

No se encontraron fracciones.

+
+ {:else} + + + + Código (HTS) + Descripción + + + + {#each filteredItems as item} + handleSelect(item)} + > + +
+ + + {item.code} + +
+
+ + {item.description || '-'} + +
+ {/each} +
+
+ {/if} +
+ + +
+ {filteredItems.length} registros encontrados +
+ +
+
+
diff --git a/frontend/src/lib/components/dashboard/goods/parts/partForm.svelte b/frontend/src/lib/components/dashboard/goods/parts/partForm.svelte index c82acb6d..5991f15e 100644 --- a/frontend/src/lib/components/dashboard/goods/parts/partForm.svelte +++ b/frontend/src/lib/components/dashboard/goods/parts/partForm.svelte @@ -36,6 +36,7 @@ import CurrencySelectorDialog from '$lib/components/dashboard/goods/modales/currency-selector-dialog.svelte'; import CountrySelectorDialog from '$lib/components/dashboard/goods/modales/country-selector-dialog.svelte'; import FractionSelectorDialog from '$lib/components/dashboard/goods/modales/fraction-selector-dialog.svelte'; + import USFractionSelectorDialog from '$lib/components/dashboard/goods/modales/us-fraction-selector-dialog.svelte'; // --- PROPS --- let { partId = null, formType = 'inv' }: { partId?: number | null, formType?: 'inv' | 'fa' } = $props(); @@ -57,6 +58,7 @@ let showCurrencyModal = $state(false); let showCountryModal = $state(false); let showFractionModal = $state(false); + let showUSFractionModal = $state(false); // Descripciones Visuales let selectedClientName = $state(""); @@ -222,6 +224,7 @@ selectedCountryName = country.description_es; } function handleFractionSelect(item: any) { formData.fraction = item.fraction; } + function handleUSFractionSelect(item: any) { formData.us_fraction = item.code; } // --- SUBMIT --- async function handleSubmit() { @@ -436,7 +439,10 @@
- +
+ showUSFractionModal = true}/> + +
@@ -691,7 +697,10 @@
- +
+ showUSFractionModal = true}/> + +
@@ -885,6 +894,7 @@ +