HEX
Server: Apache/2.4.58 (Ubuntu)
System: Linux Bradford-Sitios 6.14.0-1017-azure #17~24.04.1-Ubuntu SMP Mon Dec 1 20:10:50 UTC 2025 x86_64
User: www-data (33)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /var/www/api_matriculas/app/Exports/ComparativeReportExport.php
<?php

namespace App\Exports;

use Maatwebsite\Excel\Concerns\WithMultipleSheets;

class ComparativeReportExport implements WithMultipleSheets
{
    protected $data;

    public function __construct(array $data)
    {
        $this->data = $data;
    }

    public function sheets(): array
    {
        return [
            new ComparativeIndicatorsSheet($this->data['periods'] ?? []),
            new ComparativeFinancialSheet($this->data['periods'] ?? []),
            new ComparativeMovementsSheet($this->data['movements'] ?? []),
        ];
    }
}

// ─── Hoja 1: Indicadores ─────────────────────────────────────

class ComparativeIndicatorsSheet implements
    \Maatwebsite\Excel\Concerns\FromArray,
    \Maatwebsite\Excel\Concerns\WithHeadings,
    \Maatwebsite\Excel\Concerns\WithTitle,
    \Maatwebsite\Excel\Concerns\ShouldAutoSize
{
    protected $periods;

    public function __construct(array $periods)
    {
        $this->periods = $periods;
    }

    public function headings(): array
    {
        $headers = ['Indicador'];
        foreach ($this->periods as $period) {
            $headers[] = $period['label'] ?? '';
        }
        return $headers;
    }

    public function array(): array
    {
        $indicators = [
            ['key' => 'total', 'label' => 'Total contratos'],
            ['key' => 'total_students', 'label' => 'Alumnos únicos'],
            ['key' => 'finished', 'label' => 'Matrículas cerradas'],
            ['key' => 'in_course', 'label' => 'En curso'],
            ['key' => 'pending_payment', 'label' => 'Pendientes de pago'],
            ['key' => 'pending_signature', 'label' => 'Pendientes de firma'],
            ['key' => 'canceled', 'label' => 'Canceladas / Retiro'],
            ['key' => 'desistimiento_count', 'label' => 'Desistimiento'],
        ];

        $rows = [];
        foreach ($indicators as $indicator) {
            $row = [$indicator['label']];
            foreach ($this->periods as $period) {
                $row[] = $period['stats'][$indicator['key']] ?? 0;
            }
            $rows[] = $row;
        }

        return $rows;
    }

    public function title(): string
    {
        return 'Indicadores';
    }
}

// ─── Hoja 2: Financiero ──────────────────────────────────────

class ComparativeFinancialSheet implements
    \Maatwebsite\Excel\Concerns\FromArray,
    \Maatwebsite\Excel\Concerns\WithHeadings,
    \Maatwebsite\Excel\Concerns\WithTitle,
    \Maatwebsite\Excel\Concerns\ShouldAutoSize
{
    protected $periods;

    public function __construct(array $periods)
    {
        $this->periods = $periods;
    }

    public function headings(): array
    {
        $headers = ['Indicador'];
        foreach ($this->periods as $period) {
            $headers[] = $period['label'] ?? '';
        }
        return $headers;
    }

    public function array(): array
    {
        $indicators = [
            ['key' => 'total', 'label' => 'Total facturado'],
            ['key' => 'paid', 'label' => 'Total recaudado'],
            ['key' => 'pending', 'label' => 'Pendiente por cobrar'],
        ];

        $rows = [];
        foreach ($indicators as $indicator) {
            $row = [$indicator['label']];
            foreach ($this->periods as $period) {
                $row[] = round($period['financial'][$indicator['key']] ?? 0);
            }
            $rows[] = $row;
        }

        return $rows;
    }

    public function title(): string
    {
        return 'Financiero';
    }
}

// ─── Hoja 3: Movimientos ─────────────────────────────────────

class ComparativeMovementsSheet implements
    \Maatwebsite\Excel\Concerns\FromArray,
    \Maatwebsite\Excel\Concerns\WithTitle,
    \Maatwebsite\Excel\Concerns\ShouldAutoSize
{
    protected $movements;

    public function __construct(array $movements)
    {
        $this->movements = $movements;
    }

    public function array(): array
    {
        $rows = [];
        $headers = [
            'Código', 'Alumno', 'RUT Alumno', 'Curso', 'Nivel',
            'Apoderado', 'RUT Apoderado', 'Email Apoderado', 'Teléfono Apoderado',
            'Estado Contrato', 'Estado Pago', 'Estado Firma',
            'Matrícula Pagada', 'Código Toku',
            'Total ($)', 'Pagado ($)', 'Pendiente ($)',
        ];

        foreach ($this->movements as $movement) {
            $periodTo = $movement['period_to']['label'] ?? '';
            $periodFrom = $movement['period_from']['label'] ?? '';

            // Sección: Nuevos ingresos
            $rows[] = ["NUEVOS INGRESOS EN {$periodTo}"];
            $rows[] = $headers;

            foreach ($movement['nuevos_ingresos']['contracts'] ?? [] as $contract) {
                $rows[] = $this->contractToRow($contract);
            }

            if (empty($movement['nuevos_ingresos']['contracts'])) {
                $rows[] = ['Sin registros'];
            }

            $rows[] = ['']; // Separador

            // Sección: Desistimiento
            $rows[] = ["DESISTIMIENTO / RETIRO DESDE {$periodFrom}"];
            $rows[] = $headers;

            foreach ($movement['desistimiento']['contracts'] ?? [] as $contract) {
                $rows[] = $this->contractToRow($contract);
            }

            if (empty($movement['desistimiento']['contracts'])) {
                $rows[] = ['Sin registros'];
            }

            $rows[] = [''];
        }

        return $rows;
    }

    protected function contractToRow($contract)
    {
        $student = $contract['students'][0] ?? [];
        return [
            $contract['code_contract'] ?? '',
            $student['full_name'] ?? '',
            $student['rut'] ?? '',
            $student['course'] ?? '',
            $student['course_level'] ?? '',
            $contract['financial_parent']['full_name'] ?? '',
            $contract['financial_parent']['rut'] ?? '',
            $contract['financial_parent']['email'] ?? '',
            $contract['financial_parent']['mobile'] ?? '',
            $contract['status_contract']['description'] ?? '',
            $contract['status_payment']['description'] ?? '',
            $contract['status_signature']['description'] ?? '',
            ($contract['matricula_paid'] ?? false) ? 'Sí' : 'No',
            $contract['code_toku'] ?? '',
            $contract['total_amount_clp'] ?? 0,
            $contract['total_paid_clp'] ?? 0,
            $contract['total_pending_clp'] ?? 0,
        ];
    }

    public function title(): string
    {
        return 'Movimientos';
    }
}