feature/frontend-integration
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
<script lang="ts">
|
||||
import { Label } from '$lib/components/ui/label/index.js';
|
||||
import { Input } from '$lib/components/ui/input/index.js';
|
||||
import { Checkbox } from '$lib/components/ui/checkbox/index.js';
|
||||
import * as RadioGroup from '$lib/components/ui/radio-group/index.js';
|
||||
import { Settings2 } from 'lucide-svelte';
|
||||
import { tabSettings } from '$lib/config/csv-upload';
|
||||
|
||||
let {
|
||||
activeTab,
|
||||
settings = $bindable()
|
||||
}: {
|
||||
activeTab: string;
|
||||
settings: Record<string, any>;
|
||||
} = $props();
|
||||
|
||||
let currentFields = $derived(tabSettings[activeTab] || []);
|
||||
|
||||
// Determine grid columns based on number of fields
|
||||
let gridClass = $derived(
|
||||
currentFields.length > 4
|
||||
? 'grid-cols-4'
|
||||
: currentFields.length > 2
|
||||
? 'grid-cols-3'
|
||||
: currentFields.length > 1
|
||||
? 'grid-cols-2'
|
||||
: 'grid-cols-1'
|
||||
);
|
||||
</script>
|
||||
|
||||
<!--
|
||||
No positioning here. Parent layout controls placement.
|
||||
Just styling the "Island".
|
||||
-->
|
||||
<div
|
||||
class="border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 p-4 rounded-xl shadow-2xl mx-4 mb-4"
|
||||
>
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex items-center gap-2 text-muted-foreground border-b pb-2">
|
||||
<Settings2 class="h-4 w-4" />
|
||||
<span class="text-xs font-semibold uppercase tracking-wider">Configuración: {activeTab}</span>
|
||||
</div>
|
||||
|
||||
{#if currentFields.length > 0}
|
||||
<div class="grid {gridClass} gap-6">
|
||||
{#each currentFields as field}
|
||||
<div class="flex flex-col gap-2">
|
||||
{#if field.type !== 'boolean'}
|
||||
<Label class="text-xs font-medium text-muted-foreground uppercase"
|
||||
>{field.label}</Label
|
||||
>
|
||||
{/if}
|
||||
|
||||
{#if field.type === 'text'}
|
||||
<Input type="text" bind:value={settings[field.name]} class="h-8" />
|
||||
{:else if field.type === 'boolean'}
|
||||
<div class="flex items-center space-x-2 h-8">
|
||||
<Checkbox id={field.name} bind:checked={settings[field.name]} />
|
||||
<Label
|
||||
for={field.name}
|
||||
class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 cursor-pointer"
|
||||
>{field.label}</Label
|
||||
>
|
||||
</div>
|
||||
{:else if field.type === 'select' && field.options}
|
||||
<select
|
||||
class="flex h-8 w-full rounded-md border border-input bg-background px-3 py-1 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
||||
bind:value={settings[field.name]}
|
||||
>
|
||||
{#each field.options as opt}
|
||||
<option value={opt.value}>{opt.label}</option>
|
||||
{/each}
|
||||
</select>
|
||||
{:else if field.type === 'radio' && field.options}
|
||||
<RadioGroup.Root
|
||||
bind:value={settings[field.name]}
|
||||
class="flex gap-4 h-8 items-center"
|
||||
>
|
||||
{#each field.options as opt}
|
||||
<div class="flex items-center space-x-2">
|
||||
<RadioGroup.Item value={opt.value} id={`${field.name}-${opt.value}`} />
|
||||
<Label for={`${field.name}-${opt.value}`}>{opt.label}</Label>
|
||||
</div>
|
||||
{/each}
|
||||
</RadioGroup.Root>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex items-center justify-center h-8 text-sm text-muted-foreground italic">
|
||||
No hay configuraciones específicas para este módulo.
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,123 @@
|
||||
<script lang="ts">
|
||||
import * as Dialog from '$lib/components/ui/dialog/index.js';
|
||||
import { Button } from '$lib/components/ui/button/index.js';
|
||||
import { Label } from '$lib/components/ui/label/index.js';
|
||||
import { Upload, FileType } from 'lucide-svelte';
|
||||
import type { CsvUploadItem } from '$lib/config/csv-upload';
|
||||
|
||||
let {
|
||||
open = $bindable(false),
|
||||
config,
|
||||
currentSettings // Read-only prop passed from page
|
||||
}: {
|
||||
open: boolean;
|
||||
config: CsvUploadItem;
|
||||
currentSettings: Record<string, any>;
|
||||
} = $props();
|
||||
|
||||
// State
|
||||
let file: File | null = $state(null);
|
||||
let isProcessing = $state(false);
|
||||
|
||||
function handleFileChange(e: Event) {
|
||||
const target = e.target as HTMLInputElement;
|
||||
if (target.files && target.files.length > 0) {
|
||||
file = target.files[0];
|
||||
}
|
||||
}
|
||||
|
||||
function handleProcess() {
|
||||
isProcessing = true;
|
||||
console.log('Processing Upload Request:', {
|
||||
entityConfig: config,
|
||||
file: file,
|
||||
activeSettings: currentSettings // Log the global/tab settings being applied
|
||||
});
|
||||
|
||||
// Mock processing time
|
||||
setTimeout(() => {
|
||||
isProcessing = false;
|
||||
open = false;
|
||||
alert(
|
||||
`Procesando archivo para: ${config.title}\nConfiguración aplicada: ${JSON.stringify(currentSettings, null, 2)}`
|
||||
);
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// Reset file state when config changes or modal opens
|
||||
$effect(() => {
|
||||
if (config) {
|
||||
file = null;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<Dialog.Root bind:open>
|
||||
<Dialog.Content class="sm:max-w-[500px]">
|
||||
<Dialog.Header>
|
||||
<Dialog.Title class="flex items-center gap-2">
|
||||
{#if config.icon}
|
||||
<config.icon class="h-5 w-5" />
|
||||
{/if}
|
||||
Importar {config.title}
|
||||
</Dialog.Title>
|
||||
<Dialog.Description>
|
||||
Selecciona tu archivo CSV para procesar.
|
||||
<br />
|
||||
<span class="text-xs text-muted-foreground mt-1 block">
|
||||
La configuración activa del pie de página se aplicará a esta carga.
|
||||
</span>
|
||||
</Dialog.Description>
|
||||
</Dialog.Header>
|
||||
|
||||
<div class="grid gap-6 py-4">
|
||||
<!-- Stage 1: File Selection -->
|
||||
<div class="flex flex-col gap-3">
|
||||
<div
|
||||
class="border-2 border-dashed rounded-lg p-8 flex flex-col items-center justify-center gap-2 hover:bg-muted/50 transition-colors cursor-pointer relative"
|
||||
>
|
||||
<input
|
||||
type="file"
|
||||
accept=".csv,.txt"
|
||||
class="absolute inset-0 opacity-0 cursor-pointer"
|
||||
onchange={handleFileChange}
|
||||
/>
|
||||
{#if file}
|
||||
<FileType class="h-12 w-12 text-primary" />
|
||||
<div class="text-center">
|
||||
<span class="font-medium text-sm block">{file.name}</span>
|
||||
<span class="text-xs text-muted-foreground">{(file.size / 1024).toFixed(2)} KB</span>
|
||||
</div>
|
||||
{:else}
|
||||
<Upload class="h-10 w-10 text-muted-foreground" />
|
||||
<span class="font-medium text-sm">Arrastra tu archivo aquí o haz clic</span>
|
||||
<span class="text-xs text-muted-foreground">Soporta CSV, TXT</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Preview of Current Settings (Read Only) -->
|
||||
{#if Object.keys(currentSettings).length > 0}
|
||||
<div class="bg-muted/40 p-3 rounded text-xs text-muted-foreground">
|
||||
<strong>Configuración Activa:</strong>
|
||||
<ul class="list-disc pl-4 mt-1 space-y-0.5">
|
||||
{#each Object.entries(currentSettings) as [key, value]}
|
||||
<li>{key}: <span class="font-mono">{value}</span></li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<Dialog.Footer>
|
||||
<Button variant="outline" onclick={() => (open = false)}>Cancelar</Button>
|
||||
<Button onclick={handleProcess} disabled={!file || isProcessing}>
|
||||
{#if isProcessing}
|
||||
Procesando...
|
||||
{:else}
|
||||
Procesar
|
||||
{/if}
|
||||
</Button>
|
||||
</Dialog.Footer>
|
||||
</Dialog.Content>
|
||||
</Dialog.Root>
|
||||
@@ -0,0 +1,264 @@
|
||||
<script lang="ts">
|
||||
import * as Card from '$lib/components/ui/card/index.js';
|
||||
import type { CsvUploadItem } from '$lib/config/csv-upload';
|
||||
import { UploadCloud, Lock } from 'lucide-svelte';
|
||||
import { cn } from '$lib/utils';
|
||||
import { toast } from 'svelte-sonner';
|
||||
|
||||
let {
|
||||
items,
|
||||
onUpload
|
||||
}: {
|
||||
items: CsvUploadItem[];
|
||||
onUpload: (file: File, config: CsvUploadItem) => void;
|
||||
} = $props();
|
||||
|
||||
let dragOverId = $state<string | null>(null);
|
||||
|
||||
// Group items
|
||||
let groupedItems = $derived.by(() => {
|
||||
const groups: Record<string, CsvUploadItem[]> = {};
|
||||
const ungrouped: CsvUploadItem[] = [];
|
||||
|
||||
items.forEach((item) => {
|
||||
if (item.group) {
|
||||
if (!groups[item.group]) groups[item.group] = [];
|
||||
groups[item.group].push(item);
|
||||
} else {
|
||||
ungrouped.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
return { groups, ungrouped };
|
||||
});
|
||||
|
||||
function handleDragEnter(e: DragEvent, id: string, disabled?: boolean) {
|
||||
if (disabled) return;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
dragOverId = id;
|
||||
}
|
||||
|
||||
function handleDragLeave(e: DragEvent) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
dragOverId = null;
|
||||
}
|
||||
|
||||
function handleDragOver(e: DragEvent, disabled?: boolean) {
|
||||
if (disabled) return;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
dragOverId = null;
|
||||
}
|
||||
|
||||
function validateAndUpload(file: File, item: CsvUploadItem) {
|
||||
const isValidExtension = file.name.toLowerCase().endsWith('.csv');
|
||||
|
||||
if (!isValidExtension) {
|
||||
toast.error('Formato inválido. Solo se permiten archivos .csv');
|
||||
return;
|
||||
}
|
||||
|
||||
onUpload(file, item);
|
||||
}
|
||||
|
||||
function handleDrop(e: DragEvent, item: CsvUploadItem) {
|
||||
if (item.disabled) return;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
dragOverId = null;
|
||||
|
||||
if (e.dataTransfer && e.dataTransfer.files.length > 0) {
|
||||
validateAndUpload(e.dataTransfer.files[0], item);
|
||||
}
|
||||
}
|
||||
|
||||
function handleClick(id: string, disabled?: boolean) {
|
||||
if (disabled) return;
|
||||
const input = document.getElementById(`file-input-${id}`) as HTMLInputElement;
|
||||
if (input) input.click();
|
||||
}
|
||||
|
||||
function handleFileChange(e: Event, item: CsvUploadItem) {
|
||||
const target = e.target as HTMLInputElement;
|
||||
if (target.files && target.files.length > 0) {
|
||||
validateAndUpload(target.files[0], item);
|
||||
target.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
function handleContextMenu(e: MouseEvent, item: CsvUploadItem) {
|
||||
if (item.disabled) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
if (!item.templateUrl) return;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
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}...`);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col gap-6 select-none">
|
||||
{#if groupedItems.ungrouped.length > 0}
|
||||
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
||||
{#each groupedItems.ungrouped as item}
|
||||
<div
|
||||
class={cn(
|
||||
'relative group transition-all duration-200 ease-in-out transform',
|
||||
item.disabled ? 'opacity-60 cursor-not-allowed' : 'cursor-pointer',
|
||||
!item.disabled && dragOverId === item.id ? 'scale-105' : ''
|
||||
)}
|
||||
ondragenter={(e) => handleDragEnter(e, item.id, item.disabled)}
|
||||
ondragleave={handleDragLeave}
|
||||
ondragover={(e) => handleDragOver(e, item.disabled)}
|
||||
ondrop={(e) => handleDrop(e, item)}
|
||||
oncontextmenu={(e) => handleContextMenu(e, item)}
|
||||
roles="button"
|
||||
tabindex={item.disabled ? -1 : 0}
|
||||
onclick={() => handleClick(item.id, item.disabled)}
|
||||
onkeydown={(e) => !item.disabled && e.key === 'Enter' && handleClick(item.id)}
|
||||
>
|
||||
<input
|
||||
type="file"
|
||||
id={`file-input-${item.id}`}
|
||||
class="hidden"
|
||||
accept=".csv"
|
||||
onchange={(e) => handleFileChange(e, item)}
|
||||
disabled={item.disabled}
|
||||
/>
|
||||
|
||||
<Card.Root
|
||||
class={cn(
|
||||
'h-full border-2 border-dashed border-transparent transition-colors w-full text-left relative overflow-hidden',
|
||||
!item.disabled && 'hover:border-primary/50 hover:shadow-md',
|
||||
!item.disabled && dragOverId === item.id
|
||||
? 'border-primary bg-primary/5 shadow-xl ring-2 ring-primary ring-offset-2'
|
||||
: ''
|
||||
)}
|
||||
>
|
||||
{#if item.disabled}
|
||||
<div class="absolute inset-0 bg-background/50 z-20 flex items-center justify-center">
|
||||
<span
|
||||
class="bg-muted px-2 py-1 rounded text-xs font-semibold text-muted-foreground border flex items-center gap-1"
|
||||
>
|
||||
<Lock class="h-3 w-3" /> Próximamente
|
||||
</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<Card.Content
|
||||
class="flex flex-col items-center justify-center p-6 gap-3 text-center h-full relative z-10"
|
||||
>
|
||||
{#if !item.disabled && dragOverId === item.id}
|
||||
<div class="animate-bounce">
|
||||
<UploadCloud class="h-8 w-8 text-primary" />
|
||||
</div>
|
||||
<span class="text-sm font-semibold text-primary">¡Suelta el archivo!</span>
|
||||
{:else}
|
||||
<div
|
||||
class={cn(
|
||||
'p-3 bg-muted rounded-full transition-transform duration-200',
|
||||
!item.disabled && 'group-hover:scale-110'
|
||||
)}
|
||||
>
|
||||
<item.icon class="h-6 w-6 text-primary" />
|
||||
</div>
|
||||
<div class="font-medium text-sm text-balance">{item.title}</div>
|
||||
{/if}
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#each Object.entries(groupedItems.groups) as [groupName, groupItems]}
|
||||
<div class="flex flex-col gap-3">
|
||||
<h3 class="text-sm font-semibold text-muted-foreground uppercase tracking-wider pl-1">
|
||||
{groupName}
|
||||
</h3>
|
||||
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
||||
{#each groupItems as item}
|
||||
<div
|
||||
class={cn(
|
||||
'relative group transition-all duration-200 ease-in-out transform',
|
||||
item.disabled ? 'opacity-60 cursor-not-allowed' : 'cursor-pointer',
|
||||
!item.disabled && dragOverId === item.id ? 'scale-105' : ''
|
||||
)}
|
||||
ondragenter={(e) => handleDragEnter(e, item.id, item.disabled)}
|
||||
ondragleave={handleDragLeave}
|
||||
ondragover={(e) => handleDragOver(e, item.disabled)}
|
||||
ondrop={(e) => handleDrop(e, item)}
|
||||
oncontextmenu={(e) => handleContextMenu(e, item)}
|
||||
role="button"
|
||||
tabindex={item.disabled ? -1 : 0}
|
||||
onclick={() => handleClick(item.id, item.disabled)}
|
||||
onkeydown={(e) => !item.disabled && e.key === 'Enter' && handleClick(item.id)}
|
||||
>
|
||||
<input
|
||||
type="file"
|
||||
id={`file-input-${item.id}`}
|
||||
class="hidden"
|
||||
accept=".csv"
|
||||
onchange={(e) => handleFileChange(e, item)}
|
||||
disabled={item.disabled}
|
||||
/>
|
||||
|
||||
<Card.Root
|
||||
class={cn(
|
||||
'h-full border-2 border-dashed border-transparent transition-colors w-full text-left relative overflow-hidden',
|
||||
!item.disabled && 'hover:border-primary/50 hover:shadow-md',
|
||||
!item.disabled && dragOverId === item.id
|
||||
? 'border-primary bg-primary/5 shadow-xl ring-2 ring-primary ring-offset-2'
|
||||
: ''
|
||||
)}
|
||||
>
|
||||
{#if item.disabled}
|
||||
<div
|
||||
class="absolute inset-0 bg-background/50 z-20 flex items-center justify-center"
|
||||
>
|
||||
<span
|
||||
class="bg-muted px-2 py-1 rounded text-xs font-semibold text-muted-foreground border flex items-center gap-1"
|
||||
>
|
||||
<Lock class="h-3 w-3" /> Próximamente
|
||||
</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<Card.Content
|
||||
class="flex flex-col items-center justify-center p-6 gap-3 text-center h-full relative z-10"
|
||||
>
|
||||
{#if !item.disabled && dragOverId === item.id}
|
||||
<div class="animate-bounce">
|
||||
<UploadCloud class="h-8 w-8 text-primary" />
|
||||
</div>
|
||||
<span class="text-sm font-semibold text-primary">¡Suelta el archivo!</span>
|
||||
{:else}
|
||||
<div
|
||||
class={cn(
|
||||
'p-3 bg-muted rounded-full transition-transform duration-200',
|
||||
!item.disabled && 'group-hover:scale-110'
|
||||
)}
|
||||
>
|
||||
<item.icon class="h-6 w-6 text-primary" />
|
||||
</div>
|
||||
<div class="font-medium text-sm text-balance">{item.title}</div>
|
||||
{/if}
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
Shield,
|
||||
Users,
|
||||
Ship,
|
||||
MoreHorizontal,
|
||||
} from 'lucide-svelte';
|
||||
import * as m from "$lib/paraglide/messages.js";
|
||||
import { Title } from '../ui/alert';
|
||||
@@ -423,6 +424,7 @@ export function getSidebarData(): SidebarData {
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
title: m["sidebar.clients_and_providers"](),
|
||||
url: "/dashboard/clients_and_providers",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
<script lang="ts">
|
||||
import { tick } from "svelte";
|
||||
import * as DropdownMenu from "$lib/components/ui/dropdown-menu/index.js";
|
||||
import { useSidebar } from "$lib/components/ui/sidebar/context.svelte.js";
|
||||
import * as Sidebar from "$lib/components/ui/sidebar/index.js";
|
||||
@@ -20,6 +21,17 @@
|
||||
} = $props();
|
||||
|
||||
const sidebar = useSidebar();
|
||||
|
||||
let open = $state(false);
|
||||
let position = $state({ x: 0, y: 0 });
|
||||
|
||||
async function handleMoreClick(e: MouseEvent) {
|
||||
e.preventDefault();
|
||||
open = false;
|
||||
position = { x: e.clientX, y: e.clientY };
|
||||
await tick();
|
||||
open = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<Sidebar.Group class="group-data-[collapsible=icon]:hidden">
|
||||
@@ -66,11 +78,28 @@
|
||||
</DropdownMenu.Root>
|
||||
</Sidebar.MenuItem>
|
||||
{/each}
|
||||
|
||||
<Sidebar.MenuItem>
|
||||
<Sidebar.MenuButton class="text-sidebar-foreground/70">
|
||||
<Sidebar.MenuButton class="text-sidebar-foreground/70" onclick={handleMoreClick}>
|
||||
<EllipsisIcon class="text-sidebar-foreground/70" />
|
||||
<span>More</span>
|
||||
</Sidebar.MenuButton>
|
||||
|
||||
<DropdownMenu.Root bind:open>
|
||||
<DropdownMenu.Trigger class="fixed z-50 size-0" style="top: {position.y}px; left: {position.x}px" />
|
||||
<DropdownMenu.Content
|
||||
class="w-48 rounded-lg"
|
||||
side="right"
|
||||
align="start"
|
||||
>
|
||||
<DropdownMenu.Item>
|
||||
<a href="/dashboard/csv-upload" class="flex items-center gap-2 w-full">
|
||||
<FolderIcon class="size-4 text-muted-foreground" />
|
||||
<span>Carga CSV</span>
|
||||
</a>
|
||||
</DropdownMenu.Item>
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Root>
|
||||
</Sidebar.MenuItem>
|
||||
</Sidebar.Menu>
|
||||
</Sidebar.Group>
|
||||
|
||||
366
frontend/src/lib/config/csv-upload.ts
Normal file
366
frontend/src/lib/config/csv-upload.ts
Normal file
@@ -0,0 +1,366 @@
|
||||
import {
|
||||
User,
|
||||
Users,
|
||||
FileText,
|
||||
Truck,
|
||||
Container,
|
||||
Ship,
|
||||
Plane,
|
||||
Package,
|
||||
Briefcase,
|
||||
Globe,
|
||||
CreditCard,
|
||||
DollarSign,
|
||||
Calendar,
|
||||
Hash,
|
||||
MapPin,
|
||||
ShieldCheck,
|
||||
FileDigit,
|
||||
Scale,
|
||||
} from 'lucide-svelte';
|
||||
|
||||
// --- Interfaces ---
|
||||
|
||||
export interface CsvUploadItem {
|
||||
id: string;
|
||||
title: string;
|
||||
icon: any;
|
||||
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/
|
||||
disabled?: boolean; // New property to mark items as "Coming Soon"
|
||||
}
|
||||
|
||||
export interface CsvUploadField {
|
||||
name: string;
|
||||
label: string;
|
||||
type: 'text' | 'select' | 'boolean' | 'date' | 'radio';
|
||||
options?: { label: string; value: string | boolean | number }[];
|
||||
required?: boolean;
|
||||
defaultValue?: any;
|
||||
}
|
||||
|
||||
// Map of Tab ID -> Array of Fields
|
||||
export const tabSettings: Record<string, CsvUploadField[]> = {
|
||||
catalogos: [
|
||||
{
|
||||
name: 'mode',
|
||||
label: 'Modo de Carga',
|
||||
type: 'radio',
|
||||
options: [
|
||||
{ label: 'Actualizar', value: 'update' },
|
||||
{ label: 'Reemplazar', value: 'replace' }
|
||||
],
|
||||
defaultValue: 'update'
|
||||
}
|
||||
],
|
||||
transportes: [
|
||||
{
|
||||
name: 'mode',
|
||||
label: 'Modo de Carga',
|
||||
type: 'radio',
|
||||
options: [
|
||||
{ label: 'Actualizar', value: 'update' },
|
||||
{ label: 'Reemplazar', value: 'replace' }
|
||||
],
|
||||
defaultValue: 'update'
|
||||
}
|
||||
],
|
||||
importacion: [
|
||||
{
|
||||
name: 'autonumber_remesas',
|
||||
label: 'Autonumerar Remesas',
|
||||
type: 'boolean',
|
||||
defaultValue: false
|
||||
},
|
||||
{
|
||||
name: 'recalculate_dates',
|
||||
label: 'Recalcular Fechas',
|
||||
type: 'boolean',
|
||||
defaultValue: false
|
||||
},
|
||||
{
|
||||
name: 'dateFormat',
|
||||
label: 'Formato de Fecha',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: 'DD/MM/YYYY', value: 'dd/mm/yyyy' },
|
||||
{ label: 'MM/DD/YYYY', value: 'mm/dd/yyyy' },
|
||||
{ label: 'YYYY-MM-DD', value: 'yyyy-mm-dd' }
|
||||
],
|
||||
defaultValue: 'dd/mm/yyyy'
|
||||
}
|
||||
],
|
||||
exportacion: [
|
||||
{
|
||||
name: 'invoice_type',
|
||||
label: 'Tipo de Factura',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: 'AFIJO', value: 'AFIJO' },
|
||||
{ label: 'NORMAL', value: 'NORMAL' },
|
||||
],
|
||||
defaultValue: 'AFIJO',
|
||||
},
|
||||
{
|
||||
name: 'is_regime_change',
|
||||
label: 'Es Cambio de Régimen',
|
||||
type: 'boolean',
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
name: 'dateFormat',
|
||||
label: 'Formato de Fecha',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: 'DD/MM/YYYY', value: 'dd/mm/yyyy' },
|
||||
{ label: 'MM/DD/YYYY', value: 'mm/dd/yyyy' },
|
||||
{ label: 'YYYY-MM-DD', value: 'yyyy-mm-dd' }
|
||||
],
|
||||
defaultValue: 'dd/mm/yyyy'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// --- DATA DEFINITIONS (Items only, no config) ---
|
||||
|
||||
export const catalogosConfig: CsvUploadItem[] = [
|
||||
{
|
||||
id: 'customs_brokers',
|
||||
title: 'Agentes Aduanales',
|
||||
icon: User,
|
||||
modelTarget: 'CustomsBroker',
|
||||
templateUrl: '/csv/EstructuraCatAgenteAduanal.xls'
|
||||
},
|
||||
{
|
||||
id: 'clients_providers',
|
||||
title: 'Clientes y Proveedores',
|
||||
icon: Users,
|
||||
modelTarget: 'ClientProvider',
|
||||
templateUrl: '/csv/EstructuraCatClienteProv.xls'
|
||||
},
|
||||
{
|
||||
id: 'exchange_rates',
|
||||
title: 'Tipo de Cambios',
|
||||
icon: DollarSign,
|
||||
modelTarget: 'ExchangeRate',
|
||||
templateUrl: '/csv/EstructuraCatTiposCambio.xls'
|
||||
},
|
||||
{
|
||||
id: 'american_fractions',
|
||||
title: 'Fracc. Ame.',
|
||||
icon: Globe,
|
||||
modelTarget: 'AmericanFraction',
|
||||
templateUrl: '/csv/EstructuraCatFraccAme.xls'
|
||||
},
|
||||
{
|
||||
id: 'material_classes',
|
||||
title: 'Clases de Materiales',
|
||||
icon: Package,
|
||||
modelTarget: 'MaterialClass',
|
||||
templateUrl: '/csv/EstructuraCatClasesAF.xls'
|
||||
},
|
||||
{
|
||||
id: 'items',
|
||||
title: 'Partidas (Permisos)',
|
||||
icon: FileText,
|
||||
group: 'Permisos',
|
||||
modelTarget: 'ItemPermission',
|
||||
templateUrl: '/csv/EstructuraCatPartesAF.xls'
|
||||
},
|
||||
{
|
||||
id: 'headers',
|
||||
title: 'Encabezados (Permisos)',
|
||||
icon: FileText,
|
||||
group: 'Permisos',
|
||||
modelTarget: 'HeaderPermission',
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
id: 'historical_fractions',
|
||||
title: 'Fracciones Históricas',
|
||||
icon: Calendar,
|
||||
modelTarget: 'HistoricalFraction',
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
id: 'pedimentos',
|
||||
title: 'Pedimentos',
|
||||
icon: FileDigit,
|
||||
modelTarget: 'Pedimento',
|
||||
templateUrl: '/csv/EstructuraCatPedimentos.xls'
|
||||
},
|
||||
];
|
||||
|
||||
export const transportesConfig: CsvUploadItem[] = [
|
||||
{
|
||||
id: 'transports',
|
||||
title: 'Transportes',
|
||||
icon: Truck,
|
||||
modelTarget: 'Transport',
|
||||
templateUrl: '/csv/EstructuraCatTransportes.xls'
|
||||
},
|
||||
{
|
||||
id: 'drivers',
|
||||
title: 'Conductores',
|
||||
icon: User,
|
||||
modelTarget: 'Driver',
|
||||
templateUrl: '/csv/EstructuraCatConductor.xls'
|
||||
},
|
||||
{
|
||||
id: 'trailers',
|
||||
title: 'Trailers y Cajas',
|
||||
icon: Container,
|
||||
modelTarget: 'Trailer',
|
||||
templateUrl: '/csv/EstructuraCatTrailers.xls'
|
||||
},
|
||||
];
|
||||
|
||||
export const importacionConfig: CsvUploadItem[] = [
|
||||
// Impo Temp
|
||||
{
|
||||
id: 'imp_temp_header',
|
||||
title: 'Encabezado',
|
||||
icon: FileText,
|
||||
group: 'Impo. Temp.',
|
||||
modelTarget: 'InvoiceHeader',
|
||||
templateUrl: '/csv/EstructuraEncFacImpoTemp.xls'
|
||||
},
|
||||
{
|
||||
id: 'imp_temp_details',
|
||||
title: 'Partidas',
|
||||
icon: Package,
|
||||
group: 'Impo. Temp.',
|
||||
modelTarget: 'InvoiceSalesDetails',
|
||||
templateUrl: '/csv/EstructuraParFacImpoTempAF.xls'
|
||||
},
|
||||
{
|
||||
id: 'imp_temp_series',
|
||||
title: 'Series',
|
||||
icon: Hash,
|
||||
group: 'Impo. Temp.',
|
||||
modelTarget: 'InvoiceSeries',
|
||||
disabled: true,
|
||||
},
|
||||
// Impo Def
|
||||
{
|
||||
id: 'imp_def_header',
|
||||
title: 'Encabezado',
|
||||
icon: FileText,
|
||||
group: 'Impo. Def.',
|
||||
modelTarget: 'InvoiceHeader',
|
||||
templateUrl: '/csv/EstructuraEncFacImpoDef.xls'
|
||||
},
|
||||
{
|
||||
id: 'imp_def_details',
|
||||
title: 'Partidas',
|
||||
icon: Package,
|
||||
group: 'Impo. Def.',
|
||||
modelTarget: 'InvoiceSalesDetails',
|
||||
templateUrl: '/csv/EstructuraParFacImpoDefAF.xls'
|
||||
},
|
||||
{
|
||||
id: 'imp_def_series',
|
||||
title: 'Series',
|
||||
icon: Hash,
|
||||
group: 'Impo. Def.',
|
||||
modelTarget: 'InvoiceSeries',
|
||||
disabled: true,
|
||||
},
|
||||
// Compras Mex
|
||||
{
|
||||
id: 'comp_mex_header',
|
||||
title: 'Encabezado',
|
||||
icon: FileText,
|
||||
group: 'Compras Mex.',
|
||||
modelTarget: 'InvoiceHeader',
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
id: 'comp_mex_details',
|
||||
title: 'Partidas',
|
||||
icon: Package,
|
||||
group: 'Compras Mex.',
|
||||
modelTarget: 'InvoiceSalesDetails',
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
id: 'comp_mex_series',
|
||||
title: 'Series',
|
||||
icon: Hash,
|
||||
group: 'Compras Mex.',
|
||||
modelTarget: 'InvoiceSeries',
|
||||
disabled: true,
|
||||
},
|
||||
];
|
||||
|
||||
export const exportacionConfig: CsvUploadItem[] = [
|
||||
// Expo Def / Cam. Reg.
|
||||
{
|
||||
id: 'exp_def_header',
|
||||
title: 'Encabezado',
|
||||
icon: FileText,
|
||||
group: 'Expo. Def./Cam. Reg.',
|
||||
modelTarget: 'InvoiceHeader',
|
||||
templateUrl: '/csv/EstructuraEncFacExpoCamReg.xls'
|
||||
},
|
||||
{
|
||||
id: 'exp_def_details',
|
||||
title: 'Partidas',
|
||||
icon: Package,
|
||||
group: 'Expo. Def./Cam. Reg.',
|
||||
modelTarget: 'InvoiceSalesDetails',
|
||||
templateUrl: '/csv/EstructuraParExpoCamReg.xls'
|
||||
},
|
||||
{
|
||||
id: 'exp_def_series',
|
||||
title: 'Series',
|
||||
icon: Hash,
|
||||
group: 'Expo. Def./Cam. Reg.',
|
||||
modelTarget: 'InvoiceSeries',
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
id: 'exp_def_nodes',
|
||||
title: 'NODES',
|
||||
icon: Briefcase,
|
||||
group: 'Expo. Def./Cam. Reg.',
|
||||
modelTarget: 'Nodes',
|
||||
disabled: true,
|
||||
},
|
||||
// Expo Rep
|
||||
{
|
||||
id: 'exp_rep_header',
|
||||
title: 'Encabezado',
|
||||
icon: FileText,
|
||||
group: 'Expo. Rep.',
|
||||
modelTarget: 'InvoiceHeader',
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
id: 'exp_rep_details',
|
||||
title: 'Partidas',
|
||||
icon: Package,
|
||||
group: 'Expo. Rep.',
|
||||
modelTarget: 'InvoiceSalesDetails',
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
id: 'exp_rep_series',
|
||||
title: 'Series',
|
||||
icon: Hash,
|
||||
group: 'Expo. Rep.',
|
||||
modelTarget: 'InvoiceSeries',
|
||||
disabled: true,
|
||||
},
|
||||
// Manifiesto
|
||||
{
|
||||
id: 'manifest_header',
|
||||
title: 'Encabezado',
|
||||
icon: FileText,
|
||||
group: 'Manifiesto',
|
||||
modelTarget: 'Manifest',
|
||||
disabled: true,
|
||||
},
|
||||
];
|
||||
107
frontend/src/routes/dashboard/csv-upload/+page.svelte
Normal file
107
frontend/src/routes/dashboard/csv-upload/+page.svelte
Normal file
@@ -0,0 +1,107 @@
|
||||
<script lang="ts">
|
||||
import * as Tabs from '$lib/components/ui/tabs/index.js';
|
||||
import UploadLauncherGrid from '$lib/components/dashboard/csv-upload/UploadLauncherGrid.svelte';
|
||||
import ConfigFooter from '$lib/components/dashboard/csv-upload/ConfigFooter.svelte';
|
||||
import {
|
||||
catalogosConfig,
|
||||
transportesConfig,
|
||||
importacionConfig,
|
||||
exportacionConfig,
|
||||
tabSettings,
|
||||
type CsvUploadItem
|
||||
} from '$lib/config/csv-upload';
|
||||
import { toast } from 'svelte-sonner';
|
||||
|
||||
// We no longer need modal state
|
||||
let activeTab = $state('catalogos');
|
||||
|
||||
let allSettings = $state<Record<string, any>>({});
|
||||
|
||||
$effect(() => {
|
||||
const fields = tabSettings[activeTab] || [];
|
||||
if (!allSettings[activeTab]) {
|
||||
allSettings[activeTab] = {};
|
||||
fields.forEach((f) => {
|
||||
allSettings[activeTab][f.name] = f.defaultValue;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function handleUpload(file: File, config: CsvUploadItem) {
|
||||
const currentSettings = allSettings[activeTab] || {};
|
||||
|
||||
console.log('🚀 Starting Direct Upload Processing', {
|
||||
file: file.name,
|
||||
size: file.size,
|
||||
target: config.modelTarget,
|
||||
config: config.title,
|
||||
settings: currentSettings
|
||||
});
|
||||
|
||||
// Mock Processing Feedback
|
||||
const promise = new Promise((resolve) => setTimeout(resolve, 2000));
|
||||
|
||||
toast.promise(promise, {
|
||||
loading: `Procesando ${file.name} para ${config.title}...`,
|
||||
success: `Archivo cargado correctamente con configuración: ${JSON.stringify(currentSettings)}`,
|
||||
error: 'Error al cargar el archivo'
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col h-[calc(100vh-4rem)] -m-4 overflow-hidden">
|
||||
<!-- Scrollable Content Area -->
|
||||
<div class="flex-1 overflow-y-auto p-4 md:p-8 space-y-4">
|
||||
<div class="flex items-center gap-4">
|
||||
<h1 class="text-lg font-semibold md:text-2xl">Importación Masiva de Datos (CSV)</h1>
|
||||
</div>
|
||||
|
||||
<Tabs.Root bind:value={activeTab} class="w-full">
|
||||
<Tabs.List class="grid w-full grid-cols-2 md:grid-cols-4 lg:w-auto">
|
||||
<Tabs.Trigger value="catalogos">Catálogos</Tabs.Trigger>
|
||||
<Tabs.Trigger value="transportes">Transportes</Tabs.Trigger>
|
||||
<Tabs.Trigger value="importacion">Importación</Tabs.Trigger>
|
||||
<Tabs.Trigger value="exportacion">Exportación</Tabs.Trigger>
|
||||
</Tabs.List>
|
||||
|
||||
<div class="mt-6">
|
||||
<Tabs.Content value="catalogos" class="space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="text-lg font-medium tracking-tight">Catálogos Generales</h2>
|
||||
</div>
|
||||
<UploadLauncherGrid items={catalogosConfig} onUpload={handleUpload} />
|
||||
</Tabs.Content>
|
||||
|
||||
<Tabs.Content value="transportes" class="space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="text-lg font-medium tracking-tight">Logística y Transporte</h2>
|
||||
</div>
|
||||
<UploadLauncherGrid items={transportesConfig} onUpload={handleUpload} />
|
||||
</Tabs.Content>
|
||||
|
||||
<Tabs.Content value="importacion" class="space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="text-lg font-medium tracking-tight">Operaciones de Importación</h2>
|
||||
</div>
|
||||
<UploadLauncherGrid items={importacionConfig} onUpload={handleUpload} />
|
||||
</Tabs.Content>
|
||||
|
||||
<Tabs.Content value="exportacion" class="space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="text-lg font-medium tracking-tight">Operaciones de Exportación</h2>
|
||||
</div>
|
||||
<UploadLauncherGrid items={exportacionConfig} onUpload={handleUpload} />
|
||||
</Tabs.Content>
|
||||
</div>
|
||||
</Tabs.Root>
|
||||
|
||||
<div class="h-4"></div>
|
||||
</div>
|
||||
|
||||
<!-- Fixed Footer Area -->
|
||||
{#if allSettings[activeTab]}
|
||||
<div class="flex-none z-20">
|
||||
<ConfigFooter {activeTab} bind:settings={allSettings[activeTab]} />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
1
frontend/static/csv/EstructuraCatAgenteAduanal.xls
Normal file
1
frontend/static/csv/EstructuraCatAgenteAduanal.xls
Normal file
@@ -0,0 +1 @@
|
||||
TIPO(MEX=Mexicano,AME=AMERICANO) CLAVE AADUANAL PATENTE NOMBRE RFC DIRECCION CODIGO POSTAL CIUDAD ESTADO PAIS TELEFONO NUMERO FAX CORREO ELECTRONICO CURP
|
||||
1
frontend/static/csv/EstructuraCatClasesAF.xls
Normal file
1
frontend/static/csv/EstructuraCatClasesAF.xls
Normal file
@@ -0,0 +1 @@
|
||||
CLAVE CLASE DESCRIPCION ESPA<50>OL DESCRIPCION INGLES TIPO DE MATERIAL U.M. COMERCIAL FRACCION ARANCELARIA FRACCION AMERICANA TASA DE DEPRECIACION REVISION FISICA (1/0) CODIGO DE PRODUCTO/SERVICIO CP
|
||||
1
frontend/static/csv/EstructuraCatClienteProv.xls
Normal file
1
frontend/static/csv/EstructuraCatClienteProv.xls
Normal file
@@ -0,0 +1 @@
|
||||
PROCEDENCIA CLIENTE(E=Extranjero, N=Nacional) TIPO(C=Cliente,P=Proveedor,A=Ambos) CLAVE CLIENTE NOMBRE RFC CALLES NUM. EXTERIOR CODIGO POSTAL COLONIA o PARQUE IND. CIUDAD ESTADO PAIS TELEFONO NUMERO FAX CORREO ELECTRONICO CURP TIPO DE PROGRAMA SECON NUMERO DE PROGRAMA SECON FECHA AUT. SECON ##/##/#### ES PROGRAMA PROSEC? (SI o NO) NUMERO DE PROGRAMA PROSEC VINCULACION ES EMPRESA CERTIFICADA? REGISTRO DE EMPRESA CERT. INFORMACION ADICIONAL CONTACTO CLAVE MANUFACTURERO TAX I.D. CLAVE BROKER AMERICANO EXPO CLAVE BROKER AMERICANO IMPO CLAVE TRANSFERENCIA A.A. TRANSFORMADOR/SUBMAQUILA CLAVE INTERFACE
|
||||
1
frontend/static/csv/EstructuraCatConductor.xls
Normal file
1
frontend/static/csv/EstructuraCatConductor.xls
Normal file
@@ -0,0 +1 @@
|
||||
TRANSPORTISTA LINEA CLAVE CONDUCTOR LICENCIA PERMISO LINEA EXPRESS IDENTIFICACION ACE FECHA NACIMIENTO SEXO PAIS NACIMIENTO TRANSPORTA MAT. PELIGROSO? PERMISO MAT. PELIGROSO NOMBRE(S) APELLIDO PATERNO FORMA IDENTIFICACION 1 NUM. IDENTIFICACION 1 ESTADO PAIS FORMA IDENTIFICACION 2 NUM. IDENTIFICACION 2 ESTADO PAIS
|
||||
1
frontend/static/csv/EstructuraCatFraccAme.xls
Normal file
1
frontend/static/csv/EstructuraCatFraccAme.xls
Normal file
@@ -0,0 +1 @@
|
||||
FRACCION ARANCELARIA PREFIJO UNIDAD DE MEDIDA DESCRIPCION TIPO DE ADVALOREM ADVALOREM % ADVALOREM DLLS
|
||||
1
frontend/static/csv/EstructuraCatPartesAF.xls
Normal file
1
frontend/static/csv/EstructuraCatPartesAF.xls
Normal file
@@ -0,0 +1 @@
|
||||
NUMERO DE PARTE DESCRIPCION EN ESPA<50>OL DESCRIPCION EN INGLES CLASE UNIDAD DE MEDIDA COMERCIAL COSTO UNITARIO TIPO MONEDA COSTO CLAVE MONEDA PESO UNITARIO TIPO PESO FRACCION PAIS PREFERENCIA SECTOR RUTA DE LA IMAGEN
|
||||
1
frontend/static/csv/EstructuraCatPedimentos.xls
Normal file
1
frontend/static/csv/EstructuraCatPedimentos.xls
Normal file
@@ -0,0 +1 @@
|
||||
NUMERO DE PEDIMENTO (##-####-######) TIPO MOV(I=Impotaci<63>n,E=Expotaci<63>n) CLAVE PEDIMENTO REGIMEN FECHA INICIO FECHA FINAL FECHA DE PAGO ADUANA Y SECCION DE CRUCE ACUSE ELECTRONICO INDIVIDUAL o CONSOLIDADO (IND,CON) MET TRANS ENTRADA MET TRANS ARRIVO MET TRANS SALIDA IEPS DTA CNT PREVALIDACION MONTO TIGIE PAGO IMPUESTO? (S/N) ES MIXTO (SI/NO) OBS RECTIFICA OPCION DESTINO(Interior del Pais/Regi<67>n Fronteriza/Franja Fronteriza) VALOR IVA VALOR ME VALOR ADUANAS FLETE VALOR SEGUROS SEGUROS EMBALAJES OTROS INCREMENTABLES ESTATUS (ABIERTO/CERRADO) PERSONA REV FECHA CIERRE FECHA REVISION FECHA AUTORIZACION FECHA RECIBIDO REPRESENTANTE AA CLAVE DEST ORIGEN FECHA ENTRADA RECINTO FECHA EXTRACCION RECINTO ERRORES FORMA PAGO DTA FORMA PAGO IGI FORMA PAGO PREVAL FORMA PAGO IVA RECARGOS MULTAS IVA DE PREV CUOTAS CONPENSATORIAS IDENTIFICADORES IEPS 2 FORMA DE PAGO IEPS 2 DTA 2 FORMA DE PAGO DTA 2 IVA 2 FORMA DE PAGO IVA 2 IGI 2 FORMA DE PAGO IGI 2 PREVALIDACION FORMA DE PAGO PREVALIDACION 2 CNT 2 FORMA DE PAGO CNT 2
|
||||
1
frontend/static/csv/EstructuraCatTiposCambio.xls
Normal file
1
frontend/static/csv/EstructuraCatTiposCambio.xls
Normal file
@@ -0,0 +1 @@
|
||||
FECHA (##/##/####) TIPO DE CAMBIO
|
||||
1
frontend/static/csv/EstructuraCatTrailers.xls
Normal file
1
frontend/static/csv/EstructuraCatTrailers.xls
Normal file
@@ -0,0 +1 @@
|
||||
CLAVE TRAILER/CAJA NUMERO ACE TIPO DE TRAILER PRECINTO CODIGO DE ENTIDAD PLACAS ESTADO PAIS
|
||||
1
frontend/static/csv/EstructuraCatTransportes.xls
Normal file
1
frontend/static/csv/EstructuraCatTransportes.xls
Normal file
@@ -0,0 +1 @@
|
||||
CLAVE CLAVE ACE CLAVE TRANSPORTE VIN TIPO TRANSPORTE CODIGO DE ENTIDAD TRANSPONDEDOR NUMERO DOT PLACAS CIUDAD ESTADO PAIS PRECINTO EMPRESA ASEGURADORA NUM. ASEGURADORA MONTO ASEGURADO FECHA DE ASEGURADORA
|
||||
1
frontend/static/csv/EstructuraEncFacExpoCamReg.xls
Normal file
1
frontend/static/csv/EstructuraEncFacExpoCamReg.xls
Normal file
@@ -0,0 +1 @@
|
||||
PEDIMENTO REMESA NUMERO FACTURA FECHA FACTURA TIPO DE CAMBIO REGIMEN CLAVE PROVEEDOR CLAVE VENDIDO A: CLAVE ENVIADO A AGENTE ADUANAL CLAVE TRANSPORTISTA NOMBRE CONDUCTOR TIPO TRANSPORTE NUMERO TRANSPORTE TIPO MONEDA CLAVE MONEDA FLETES VALOR SEGUROS SEGUROS EMBALAJES OTROS INCREMENTABLES CLAVE INCOTERM PRECINTO TIPO PESO MANIFIESTO E-DOCUMENT NUM. OPERACION ENVIADO POR ADUANA DE CRUCE OBSERVACIONES E OBSERVACIONES I FACTURA ALTERNA
|
||||
1
frontend/static/csv/EstructuraEncFacImpoDef.xls
Normal file
1
frontend/static/csv/EstructuraEncFacImpoDef.xls
Normal file
@@ -0,0 +1 @@
|
||||
PEDIMENTO REMESA NUMERO FACTURA FECHA FACTURA TIPO DE CAMBIO REGIMEN CLAVE PROVEEDOR CLAVE VENDIDO A: CLAVE ENVIADO A AGENTE ADUANAL CLAVE TRANSPORTISTA NOMBRE CONDUCTOR TIPO TRANSPORTE NUMERO TRANSPORTE TIPO MONEDA CLAVE MONEDA FLETES VALOR SEGUROS SEGUROS EMBALAJES OTROS INCREMENTABLES CLAVE INCOTERM PRECINTO FECHA EMISION TIPO PESO E-DOCUMENT NUM. OPERACION ADUANA DE CRUCE OBSERVACIONES E OBSERVACIONES I
|
||||
1
frontend/static/csv/EstructuraEncFacImpoTemp.xls
Normal file
1
frontend/static/csv/EstructuraEncFacImpoTemp.xls
Normal file
@@ -0,0 +1 @@
|
||||
PEDIMENTO REMESA NUMERO FACTURA FECHA FACTURA TIPO DE CAMBIO REGIMEN CLAVE PROVEEDOR CLAVE VENDIDO A: CLAVE ENVIADO A AGENTE ADUANAL CLAVE TRANSPORTISTA NOMBRE CONDUCTOR TIPO TRANSPORTE NUMERO TRANSPORTE TIPO MONEDA CLAVE MONEDA FLETES VALOR SEGUROS SEGUROS EMBALAJES OTROS INCREMENTABLES CLAVE INCOTERM PRECINTO FECHA EMISION TIPO PESO E-DOCUMENT NUM. OPERACION ADUANA DE CRUCE OBSERVACIONES E OBSERVACIONES I FACTURA ALTERNA
|
||||
1
frontend/static/csv/EstructuraParExpoCamReg.xls
Normal file
1
frontend/static/csv/EstructuraParExpoCamReg.xls
Normal file
@@ -0,0 +1 @@
|
||||
NUMERO FACTURA EXPO. LINEA EXPO. TIPO DE IMPO. FACTURA IMPO. LINEA IMPO. GENERA DESCARGA CANTIDAD EXPORTADA/DESCARGAR COSTO UNITARIO PESO NETO PESO BRUTO SE PAGO IMPUESTO? (SI o NO) FORMA DE PAGO DESCRIPCION EXTRA INFORMACION ADICIONAL AGREGAR(A)/SUSTITUIR(S) LOTE NUMERO ENTRADA ES PARTIDA/SUBPARTIDA LINEA PRINCIPAL FRACCION AMERICANA FRACCION ARANCELARIA
|
||||
1
frontend/static/csv/EstructuraParFacImpoDefAF.xls
Normal file
1
frontend/static/csv/EstructuraParFacImpoDefAF.xls
Normal file
@@ -0,0 +1 @@
|
||||
NUMERO FACTURA LINEA CLASE CANTIDAD IMPORTADA UNIDAD DE MEDIDA COSTO UNITARIO PESO NETO PESO BRUTO CANTIDAD BULTOS CLAVE BULTOS PAIS ORIGEN FRACCION ARANCELARIA PREFERENCIA ARANCELARIA SECTOR FRACCION AMERICANA ORDEN DE COMPRA DESCRIPCION ESPA<50>OL DESCRIPCION INGLES MARCA MODELO ES PARTIDA O SUBPARTIDA LINEA PRINCIPAL NUM. PARTE SE PAGO IMPUESTO? (SI o NO) FORMA DE PAGO METODO DE VALORACION DESCRIPCION EXTRA INFORMACION ADICIONAL AGREGAR(A)/SUSTITUIR(S) VALOR TOTAL LOTE NUMERO ENTRADA ID TYPE
|
||||
1
frontend/static/csv/EstructuraParFacImpoTempAF.xls
Normal file
1
frontend/static/csv/EstructuraParFacImpoTempAF.xls
Normal file
@@ -0,0 +1 @@
|
||||
NUMERO FACTURA LINEA CLASE CANTIDAD IMPORTADA UNIDAD DE MEDIDA COSTO UNITARIO PESO NETO PESO BRUTO CANTIDAD BULTOS CLAVE BULTOS PAIS ORIGEN FRACCION ARANCELARIA PREFERENCIA ARANCELARIA SECTOR FRACCION AMERICANA ORDEN DE COMPRA DESCRIPCION ESPA<50>OL DESCRIPCION INGLES MARCA MODELO ES PARTIDA O SUBPARTIDA LINEA PRINCIPAL NUM. PARTE SE PAGO IMPUESTO? (SI o NO) FORMA DE PAGO METODO DE VALORACION DESCRIPCION EXTRA INFORMACION ADICIONAL AGREGAR(A)/SUSTITUIR(S) TOTAL NUMERO ENTRADA LOTE ID TYPE
|
||||
Reference in New Issue
Block a user