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/Services/PostulationService.php
<?php

namespace App\Services;

use App\Repositories\PeriodRepository;
use App\Repositories\PostulationRepository;
use App\Repositories\StudentRepository;
use Exception;

class PostulationService
{
    protected $postulationRepository;

    public function __construct(PostulationRepository $postulationRepository)
    {
        $this->postulationRepository = $postulationRepository;
    }

    public function list($periodId = null, $userCreated = null, $limit = null)
    {
        $registers = $this->postulationRepository->getAll($periodId, $userCreated, $limit);
        if ($registers->count() < 1) return [];

        return $registers->map(fn($r) => $this->mapperData($r, true));
    }

    public function listByRut($rut)
    {
        $registers = $this->postulationRepository->getByRut($rut, true);
        if ($registers->count() < 1) return [];

        return $registers->map(fn($r) => $this->mapperData($r, true));
    }

    public function store($request)
    {
        $this->validatePeriod();

        $studentRut = formatterRut($request->student_rut, false);

        if ($this->postulationRepository->getByRut($studentRut, false)) {
            throw new Exception("Ya existe una postulación asociada al RUT del estudiante.", 409);
        }

        $studentRepository = new StudentRepository();
        if ($studentRepository->getByRut($studentRut)) {
            throw new Exception("El RUT del alumno ya corresponde a un estudiante del colegio.", 409);
        }

        $register = $this->postulationRepository->create((object)$request);
        if (!$register) {
            throw new Exception("Ha ocurrido un error al crear la postulación.", 500);
        }

        return null;
    }

    public function update($request, $id)
    {
        $this->validatePeriod();

        $register = $this->show($id, true, true);

        $studentRut = formatterRut($request->student_rut, false);
        if ($this->postulationRepository->getByRut($studentRut, false, $id)) {
            throw new Exception("Ya existe una postulación asociada al RUT del estudiante.", 409);
        }

        $studentRepository = new StudentRepository();
        if ($studentRepository->getByRut($studentRut)) {
            throw new Exception("El RUT del alumno ya corresponde a un estudiante del colegio.", 409);
        }

        $update = $this->postulationRepository->update($register, $request);
        if (!$update) {
            throw new Exception("Ha ocurrido un error al actualizar la postulación.", 500);
        }

        return true;
    }

    public function show($id, $allData = true, $editMode = false)
    {
        $register = $this->postulationRepository->getById($id);
        if (!$register) throw new Exception("Postulación no existe o fue eliminada", 404);

        if ($editMode) return $register;
        return (object) $this->mapperData($register, $allData);
    }

    public function delete($id)
    {
        $register = $this->show($id, true, true);
        $register->deleted = true;
        $register->deleted_at = now();
        $register->user_deleted = auth()->id();

        if (!$register->save()) {
            throw new Exception("Ha ocurrido un error al eliminar la postulación.", 500);
        }

        return true;
    }

    // ----------------- PRIVATE ----------------- //

    private function mapperData($data, $allData = true)
    {
        $studentFullName = trim("{$data->student_first_name} {$data->student_second_name} {$data->student_last_name} {$data->student_second_last_name}");
        $parentFullName  = trim("{$data->parent_first_name} {$data->parent_second_name} {$data->parent_last_name} {$data->parent_second_last_name}");

        $mapped = [
            'id' => $data->id,
            'code_postulation' => $data->code_postulation,
            'period'            => !empty($data->period) ? [
                'period_year' => $data->period->period_year,
                'description' => $data->period->period,
            ] :  null,
            'status_postulation'   => [
                'description' => $data->statusPostulation->description,
                'code'        => $data->statusPostulation->code,
                'background'  => $data->statusPostulation->background,
            ],
            // === Estudiante extendido ===
            'student' => [
                'first_name'       => $data->student_first_name,
                'second_name'      => $data->student_second_name ?? '',
                'last_name'        => $data->student_last_name,
                'second_last_name' => $data->student_second_last_name ?? '',
                'full_name'        => $studentFullName,
                'rut'              => $data->student_rut,
                'email'            => $data->student_email,
                'mobile'           => $data->student_mobile,
                'address'          => $data->student_address,

                // === Relaciones extendidas del estudiante ===
                'gender' => $data->student_gender_id > 0 ? [
                    'id'   => $data->studentGender->id,
                    'name' => $data->studentGender->gender,
                ] : null,

                'country' => $data->student_country_id > 0 ? [
                    'id'   => $data->studentCountry->id,
                    'name' => $data->studentCountry->country,
                ] : null,

                'region' => $data->student_region_id > 0 ? [
                    'id'        => $data->studentRegion->id,
                    'region'    => $data->studentRegion->region,
                    'long_name' => $data->studentRegion->long_name ?? null,
                ] : null,

                'commune' => $data->student_commune_id > 0 ? [
                    'id'      => $data->studentCommune->id,
                    'commune' => $data->studentCommune->commune,
                ] : null,
            ],

            // === Curso ===
            'course' => $data->course_id > 0 ? [
                'id'   => $data->course->id,
                'name' => $data->course->course,
            ] : null,

            // === Apoderado extendido ===
            'parent' => [
                'first_name'       => $data->parent_first_name,
                'second_name'      => $data->parent_second_name ?? '',
                'last_name'        => $data->parent_last_name,
                'second_last_name' => $data->parent_second_last_name ?? '',
                'full_name'        => $parentFullName,
                'email'            => $data->parent_email,
                'mobile'           => $data->parent_mobile,
                'profession'       => $data->parent_profession,
                'address'          => $data->parent_address,

                'relationship' => $data->parent_relationship_id > 0 ? [
                    'id'   => $data->parentRelationship->id,
                    'name' => $data->parentRelationship->relationship,
                ] : null,

                'gender' => $data->parent_gender_id > 0 ? [
                    'id'   => $data->parentGender->id,
                    'name' => $data->parentGender->gender,
                ] : null,

                'country' => $data->parent_country_id > 0 ? [
                    'id'   => $data->parentCountry->id,
                    'name' => $data->parentCountry->country,
                ] : null,

                'region' => $data->parent_region_id > 0 ? [
                    'id'        => $data->parentRegion->id,
                    'region'    => $data->parentRegion->region,
                    'long_name' => $data->parentRegion->long_name ?? null,
                ] : null,

                'commune' => $data->parent_commune_id > 0 ? [
                    'id'      => $data->parentCommune->id,
                    'commune' => $data->parentCommune->commune,
                ] : null,
            ],

            // === Información académica / adicional ===
            'previous_school' => $data->previous_school,
            'special_needs'   => $data->special_needs,
            'siblings'        => $data->siblings,
            'date_entry'      => $data->date_entry,
        ];

        if ($allData) {
            $mapped['created_at']   = sort_datetimeHuman($data->created_at);
            $mapped['updated_at']   = sort_datetimeHuman($data->updated_at);
            $mapped['user_created'] = $data->createdBy->username ?? null;
            $mapped['user_updated'] = $data->updatedBy->username ?? null;
        }

        return $mapped;
    }
    private function validatePeriod()
    {
        $periodRepository = new PeriodRepository();
        $periodActive = $periodRepository->getActive();

        if (empty($periodActive)) {
            throw new Exception("Actualmente no hay períodos de matrícula disponibles para realizar una postulación.");
        }

        if ($periodActive->finished) {
            throw new Exception("La postulación no puede ser editada porque el período de matrícula ya finalizó.");
        }

        return true;
    }
}