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/gestion-formularios.bdfschool/app/Imports/ProcessUploadStudentPaymentsImport.php
<?php

namespace App\Imports;

use App\Models\ConceptJournal;
use App\Models\UploadStudentPayment;
use App\Models\UploadStudentPaymentDetail;
use Carbon\Carbon;
use Maatwebsite\Excel\Facades\Excel;

class ProcessUploadStudentPaymentsImport {

    private $first_file;
    private $second_file;
    public $errorMessage;
    public $successMessage;
    public $register_id;
    private $partners;

    public function __construct($first_file, $second_file, $partners)
    {
        $this->first_file = $first_file;
        $this->second_file = $second_file;
        $this->partners = $partners;
    }

    public function import()
    {
        $first_file_data = Excel::toCollection(new UploadStudentPaymentsImport, $this->first_file);
        $second_file_data = Excel::toCollection(new UploadStudentPaymentsImport, $this->second_file);

        if ($first_file_data[0]->isEmpty() || $second_file_data[0]->isEmpty()) {
            $this->errorMessage = 'Uno de los archivos está vacío.';
            return;
        }

        $first_headers = $first_file_data[0]->first()->keys()->toArray();
        $second_headers = $second_file_data[0]->first()->keys()->toArray();

        $first_file_array = $first_file_data->toArray()[0];
        $second_file_array = $second_file_data->toArray()[0];

        //ENCABEZADOS REQUERIDOS EN CADA TABLA
        $payment_detail_columns = [
            'n',
            'apoderado',
            'rut_apoderado',
            'id_apoderado',
            'fecha_de_pago',
            'monto_del_pago',
            'forma_de_pago',
            'tarjeta_de_debito_o_credito',
            'nro_operacion_orden_compra_o_cheque',
            'n_boleta',
            'tipo_documento',
            'estado',
            'fecha_emision',
            'monto_total'
        ];

        $items_detail_columns = [
            'boleta',
            'fecha_pago',
            'forma_de_pago',
            'cod_autorizacion',
            'item_de_cargo',
            'alumnoa',
            'rut',
            'curso',
            'septiembre',
        ];


        //VALIDACIÓN DE ARCHIVOS POR ENCABEZADOS REQUERIDOS
        $detail_file = null;
        $items_file = null;

        if ($this->validateHeaders($first_headers, $payment_detail_columns)) {
            $detail_file = $first_file_array;
            $items_file = $second_file_array;

            if(!$this->validateHeaders($second_headers, $items_detail_columns)) {
                $this->errorMessage = 'Ninguno de los archivos tiene los encabezados requeridos de detalle de items.';
                return;
            }

        } elseif ($this->validateHeaders($second_headers, $payment_detail_columns)) {
            $detail_file = $second_file_array;
            $items_file = $first_file_array;

            if(!$this->validateHeaders($first_headers, $items_detail_columns)) {
                $this->errorMessage = 'Ninguno de los archivos tiene los encabezados requeridos de detalle de items.';
                return;
            }

        } else {
            $this->errorMessage = 'Ninguno de los archivos tiene los encabezados requeridos de detalle de pagos.';
            return;
        }

        
        //BUSCAR COINCIDENCIAS POR NÚMERO DE BOLETA, SI NO LAS HAY NO SE GENERA REGISTRO

        // 1. Obtener números de boletas del archivo de items
        $invoice_numbers = array_filter(
            array_merge(...array_map(fn($value) => explode('-', $value), 
            array_filter(array_column($items_file, 'boleta'), fn($value) => $value && $value !== '0'))
        ));

        //pre_die($items_file);

        // 2. Buscar coincidencias por número de boletas en archivo de detalles de pago y almacenarlas en un array si las hay
        $invoice_number_matches = [];

        foreach($invoice_numbers as $invoice_number) {

            foreach($detail_file as $payment_detail) {

                if($invoice_number == $payment_detail['n_boleta']) {

                    // OBTENER DATA DE ITEM_DETAIL
                    $item_detail = array_values(array_filter($items_file, function($item) use ($invoice_number) {
                        return isset($item['boleta']) && in_array($invoice_number, explode('-', $item['boleta']));
                    }));

                    $item_detail = $item_detail[0];

                    // $odoo_parent_id = isset($this->partners[strUpper(str_replace('.', '', formateaRut($payment_detail['rut_apoderado'])))]) ? $this->partners[strUpper(str_replace('.', '', formateaRut($payment_detail['rut_apoderado'])))] : null;

                    // $odoo_student_id = isset($this->partners[str_replace('.', '', formateaRut($item_detail['rut']))]) ? $this->partners[str_replace('.', '', formateaRut($item_detail['rut']))] : null;

                    //FORMATEAR DATOS PARA INSERTAR
                    $upload_payment_detail_insertion = [
                        'invoice_number' => !empty($payment_detail['n_boleta']) ? $payment_detail['n_boleta'] : null,
                        'payment_number' => !empty($payment_detail['n']) ? $payment_detail['n'] : null,
                        'guardian' => !empty($payment_detail['apoderado']) ? $payment_detail['apoderado'] : null,
                        'guardian_id' => !empty($payment_detail['id_apoderado']) ? $payment_detail['id_apoderado'] : null,
                        'payment_date' => !empty($payment_detail['fecha_de_pago']) ? $payment_detail['fecha_de_pago'] : null,
                        'payment_amount' => !empty($payment_detail['monto_del_pago']) ? $payment_detail['monto_del_pago'] : null,
                        'payment_method' => !empty($payment_detail['forma_de_pago']) ? $payment_detail['forma_de_pago'] : null,
                        'operation_number' => !empty($payment_detail['nro_operacion_orden_compra_o_cheque']) ? $payment_detail['nro_operacion_orden_compra_o_cheque'] : null,
                        'document_type' => !empty($payment_detail['tipo_documento']) ? $payment_detail['tipo_documento'] : null,
                        'status' => !empty($payment_detail['estado']) ? $payment_detail['estado'] : null,
                        'emision_date' => !empty($payment_detail['fecha_emision']) ? $payment_detail['fecha_emision'] : null,
                        'total_amount' => !empty($payment_detail['monto_total']) ? $payment_detail['monto_total'] : null,
                        'user_created' => auth()->user()->id,
                        'created_at' => Carbon::now(),
                        'authorization_code' => !empty($item_detail['cod_autorizacion']) ? $item_detail['cod_autorizacion'] : null,
                        'charge_item' => !empty($item_detail['item_de_cargo']) ? $item_detail['item_de_cargo'] : null,
                        'student' => !empty($item_detail['alumnoa']) ? $item_detail['alumnoa'] : null,
                        'student_rut' => !empty($item_detail['rut']) ? $item_detail['rut'] : null,
                        'student_class' => !empty($item_detail['curso']) ? $item_detail['curso'] : null,
                        'upload_student_payment_id' => null,
                        'guardian_rut' => !empty($payment_detail['rut_apoderado']) ? $payment_detail['rut_apoderado'] : null,
                        'load_status' => 1,
                        'detail_integration_status_id' => 1,
                        'debit' => isset($payment_detail['debe']) ? $payment_detail['debe'] : '',
                        //'credit_account_id' => 21, //dato fijo: Cuenta única para apoderados
                        'credit' => isset($payment_detail['haber']) ? $payment_detail['haber'] : ''
                    ];

                    array_push($invoice_number_matches, $upload_payment_detail_insertion);
                }
            }
        }

        //pre_die($invoice_number_matches);

        if(empty($invoice_number_matches)) {
            $this->errorMessage = 'No se han encontrado coincidencias por número de boleta en los archivos.';
            return;
        }

        //ALMACENAR REGISTROS

        //1.Crear cabecera
        $quantity = count($invoice_number_matches);
        $quantity_success = 0;
        $quantity_error = 0;
        $num_row = 1;

        try {
            $upload_student_payment = UploadStudentPayment::create([
                'quantity' => $quantity,
                'user_created' => auth()->user()->id,
                'created_at' => Carbon::now()
    
            ]);

            $this->register_id = $upload_student_payment->id;
        } catch (\Throwable $th) {
            $this->errorMessage = 'Ha ocurrido un error, por favor vuelve a intentarlo más tarde';
            return;
        }

        //pre_die($upload_student_payment);

        
        foreach($invoice_number_matches as $detail) {

            $validation_errors = 0;
            $validation_messages = '';

            try {
                // Validar los rut
                $guardian_rut = strUpper(str_replace('.', '', formateaRut($detail['guardian_rut'])));
                $student_rut = strUpper(str_replace('.', '', formateaRut($detail['student_rut'])));

                // Rut apoderado
                if (isset($this->partners[$guardian_rut])) {
                    $odoo_parent_id = $this->partners[$guardian_rut];
                } else {
                    //registrar el error
                    $validation_errors++;
                    $validation_messages .= ($validation_errors + 1) . ': Rut de apoderado no encontrado. ';
                    $odoo_parent_id = null;
                }

                // Rut apoderado
                if (isset($this->partners[$student_rut])) {
                    $odoo_student_id = $this->partners[$student_rut];
                } else {
                    //registrar el error
                    $validation_errors++;
                    $validation_messages .= ($validation_errors + 1) . ': Rut de alumno no encontrado. ';
                    $odoo_student_id = null;
                }

                // Validar método de pago
                $assignment = ConceptJournal::where('concept', strUpper(trim($detail['payment_method'])))->first();

                if (!$assignment) {
                    $validation_messages .= ($validation_errors + 1) . ': Método de pago "' . $detail['payment_method'] . '" no encontrado.';
                    $validation_errors++;
                    $detail['payment_method'] = null;
                }

                //2.Formatear datos
                $detail['invoice_number'] = intval($detail['invoice_number']);
                $detail['payment_number'] = intval($detail['payment_number']);
                $detail['operation_number'] = intval($detail['operation_number']);
                $detail['guardian_rut'] = $guardian_rut;
                $detail['student_rut'] = $student_rut;
                $detail['payment_date'] = ordenar_fechaServidor($detail['payment_date']);
                $detail['emision_date'] = ordenar_fechaServidor($detail['emision_date']);
                $detail['payment_amount'] = floatval(str_replace(',', '.', $detail['payment_amount']));
                $detail['total_amount'] = floatval(str_replace(',', '.', $detail['total_amount']));
                $detail['upload_student_payment_id'] = $upload_student_payment->id;
                $detail['num_row'] = $num_row;
                $detail['odoo_parent_id'] = $odoo_parent_id;
                $detail['odoo_student_id'] = $odoo_student_id;

                //3.Guardar detalle
                if ($validation_errors == 0) {
                    UploadStudentPaymentDetail::create($detail);

                    $quantity_success++;
                } else {
                    $detail['load_status'] = 0;
                    $detail['error'] = $validation_messages;
                    UploadStudentPaymentDetail::create($detail);

                    $quantity_error++;
                }
                
                $num_row++;
            } catch (\Exception $e) {
                
                UploadStudentPaymentDetail::create([
                    'num_row' => $num_row,
                    'user_created' => auth()->user()->id,
                    'created_at' => Carbon::now(),
                    'load_status' => 0,
                    'upload_student_payment_id' => $upload_student_payment->id,
                    'detail_integration_status_id' => 1,
                    'error' => $e->getMessage()
                ]);

                $quantity_error++;
                $num_row++;
            }
        }

        $upload_student_payment->update([
            'quantity_success' => $quantity_success,
            'quantity_error' => $quantity_error,
        ]);

        $this->successMessage = 'Importación realizada correctamente. Registros exitosos: ' . $quantity_success . ', Errores: ' . $quantity_error;
    }

    private function validateHeaders($headers, $required_columns)
    {
        foreach ($required_columns as $column) {
            if (!in_array($column, $headers)) {
                return false;
            }
        }
        return true;
    }
}