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:
@@ -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');
|
||||
}
|
||||
};
|
||||
@@ -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');
|
||||
}
|
||||
};
|
||||
@@ -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');
|
||||
}
|
||||
};
|
||||
@@ -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');
|
||||
}
|
||||
};
|
||||
@@ -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');
|
||||
}
|
||||
};
|
||||
@@ -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');
|
||||
}
|
||||
};
|
||||
@@ -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');
|
||||
}
|
||||
};
|
||||
@@ -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');
|
||||
}
|
||||
};
|
||||
@@ -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');
|
||||
}
|
||||
};
|
||||
@@ -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');
|
||||
}
|
||||
};
|
||||
@@ -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');
|
||||
}
|
||||
};
|
||||
@@ -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');
|
||||
}
|
||||
};
|
||||
@@ -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');
|
||||
}
|
||||
};
|
||||
21
backend/database/seeders/AdminUserSeeder.php
Normal file
21
backend/database/seeders/AdminUserSeeder.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
class AdminUserSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
User::create([
|
||||
'nombre' => 'Administrador',
|
||||
'email' => 'admin@horux360.com',
|
||||
'password' => Hash::make('password'),
|
||||
'role' => 'admin',
|
||||
'cliente_id' => null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
19
backend/database/seeders/DatabaseSeeder.php
Normal file
19
backend/database/seeders/DatabaseSeeder.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class DatabaseSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
$this->call([
|
||||
GirosSeeder::class,
|
||||
ReportesContablesSeeder::class,
|
||||
ReglasMapeeoContpaqiSeeder::class,
|
||||
UmbralesSeeder::class,
|
||||
AdminUserSeeder::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
43
backend/database/seeders/GirosSeeder.php
Normal file
43
backend/database/seeders/GirosSeeder.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Giro;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class GirosSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
$giros = [
|
||||
'Agricultura y Ganadería',
|
||||
'Alimentos y Bebidas',
|
||||
'Automotriz',
|
||||
'Comercio al por Mayor',
|
||||
'Comercio al por Menor',
|
||||
'Construcción',
|
||||
'Educación',
|
||||
'Energía',
|
||||
'Farmacéutica',
|
||||
'Financiero',
|
||||
'Hotelería',
|
||||
'Inmobiliario',
|
||||
'Logística y Transporte',
|
||||
'Manufactura',
|
||||
'Medios y Entretenimiento',
|
||||
'Minería',
|
||||
'Restaurantes',
|
||||
'Salud',
|
||||
'Servicios Profesionales',
|
||||
'Tecnología',
|
||||
'Telecomunicaciones',
|
||||
'Textil y Moda',
|
||||
'Turismo',
|
||||
'Otro',
|
||||
];
|
||||
|
||||
foreach ($giros as $nombre) {
|
||||
Giro::create(['nombre' => $nombre, 'activo' => true]);
|
||||
}
|
||||
}
|
||||
}
|
||||
142
backend/database/seeders/ReglasMapeeoContpaqiSeeder.php
Normal file
142
backend/database/seeders/ReglasMapeeoContpaqiSeeder.php
Normal file
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\ReglaMapeo;
|
||||
use App\Models\ReporteContable;
|
||||
use App\Models\CategoriaContable;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class ReglasMapeeoContpaqiSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
$balanceGeneral = ReporteContable::where('nombre', 'Balance General')->first();
|
||||
$estadoResultados = ReporteContable::where('nombre', 'Estado de Resultados')->first();
|
||||
|
||||
// Obtener categorías
|
||||
$activosCirculantes = CategoriaContable::where('nombre', 'Activos Circulantes')->first();
|
||||
$activosNoCirculantes = CategoriaContable::where('nombre', 'Activos No Circulantes')->first();
|
||||
$pasivoCirculante = CategoriaContable::where('nombre', 'Pasivo Circulante')->first();
|
||||
$pasivoNoCirculante = CategoriaContable::where('nombre', 'Pasivo No Circulante')->first();
|
||||
$capitalSocial = CategoriaContable::where('nombre', 'Capital Social')->first();
|
||||
$perdidasAnteriores = CategoriaContable::where('nombre', 'Pérdidas Ejercicios Anteriores')->first();
|
||||
$utilidadesAnteriores = CategoriaContable::where('nombre', 'Utilidades Ejercicios Anteriores')->first();
|
||||
$ingresos = CategoriaContable::where('nombre', 'Ingresos')->first();
|
||||
$costoVenta = CategoriaContable::where('nombre', 'Costo de Venta')->first();
|
||||
$gastosOperativos = CategoriaContable::where('nombre', 'Gastos Operativos')->first();
|
||||
$otrosGastos = CategoriaContable::where('nombre', 'Otros Gastos')->first();
|
||||
$gastosFinancieros = CategoriaContable::where('nombre', 'Gastos Financieros')->first();
|
||||
|
||||
$reglas = [
|
||||
// Activos Circulantes: 001-100-000, hijos 101-000-000 a 154-999-999
|
||||
[
|
||||
'sistema_origen' => 'contpaqi',
|
||||
'cuenta_padre_codigo' => '001-100-000',
|
||||
'rango_inicio' => '101-000-000',
|
||||
'rango_fin' => '154-999-999',
|
||||
'reporte_contable_id' => $balanceGeneral->id,
|
||||
'categoria_contable_id' => $activosCirculantes->id,
|
||||
'prioridad' => 10,
|
||||
],
|
||||
// Activos No Circulantes: 001-200-000, hijos 155-000-000 a 199-999-999
|
||||
[
|
||||
'sistema_origen' => 'contpaqi',
|
||||
'cuenta_padre_codigo' => '001-200-000',
|
||||
'rango_inicio' => '155-000-000',
|
||||
'rango_fin' => '199-999-999',
|
||||
'reporte_contable_id' => $balanceGeneral->id,
|
||||
'categoria_contable_id' => $activosNoCirculantes->id,
|
||||
'prioridad' => 10,
|
||||
],
|
||||
// Pasivo Circulante: 002-100-000, hijos 200-000-000 a 209-999-999
|
||||
[
|
||||
'sistema_origen' => 'contpaqi',
|
||||
'cuenta_padre_codigo' => '002-100-000',
|
||||
'rango_inicio' => '200-000-000',
|
||||
'rango_fin' => '209-999-999',
|
||||
'reporte_contable_id' => $balanceGeneral->id,
|
||||
'categoria_contable_id' => $pasivoCirculante->id,
|
||||
'prioridad' => 10,
|
||||
],
|
||||
// Pasivo No Circulante: 002-200-000, hijos 210-000-000 a 220-999-999
|
||||
[
|
||||
'sistema_origen' => 'contpaqi',
|
||||
'cuenta_padre_codigo' => '002-200-000',
|
||||
'rango_inicio' => '210-000-000',
|
||||
'rango_fin' => '220-999-999',
|
||||
'reporte_contable_id' => $balanceGeneral->id,
|
||||
'categoria_contable_id' => $pasivoNoCirculante->id,
|
||||
'prioridad' => 10,
|
||||
],
|
||||
// Capital Social: 300-XXX-XXX
|
||||
[
|
||||
'sistema_origen' => 'contpaqi',
|
||||
'patron_regex' => '/^30[0-9]-/',
|
||||
'reporte_contable_id' => $balanceGeneral->id,
|
||||
'categoria_contable_id' => $capitalSocial->id,
|
||||
'prioridad' => 10,
|
||||
],
|
||||
// Pérdidas Ejercicios Anteriores: 310-XXX-XXX
|
||||
[
|
||||
'sistema_origen' => 'contpaqi',
|
||||
'patron_regex' => '/^310-/',
|
||||
'reporte_contable_id' => $balanceGeneral->id,
|
||||
'categoria_contable_id' => $perdidasAnteriores->id,
|
||||
'prioridad' => 15,
|
||||
],
|
||||
// Utilidades Ejercicios Anteriores: 311-XXX-XXX
|
||||
[
|
||||
'sistema_origen' => 'contpaqi',
|
||||
'patron_regex' => '/^311-/',
|
||||
'reporte_contable_id' => $balanceGeneral->id,
|
||||
'categoria_contable_id' => $utilidadesAnteriores->id,
|
||||
'prioridad' => 15,
|
||||
],
|
||||
// Ingresos: 40X-XXX-XXX
|
||||
[
|
||||
'sistema_origen' => 'contpaqi',
|
||||
'patron_regex' => '/^40[0-9]-/',
|
||||
'reporte_contable_id' => $estadoResultados->id,
|
||||
'categoria_contable_id' => $ingresos->id,
|
||||
'prioridad' => 10,
|
||||
],
|
||||
// Costo de Venta: podría ser 410-XXX o 50X en algunos casos
|
||||
[
|
||||
'sistema_origen' => 'contpaqi',
|
||||
'patron_regex' => '/^41[0-9]-/',
|
||||
'reporte_contable_id' => $estadoResultados->id,
|
||||
'categoria_contable_id' => $costoVenta->id,
|
||||
'prioridad' => 10,
|
||||
],
|
||||
// Gastos Operativos: 5XX-XXX-XXX
|
||||
[
|
||||
'sistema_origen' => 'contpaqi',
|
||||
'patron_regex' => '/^5[0-9]{2}-/',
|
||||
'reporte_contable_id' => $estadoResultados->id,
|
||||
'categoria_contable_id' => $gastosOperativos->id,
|
||||
'prioridad' => 10,
|
||||
],
|
||||
// Otros Gastos: 6XX-XXX-XXX
|
||||
[
|
||||
'sistema_origen' => 'contpaqi',
|
||||
'patron_regex' => '/^6[0-9]{2}-/',
|
||||
'reporte_contable_id' => $estadoResultados->id,
|
||||
'categoria_contable_id' => $otrosGastos->id,
|
||||
'prioridad' => 10,
|
||||
],
|
||||
// Gastos Financieros: 7XX-XXX-XXX
|
||||
[
|
||||
'sistema_origen' => 'contpaqi',
|
||||
'patron_regex' => '/^7[0-9]{2}-/',
|
||||
'reporte_contable_id' => $estadoResultados->id,
|
||||
'categoria_contable_id' => $gastosFinancieros->id,
|
||||
'prioridad' => 10,
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($reglas as $regla) {
|
||||
ReglaMapeo::create(array_merge($regla, ['activo' => true]));
|
||||
}
|
||||
}
|
||||
}
|
||||
53
backend/database/seeders/ReportesContablesSeeder.php
Normal file
53
backend/database/seeders/ReportesContablesSeeder.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\ReporteContable;
|
||||
use App\Models\CategoriaContable;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class ReportesContablesSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
// Balance General
|
||||
$balanceGeneral = ReporteContable::create(['nombre' => 'Balance General']);
|
||||
|
||||
$categoriasBalance = [
|
||||
['nombre' => 'Activos Circulantes', 'orden' => 1],
|
||||
['nombre' => 'Activos No Circulantes', 'orden' => 2],
|
||||
['nombre' => 'Pasivo Circulante', 'orden' => 3],
|
||||
['nombre' => 'Pasivo No Circulante', 'orden' => 4],
|
||||
['nombre' => 'Capital Social', 'orden' => 5],
|
||||
['nombre' => 'Pérdidas Ejercicios Anteriores', 'orden' => 6],
|
||||
['nombre' => 'Utilidades Ejercicios Anteriores', 'orden' => 7],
|
||||
];
|
||||
|
||||
foreach ($categoriasBalance as $categoria) {
|
||||
CategoriaContable::create([
|
||||
'reporte_contable_id' => $balanceGeneral->id,
|
||||
'nombre' => $categoria['nombre'],
|
||||
'orden' => $categoria['orden'],
|
||||
]);
|
||||
}
|
||||
|
||||
// Estado de Resultados
|
||||
$estadoResultados = ReporteContable::create(['nombre' => 'Estado de Resultados']);
|
||||
|
||||
$categoriasResultados = [
|
||||
['nombre' => 'Ingresos', 'orden' => 1],
|
||||
['nombre' => 'Costo de Venta', 'orden' => 2],
|
||||
['nombre' => 'Gastos Operativos', 'orden' => 3],
|
||||
['nombre' => 'Otros Gastos', 'orden' => 4],
|
||||
['nombre' => 'Gastos Financieros', 'orden' => 5],
|
||||
];
|
||||
|
||||
foreach ($categoriasResultados as $categoria) {
|
||||
CategoriaContable::create([
|
||||
'reporte_contable_id' => $estadoResultados->id,
|
||||
'nombre' => $categoria['nombre'],
|
||||
'orden' => $categoria['orden'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
55
backend/database/seeders/UmbralesSeeder.php
Normal file
55
backend/database/seeders/UmbralesSeeder.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Umbral;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class UmbralesSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
// Umbrales por defecto (sin giro específico)
|
||||
$umbrales = [
|
||||
// Márgenes (valores en decimales, ej: 0.20 = 20%)
|
||||
['metrica' => 'margen_bruto', 'muy_positivo' => 0.50, 'positivo' => 0.35, 'neutral' => 0.20, 'negativo' => 0.10, 'muy_negativo' => 0],
|
||||
['metrica' => 'margen_ebitda', 'muy_positivo' => 0.30, 'positivo' => 0.20, 'neutral' => 0.10, 'negativo' => 0.05, 'muy_negativo' => 0],
|
||||
['metrica' => 'margen_operativo', 'muy_positivo' => 0.25, 'positivo' => 0.15, 'neutral' => 0.08, 'negativo' => 0.03, 'muy_negativo' => 0],
|
||||
['metrica' => 'margen_neto', 'muy_positivo' => 0.20, 'positivo' => 0.10, 'neutral' => 0.05, 'negativo' => 0.02, 'muy_negativo' => 0],
|
||||
['metrica' => 'margen_nopat', 'muy_positivo' => 0.18, 'positivo' => 0.10, 'neutral' => 0.05, 'negativo' => 0.02, 'muy_negativo' => 0],
|
||||
['metrica' => 'margen_ocf', 'muy_positivo' => 0.25, 'positivo' => 0.15, 'neutral' => 0.08, 'negativo' => 0.03, 'muy_negativo' => 0],
|
||||
['metrica' => 'margen_fcf', 'muy_positivo' => 0.20, 'positivo' => 0.10, 'neutral' => 0.05, 'negativo' => 0, 'muy_negativo' => -0.10],
|
||||
|
||||
// Retorno
|
||||
['metrica' => 'roic', 'muy_positivo' => 0.20, 'positivo' => 0.12, 'neutral' => 0.08, 'negativo' => 0.04, 'muy_negativo' => 0],
|
||||
['metrica' => 'roe', 'muy_positivo' => 0.25, 'positivo' => 0.15, 'neutral' => 0.10, 'negativo' => 0.05, 'muy_negativo' => 0],
|
||||
['metrica' => 'roa', 'muy_positivo' => 0.15, 'positivo' => 0.08, 'neutral' => 0.05, 'negativo' => 0.02, 'muy_negativo' => 0],
|
||||
['metrica' => 'roce', 'muy_positivo' => 0.20, 'positivo' => 0.12, 'neutral' => 0.08, 'negativo' => 0.04, 'muy_negativo' => 0],
|
||||
|
||||
// Eficiencia (días)
|
||||
['metrica' => 'dias_clientes', 'muy_positivo' => 30, 'positivo' => 45, 'neutral' => 60, 'negativo' => 90, 'muy_negativo' => 120],
|
||||
['metrica' => 'dias_proveedores', 'muy_positivo' => 60, 'positivo' => 45, 'neutral' => 30, 'negativo' => 20, 'muy_negativo' => 15],
|
||||
['metrica' => 'dias_inventario', 'muy_positivo' => 30, 'positivo' => 45, 'neutral' => 60, 'negativo' => 90, 'muy_negativo' => 120],
|
||||
['metrica' => 'ciclo_conversion', 'muy_positivo' => 30, 'positivo' => 45, 'neutral' => 60, 'negativo' => 90, 'muy_negativo' => 120],
|
||||
|
||||
// Liquidez (ratios)
|
||||
['metrica' => 'current_ratio', 'muy_positivo' => 2.5, 'positivo' => 2.0, 'neutral' => 1.5, 'negativo' => 1.0, 'muy_negativo' => 0.8],
|
||||
['metrica' => 'quick_ratio', 'muy_positivo' => 1.5, 'positivo' => 1.2, 'neutral' => 1.0, 'negativo' => 0.8, 'muy_negativo' => 0.5],
|
||||
['metrica' => 'cash_ratio', 'muy_positivo' => 0.5, 'positivo' => 0.3, 'neutral' => 0.2, 'negativo' => 0.1, 'muy_negativo' => 0.05],
|
||||
|
||||
// Solvencia
|
||||
['metrica' => 'net_debt_ebitda', 'muy_positivo' => 1.0, 'positivo' => 2.0, 'neutral' => 3.0, 'negativo' => 4.0, 'muy_negativo' => 5.0],
|
||||
['metrica' => 'interest_coverage', 'muy_positivo' => 10.0, 'positivo' => 5.0, 'neutral' => 3.0, 'negativo' => 2.0, 'muy_negativo' => 1.0],
|
||||
['metrica' => 'debt_ratio', 'muy_positivo' => 0.30, 'positivo' => 0.40, 'neutral' => 0.50, 'negativo' => 0.60, 'muy_negativo' => 0.70],
|
||||
|
||||
// Gestión
|
||||
['metrica' => 'revenue_growth', 'muy_positivo' => 0.20, 'positivo' => 0.10, 'neutral' => 0.05, 'negativo' => 0, 'muy_negativo' => -0.05],
|
||||
['metrica' => 'capex_revenue', 'muy_positivo' => 0.05, 'positivo' => 0.08, 'neutral' => 0.12, 'negativo' => 0.15, 'muy_negativo' => 0.20],
|
||||
['metrica' => 'effective_tax_rate', 'muy_positivo' => 0.25, 'positivo' => 0.28, 'neutral' => 0.30, 'negativo' => 0.33, 'muy_negativo' => 0.35],
|
||||
];
|
||||
|
||||
foreach ($umbrales as $umbral) {
|
||||
Umbral::create(array_merge($umbral, ['giro_id' => null]));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user