#!/usr/bin/env node /** * Script para crear proyectos de prueba en Dolibarr llamando directamente a la API * NO requiere que Next.js esté corriendo * * Uso: node scripts/seed-projects-direct.js */ // Configuración - lee de .env.local o usa valores por defecto const fs = require('fs'); const path = require('path'); // Leer .env.local function loadEnv() { const envPath = path.join(__dirname, '..', '.env.local'); const env = {}; try { const content = fs.readFileSync(envPath, 'utf8'); content.split('\n').forEach(line => { const [key, ...valueParts] = line.split('='); if (key && valueParts.length > 0) { env[key.trim()] = valueParts.join('=').trim(); } }); } catch (e) { console.error('Error leyendo .env.local:', e.message); } return env; } const env = loadEnv(); const DOLIBARR_API_URL = env.NEXT_PUBLIC_API_URL || 'http://localhost:8200/api/index.php'; const DOLIBARR_API_KEY = env.NEXT_PUBLIC_DOLIBARR_API_KEY || ''; if (!DOLIBARR_API_KEY) { console.error('❌ ERROR: No se encontró NEXT_PUBLIC_DOLIBARR_API_KEY en .env.local'); process.exit(1); } // Nombres de clientes para asignar aleatoriamente const clientNames = [ "TechCorp Solutions", "Innovatech S.L.", "Digital Factory", "CloudBase Systems", "DataPrime Analytics", "WebMasters Pro", "AppDev Studio", "CyberTech Security", "SmartBiz Solutions", "NextGen Software" ]; // Datos de proyectos de ejemplo con variedad de estados y presupuestos const projectsData = [ { title: "Desarrollo de App Movil", ref: "PROJ-2025-001", description: "Aplicacion movil para gestion de inventario con funcionalidades de escaneo QR y sincronizacion en tiempo real.", opp_amount: 45000, opp_percent: 65, date_start: Math.floor(new Date('2025-01-15').getTime() / 1000), date_end: Math.floor(new Date('2025-06-30').getTime() / 1000), }, { title: "Rediseno Web Corporativo", ref: "PROJ-2025-002", description: "Renovacion completa del sitio web corporativo con nuevo diseno responsive y optimizacion SEO.", opp_amount: 28000, opp_percent: 90, date_start: Math.floor(new Date('2024-11-01').getTime() / 1000), date_end: Math.floor(new Date('2025-02-28').getTime() / 1000), }, { title: "Sistema de Facturacion Automatica", ref: "PROJ-2025-003", description: "Desarrollo de sistema automatizado para generacion y envio de facturas con integracion a contabilidad.", opp_amount: 62000, opp_percent: 35, date_start: Math.floor(new Date('2025-02-01').getTime() / 1000), date_end: Math.floor(new Date('2025-08-31').getTime() / 1000), }, { title: "Migracion a Cloud AWS", ref: "PROJ-2025-004", description: "Migracion completa de infraestructura on-premise a AWS con configuracion de alta disponibilidad.", opp_amount: 85000, opp_percent: 20, date_start: Math.floor(new Date('2025-03-01').getTime() / 1000), date_end: Math.floor(new Date('2025-12-31').getTime() / 1000), }, { title: "Dashboard Analitico BI", ref: "PROJ-2025-005", description: "Creacion de dashboard de Business Intelligence para analisis de ventas y KPIs en tiempo real.", opp_amount: 38000, opp_percent: 100, date_start: Math.floor(new Date('2024-09-01').getTime() / 1000), date_end: Math.floor(new Date('2024-12-15').getTime() / 1000), status: 2, // Cerrado }, { title: "API REST Microservicios", ref: "PROJ-2025-006", description: "Desarrollo de arquitectura de microservicios con API REST para integracion de sistemas legacy.", opp_amount: 72000, opp_percent: 50, date_start: Math.floor(new Date('2025-01-20').getTime() / 1000), date_end: Math.floor(new Date('2025-07-31').getTime() / 1000), }, { title: "App de Gestion de Proyectos", ref: "PROJ-2025-007", description: "Plataforma web para gestion agil de proyectos con tableros Kanban, Gantt y reporting automatico.", opp_amount: 55000, opp_percent: 75, date_start: Math.floor(new Date('2024-12-01').getTime() / 1000), date_end: Math.floor(new Date('2025-05-31').getTime() / 1000), }, { title: "E-commerce con Marketplace", ref: "PROJ-2025-008", description: "Plataforma de e-commerce completa con funcionalidad de marketplace multivendedor y pasarela de pagos.", opp_amount: 120000, opp_percent: 15, date_start: Math.floor(new Date('2025-04-01').getTime() / 1000), date_end: Math.floor(new Date('2026-03-31').getTime() / 1000), }, { title: "Sistema CRM Personalizado", ref: "PROJ-2025-009", description: "CRM a medida con automatizacion de marketing, gestion de leads y pipeline de ventas.", opp_amount: 48000, opp_percent: 0, date_start: Math.floor(new Date('2025-05-01').getTime() / 1000), date_end: Math.floor(new Date('2025-11-30').getTime() / 1000), }, { title: "Portal de Empleados", ref: "PROJ-2025-010", description: "Portal interno para empleados con gestion de vacaciones, nominas, formacion y comunicacion interna.", opp_amount: 35000, opp_percent: 100, date_start: Math.floor(new Date('2024-10-01').getTime() / 1000), date_end: Math.floor(new Date('2024-12-31').getTime() / 1000), status: 2, // Cerrado }, { title: "Sistema de Reservas Online", ref: "PROJ-2025-011", description: "Plataforma de reservas con calendario interactivo, confirmacion automatica y pasarela de pago.", opp_amount: 42000, opp_percent: 45, date_start: Math.floor(new Date('2025-02-15').getTime() / 1000), date_end: Math.floor(new Date('2025-07-15').getTime() / 1000), }, { title: "App de Formacion Online", ref: "PROJ-2025-012", description: "Plataforma LMS para formacion online con seguimiento de progreso, certificados y evaluaciones.", opp_amount: 68000, opp_percent: 30, date_start: Math.floor(new Date('2025-03-10').getTime() / 1000), date_end: Math.floor(new Date('2025-10-31').getTime() / 1000), }, { title: "Automatizacion de Procesos RPA", ref: "PROJ-2025-013", description: "Implementacion de robots de automatizacion para procesos administrativos repetitivos.", opp_amount: 95000, opp_percent: 10, date_start: Math.floor(new Date('2025-06-01').getTime() / 1000), date_end: Math.floor(new Date('2026-02-28').getTime() / 1000), }, { title: "Plataforma IoT Industrial", ref: "PROJ-2025-014", description: "Sistema de monitoreo IoT para maquinaria industrial con alertas predictivas y mantenimiento.", opp_amount: 150000, opp_percent: 5, date_start: Math.floor(new Date('2025-07-01').getTime() / 1000), date_end: Math.floor(new Date('2026-06-30').getTime() / 1000), }, { title: "Chatbot con IA", ref: "PROJ-2025-015", description: "Desarrollo de chatbot inteligente para atencion al cliente con procesamiento de lenguaje natural.", opp_amount: 32000, opp_percent: 80, date_start: Math.floor(new Date('2024-11-15').getTime() / 1000), date_end: Math.floor(new Date('2025-03-15').getTime() / 1000), }, ]; /** * Llamar a la API de Dolibarr directamente */ async function dolibarrFetch(endpoint, options = {}) { const url = `${DOLIBARR_API_URL}/${endpoint}`; const response = await fetch(url, { ...options, headers: { 'Content-Type': 'application/json', 'DOLAPIKEY': DOLIBARR_API_KEY, ...options.headers, }, }); if (!response.ok) { const text = await response.text(); throw new Error(`HTTP ${response.status}: ${text}`); } return response.json(); } /** * Crear un proyecto */ async function createProject(projectData) { return dolibarrFetch('projects', { method: 'POST', body: JSON.stringify(projectData), }); } /** * Validar proyecto (cambiar estado a abierto) */ async function validateProject(projectId) { try { await dolibarrFetch(`projects/${projectId}/validate`, { method: 'POST', body: JSON.stringify({ notrigger: 0 }), }); return true; } catch (e) { return false; } } /** * Cerrar proyecto */ async function closeProject(projectId) { try { await dolibarrFetch(`projects/${projectId}/close`, { method: 'POST', body: JSON.stringify({ notrigger: 0 }), }); return true; } catch (e) { return false; } } /** * Script principal */ async function main() { console.log('\n🚀 SEED DE PROYECTOS DE PRUEBA PARA DOLIBARR\n'); console.log('═'.repeat(60)); console.log(`📡 API Dolibarr: ${DOLIBARR_API_URL}`); console.log(`🔑 API Key: ${DOLIBARR_API_KEY.substring(0, 10)}...`); console.log(`📊 Proyectos a crear: ${projectsData.length}`); console.log('═'.repeat(60)); console.log(''); // Verificar conexión con Dolibarr console.log('🔍 Verificando conexion con Dolibarr...'); try { await dolibarrFetch('status'); console.log('✅ Conexion exitosa con Dolibarr\n'); } catch (error) { console.error('❌ ERROR: No se puede conectar a Dolibarr'); console.error(` ${error.message}`); console.error('\n Verifica que:'); console.error(' 1. Docker está corriendo'); console.error(' 2. La URL en .env.local es correcta'); console.error(' 3. La API key es válida\n'); process.exit(1); } let successCount = 0; let errorCount = 0; const errors = []; for (let i = 0; i < projectsData.length; i++) { const project = projectsData[i]; const num = i + 1; const percentage = project.opp_percent; const shouldClose = project.status === 2; // Asignar cliente aleatorio const clientName = clientNames[i % clientNames.length]; // Indicador visual del progreso const progressBar = '▓'.repeat(Math.floor(percentage / 10)) + '░'.repeat(10 - Math.floor(percentage / 10)); console.log(`[${num}/${projectsData.length}] ${project.title}`); console.log(` 📈 Progreso: [${progressBar}] ${percentage}%`); console.log(` 💰 Presupuesto: €${project.opp_amount.toLocaleString()}`); console.log(` 👤 Cliente: ${clientName}`); try { // Crear proyecto const projectPayload = { ref: project.ref, title: project.title, description: project.description, opp_amount: project.opp_amount.toString(), opp_percent: project.opp_percent.toString(), date_start: project.date_start, date_end: project.date_end, usage_opportunity: 1, usage_task: 1, public: 1, }; const projectId = await createProject(projectPayload); console.log(` ✅ Creado con ID: ${projectId}`); // Validar proyecto si tiene progreso > 0 if (percentage > 0) { const validated = await validateProject(projectId); if (validated) { console.log(` ✓ Validado (estado: abierto)`); // Cerrar si debe estar cerrado if (shouldClose) { const closed = await closeProject(projectId); if (closed) { console.log(` ✓ Cerrado (completado)`); } } } else { console.log(` ⚠ Creado pero no validado`); } } else { console.log(` 📋 Dejado como borrador`); } successCount++; // Pequeña pausa para no saturar la API await new Promise(resolve => setTimeout(resolve, 300)); } catch (error) { console.log(` ❌ Error: ${error.message}`); errors.push({ project: project.title, error: error.message }); errorCount++; } console.log(''); } // Resumen final console.log('═'.repeat(60)); console.log('✨ PROCESO COMPLETADO\n'); console.log(`✅ Proyectos creados exitosamente: ${successCount}`); console.log(`❌ Proyectos con error: ${errorCount}`); if (errors.length > 0) { console.log('\n📋 Errores encontrados:'); errors.forEach(({ project, error }) => { console.log(` • ${project}: ${error}`); }); } console.log('═'.repeat(60)); if (successCount > 0) { console.log('\n💡 Ahora puedes iniciar tu app con "npm run dev"'); console.log(' y ver los proyectos en http://localhost:3000\n'); } } // Ejecutar main().catch(error => { console.error('\n❌ ERROR FATAL:', error.message); process.exit(1); });