Skip to main content

Introduction

The Gerencia (Management) module provides executives and managers with comprehensive analytics, reporting tools, and business intelligence dashboards to monitor project performance, sales velocity, and financial projections.

Accessing the Management Dashboard

The management module requires manager-level authentication:
Route::middleware(['auth', 'check.cargo:Gerente'])
Authorized Role: Gerente (Manager) Route: /gerencia/dashboard

Dashboard Architecture

The management dashboard uses the GerenciaEstadisticasService to aggregate data from across the platform:
// GerenciaDashboardWebController::index
public function index(Request $request, GerenciaEstadisticasService $service)
{
    $filtros = [
        'desde'           => $request->query('desde'),
        'hasta'           => $request->query('hasta'),
        'proyecto_id'     => $request->query('proyecto_id'),
        'asesor_id'       => $request->query('asesor_id'),
        'estado_inmueble' => $request->query('estado_inmueble'),
    ];
    
    $dashboard = $service->obtenerDashboard($filtros);
    // Returns: resumenGlobal, ventasPorProyecto, proyeccionVsReal, etc.
}

Key Dashboard Components

Global Summary (Resumen Global)

High-level KPIs across all projects:
// GerenciaEstadisticasService::resumenGlobal
return [
    'ventas_totales'        => float,   // Total sales revenue
    'unidades_vendidas'     => int,     // Units sold
    'inventario_disponible' => int,     // Available units
];
Example Display:
┌─────────────────────────────┐
│  Ventas Totales         │
│  $15,234,567,890        │
└─────────────────────────────┘

┌─────────────────────────────┐
│  Unidades Vendidas      │
│  127 / 180              │
└─────────────────────────────┘

┌─────────────────────────────┐
│  Inventario Disponible  │
│  53 unidades            │
└─────────────────────────────┘

Sales by Project (Ventas por Proyecto)

Breakdown of performance per project:
return [
    [
        'id_proyecto' => int,
        'nombre'      => string,
        'total_valor' => float,
        'unidades'    => int,
    ],
    // ...
];
Displayed as bar chart comparing projects.

Goals vs. Actual (Proyección vs Real)

Compares monthly sales targets (metas) against actual performance:
// GerenciaEstadisticasService::proyeccionVsRealMensual
return [
    [
        'id_proyecto'   => int,
        'nombre'        => string,
        'meta_unidades' => int,     // Target units
        'meta_valor'    => float,   // Target revenue
        'real_unidades' => int,     // Actual units sold
        'real_valor'    => float,   // Actual revenue
    ],
    // ...
];
Visualized with grouped bar charts:
Proyecto Aurora
  Meta:  15 unidades  |  Real: 18 unidades  ✓
  Meta:  $450M        |  Real: $475M        ✓

Proyecto Esmeralda
  Meta:  20 unidades  |  Real: 17 unidades  ✗
  Meta:  $600M        |  Real: $530M        ✗

Sales Velocity (Velocidad de Ventas)

Average days from project start to unit sale:
// GerenciaEstadisticasService::velocidadVentasPorProyecto
return [
    [
        'id_proyecto'         => int,
        'proyecto'            => string,
        'dias_promedio_venta' => float,  // Average days to sell
    ],
    // ...
];
Calculation:
$inicio = Carbon::parse($proyecto->fecha_inicio);
$dias = $ventas->map(function ($v) use ($inicio) {
    return $inicio->diffInDays(Carbon::parse($v->fecha_venta));
});
$promedio = $dias->avg();

Separation Effectiveness (Separaciones y Efectividad)

Tracks conversion rates for sales advisors:
return [
    [
        'id_empleado'             => int,
        'empleado'                => string,
        'total_separaciones'      => int,
        'separaciones_caducadas'  => int,  // Expired
        'separaciones_ejecutadas' => int,  // Converted
    ],
    // ...
];
Conversion rate = ejecutadas / total

Inventory by Project (Inventario por Proyecto)

Detailed property status across all projects:
return [
    [
        'id_proyecto' => int,
        'nombre'      => string,
        'inmuebles'   => [
            [
                'tipo'            => 'Apartamento' | 'Local',
                'etiqueta'        => string,  // e.g., "Apto 1501"
                'precio_base'     => float,
                'precio_vigente'  => float,
                'estado'          => string,  // Disponible/Vendido/etc.
                'asesor'          => string,  // Last advisor if sold
                'fecha_operacion' => date,
            ],
            // ...
        ],
    ],
    // ...
];
Filters:
  • By project
  • By property state (Disponible, Vendido, Separado)

Sales by Advisor & Project (Ventas por Asesor y Proyecto)

Performance matrix:
return [
    [
        'id_proyecto'             => int,
        'proyecto'                => string,
        'id_empleado'             => int,
        'empleado'                => string,
        'ventas'                  => int,
        'separaciones'            => int,
        'separaciones_ejecutadas' => int,
        'separaciones_caducadas'  => int,
    ],
    // ...
];
Used for ranking and commission calculations.

Additional Analytics

Inventory Status (Estado Inventario)

Doughnut charts showing property distribution:
// GerenciaEstadisticasService::estadoInventario
return Proyecto::with(['torres.apartamentos.estadoInmueble'])
    ->get()
    ->map(function ($proyecto) {
        $estados = [
            'Disponible' => 0,
            'Vendido' => 0,
            'Separado' => 0,
            'Bloqueado' => 0,
            'Congelado' => 0,
        ];
        
        foreach ($proyecto->torres as $torre) {
            foreach ($torre->apartamentos as $apto) {
                $nombre = $apto->estadoInmueble?->nombre;
                if (isset($estados[$nombre])) {
                    $estados[$nombre]++;
                }
            }
        }
        
        return [
            'proyecto' => $proyecto->nombre,
            'estados'  => $estados,
        ];
    });

Advisor Ranking (Ranking Asesores)

Top performers by revenue:
// GerenciaEstadisticasService::rankingAsesores
return DB::table('ventas')
    ->join('empleados', 'empleados.id_empleado', '=', 'ventas.id_empleado')
    ->where('ventas.tipo_operacion', 'venta')
    ->select(
        'empleados.id_empleado',
        DB::raw("CONCAT(empleados.nombre, ' ', empleados.apellido) as asesor"),
        DB::raw("SUM(ventas.valor_total) as total_ventas")
    )
    ->groupBy('empleados.id_empleado', 'empleados.nombre', 'empleados.apellido')
    ->orderByDesc('total_ventas')
    ->get();

Monthly Absorption (Absorción Mensual)

Units sold per month by project (time series):
// GerenciaEstadisticasService::absorcionMensual
return DB::table('ventas')
    ->join('proyectos', 'proyectos.id_proyecto', '=', 'ventas.id_proyecto')
    ->where('ventas.tipo_operacion', 'venta')
    ->select(
        'proyectos.nombre as proyecto',
        DB::raw("TO_CHAR(fecha_venta, 'YYYY-MM') as mes"),
        DB::raw("COUNT(*) as unidades")
    )
    ->groupBy('proyectos.nombre', DB::raw("TO_CHAR(fecha_venta, 'YYYY-MM')"))
    ->orderBy('mes')
    ->get();
Displayed as line chart showing sales trends.

Filter Controls

The dashboard supports dynamic filtering:

Date Range Filter

'desde' => Carbon::now()->startOfYear(),  // Default: year start
'hasta' => Carbon::now()->endOfYear(),    // Default: year end
User can select custom ranges to focus on specific periods.

Project Filter

'proyecto_id' => integer | null  // null = all projects
Filters all dashboard widgets to single project.

Advisor Filter

'asesor_id' => integer | null  // Filter by commercial advisor
Focuses on specific salesperson’s performance.

Property State Filter

'estado_inmueble' => integer | null  // Filter inventory view
Filters inventory table by Disponible, Vendido, etc.

Chart Visualizations

The dashboard uses Chart.js with custom plugins:
// resources/js/Pages/Gerencia/Dashboard/Index.vue

import { Bar, Doughnut, Line } from 'vue-chartjs'
import {
  Chart as ChartJS,
  ArcElement,
  BarElement,
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  Tooltip,
  Legend,
} from 'chart.js'

Custom Value Labels Plugin

Displays values directly on charts without hover:
const ValueLabelsPlugin = {
  id: 'valueLabelsPlugin',
  afterDatasetsDraw(chart) {
    const { ctx } = chart
    
    // Format large currency values compactly
    const formatCompactMoney = (v) => {
      const abs = Math.abs(v)
      if (abs >= 1_000_000) {
        return `${(v / 1_000_000).toFixed(1)}MM`
      }
      if (abs >= 1_000) {
        return `${(v / 1_000).toFixed(1)}k`
      }
      return `${Math.round(v)}`
    }
    
    // Draw labels on bars/lines
    // ...
  }
}

Sales Goals Management

Managers can define monthly sales targets. Route: /gerencia/metas

Viewing Analytics

Learn how to use analytics tools and export reports.

Payment Plan Consolidation

View consolidated down payment schedules across all sales. Route: /gerencia/dashboard (Plan Pagos CI section) Displays horizontal timeline showing:
  • Client and property
  • Monthly installments
  • Row per sale
  • Column per month
  • Totals row
Export: /gerencia/plan-pagos-ci/export (Excel)

Login Activity Monitoring

Track user access: Route: /gerencia/login-logs Displays:
  • Employee name
  • Login timestamp
  • IP address
  • User agent
Useful for security audits and activity tracking.

Access Control

All management routes require Gerente role:
Route::middleware(['auth', 'check.cargo:Gerente'])->group(function () {
    Route::get('/gerencia/dashboard', [GerenciaDashboardWebController::class, 'index']);
    Route::get('/gerencia/metas', [MetasController::class, 'index']);
    // ...
});

Dashboard Performance

Optimizations

The service uses efficient queries:
// Eager loading to prevent N+1
$proyectos = Proyecto::with([
    'torres.apartamentos.estadoInmueble',
    'torres.apartamentos.ventas' => fn($q) => $q->orderBy('fecha_venta', 'desc'),
])->get();

// Aggregations at database level
$ventasQ = Venta::select(
    'id_proyecto',
    DB::raw('SUM(valor_total) as total_valor'),
    DB::raw('COUNT(*) as unidades')
)
->groupBy('id_proyecto');

Caching Strategy

For large datasets, consider implementing caching:
// Example: Cache dashboard data for 5 minutes
$dashboard = Cache::remember(
    "gerencia_dashboard_{$userId}_" . md5(json_encode($filtros)),
    300,
    fn() => $service->obtenerDashboard($filtros)
);

Export Capabilities

Managers can export data to Excel:
// Plan Pagos CI Export
Route::get('/gerencia/plan-pagos-ci/export', [PlanPagosCIExportController::class, 'export'])
    ->name('gerencia.plan_pagos_ci.export');

// Uses Maatwebsite/Excel
return Excel::download(
    new PlanPagosCIExport($encabezados, $filas, $totales),
    'plan_pagos_cuota_inicial.xlsx'
);

Next Steps

Viewing Analytics

Detailed guide on using analytics tools, interpreting reports, and exporting data.

Technical Reference

  • Controllers:
    • app/Http/Controllers/Gerencia/GerenciaDashboardWebController.php
    • app/Http/Controllers/Gerencia/MetasController.php
  • Services: app/Services/GerenciaEstadisticasService.php
  • Views: resources/js/Pages/Gerencia/Dashboard/Index.vue
  • Routes: routes/web.php:414-448
  • Exports: app/Exports/PlanPagosCIExport.php

Build docs developers (and LLMs) love