feat: Update API endpoints to ensure trailing slashes and adjust data types in models
This commit is contained in:
@@ -388,7 +388,7 @@ class TenantCRUDRoutes(
|
||||
update_schema = self.update_schema
|
||||
|
||||
@self.router.put(
|
||||
f"/{{{self.id_name}}}",
|
||||
f"/{{{self.id_name}}}/",
|
||||
response_model=self.response_schema,
|
||||
summary=f"Update {self.resource_name}",
|
||||
description=f"Update an existing {self.resource_name} by {self.id_name}",
|
||||
|
||||
@@ -24,7 +24,7 @@ class PedimentoDatesBase(BaseModel):
|
||||
class PedimentoDatesCreate(BaseModel):
|
||||
"""Schema for creating a new Pedimento Dates - pedimento_id and tenant_id are set by backend"""
|
||||
|
||||
entry_date: Optional[datetime] = Field(None, description="Entry date")
|
||||
entry_date: datetime = Field(..., description="Entry date")
|
||||
pedimento_date: Optional[datetime] = Field(None, description="Pedimento date")
|
||||
payment_date: datetime = Field(..., description="Payment date")
|
||||
rectification_payment_date: Optional[datetime] = Field(None, description="Rectification payment date")
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from api.v1.common.base_models import TenantScopedMixin, TimestampMixin
|
||||
from core.database import Base
|
||||
from sqlalchemy import (
|
||||
Boolean,
|
||||
ForeignKeyConstraint,
|
||||
Integer,
|
||||
PrimaryKeyConstraint,
|
||||
SmallInteger,
|
||||
String,
|
||||
UniqueConstraint,
|
||||
)
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
@@ -38,12 +37,12 @@ class PedimentoConfigAdditional(Base, TenantScopedMixin, TimestampMixin):
|
||||
id: Mapped[int] = mapped_column(Integer)
|
||||
pedimento_id: Mapped[int] = mapped_column(Integer, nullable=False)
|
||||
|
||||
add_po_identifier: Mapped[int] = mapped_column(SmallInteger)
|
||||
do_not_exempt_norms_complement_x: Mapped[int] = mapped_column(SmallInteger)
|
||||
manual_pedimento_year: Mapped[str] = mapped_column(String(2))
|
||||
enable_import_invoice_recipient: Mapped[int] = mapped_column(SmallInteger)
|
||||
send_502_validation_file_for_consolidated: Mapped[int] = mapped_column(SmallInteger)
|
||||
add_remove_norms: Mapped[int] = mapped_column(SmallInteger)
|
||||
add_po_identifier: Mapped[bool] = mapped_column(Boolean)
|
||||
do_not_exempt_norms_complement_x: Mapped[bool] = mapped_column(Boolean)
|
||||
manual_pedimento_year: Mapped[Optional[int]] = mapped_column(Integer)
|
||||
enable_import_invoice_recipient: Mapped[bool] = mapped_column(Boolean)
|
||||
send_502_validation_file_for_consolidated: Mapped[bool] = mapped_column(Boolean)
|
||||
add_remove_norms: Mapped[bool] = mapped_column(Boolean)
|
||||
|
||||
pedimento: Mapped["Pedimentos"] = relationship(
|
||||
"Pedimentos", back_populates="pedimento_config_additional"
|
||||
|
||||
@@ -3,6 +3,7 @@ from typing import TYPE_CHECKING
|
||||
from api.v1.common.base_models import TenantScopedMixin, TimestampMixin
|
||||
from core.database import Base
|
||||
from sqlalchemy import (
|
||||
Boolean,
|
||||
ForeignKeyConstraint,
|
||||
Integer,
|
||||
PrimaryKeyConstraint,
|
||||
@@ -37,12 +38,12 @@ class PedimentoConfigSurcharges(Base, TenantScopedMixin, TimestampMixin):
|
||||
id: Mapped[int] = mapped_column(Integer)
|
||||
pedimento_id: Mapped[int] = mapped_column(Integer, nullable=False)
|
||||
|
||||
surcharge_igi: Mapped[int] = mapped_column(SmallInteger)
|
||||
surcharge_dta: Mapped[int] = mapped_column(SmallInteger)
|
||||
surcharge_vat: Mapped[int] = mapped_column(SmallInteger)
|
||||
surcharge_isan: Mapped[int] = mapped_column(SmallInteger)
|
||||
surcharge_ieps: Mapped[int] = mapped_column(SmallInteger)
|
||||
surcharge_cc: Mapped[int] = mapped_column(SmallInteger)
|
||||
surcharge_igi: Mapped[bool] = mapped_column(Boolean)
|
||||
surcharge_dta: Mapped[bool] = mapped_column(Boolean)
|
||||
surcharge_vat: Mapped[bool] = mapped_column(Boolean)
|
||||
surcharge_isan: Mapped[bool] = mapped_column(Boolean)
|
||||
surcharge_ieps: Mapped[bool] = mapped_column(Boolean)
|
||||
surcharge_cc: Mapped[bool] = mapped_column(Boolean)
|
||||
|
||||
pedimento: Mapped["Pedimentos"] = relationship(
|
||||
"Pedimentos", back_populates="pedimento_config_surcharges"
|
||||
|
||||
@@ -110,7 +110,7 @@ export const clientsProvidersApi = {
|
||||
}
|
||||
|
||||
return api.get<ClientProviderListResponse>(
|
||||
`/v1/a76/clients-providers?${params.toString()}`
|
||||
`/v1/a76/clients-providers/?${params.toString()}`
|
||||
);
|
||||
},
|
||||
|
||||
@@ -138,7 +138,7 @@ export const clientsProvidersApi = {
|
||||
* @param data - Datos del cliente/proveedor a crear
|
||||
*/
|
||||
create: (companyId: number, data: CreateClientProviderData) =>
|
||||
api.post<ClientProvider>(`/v1/a76/clients-providers?company_id=${companyId}`, data),
|
||||
api.post<ClientProvider>(`/v1/a76/clients-providers/?company_id=${companyId}`, data),
|
||||
|
||||
/**
|
||||
* Actualiza un cliente/proveedor existente
|
||||
@@ -156,7 +156,7 @@ export const clientsProvidersApi = {
|
||||
*/
|
||||
toggleStatus: (id: number, companyId: number) =>
|
||||
api.put<ClientProvider>(
|
||||
`/v1/a76/clients-providers/${id}/toggle-status?company_id=${companyId}`,
|
||||
`/v1/a76/clients-providers/${id}/toggle-status/?company_id=${companyId}`,
|
||||
{}
|
||||
),
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ export const customsBrokersApi = {
|
||||
* Lista todos los agentes aduanales
|
||||
*/
|
||||
list: (companyId: string) => {
|
||||
return api.get<CustomsBroker[]>(`/v1/a76/customs-brokers?company_id=${companyId}`);
|
||||
return api.get<CustomsBroker[]>(`/v1/a76/customs-brokers/?company_id=${companyId}`);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -104,7 +104,7 @@ export const customsBrokersApi = {
|
||||
*/
|
||||
create: (data: CreateCustomsBrokerData) => {
|
||||
const companyId = data.company_id;
|
||||
return api.post<CustomsBroker>(`/v1/a76/customs-brokers?company_id=${companyId}`, data);
|
||||
return api.post<CustomsBroker>(`/v1/a76/customs-brokers/?company_id=${companyId}`, data);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -76,7 +76,7 @@ export const itemsApi = {
|
||||
const params = new URLSearchParams({
|
||||
company_id: companyId.toString()
|
||||
});
|
||||
return api.get<ItemListResponse>(`/v1/a76/items/invoice/${invoiceId}/items?${params.toString()}`);
|
||||
return api.get<ItemListResponse>(`/v1/a76/items/invoice/${invoiceId}/items/?${params.toString()}`);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -86,7 +86,7 @@ export const itemsApi = {
|
||||
const params = new URLSearchParams({
|
||||
company_id: companyId.toString()
|
||||
});
|
||||
return api.get<Item>(`/v1/a76/items/${itemId}?${params.toString()}`);
|
||||
return api.get<Item>(`/v1/a76/items/${itemId}/?${params.toString()}`);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -106,7 +106,7 @@ export const itemsApi = {
|
||||
const params = new URLSearchParams({
|
||||
company_id: companyId.toString()
|
||||
});
|
||||
return api.put<Item>(`/v1/a76/items/${itemId}?${params.toString()}`, data);
|
||||
return api.put<Item>(`/v1/a76/items/${itemId}/?${params.toString()}`, data);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -116,6 +116,6 @@ export const itemsApi = {
|
||||
const params = new URLSearchParams({
|
||||
company_id: companyId.toString()
|
||||
});
|
||||
return api.delete(`/v1/a76/items/${itemId}?${params.toString()}`);
|
||||
return api.delete(`/v1/a76/items/${itemId}/?${params.toString()}`);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -276,7 +276,7 @@ export const pedimentosApi = {
|
||||
* @param companyId - ID de la compañía (por defecto 1)
|
||||
*/
|
||||
list: (page = 1, pageSize = 50, filters?: PedimentoFilters, companyId = 1) => {
|
||||
let url = `/v1/a76/pedimentos?company_id=${companyId}&page=${page}&page_size=${pageSize}`;
|
||||
let url = `/v1/a76/pedimentos/?company_id=${companyId}&page=${page}&page_size=${pageSize}`;
|
||||
|
||||
if (filters?.status) {
|
||||
url += `&status=${encodeURIComponent(filters.status)}`;
|
||||
@@ -296,7 +296,7 @@ export const pedimentosApi = {
|
||||
* @param id - ID del pedimento
|
||||
* @param companyId - ID de la compañía (por defecto 1)
|
||||
*/
|
||||
get: (id: number, companyId = 1) => api.get<Pedimento>(`/v1/a76/pedimentos/${id}?company_id=${companyId}`),
|
||||
get: (id: number, companyId = 1) => api.get<Pedimento>(`/v1/a76/pedimentos/${id}/?company_id=${companyId}`),
|
||||
|
||||
/**
|
||||
* Crea un nuevo pedimento
|
||||
@@ -304,7 +304,7 @@ export const pedimentosApi = {
|
||||
* @param companyId - ID de la compañía (por defecto 1)
|
||||
*/
|
||||
create: (data: CreatePedimentoData, companyId = 1) =>
|
||||
api.post<Pedimento>(`/v1/a76/pedimentos?company_id=${companyId}`, data),
|
||||
api.post<Pedimento>(`/v1/a76/pedimentos/?company_id=${companyId}`, data),
|
||||
|
||||
/**
|
||||
* Actualiza un pedimento existente
|
||||
@@ -313,12 +313,12 @@ export const pedimentosApi = {
|
||||
* @param companyId - ID de la compañía (por defecto 1)
|
||||
*/
|
||||
update: (id: number, data: UpdatePedimentoData, companyId = 1) =>
|
||||
api.put<Pedimento>(`/v1/a76/pedimentos/${id}?company_id=${companyId}`, data),
|
||||
api.put<Pedimento>(`/v1/a76/pedimentos/${id}/?company_id=${companyId}`, data),
|
||||
|
||||
/**
|
||||
* Elimina un pedimento
|
||||
* @param id - ID del pedimento a eliminar
|
||||
* @param companyId - ID de la compañía (por defecto 1)
|
||||
*/
|
||||
delete: (id: number, companyId = 1) => api.delete(`/v1/a76/pedimentos/${id}?company_id=${companyId}`)
|
||||
delete: (id: number, companyId = 1) => api.delete(`/v1/a76/pedimentos/${id}/?company_id=${companyId}`)
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import * as Card from '$lib/components/ui/card';
|
||||
import { Input } from '$lib/components/ui/input';
|
||||
import { Label } from '$lib/components/ui/label';
|
||||
@@ -66,6 +67,10 @@
|
||||
{ value: 2, label: 'Importación' },
|
||||
];
|
||||
|
||||
// Track previous values to detect changes
|
||||
let previousPedimentoCode = $state('');
|
||||
let previousOperationType = $state<number | null>(null);
|
||||
|
||||
// Opciones filtradas para Régimen y Tipo de Operación basadas en las selecciones actuales
|
||||
// NOTA: La Clave NO se filtra, siempre muestra todas las opciones
|
||||
|
||||
@@ -104,11 +109,7 @@
|
||||
return operationOptions.filter(opt => validTypes.has(opt.value));
|
||||
}
|
||||
return operationOptions;
|
||||
});
|
||||
|
||||
// Track previous values to detect changes
|
||||
let previousPedimentoCode = $state(formData?.pedimento_code || '');
|
||||
let previousOperationType = $state(formData?.operation_type ?? null);
|
||||
});
|
||||
|
||||
// Reactive synchronization between Clave, Régimen, and Tipo de Operación
|
||||
// REGLA: La Clave es el campo principal y NUNCA se modifica automáticamente
|
||||
@@ -204,10 +205,8 @@
|
||||
});
|
||||
|
||||
// Obtener el año actual (últimos 2 dígitos)
|
||||
const currentYear = String(new Date().getFullYear()).slice(-2);
|
||||
|
||||
// Obtener fecha y hora actual para captura
|
||||
const now = new Date();
|
||||
const currentYear = String(now.getFullYear()).slice(-2);
|
||||
const currentDate = now.toISOString().substring(0, 10); // YYYY-MM-DD
|
||||
const currentTime = now.toTimeString().substring(0, 5); // HH:MM
|
||||
|
||||
@@ -250,16 +249,12 @@
|
||||
});
|
||||
|
||||
// Obtener automáticamente el tipo de cambio cuando cambie la fecha de entrada
|
||||
$effect(() => {
|
||||
if (formData && formData.entry_date && companyStore.activeCompany) {
|
||||
console.log('🔍 [TIPO CAMBIO] Buscando para fecha:', formData.entry_date, 'Company ID:', companyStore.activeCompany.id);
|
||||
|
||||
onMount(() => {
|
||||
if (formData && formData.entry_date && companyStore.activeCompany) {
|
||||
getExchangeRateByDate(formData.entry_date, companyStore.activeCompany.id)
|
||||
.then(usdRate => {
|
||||
console.log('✅ [TIPO CAMBIO] Respuesta recibida:', usdRate);
|
||||
.then(usdRate => {
|
||||
if (usdRate && formData) {
|
||||
formData.exchange_rate = usdRate.value;
|
||||
console.log('✅ [TIPO CAMBIO] Actualizado a:', usdRate.value);
|
||||
formData.exchange_rate = usdRate.value;
|
||||
} else {
|
||||
console.warn('⚠️ [TIPO CAMBIO] No encontrado para fecha:', formData.entry_date);
|
||||
}
|
||||
@@ -267,9 +262,7 @@
|
||||
.catch(err => {
|
||||
console.error('❌ [TIPO CAMBIO] Error:', err);
|
||||
});
|
||||
} else {
|
||||
console.log('⏭️ [TIPO CAMBIO] Saltado - formData:', !!formData, 'entry_date:', formData?.entry_date, 'company:', !!companyStore.activeCompany);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const statusOptions = [
|
||||
@@ -750,7 +743,7 @@
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
<!-- Fecha de Entrada -->
|
||||
<div class="space-y-2">
|
||||
<Label for="entry_date">Fecha de Entrada</Label>
|
||||
<Label for="entry_date">Fecha de Entrada <span class="text-red-500">*</span></Label>
|
||||
<Input
|
||||
id="entry_date"
|
||||
type="date"
|
||||
@@ -800,7 +793,7 @@
|
||||
|
||||
<!-- Fecha de Pago -->
|
||||
<div class="space-y-2">
|
||||
<Label for="payment_date">Fecha de Pago</Label>
|
||||
<Label for="payment_date">Fecha de Pago <span class="text-red-500">*</span></Label>
|
||||
<Input
|
||||
id="payment_date"
|
||||
type="date"
|
||||
|
||||
@@ -434,8 +434,7 @@
|
||||
update_dta: otrosDatosFormData.actualizar_dta || false,
|
||||
update_cc: otrosDatosFormData.actualizar_cc || false,
|
||||
update_ieps: otrosDatosFormData.actualizar_ieps || false
|
||||
};
|
||||
console.log('📤 Enviando pedimento_config_updates:', payload.pedimento_config_updates);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user