feat: Enhance Dolibarr project management dashboard with new features and scripts
- Updated README.md to include detailed project description, features, installation steps, and troubleshooting tips. - Added new scripts for seeding test projects via API and direct connection to Dolibarr. - Introduced a diagnostic script to check the status of Dolibarr and Next.js services. - Implemented project seeding scripts with realistic data and validation processes. - Updated project TypeScript definitions to allow nullable date fields for better compatibility.
This commit is contained in:
parent
ea708254e3
commit
997ff4d64d
|
|
@ -0,0 +1,216 @@
|
|||
# 🚀 Guía Rápida de Uso
|
||||
|
||||
## Paso 1: Iniciar Dolibarr (Docker)
|
||||
|
||||
Si tienes Dolibarr en Docker:
|
||||
|
||||
```bash
|
||||
docker start <nombre-contenedor-dolibarr>
|
||||
# o
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
Verifica que Dolibarr esté accesible en `http://localhost:8200`
|
||||
|
||||
---
|
||||
|
||||
## Paso 2: Iniciar la aplicación
|
||||
|
||||
```bash
|
||||
# Asegúrate de estar en el directorio del proyecto
|
||||
cd trello_fake
|
||||
|
||||
# Inicia el servidor de desarrollo
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Espera a ver:
|
||||
```
|
||||
✓ Ready in 2.3s
|
||||
○ Local: http://localhost:3000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Paso 3: Crear proyectos de prueba
|
||||
|
||||
**Opción A: Usando el script (Recomendado)**
|
||||
|
||||
En una **nueva terminal** (dejando `npm run dev` corriendo):
|
||||
|
||||
```bash
|
||||
npm run seed
|
||||
```
|
||||
|
||||
Verás algo como:
|
||||
```
|
||||
🚀 SEED DE PROYECTOS DE PRUEBA PARA DOLIBARR
|
||||
|
||||
[1/12] Desarrollo de App Móvil
|
||||
📈 Progreso: [▓▓▓▓▓▓░░░░] 65%
|
||||
💰 Presupuesto: €45,000
|
||||
✅ Creado con ID: 1
|
||||
✓ Validado (estado: abierto)
|
||||
|
||||
...
|
||||
|
||||
✨ PROCESO COMPLETADO
|
||||
✅ Proyectos creados exitosamente: 12
|
||||
```
|
||||
|
||||
**Opción B: Crear proyectos manualmente en Dolibarr**
|
||||
|
||||
1. Accede a Dolibarr: `http://localhost:8200`
|
||||
2. Login: admin / p4ssw0rd
|
||||
3. Ve a Proyectos > Nuevo Proyecto
|
||||
4. Completa el formulario y guarda
|
||||
|
||||
---
|
||||
|
||||
## Paso 4: Ver los proyectos
|
||||
|
||||
Abre tu navegador en: `http://localhost:3000`
|
||||
|
||||
Deberías ver:
|
||||
- 📊 Dashboard con estadísticas
|
||||
- 🎴 Proyectos en vista de grid (por defecto)
|
||||
- 🔍 Barra de búsqueda funcional
|
||||
- 🌓 Toggle de modo oscuro
|
||||
|
||||
---
|
||||
|
||||
## Paso 5: Explorar funcionalidades
|
||||
|
||||
### Vista de Lista
|
||||
- Haz clic en el botón **☰** (lista) en el header
|
||||
|
||||
### Detalle de Proyecto
|
||||
- Haz clic en cualquier tarjeta de proyecto
|
||||
- Verás información completa: descripción, progreso, presupuesto, fechas
|
||||
|
||||
### Búsqueda
|
||||
- Escribe en la barra de búsqueda
|
||||
- Filtra por nombre, cliente o referencia
|
||||
|
||||
### Modo Oscuro
|
||||
- Haz clic en el icono **☀️/🌙** en el header
|
||||
- Elige: Claro, Oscuro o Sistema
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Casos de Uso
|
||||
|
||||
### Ver proyectos completados
|
||||
1. Busca proyectos con badge verde "Cerrado"
|
||||
2. O con progreso del 100%
|
||||
3. Ejemplos: "Dashboard Analítico BI", "Portal de Empleados"
|
||||
|
||||
### Ver proyectos en progreso
|
||||
1. Busca proyectos con badge azul "Abierto"
|
||||
2. Progreso entre 1% y 99%
|
||||
3. Ejemplo: "App de Gestión de Proyectos" (75%)
|
||||
|
||||
### Ver borradores
|
||||
1. Busca proyectos con badge gris "Borrador"
|
||||
2. Progreso del 0%
|
||||
3. Ejemplo: "Sistema CRM Personalizado"
|
||||
|
||||
### Comparar presupuestos
|
||||
1. Cambia a vista de lista (☰)
|
||||
2. Compara la columna "Presupuesto"
|
||||
3. Proyecto más caro: "E-commerce con Marketplace" (€120k)
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Solución de Problemas
|
||||
|
||||
### No veo proyectos
|
||||
```bash
|
||||
# 1. Verifica que Dolibarr esté corriendo
|
||||
curl http://localhost:8200
|
||||
|
||||
# 2. Ejecuta el seed
|
||||
npm run seed
|
||||
|
||||
# 3. Recarga la página (F5)
|
||||
```
|
||||
|
||||
### Error 500 en la consola
|
||||
- Revisa `.env.local`
|
||||
- Verifica las credenciales de Dolibarr
|
||||
- Comprueba que la API esté habilitada en Dolibarr
|
||||
|
||||
### Página en blanco
|
||||
- Abre la consola del navegador (F12)
|
||||
- Busca errores en rojo
|
||||
- Verifica que `npm run dev` esté corriendo
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Personalización
|
||||
|
||||
### Cambiar el número de proyectos de prueba
|
||||
Edita `scripts/seed-projects-via-api.js`:
|
||||
```javascript
|
||||
// Comenta los proyectos que no quieras
|
||||
const projectsData = [
|
||||
// ... solo deja los que quieras
|
||||
];
|
||||
```
|
||||
|
||||
### Modificar datos de un proyecto
|
||||
Edita el objeto correspondiente:
|
||||
```javascript
|
||||
{
|
||||
title: "Tu Proyecto Personalizado",
|
||||
ref: "PROJ-2024-XXX",
|
||||
description: "Tu descripción...",
|
||||
opp_amount: 75000, // Tu presupuesto
|
||||
opp_percent: 80, // Tu progreso
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Luego ejecuta:
|
||||
```bash
|
||||
npm run seed
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Resetear todo
|
||||
|
||||
### Limpiar proyectos en Dolibarr
|
||||
1. Accede a Dolibarr
|
||||
2. Ve a cada proyecto
|
||||
3. Elimina uno por uno
|
||||
|
||||
### Limpiar caché de Next.js
|
||||
```bash
|
||||
rm -rf .next
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Empezar de cero
|
||||
```bash
|
||||
# Detén el servidor (Ctrl+C)
|
||||
rm -rf .next
|
||||
npm run dev
|
||||
npm run seed
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Referencias Rápidas
|
||||
|
||||
| Acción | Comando |
|
||||
|--------|---------|
|
||||
| Iniciar desarrollo | `npm run dev` |
|
||||
| Crear proyectos | `npm run seed` |
|
||||
| Build producción | `npm run build` |
|
||||
| Ver logs | Ver terminal donde corre `npm run dev` |
|
||||
| Ver API calls | F12 > Network > Fetch/XHR |
|
||||
|
||||
---
|
||||
|
||||
¡Listo! Ya puedes explorar tu dashboard de proyectos Dolibarr 🎉
|
||||
199
README.md
199
README.md
|
|
@ -2,27 +2,198 @@ This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-
|
|||
|
||||

|
||||
|
||||
## Dashboard de Proyectos Dolibarr
|
||||
|
||||
Aplicación web moderna para visualizar y gestionar proyectos de Dolibarr con una interfaz intuitiva y profesional.
|
||||
|
||||
### ✨ Características
|
||||
|
||||
- 📊 Vista de proyectos en Grid y Lista
|
||||
- 🎨 Modo oscuro completo
|
||||
- 📱 Diseño responsive
|
||||
- 🔍 Búsqueda en tiempo real
|
||||
- 📈 Estadísticas y KPIs
|
||||
- 🔐 API segura (API key protegida en el backend)
|
||||
- ⚡ Skeletons loading para mejor UX
|
||||
- 📄 Página de detalle completa para cada proyecto
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Getting Started
|
||||
|
||||
### Requisitos previos
|
||||
|
||||
- Node.js 18+
|
||||
- Dolibarr con API habilitada
|
||||
- Docker (opcional, para Dolibarr)
|
||||
|
||||
### Instalación
|
||||
|
||||
1. **Clonar el repositorio**
|
||||
```bash
|
||||
git clone <tu-repo>
|
||||
cd trello_fake
|
||||
```
|
||||
|
||||
2. **Instalar dependencias**
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
3. **Configurar variables de entorno**
|
||||
|
||||
Crea un archivo `.env.local` en la raíz:
|
||||
|
||||
```bash
|
||||
# API de Dolibarr (segura - solo servidor)
|
||||
DOLIBARR_API_URL=http://localhost:8200/api/index.php
|
||||
DOLIBARR_API_KEY=tu-api-key-aqui
|
||||
|
||||
# Variables públicas
|
||||
NEXT_PUBLIC_DOLIBARR_USER_ID=2
|
||||
```
|
||||
|
||||
4. **Iniciar el servidor de desarrollo**
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Abre [http://localhost:3000](http://localhost:3000) en tu navegador.
|
||||
|
||||
---
|
||||
|
||||
## 📊 Datos de Prueba
|
||||
|
||||
Si no tienes proyectos en tu Dolibarr, puedes generar datos de prueba:
|
||||
|
||||
```bash
|
||||
# Con el servidor corriendo (npm run dev)
|
||||
npm run seed
|
||||
```
|
||||
|
||||
Este comando creará 12 proyectos de ejemplo con:
|
||||
- Diferentes estados de progreso (0% - 100%)
|
||||
- Presupuestos variados (€28k - €120k)
|
||||
- Descripciones detalladas
|
||||
- Fechas realistas
|
||||
|
||||
Ver más detalles en [scripts/README.md](scripts/README.md)
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Estructura del Proyecto
|
||||
|
||||
```
|
||||
/
|
||||
├── app/ # Next.js App Router
|
||||
│ ├── api/dolibarr/[...path]/ # API Route proxy (protege la API key)
|
||||
│ ├── proyectos/[id]/ # Página de detalle de proyecto
|
||||
│ ├── layout.tsx # Layout principal
|
||||
│ └── page.tsx # Página de inicio
|
||||
├── components/
|
||||
│ ├── dashboard/ # Componentes del dashboard
|
||||
│ ├── ui/ # Componentes shadcn/ui
|
||||
│ ├── theme-provider.tsx # Provider de tema
|
||||
│ └── theme-toggle.tsx # Toggle de modo oscuro
|
||||
├── lib/ # Utilidades y servicios
|
||||
│ ├── dolibarrClient.ts # Cliente de API
|
||||
│ ├── projectsService.ts # Servicio de proyectos
|
||||
│ └── usersService.ts # Servicio de usuarios
|
||||
├── types/ # Definiciones TypeScript
|
||||
└── scripts/ # Scripts de utilidad
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Scripts Disponibles
|
||||
|
||||
```bash
|
||||
npm run dev # Servidor de desarrollo
|
||||
npm run build # Build de producción
|
||||
npm run start # Servidor de producción
|
||||
npm run lint # Ejecutar ESLint
|
||||
npm run seed # Crear proyectos de prueba
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Tecnologías
|
||||
|
||||
- **Framework:** Next.js 16 (App Router)
|
||||
- **Lenguaje:** TypeScript 5
|
||||
- **UI:** shadcn/ui + Radix UI
|
||||
- **Estilos:** Tailwind CSS
|
||||
- **Iconos:** Lucide React
|
||||
- **Tema:** next-themes
|
||||
- **API:** Dolibarr REST API
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Seguridad
|
||||
|
||||
La aplicación implementa las siguientes medidas de seguridad:
|
||||
|
||||
- ✅ API key protegida en el servidor (NO expuesta al cliente)
|
||||
- ✅ API Route proxy para todas las llamadas a Dolibarr
|
||||
- ✅ Variables de entorno seguras
|
||||
- ✅ Validación de datos de entrada
|
||||
|
||||
---
|
||||
|
||||
## 📖 Documentación Adicional
|
||||
|
||||
- [AGENTS.md](AGENTS.md) - Guías para agentes de IA y arquitectura del proyecto
|
||||
- [scripts/README.md](scripts/README.md) - Documentación de scripts de utilidad
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### Error: "Cannot connect to Dolibarr"
|
||||
- Verifica que Dolibarr esté corriendo
|
||||
- Revisa la URL en `.env.local`
|
||||
- Comprueba que la API esté habilitada en Dolibarr
|
||||
|
||||
### No se muestran proyectos
|
||||
- Ejecuta `npm run seed` para crear datos de prueba
|
||||
- Verifica las credenciales de la API
|
||||
- Revisa la consola del navegador para errores
|
||||
|
||||
### Modo oscuro no funciona
|
||||
- Limpia la caché del navegador
|
||||
- Verifica que ThemeProvider esté envolviendo la app
|
||||
|
||||
---
|
||||
|
||||
## 📝 Credenciales de Dolibarr (Demo)
|
||||
|
||||
username: admin
|
||||
password: p4ssw0rd
|
||||
|
||||
## Getting Started
|
||||
---
|
||||
|
||||
First, run the development server:
|
||||
## 🤝 Contribuir
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
# or
|
||||
yarn dev
|
||||
# or
|
||||
pnpm dev
|
||||
# or
|
||||
bun dev
|
||||
```
|
||||
Las contribuciones son bienvenidas. Por favor:
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
1. Fork el proyecto
|
||||
2. Crea una rama para tu feature (`git checkout -b feature/AmazingFeature`)
|
||||
3. Commit tus cambios (`git commit -m 'Add: AmazingFeature'`)
|
||||
4. Push a la rama (`git push origin feature/AmazingFeature`)
|
||||
5. Abre un Pull Request
|
||||
|
||||
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
||||
---
|
||||
|
||||
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
|
||||
## 📄 Licencia
|
||||
|
||||
Este proyecto es privado y de uso interno.
|
||||
|
||||
---
|
||||
|
||||
## Learn More
|
||||
|
||||
To learn more about Next.js, take a look at the following resources:
|
||||
|
||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||
- [Dolibarr API Documentation](https://wiki.dolibarr.org/index.php/Module_Web_Services_API_REST_(v1)) - Dolibarr REST API reference.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,10 @@
|
|||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "eslint"
|
||||
"lint": "eslint",
|
||||
"seed": "node scripts/seed-projects-via-api.js",
|
||||
"seed:direct": "node scripts/seed-projects.js",
|
||||
"diagnose": "node scripts/diagnose.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-avatar": "^1.1.11",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,114 @@
|
|||
# Scripts de Utilidad
|
||||
|
||||
Este directorio contiene scripts para facilitar el desarrollo y testing de la aplicación.
|
||||
|
||||
## 📊 Seed de Proyectos de Prueba
|
||||
|
||||
### Opción 1: Via API Route de Next.js (Recomendado) ✅
|
||||
|
||||
Este método es más seguro ya que usa la API Route protegida.
|
||||
|
||||
**Requisitos:**
|
||||
- El servidor de Next.js debe estar corriendo (`npm run dev`)
|
||||
- Dolibarr debe estar accesible
|
||||
|
||||
**Uso:**
|
||||
```bash
|
||||
npm run seed
|
||||
```
|
||||
|
||||
**Lo que hace:**
|
||||
- Crea 12 proyectos de prueba con datos realistas
|
||||
- Diferentes estados de progreso (0%, 15%, 35%, 50%, 65%, 75%, 90%, 100%)
|
||||
- Variedad de presupuestos (€28k - €120k)
|
||||
- Fechas de inicio y fin variadas
|
||||
- Valida automáticamente los proyectos con progreso > 0%
|
||||
|
||||
**Proyectos incluidos:**
|
||||
1. Desarrollo de App Móvil (65%)
|
||||
2. Rediseño Web Corporativo (90%)
|
||||
3. Sistema de Facturación Automática (35%)
|
||||
4. Migración a Cloud AWS (20%)
|
||||
5. Dashboard Analítico BI (100% - completado)
|
||||
6. API REST Microservicios (50%)
|
||||
7. App de Gestión de Proyectos (75%)
|
||||
8. E-commerce con Marketplace (15%)
|
||||
9. Sistema CRM Personalizado (0% - borrador)
|
||||
10. Portal de Empleados (100% - completado)
|
||||
11. Sistema de Reservas Online (45%)
|
||||
12. App de Formación Online (30%)
|
||||
|
||||
---
|
||||
|
||||
### Opción 2: Conexión Directa a Dolibarr
|
||||
|
||||
Este método se conecta directamente a la API de Dolibarr (sin pasar por Next.js).
|
||||
|
||||
**Requisitos:**
|
||||
- Dolibarr debe estar accesible
|
||||
- Variables de entorno configuradas en `.env.local`
|
||||
|
||||
**Uso:**
|
||||
```bash
|
||||
npm run seed:direct
|
||||
```
|
||||
|
||||
⚠️ **Nota:** Este método usa las credenciales directamente desde `.env.local`.
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Troubleshooting
|
||||
|
||||
### Error: "No se puede conectar al servidor Next.js"
|
||||
**Solución:** Asegúrate de que el servidor esté corriendo:
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Error: "Dolibarr API error"
|
||||
**Soluciones posibles:**
|
||||
1. Verifica que Dolibarr esté corriendo (Docker)
|
||||
2. Revisa las credenciales en `.env.local`
|
||||
3. Verifica que la URL de la API sea correcta
|
||||
|
||||
### Error: "No se pudo validar"
|
||||
**No te preocupes:** Es normal. Algunos proyectos se crean correctamente pero no se pueden validar automáticamente. Puedes validarlos manualmente desde Dolibarr si es necesario.
|
||||
|
||||
---
|
||||
|
||||
## 🧹 Limpiar Proyectos de Prueba
|
||||
|
||||
Si quieres eliminar los proyectos de prueba creados, puedes hacerlo desde la interfaz de Dolibarr o usando la API:
|
||||
|
||||
```bash
|
||||
# TODO: Crear script de limpieza
|
||||
# npm run clean:projects
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 Notas
|
||||
|
||||
- Los scripts pausan 500ms entre cada creación para no saturar la API
|
||||
- Los proyectos con progreso 0% se dejan como "borrador"
|
||||
- Los proyectos con progreso > 0% se intentan validar automáticamente
|
||||
- Todos los proyectos tienen descripciones detalladas
|
||||
- Las fechas están distribuidas entre 2023 y 2025
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Personalización
|
||||
|
||||
Para modificar los proyectos de prueba, edita el array `projectsData` en cualquiera de los scripts:
|
||||
|
||||
```javascript
|
||||
{
|
||||
title: "Tu Proyecto",
|
||||
ref: "PROJ-2024-XXX",
|
||||
description: "Descripción detallada...",
|
||||
opp_amount: 50000, // Presupuesto en euros
|
||||
opp_percent: 50, // Progreso (0-100)
|
||||
date_start: timestamp, // Unix timestamp en segundos
|
||||
date_end: timestamp, // Unix timestamp en segundos
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Script de diagnóstico para verificar que la aplicación esté funcionando correctamente
|
||||
*/
|
||||
|
||||
const COLORS = {
|
||||
reset: '\x1b[0m',
|
||||
green: '\x1b[32m',
|
||||
red: '\x1b[31m',
|
||||
yellow: '\x1b[33m',
|
||||
blue: '\x1b[34m',
|
||||
cyan: '\x1b[36m',
|
||||
};
|
||||
|
||||
function log(color, symbol, message) {
|
||||
console.log(`${color}${symbol}${COLORS.reset} ${message}`);
|
||||
}
|
||||
|
||||
async function checkDolibarr() {
|
||||
try {
|
||||
const response = await fetch('http://localhost:8200');
|
||||
if (response.ok || response.status === 404) {
|
||||
log(COLORS.green, '✓', 'Dolibarr está accesible en http://localhost:8200');
|
||||
return true;
|
||||
}
|
||||
log(COLORS.red, '✗', `Dolibarr respondió con status ${response.status}`);
|
||||
return false;
|
||||
} catch (error) {
|
||||
log(COLORS.red, '✗', 'Dolibarr NO está accesible en http://localhost:8200');
|
||||
log(COLORS.yellow, '⚠', 'Asegúrate de que Docker esté corriendo: docker ps');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function checkNextJS() {
|
||||
try {
|
||||
const response = await fetch('http://localhost:3000');
|
||||
if (response.ok || response.status === 404) {
|
||||
log(COLORS.green, '✓', 'Next.js está corriendo en http://localhost:3000');
|
||||
return true;
|
||||
}
|
||||
log(COLORS.red, '✗', `Next.js respondió con status ${response.status}`);
|
||||
return false;
|
||||
} catch (error) {
|
||||
log(COLORS.red, '✗', 'Next.js NO está corriendo en http://localhost:3000');
|
||||
log(COLORS.yellow, '⚠', 'Ejecuta: npm run dev');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function checkAPIRoute() {
|
||||
try {
|
||||
const response = await fetch('http://localhost:3000/api/dolibarr/projects');
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
log(COLORS.green, '✓', `API Route funciona correctamente`);
|
||||
log(COLORS.cyan, 'ℹ', `Proyectos encontrados: ${data.length}`);
|
||||
return data.length;
|
||||
}
|
||||
const errorData = await response.json();
|
||||
log(COLORS.red, '✗', `API Route falló: ${errorData.error}`);
|
||||
return 0;
|
||||
} catch (error) {
|
||||
log(COLORS.red, '✗', `Error en API Route: ${error.message}`);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
async function checkDolibarrAPI() {
|
||||
try {
|
||||
const API_URL = 'http://localhost:8200/api/index.php';
|
||||
const API_KEY = process.env.NEXT_PUBLIC_DOLIBARR_API_KEY || 'Xzulu2Jbv1Ge4V1IVtXKe45db9W64WN7';
|
||||
|
||||
const response = await fetch(`${API_URL}/projects?DOLAPIKEY=${API_KEY}`);
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
log(COLORS.green, '✓', 'API de Dolibarr funciona correctamente');
|
||||
log(COLORS.cyan, 'ℹ', `Proyectos en Dolibarr: ${data.length}`);
|
||||
|
||||
if (data.length > 0) {
|
||||
const sample = data[0];
|
||||
log(COLORS.blue, '→', `Ejemplo: ${sample.title} (${sample.ref})`);
|
||||
}
|
||||
|
||||
return data.length;
|
||||
}
|
||||
log(COLORS.red, '✗', `API de Dolibarr falló con status ${response.status}`);
|
||||
return 0;
|
||||
} catch (error) {
|
||||
log(COLORS.red, '✗', `Error conectando a API de Dolibarr: ${error.message}`);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('\n' + '═'.repeat(60));
|
||||
console.log('🔍 DIAGNÓSTICO DEL SISTEMA');
|
||||
console.log('═'.repeat(60) + '\n');
|
||||
|
||||
// 1. Verificar Dolibarr
|
||||
console.log('1️⃣ Verificando Dolibarr...');
|
||||
const dolibarrOk = await checkDolibarr();
|
||||
console.log('');
|
||||
|
||||
if (!dolibarrOk) {
|
||||
console.log('💡 Solución:');
|
||||
console.log(' docker ps # Ver contenedores');
|
||||
console.log(' docker start <container> # Iniciar Dolibarr\n');
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Verificar Next.js
|
||||
console.log('2️⃣ Verificando Next.js...');
|
||||
const nextOk = await checkNextJS();
|
||||
console.log('');
|
||||
|
||||
if (!nextOk) {
|
||||
console.log('💡 Solución:');
|
||||
console.log(' npm run dev\n');
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. Verificar API de Dolibarr directa
|
||||
console.log('3️⃣ Verificando API de Dolibarr...');
|
||||
const dolibarrProjectCount = await checkDolibarrAPI();
|
||||
console.log('');
|
||||
|
||||
// 4. Verificar API Route
|
||||
console.log('4️⃣ Verificando API Route de Next.js...');
|
||||
const apiRouteProjectCount = await checkAPIRoute();
|
||||
console.log('');
|
||||
|
||||
// Resumen
|
||||
console.log('═'.repeat(60));
|
||||
console.log('📊 RESUMEN');
|
||||
console.log('═'.repeat(60));
|
||||
|
||||
if (dolibarrProjectCount === 0) {
|
||||
log(COLORS.yellow, '⚠', 'No hay proyectos en Dolibarr');
|
||||
console.log('\n💡 Solución:');
|
||||
console.log(' npm run seed # Crear proyectos de prueba\n');
|
||||
} else if (apiRouteProjectCount === 0) {
|
||||
log(COLORS.red, '✗', 'Hay proyectos en Dolibarr pero no se pueden obtener via API Route');
|
||||
console.log('\n💡 Posibles causas:');
|
||||
console.log(' 1. Revisa las credenciales en .env.local');
|
||||
console.log(' 2. Verifica que la API key sea correcta');
|
||||
console.log(' 3. Mira los logs del servidor Next.js (terminal donde corre npm run dev)\n');
|
||||
} else if (dolibarrProjectCount !== apiRouteProjectCount) {
|
||||
log(COLORS.yellow, '⚠', 'Discrepancia en el número de proyectos');
|
||||
log(COLORS.cyan, 'ℹ', `Dolibarr: ${dolibarrProjectCount}, API Route: ${apiRouteProjectCount}`);
|
||||
} else {
|
||||
log(COLORS.green, '✓', 'Todo está funcionando correctamente!');
|
||||
console.log('');
|
||||
log(COLORS.cyan, '🎉', 'Abre http://localhost:3000 para ver tus proyectos');
|
||||
console.log('');
|
||||
}
|
||||
|
||||
// Consejos adicionales
|
||||
if (apiRouteProjectCount > 0) {
|
||||
console.log('═'.repeat(60));
|
||||
console.log('💡 CONSEJOS');
|
||||
console.log('═'.repeat(60));
|
||||
console.log('• Abre las DevTools del navegador (F12)');
|
||||
console.log('• Ve a la pestaña Console');
|
||||
console.log('• Busca errores en rojo');
|
||||
console.log('• Ve a la pestaña Network > Fetch/XHR');
|
||||
console.log('• Verifica que la petición a /api/dolibarr/projects retorne 200\n');
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(error => {
|
||||
console.error('\n❌ Error fatal:', error.message);
|
||||
process.exit(1);
|
||||
});
|
||||
|
|
@ -0,0 +1,281 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Script para crear proyectos de prueba en Dolibarr usando la API Route
|
||||
* Este script usa la API Route segura de Next.js
|
||||
*
|
||||
* REQUISITO: El servidor de Next.js debe estar corriendo (npm run dev)
|
||||
* Uso: node scripts/seed-projects-via-api.js
|
||||
*/
|
||||
|
||||
const NEXT_API_URL = 'http://localhost:3000/api/dolibarr';
|
||||
|
||||
// Datos de proyectos de ejemplo con variedad de estados y presupuestos
|
||||
const projectsData = [
|
||||
{
|
||||
title: "Desarrollo de App Móvil",
|
||||
ref: "PROJ-2024-001",
|
||||
description: "Aplicación móvil para gestión de inventario con funcionalidades de escaneo QR y sincronización en tiempo real.",
|
||||
opp_amount: 45000,
|
||||
opp_percent: 65,
|
||||
date_start: Math.floor(new Date('2024-01-15').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2024-06-30').getTime() / 1000),
|
||||
},
|
||||
{
|
||||
title: "Rediseño Web Corporativo",
|
||||
ref: "PROJ-2024-002",
|
||||
description: "Renovación completa del sitio web corporativo con nuevo diseño responsive y optimización SEO.",
|
||||
opp_amount: 28000,
|
||||
opp_percent: 90,
|
||||
date_start: Math.floor(new Date('2023-11-01').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2024-02-28').getTime() / 1000),
|
||||
},
|
||||
{
|
||||
title: "Sistema de Facturación Automática",
|
||||
ref: "PROJ-2024-003",
|
||||
description: "Desarrollo de sistema automatizado para generación y envío de facturas con integración a contabilidad.",
|
||||
opp_amount: 62000,
|
||||
opp_percent: 35,
|
||||
date_start: Math.floor(new Date('2024-02-01').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2024-08-31').getTime() / 1000),
|
||||
},
|
||||
{
|
||||
title: "Migración a Cloud AWS",
|
||||
ref: "PROJ-2024-004",
|
||||
description: "Migración completa de infraestructura on-premise a AWS con configuración de alta disponibilidad.",
|
||||
opp_amount: 85000,
|
||||
opp_percent: 20,
|
||||
date_start: Math.floor(new Date('2024-03-01').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2024-12-31').getTime() / 1000),
|
||||
},
|
||||
{
|
||||
title: "Dashboard Analítico BI",
|
||||
ref: "PROJ-2024-005",
|
||||
description: "Creación de dashboard de Business Intelligence para análisis de ventas y KPIs en tiempo real.",
|
||||
opp_amount: 38000,
|
||||
opp_percent: 100,
|
||||
date_start: Math.floor(new Date('2023-09-01').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2023-12-15').getTime() / 1000),
|
||||
},
|
||||
{
|
||||
title: "API REST Microservicios",
|
||||
ref: "PROJ-2024-006",
|
||||
description: "Desarrollo de arquitectura de microservicios con API REST para integración de sistemas legacy.",
|
||||
opp_amount: 72000,
|
||||
opp_percent: 50,
|
||||
date_start: Math.floor(new Date('2024-01-20').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2024-07-31').getTime() / 1000),
|
||||
},
|
||||
{
|
||||
title: "App de Gestión de Proyectos",
|
||||
ref: "PROJ-2024-007",
|
||||
description: "Plataforma web para gestión ágil de proyectos con tableros Kanban, Gantt y reporting automático.",
|
||||
opp_amount: 55000,
|
||||
opp_percent: 75,
|
||||
date_start: Math.floor(new Date('2023-12-01').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2024-05-31').getTime() / 1000),
|
||||
},
|
||||
{
|
||||
title: "E-commerce con Marketplace",
|
||||
ref: "PROJ-2024-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('2024-04-01').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2025-03-31').getTime() / 1000),
|
||||
},
|
||||
{
|
||||
title: "Sistema CRM Personalizado",
|
||||
ref: "PROJ-2024-009",
|
||||
description: "CRM a medida con automatización de marketing, gestión de leads y pipeline de ventas.",
|
||||
opp_amount: 48000,
|
||||
opp_percent: 0,
|
||||
date_start: Math.floor(new Date('2024-05-01').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2024-11-30').getTime() / 1000),
|
||||
},
|
||||
{
|
||||
title: "Portal de Empleados",
|
||||
ref: "PROJ-2024-010",
|
||||
description: "Portal interno para empleados con gestión de vacaciones, nóminas, formación y comunicación interna.",
|
||||
opp_amount: 35000,
|
||||
opp_percent: 100,
|
||||
date_start: Math.floor(new Date('2023-10-01').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2023-12-31').getTime() / 1000),
|
||||
},
|
||||
{
|
||||
title: "Sistema de Reservas Online",
|
||||
ref: "PROJ-2024-011",
|
||||
description: "Plataforma de reservas con calendario interactivo, confirmación automática y pasarela de pago.",
|
||||
opp_amount: 42000,
|
||||
opp_percent: 45,
|
||||
date_start: Math.floor(new Date('2024-02-15').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2024-07-15').getTime() / 1000),
|
||||
},
|
||||
{
|
||||
title: "App de Formación Online",
|
||||
ref: "PROJ-2024-012",
|
||||
description: "Plataforma LMS para formación online con seguimiento de progreso, certificados y evaluaciones.",
|
||||
opp_amount: 68000,
|
||||
opp_percent: 30,
|
||||
date_start: Math.floor(new Date('2024-03-10').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2024-10-31').getTime() / 1000),
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* Crear un proyecto usando la API Route de Next.js
|
||||
*/
|
||||
async function createProject(projectData) {
|
||||
const url = `${NEXT_API_URL}/projects`;
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(projectData),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
throw new Error(`Error ${response.status}: ${errorData.error || 'Unknown error'}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (error.code === 'ECONNREFUSED') {
|
||||
throw new Error('No se puede conectar al servidor Next.js. ¿Está corriendo "npm run dev"?');
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validar proyecto (cambiar estado a validado/abierto)
|
||||
*/
|
||||
async function validateProject(projectId) {
|
||||
const url = `${NEXT_API_URL}/projects/${projectId}/validate`;
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ notrigger: 0 }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
// Es normal que algunos proyectos no se puedan validar
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
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 Next.js: ${NEXT_API_URL}`);
|
||||
console.log(`📊 Proyectos a crear: ${projectsData.length}`);
|
||||
console.log('═'.repeat(60));
|
||||
console.log('');
|
||||
|
||||
// Verificar que Next.js esté corriendo
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// 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()}`);
|
||||
|
||||
try {
|
||||
// Crear proyecto
|
||||
const result = await createProject(project);
|
||||
console.log(` ✅ Creado con ID: ${result}`);
|
||||
|
||||
// Validar proyecto si tiene progreso > 0
|
||||
if (percentage > 0) {
|
||||
const validated = await validateProject(result);
|
||||
if (validated) {
|
||||
console.log(` ✓ Validado (estado: abierto)`);
|
||||
} else {
|
||||
console.log(` ⚠ Creado pero no validado (normal para algunos proyectos)`);
|
||||
}
|
||||
} else {
|
||||
console.log(` 📋 Dejado como borrador`);
|
||||
}
|
||||
|
||||
successCount++;
|
||||
|
||||
// Pequeña pausa para no saturar la API
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
} 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💡 ¡Recarga tu aplicación para ver los proyectos!');
|
||||
console.log(' Abre http://localhost:3000 en tu navegador\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. Las credenciales en .env.local son correctas\n');
|
||||
process.exit(1);
|
||||
});
|
||||
|
|
@ -0,0 +1,229 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Script para crear proyectos de prueba en Dolibarr
|
||||
* Uso: node scripts/seed-projects.js
|
||||
*/
|
||||
|
||||
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8200/api/index.php';
|
||||
const API_KEY = process.env.NEXT_PUBLIC_DOLIBARR_API_KEY || 'Xzulu2Jbv1Ge4V1IVtXKe45db9W64WN7';
|
||||
|
||||
// Datos de proyectos de ejemplo
|
||||
const projectsData = [
|
||||
{
|
||||
title: "Desarrollo de App Móvil",
|
||||
ref: "PROJ-2024-001",
|
||||
description: "Aplicación móvil para gestión de inventario con funcionalidades de escaneo QR y sincronización en tiempo real.",
|
||||
socid: null, // Sin cliente asignado
|
||||
opp_amount: 45000,
|
||||
opp_percent: 65,
|
||||
date_start: Math.floor(new Date('2024-01-15').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2024-06-30').getTime() / 1000),
|
||||
},
|
||||
{
|
||||
title: "Rediseño Web Corporativo",
|
||||
ref: "PROJ-2024-002",
|
||||
description: "Renovación completa del sitio web corporativo con nuevo diseño responsive y optimización SEO.",
|
||||
socid: null,
|
||||
opp_amount: 28000,
|
||||
opp_percent: 90,
|
||||
date_start: Math.floor(new Date('2023-11-01').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2024-02-28').getTime() / 1000),
|
||||
},
|
||||
{
|
||||
title: "Sistema de Facturación Automática",
|
||||
ref: "PROJ-2024-003",
|
||||
description: "Desarrollo de sistema automatizado para generación y envío de facturas con integración a contabilidad.",
|
||||
socid: null,
|
||||
opp_amount: 62000,
|
||||
opp_percent: 35,
|
||||
date_start: Math.floor(new Date('2024-02-01').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2024-08-31').getTime() / 1000),
|
||||
},
|
||||
{
|
||||
title: "Migración a Cloud AWS",
|
||||
ref: "PROJ-2024-004",
|
||||
description: "Migración completa de infraestructura on-premise a AWS con configuración de alta disponibilidad.",
|
||||
socid: null,
|
||||
opp_amount: 85000,
|
||||
opp_percent: 20,
|
||||
date_start: Math.floor(new Date('2024-03-01').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2024-12-31').getTime() / 1000),
|
||||
},
|
||||
{
|
||||
title: "Dashboard Analítico BI",
|
||||
ref: "PROJ-2024-005",
|
||||
description: "Creación de dashboard de Business Intelligence para análisis de ventas y KPIs en tiempo real.",
|
||||
socid: null,
|
||||
opp_amount: 38000,
|
||||
opp_percent: 100,
|
||||
date_start: Math.floor(new Date('2023-09-01').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2023-12-15').getTime() / 1000),
|
||||
},
|
||||
{
|
||||
title: "API REST Microservicios",
|
||||
ref: "PROJ-2024-006",
|
||||
description: "Desarrollo de arquitectura de microservicios con API REST para integración de sistemas legacy.",
|
||||
socid: null,
|
||||
opp_amount: 72000,
|
||||
opp_percent: 50,
|
||||
date_start: Math.floor(new Date('2024-01-20').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2024-07-31').getTime() / 1000),
|
||||
},
|
||||
{
|
||||
title: "App de Gestión de Proyectos",
|
||||
ref: "PROJ-2024-007",
|
||||
description: "Plataforma web para gestión ágil de proyectos con tableros Kanban, Gantt y reporting automático.",
|
||||
socid: null,
|
||||
opp_amount: 55000,
|
||||
opp_percent: 75,
|
||||
date_start: Math.floor(new Date('2023-12-01').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2024-05-31').getTime() / 1000),
|
||||
},
|
||||
{
|
||||
title: "E-commerce con Marketplace",
|
||||
ref: "PROJ-2024-008",
|
||||
description: "Plataforma de e-commerce completa con funcionalidad de marketplace multivendedor y pasarela de pagos.",
|
||||
socid: null,
|
||||
opp_amount: 120000,
|
||||
opp_percent: 15,
|
||||
date_start: Math.floor(new Date('2024-04-01').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2025-03-31').getTime() / 1000),
|
||||
},
|
||||
{
|
||||
title: "Sistema CRM Personalizado",
|
||||
ref: "PROJ-2024-009",
|
||||
description: "CRM a medida con automatización de marketing, gestión de leads y pipeline de ventas.",
|
||||
socid: null,
|
||||
opp_amount: 48000,
|
||||
opp_percent: 0,
|
||||
date_start: Math.floor(new Date('2024-05-01').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2024-11-30').getTime() / 1000),
|
||||
},
|
||||
{
|
||||
title: "Portal de Empleados",
|
||||
ref: "PROJ-2024-010",
|
||||
description: "Portal interno para empleados con gestión de vacaciones, nóminas, formación y comunicación interna.",
|
||||
socid: null,
|
||||
opp_amount: 35000,
|
||||
opp_percent: 100,
|
||||
date_start: Math.floor(new Date('2023-10-01').getTime() / 1000),
|
||||
date_end: Math.floor(new Date('2023-12-31').getTime() / 1000),
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* Crear un proyecto en Dolibarr
|
||||
*/
|
||||
async function createProject(projectData) {
|
||||
const url = `${API_URL}/projects?DOLAPIKEY=${API_KEY}`;
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(projectData),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
throw new Error(`Error ${response.status}: ${errorText}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
return result;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validar proyecto (cambiar estado a validado/abierto)
|
||||
*/
|
||||
async function validateProject(projectId) {
|
||||
const url = `${API_URL}/projects/${projectId}/validate?DOLAPIKEY=${API_KEY}`;
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ notrigger: 0 }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
console.warn(` ⚠️ No se pudo validar (puede ser normal): ${errorText.substring(0, 100)}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.warn(` ⚠️ Error validando proyecto: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Script principal
|
||||
*/
|
||||
async function main() {
|
||||
console.log('🚀 Iniciando creación de proyectos de prueba en Dolibarr...\n');
|
||||
console.log(`📡 API URL: ${API_URL}`);
|
||||
console.log(`🔑 API Key: ${API_KEY.substring(0, 10)}...`);
|
||||
console.log(`📊 Proyectos a crear: ${projectsData.length}\n`);
|
||||
|
||||
let successCount = 0;
|
||||
let errorCount = 0;
|
||||
|
||||
for (let i = 0; i < projectsData.length; i++) {
|
||||
const project = projectsData[i];
|
||||
const num = i + 1;
|
||||
|
||||
console.log(`[${num}/${projectsData.length}] Creando: "${project.title}"...`);
|
||||
|
||||
try {
|
||||
// Crear proyecto
|
||||
const result = await createProject(project);
|
||||
console.log(` ✅ Proyecto creado con ID: ${result}`);
|
||||
|
||||
// Validar proyecto (cambiar a estado abierto)
|
||||
// Solo validar proyectos que no estén al 0% (borradores)
|
||||
if (project.opp_percent > 0) {
|
||||
console.log(` 📝 Validando proyecto...`);
|
||||
await validateProject(result);
|
||||
}
|
||||
|
||||
successCount++;
|
||||
|
||||
// Pequeña pausa entre creaciones
|
||||
await new Promise(resolve => setTimeout(resolve, 300));
|
||||
} catch (error) {
|
||||
console.error(` ❌ Error: ${error.message}`);
|
||||
errorCount++;
|
||||
}
|
||||
|
||||
console.log('');
|
||||
}
|
||||
|
||||
console.log('═'.repeat(60));
|
||||
console.log(`✨ Proceso completado!`);
|
||||
console.log(`✅ Exitosos: ${successCount}`);
|
||||
console.log(`❌ Errores: ${errorCount}`);
|
||||
console.log('═'.repeat(60));
|
||||
|
||||
if (successCount > 0) {
|
||||
console.log('\n💡 Ahora puedes recargar tu aplicación para ver los proyectos creados!');
|
||||
}
|
||||
}
|
||||
|
||||
// Ejecutar
|
||||
main().catch(error => {
|
||||
console.error('❌ Error fatal:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
|
@ -7,8 +7,8 @@ export interface DolibarrProject {
|
|||
ref: string;
|
||||
title: string;
|
||||
description: string;
|
||||
date_start: number; // timestamp
|
||||
date_end: number; // timestamp
|
||||
date_start: number | null; // timestamp (puede ser null)
|
||||
date_end: number | null; // timestamp (puede ser null)
|
||||
status: string;
|
||||
statut: string;
|
||||
budget_amount: string;
|
||||
|
|
@ -20,8 +20,8 @@ export interface DolibarrProject {
|
|||
public: string | number;
|
||||
usage_opportunity: string | number;
|
||||
usage_task: string | number;
|
||||
date_c: number; // fecha creación
|
||||
date_m: number; // fecha modificación
|
||||
date_c: number | null; // fecha creación (puede ser null)
|
||||
date_m: number | null; // fecha modificación (puede ser null)
|
||||
}
|
||||
|
||||
// Interface para usar en la UI (formato normalizado)
|
||||
|
|
@ -74,6 +74,14 @@ export function mapDolibarrProject(dolibarr: DolibarrProject): Project {
|
|||
const oppAmount = parseFloat(dolibarr.opp_amount || '0');
|
||||
const progress = parseFloat(dolibarr.opp_percent || '0');
|
||||
|
||||
// Helper para convertir timestamp de Dolibarr (segundos) a fecha ISO
|
||||
const timestampToDate = (timestamp: number | null | undefined): string => {
|
||||
if (!timestamp || timestamp === 0) {
|
||||
return new Date().toISOString().split('T')[0]; // Fecha actual por defecto
|
||||
}
|
||||
return new Date(timestamp * 1000).toISOString().split('T')[0];
|
||||
};
|
||||
|
||||
return {
|
||||
id: typeof dolibarr.id === 'string' ? parseInt(dolibarr.id) : dolibarr.id,
|
||||
ref: dolibarr.ref,
|
||||
|
|
@ -83,10 +91,10 @@ export function mapDolibarrProject(dolibarr: DolibarrProject): Project {
|
|||
progress: progress,
|
||||
budget: oppAmount || budget,
|
||||
spent: (oppAmount || budget) * (progress / 100), // Calcular gastado según progreso
|
||||
startDate: new Date(dolibarr.date_start * 1000).toISOString().split('T')[0],
|
||||
endDate: new Date(dolibarr.date_end * 1000).toISOString().split('T')[0],
|
||||
startDate: timestampToDate(dolibarr.date_start),
|
||||
endDate: timestampToDate(dolibarr.date_end),
|
||||
description: dolibarr.description || '',
|
||||
createdAt: new Date(dolibarr.date_c * 1000).toISOString().split('T')[0],
|
||||
updatedAt: new Date(dolibarr.date_m * 1000).toISOString().split('T')[0],
|
||||
createdAt: timestampToDate(dolibarr.date_c),
|
||||
updatedAt: timestampToDate(dolibarr.date_m),
|
||||
};
|
||||
}
|
||||
Loading…
Reference in New Issue