feature/csv-templates
This commit is contained in:
@@ -315,6 +315,35 @@ export const api = {
|
||||
|
||||
delete: <T = any>(endpoint: string, options: RequestInit = {}) => fetchApi<T>(endpoint, { method: 'DELETE', ...options }),
|
||||
|
||||
/**
|
||||
* Download CSV template by template_id (generated from code, no static file).
|
||||
* Returns blob and suggested filename for the browser download.
|
||||
*/
|
||||
async getCsvTemplateDownload(
|
||||
templateId: string
|
||||
): Promise<{ blob: Blob; filename: string }> {
|
||||
const token = getToken();
|
||||
const headers: Record<string, string> = {};
|
||||
if (token) headers['Authorization'] = `Bearer ${token}`;
|
||||
const response = await fetch(`${API_BASE_URL}/v1/a76/csv-templates/${templateId}`, {
|
||||
method: 'GET',
|
||||
headers,
|
||||
credentials: 'include'
|
||||
});
|
||||
if (!response.ok) {
|
||||
const msg = response.status === 404 ? 'Plantilla no encontrada' : `Error ${response.status}`;
|
||||
throw new Error(msg);
|
||||
}
|
||||
const blob = await response.blob();
|
||||
let filename = `plantilla_${templateId}.csv`;
|
||||
const disposition = response.headers.get('Content-Disposition');
|
||||
if (disposition) {
|
||||
const match = /filename="?([^";\n]+)"?/.exec(disposition);
|
||||
if (match) filename = match[1].trim();
|
||||
}
|
||||
return { blob, filename };
|
||||
},
|
||||
|
||||
// Endpoints específicos
|
||||
auth: {
|
||||
login: (credentials: { username: string; password: string; tenant_slug: string }) =>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import { UploadCloud, Lock } from 'lucide-svelte';
|
||||
import { cn } from '$lib/utils';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import { api } from '$lib/api';
|
||||
|
||||
let {
|
||||
items,
|
||||
@@ -88,7 +89,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
function handleContextMenu(e: MouseEvent, item: CsvUploadItem) {
|
||||
async function handleContextMenu(e: MouseEvent, item: CsvUploadItem) {
|
||||
if (item.disabled) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
@@ -96,16 +97,23 @@
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
if (!item.templateUrl) return;
|
||||
if (!item.templateId) return;
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = item.templateUrl;
|
||||
link.download = item.templateUrl.split('/').pop() || 'plantilla.xls';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
|
||||
toast.info(`Descargando plantilla para ${item.title}...`);
|
||||
try {
|
||||
toast.info(`Descargando plantilla para ${item.title}...`);
|
||||
const { blob, filename } = await api.getCsvTemplateDownload(item.templateId);
|
||||
const url = URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = filename;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(url);
|
||||
toast.success(`Plantilla descargada: ${filename}`);
|
||||
} catch (err) {
|
||||
toast.error(err instanceof Error ? err.message : 'Error al descargar la plantilla');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -28,7 +28,8 @@ export interface CsvUploadItem {
|
||||
group?: string; // For grouping within a tab
|
||||
modelTarget?: string; // The backend model this maps to
|
||||
description?: string;
|
||||
templateUrl?: string; // Path to the template file in static/
|
||||
/** Backend template id for CSV download (e.g. customs_brokers, part_numbers). No physical file. */
|
||||
templateId?: string;
|
||||
disabled?: boolean; // New property to mark items as "Coming Soon"
|
||||
}
|
||||
|
||||
@@ -131,49 +132,49 @@ export const catalogosConfig: CsvUploadItem[] = [
|
||||
title: 'Agentes Aduanales',
|
||||
icon: User,
|
||||
modelTarget: 'CustomsBroker',
|
||||
templateUrl: '/csv/EstructuraCatAgenteAduanal.xls'
|
||||
templateId: 'customs_brokers'
|
||||
},
|
||||
{
|
||||
id: 'clients_providers',
|
||||
title: 'Clientes y Proveedores',
|
||||
icon: Users,
|
||||
modelTarget: 'ClientProvider',
|
||||
templateUrl: '/csv/EstructuraCatClienteProv.xls'
|
||||
templateId: 'clients_providers'
|
||||
},
|
||||
{
|
||||
id: 'exchange_rates',
|
||||
title: 'Tipo de Cambios',
|
||||
icon: DollarSign,
|
||||
modelTarget: 'ExchangeRate',
|
||||
templateUrl: '/csv/EstructuraCatTiposCambio.xls'
|
||||
templateId: 'exchange_rates'
|
||||
},
|
||||
{
|
||||
id: 'american_fractions',
|
||||
title: 'Fracc. Ame.',
|
||||
icon: Globe,
|
||||
modelTarget: 'AmericanFraction',
|
||||
templateUrl: '/csv/EstructuraCatFraccAme.xls'
|
||||
templateId: 'american_fractions'
|
||||
},
|
||||
{
|
||||
id: 'material_classes',
|
||||
title: 'Clases de Materiales',
|
||||
icon: Package,
|
||||
modelTarget: 'MaterialClass',
|
||||
templateUrl: '/csv/EstructuraCatClasesAF.xls'
|
||||
templateId: 'material_classes'
|
||||
},
|
||||
{
|
||||
id: 'part_numbers',
|
||||
title: 'Números de parte',
|
||||
icon: Hash,
|
||||
modelTarget: 'Part',
|
||||
templateUrl: '/csv/EstructuraCatPartesAF.xls',
|
||||
templateId: 'part_numbers',
|
||||
},
|
||||
{
|
||||
id: 'boms',
|
||||
title: 'BOMs',
|
||||
icon: Briefcase,
|
||||
modelTarget: 'Bom',
|
||||
templateUrl: '/csv/EstructuraBOMS.xlsx',
|
||||
templateId: 'boms',
|
||||
},
|
||||
{
|
||||
id: 'items',
|
||||
@@ -181,7 +182,7 @@ export const catalogosConfig: CsvUploadItem[] = [
|
||||
icon: FileText,
|
||||
group: 'Permisos',
|
||||
modelTarget: 'ItemPermission',
|
||||
templateUrl: '/csv/EstructuraCatPartesAF.xls'
|
||||
templateId: 'part_numbers'
|
||||
},
|
||||
{
|
||||
id: 'headers',
|
||||
@@ -203,7 +204,7 @@ export const catalogosConfig: CsvUploadItem[] = [
|
||||
title: 'Pedimentos',
|
||||
icon: FileDigit,
|
||||
modelTarget: 'Pedimento',
|
||||
templateUrl: '/csv/EstructuraCatPedimentos.xls'
|
||||
templateId: 'pedimentos'
|
||||
},
|
||||
];
|
||||
|
||||
@@ -213,28 +214,28 @@ export const transportesConfig: CsvUploadItem[] = [
|
||||
title: 'Transportistas',
|
||||
icon: Ship,
|
||||
modelTarget: 'Transporter',
|
||||
templateUrl: '/csv/EstructuraCatTransportistas.xlsx',
|
||||
// No templateId: backend transporters/imports not implemented yet
|
||||
},
|
||||
{
|
||||
id: 'transports',
|
||||
title: 'Transportes',
|
||||
icon: Truck,
|
||||
modelTarget: 'Transport',
|
||||
templateUrl: '/csv/EstructuraCatTransportes.xls'
|
||||
templateId: 'transports'
|
||||
},
|
||||
{
|
||||
id: 'drivers',
|
||||
title: 'Conductores',
|
||||
icon: User,
|
||||
modelTarget: 'Driver',
|
||||
templateUrl: '/csv/EstructuraCatConductor.xls'
|
||||
templateId: 'drivers'
|
||||
},
|
||||
{
|
||||
id: 'trailers',
|
||||
title: 'Trailers y Cajas',
|
||||
icon: Container,
|
||||
modelTarget: 'Trailer',
|
||||
templateUrl: '/csv/EstructuraCatTrailers.xls'
|
||||
templateId: 'trailers'
|
||||
},
|
||||
];
|
||||
|
||||
@@ -246,7 +247,7 @@ export const importacionConfig: CsvUploadItem[] = [
|
||||
icon: FileText,
|
||||
group: 'Impo. Temp.',
|
||||
modelTarget: 'invoice_header',
|
||||
templateUrl: '/csv/EstructuraEncFacImpoTemp.xls'
|
||||
templateId: 'imp_temp_header'
|
||||
},
|
||||
{
|
||||
id: 'imp_temp_details',
|
||||
@@ -254,7 +255,7 @@ export const importacionConfig: CsvUploadItem[] = [
|
||||
icon: Package,
|
||||
group: 'Impo. Temp.',
|
||||
modelTarget: 'invoice_details',
|
||||
templateUrl: '/csv/EstructuraParFacImpoTempAF.xls'
|
||||
templateId: 'imp_temp_details'
|
||||
},
|
||||
{
|
||||
id: 'imp_temp_series',
|
||||
@@ -271,7 +272,7 @@ export const importacionConfig: CsvUploadItem[] = [
|
||||
icon: FileText,
|
||||
group: 'Impo. Def.',
|
||||
modelTarget: 'invoice_header',
|
||||
templateUrl: '/csv/EstructuraEncFacImpoDef.xls'
|
||||
templateId: 'imp_def_header'
|
||||
},
|
||||
{
|
||||
id: 'imp_def_details',
|
||||
@@ -279,7 +280,7 @@ export const importacionConfig: CsvUploadItem[] = [
|
||||
icon: Package,
|
||||
group: 'Impo. Def.',
|
||||
modelTarget: 'invoice_details',
|
||||
templateUrl: '/csv/EstructuraParFacImpoDefAF.xls'
|
||||
templateId: 'imp_def_details'
|
||||
},
|
||||
{
|
||||
id: 'imp_def_series',
|
||||
@@ -324,7 +325,7 @@ export const exportacionConfig: CsvUploadItem[] = [
|
||||
icon: FileText,
|
||||
group: 'Expo. Def./Cam. Reg.',
|
||||
modelTarget: 'invoice_header',
|
||||
templateUrl: '/csv/EstructuraEncFacExpoCamReg.xls'
|
||||
templateId: 'exp_def_header'
|
||||
},
|
||||
{
|
||||
id: 'exp_def_details',
|
||||
@@ -332,7 +333,7 @@ export const exportacionConfig: CsvUploadItem[] = [
|
||||
icon: Package,
|
||||
group: 'Expo. Def./Cam. Reg.',
|
||||
modelTarget: 'invoice_details',
|
||||
templateUrl: '/csv/EstructuraParExpoCamReg.xls'
|
||||
templateId: 'exp_def_details'
|
||||
},
|
||||
{
|
||||
id: 'exp_def_series',
|
||||
|
||||
Reference in New Issue
Block a user