Arreglo de filtros, acomodo de fechas y se agrego catalogos

This commit is contained in:
2026-05-20 16:56:20 -05:00
parent 60d552da59
commit e8a486c119
4 changed files with 104 additions and 58 deletions

View File

@@ -3,15 +3,19 @@
import * as Dialog from '$lib/components/ui/dialog';
import { Input } from '$lib/components/ui/input';
import { Label } from '$lib/components/ui/label';
// 👇 Verifica la ruta de tu archivo TS
import { Search } from 'lucide-svelte';
import {
createMultiCurrencyType,
updateMultiCurrencyType,
type MultiCurrencyType
} from '$lib/api/dashboard/a76/general_catalogs/multi-currency-types';
import { companyStore } from '$lib/stores/company.svelte';
import { obtenerAtajosFormularioMonedas } from '$lib/config/shortcuts/dashboard/general_catalogs/multi_currency_types/edit';
import { m } from '$lib/i18n/messages';
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 type { CurrencyType } from '$lib/api/dashboard/reference_data/currency_types';
import type { Country } from '$lib/api/dashboard/reference_data/countries';
import { toast } from 'svelte-sonner';
let {
open = $bindable(false),
@@ -23,45 +27,36 @@
onSuccess?: () => void;
} = $props();
// Atajos
const isEdit = $derived(!!item);
const title = $derived(
isEdit ? m.multi_currency_edit_title() : m.multi_currency_new_title()
);
const title = $derived(isEdit ? m.multi_currency_edit_title() : m.multi_currency_new_title());
// Estado del formulario
let formData = $state({
currency_type_code: '',
country_key: '',
conversion_factor: null as number | null,
date_str: '' // Usamos un string temporal para el input type="date"
date_str: ''
});
let loading = $state(false);
let error = $state<string | null>(null);
let showCurrencyDialog = $state(false);
let showCountryDialog = $state(false);
// Cargar datos al abrir
$effect(() => {
if (open) {
if (item) {
// Truco: Convertir Entero (20251231) -> String ("2025-12-31")
const s = item.publication_date?.toString();
let dateFormatted = '';
if (item.publication_date) {
const s = item.publication_date.toString();
if (s.length === 8) {
dateFormatted = `${s.slice(0, 4)}-${s.slice(4, 6)}-${s.slice(6, 8)}`;
}
if (s?.length === 8) {
dateFormatted = `${s.slice(0, 4)}-${s.slice(4, 6)}-${s.slice(6, 8)}`;
}
formData = {
currency_type_code: item.currency_type_code,
country_key: item.country_key || '',
conversion_factor: item.conversion_factor,
date_str: dateFormatted
};
} else {
// Default: Fecha de hoy
} else {
formData = {
currency_type_code: '',
country_key: '',
@@ -73,6 +68,16 @@
}
});
function handleCurrencySelect(currency: CurrencyType) {
formData.currency_type_code = currency.code;
toast.success(`${currency.code}${currency.currency_name}`);
}
function handleCountrySelect(country: Country) {
formData.country_key = country.m3_key;
toast.success(`${country.m3_key}${country.description_es || country.description_en || ''}`);
}
async function handleSubmit() {
loading = true;
error = null;
@@ -80,33 +85,23 @@
try {
const companyId = companyStore.activeCompany?.id;
if (!companyId) throw new Error(m.exchange_rate_error_no_company());
// Validaciones
if (!formData.currency_type_code.trim()) throw new Error(m.multi_currency_error_currency_required());
if (!formData.date_str) throw new Error(m.multi_currency_error_date_required());
// Truco: Convertir String ("2025-12-31") -> Entero (20251231)
// Quitamos los guiones y parseamos a int
const dateInt = parseInt(formData.date_str.replaceAll('-', ''), 10);
// Preparar datos
const dataToSend = {
currency_type_code: formData.currency_type_code.trim().toUpperCase(),
country_key: formData.country_key.trim().toUpperCase() || null,
conversion_factor: formData.conversion_factor ? Number(formData.conversion_factor) : null,
publication_date: dateInt // Mandamos el INT que espera Python
publication_date: dateInt
};
let response;
if (isEdit && item) {
response = await updateMultiCurrencyType(item.id, dataToSend, companyId);
} else {
response = await createMultiCurrencyType(dataToSend, companyId);
}
const response = isEdit && item
? await updateMultiCurrencyType(item.id, dataToSend, companyId)
: await createMultiCurrencyType(dataToSend, companyId);
if (response?.error) {
throw new Error(response.error);
}
if (response?.error) throw new Error(response.error);
open = false;
if (onSuccess) onSuccess();
@@ -119,16 +114,16 @@
</script>
<Dialog.Root bind:open>
<Dialog.Content class="sm:max-w-[500px]">
<Dialog.Content
class="sm:max-w-[500px]"
onInteractOutside={(e) => e.preventDefault()}
>
<Dialog.Header>
<Dialog.Title>{title}</Dialog.Title>
</Dialog.Header>
<form
onsubmit={(e) => {
e.preventDefault();
handleSubmit();
}}
onsubmit={(e) => { e.preventDefault(); handleSubmit(); }}
class="space-y-4 py-4"
>
{#if error}
@@ -138,41 +133,77 @@
{/if}
<div class="grid gap-4">
<!-- Código Moneda -->
<div class="grid grid-cols-4 items-center gap-4">
<Label for="currency_code" class="text-right"
>{m.multi_currency_currency_label()} <span class="text-destructive">*</span></Label
>
<div class="col-span-3">
<Label for="currency_code" class="text-right">
{m.multi_currency_currency_label()} <span class="text-destructive">*</span>
</Label>
<div class="col-span-3 flex gap-2">
<Input
id="currency_code"
bind:value={formData.currency_type_code}
placeholder="{m.exchange_rate_example_suffix()} USD"
oninput={(e) => {
formData.currency_type_code = e.currentTarget.value
.toUpperCase()
.replace(/[^A-Z]/g, '')
.slice(0, 3);
e.currentTarget.value = formData.currency_type_code;
}}
placeholder="Ej. USD"
maxlength={3}
disabled={loading}
required
class="flex-1 font-mono"
/>
<p class="text-[10px] text-muted-foreground mt-1">{m.multi_currency_currency_help()}</p>
<Button
type="button"
variant="outline"
size="icon"
class="h-10 w-10 shrink-0"
onclick={() => (showCurrencyDialog = true)}
disabled={loading}
>
<Search class="h-4 w-4" />
</Button>
</div>
</div>
<!-- País -->
<div class="grid grid-cols-4 items-center gap-4">
<Label for="country_key" class="text-right">{m.multi_currency_country_label()}</Label>
<div class="col-span-3">
<div class="col-span-3 flex gap-2">
<Input
id="country_key"
bind:value={formData.country_key}
placeholder="{m.exchange_rate_example_suffix()} MEX"
oninput={(e) => {
formData.country_key = e.currentTarget.value
.toUpperCase()
.replace(/[^A-Z]/g, '')
.slice(0, 3);
e.currentTarget.value = formData.country_key;
}}
placeholder="Ej. MEX"
maxlength={3}
disabled={loading}
class="flex-1 font-mono"
/>
<p class="text-[10px] text-muted-foreground mt-1">{m.multi_currency_country_help()}</p>
<Button
type="button"
variant="outline"
size="icon"
class="h-10 w-10 shrink-0"
onclick={() => (showCountryDialog = true)}
disabled={loading}
>
<Search class="h-4 w-4" />
</Button>
</div>
</div>
<!-- Fecha Publicación -->
<div class="grid grid-cols-4 items-center gap-4">
<Label for="pub_date" class="text-right"
>{m.multi_currency_date_label()} <span class="text-destructive">*</span></Label
>
<Label for="pub_date" class="text-right">
{m.multi_currency_date_label()} <span class="text-destructive">*</span>
</Label>
<div class="col-span-3">
<Input
id="pub_date"
@@ -181,10 +212,11 @@
disabled={loading}
required
/>
<p class="text-[10px] text-muted-foreground mt-1">{m.multi_currency_date_help()}</p>
<p class="mt-1 text-[10px] text-muted-foreground">{m.multi_currency_date_help()}</p>
</div>
</div>
<!-- Factor de Conversión -->
<div class="grid grid-cols-4 items-center gap-4">
<Label for="factor" class="text-right">{m.multi_currency_factor_label()}</Label>
<div class="col-span-3">
@@ -211,3 +243,6 @@
</form>
</Dialog.Content>
</Dialog.Root>
<CurrencySelectorDialog bind:open={showCurrencyDialog} onSelect={handleCurrencySelect} />
<CountrySelectorDialog bind:open={showCountryDialog} onSelect={handleCountrySelect} />

View File

@@ -72,7 +72,11 @@
{
accessorKey: 'publication_date',
header: 'Fecha Publicación',
cell: ({ row }) => row.original.publication_date || '-'
cell: ({ row }) => {
const d = row.original.publication_date?.toString();
if (!d || d.length !== 8) return '-';
return `${d.slice(6, 8)}/${d.slice(4, 6)}/${d.slice(0, 4)}`;
}
}
];
@@ -258,8 +262,8 @@
<p class="text-muted-foreground">Gestión del catálogo de tipos de moneda múltiple</p>
</div>
<div class="flex items-center gap-3">
<Button variant="outline" size="sm" class="h-9" onclick={reloadData}>
<RefreshCw class="mr-2 h-4 w-4" />
<Button variant="outline" size="sm" class="h-9" onclick={reloadData} disabled={loading}>
<RefreshCw class="mr-2 h-4 w-4 {loading ? 'animate-spin' : ''}" />
Actualizar
</Button>
{#if !isError && canCreate}