Arquitectura híbrida con BD compartida o dedicada según necesidades
Seguridad
Autenticación con Keycloak y control de acceso basado en roles
Licencias
Planes flexibles desde Free hasta Enterprise con features personalizadas
+
+
+
+
+
diff --git a/frontend/src/lib/components/dashboard/exchange_rate/create-edit-dialog.svelte b/frontend/src/lib/components/dashboard/exchange_rate/create-edit-dialog.svelte
index f19312c0..de77a2d1 100644
--- a/frontend/src/lib/components/dashboard/exchange_rate/create-edit-dialog.svelte
+++ b/frontend/src/lib/components/dashboard/exchange_rate/create-edit-dialog.svelte
@@ -119,7 +119,14 @@
const companyId = companyStore.activeCompany?.id;
if (!companyId) throw new Error('No hay una compañía seleccionada');
if (!formData.date) throw new Error('La fecha es requerida');
- if (formData.value === null) throw new Error('El valor es requerido');
+ if (
+ formData.value === null ||
+ formData.value === undefined ||
+ String(formData.value).trim() === ''
+ )
+ throw new Error('El tipo de cambio es requerido');
+ if (Number(formData.value) <= 0)
+ throw new Error('El tipo de cambio debe ser un valor mayor a 0');
showConfirmation = true;
} catch (e) {
diff --git a/frontend/src/lib/components/dashboard/invoices/create-edit-dialog.svelte b/frontend/src/lib/components/dashboard/invoices/create-edit-dialog.svelte
index c6a4e708..4237c5e9 100644
--- a/frontend/src/lib/components/dashboard/invoices/create-edit-dialog.svelte
+++ b/frontend/src/lib/components/dashboard/invoices/create-edit-dialog.svelte
@@ -181,6 +181,20 @@
return;
}
+ // Validar tipo de cambio
+ if (
+ formData.exchange_rate === null ||
+ formData.exchange_rate === undefined ||
+ String(formData.exchange_rate).trim() === ''
+ ) {
+ error = 'El tipo de cambio es requerido (pestaña Financieros)';
+ return;
+ }
+ if (Number(formData.exchange_rate) <= 0) {
+ error = 'El tipo de cambio debe ser mayor a 0 (pestaña Financieros)';
+ return;
+ }
+
loading = true;
error = null;
diff --git a/frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.svelte b/frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.svelte
index ccd4acc7..6fa87ac2 100644
--- a/frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.svelte
+++ b/frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.svelte
@@ -433,6 +433,31 @@
}
}
+ // Validar tipo de cambio en create y update
+ if (generalFormData) {
+ const rate = generalFormData.exchange_rate;
+ if (
+ rate === null ||
+ rate === undefined ||
+ String(rate).trim() === '' ||
+ Number(rate) <= 0
+ ) {
+ saving = false;
+ activeTab = 'general';
+ const date = generalFormData.entry_date || '';
+ toast.error(
+ Number(rate) <= 0 && rate !== null && rate !== undefined
+ ? 'El tipo de cambio debe ser mayor a 0. Registra el tipo de cambio para la fecha de entrada.'
+ : 'No hay tipo de cambio registrado para la fecha de entrada. Por favor, regístralo antes de guardar.'
+ );
+ if (date) {
+ missingExchangeRateDate = date;
+ showExchangeRateDialog = true;
+ }
+ return;
+ }
+ }
+
// Construir el payload unificado
const payload: any = {
// Datos generales