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:
2026-01-31 22:24:00 -06:00
commit 4c3dc94ff2
107 changed files with 10701 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('giros', function (Blueprint $table) {
$table->id();
$table->string('nombre');
$table->boolean('activo')->default(true);
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('giros');
}
};

View File

@@ -0,0 +1,26 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('clientes', function (Blueprint $table) {
$table->id();
$table->string('nombre_empresa');
$table->string('logo')->nullable();
$table->foreignId('giro_id')->constrained('giros');
$table->string('moneda')->default('MXN');
$table->json('configuracion')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('clientes');
}
};

View File

@@ -0,0 +1,45 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('nombre');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->enum('role', ['admin', 'analista', 'cliente', 'empleado']);
$table->foreignId('cliente_id')->nullable()->constrained('clientes')->nullOnDelete();
$table->rememberToken();
$table->timestamps();
});
Schema::create('password_reset_tokens', function (Blueprint $table) {
$table->string('email')->primary();
$table->string('token');
$table->timestamp('created_at')->nullable();
});
Schema::create('sessions', function (Blueprint $table) {
$table->string('id')->primary();
$table->foreignId('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->longText('payload');
$table->integer('last_activity')->index();
});
}
public function down(): void
{
Schema::dropIfExists('sessions');
Schema::dropIfExists('password_reset_tokens');
Schema::dropIfExists('users');
}
};

View File

@@ -0,0 +1,26 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('permisos_empleado', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained('users')->cascadeOnDelete();
$table->foreignId('cliente_id')->constrained('clientes')->cascadeOnDelete();
$table->json('permisos'); // {ver_dashboard, ver_estados, exportar_pdf, etc.}
$table->timestamps();
$table->unique(['user_id', 'cliente_id']);
});
}
public function down(): void
{
Schema::dropIfExists('permisos_empleado');
}
};

View File

@@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('reportes_contables', function (Blueprint $table) {
$table->id();
$table->string('nombre'); // "Balance General", "Estado de Resultados"
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('reportes_contables');
}
};

View File

@@ -0,0 +1,24 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('categorias_contables', function (Blueprint $table) {
$table->id();
$table->foreignId('reporte_contable_id')->constrained('reportes_contables')->cascadeOnDelete();
$table->string('nombre');
$table->integer('orden');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('categorias_contables');
}
};

View File

@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('umbrales', function (Blueprint $table) {
$table->id();
$table->string('metrica'); // nombre de la métrica
$table->decimal('muy_positivo', 10, 4)->nullable();
$table->decimal('positivo', 10, 4)->nullable();
$table->decimal('neutral', 10, 4)->nullable();
$table->decimal('negativo', 10, 4)->nullable();
$table->decimal('muy_negativo', 10, 4)->nullable();
$table->foreignId('giro_id')->nullable()->constrained('giros')->nullOnDelete();
$table->timestamps();
$table->unique(['metrica', 'giro_id']);
});
}
public function down(): void
{
Schema::dropIfExists('umbrales');
}
};

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('balanzas', function (Blueprint $table) {
$table->id();
$table->foreignId('cliente_id')->constrained('clientes')->cascadeOnDelete();
$table->date('periodo_inicio');
$table->date('periodo_fin');
$table->string('sistema_origen'); // contpaqi, aspel, sap, etc.
$table->string('archivo_original');
$table->enum('status', ['pendiente', 'procesando', 'completado', 'error'])->default('pendiente');
$table->text('error_mensaje')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('balanzas');
}
};

View File

@@ -0,0 +1,40 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('cuentas', function (Blueprint $table) {
$table->id();
$table->foreignId('balanza_id')->constrained('balanzas')->cascadeOnDelete();
$table->string('codigo'); // ej: 001-100-000
$table->string('nombre');
$table->integer('nivel'); // nivel jerárquico
$table->foreignId('reporte_contable_id')->nullable()->constrained('reportes_contables');
$table->foreignId('categoria_contable_id')->nullable()->constrained('categorias_contables');
$table->foreignId('cuenta_padre_id')->nullable()->constrained('cuentas')->nullOnDelete();
$table->decimal('saldo_inicial_deudor', 18, 2)->default(0);
$table->decimal('saldo_inicial_acreedor', 18, 2)->default(0);
$table->decimal('cargos', 18, 2)->default(0);
$table->decimal('abonos', 18, 2)->default(0);
$table->decimal('saldo_final_deudor', 18, 2)->default(0);
$table->decimal('saldo_final_acreedor', 18, 2)->default(0);
$table->boolean('excluida')->default(false);
$table->boolean('es_cuenta_padre')->default(false);
$table->boolean('requiere_revision')->default(false);
$table->text('nota_revision')->nullable();
$table->timestamps();
$table->index(['balanza_id', 'codigo']);
});
}
public function down(): void
{
Schema::dropIfExists('cuentas');
}
};

View File

@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('reglas_mapeo', function (Blueprint $table) {
$table->id();
$table->string('sistema_origen'); // contpaqi, aspel, etc.
$table->string('cuenta_padre_codigo')->nullable(); // ej: 001-100-000
$table->string('rango_inicio')->nullable(); // ej: 101-000-000
$table->string('rango_fin')->nullable(); // ej: 154-999-999
$table->string('patron_regex')->nullable(); // para casos especiales
$table->foreignId('reporte_contable_id')->constrained('reportes_contables');
$table->foreignId('categoria_contable_id')->constrained('categorias_contables');
$table->integer('prioridad')->default(0);
$table->boolean('activo')->default(true);
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('reglas_mapeo');
}
};

View File

@@ -0,0 +1,27 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('mapeo_cuentas', function (Blueprint $table) {
$table->id();
$table->foreignId('cliente_id')->constrained('clientes')->cascadeOnDelete();
$table->string('codigo_patron'); // patrón de código para matching
$table->foreignId('categoria_contable_id')->constrained('categorias_contables');
$table->text('notas')->nullable();
$table->timestamps();
$table->unique(['cliente_id', 'codigo_patron']);
});
}
public function down(): void
{
Schema::dropIfExists('mapeo_cuentas');
}
};

View File

@@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('reportes', function (Blueprint $table) {
$table->id();
$table->foreignId('cliente_id')->constrained('clientes')->cascadeOnDelete();
$table->string('nombre');
$table->enum('periodo_tipo', ['mensual', 'trimestral', 'anual']);
$table->date('periodo_inicio');
$table->date('periodo_fin');
$table->timestamp('fecha_generacion')->nullable();
$table->json('data_calculada')->nullable(); // métricas, estados financieros, etc.
$table->string('pdf_path')->nullable();
$table->enum('status', ['pendiente', 'procesando', 'completado', 'error'])->default('pendiente');
$table->timestamps();
});
// Tabla pivote para relacionar reportes con balanzas
Schema::create('reporte_balanza', function (Blueprint $table) {
$table->foreignId('reporte_id')->constrained('reportes')->cascadeOnDelete();
$table->foreignId('balanza_id')->constrained('balanzas')->cascadeOnDelete();
$table->primary(['reporte_id', 'balanza_id']);
});
}
public function down(): void
{
Schema::dropIfExists('reporte_balanza');
Schema::dropIfExists('reportes');
}
};

View File

@@ -0,0 +1,27 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('personal_access_tokens', function (Blueprint $table) {
$table->id();
$table->morphs('tokenable');
$table->string('name');
$table->string('token', 64)->unique();
$table->text('abilities')->nullable();
$table->timestamp('last_used_at')->nullable();
$table->timestamp('expires_at')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('personal_access_tokens');
}
};