335 lines
10 KiB
JavaScript
335 lines
10 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Script para crear tareas de prueba en proyectos de Dolibarr
|
|
*
|
|
* REQUISITO: El servidor de Next.js debe estar corriendo (npm run dev)
|
|
* Uso: node scripts/seed-tasks.js
|
|
*/
|
|
|
|
const NEXT_API_URL = 'http://localhost:3000/api/dolibarr';
|
|
|
|
// Plantillas de tareas variadas para cada proyecto
|
|
const taskTemplates = [
|
|
// Tareas de análisis/planificación
|
|
{
|
|
label: "Análisis de requisitos",
|
|
description: "Documentar todos los requisitos funcionales y no funcionales del proyecto con el cliente.",
|
|
planned_workload: 28800, // 8 horas en segundos
|
|
progress: 100,
|
|
priority: 2,
|
|
},
|
|
{
|
|
label: "Diseño de arquitectura",
|
|
description: "Definir la arquitectura técnica, selección de tecnologías y patrones de diseño a utilizar.",
|
|
planned_workload: 36000, // 10 horas
|
|
progress: 100,
|
|
priority: 3,
|
|
},
|
|
{
|
|
label: "Creación de wireframes",
|
|
description: "Diseñar los wireframes y mockups de las principales pantallas de la aplicación.",
|
|
planned_workload: 21600, // 6 horas
|
|
progress: 80,
|
|
priority: 2,
|
|
},
|
|
// Tareas de desarrollo
|
|
{
|
|
label: "Configuración del entorno de desarrollo",
|
|
description: "Preparar repositorio, CI/CD, entornos de desarrollo y staging.",
|
|
planned_workload: 14400, // 4 horas
|
|
progress: 100,
|
|
priority: 3,
|
|
},
|
|
{
|
|
label: "Desarrollo del backend",
|
|
description: "Implementar la API REST, modelos de datos y lógica de negocio del servidor.",
|
|
planned_workload: 72000, // 20 horas
|
|
progress: 60,
|
|
priority: 3,
|
|
},
|
|
{
|
|
label: "Desarrollo del frontend",
|
|
description: "Implementar la interfaz de usuario con componentes, estados y conexión con API.",
|
|
planned_workload: 64800, // 18 horas
|
|
progress: 45,
|
|
priority: 3,
|
|
},
|
|
{
|
|
label: "Integración con servicios externos",
|
|
description: "Conectar con APIs de terceros, pasarelas de pago y servicios cloud.",
|
|
planned_workload: 28800, // 8 horas
|
|
progress: 30,
|
|
priority: 2,
|
|
},
|
|
// Tareas de testing
|
|
{
|
|
label: "Pruebas unitarias",
|
|
description: "Escribir y ejecutar tests unitarios para componentes críticos del sistema.",
|
|
planned_workload: 21600, // 6 horas
|
|
progress: 25,
|
|
priority: 2,
|
|
},
|
|
{
|
|
label: "Pruebas de integración",
|
|
description: "Realizar pruebas de integración entre módulos y con servicios externos.",
|
|
planned_workload: 18000, // 5 horas
|
|
progress: 10,
|
|
priority: 2,
|
|
},
|
|
{
|
|
label: "QA y corrección de bugs",
|
|
description: "Ejecutar plan de QA, documentar bugs encontrados y corregirlos.",
|
|
planned_workload: 36000, // 10 horas
|
|
progress: 0,
|
|
priority: 1,
|
|
},
|
|
// Tareas de documentación
|
|
{
|
|
label: "Documentación técnica",
|
|
description: "Crear documentación de API, guías de instalación y arquitectura del sistema.",
|
|
planned_workload: 14400, // 4 horas
|
|
progress: 15,
|
|
priority: 1,
|
|
},
|
|
{
|
|
label: "Manual de usuario",
|
|
description: "Redactar el manual de usuario con capturas y tutoriales paso a paso.",
|
|
planned_workload: 10800, // 3 horas
|
|
progress: 0,
|
|
priority: 1,
|
|
},
|
|
// Tareas de despliegue
|
|
{
|
|
label: "Configuración de producción",
|
|
description: "Preparar servidores, certificados SSL, dominios y configuraciones de producción.",
|
|
planned_workload: 18000, // 5 horas
|
|
progress: 0,
|
|
priority: 3,
|
|
},
|
|
{
|
|
label: "Despliegue inicial",
|
|
description: "Realizar el despliegue a producción y verificar el correcto funcionamiento.",
|
|
planned_workload: 7200, // 2 horas
|
|
progress: 0,
|
|
priority: 3,
|
|
},
|
|
{
|
|
label: "Formación al cliente",
|
|
description: "Sesión de formación al equipo del cliente sobre el uso del sistema.",
|
|
planned_workload: 10800, // 3 horas
|
|
progress: 0,
|
|
priority: 2,
|
|
},
|
|
];
|
|
|
|
/**
|
|
* Obtener todos los proyectos existentes
|
|
*/
|
|
async function getProjects() {
|
|
const url = `${NEXT_API_URL}/projects`;
|
|
|
|
const response = await fetch(url, {
|
|
method: 'GET',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`Error obteniendo proyectos: ${response.status}`);
|
|
}
|
|
|
|
return response.json();
|
|
}
|
|
|
|
// Contador global para generar refs únicos
|
|
let taskCounter = 0;
|
|
|
|
/**
|
|
* Generar referencia única para una tarea
|
|
*/
|
|
function generateTaskRef(projectId) {
|
|
taskCounter++;
|
|
const timestamp = Date.now().toString(36).toUpperCase();
|
|
return `TASK-P${projectId}-${String(taskCounter).padStart(3, '0')}`;
|
|
}
|
|
|
|
/**
|
|
* Crear una tarea en un proyecto
|
|
*/
|
|
async function createTask(projectId, taskData) {
|
|
const url = `${NEXT_API_URL}/tasks`;
|
|
|
|
// Calcular fechas basadas en la fecha actual
|
|
const now = new Date();
|
|
const startDate = new Date(now);
|
|
startDate.setDate(startDate.getDate() - Math.floor(Math.random() * 30)); // Hace 0-30 días
|
|
|
|
const endDate = new Date(startDate);
|
|
endDate.setDate(endDate.getDate() + Math.floor(Math.random() * 30) + 7); // 7-37 días después
|
|
|
|
const payload = {
|
|
ref: generateTaskRef(projectId), // Campo requerido por Dolibarr
|
|
fk_project: String(projectId), // Dolibarr espera string
|
|
label: taskData.label,
|
|
description: taskData.description,
|
|
planned_workload: taskData.planned_workload,
|
|
progress: taskData.progress,
|
|
priority: taskData.priority,
|
|
dateo: Math.floor(startDate.getTime() / 1000), // Fecha inicio planificada
|
|
datee: Math.floor(endDate.getTime() / 1000), // Fecha fin planificada
|
|
date_start: taskData.progress > 0 ? Math.floor(startDate.getTime() / 1000) : null,
|
|
date_end: taskData.progress >= 100 ? Math.floor(new Date().getTime() / 1000) : null,
|
|
};
|
|
|
|
const response = await fetch(url, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(payload),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const errorData = await response.json().catch(() => ({}));
|
|
throw new Error(`Error ${response.status}: ${errorData.error || 'Unknown error'}`);
|
|
}
|
|
|
|
return response.json();
|
|
}
|
|
|
|
/**
|
|
* Seleccionar tareas aleatorias para un proyecto
|
|
*/
|
|
function selectTasksForProject(projectProgress, count = 6) {
|
|
// Mezclar las tareas aleatoriamente
|
|
const shuffled = [...taskTemplates].sort(() => Math.random() - 0.5);
|
|
|
|
// Seleccionar las primeras 'count' tareas
|
|
const selected = shuffled.slice(0, count);
|
|
|
|
// Ajustar el progreso de las tareas según el progreso del proyecto
|
|
return selected.map((task, index) => {
|
|
let adjustedProgress = task.progress;
|
|
|
|
// Si el proyecto tiene poco progreso, reducir el progreso de las tareas
|
|
if (projectProgress < 30) {
|
|
adjustedProgress = Math.min(task.progress, 30 + Math.random() * 20);
|
|
} else if (projectProgress >= 100) {
|
|
// Si el proyecto está completo, completar más tareas
|
|
adjustedProgress = index < count - 1 ? 100 : Math.max(task.progress, 80);
|
|
} else {
|
|
// Ajustar proporcionalmente
|
|
const factor = projectProgress / 50;
|
|
adjustedProgress = Math.min(100, Math.round(task.progress * factor));
|
|
}
|
|
|
|
return {
|
|
...task,
|
|
progress: Math.round(adjustedProgress),
|
|
};
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Script principal
|
|
*/
|
|
async function main() {
|
|
console.log('\n📋 SEED DE TAREAS PARA PROYECTOS DE DOLIBARR\n');
|
|
console.log('═'.repeat(60));
|
|
console.log(`📡 API Next.js: ${NEXT_API_URL}`);
|
|
console.log(`📝 Plantillas de tareas: ${taskTemplates.length}`);
|
|
console.log('═'.repeat(60));
|
|
console.log('');
|
|
|
|
// Verificar conexión con Next.js
|
|
console.log('🔍 Verificando conexión con Next.js...');
|
|
try {
|
|
const testResponse = await fetch('http://localhost:3000');
|
|
if (!testResponse.ok && testResponse.status !== 404) {
|
|
throw new Error('Server not responding');
|
|
}
|
|
console.log('✅ Servidor Next.js está corriendo\n');
|
|
} catch (error) {
|
|
console.error('❌ ERROR: No se puede conectar al servidor Next.js');
|
|
console.error(' Por favor, ejecuta "npm run dev" en otra terminal primero.\n');
|
|
process.exit(1);
|
|
}
|
|
|
|
// Obtener proyectos existentes
|
|
console.log('📂 Obteniendo proyectos existentes...');
|
|
let projects;
|
|
try {
|
|
projects = await getProjects();
|
|
console.log(`✅ Encontrados ${projects.length} proyectos\n`);
|
|
} catch (error) {
|
|
console.error('❌ Error obteniendo proyectos:', error.message);
|
|
process.exit(1);
|
|
}
|
|
|
|
if (projects.length === 0) {
|
|
console.log('⚠️ No hay proyectos. Ejecuta primero: npm run seed\n');
|
|
process.exit(0);
|
|
}
|
|
|
|
let totalTasks = 0;
|
|
let totalErrors = 0;
|
|
const TASKS_PER_PROJECT = 6;
|
|
|
|
for (let i = 0; i < projects.length; i++) {
|
|
const project = projects[i];
|
|
const projectId = project.id;
|
|
const projectTitle = project.title || project.ref || `Proyecto ${projectId}`;
|
|
const projectProgress = parseFloat(project.opp_percent || '0');
|
|
|
|
console.log(`\n[${i + 1}/${projects.length}] 📁 ${projectTitle}`);
|
|
console.log(` ID: ${projectId} | Progreso: ${projectProgress}%`);
|
|
console.log(' Creando tareas:');
|
|
|
|
// Seleccionar tareas para este proyecto
|
|
const tasksToCreate = selectTasksForProject(projectProgress, TASKS_PER_PROJECT);
|
|
|
|
for (let j = 0; j < tasksToCreate.length; j++) {
|
|
const task = tasksToCreate[j];
|
|
|
|
try {
|
|
const taskId = await createTask(projectId, task);
|
|
const progressBar = '█'.repeat(Math.floor(task.progress / 10)) + '░'.repeat(10 - Math.floor(task.progress / 10));
|
|
console.log(` ✅ [${progressBar}] ${task.progress}% - ${task.label}`);
|
|
totalTasks++;
|
|
|
|
// Pequeña pausa para no saturar la API
|
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
} catch (error) {
|
|
console.log(` ❌ Error: ${task.label} - ${error.message}`);
|
|
totalErrors++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Resumen final
|
|
console.log('\n');
|
|
console.log('═'.repeat(60));
|
|
console.log('✨ PROCESO COMPLETADO\n');
|
|
console.log(`📊 Proyectos procesados: ${projects.length}`);
|
|
console.log(`✅ Tareas creadas: ${totalTasks}`);
|
|
console.log(`❌ Errores: ${totalErrors}`);
|
|
console.log('═'.repeat(60));
|
|
|
|
if (totalTasks > 0) {
|
|
console.log('\n💡 ¡Recarga tu aplicación para ver las tareas!');
|
|
console.log(' Haz clic en cualquier proyecto para ver sus tareas.\n');
|
|
}
|
|
}
|
|
|
|
// Ejecutar
|
|
main().catch(error => {
|
|
console.error('\n❌ ERROR FATAL:', error.message);
|
|
console.error('\nAsegúrate de que:');
|
|
console.error(' 1. El servidor Next.js está corriendo (npm run dev)');
|
|
console.error(' 2. Dolibarr está accesible');
|
|
console.error(' 3. Existen proyectos (ejecuta "npm run seed" primero)\n');
|
|
process.exit(1);
|
|
});
|