Initial commit: Horux Strategy Platform
- Laravel 11 backend with API REST - React 18 + TypeScript + Vite frontend - Multi-parser architecture for accounting systems (CONTPAQi, Aspel, SAP) - 27+ financial metrics calculation - PDF report generation with Browsershot - Complete documentation (10 documents) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
86
docs/01-descripcion-general.md
Normal file
86
docs/01-descripcion-general.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# 1. Descripción General
|
||||
|
||||
## ¿Qué es Horux Strategy?
|
||||
|
||||
Horux Strategy es una plataforma web para generar reportes financieros automatizados a partir de balanzas de comprobación. Permite a empresas subir sus datos contables de múltiples sistemas (CONTPAQi, Aspel, SAP, Odoo, etc.) y obtener:
|
||||
|
||||
- Dashboard interactivo con métricas financieras
|
||||
- Exportación a PDF profesional (32 páginas)
|
||||
- Clasificación automática de cuentas contables
|
||||
- Comparativos entre periodos
|
||||
- Semáforos de rendimiento (indicadores de salud financiera)
|
||||
|
||||
## Características Principales
|
||||
|
||||
### Para Analistas
|
||||
- Gestión de múltiples clientes
|
||||
- Subida y procesamiento de balanzas de comprobación
|
||||
- Revisión y corrección de anomalías contables
|
||||
- Generación de reportes financieros
|
||||
- Exportación a PDF
|
||||
|
||||
### Para Clientes
|
||||
- Dashboard personalizado de su empresa
|
||||
- Descarga de reportes en PDF
|
||||
- Gestión de empleados y permisos
|
||||
|
||||
### Para Administradores
|
||||
- Gestión completa de usuarios
|
||||
- Configuración de umbrales por industria
|
||||
- Reglas de mapeo contable por sistema
|
||||
- Catálogo de giros de negocio
|
||||
|
||||
## Stack Tecnológico
|
||||
|
||||
| Componente | Tecnología |
|
||||
|------------|------------|
|
||||
| Backend | Laravel 11 (PHP 8.2+) |
|
||||
| Frontend | React 18 + TypeScript |
|
||||
| Build Tool | Vite |
|
||||
| Base de Datos | MySQL / PostgreSQL |
|
||||
| Autenticación | Laravel Sanctum (tokens) |
|
||||
| Gráficas | Recharts |
|
||||
| Estilos | Tailwind CSS |
|
||||
| PDF | Browsershot (Puppeteer) |
|
||||
| Parsing PDF | spatie/pdf-to-text |
|
||||
| Excel | PhpSpreadsheet |
|
||||
|
||||
## Flujo de Trabajo
|
||||
|
||||
```
|
||||
1. Crear Cliente
|
||||
└── Nombre, logo, giro, moneda
|
||||
|
||||
2. Subir Balanzas (2+ archivos)
|
||||
└── PDF, Excel o CSV de diferentes periodos
|
||||
|
||||
3. Detección Automática
|
||||
└── Sistema identifica origen (CONTPAQi, Aspel, etc.)
|
||||
|
||||
4. Clasificación Automática
|
||||
└── Mapeo a categorías contables
|
||||
|
||||
5. Revisión de Anomalías
|
||||
└── Corregir cuentas mal clasificadas
|
||||
|
||||
6. Limpieza de Cuentas
|
||||
└── Excluir cuentas de estrategia fiscal
|
||||
|
||||
7. Generación de Reporte
|
||||
└── Cálculo de 27+ métricas
|
||||
|
||||
8. Dashboard Interactivo
|
||||
└── Visualización de resultados
|
||||
|
||||
9. Exportar PDF
|
||||
└── Reporte profesional de 32 páginas
|
||||
```
|
||||
|
||||
## Roles de Usuario
|
||||
|
||||
| Rol | Descripción | Permisos |
|
||||
|-----|-------------|----------|
|
||||
| **Admin** | Superusuario del sistema | Acceso total, configuración global, gestión de umbrales |
|
||||
| **Analista** | Operador de la plataforma | Gestionar clientes asignados, procesar balanzas, generar reportes |
|
||||
| **Cliente** | Usuario empresarial | Ver dashboard propio, descargar PDFs, gestionar empleados |
|
||||
| **Empleado** | Colaborador del cliente | Permisos configurables por el cliente |
|
||||
169
docs/02-arquitectura.md
Normal file
169
docs/02-arquitectura.md
Normal file
@@ -0,0 +1,169 @@
|
||||
# 2. Arquitectura del Sistema
|
||||
|
||||
## Diagrama de Componentes
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ FRONTEND (React) │
|
||||
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
||||
│ │ Login │ │Clientes │ │Dashboard│ │ Admin │ │ PdfView │ │
|
||||
│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │
|
||||
│ └───────────┴───────────┴───────────┴───────────┘ │
|
||||
│ │ │
|
||||
│ ┌─────────┴─────────┐ │
|
||||
│ │ API Service │ │
|
||||
│ │ (Axios) │ │
|
||||
│ └─────────┬─────────┘ │
|
||||
└──────────────────────────────┼──────────────────────────────────┘
|
||||
│ HTTP/REST
|
||||
▼
|
||||
┌──────────────────────────────┴──────────────────────────────────┐
|
||||
│ BACKEND (Laravel) │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ Controllers │ │
|
||||
│ │ Auth │ Cliente │ Balanza │ Cuenta │ Reporte │ Admin │ │
|
||||
│ └───────────────────────────┬─────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌───────────────────────────┴─────────────────────────────┐ │
|
||||
│ │ Services │ │
|
||||
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
|
||||
│ │ │ Parsers │ │ Clasificador │ │ Calculador │ │ │
|
||||
│ │ │ - CONTPAQi │ │ Cuentas │ │ Métricas │ │ │
|
||||
│ │ │ - Genérico │ │ │ │ │ │ │
|
||||
│ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │
|
||||
│ │ ┌──────────────┐ │ │
|
||||
│ │ │ Generador │ │ │
|
||||
│ │ │ PDF │ │ │
|
||||
│ │ └──────────────┘ │ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌───────────────────────────┴─────────────────────────────┐ │
|
||||
│ │ Models │ │
|
||||
│ │ User │ Cliente │ Balanza │ Cuenta │ Reporte │ etc. │ │
|
||||
│ └───────────────────────────┬─────────────────────────────┘ │
|
||||
└──────────────────────────────┼──────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ Database │
|
||||
│ MySQL/PostgreSQL│
|
||||
└──────────────────┘
|
||||
```
|
||||
|
||||
## Estructura de Directorios
|
||||
|
||||
```
|
||||
horux-strategy-platform/
|
||||
├── backend/ # Laravel 11 API
|
||||
│ ├── app/
|
||||
│ │ ├── Http/
|
||||
│ │ │ ├── Controllers/
|
||||
│ │ │ │ ├── AuthController.php
|
||||
│ │ │ │ ├── ClienteController.php
|
||||
│ │ │ │ ├── BalanzaController.php
|
||||
│ │ │ │ ├── CuentaController.php
|
||||
│ │ │ │ ├── ReporteController.php
|
||||
│ │ │ │ └── Admin/
|
||||
│ │ │ │ ├── UsuarioController.php
|
||||
│ │ │ │ ├── GiroController.php
|
||||
│ │ │ │ ├── UmbralController.php
|
||||
│ │ │ │ └── ReglaMapeeoController.php
|
||||
│ │ │ └── Middleware/
|
||||
│ │ │ └── RoleMiddleware.php
|
||||
│ │ ├── Models/
|
||||
│ │ │ ├── User.php
|
||||
│ │ │ ├── Cliente.php
|
||||
│ │ │ ├── Giro.php
|
||||
│ │ │ ├── Balanza.php
|
||||
│ │ │ ├── Cuenta.php
|
||||
│ │ │ ├── Reporte.php
|
||||
│ │ │ ├── ReporteContable.php
|
||||
│ │ │ ├── CategoriaContable.php
|
||||
│ │ │ ├── Umbral.php
|
||||
│ │ │ ├── ReglaMapeo.php
|
||||
│ │ │ ├── MapeoCuenta.php
|
||||
│ │ │ └── PermisoEmpleado.php
|
||||
│ │ └── Services/
|
||||
│ │ ├── Parsers/
|
||||
│ │ │ ├── ParserInterface.php
|
||||
│ │ │ ├── DetectorFormato.php
|
||||
│ │ │ ├── ContpaqiParser.php
|
||||
│ │ │ └── GenericoParser.php
|
||||
│ │ ├── ClasificadorCuentas.php
|
||||
│ │ ├── CalculadorMetricas.php
|
||||
│ │ └── GeneradorPdf.php
|
||||
│ ├── database/
|
||||
│ │ ├── migrations/
|
||||
│ │ └── seeders/
|
||||
│ ├── routes/
|
||||
│ │ └── api.php
|
||||
│ └── config/
|
||||
│
|
||||
├── frontend/ # React + TypeScript
|
||||
│ ├── src/
|
||||
│ │ ├── components/
|
||||
│ │ │ ├── charts/
|
||||
│ │ │ │ ├── BarChart.tsx
|
||||
│ │ │ │ └── LineChart.tsx
|
||||
│ │ │ ├── cards/
|
||||
│ │ │ │ ├── KPICard.tsx
|
||||
│ │ │ │ └── MetricTable.tsx
|
||||
│ │ │ ├── forms/
|
||||
│ │ │ │ ├── ClienteForm.tsx
|
||||
│ │ │ │ ├── UploadBalanza.tsx
|
||||
│ │ │ │ └── GenerarReporte.tsx
|
||||
│ │ │ └── layout/
|
||||
│ │ │ ├── Layout.tsx
|
||||
│ │ │ ├── Sidebar.tsx
|
||||
│ │ │ └── Header.tsx
|
||||
│ │ ├── pages/
|
||||
│ │ │ ├── Login.tsx
|
||||
│ │ │ ├── Clientes/
|
||||
│ │ │ ├── Dashboard/
|
||||
│ │ │ ├── PdfView/
|
||||
│ │ │ └── Admin/
|
||||
│ │ ├── context/
|
||||
│ │ │ └── AuthContext.tsx
|
||||
│ │ ├── services/
|
||||
│ │ │ └── api.ts
|
||||
│ │ ├── types/
|
||||
│ │ │ └── index.ts
|
||||
│ │ └── hooks/
|
||||
│ └── public/
|
||||
│
|
||||
└── docs/ # Documentación
|
||||
└── plans/
|
||||
```
|
||||
|
||||
## Flujo de Datos
|
||||
|
||||
### Subida de Balanza
|
||||
```
|
||||
1. Usuario sube archivo (PDF/Excel/CSV)
|
||||
2. DetectorFormato identifica sistema origen
|
||||
3. Parser específico extrae datos
|
||||
4. ClasificadorCuentas aplica reglas de mapeo
|
||||
5. Cuentas se guardan en BD con clasificación
|
||||
6. Cuentas con anomalías se marcan para revisión
|
||||
```
|
||||
|
||||
### Generación de Reporte
|
||||
```
|
||||
1. Usuario selecciona balanzas a incluir
|
||||
2. CalculadorMetricas procesa datos
|
||||
3. Se calculan estados financieros
|
||||
4. Se calculan 27+ métricas
|
||||
5. Se evalúan umbrales para semáforos
|
||||
6. Se guardan resultados en JSON
|
||||
7. Dashboard muestra resultados
|
||||
```
|
||||
|
||||
### Exportación PDF
|
||||
```
|
||||
1. Usuario solicita PDF
|
||||
2. GeneradorPdf prepara URL con token
|
||||
3. Browsershot renderiza PdfView de React
|
||||
4. Se genera PDF de 32 páginas
|
||||
5. Se guarda en storage
|
||||
6. Se descarga al usuario
|
||||
```
|
||||
205
docs/03-instalacion.md
Normal file
205
docs/03-instalacion.md
Normal file
@@ -0,0 +1,205 @@
|
||||
# 3. Instalación y Configuración
|
||||
|
||||
## Requisitos del Sistema
|
||||
|
||||
### Backend
|
||||
- PHP 8.2 o superior
|
||||
- Composer 2.x
|
||||
- MySQL 8.0+ o PostgreSQL 14+
|
||||
- Extensiones PHP: pdo_mysql, openssl, mbstring, fileinfo, gd
|
||||
|
||||
### Frontend
|
||||
- Node.js 18 o superior
|
||||
- npm o yarn
|
||||
|
||||
### Para generación de PDF
|
||||
- Node.js (para Puppeteer)
|
||||
- Chromium (se instala automáticamente)
|
||||
|
||||
---
|
||||
|
||||
## Instalación en Windows
|
||||
|
||||
### Opción 1: Usando Laragon (Recomendado)
|
||||
|
||||
1. **Descargar Laragon**
|
||||
- Visita https://laragon.org/download/
|
||||
- Descarga la versión "Full" (incluye PHP, MySQL, Composer)
|
||||
- Instala y ejecuta Laragon
|
||||
|
||||
2. **Configurar el proyecto**
|
||||
```bash
|
||||
# Copia el proyecto a C:\laragon\www\horux-strategy-platform
|
||||
|
||||
# Abre la terminal de Laragon (clic derecho > Terminal)
|
||||
cd horux-strategy-platform\backend
|
||||
composer install
|
||||
copy .env.example .env
|
||||
php artisan key:generate
|
||||
```
|
||||
|
||||
3. **Crear base de datos**
|
||||
- En Laragon, clic en "Database" > "MySQL"
|
||||
- Crea una base de datos llamada `horux_strategy`
|
||||
|
||||
4. **Ejecutar migraciones**
|
||||
```bash
|
||||
php artisan migrate --seed
|
||||
```
|
||||
|
||||
5. **Iniciar backend**
|
||||
```bash
|
||||
php artisan serve
|
||||
```
|
||||
|
||||
6. **Iniciar frontend** (otra terminal)
|
||||
```bash
|
||||
cd horux-strategy-platform\frontend
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Opción 2: Instalación Manual
|
||||
|
||||
1. **Instalar PHP**
|
||||
- Descarga de https://windows.php.net/download/
|
||||
- Versión: VS16 x64 Thread Safe
|
||||
- Extrae en `C:\php`
|
||||
- Agrega `C:\php` al PATH del sistema
|
||||
- Copia `php.ini-development` a `php.ini`
|
||||
- Edita `php.ini` y habilita:
|
||||
```ini
|
||||
extension=pdo_mysql
|
||||
extension=openssl
|
||||
extension=mbstring
|
||||
extension=fileinfo
|
||||
extension=gd
|
||||
```
|
||||
|
||||
2. **Instalar Composer**
|
||||
- Descarga de https://getcomposer.org/download/
|
||||
- Ejecuta el instalador
|
||||
|
||||
3. **Instalar MySQL**
|
||||
- Descarga de https://dev.mysql.com/downloads/mysql/
|
||||
- Durante instalación, anota usuario y contraseña
|
||||
|
||||
4. **Configurar proyecto** (igual que Opción 1, pasos 2-6)
|
||||
|
||||
---
|
||||
|
||||
## Instalación en Linux/Mac
|
||||
|
||||
```bash
|
||||
# Clonar o copiar el proyecto
|
||||
cd horux-strategy-platform
|
||||
|
||||
# Backend
|
||||
cd backend
|
||||
composer install
|
||||
cp .env.example .env
|
||||
php artisan key:generate
|
||||
|
||||
# Configurar .env con datos de MySQL
|
||||
nano .env
|
||||
|
||||
# Migraciones
|
||||
php artisan migrate --seed
|
||||
php artisan serve
|
||||
|
||||
# Frontend (otra terminal)
|
||||
cd ../frontend
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuración del Archivo .env
|
||||
|
||||
```env
|
||||
# Aplicación
|
||||
APP_NAME="Horux Strategy"
|
||||
APP_ENV=local
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://localhost:8000
|
||||
FRONTEND_URL=http://localhost:5173
|
||||
|
||||
# Base de Datos
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=horux_strategy
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=tu_password
|
||||
|
||||
# Sanctum (autenticación)
|
||||
SANCTUM_STATEFUL_DOMAINS=localhost:5173,127.0.0.1:5173
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Verificación de Instalación
|
||||
|
||||
### Backend
|
||||
```bash
|
||||
# Verificar que el servidor responde
|
||||
curl http://localhost:8000/api/giros
|
||||
# Debe retornar lista de giros en JSON
|
||||
```
|
||||
|
||||
### Frontend
|
||||
```bash
|
||||
# Abrir en navegador
|
||||
http://localhost:5173
|
||||
# Debe mostrar página de login
|
||||
```
|
||||
|
||||
### Credenciales de Prueba
|
||||
- **Email**: admin@horux360.com
|
||||
- **Password**: password
|
||||
|
||||
---
|
||||
|
||||
## Solución de Problemas
|
||||
|
||||
### Error: "php" no es reconocido
|
||||
- Verifica que PHP está en el PATH del sistema
|
||||
- Reinicia la terminal
|
||||
|
||||
### Error: SQLSTATE Connection refused
|
||||
- Verifica que MySQL está corriendo
|
||||
- Verifica credenciales en .env
|
||||
|
||||
### Error: CORS
|
||||
- Verifica FRONTEND_URL en .env
|
||||
- Verifica config/cors.php
|
||||
|
||||
### Error: 419 Page Expired
|
||||
- Ejecuta `php artisan config:clear`
|
||||
- Verifica SANCTUM_STATEFUL_DOMAINS
|
||||
|
||||
---
|
||||
|
||||
## Despliegue en Producción
|
||||
|
||||
### Backend
|
||||
```bash
|
||||
composer install --optimize-autoloader --no-dev
|
||||
php artisan config:cache
|
||||
php artisan route:cache
|
||||
php artisan view:cache
|
||||
```
|
||||
|
||||
### Frontend
|
||||
```bash
|
||||
npm run build
|
||||
# Servir carpeta dist/ con nginx/apache
|
||||
```
|
||||
|
||||
### Variables de Producción
|
||||
```env
|
||||
APP_ENV=production
|
||||
APP_DEBUG=false
|
||||
FRONTEND_URL=https://tu-dominio.com
|
||||
```
|
||||
322
docs/04-api-reference.md
Normal file
322
docs/04-api-reference.md
Normal file
@@ -0,0 +1,322 @@
|
||||
# 4. API Reference
|
||||
|
||||
## Base URL
|
||||
```
|
||||
http://localhost:8000/api
|
||||
```
|
||||
|
||||
## Autenticación
|
||||
|
||||
Todos los endpoints (excepto login) requieren token Bearer:
|
||||
```
|
||||
Authorization: Bearer {token}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Endpoints de Autenticación
|
||||
|
||||
### POST /login
|
||||
Iniciar sesión
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"email": "admin@horux360.com",
|
||||
"password": "password"
|
||||
}
|
||||
```
|
||||
|
||||
**Response 200:**
|
||||
```json
|
||||
{
|
||||
"user": {
|
||||
"id": 1,
|
||||
"nombre": "Administrador",
|
||||
"email": "admin@horux360.com",
|
||||
"role": "admin",
|
||||
"cliente_id": null
|
||||
},
|
||||
"token": "1|abc123..."
|
||||
}
|
||||
```
|
||||
|
||||
### POST /logout
|
||||
Cerrar sesión (requiere autenticación)
|
||||
|
||||
**Response 200:**
|
||||
```json
|
||||
{
|
||||
"message": "Sesión cerrada exitosamente"
|
||||
}
|
||||
```
|
||||
|
||||
### GET /user
|
||||
Obtener usuario actual
|
||||
|
||||
**Response 200:**
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"nombre": "Administrador",
|
||||
"email": "admin@horux360.com",
|
||||
"role": "admin",
|
||||
"cliente_id": null,
|
||||
"cliente": null
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Endpoints de Giros
|
||||
|
||||
### GET /giros
|
||||
Listar giros activos
|
||||
|
||||
**Response 200:**
|
||||
```json
|
||||
[
|
||||
{ "id": 1, "nombre": "Hotelería", "activo": true },
|
||||
{ "id": 2, "nombre": "Comercio", "activo": true }
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Endpoints de Clientes
|
||||
|
||||
### GET /clientes
|
||||
Listar clientes (filtrado por rol)
|
||||
|
||||
**Response 200:**
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"nombre_empresa": "Hotel Boutique HSA",
|
||||
"logo": "logos/abc123.png",
|
||||
"giro_id": 1,
|
||||
"moneda": "MXN",
|
||||
"giro": { "id": 1, "nombre": "Hotelería" }
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### POST /clientes
|
||||
Crear cliente (multipart/form-data)
|
||||
|
||||
**Request:**
|
||||
```
|
||||
nombre_empresa: Hotel Ejemplo
|
||||
giro_id: 1
|
||||
moneda: MXN
|
||||
logo: [archivo imagen]
|
||||
```
|
||||
|
||||
**Response 201:**
|
||||
```json
|
||||
{
|
||||
"id": 2,
|
||||
"nombre_empresa": "Hotel Ejemplo",
|
||||
"giro_id": 1,
|
||||
"moneda": "MXN",
|
||||
"logo": "logos/xyz789.png"
|
||||
}
|
||||
```
|
||||
|
||||
### GET /clientes/{id}
|
||||
Obtener cliente con balanzas y reportes
|
||||
|
||||
### PUT /clientes/{id}
|
||||
Actualizar cliente
|
||||
|
||||
### DELETE /clientes/{id}
|
||||
Eliminar cliente (solo admin)
|
||||
|
||||
---
|
||||
|
||||
## Endpoints de Balanzas
|
||||
|
||||
### GET /clientes/{id}/balanzas
|
||||
Listar balanzas de un cliente
|
||||
|
||||
**Response 200:**
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"cliente_id": 1,
|
||||
"periodo_inicio": "2024-01-01",
|
||||
"periodo_fin": "2024-12-31",
|
||||
"sistema_origen": "contpaqi",
|
||||
"status": "completado"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### POST /clientes/{id}/balanzas
|
||||
Subir balanza (multipart/form-data)
|
||||
|
||||
**Request:**
|
||||
```
|
||||
archivo: [archivo PDF/Excel/CSV]
|
||||
periodo_inicio: 2024-01-01
|
||||
periodo_fin: 2024-12-31
|
||||
```
|
||||
|
||||
**Response 201:**
|
||||
```json
|
||||
{
|
||||
"id": 2,
|
||||
"sistema_origen": "contpaqi",
|
||||
"status": "procesando"
|
||||
}
|
||||
```
|
||||
|
||||
### GET /balanzas/{id}/cuentas
|
||||
Listar cuentas de una balanza
|
||||
|
||||
**Response 200:**
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"codigo": "001-100-000",
|
||||
"nombre": "ACTIVO CIRCULANTE",
|
||||
"nivel": 1,
|
||||
"saldo_final_deudor": 1500000.00,
|
||||
"saldo_final_acreedor": 0,
|
||||
"excluida": false,
|
||||
"es_cuenta_padre": true,
|
||||
"requiere_revision": false,
|
||||
"categoria_contable": {
|
||||
"id": 1,
|
||||
"nombre": "Activos Circulantes"
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### PUT /balanzas/{id}/exclusiones
|
||||
Actualizar cuentas excluidas
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"exclusiones": [5, 12, 23]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Endpoints de Cuentas
|
||||
|
||||
### PUT /cuentas/{id}/clasificacion
|
||||
Corregir clasificación de cuenta
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"reporte_contable_id": 1,
|
||||
"categoria_contable_id": 3,
|
||||
"requiere_revision": false
|
||||
}
|
||||
```
|
||||
|
||||
### POST /cuentas/{id}/toggle-exclusion
|
||||
Alternar exclusión de cuenta
|
||||
|
||||
### GET /anomalias
|
||||
Listar cuentas que requieren revisión
|
||||
|
||||
---
|
||||
|
||||
## Endpoints de Reportes
|
||||
|
||||
### GET /clientes/{id}/reportes
|
||||
Listar reportes de un cliente
|
||||
|
||||
### POST /clientes/{id}/reportes
|
||||
Generar nuevo reporte
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"nombre": "Reporte Anual 2024",
|
||||
"balanza_ids": [1, 2, 3]
|
||||
}
|
||||
```
|
||||
|
||||
**Response 201:**
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"nombre": "Reporte Anual 2024",
|
||||
"periodo_tipo": "anual",
|
||||
"status": "completado",
|
||||
"data_calculada": { ... }
|
||||
}
|
||||
```
|
||||
|
||||
### GET /reportes/{id}
|
||||
Obtener reporte con datos calculados
|
||||
|
||||
### GET /reportes/{id}/pdf
|
||||
Descargar PDF del reporte
|
||||
|
||||
**Response:** Archivo PDF
|
||||
|
||||
### DELETE /reportes/{id}
|
||||
Eliminar reporte
|
||||
|
||||
---
|
||||
|
||||
## Endpoints de Administración
|
||||
|
||||
Requieren rol `admin`.
|
||||
|
||||
### Usuarios
|
||||
- `GET /admin/usuarios` - Listar usuarios
|
||||
- `POST /admin/usuarios` - Crear usuario
|
||||
- `PUT /admin/usuarios/{id}` - Actualizar usuario
|
||||
- `DELETE /admin/usuarios/{id}` - Eliminar usuario
|
||||
|
||||
### Giros
|
||||
- `GET /admin/giros` - Listar todos los giros
|
||||
- `POST /admin/giros` - Crear giro
|
||||
- `PUT /admin/giros/{id}` - Actualizar giro
|
||||
- `DELETE /admin/giros/{id}` - Eliminar giro
|
||||
|
||||
### Umbrales
|
||||
- `GET /admin/umbrales` - Listar umbrales
|
||||
- `POST /admin/umbrales` - Crear umbral
|
||||
- `PUT /admin/umbrales/{id}` - Actualizar umbral
|
||||
- `DELETE /admin/umbrales/{id}` - Eliminar umbral
|
||||
|
||||
### Reglas de Mapeo
|
||||
- `GET /admin/reglas-mapeo` - Listar reglas
|
||||
- `POST /admin/reglas-mapeo` - Crear regla
|
||||
- `PUT /admin/reglas-mapeo/{id}` - Actualizar regla
|
||||
- `DELETE /admin/reglas-mapeo/{id}` - Eliminar regla
|
||||
|
||||
---
|
||||
|
||||
## Códigos de Error
|
||||
|
||||
| Código | Descripción |
|
||||
|--------|-------------|
|
||||
| 401 | No autenticado |
|
||||
| 403 | No autorizado |
|
||||
| 404 | Recurso no encontrado |
|
||||
| 422 | Error de validación |
|
||||
| 500 | Error del servidor |
|
||||
|
||||
**Ejemplo error 422:**
|
||||
```json
|
||||
{
|
||||
"message": "The email field is required.",
|
||||
"errors": {
|
||||
"email": ["The email field is required."]
|
||||
}
|
||||
}
|
||||
```
|
||||
271
docs/05-frontend.md
Normal file
271
docs/05-frontend.md
Normal file
@@ -0,0 +1,271 @@
|
||||
# 5. Guía del Frontend
|
||||
|
||||
## Stack Tecnológico
|
||||
|
||||
- **React 18** - Biblioteca de UI
|
||||
- **TypeScript** - Tipado estático
|
||||
- **Vite** - Build tool y dev server
|
||||
- **React Router** - Navegación
|
||||
- **Axios** - Cliente HTTP
|
||||
- **Recharts** - Gráficas
|
||||
- **Tailwind CSS** - Estilos
|
||||
- **react-hot-toast** - Notificaciones
|
||||
- **react-dropzone** - Upload de archivos
|
||||
|
||||
---
|
||||
|
||||
## Estructura de Carpetas
|
||||
|
||||
```
|
||||
frontend/src/
|
||||
├── components/
|
||||
│ ├── charts/ # Componentes de gráficas
|
||||
│ │ ├── BarChart.tsx
|
||||
│ │ └── LineChart.tsx
|
||||
│ ├── cards/ # Tarjetas y tablas
|
||||
│ │ ├── KPICard.tsx
|
||||
│ │ └── MetricTable.tsx
|
||||
│ ├── forms/ # Formularios
|
||||
│ │ ├── ClienteForm.tsx
|
||||
│ │ ├── UploadBalanza.tsx
|
||||
│ │ └── GenerarReporte.tsx
|
||||
│ └── layout/ # Estructura de página
|
||||
│ ├── Layout.tsx
|
||||
│ ├── Sidebar.tsx
|
||||
│ └── Header.tsx
|
||||
├── pages/
|
||||
│ ├── Login.tsx
|
||||
│ ├── Clientes/
|
||||
│ │ ├── ClientesList.tsx
|
||||
│ │ └── ClienteDetail.tsx
|
||||
│ ├── Dashboard/
|
||||
│ │ └── index.tsx
|
||||
│ ├── PdfView/
|
||||
│ │ └── index.tsx
|
||||
│ └── Admin/
|
||||
│ ├── Usuarios.tsx
|
||||
│ ├── Giros.tsx
|
||||
│ ├── Umbrales.tsx
|
||||
│ └── ReglasMapeeo.tsx
|
||||
├── context/
|
||||
│ └── AuthContext.tsx
|
||||
├── services/
|
||||
│ └── api.ts
|
||||
├── types/
|
||||
│ └── index.ts
|
||||
└── hooks/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Contexto de Autenticación
|
||||
|
||||
```tsx
|
||||
// Uso del contexto
|
||||
import { useAuth } from '../context/AuthContext';
|
||||
|
||||
function MyComponent() {
|
||||
const { user, login, logout, isAdmin, isAnalista } = useAuth();
|
||||
|
||||
if (!user) return <Navigate to="/login" />;
|
||||
|
||||
return <div>Hola {user.nombre}</div>;
|
||||
}
|
||||
```
|
||||
|
||||
### Propiedades disponibles:
|
||||
- `user` - Usuario actual o null
|
||||
- `loading` - Estado de carga inicial
|
||||
- `login(email, password)` - Iniciar sesión
|
||||
- `logout()` - Cerrar sesión
|
||||
- `isAdmin` - Es administrador
|
||||
- `isAnalista` - Es analista
|
||||
- `isCliente` - Es cliente
|
||||
- `isEmpleado` - Es empleado
|
||||
|
||||
---
|
||||
|
||||
## Servicio API
|
||||
|
||||
```tsx
|
||||
import { clientesApi, balanzasApi, reportesApi } from '../services/api';
|
||||
|
||||
// Listar clientes
|
||||
const clientes = await clientesApi.list();
|
||||
|
||||
// Crear cliente
|
||||
const formData = new FormData();
|
||||
formData.append('nombre_empresa', 'Mi Empresa');
|
||||
formData.append('giro_id', '1');
|
||||
const cliente = await clientesApi.create(formData);
|
||||
|
||||
// Subir balanza
|
||||
const balanza = await balanzasApi.upload(clienteId, formData);
|
||||
|
||||
// Generar reporte
|
||||
const reporte = await reportesApi.create(clienteId, 'Reporte 2024', [1, 2]);
|
||||
|
||||
// Descargar PDF
|
||||
const blob = await reportesApi.downloadPdf(reporteId);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tipos TypeScript
|
||||
|
||||
```tsx
|
||||
// Principales tipos disponibles
|
||||
interface User {
|
||||
id: number;
|
||||
nombre: string;
|
||||
email: string;
|
||||
role: 'admin' | 'analista' | 'cliente' | 'empleado';
|
||||
cliente_id: number | null;
|
||||
}
|
||||
|
||||
interface Cliente {
|
||||
id: number;
|
||||
nombre_empresa: string;
|
||||
logo: string | null;
|
||||
giro_id: number;
|
||||
moneda: string;
|
||||
giro?: Giro;
|
||||
}
|
||||
|
||||
interface Balanza {
|
||||
id: number;
|
||||
cliente_id: number;
|
||||
periodo_inicio: string;
|
||||
periodo_fin: string;
|
||||
sistema_origen: string;
|
||||
status: 'pendiente' | 'procesando' | 'completado' | 'error';
|
||||
}
|
||||
|
||||
interface Reporte {
|
||||
id: number;
|
||||
nombre: string;
|
||||
periodo_tipo: 'mensual' | 'trimestral' | 'anual';
|
||||
data_calculada: DataCalculada | null;
|
||||
status: string;
|
||||
}
|
||||
|
||||
type Tendencia = 'muy_positivo' | 'positivo' | 'neutral' | 'negativo' | 'muy_negativo';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Componentes Reutilizables
|
||||
|
||||
### KPICard
|
||||
```tsx
|
||||
<KPICard
|
||||
title="Ingresos"
|
||||
value="$1,500,000"
|
||||
subtitle="12% vs mes anterior"
|
||||
tendencia="positivo"
|
||||
/>
|
||||
```
|
||||
|
||||
### MetricTable
|
||||
```tsx
|
||||
<MetricTable
|
||||
title="Márgenes"
|
||||
metricas={[
|
||||
{ nombre: 'Margen Bruto', valor: 0.45, tendencia: 'positivo' },
|
||||
{ nombre: 'Margen Neto', valor: 0.12, tendencia: 'neutral' },
|
||||
]}
|
||||
/>
|
||||
```
|
||||
|
||||
### BarChart
|
||||
```tsx
|
||||
<BarChartComponent
|
||||
data={[
|
||||
{ name: 'Ingresos', valor: 1500000 },
|
||||
{ name: 'Gastos', valor: -800000 },
|
||||
]}
|
||||
horizontal={false}
|
||||
/>
|
||||
```
|
||||
|
||||
### LineChart
|
||||
```tsx
|
||||
<LineChartComponent
|
||||
data={periodos.map(p => ({
|
||||
periodo: p.periodo,
|
||||
'Margen Bruto': p.margen_bruto * 100,
|
||||
'Margen Neto': p.margen_neto * 100,
|
||||
}))}
|
||||
lines={['Margen Bruto', 'Margen Neto']}
|
||||
/>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Estilos con Tailwind
|
||||
|
||||
### Clases personalizadas (index.css)
|
||||
```css
|
||||
.btn { @apply px-4 py-2 rounded-lg font-medium transition-colors; }
|
||||
.btn-primary { @apply bg-primary-600 text-white hover:bg-primary-700; }
|
||||
.btn-secondary { @apply bg-gray-200 text-gray-800 hover:bg-gray-300; }
|
||||
.input { @apply w-full px-3 py-2 border rounded-lg focus:ring-2 focus:ring-primary-500; }
|
||||
.card { @apply bg-white rounded-xl shadow-sm border border-gray-100 p-6; }
|
||||
.label { @apply block text-sm font-medium text-gray-700 mb-1; }
|
||||
```
|
||||
|
||||
### Colores de marca (tailwind.config.js)
|
||||
```js
|
||||
colors: {
|
||||
horux: {
|
||||
dark: '#1a1a2e',
|
||||
primary: '#16213e',
|
||||
accent: '#0f3460',
|
||||
highlight: '#e94560',
|
||||
},
|
||||
status: {
|
||||
'muy-positivo': '#10b981',
|
||||
'positivo': '#34d399',
|
||||
'neutral': '#fbbf24',
|
||||
'negativo': '#f97316',
|
||||
'muy-negativo': '#ef4444',
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Rutas
|
||||
|
||||
| Ruta | Componente | Rol requerido |
|
||||
|------|------------|---------------|
|
||||
| `/login` | Login | Público |
|
||||
| `/clientes` | ClientesList | Autenticado |
|
||||
| `/clientes/:id` | ClienteDetail | Autenticado |
|
||||
| `/dashboard/:clienteId/:reporteId` | Dashboard | Autenticado |
|
||||
| `/pdf-view/:id` | PdfView | Token especial |
|
||||
| `/admin/usuarios` | AdminUsuarios | Admin |
|
||||
| `/admin/giros` | AdminGiros | Admin |
|
||||
| `/admin/umbrales` | AdminUmbrales | Admin |
|
||||
| `/admin/reglas-mapeo` | AdminReglasMapeeo | Admin |
|
||||
|
||||
---
|
||||
|
||||
## Desarrollo
|
||||
|
||||
```bash
|
||||
# Instalar dependencias
|
||||
npm install
|
||||
|
||||
# Servidor de desarrollo
|
||||
npm run dev
|
||||
|
||||
# Build para producción
|
||||
npm run build
|
||||
|
||||
# Preview del build
|
||||
npm run preview
|
||||
|
||||
# Linting
|
||||
npm run lint
|
||||
```
|
||||
241
docs/06-base-de-datos.md
Normal file
241
docs/06-base-de-datos.md
Normal file
@@ -0,0 +1,241 @@
|
||||
# 6. Base de Datos
|
||||
|
||||
## Diagrama Entidad-Relación
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ giros │ │ clientes │ │ users │
|
||||
├─────────────┤ ├─────────────┤ ├─────────────┤
|
||||
│ id │◄──────┤ giro_id │ │ id │
|
||||
│ nombre │ │ id │◄──────┤ cliente_id │
|
||||
│ activo │ │ nombre_emp │ │ nombre │
|
||||
└─────────────┘ │ logo │ │ email │
|
||||
│ moneda │ │ password │
|
||||
│ config │ │ role │
|
||||
└──────┬──────┘ └─────────────┘
|
||||
│
|
||||
┌──────────────┼──────────────┐
|
||||
▼ ▼ ▼
|
||||
┌─────────────┐┌─────────────┐┌─────────────┐
|
||||
│ balanzas ││ reportes ││mapeo_cuentas│
|
||||
├─────────────┤├─────────────┤├─────────────┤
|
||||
│ id ││ id ││ id │
|
||||
│ cliente_id ││ cliente_id ││ cliente_id │
|
||||
│ periodo_ini ││ nombre ││ codigo_pat │
|
||||
│ periodo_fin ││ periodo_tipo││ categoria_id│
|
||||
│ sistema_orig││ data_calc │└─────────────┘
|
||||
│ status ││ pdf_path │
|
||||
└──────┬──────┘└─────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────┐
|
||||
│ cuentas │
|
||||
├─────────────┤
|
||||
│ id │
|
||||
│ balanza_id │
|
||||
│ codigo │
|
||||
│ nombre │
|
||||
│ nivel │
|
||||
│ saldos... │
|
||||
│ excluida │
|
||||
│ categoria_id│
|
||||
└─────────────┘
|
||||
|
||||
┌─────────────────┐ ┌─────────────────┐
|
||||
│reportes_contable│ │categorias_contab│
|
||||
├─────────────────┤ ├─────────────────┤
|
||||
│ id │◄────┤ reporte_cont_id │
|
||||
│ nombre │ │ id │
|
||||
└─────────────────┘ │ nombre │
|
||||
│ orden │
|
||||
└────────┬────────┘
|
||||
│
|
||||
┌────────┴────────┐
|
||||
▼ ▼
|
||||
┌─────────────┐ ┌─────────────┐
|
||||
│reglas_mapeo │ │ umbrales │
|
||||
├─────────────┤ ├─────────────┤
|
||||
│ sistema_orig│ │ metrica │
|
||||
│ rango_ini │ │ muy_positivo│
|
||||
│ rango_fin │ │ positivo │
|
||||
│ categoria_id│ │ neutral │
|
||||
│ prioridad │ │ negativo │
|
||||
└─────────────┘ │ muy_negativo│
|
||||
│ giro_id │
|
||||
└─────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tablas
|
||||
|
||||
### users
|
||||
Usuarios del sistema.
|
||||
|
||||
| Campo | Tipo | Descripción |
|
||||
|-------|------|-------------|
|
||||
| id | bigint | PK |
|
||||
| nombre | varchar(255) | Nombre completo |
|
||||
| email | varchar(255) | Email único |
|
||||
| password | varchar(255) | Hash de contraseña |
|
||||
| role | enum | admin, analista, cliente, empleado |
|
||||
| cliente_id | bigint | FK a clientes (nullable) |
|
||||
|
||||
### clientes
|
||||
Empresas registradas.
|
||||
|
||||
| Campo | Tipo | Descripción |
|
||||
|-------|------|-------------|
|
||||
| id | bigint | PK |
|
||||
| nombre_empresa | varchar(255) | Nombre de la empresa |
|
||||
| logo | varchar(255) | Path al logo |
|
||||
| giro_id | bigint | FK a giros |
|
||||
| moneda | varchar(3) | MXN, USD, EUR |
|
||||
| configuracion | json | Configuración adicional |
|
||||
|
||||
### giros
|
||||
Catálogo de giros de negocio.
|
||||
|
||||
| Campo | Tipo | Descripción |
|
||||
|-------|------|-------------|
|
||||
| id | bigint | PK |
|
||||
| nombre | varchar(255) | Nombre del giro |
|
||||
| activo | boolean | Estado |
|
||||
|
||||
### balanzas
|
||||
Archivos de balanza subidos.
|
||||
|
||||
| Campo | Tipo | Descripción |
|
||||
|-------|------|-------------|
|
||||
| id | bigint | PK |
|
||||
| cliente_id | bigint | FK a clientes |
|
||||
| periodo_inicio | date | Inicio del periodo |
|
||||
| periodo_fin | date | Fin del periodo |
|
||||
| sistema_origen | varchar(50) | contpaqi, aspel, etc. |
|
||||
| archivo_original | varchar(255) | Path al archivo |
|
||||
| status | enum | pendiente, procesando, completado, error |
|
||||
| error_mensaje | text | Mensaje de error si aplica |
|
||||
|
||||
### cuentas
|
||||
Cuentas extraídas de balanzas.
|
||||
|
||||
| Campo | Tipo | Descripción |
|
||||
|-------|------|-------------|
|
||||
| id | bigint | PK |
|
||||
| balanza_id | bigint | FK a balanzas |
|
||||
| codigo | varchar(20) | Código de cuenta (ej: 001-100-000) |
|
||||
| nombre | varchar(255) | Nombre de la cuenta |
|
||||
| nivel | int | Nivel jerárquico (1, 2, 3) |
|
||||
| reporte_contable_id | bigint | FK a reportes_contables |
|
||||
| categoria_contable_id | bigint | FK a categorias_contables |
|
||||
| cuenta_padre_id | bigint | FK a cuentas (self-reference) |
|
||||
| saldo_inicial_deudor | decimal(18,2) | |
|
||||
| saldo_inicial_acreedor | decimal(18,2) | |
|
||||
| cargos | decimal(18,2) | |
|
||||
| abonos | decimal(18,2) | |
|
||||
| saldo_final_deudor | decimal(18,2) | |
|
||||
| saldo_final_acreedor | decimal(18,2) | |
|
||||
| excluida | boolean | Excluida del cálculo |
|
||||
| es_cuenta_padre | boolean | Es cuenta padre |
|
||||
| requiere_revision | boolean | Necesita revisión manual |
|
||||
| nota_revision | text | Nota sobre la anomalía |
|
||||
|
||||
### reportes_contables
|
||||
Tipos de reporte (Balance, Estado de Resultados).
|
||||
|
||||
| Campo | Tipo | Descripción |
|
||||
|-------|------|-------------|
|
||||
| id | bigint | PK |
|
||||
| nombre | varchar(255) | "Balance General", "Estado de Resultados" |
|
||||
|
||||
### categorias_contables
|
||||
Categorías dentro de cada reporte.
|
||||
|
||||
| Campo | Tipo | Descripción |
|
||||
|-------|------|-------------|
|
||||
| id | bigint | PK |
|
||||
| reporte_contable_id | bigint | FK a reportes_contables |
|
||||
| nombre | varchar(255) | Nombre de la categoría |
|
||||
| orden | int | Orden de aparición |
|
||||
|
||||
**Categorías de Balance General:**
|
||||
1. Activos Circulantes
|
||||
2. Activos No Circulantes
|
||||
3. Pasivo Circulante
|
||||
4. Pasivo No Circulante
|
||||
5. Capital Social
|
||||
6. Pérdidas Ejercicios Anteriores
|
||||
7. Utilidades Ejercicios Anteriores
|
||||
|
||||
**Categorías de Estado de Resultados:**
|
||||
1. Ingresos
|
||||
2. Costo de Venta
|
||||
3. Gastos Operativos
|
||||
4. Otros Gastos
|
||||
5. Gastos Financieros
|
||||
|
||||
### reglas_mapeo
|
||||
Reglas para clasificar cuentas automáticamente.
|
||||
|
||||
| Campo | Tipo | Descripción |
|
||||
|-------|------|-------------|
|
||||
| id | bigint | PK |
|
||||
| sistema_origen | varchar(50) | contpaqi, aspel, etc. |
|
||||
| cuenta_padre_codigo | varchar(20) | Código de cuenta padre |
|
||||
| rango_inicio | varchar(20) | Inicio del rango de códigos |
|
||||
| rango_fin | varchar(20) | Fin del rango |
|
||||
| patron_regex | varchar(255) | Patrón regex alternativo |
|
||||
| reporte_contable_id | bigint | FK |
|
||||
| categoria_contable_id | bigint | FK |
|
||||
| prioridad | int | Mayor = se evalúa primero |
|
||||
| activo | boolean | Regla activa |
|
||||
|
||||
### umbrales
|
||||
Umbrales para semáforos de métricas.
|
||||
|
||||
| Campo | Tipo | Descripción |
|
||||
|-------|------|-------------|
|
||||
| id | bigint | PK |
|
||||
| metrica | varchar(100) | Nombre de la métrica |
|
||||
| muy_positivo | decimal(10,4) | Umbral muy positivo |
|
||||
| positivo | decimal(10,4) | Umbral positivo |
|
||||
| neutral | decimal(10,4) | Umbral neutral |
|
||||
| negativo | decimal(10,4) | Umbral negativo |
|
||||
| muy_negativo | decimal(10,4) | Umbral muy negativo |
|
||||
| giro_id | bigint | FK a giros (nullable = general) |
|
||||
|
||||
### reportes
|
||||
Reportes generados.
|
||||
|
||||
| Campo | Tipo | Descripción |
|
||||
|-------|------|-------------|
|
||||
| id | bigint | PK |
|
||||
| cliente_id | bigint | FK a clientes |
|
||||
| nombre | varchar(255) | Nombre del reporte |
|
||||
| periodo_tipo | enum | mensual, trimestral, anual |
|
||||
| periodo_inicio | date | |
|
||||
| periodo_fin | date | |
|
||||
| fecha_generacion | timestamp | |
|
||||
| data_calculada | json | Métricas y estados financieros |
|
||||
| pdf_path | varchar(255) | Path al PDF generado |
|
||||
| status | enum | pendiente, procesando, completado, error |
|
||||
|
||||
### reporte_balanza
|
||||
Tabla pivote reporte-balanza.
|
||||
|
||||
| Campo | Tipo | Descripción |
|
||||
|-------|------|-------------|
|
||||
| reporte_id | bigint | FK a reportes |
|
||||
| balanza_id | bigint | FK a balanzas |
|
||||
|
||||
---
|
||||
|
||||
## Seeders
|
||||
|
||||
Los seeders iniciales crean:
|
||||
|
||||
1. **GirosSeeder** - 24 giros de negocio
|
||||
2. **ReportesContablesSeeder** - 2 reportes + 12 categorías
|
||||
3. **ReglasMapeeoContpaqiSeeder** - 12 reglas para CONTPAQi
|
||||
4. **UmbralesSeeder** - 24 umbrales por defecto
|
||||
5. **AdminUserSeeder** - Usuario admin inicial
|
||||
253
docs/07-parsers.md
Normal file
253
docs/07-parsers.md
Normal file
@@ -0,0 +1,253 @@
|
||||
# 7. Parsers de Balanzas
|
||||
|
||||
## Arquitectura
|
||||
|
||||
```
|
||||
Upload archivo
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ DetectorFormato │ ← Detecta el sistema origen
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ Parser Específico│
|
||||
│ - ContpaqiParser│
|
||||
│ - GenericoParser│
|
||||
│ - (futuro: Aspel)│
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ Formato Standard│ ← Estructura normalizada
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ ClasificadorCtas│ ← Aplica reglas de mapeo
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Interface ParserInterface
|
||||
|
||||
Todos los parsers deben implementar:
|
||||
|
||||
```php
|
||||
interface ParserInterface
|
||||
{
|
||||
/**
|
||||
* Parsea archivo y retorna array de cuentas normalizadas
|
||||
*/
|
||||
public function parsear(string $filePath): array;
|
||||
|
||||
/**
|
||||
* Verifica si puede manejar el archivo
|
||||
*/
|
||||
public function puedeManej(string $filePath): bool;
|
||||
|
||||
/**
|
||||
* Retorna identificador del sistema
|
||||
*/
|
||||
public function getSistema(): string;
|
||||
}
|
||||
```
|
||||
|
||||
### Estructura de cuenta normalizada:
|
||||
|
||||
```php
|
||||
[
|
||||
'codigo' => '001-100-000',
|
||||
'nombre' => 'ACTIVO CIRCULANTE',
|
||||
'nivel' => 1,
|
||||
'saldo_inicial_deudor' => 1500000.00,
|
||||
'saldo_inicial_acreedor' => 0.00,
|
||||
'cargos' => 500000.00,
|
||||
'abonos' => 200000.00,
|
||||
'saldo_final_deudor' => 1800000.00,
|
||||
'saldo_final_acreedor' => 0.00,
|
||||
'es_cuenta_padre' => true,
|
||||
'cuenta_padre_codigo' => null, // opcional
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## DetectorFormato
|
||||
|
||||
Detecta automáticamente el sistema origen del archivo.
|
||||
|
||||
```php
|
||||
class DetectorFormato
|
||||
{
|
||||
private array $parsers = [
|
||||
new ContpaqiParser(),
|
||||
// new AspelParser(),
|
||||
// new SapParser(),
|
||||
new GenericoParser(), // Fallback
|
||||
];
|
||||
|
||||
public function detectar(string $filePath): array
|
||||
{
|
||||
foreach ($this->parsers as $parser) {
|
||||
if ($parser->puedeManej($filePath)) {
|
||||
return [
|
||||
'sistema' => $parser->getSistema(),
|
||||
'parser' => $parser,
|
||||
];
|
||||
}
|
||||
}
|
||||
throw new Exception('Formato no reconocido');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ContpaqiParser
|
||||
|
||||
Parser para balanzas de CONTPAQi.
|
||||
|
||||
### Detección
|
||||
Busca patrones característicos en el PDF:
|
||||
- Texto "CONTPAQ" o "CONTPAQi"
|
||||
- Patrón de códigos: `\d{3}-\d{3}-\d{3}`
|
||||
- Encabezados típicos: "Saldo Inicial", "Debe", "Haber"
|
||||
|
||||
### Formato de código CONTPAQi
|
||||
```
|
||||
XXX-XXX-XXX
|
||||
│ │ │
|
||||
│ │ └── Detalle (000 = padre)
|
||||
│ └────── Subcuenta (000 = padre)
|
||||
└────────── Mayor
|
||||
```
|
||||
|
||||
Ejemplos:
|
||||
- `001-100-000` → Nivel 1 (Mayor: Activo Circulante)
|
||||
- `101-000-000` → Nivel 2 (Subcuenta: Caja)
|
||||
- `101-001-000` → Nivel 3 (Detalle)
|
||||
|
||||
### Reglas de mapeo CONTPAQi
|
||||
|
||||
| Cuenta Padre | Rango Hijos | Categoría |
|
||||
|--------------|-------------|-----------|
|
||||
| 001-100-000 | 101-000-000 a 154-999-999 | Activos Circulantes |
|
||||
| 001-200-000 | 155-000-000 a 199-999-999 | Activos No Circulantes |
|
||||
| 002-100-000 | 200-000-000 a 209-999-999 | Pasivo Circulante |
|
||||
| 002-200-000 | 210-000-000 a 220-999-999 | Pasivo No Circulante |
|
||||
| 30X-XXX-XXX | - | Capital Social |
|
||||
| 310-XXX-XXX | - | Pérdidas Anteriores |
|
||||
| 311-XXX-XXX | - | Utilidades Anteriores |
|
||||
| 40X-XXX-XXX | - | Ingresos |
|
||||
| 5XX-XXX-XXX | - | Gastos Operativos |
|
||||
| 6XX-XXX-XXX | - | Otros Gastos |
|
||||
| 7XX-XXX-XXX | - | Gastos Financieros |
|
||||
|
||||
---
|
||||
|
||||
## GenericoParser
|
||||
|
||||
Parser para archivos Excel/CSV genéricos.
|
||||
|
||||
### Formatos soportados
|
||||
- `.xlsx` - Excel 2007+
|
||||
- `.xls` - Excel 97-2003
|
||||
- `.csv` - Valores separados por coma/punto y coma
|
||||
|
||||
### Detección de columnas
|
||||
Busca headers similares a:
|
||||
|
||||
| Campo | Aliases aceptados |
|
||||
|-------|-------------------|
|
||||
| codigo | codigo, cuenta, code, account, cta, numero |
|
||||
| nombre | nombre, descripcion, name, description, concepto |
|
||||
| saldo_inicial_deudor | saldo_inicial_deudor, inicial_debe, opening_debit |
|
||||
| cargos | cargos, debe, debit, debits, movs_deudor |
|
||||
| abonos | abonos, haber, credit, credits, movs_acreedor |
|
||||
| saldo_final_deudor | saldo_final_deudor, final_debe, closing_debit |
|
||||
|
||||
### Detección de delimitador CSV
|
||||
Detecta automáticamente: `,`, `;`, `\t`, `|`
|
||||
|
||||
---
|
||||
|
||||
## Agregar Nuevo Parser
|
||||
|
||||
1. **Crear clase** en `app/Services/Parsers/`:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Services\Parsers;
|
||||
|
||||
class AspelParser implements ParserInterface
|
||||
{
|
||||
public function getSistema(): string
|
||||
{
|
||||
return 'aspel';
|
||||
}
|
||||
|
||||
public function puedeManej(string $filePath): bool
|
||||
{
|
||||
// Lógica de detección para Aspel
|
||||
$text = file_get_contents($filePath);
|
||||
return str_contains(strtoupper($text), 'ASPEL');
|
||||
}
|
||||
|
||||
public function parsear(string $filePath): array
|
||||
{
|
||||
// Lógica de parsing
|
||||
$cuentas = [];
|
||||
// ... extraer datos ...
|
||||
return $cuentas;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. **Registrar en DetectorFormato**:
|
||||
|
||||
```php
|
||||
// En DetectorFormato::__construct()
|
||||
$this->parsers = [
|
||||
new ContpaqiParser(),
|
||||
new AspelParser(), // ← Agregar antes de GenericoParser
|
||||
new GenericoParser(),
|
||||
];
|
||||
```
|
||||
|
||||
3. **Agregar reglas de mapeo** en seeder:
|
||||
|
||||
```php
|
||||
// Crear nuevo seeder: ReglasMapeeoAspelSeeder.php
|
||||
ReglaMapeo::create([
|
||||
'sistema_origen' => 'aspel',
|
||||
'patron_regex' => '/^1\d{3}/',
|
||||
'reporte_contable_id' => $balance->id,
|
||||
'categoria_contable_id' => $activosCirc->id,
|
||||
'prioridad' => 10,
|
||||
]);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ClasificadorCuentas
|
||||
|
||||
Aplica reglas de mapeo a las cuentas importadas.
|
||||
|
||||
### Proceso:
|
||||
1. Buscar mapeo específico del cliente
|
||||
2. Si no existe, buscar regla del sistema
|
||||
3. Si no existe regla, marcar para revisión
|
||||
|
||||
### Detección de anomalías:
|
||||
- Cuentas 45X (normalmente pasivo) usadas como gasto
|
||||
- Cuentas 8XX-9XX (cuentas de orden)
|
||||
- Códigos sin regla de mapeo
|
||||
|
||||
```php
|
||||
// Ejemplo de nota de revisión automática
|
||||
"Código 45X normalmente es pasivo pero podría ser gasto. Verificar clasificación."
|
||||
```
|
||||
232
docs/08-metricas.md
Normal file
232
docs/08-metricas.md
Normal file
@@ -0,0 +1,232 @@
|
||||
# 8. Métricas Financieras
|
||||
|
||||
## Resumen
|
||||
|
||||
El sistema calcula **27+ métricas financieras** organizadas en 6 categorías:
|
||||
|
||||
| Categoría | # Métricas |
|
||||
|-----------|------------|
|
||||
| Márgenes | 7 |
|
||||
| Retorno | 4 |
|
||||
| Eficiencia | 6 |
|
||||
| Liquidez | 3 |
|
||||
| Solvencia | 3 |
|
||||
| Gestión | 4 |
|
||||
|
||||
---
|
||||
|
||||
## Estados Financieros Base
|
||||
|
||||
### Balance General
|
||||
|
||||
```
|
||||
ACTIVOS
|
||||
├── Activos Circulantes
|
||||
│ ├── Efectivo
|
||||
│ ├── Cuentas por Cobrar
|
||||
│ └── Inventarios
|
||||
├── Activos No Circulantes
|
||||
│ ├── Propiedad, Planta y Equipo
|
||||
│ └── Activos Intangibles
|
||||
└── TOTAL ACTIVOS
|
||||
|
||||
PASIVOS
|
||||
├── Pasivo Circulante
|
||||
│ ├── Cuentas por Pagar
|
||||
│ └── Deuda Corto Plazo
|
||||
├── Pasivo No Circulante
|
||||
│ └── Deuda Largo Plazo
|
||||
└── TOTAL PASIVOS
|
||||
|
||||
CAPITAL
|
||||
├── Capital Social
|
||||
├── Utilidades Retenidas
|
||||
└── TOTAL CAPITAL
|
||||
|
||||
TOTAL PASIVOS + CAPITAL = TOTAL ACTIVOS
|
||||
```
|
||||
|
||||
### Estado de Resultados
|
||||
|
||||
```
|
||||
Ingresos
|
||||
(-) Costo de Venta
|
||||
= Utilidad Bruta
|
||||
(-) Gastos Operativos
|
||||
= Utilidad Operativa (EBIT)
|
||||
(-) Otros Gastos
|
||||
(-) Gastos Financieros
|
||||
= Utilidad Antes de Impuestos (EBT)
|
||||
(-) Impuestos
|
||||
= UTILIDAD NETA
|
||||
```
|
||||
|
||||
### Flujo de Efectivo (Método Indirecto)
|
||||
|
||||
```
|
||||
FLUJO DE OPERACIÓN
|
||||
Utilidad Neta
|
||||
+ Depreciación
|
||||
- Cambios en Capital de Trabajo
|
||||
|
||||
FLUJO DE INVERSIÓN
|
||||
- Adquisición de Activos Fijos
|
||||
+ Venta de Activos
|
||||
|
||||
FLUJO DE FINANCIAMIENTO
|
||||
+ Nueva Deuda
|
||||
- Pago de Deuda
|
||||
+ Aportaciones de Capital
|
||||
- Dividendos
|
||||
|
||||
= FLUJO NETO
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Métricas por Categoría
|
||||
|
||||
### 1. Márgenes
|
||||
|
||||
| Métrica | Fórmula | Interpretación |
|
||||
|---------|---------|----------------|
|
||||
| **Margen Bruto** | Utilidad Bruta / Ingresos | Rentabilidad después de costos directos |
|
||||
| **Margen EBITDA** | EBITDA / Ingresos | Rentabilidad operativa antes de D&A |
|
||||
| **Margen Operativo** | EBIT / Ingresos | Rentabilidad operativa |
|
||||
| **Margen Neto** | Utilidad Neta / Ingresos | Rentabilidad final |
|
||||
| **Margen NOPAT** | NOPAT / Ingresos | Utilidad operativa después de impuestos |
|
||||
| **Margen OCF** | Flujo Operación / Ingresos | Generación de efectivo operativo |
|
||||
| **Margen FCF** | Flujo Libre / Ingresos | Efectivo disponible |
|
||||
|
||||
Donde:
|
||||
- EBITDA = EBIT + Depreciación + Amortización
|
||||
- NOPAT = EBIT × (1 - Tasa Impuestos)
|
||||
- FCF = Flujo Operación - CapEx
|
||||
|
||||
### 2. Retorno
|
||||
|
||||
| Métrica | Fórmula | Interpretación |
|
||||
|---------|---------|----------------|
|
||||
| **ROIC** | NOPAT / Capital Invertido | Retorno sobre capital invertido |
|
||||
| **ROE** | Utilidad Neta / Capital | Retorno para accionistas |
|
||||
| **ROA** | Utilidad Neta / Activo Total | Eficiencia de activos |
|
||||
| **ROCE** | EBIT / Capital Empleado | Retorno sobre capital empleado |
|
||||
|
||||
Donde:
|
||||
- Capital Invertido = Activo Total - Pasivo Circulante
|
||||
- Capital Empleado = Activo Total - Pasivo Circulante
|
||||
|
||||
### 3. Eficiencia
|
||||
|
||||
| Métrica | Fórmula | Interpretación |
|
||||
|---------|---------|----------------|
|
||||
| **Asset Turnover** | Ingresos / Activo Total | Rotación de activos |
|
||||
| **Inventory Turnover** | Costo Venta / Inventario | Rotación de inventario |
|
||||
| **Días Clientes** | (Clientes / Ingresos) × 365 | Días para cobrar |
|
||||
| **Días Proveedores** | (Proveedores / Costo) × 365 | Días para pagar |
|
||||
| **Días Inventario** | (Inventario / Costo) × 365 | Días de inventario |
|
||||
| **Ciclo Conversión** | Días Clientes + Días Inv. - Días Prov. | Ciclo de efectivo |
|
||||
|
||||
### 4. Liquidez
|
||||
|
||||
| Métrica | Fórmula | Interpretación |
|
||||
|---------|---------|----------------|
|
||||
| **Current Ratio** | Activo Circ. / Pasivo Circ. | Capacidad de pago corto plazo |
|
||||
| **Quick Ratio** | (Activo Circ. - Inv.) / Pasivo Circ. | Liquidez sin inventario |
|
||||
| **Cash Ratio** | Efectivo / Pasivo Circ. | Liquidez inmediata |
|
||||
|
||||
### 5. Solvencia
|
||||
|
||||
| Métrica | Fórmula | Interpretación |
|
||||
|---------|---------|----------------|
|
||||
| **Net Debt/EBITDA** | (Deuda - Efectivo) / EBITDA | Años para pagar deuda |
|
||||
| **Interest Coverage** | EBITDA / Gastos Financieros | Cobertura de intereses |
|
||||
| **Debt Ratio** | Deuda Total / Activo Total | Apalancamiento |
|
||||
|
||||
### 6. Gestión
|
||||
|
||||
| Métrica | Fórmula | Interpretación |
|
||||
|---------|---------|----------------|
|
||||
| **Revenue Growth** | (Ingreso Actual - Anterior) / Anterior | Crecimiento de ventas |
|
||||
| **Key Score** | Crec. Ingreso 12m + Margen EBITDA 12m | Score compuesto |
|
||||
| **CapEx/Revenue** | CAPEX / Ingresos | Inversión en activos |
|
||||
| **Effective Tax Rate** | Impuestos / EBT | Tasa impositiva efectiva |
|
||||
|
||||
---
|
||||
|
||||
## Sistema de Semáforos
|
||||
|
||||
Cada métrica se evalúa contra umbrales para determinar su "tendencia":
|
||||
|
||||
| Tendencia | Color | Significado |
|
||||
|-----------|-------|-------------|
|
||||
| muy_positivo | Verde oscuro | Excelente desempeño |
|
||||
| positivo | Verde claro | Buen desempeño |
|
||||
| neutral | Amarillo | Desempeño aceptable |
|
||||
| negativo | Naranja | Área de atención |
|
||||
| muy_negativo | Rojo | Área crítica |
|
||||
|
||||
### Ejemplo de umbrales (Margen Neto):
|
||||
|
||||
| Tendencia | Umbral |
|
||||
|-----------|--------|
|
||||
| muy_positivo | ≥ 20% |
|
||||
| positivo | ≥ 10% |
|
||||
| neutral | ≥ 5% |
|
||||
| negativo | ≥ 2% |
|
||||
| muy_negativo | < 2% |
|
||||
|
||||
### Umbrales por Giro
|
||||
|
||||
Los umbrales pueden personalizarse por industria. Por ejemplo, hotelería puede tener diferentes expectativas de margen que manufactura.
|
||||
|
||||
---
|
||||
|
||||
## Comparativos
|
||||
|
||||
Para cada métrica se calculan:
|
||||
|
||||
| Comparativo | Descripción |
|
||||
|-------------|-------------|
|
||||
| Valor Actual | Valor del periodo actual |
|
||||
| Periodo Anterior | Valor del periodo inmediato anterior |
|
||||
| Variación Absoluta | Diferencia numérica |
|
||||
| Variación % | Cambio porcentual |
|
||||
| Promedio 3 Periodos | Media de últimos 3 periodos |
|
||||
| Mismo Periodo Año Anterior | Para comparación interanual |
|
||||
|
||||
---
|
||||
|
||||
## Implementación
|
||||
|
||||
```php
|
||||
// CalculadorMetricas.php
|
||||
|
||||
public function calcular(Reporte $reporte): array
|
||||
{
|
||||
// 1. Calcular estados financieros por periodo
|
||||
foreach ($balanzas as $balanza) {
|
||||
$periodos[] = [
|
||||
'periodo' => $balanza->periodo_fin,
|
||||
'balance_general' => $this->calcularBalanceGeneral($balanza),
|
||||
'estado_resultados' => $this->calcularEstadoResultados($balanza),
|
||||
];
|
||||
}
|
||||
|
||||
// 2. Calcular métricas del último periodo
|
||||
$metricas = $this->calcularTodasLasMetricas($ultimoPeriodo);
|
||||
|
||||
// 3. Calcular comparativos
|
||||
$comparativos = $this->calcularComparativos($periodos, $metricas);
|
||||
|
||||
// 4. Calcular flujo de efectivo
|
||||
$flujoEfectivo = $this->calcularFlujoEfectivo($periodos);
|
||||
|
||||
return [
|
||||
'periodos' => $periodos,
|
||||
'metricas' => $metricas,
|
||||
'comparativos' => $comparativos,
|
||||
'flujo_efectivo' => $flujoEfectivo,
|
||||
];
|
||||
}
|
||||
```
|
||||
479
docs/09-pdf.md
Normal file
479
docs/09-pdf.md
Normal file
@@ -0,0 +1,479 @@
|
||||
# 9. Generación de PDF
|
||||
|
||||
## Descripción
|
||||
|
||||
El sistema genera reportes PDF profesionales de **32 páginas** usando Browsershot (wrapper de Puppeteer para Laravel).
|
||||
|
||||
---
|
||||
|
||||
## Arquitectura
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ ReporteController│
|
||||
│ /pdf │
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ GeneradorPdf │
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ Browsershot │ ← Puppeteer headless Chrome
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ React PdfView │ ← Componente optimizado para impresión
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ PDF 32 págs │
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Estructura del PDF (32 páginas)
|
||||
|
||||
| # | Sección | Contenido |
|
||||
|---|---------|-----------|
|
||||
| 1 | Portada | Logo, nombre empresa, periodo |
|
||||
| 2 | Índice | Tabla de contenidos |
|
||||
| 3-4 | Resumen Ejecutivo | KPIs principales, semáforos |
|
||||
| 5-8 | Balance General | Activos, Pasivos, Capital |
|
||||
| 9-12 | Estado de Resultados | Ingresos, Costos, Gastos |
|
||||
| 13-14 | Flujo de Efectivo | Operación, Inversión, Financiamiento |
|
||||
| 15-18 | Análisis de Márgenes | 7 métricas con gráficas |
|
||||
| 19-20 | Análisis de Retorno | ROIC, ROE, ROA, ROCE |
|
||||
| 21-22 | Análisis de Eficiencia | Rotaciones, ciclo conversión |
|
||||
| 23-24 | Análisis de Liquidez | Ratios de liquidez |
|
||||
| 25-26 | Análisis de Solvencia | Deuda, cobertura |
|
||||
| 27-28 | Análisis de Gestión | Crecimiento, inversión |
|
||||
| 29-30 | Comparativos | Tendencias históricas |
|
||||
| 31 | Notas | Observaciones y anomalías |
|
||||
| 32 | Glosario | Definiciones de métricas |
|
||||
|
||||
---
|
||||
|
||||
## Implementación Backend
|
||||
|
||||
### GeneradorPdf.php
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Reporte;
|
||||
use Spatie\Browsershot\Browsershot;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class GeneradorPdf
|
||||
{
|
||||
public function generar(Reporte $reporte): string
|
||||
{
|
||||
// URL del frontend con datos del reporte
|
||||
$url = config('app.frontend_url') . '/pdf/' . $reporte->id;
|
||||
|
||||
// Nombre del archivo
|
||||
$filename = sprintf(
|
||||
'reportes/%s/%s-%s.pdf',
|
||||
$reporte->cliente_id,
|
||||
$reporte->periodo_fin->format('Y-m'),
|
||||
now()->timestamp
|
||||
);
|
||||
|
||||
$fullPath = storage_path('app/public/' . $filename);
|
||||
|
||||
// Asegurar directorio existe
|
||||
$dir = dirname($fullPath);
|
||||
if (!is_dir($dir)) {
|
||||
mkdir($dir, 0755, true);
|
||||
}
|
||||
|
||||
// Generar PDF con Browsershot
|
||||
Browsershot::url($url)
|
||||
->setNodeBinary(config('browsershot.node_binary'))
|
||||
->setNpmBinary(config('browsershot.npm_binary'))
|
||||
->setChromePath(config('browsershot.chrome_path'))
|
||||
->format('Letter')
|
||||
->margins(10, 10, 10, 10)
|
||||
->showBackground()
|
||||
->waitUntilNetworkIdle()
|
||||
->timeout(120)
|
||||
->save($fullPath);
|
||||
|
||||
// Actualizar reporte
|
||||
$reporte->update([
|
||||
'pdf_path' => $filename,
|
||||
'status' => 'completado',
|
||||
]);
|
||||
|
||||
return $filename;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Configuración Browsershot
|
||||
|
||||
```php
|
||||
// config/browsershot.php
|
||||
return [
|
||||
'node_binary' => env('NODE_BINARY', '/usr/bin/node'),
|
||||
'npm_binary' => env('NPM_BINARY', '/usr/bin/npm'),
|
||||
'chrome_path' => env('CHROME_PATH', null), // null = usa Chromium de Puppeteer
|
||||
];
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementación Frontend
|
||||
|
||||
### PdfView Component
|
||||
|
||||
```tsx
|
||||
// src/pages/PdfView/index.tsx
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { api } from '@/services/api';
|
||||
import { Reporte } from '@/types';
|
||||
|
||||
// Importar secciones
|
||||
import Portada from './sections/Portada';
|
||||
import Indice from './sections/Indice';
|
||||
import ResumenEjecutivo from './sections/ResumenEjecutivo';
|
||||
import BalanceGeneral from './sections/BalanceGeneral';
|
||||
import EstadoResultados from './sections/EstadoResultados';
|
||||
import FlujoEfectivo from './sections/FlujoEfectivo';
|
||||
import AnalisisMargenes from './sections/AnalisisMargenes';
|
||||
import AnalisisRetorno from './sections/AnalisisRetorno';
|
||||
import AnalisisEficiencia from './sections/AnalisisEficiencia';
|
||||
import AnalisisLiquidez from './sections/AnalisisLiquidez';
|
||||
import AnalisisSolvencia from './sections/AnalisisSolvencia';
|
||||
import AnalisisGestion from './sections/AnalisisGestion';
|
||||
import Comparativos from './sections/Comparativos';
|
||||
import Notas from './sections/Notas';
|
||||
import Glosario from './sections/Glosario';
|
||||
|
||||
export default function PdfView() {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const [reporte, setReporte] = useState<Reporte | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchReporte = async () => {
|
||||
try {
|
||||
const data = await api.reportes.get(Number(id));
|
||||
setReporte(data);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
fetchReporte();
|
||||
}, [id]);
|
||||
|
||||
if (loading || !reporte) {
|
||||
return <div>Cargando...</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="pdf-container">
|
||||
<Portada reporte={reporte} />
|
||||
<Indice />
|
||||
<ResumenEjecutivo reporte={reporte} />
|
||||
<BalanceGeneral reporte={reporte} />
|
||||
<EstadoResultados reporte={reporte} />
|
||||
<FlujoEfectivo reporte={reporte} />
|
||||
<AnalisisMargenes reporte={reporte} />
|
||||
<AnalisisRetorno reporte={reporte} />
|
||||
<AnalisisEficiencia reporte={reporte} />
|
||||
<AnalisisLiquidez reporte={reporte} />
|
||||
<AnalisisSolvencia reporte={reporte} />
|
||||
<AnalisisGestion reporte={reporte} />
|
||||
<Comparativos reporte={reporte} />
|
||||
<Notas reporte={reporte} />
|
||||
<Glosario />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Estilos de Impresión
|
||||
|
||||
```css
|
||||
/* src/styles/pdf.css */
|
||||
|
||||
@media print {
|
||||
/* Ocultar elementos no imprimibles */
|
||||
.no-print {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Saltos de página */
|
||||
.page-break {
|
||||
page-break-after: always;
|
||||
}
|
||||
|
||||
.page-break-before {
|
||||
page-break-before: always;
|
||||
}
|
||||
|
||||
.avoid-break {
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
}
|
||||
|
||||
/* Contenedor PDF */
|
||||
.pdf-container {
|
||||
width: 8.5in;
|
||||
margin: 0 auto;
|
||||
background: white;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
/* Página individual */
|
||||
.pdf-page {
|
||||
width: 8.5in;
|
||||
min-height: 11in;
|
||||
padding: 0.5in;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Header de página */
|
||||
.pdf-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-bottom: 0.25in;
|
||||
border-bottom: 2px solid #1A1F36;
|
||||
margin-bottom: 0.25in;
|
||||
}
|
||||
|
||||
/* Footer de página */
|
||||
.pdf-footer {
|
||||
position: absolute;
|
||||
bottom: 0.25in;
|
||||
left: 0.5in;
|
||||
right: 0.5in;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 10px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* Tabla de datos */
|
||||
.pdf-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.pdf-table th,
|
||||
.pdf-table td {
|
||||
padding: 6px 8px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.pdf-table th {
|
||||
background: #f3f4f6;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Semáforos */
|
||||
.indicator {
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.indicator-muy_positivo { background: #059669; }
|
||||
.indicator-positivo { background: #10b981; }
|
||||
.indicator-neutral { background: #f59e0b; }
|
||||
.indicator-negativo { background: #f97316; }
|
||||
.indicator-muy_negativo { background: #ef4444; }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Componentes de Sección
|
||||
|
||||
### Portada
|
||||
|
||||
```tsx
|
||||
// src/pages/PdfView/sections/Portada.tsx
|
||||
|
||||
interface PortadaProps {
|
||||
reporte: Reporte;
|
||||
}
|
||||
|
||||
export default function Portada({ reporte }: PortadaProps) {
|
||||
return (
|
||||
<div className="pdf-page flex flex-col items-center justify-center">
|
||||
{/* Logo */}
|
||||
<img
|
||||
src={reporte.cliente.logo || '/logo-horux.png'}
|
||||
alt="Logo"
|
||||
className="w-48 mb-8"
|
||||
/>
|
||||
|
||||
{/* Nombre empresa */}
|
||||
<h1 className="text-4xl font-bold text-horux-dark mb-4">
|
||||
{reporte.cliente.nombre_empresa}
|
||||
</h1>
|
||||
|
||||
{/* Tipo de reporte */}
|
||||
<h2 className="text-2xl text-gray-600 mb-8">
|
||||
Reporte Financiero
|
||||
</h2>
|
||||
|
||||
{/* Periodo */}
|
||||
<p className="text-xl text-gray-500">
|
||||
{formatPeriodo(reporte.periodo_tipo, reporte.periodo_inicio, reporte.periodo_fin)}
|
||||
</p>
|
||||
|
||||
{/* Fecha generación */}
|
||||
<p className="text-sm text-gray-400 mt-4">
|
||||
Generado: {formatDate(reporte.fecha_generacion)}
|
||||
</p>
|
||||
|
||||
{/* Branding */}
|
||||
<div className="absolute bottom-8">
|
||||
<p className="text-sm text-gray-400">
|
||||
Powered by Horux 360
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Resumen Ejecutivo
|
||||
|
||||
```tsx
|
||||
// src/pages/PdfView/sections/ResumenEjecutivo.tsx
|
||||
|
||||
export default function ResumenEjecutivo({ reporte }: { reporte: Reporte }) {
|
||||
const { metricas, comparativos } = reporte.data_calculada;
|
||||
|
||||
const kpis = [
|
||||
{ nombre: 'Ingresos', valor: metricas.ingresos, formato: 'currency' },
|
||||
{ nombre: 'Margen EBITDA', valor: metricas.margen_ebitda, formato: 'percent' },
|
||||
{ nombre: 'Margen Neto', valor: metricas.margen_neto, formato: 'percent' },
|
||||
{ nombre: 'ROIC', valor: metricas.roic, formato: 'percent' },
|
||||
{ nombre: 'Current Ratio', valor: metricas.current_ratio, formato: 'number' },
|
||||
{ nombre: 'Net Debt/EBITDA', valor: metricas.net_debt_ebitda, formato: 'number' },
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="pdf-page page-break">
|
||||
<PdfHeader titulo="Resumen Ejecutivo" pagina={3} />
|
||||
|
||||
<div className="grid grid-cols-3 gap-4 mb-8">
|
||||
{kpis.map((kpi) => (
|
||||
<KpiCard key={kpi.nombre} {...kpi} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<h3 className="text-lg font-bold mb-4">Semáforos de Rendimiento</h3>
|
||||
<SemaforoTable metricas={metricas} />
|
||||
|
||||
<PdfFooter pagina={3} />
|
||||
</div>
|
||||
|
||||
<div className="pdf-page page-break">
|
||||
<PdfHeader titulo="Resumen Ejecutivo" pagina={4} />
|
||||
|
||||
<h3 className="text-lg font-bold mb-4">Tendencias Principales</h3>
|
||||
<TrendCharts comparativos={comparativos} />
|
||||
|
||||
<PdfFooter pagina={4} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Requisitos del Servidor
|
||||
|
||||
### Instalación de Dependencias
|
||||
|
||||
```bash
|
||||
# Node.js 18+
|
||||
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
|
||||
sudo apt-get install -y nodejs
|
||||
|
||||
# Puppeteer dependencies (Ubuntu/Debian)
|
||||
sudo apt-get install -y \
|
||||
libnss3 \
|
||||
libatk1.0-0 \
|
||||
libatk-bridge2.0-0 \
|
||||
libcups2 \
|
||||
libdrm2 \
|
||||
libxkbcommon0 \
|
||||
libxcomposite1 \
|
||||
libxdamage1 \
|
||||
libxfixes3 \
|
||||
libxrandr2 \
|
||||
libgbm1 \
|
||||
libasound2
|
||||
|
||||
# Instalar Puppeteer
|
||||
cd backend
|
||||
npm install puppeteer
|
||||
```
|
||||
|
||||
### Configuración en Producción
|
||||
|
||||
```env
|
||||
# .env
|
||||
NODE_BINARY=/usr/bin/node
|
||||
NPM_BINARY=/usr/bin/npm
|
||||
CHROME_PATH=/usr/bin/google-chrome-stable
|
||||
FRONTEND_URL=https://app.horux360.com
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Error: "Unable to launch browser"
|
||||
|
||||
```bash
|
||||
# Verificar Chrome instalado
|
||||
which google-chrome-stable
|
||||
|
||||
# Instalar Chrome si no existe
|
||||
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
|
||||
sudo dpkg -i google-chrome-stable_current_amd64.deb
|
||||
sudo apt-get -f install
|
||||
```
|
||||
|
||||
### Error: "Timeout exceeded"
|
||||
|
||||
Aumentar timeout en `GeneradorPdf.php`:
|
||||
|
||||
```php
|
||||
Browsershot::url($url)
|
||||
->timeout(300) // 5 minutos
|
||||
->waitUntilNetworkIdle(false) // No esperar red
|
||||
->save($fullPath);
|
||||
```
|
||||
|
||||
### Error: "Missing fonts"
|
||||
|
||||
```bash
|
||||
# Instalar fuentes
|
||||
sudo apt-get install -y fonts-liberation fonts-noto-color-emoji
|
||||
```
|
||||
|
||||
392
docs/10-administracion.md
Normal file
392
docs/10-administracion.md
Normal file
@@ -0,0 +1,392 @@
|
||||
# 10. Panel de Administración
|
||||
|
||||
## Descripción
|
||||
|
||||
El panel de administración permite a usuarios con rol **admin** gestionar la configuración global del sistema.
|
||||
|
||||
---
|
||||
|
||||
## Acceso
|
||||
|
||||
- **URL**: `/admin`
|
||||
- **Rol requerido**: `admin`
|
||||
- **Middleware**: `auth:sanctum`, `role:admin`
|
||||
|
||||
---
|
||||
|
||||
## Secciones
|
||||
|
||||
### 1. Gestión de Usuarios
|
||||
|
||||
**Ruta**: `/admin/usuarios`
|
||||
|
||||
Permite crear, editar y eliminar usuarios del sistema.
|
||||
|
||||
| Campo | Descripción |
|
||||
|-------|-------------|
|
||||
| nombre | Nombre completo |
|
||||
| email | Email único |
|
||||
| password | Contraseña (mínimo 8 caracteres) |
|
||||
| role | admin, analista, cliente, empleado |
|
||||
| cliente_id | Cliente asignado (requerido para cliente/empleado) |
|
||||
| activo | Estado del usuario |
|
||||
|
||||
#### API Endpoints
|
||||
|
||||
```
|
||||
GET /api/admin/usuarios - Listar usuarios
|
||||
POST /api/admin/usuarios - Crear usuario
|
||||
GET /api/admin/usuarios/{id} - Ver usuario
|
||||
PUT /api/admin/usuarios/{id} - Actualizar usuario
|
||||
DELETE /api/admin/usuarios/{id} - Eliminar usuario
|
||||
```
|
||||
|
||||
#### Ejemplo de creación
|
||||
|
||||
```bash
|
||||
curl -X POST /api/admin/usuarios \
|
||||
-H "Authorization: Bearer {token}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"nombre": "Juan Pérez",
|
||||
"email": "juan@empresa.com",
|
||||
"password": "password123",
|
||||
"role": "analista"
|
||||
}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. Gestión de Giros
|
||||
|
||||
**Ruta**: `/admin/giros`
|
||||
|
||||
Catálogo de giros de negocio (industrias).
|
||||
|
||||
| Campo | Descripción |
|
||||
|-------|-------------|
|
||||
| nombre | Nombre del giro |
|
||||
| activo | Estado |
|
||||
|
||||
#### Giros predeterminados
|
||||
|
||||
1. Agricultura
|
||||
2. Alimentación y Bebidas
|
||||
3. Automotriz
|
||||
4. Comercio Mayorista
|
||||
5. Comercio Minorista
|
||||
6. Construcción
|
||||
7. Consultoría
|
||||
8. Educación
|
||||
9. Energía
|
||||
10. Farmacéutico
|
||||
11. Financiero
|
||||
12. Hotelería
|
||||
13. Inmobiliario
|
||||
14. Logística
|
||||
15. Manufactura
|
||||
16. Minería
|
||||
17. Publicidad
|
||||
18. Salud
|
||||
19. Seguros
|
||||
20. Software
|
||||
21. Telecomunicaciones
|
||||
22. Textil
|
||||
23. Transporte
|
||||
24. Turismo
|
||||
|
||||
#### API Endpoints
|
||||
|
||||
```
|
||||
GET /api/admin/giros - Listar giros
|
||||
POST /api/admin/giros - Crear giro
|
||||
PUT /api/admin/giros/{id} - Actualizar giro
|
||||
DELETE /api/admin/giros/{id} - Eliminar giro
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. Gestión de Umbrales
|
||||
|
||||
**Ruta**: `/admin/umbrales`
|
||||
|
||||
Configuración de umbrales para el sistema de semáforos.
|
||||
|
||||
| Campo | Descripción |
|
||||
|-------|-------------|
|
||||
| metrica | Nombre de la métrica |
|
||||
| muy_positivo | Umbral verde oscuro |
|
||||
| positivo | Umbral verde claro |
|
||||
| neutral | Umbral amarillo |
|
||||
| negativo | Umbral naranja |
|
||||
| muy_negativo | Umbral rojo |
|
||||
| giro_id | Giro específico (null = general) |
|
||||
|
||||
#### Umbrales por defecto
|
||||
|
||||
| Métrica | Muy Positivo | Positivo | Neutral | Negativo |
|
||||
|---------|--------------|----------|---------|----------|
|
||||
| margen_bruto | ≥40% | ≥30% | ≥20% | ≥10% |
|
||||
| margen_ebitda | ≥25% | ≥15% | ≥10% | ≥5% |
|
||||
| margen_operativo | ≥20% | ≥12% | ≥8% | ≥4% |
|
||||
| margen_neto | ≥15% | ≥10% | ≥5% | ≥2% |
|
||||
| roic | ≥20% | ≥15% | ≥10% | ≥5% |
|
||||
| roe | ≥20% | ≥15% | ≥10% | ≥5% |
|
||||
| roa | ≥12% | ≥8% | ≥5% | ≥2% |
|
||||
| current_ratio | ≥2.0 | ≥1.5 | ≥1.2 | ≥1.0 |
|
||||
| quick_ratio | ≥1.5 | ≥1.0 | ≥0.8 | ≥0.5 |
|
||||
| net_debt_ebitda | ≤1.0 | ≤2.0 | ≤3.0 | ≤4.0 |
|
||||
| interest_coverage | ≥8.0 | ≥5.0 | ≥3.0 | ≥1.5 |
|
||||
|
||||
#### API Endpoints
|
||||
|
||||
```
|
||||
GET /api/admin/umbrales - Listar umbrales
|
||||
POST /api/admin/umbrales - Crear umbral
|
||||
PUT /api/admin/umbrales/{id} - Actualizar umbral
|
||||
DELETE /api/admin/umbrales/{id} - Eliminar umbral
|
||||
```
|
||||
|
||||
#### Ejemplo: Umbral específico por giro
|
||||
|
||||
```bash
|
||||
# Crear umbral de margen bruto específico para Hotelería
|
||||
curl -X POST /api/admin/umbrales \
|
||||
-H "Authorization: Bearer {token}" \
|
||||
-d '{
|
||||
"metrica": "margen_bruto",
|
||||
"muy_positivo": 0.50,
|
||||
"positivo": 0.40,
|
||||
"neutral": 0.30,
|
||||
"negativo": 0.20,
|
||||
"giro_id": 12
|
||||
}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. Reglas de Mapeo
|
||||
|
||||
**Ruta**: `/admin/reglas-mapeo`
|
||||
|
||||
Reglas para clasificar cuentas automáticamente según el sistema contable.
|
||||
|
||||
| Campo | Descripción |
|
||||
|-------|-------------|
|
||||
| sistema_origen | contpaqi, aspel, sap, etc. |
|
||||
| cuenta_padre_codigo | Código de cuenta padre |
|
||||
| rango_inicio | Inicio del rango de códigos |
|
||||
| rango_fin | Fin del rango |
|
||||
| patron_regex | Patrón regex alternativo |
|
||||
| reporte_contable_id | Balance General o Estado de Resultados |
|
||||
| categoria_contable_id | Categoría destino |
|
||||
| prioridad | Mayor número = mayor prioridad |
|
||||
| activo | Estado de la regla |
|
||||
|
||||
#### Reglas CONTPAQi predeterminadas
|
||||
|
||||
| Cuenta Padre | Rango | Categoría |
|
||||
|--------------|-------|-----------|
|
||||
| 001-100-000 | 101-000-000 a 154-999-999 | Activos Circulantes |
|
||||
| 001-200-000 | 155-000-000 a 199-999-999 | Activos No Circulantes |
|
||||
| 002-100-000 | 200-000-000 a 209-999-999 | Pasivo Circulante |
|
||||
| 002-200-000 | 210-000-000 a 220-999-999 | Pasivo No Circulante |
|
||||
| - | 30X-XXX-XXX | Capital Social |
|
||||
| - | 310-XXX-XXX | Pérdidas Anteriores |
|
||||
| - | 311-XXX-XXX | Utilidades Anteriores |
|
||||
| - | 40X-XXX-XXX | Ingresos |
|
||||
| - | 5XX-XXX-XXX | Gastos Operativos |
|
||||
| - | 6XX-XXX-XXX | Otros Gastos |
|
||||
| - | 7XX-XXX-XXX | Gastos Financieros |
|
||||
|
||||
#### API Endpoints
|
||||
|
||||
```
|
||||
GET /api/admin/reglas-mapeo - Listar reglas
|
||||
POST /api/admin/reglas-mapeo - Crear regla
|
||||
PUT /api/admin/reglas-mapeo/{id} - Actualizar regla
|
||||
DELETE /api/admin/reglas-mapeo/{id} - Eliminar regla
|
||||
```
|
||||
|
||||
#### Ejemplo: Agregar regla para Aspel
|
||||
|
||||
```bash
|
||||
curl -X POST /api/admin/reglas-mapeo \
|
||||
-H "Authorization: Bearer {token}" \
|
||||
-d '{
|
||||
"sistema_origen": "aspel",
|
||||
"patron_regex": "^1[0-4]\\d{2}",
|
||||
"reporte_contable_id": 1,
|
||||
"categoria_contable_id": 1,
|
||||
"prioridad": 10,
|
||||
"activo": true
|
||||
}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Interfaz de Usuario
|
||||
|
||||
### Layout Admin
|
||||
|
||||
```tsx
|
||||
// src/pages/Admin/Layout.tsx
|
||||
|
||||
export default function AdminLayout({ children }) {
|
||||
const menuItems = [
|
||||
{ path: '/admin/usuarios', label: 'Usuarios', icon: UsersIcon },
|
||||
{ path: '/admin/giros', label: 'Giros', icon: BuildingIcon },
|
||||
{ path: '/admin/umbrales', label: 'Umbrales', icon: ChartIcon },
|
||||
{ path: '/admin/reglas-mapeo', label: 'Reglas Mapeo', icon: MapIcon },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="flex">
|
||||
<aside className="w-64 bg-horux-dark min-h-screen p-4">
|
||||
<h2 className="text-white text-xl font-bold mb-6">Administración</h2>
|
||||
<nav>
|
||||
{menuItems.map((item) => (
|
||||
<NavLink
|
||||
key={item.path}
|
||||
to={item.path}
|
||||
className={({ isActive }) =>
|
||||
`flex items-center px-4 py-2 rounded ${
|
||||
isActive ? 'bg-horux-primary text-white' : 'text-gray-300 hover:bg-gray-700'
|
||||
}`
|
||||
}
|
||||
>
|
||||
<item.icon className="w-5 h-5 mr-3" />
|
||||
{item.label}
|
||||
</NavLink>
|
||||
))}
|
||||
</nav>
|
||||
</aside>
|
||||
<main className="flex-1 p-8">{children}</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Tabla CRUD genérica
|
||||
|
||||
```tsx
|
||||
// src/components/admin/CrudTable.tsx
|
||||
|
||||
interface CrudTableProps<T> {
|
||||
data: T[];
|
||||
columns: Column<T>[];
|
||||
onEdit: (item: T) => void;
|
||||
onDelete: (item: T) => void;
|
||||
onCreate: () => void;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export default function CrudTable<T extends { id: number }>({
|
||||
data,
|
||||
columns,
|
||||
onEdit,
|
||||
onDelete,
|
||||
onCreate,
|
||||
title,
|
||||
}: CrudTableProps<T>) {
|
||||
return (
|
||||
<div>
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<h1 className="text-2xl font-bold">{title}</h1>
|
||||
<button
|
||||
onClick={onCreate}
|
||||
className="bg-horux-primary text-white px-4 py-2 rounded hover:bg-horux-secondary"
|
||||
>
|
||||
+ Nuevo
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<table className="w-full border-collapse">
|
||||
<thead>
|
||||
<tr className="bg-gray-100">
|
||||
{columns.map((col) => (
|
||||
<th key={col.key} className="p-3 text-left">{col.label}</th>
|
||||
))}
|
||||
<th className="p-3 text-right">Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{data.map((item) => (
|
||||
<tr key={item.id} className="border-b hover:bg-gray-50">
|
||||
{columns.map((col) => (
|
||||
<td key={col.key} className="p-3">
|
||||
{col.render ? col.render(item) : item[col.key]}
|
||||
</td>
|
||||
))}
|
||||
<td className="p-3 text-right">
|
||||
<button
|
||||
onClick={() => onEdit(item)}
|
||||
className="text-blue-600 hover:text-blue-800 mr-3"
|
||||
>
|
||||
Editar
|
||||
</button>
|
||||
<button
|
||||
onClick={() => onDelete(item)}
|
||||
className="text-red-600 hover:text-red-800"
|
||||
>
|
||||
Eliminar
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Auditoría
|
||||
|
||||
Todas las acciones administrativas se registran en el log:
|
||||
|
||||
```php
|
||||
// Ejemplo en AdminController
|
||||
Log::channel('admin')->info('Usuario creado', [
|
||||
'admin_id' => auth()->id(),
|
||||
'user_id' => $user->id,
|
||||
'email' => $user->email,
|
||||
'ip' => request()->ip(),
|
||||
]);
|
||||
```
|
||||
|
||||
### Configuración de logging
|
||||
|
||||
```php
|
||||
// config/logging.php
|
||||
'channels' => [
|
||||
'admin' => [
|
||||
'driver' => 'daily',
|
||||
'path' => storage_path('logs/admin.log'),
|
||||
'level' => 'info',
|
||||
'days' => 90,
|
||||
],
|
||||
],
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Permisos por Rol
|
||||
|
||||
| Acción | Admin | Analista | Cliente | Empleado |
|
||||
|--------|-------|----------|---------|----------|
|
||||
| Gestionar usuarios | ✓ | ✗ | ✗ | ✗ |
|
||||
| Gestionar giros | ✓ | ✗ | ✗ | ✗ |
|
||||
| Gestionar umbrales | ✓ | ✗ | ✗ | ✗ |
|
||||
| Gestionar reglas mapeo | ✓ | ✗ | ✗ | ✗ |
|
||||
| Ver todos los clientes | ✓ | ✓ | ✗ | ✗ |
|
||||
| Crear clientes | ✓ | ✓ | ✗ | ✗ |
|
||||
| Subir balanzas | ✓ | ✓ | ✗ | ✗ |
|
||||
| Generar reportes | ✓ | ✓ | ✗ | ✗ |
|
||||
| Ver dashboard propio | ✓ | ✓ | ✓ | * |
|
||||
| Descargar PDF | ✓ | ✓ | ✓ | * |
|
||||
|
||||
\* Según permisos configurados
|
||||
|
||||
35
docs/README.md
Normal file
35
docs/README.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Documentación - Horux Strategy Platform
|
||||
|
||||
## Índice
|
||||
|
||||
1. [Descripción General](./01-descripcion-general.md)
|
||||
2. [Arquitectura del Sistema](./02-arquitectura.md)
|
||||
3. [Instalación y Configuración](./03-instalacion.md)
|
||||
4. [API Reference](./04-api-reference.md)
|
||||
5. [Guía del Frontend](./05-frontend.md)
|
||||
6. [Base de Datos](./06-base-de-datos.md)
|
||||
7. [Parsers de Balanzas](./07-parsers.md)
|
||||
8. [Métricas Financieras](./08-metricas.md)
|
||||
9. [Generación de PDF](./09-pdf.md)
|
||||
10. [Administración](./10-administracion.md)
|
||||
|
||||
## Inicio Rápido
|
||||
|
||||
```bash
|
||||
# Backend
|
||||
cd backend
|
||||
composer install
|
||||
cp .env.example .env
|
||||
php artisan key:generate
|
||||
php artisan migrate --seed
|
||||
php artisan serve
|
||||
|
||||
# Frontend (otra terminal)
|
||||
cd frontend
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Accede a http://localhost:5173 con:
|
||||
- Email: admin@horux360.com
|
||||
- Password: password
|
||||
384
docs/plans/2025-01-31-horux-strategy-design.md
Normal file
384
docs/plans/2025-01-31-horux-strategy-design.md
Normal file
@@ -0,0 +1,384 @@
|
||||
# Horux Strategy Platform - Diseño de Sistema
|
||||
|
||||
**Fecha:** 2025-01-31
|
||||
**Proyecto:** Plataforma de Reportes Financieros
|
||||
**Cliente:** Horux 360
|
||||
|
||||
---
|
||||
|
||||
## 1. Resumen Ejecutivo
|
||||
|
||||
Plataforma web para generar reportes financieros automatizados a partir de balanzas de comprobación. Permite a empresas subir sus datos contables de múltiples sistemas (CONTPAQi, Aspel, SAP, etc.) y obtener dashboards interactivos con métricas financieras y exportación a PDF profesional.
|
||||
|
||||
---
|
||||
|
||||
## 2. Stack Tecnológico
|
||||
|
||||
| Componente | Tecnología |
|
||||
|------------|------------|
|
||||
| Backend | Laravel 11 (API REST) |
|
||||
| Autenticación | Laravel Sanctum |
|
||||
| Frontend | React 18 + TypeScript |
|
||||
| Base de datos | MySQL / PostgreSQL |
|
||||
| Gráficas | Recharts |
|
||||
| Generación PDF | Puppeteer / Browsershot |
|
||||
| Parsing PDFs | spatie/pdf-to-text + regex |
|
||||
|
||||
---
|
||||
|
||||
## 3. Roles de Usuario
|
||||
|
||||
| Rol | Permisos |
|
||||
|-----|----------|
|
||||
| **Administrador** | Acceso total, configuración global, gestión de umbrales |
|
||||
| **Analista** | Gestionar clientes asignados, procesar balanzas, generar reportes |
|
||||
| **Cliente** | Ver dashboard propio, descargar PDFs, gestionar empleados |
|
||||
| **Empleado** | Permisos configurables por el cliente |
|
||||
|
||||
---
|
||||
|
||||
## 4. Sistemas Contables Soportados
|
||||
|
||||
- CONTPAQi (inicial, con ejemplos)
|
||||
- Aspel
|
||||
- Alegra
|
||||
- SAP
|
||||
- Odoo
|
||||
- Parser genérico (CSV/Excel configurable)
|
||||
|
||||
### 4.1 Arquitectura de Parsers
|
||||
|
||||
```
|
||||
Upload archivo → Detector de formato → Parser específico → Formato normalizado
|
||||
```
|
||||
|
||||
Cada parser normaliza los datos a una estructura estándar interna, permitiendo agregar nuevos sistemas sin modificar el resto del código.
|
||||
|
||||
---
|
||||
|
||||
## 5. Modelo de Datos
|
||||
|
||||
### 5.1 Usuarios y Acceso
|
||||
|
||||
```sql
|
||||
-- users
|
||||
id, nombre, email, password, role, cliente_id (nullable)
|
||||
|
||||
-- clientes
|
||||
id, nombre_empresa, logo, giro_id, moneda, configuracion (JSON)
|
||||
|
||||
-- permisos_empleado
|
||||
user_id, cliente_id, permisos (JSON)
|
||||
```
|
||||
|
||||
### 5.2 Catálogos
|
||||
|
||||
```sql
|
||||
-- giros
|
||||
id, nombre, activo
|
||||
|
||||
-- umbrales
|
||||
id, metrica, muy_positivo, positivo, neutral, negativo, muy_negativo, giro_id
|
||||
|
||||
-- reportes_contables
|
||||
id, nombre ("Balance General", "Estado de Resultados")
|
||||
|
||||
-- categorias_contables
|
||||
id, reporte_contable_id, nombre, orden
|
||||
```
|
||||
|
||||
### 5.3 Categorías Contables
|
||||
|
||||
**Balance General:**
|
||||
| ID | Categoría |
|
||||
|----|-----------|
|
||||
| 1 | Activos Circulantes |
|
||||
| 2 | Activos No Circulantes |
|
||||
| 3 | Pasivo Circulante |
|
||||
| 4 | Pasivo No Circulante |
|
||||
| 5 | Capital Social |
|
||||
| 6 | Pérdidas Ejercicios Anteriores |
|
||||
| 7 | Utilidades Ejercicios Anteriores |
|
||||
|
||||
**Estado de Resultados:**
|
||||
| ID | Categoría |
|
||||
|----|-----------|
|
||||
| 8 | Ingresos |
|
||||
| 9 | Costo de Venta |
|
||||
| 10 | Gastos Operativos |
|
||||
| 11 | Otros Gastos |
|
||||
| 12 | Gastos Financieros |
|
||||
|
||||
### 5.4 Balanzas y Cuentas
|
||||
|
||||
```sql
|
||||
-- balanzas
|
||||
id, cliente_id, periodo_inicio, periodo_fin, sistema_origen, archivo_original, status
|
||||
|
||||
-- cuentas
|
||||
id, balanza_id, codigo, nombre, nivel,
|
||||
reporte_contable_id, categoria_contable_id, cuenta_padre_id,
|
||||
saldo_inicial_deudor, saldo_inicial_acreedor,
|
||||
cargos, abonos,
|
||||
saldo_final_deudor, saldo_final_acreedor,
|
||||
excluida (boolean)
|
||||
|
||||
-- reglas_mapeo
|
||||
id, sistema_origen, cuenta_padre_codigo,
|
||||
rango_hijo_inicio, rango_hijo_fin,
|
||||
reporte_contable_id, categoria_contable_id, prioridad
|
||||
|
||||
-- mapeo_cuentas (excepciones por cliente)
|
||||
cliente_id, codigo_patron, categoria_destino, notas
|
||||
```
|
||||
|
||||
### 5.5 Reportes
|
||||
|
||||
```sql
|
||||
-- reportes
|
||||
id, cliente_id, nombre, periodo_tipo, fecha_generacion, data_calculada (JSON), pdf_path
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Reglas de Mapeo Contable (CONTPAQi)
|
||||
|
||||
| Cuenta Padre | Rango Hijos | Reporte | Categoría |
|
||||
|--------------|-------------|---------|-----------|
|
||||
| 001-100-000 | 101-000-000 a 154-999-999 | Balance | Activos Circulantes |
|
||||
| 001-200-000 | 155-000-000 a 199-999-999 | Balance | Activos No Circulantes |
|
||||
| 002-100-000 | 200-000-000 a 209-999-999 | Balance | Pasivo Circulante |
|
||||
| 002-200-000 | 210-000-000 a 220-999-999 | Balance | Pasivo No Circulante |
|
||||
| 300-000-000 | - | Balance | Capital Social |
|
||||
| 310-000-000 | - | Balance | Pérdidas Ejercicios Anteriores |
|
||||
| 311-000-000 | - | Balance | Utilidades Ejercicios Anteriores |
|
||||
| 40X-000-000 | 401 a 409 | Edo. Resultados | Ingresos |
|
||||
| 5XX-000-000 | 500 a 599 | Edo. Resultados | Gastos Operativos |
|
||||
| 6XX-000-000 | 600 a 699 | Edo. Resultados | Otros Gastos |
|
||||
| 70X-000-000 | 700 a 799 | Edo. Resultados | Gastos Financieros |
|
||||
|
||||
---
|
||||
|
||||
## 7. Flujo de Usuario
|
||||
|
||||
1. **Crear/seleccionar cliente** - Nombre, logo, giro, moneda
|
||||
2. **Subir balanzas** - 2+ archivos PDF/Excel/CSV
|
||||
3. **Detección automática** - Sistema identifica origen (CONTPAQi, etc.)
|
||||
4. **Clasificación automática** - Mapeo a categorías contables
|
||||
5. **Revisión de anomalías** - Corregir cuentas mal clasificadas
|
||||
6. **Limpieza de cuentas** - Desmarcar cuentas a excluir
|
||||
7. **Procesamiento** - Cálculo de métricas
|
||||
8. **Dashboard** - Visualización interactiva
|
||||
9. **Exportar PDF** - Descarga de reporte
|
||||
|
||||
---
|
||||
|
||||
## 8. Métricas Financieras
|
||||
|
||||
### 8.1 Estados Financieros Calculados
|
||||
|
||||
- Balance General
|
||||
- Estado de Resultados
|
||||
- Flujo de Efectivo (método indirecto)
|
||||
|
||||
### 8.2 Métricas por Categoría
|
||||
|
||||
**Márgenes:**
|
||||
- Margen Bruto = Utilidad Bruta / Ingresos
|
||||
- Margen EBITDA = EBITDA / Ingresos
|
||||
- Margen Operativo = EBIT / Ingresos
|
||||
- Margen Neto = Utilidad Neta / Ingresos
|
||||
- Margen NOPAT = NOPAT / Ingresos
|
||||
- Margen OCF = Flujo Operación / Ingresos
|
||||
- Margen FCF = Flujo Libre / Ingresos
|
||||
|
||||
**Retorno:**
|
||||
- ROIC = NOPAT / Capital Invertido
|
||||
- ROE = Utilidad Neta / Capital
|
||||
- ROA = Utilidad Neta / Activo Total
|
||||
- ROCE = EBIT / Capital Empleado
|
||||
|
||||
**Eficiencia:**
|
||||
- Asset Turnover = Ingresos / Activo Total
|
||||
- Inventory Turnover = Costo Venta / Inventario
|
||||
- Días Clientes = (Clientes / Ingresos) × 365
|
||||
- Días Proveedores = (Proveedores / Costo) × 365
|
||||
- Días Inventario = (Inventario / Costo) × 365
|
||||
- Ciclo Conversión = Días Clientes + Días Inv. - Días Prov.
|
||||
|
||||
**Liquidez:**
|
||||
- Current Ratio = Activo Circ. / Pasivo Circ.
|
||||
- Quick Ratio = (Activo Circ. - Inventario) / Pasivo Circ.
|
||||
- Cash Ratio = Efectivo / Pasivo Circ.
|
||||
|
||||
**Solvencia:**
|
||||
- Net Debt / EBITDA = (Deuda Total - Efectivo) / EBITDA
|
||||
- Interest Coverage = EBITDA / Gastos Financieros
|
||||
- Debt Ratio = Deuda Total / Activo Total
|
||||
|
||||
**Gestión:**
|
||||
- Revenue Growth = (Ingreso Actual - Anterior) / Anterior
|
||||
- Key Score = Crecimiento Ingreso 12m + Margen EBITDA 12m
|
||||
- CapEx / Revenue = CAPEX / Ingresos
|
||||
- Effective Tax Rate = Impuestos / EBT
|
||||
|
||||
### 8.3 Comparativos
|
||||
|
||||
Para cada métrica:
|
||||
- Valor actual
|
||||
- Promedio 3 periodos
|
||||
- Periodo anterior
|
||||
- Mismo periodo año anterior
|
||||
- Variación absoluta y porcentual
|
||||
- Tendencia (Muy positiva → Muy negativa)
|
||||
|
||||
---
|
||||
|
||||
## 9. Dashboard
|
||||
|
||||
### 9.1 Secciones
|
||||
|
||||
1. Mensajes Destacados (KPIs + insights)
|
||||
2. Resumen Mensual
|
||||
3. Resumen 12m
|
||||
4. Márgenes
|
||||
5. Márgenes Deep Dive
|
||||
6. Resultados
|
||||
7. Balance
|
||||
8. Capital de Trabajo
|
||||
9. Flujo de Efectivo
|
||||
10. Métricas
|
||||
11. Indicadores
|
||||
12. Negocios (por unidad)
|
||||
13. Estados Financieros
|
||||
|
||||
### 9.2 Componentes React
|
||||
|
||||
```
|
||||
components/
|
||||
├── charts/
|
||||
│ ├── BarChart.tsx
|
||||
│ ├── LineChart.tsx
|
||||
│ ├── StackedBarChart.tsx
|
||||
│ ├── WaterfallChart.tsx
|
||||
│ └── ComboChart.tsx
|
||||
├── cards/
|
||||
│ ├── KPICard.tsx
|
||||
│ ├── InsightCard.tsx
|
||||
│ └── MetricTable.tsx
|
||||
├── tables/
|
||||
│ ├── FinancialStatement.tsx
|
||||
│ └── MetricsGrid.tsx
|
||||
└── layout/
|
||||
├── DashboardNav.tsx
|
||||
├── PeriodSelector.tsx
|
||||
└── ExportButton.tsx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Panel Administrativo
|
||||
|
||||
### 10.1 Módulos
|
||||
|
||||
1. Dashboard admin (estadísticas)
|
||||
2. Gestión de usuarios
|
||||
3. Gestión de clientes
|
||||
4. Catálogo de giros
|
||||
5. Configuración de umbrales
|
||||
6. Reglas de mapeo contable
|
||||
7. Parsers de sistemas
|
||||
8. Configuración general
|
||||
|
||||
### 10.2 Gestión de Empleados (Cliente)
|
||||
|
||||
El cliente puede:
|
||||
- Agregar empleados
|
||||
- Configurar permisos granulares por empleado
|
||||
- Permisos disponibles: ver dashboard, ver estados financieros, exportar PDF, etc.
|
||||
|
||||
---
|
||||
|
||||
## 11. Generación de PDF
|
||||
|
||||
### 11.1 Enfoque
|
||||
|
||||
Usar Puppeteer/Browsershot para renderizar el dashboard de React a PDF, manteniendo el mismo diseño pixel-perfect.
|
||||
|
||||
### 11.2 Estructura (32 páginas)
|
||||
|
||||
1. Portada
|
||||
2. Mensajes Destacados
|
||||
3. Separador "Resumen"
|
||||
4. Resumen Mensual
|
||||
5. Resumen 12m
|
||||
6. Márgenes
|
||||
7. Márgenes Deep Dive
|
||||
8. Separador "Resultados"
|
||||
9. Resultados
|
||||
10. Separador "Balance"
|
||||
11. Balance
|
||||
12. Capital de Trabajo
|
||||
13. Separador "Flujo"
|
||||
14. Flujo de Efectivo
|
||||
15. Separador "Métricas"
|
||||
16-17. Métricas
|
||||
18. Separador "Indicadores"
|
||||
19. Indicadores
|
||||
20. Separador "Negocios"
|
||||
21-22. Negocios por unidad
|
||||
23. Separador "Estados Financieros"
|
||||
24-25. Tabla de Métricas
|
||||
26-27. Estado de Resultados
|
||||
28-29. Subcategorías Costo/Gasto
|
||||
30. Balance General
|
||||
31. Flujo de Efectivo
|
||||
32. Contraportada
|
||||
|
||||
---
|
||||
|
||||
## 12. Estructura del Proyecto
|
||||
|
||||
```
|
||||
monthly-platform/
|
||||
├── backend/ # Laravel
|
||||
│ ├── app/
|
||||
│ │ ├── Http/Controllers/
|
||||
│ │ ├── Models/
|
||||
│ │ ├── Services/
|
||||
│ │ │ ├── Parsers/
|
||||
│ │ │ │ ├── ParserInterface.php
|
||||
│ │ │ │ ├── ContpaqiParser.php
|
||||
│ │ │ │ ├── AspelParser.php
|
||||
│ │ │ │ └── GenericoParser.php
|
||||
│ │ │ ├── DetectorFormato.php
|
||||
│ │ │ ├── ClasificadorCuentas.php
|
||||
│ │ │ ├── CalculadorMetricas.php
|
||||
│ │ │ └── GeneradorPdf.php
|
||||
│ │ └── ...
|
||||
│ ├── database/migrations/
|
||||
│ └── routes/api.php
|
||||
│
|
||||
└── frontend/ # React
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ ├── pages/
|
||||
│ │ ├── Dashboard/
|
||||
│ │ ├── Admin/
|
||||
│ │ ├── Cliente/
|
||||
│ │ └── PdfView/
|
||||
│ ├── hooks/
|
||||
│ ├── services/
|
||||
│ └── utils/
|
||||
└── ...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 13. Consideraciones Futuras
|
||||
|
||||
- Integración directa con APIs de sistemas contables
|
||||
- Generación de insights con IA
|
||||
- Comparativas con benchmarks de industria (datos reales)
|
||||
- App móvil para consulta de reportes
|
||||
- Alertas automáticas por email cuando métricas salen de rango
|
||||
355
docs/plans/2025-01-31-implementation-plan.md
Normal file
355
docs/plans/2025-01-31-implementation-plan.md
Normal file
@@ -0,0 +1,355 @@
|
||||
# Horux Strategy Platform - Plan de Implementación
|
||||
|
||||
**Fecha:** 2025-01-31
|
||||
**Documento de diseño:** 2025-01-31-horux-strategy-design.md
|
||||
|
||||
---
|
||||
|
||||
## Fases de Implementación
|
||||
|
||||
### FASE 1: Fundamentos (Backend)
|
||||
|
||||
#### 1.1 Configuración del proyecto Laravel
|
||||
- [ ] Crear proyecto Laravel 11
|
||||
- [ ] Configurar base de datos (MySQL/PostgreSQL)
|
||||
- [ ] Instalar y configurar Laravel Sanctum
|
||||
- [ ] Configurar CORS para React
|
||||
|
||||
#### 1.2 Migraciones de base de datos
|
||||
- [ ] Tabla `users` (con campo role)
|
||||
- [ ] Tabla `clientes`
|
||||
- [ ] Tabla `giros`
|
||||
- [ ] Tabla `permisos_empleado`
|
||||
- [ ] Tabla `reportes_contables`
|
||||
- [ ] Tabla `categorias_contables`
|
||||
- [ ] Tabla `umbrales`
|
||||
- [ ] Tabla `balanzas`
|
||||
- [ ] Tabla `cuentas`
|
||||
- [ ] Tabla `reglas_mapeo`
|
||||
- [ ] Tabla `mapeo_cuentas`
|
||||
- [ ] Tabla `reportes`
|
||||
- [ ] Seeders para catálogos iniciales (giros, categorías, reglas CONTPAQi)
|
||||
|
||||
#### 1.3 Modelos y relaciones
|
||||
- [ ] User (con roles)
|
||||
- [ ] Cliente
|
||||
- [ ] Giro
|
||||
- [ ] PermisoEmpleado
|
||||
- [ ] Umbral
|
||||
- [ ] Balanza
|
||||
- [ ] Cuenta
|
||||
- [ ] ReglaMappeo
|
||||
- [ ] Reporte
|
||||
|
||||
#### 1.4 Sistema de autenticación
|
||||
- [ ] Login / Logout
|
||||
- [ ] Registro (solo admin puede crear usuarios)
|
||||
- [ ] Middleware por rol
|
||||
- [ ] Policies para autorización
|
||||
|
||||
---
|
||||
|
||||
### FASE 2: Parser de Balanzas
|
||||
|
||||
#### 2.1 Arquitectura de parsers
|
||||
- [ ] Crear `ParserInterface.php`
|
||||
- [ ] Crear `DetectorFormato.php`
|
||||
- [ ] Implementar `ContpaqiParser.php`
|
||||
- [ ] Crear `ParserGenerico.php` (CSV/Excel)
|
||||
|
||||
#### 2.2 Procesamiento de archivos
|
||||
- [ ] Endpoint para upload de archivos
|
||||
- [ ] Extracción de texto de PDF
|
||||
- [ ] Parsing de estructura CONTPAQi
|
||||
- [ ] Normalización a formato interno
|
||||
- [ ] Almacenamiento en tabla `cuentas`
|
||||
|
||||
#### 2.3 Clasificación automática
|
||||
- [ ] Crear `ClasificadorCuentas.php`
|
||||
- [ ] Aplicar reglas de mapeo
|
||||
- [ ] Detectar anomalías
|
||||
- [ ] Marcar cuentas que requieren revisión
|
||||
|
||||
---
|
||||
|
||||
### FASE 3: Motor de Cálculo
|
||||
|
||||
#### 3.1 Calculador de estados financieros
|
||||
- [ ] Crear `CalculadorMetricas.php`
|
||||
- [ ] Calcular Balance General
|
||||
- [ ] Calcular Estado de Resultados
|
||||
- [ ] Calcular Flujo de Efectivo (método indirecto)
|
||||
|
||||
#### 3.2 Cálculo de métricas
|
||||
- [ ] Métricas de márgenes (7 métricas)
|
||||
- [ ] Métricas de retorno (4 métricas)
|
||||
- [ ] Métricas de eficiencia (6 métricas)
|
||||
- [ ] Métricas de liquidez (3 métricas)
|
||||
- [ ] Métricas de solvencia (3 métricas)
|
||||
- [ ] Métricas de gestión (4 métricas)
|
||||
|
||||
#### 3.3 Comparativos
|
||||
- [ ] Calcular promedio 3 periodos
|
||||
- [ ] Comparar con periodo anterior
|
||||
- [ ] Comparar con año anterior
|
||||
- [ ] Calcular variaciones
|
||||
- [ ] Determinar tendencia según umbrales
|
||||
|
||||
---
|
||||
|
||||
### FASE 4: API REST
|
||||
|
||||
#### 4.1 Endpoints de autenticación
|
||||
- [ ] POST /api/login
|
||||
- [ ] POST /api/logout
|
||||
- [ ] GET /api/user
|
||||
|
||||
#### 4.2 Endpoints de clientes
|
||||
- [ ] GET /api/clientes
|
||||
- [ ] POST /api/clientes
|
||||
- [ ] GET /api/clientes/{id}
|
||||
- [ ] PUT /api/clientes/{id}
|
||||
- [ ] DELETE /api/clientes/{id}
|
||||
|
||||
#### 4.3 Endpoints de balanzas
|
||||
- [ ] POST /api/clientes/{id}/balanzas (upload)
|
||||
- [ ] GET /api/clientes/{id}/balanzas
|
||||
- [ ] GET /api/balanzas/{id}/cuentas
|
||||
- [ ] PUT /api/balanzas/{id}/cuentas (actualizar exclusiones)
|
||||
- [ ] PUT /api/cuentas/{id}/clasificacion (corregir anomalía)
|
||||
|
||||
#### 4.4 Endpoints de reportes
|
||||
- [ ] POST /api/clientes/{id}/reportes (generar)
|
||||
- [ ] GET /api/clientes/{id}/reportes
|
||||
- [ ] GET /api/reportes/{id}
|
||||
- [ ] GET /api/reportes/{id}/pdf
|
||||
|
||||
#### 4.5 Endpoints administrativos
|
||||
- [ ] CRUD /api/admin/usuarios
|
||||
- [ ] CRUD /api/admin/giros
|
||||
- [ ] CRUD /api/admin/umbrales
|
||||
- [ ] CRUD /api/admin/reglas-mapeo
|
||||
|
||||
---
|
||||
|
||||
### FASE 5: Frontend - Fundamentos
|
||||
|
||||
#### 5.1 Configuración del proyecto React
|
||||
- [ ] Crear proyecto con Vite + TypeScript
|
||||
- [ ] Configurar React Router
|
||||
- [ ] Configurar Axios para API
|
||||
- [ ] Configurar Recharts
|
||||
- [ ] Configurar Tailwind CSS
|
||||
|
||||
#### 5.2 Autenticación
|
||||
- [ ] Página de Login
|
||||
- [ ] Context de autenticación
|
||||
- [ ] Rutas protegidas por rol
|
||||
- [ ] Interceptor para tokens
|
||||
|
||||
#### 5.3 Layout base
|
||||
- [ ] Sidebar de navegación
|
||||
- [ ] Header con usuario
|
||||
- [ ] Layout para admin
|
||||
- [ ] Layout para cliente
|
||||
|
||||
---
|
||||
|
||||
### FASE 6: Frontend - Flujo Principal
|
||||
|
||||
#### 6.1 Gestión de clientes
|
||||
- [ ] Lista de clientes
|
||||
- [ ] Formulario crear/editar cliente
|
||||
- [ ] Subida de logo
|
||||
|
||||
#### 6.2 Subida de balanzas
|
||||
- [ ] Componente de upload (drag & drop)
|
||||
- [ ] Preview de archivos
|
||||
- [ ] Indicador de progreso
|
||||
- [ ] Detección de sistema origen
|
||||
|
||||
#### 6.3 Revisión y limpieza
|
||||
- [ ] Vista de anomalías con corrección
|
||||
- [ ] Lista de cuentas con checkboxes
|
||||
- [ ] Filtros y búsqueda
|
||||
- [ ] Guardar exclusiones
|
||||
|
||||
---
|
||||
|
||||
### FASE 7: Frontend - Dashboard
|
||||
|
||||
#### 7.1 Componentes de gráficas
|
||||
- [ ] BarChart
|
||||
- [ ] LineChart
|
||||
- [ ] StackedBarChart
|
||||
- [ ] WaterfallChart
|
||||
- [ ] ComboChart
|
||||
|
||||
#### 7.2 Componentes de cards
|
||||
- [ ] KPICard (con semáforo)
|
||||
- [ ] InsightCard
|
||||
- [ ] MetricTable
|
||||
|
||||
#### 7.3 Secciones del dashboard
|
||||
- [ ] Mensajes Destacados
|
||||
- [ ] Resumen Mensual
|
||||
- [ ] Resumen 12m
|
||||
- [ ] Márgenes
|
||||
- [ ] Márgenes Deep Dive
|
||||
- [ ] Resultados
|
||||
- [ ] Balance
|
||||
- [ ] Capital de Trabajo
|
||||
- [ ] Flujo de Efectivo
|
||||
- [ ] Métricas
|
||||
- [ ] Indicadores
|
||||
- [ ] Negocios
|
||||
- [ ] Estados Financieros
|
||||
|
||||
---
|
||||
|
||||
### FASE 8: Generación de PDF
|
||||
|
||||
#### 8.1 Backend
|
||||
- [ ] Instalar Browsershot
|
||||
- [ ] Crear `GeneradorPdf.php`
|
||||
- [ ] Endpoint GET /api/reportes/{id}/pdf
|
||||
|
||||
#### 8.2 Frontend
|
||||
- [ ] Vista `PdfView` con todas las páginas
|
||||
- [ ] Estilos específicos para impresión
|
||||
- [ ] Separadores de sección
|
||||
- [ ] Portada y contraportada
|
||||
|
||||
---
|
||||
|
||||
### FASE 9: Panel Administrativo
|
||||
|
||||
#### 9.1 Dashboard admin
|
||||
- [ ] Estadísticas generales
|
||||
- [ ] Alertas pendientes
|
||||
|
||||
#### 9.2 Gestión de usuarios
|
||||
- [ ] CRUD de usuarios
|
||||
- [ ] Asignación de roles
|
||||
|
||||
#### 9.3 Configuración
|
||||
- [ ] Editor de umbrales
|
||||
- [ ] Editor de reglas de mapeo
|
||||
- [ ] Editor de giros
|
||||
|
||||
---
|
||||
|
||||
### FASE 10: Funcionalidades de Cliente
|
||||
|
||||
#### 10.1 Gestión de empleados
|
||||
- [ ] Lista de empleados
|
||||
- [ ] Crear empleado
|
||||
- [ ] Configurar permisos
|
||||
|
||||
#### 10.2 Configuración
|
||||
- [ ] Exclusiones guardadas
|
||||
- [ ] Preferencias de reporte
|
||||
|
||||
---
|
||||
|
||||
### FASE 11: Testing y Refinamiento
|
||||
|
||||
#### 11.1 Testing
|
||||
- [ ] Tests unitarios del motor de cálculo
|
||||
- [ ] Tests de parsers
|
||||
- [ ] Tests de API
|
||||
- [ ] Tests E2E del flujo principal
|
||||
|
||||
#### 11.2 Refinamiento
|
||||
- [ ] Optimización de rendimiento
|
||||
- [ ] Manejo de errores
|
||||
- [ ] Validaciones
|
||||
- [ ] UX/UI polish
|
||||
|
||||
---
|
||||
|
||||
## Prioridad de Implementación
|
||||
|
||||
1. **MVP (Fases 1-4, 5-7):** Sistema funcional con CONTPAQi, dashboard básico
|
||||
2. **PDF (Fase 8):** Exportación de reportes
|
||||
3. **Admin (Fase 9):** Panel de configuración
|
||||
4. **Multi-usuario (Fase 10):** Funcionalidades de cliente
|
||||
5. **Calidad (Fase 11):** Testing y refinamiento
|
||||
|
||||
---
|
||||
|
||||
## Archivos Clave a Crear
|
||||
|
||||
### Backend (Laravel)
|
||||
|
||||
```
|
||||
app/
|
||||
├── Http/Controllers/
|
||||
│ ├── AuthController.php
|
||||
│ ├── ClienteController.php
|
||||
│ ├── BalanzaController.php
|
||||
│ ├── CuentaController.php
|
||||
│ ├── ReporteController.php
|
||||
│ └── Admin/
|
||||
│ ├── UsuarioController.php
|
||||
│ ├── UmbralController.php
|
||||
│ └── ReglaMappeoController.php
|
||||
├── Models/
|
||||
│ ├── User.php
|
||||
│ ├── Cliente.php
|
||||
│ ├── Balanza.php
|
||||
│ ├── Cuenta.php
|
||||
│ ├── Reporte.php
|
||||
│ └── ...
|
||||
├── Services/
|
||||
│ ├── Parsers/
|
||||
│ │ ├── ParserInterface.php
|
||||
│ │ ├── ContpaqiParser.php
|
||||
│ │ └── DetectorFormato.php
|
||||
│ ├── ClasificadorCuentas.php
|
||||
│ ├── CalculadorMetricas.php
|
||||
│ └── GeneradorPdf.php
|
||||
└── ...
|
||||
```
|
||||
|
||||
### Frontend (React)
|
||||
|
||||
```
|
||||
src/
|
||||
├── components/
|
||||
│ ├── charts/
|
||||
│ │ ├── BarChart.tsx
|
||||
│ │ ├── LineChart.tsx
|
||||
│ │ ├── StackedBarChart.tsx
|
||||
│ │ ├── WaterfallChart.tsx
|
||||
│ │ └── ComboChart.tsx
|
||||
│ ├── cards/
|
||||
│ │ ├── KPICard.tsx
|
||||
│ │ └── InsightCard.tsx
|
||||
│ ├── forms/
|
||||
│ │ ├── ClienteForm.tsx
|
||||
│ │ └── UploadBalanza.tsx
|
||||
│ └── layout/
|
||||
│ ├── Sidebar.tsx
|
||||
│ └── Header.tsx
|
||||
├── pages/
|
||||
│ ├── Login.tsx
|
||||
│ ├── Dashboard/
|
||||
│ │ ├── index.tsx
|
||||
│ │ ├── Resumen.tsx
|
||||
│ │ ├── Margenes.tsx
|
||||
│ │ └── ...
|
||||
│ ├── Admin/
|
||||
│ │ ├── Usuarios.tsx
|
||||
│ │ └── Umbrales.tsx
|
||||
│ └── PdfView/
|
||||
│ └── index.tsx
|
||||
├── hooks/
|
||||
│ ├── useAuth.ts
|
||||
│ ├── useCliente.ts
|
||||
│ └── useReporte.ts
|
||||
├── services/
|
||||
│ └── api.ts
|
||||
└── types/
|
||||
└── index.ts
|
||||
```
|
||||
Reference in New Issue
Block a user