2026-01-09 17:39:19 +00:00
|
|
|
// lib/projectsService.ts
|
2025-12-12 12:53:37 +00:00
|
|
|
import { dolibarrFetch } from "./dolibarrClient";
|
2026-01-31 13:50:07 +00:00
|
|
|
import {
|
|
|
|
|
DolibarrProject,
|
|
|
|
|
Project,
|
|
|
|
|
mapDolibarrProject,
|
|
|
|
|
CreateProjectData,
|
|
|
|
|
UpdateProjectData
|
|
|
|
|
} from "@/types/project";
|
2025-12-12 12:53:37 +00:00
|
|
|
|
2026-01-09 17:39:19 +00:00
|
|
|
// Obtener proyectos crudos de Dolibarr
|
|
|
|
|
export async function getDolibarrProjects(): Promise<DolibarrProject[]> {
|
2025-12-12 12:53:37 +00:00
|
|
|
return dolibarrFetch("projects");
|
|
|
|
|
}
|
2026-01-09 17:39:19 +00:00
|
|
|
|
|
|
|
|
// Obtener proyectos mapeados al formato de la UI
|
|
|
|
|
export async function getProjects(): Promise<Project[]> {
|
|
|
|
|
try {
|
|
|
|
|
const dolibarrProjects = await getDolibarrProjects();
|
|
|
|
|
|
|
|
|
|
// Mapear los proyectos de Dolibarr a nuestro formato
|
|
|
|
|
return dolibarrProjects.map(mapDolibarrProject);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error fetching projects from Dolibarr:', error);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Obtener un proyecto específico por ID
|
2026-01-31 13:50:07 +00:00
|
|
|
export async function getProjectById(id: number): Promise<Project | null> {
|
2026-01-09 17:39:19 +00:00
|
|
|
try {
|
2026-01-31 13:50:07 +00:00
|
|
|
const dolibarrProject = await getDolibarrProjectById(id);
|
|
|
|
|
return mapDolibarrProject(dolibarrProject);
|
2026-01-09 17:39:19 +00:00
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error fetching project by id:', error);
|
2026-01-31 13:50:07 +00:00
|
|
|
return null;
|
2026-01-09 17:39:19 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Si necesitas obtener un proyecto específico directamente de Dolibarr
|
|
|
|
|
export async function getDolibarrProjectById(id: number): Promise<DolibarrProject> {
|
|
|
|
|
return dolibarrFetch(`projects/${id}`);
|
2026-01-31 13:50:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ==================== FUNCIONES DE ESCRITURA (CREATE/UPDATE/DELETE) ====================
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Crear un nuevo proyecto
|
|
|
|
|
* Endpoint: POST /projects
|
|
|
|
|
* @returns El proyecto creado con su ID
|
|
|
|
|
*/
|
|
|
|
|
export async function createProject(data: CreateProjectData): Promise<Project> {
|
|
|
|
|
try {
|
|
|
|
|
// Limpiar datos undefined/null para la API
|
|
|
|
|
const cleanData = Object.fromEntries(
|
|
|
|
|
Object.entries(data).filter(([, v]) => v !== undefined && v !== null && v !== '')
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const response = await dolibarrFetch('projects', {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
body: JSON.stringify(cleanData),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Dolibarr devuelve el ID del proyecto creado
|
|
|
|
|
const projectId = typeof response === 'object' ? response.id || response : response;
|
|
|
|
|
|
|
|
|
|
// Obtener el proyecto completo
|
|
|
|
|
const createdProject = await getProjectById(Number(projectId));
|
|
|
|
|
if (!createdProject) {
|
|
|
|
|
throw new Error('No se pudo obtener el proyecto creado');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return createdProject;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error creating project:', error);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Actualizar un proyecto existente
|
|
|
|
|
* Endpoint: PUT /projects/{id}
|
|
|
|
|
* @returns El proyecto actualizado
|
|
|
|
|
*/
|
|
|
|
|
export async function updateProject(projectId: number, data: UpdateProjectData): Promise<Project> {
|
|
|
|
|
try {
|
|
|
|
|
// Limpiar datos undefined/null para la API
|
|
|
|
|
const cleanData = Object.fromEntries(
|
|
|
|
|
Object.entries(data).filter(([, v]) => v !== undefined && v !== null)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await dolibarrFetch(`projects/${projectId}`, {
|
|
|
|
|
method: 'PUT',
|
|
|
|
|
body: JSON.stringify(cleanData),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Obtener el proyecto actualizado
|
|
|
|
|
const updatedProject = await getProjectById(projectId);
|
|
|
|
|
if (!updatedProject) {
|
|
|
|
|
throw new Error('No se pudo obtener el proyecto actualizado');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return updatedProject;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error updating project:', projectId, error);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Eliminar un proyecto
|
|
|
|
|
* Endpoint: DELETE /projects/{id}
|
|
|
|
|
*/
|
|
|
|
|
export async function deleteProject(projectId: number): Promise<void> {
|
|
|
|
|
try {
|
|
|
|
|
await dolibarrFetch(`projects/${projectId}`, {
|
|
|
|
|
method: 'DELETE',
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error deleting project:', projectId, error);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Validar (cambiar estado a 1 - abierto) un proyecto
|
|
|
|
|
* Endpoint: POST /projects/{id}/validate
|
|
|
|
|
*/
|
|
|
|
|
export async function validateProject(projectId: number): Promise<Project> {
|
|
|
|
|
try {
|
|
|
|
|
await dolibarrFetch(`projects/${projectId}/validate`, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
body: JSON.stringify({ notrigger: 0 }),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const project = await getProjectById(projectId);
|
|
|
|
|
if (!project) {
|
|
|
|
|
throw new Error('No se pudo obtener el proyecto validado');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return project;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error validating project:', projectId, error);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Cerrar un proyecto (cambiar estado a 2)
|
|
|
|
|
* Endpoint: POST /projects/{id}/close
|
|
|
|
|
*/
|
|
|
|
|
export async function closeProject(projectId: number): Promise<Project> {
|
|
|
|
|
try {
|
|
|
|
|
await dolibarrFetch(`projects/${projectId}/close`, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
body: JSON.stringify({ notrigger: 0 }),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const project = await getProjectById(projectId);
|
|
|
|
|
if (!project) {
|
|
|
|
|
throw new Error('No se pudo obtener el proyecto cerrado');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return project;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error closing project:', projectId, error);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
2026-01-09 17:39:19 +00:00
|
|
|
}
|