diff --git a/app/api/dolibarr/[...path]/route.ts b/app/api/dolibarr/[...path]/route.ts index 857c845..e87720f 100644 --- a/app/api/dolibarr/[...path]/route.ts +++ b/app/api/dolibarr/[...path]/route.ts @@ -27,8 +27,19 @@ export async function GET( ); } - // Construir URL completa - const url = `${apiUrl}/${endpoint}?DOLAPIKEY=${apiKey}`; + // Construir URL completa (soporta query params en el endpoint + request) + const [baseEndpoint, queryString] = endpoint.split('?'); + let url = `${apiUrl}/${baseEndpoint}?DOLAPIKEY=${apiKey}`; + if (queryString) { + url += `&${queryString}`; + } + // Reenviar query params de la request original (para client-side) + const searchParams = request.nextUrl.searchParams; + searchParams.forEach((value, key) => { + if (key !== 'DOLAPIKEY') { + url += `&${encodeURIComponent(key)}=${encodeURIComponent(value)}`; + } + }); // Realizar la petición a Dolibarr const response = await fetch(url, { @@ -86,7 +97,11 @@ export async function POST( ); } - const url = `${apiUrl}/${endpoint}?DOLAPIKEY=${apiKey}`; + const [baseEndpoint, queryString] = endpoint.split('?'); + let url = `${apiUrl}/${baseEndpoint}?DOLAPIKEY=${apiKey}`; + if (queryString) { + url += `&${queryString}`; + } const response = await fetch(url, { method: 'POST', @@ -158,7 +173,11 @@ export async function PUT( ); } - const url = `${apiUrl}/${endpoint}?DOLAPIKEY=${apiKey}`; + const [baseEndpoint, queryString] = endpoint.split('?'); + let url = `${apiUrl}/${baseEndpoint}?DOLAPIKEY=${apiKey}`; + if (queryString) { + url += `&${queryString}`; + } const response = await fetch(url, { method: 'PUT', @@ -227,7 +246,11 @@ export async function DELETE( ); } - const url = `${apiUrl}/${endpoint}?DOLAPIKEY=${apiKey}`; + const [baseEndpoint, queryString] = endpoint.split('?'); + let url = `${apiUrl}/${baseEndpoint}?DOLAPIKEY=${apiKey}`; + if (queryString) { + url += `&${queryString}`; + } const response = await fetch(url, { method: 'DELETE', diff --git a/lib/dolibarrClient.ts b/lib/dolibarrClient.ts index d60a202..bf4024b 100644 --- a/lib/dolibarrClient.ts +++ b/lib/dolibarrClient.ts @@ -19,7 +19,11 @@ async function dolibarrDirectFetch(endpoint: string, options: RequestInit = {}) throw new Error('Dolibarr configuration missing (DOLIBARR_API_URL or DOLIBARR_API_KEY)'); } - const url = `${apiUrl}/${endpoint}?DOLAPIKEY=${apiKey}`; + const [baseEndpoint, queryString] = endpoint.split('?'); + let url = `${apiUrl}/${baseEndpoint}?DOLAPIKEY=${apiKey}`; + if (queryString) { + url += `&${queryString}`; + } const res = await fetch(url, { ...options, diff --git a/lib/tasksService.ts b/lib/tasksService.ts index bc8bced..fe2fcb0 100644 --- a/lib/tasksService.ts +++ b/lib/tasksService.ts @@ -13,11 +13,14 @@ import { * * Nota: El endpoint /projects/{id}/tasks de Dolibarr no devuelve tareas correctamente, * por lo que obtenemos todas las tareas y filtramos por fk_project en el cliente. + * Se usa limit=10000 para evitar problemas de paginación por defecto (100). */ export async function getTasksByProjectId(projectId: number): Promise { try { - // Obtener todas las tareas (Dolibarr no filtra bien por proyecto) - const dolibarrTasks: DolibarrTask[] = await dolibarrFetch('tasks'); + // Usar limit alto + sortfield para obtener todas las tareas y evitar paginación + const dolibarrTasks: DolibarrTask[] = await dolibarrFetch( + `tasks?limit=10000&sortfield=t.rowid&sortorder=ASC` + ); // Si no hay tareas, devolver array vacío if (!dolibarrTasks || !Array.isArray(dolibarrTasks)) { @@ -47,7 +50,9 @@ export async function getTasksByProjectId(projectId: number): Promise { */ export async function getAllTasks(): Promise { try { - const dolibarrTasks: DolibarrTask[] = await dolibarrFetch('tasks'); + const dolibarrTasks: DolibarrTask[] = await dolibarrFetch( + 'tasks?limit=10000&sortfield=t.rowid&sortorder=ASC' + ); if (!dolibarrTasks || !Array.isArray(dolibarrTasks)) { return []; diff --git a/presentaciones/marcos/Canva.txt b/presentaciones/marcos/Canva.txt index b10b07c..3e56b20 100644 --- a/presentaciones/marcos/Canva.txt +++ b/presentaciones/marcos/Canva.txt @@ -1 +1 @@ -https://canva.link/rvvkr8loc8gx8v1 +https://canva.link/####rvvkr8loc8gx8v1