HEX
Server: Apache/2.4.41 (Ubuntu)
System: Linux ip-172-31-42-149 5.15.0-1084-aws #91~20.04.1-Ubuntu SMP Fri May 2 07:00:04 UTC 2025 aarch64
User: ubuntu (1000)
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/vhost/disk-apps/qas.sports-crowd.com/app/Http/Controllers/Api/AcademyUserApiController.php
<?php

namespace App\Http\Controllers\Api;

use App\Module;
use App\Address;
use App\AcademyUser;
use App\AcademyState;
use App\AcademyDocument;
use App\AcademyDocumentUser;
use Illuminate\Http\Request;
use App\AcademyUsersDiscount;
use App\Models\AcademyReport;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use App\Http\Controllers\AcademyController;
use App\Http\Controllers\AcademyStateController;
use App\Http\Controllers\AcademyPurchaseController;
use App\Core\Academy\Application\AcademyUserService;
use App\Http\Controllers\AcademyParameterController;

class AcademyUserApiController extends Controller
{
    private $academyController;
    private $academyParameterController;
    private $academyUserService;
    private $academyPurchaseController;

    public function __construct()
    {
        $this->academyController = new AcademyController;
        $this->academyParameterController = new AcademyParameterController;
        $this->academyUserService = new AcademyUserService();
        $this->academyPurchaseController = new AcademyPurchaseController();
    }

    public function getAcademyUsersInfo($type_academy = 'children')
    {
        $academyUsers = AcademyUser::where('academy_users.user_id', Auth::user()->id)
            ->with('academy_state')
            ->with('student_document_type')
            ->with('academy_category')
            ->with('address')
            ->with('address.city')
            ->with('advisor_address')
            ->with('advisor_address.city')
            ->with('academy_location')
            ->withCount(['academy_purchases as pendingPayments' => function ($query) {
                $query
                    ->leftjoin('payment_transactions', 'payment_transactions.id', '=', 'academy_purchases.payment_transaction_id')
                    ->where('payment_transactions.state', '!=', 'CONFIRMED')
                    ->orWhereNull('payment_transactions.id');
            },])
            ->where('type_academy', $type_academy)
            ->get();

        foreach ($academyUsers as $user) {
            if ($user->academy_category) {
                $user->academy_location_id = $user->academy_category->academy_location_id;
            } else {
                $user->academy_location_id = null;
            }
        }

        $enableRegistrationRenewal = $this->academyParameterController->getParametersValueByTypeAcademy('enable_registration_renewal', $type_academy);
        foreach ($academyUsers as $academyUser) {
            $reports = AcademyReport::where('academy_user_id', $academyUser->id)->count();
            $academyUser->isReportValid = $reports > 0 ? true : false;
            $discounts = AcademyUsersDiscount::where('academy_user_id', $academyUser->id)->pluck('academy_discount_id');
            $academyUser->academy_discounts = $discounts;
            $isRenewable = false;
            if ($academyUser->academy_state->name == 'Matriculado' && $academyUser->pendingPayments == 0 && $enableRegistrationRenewal == 'true') {
                $validateEnrollmentTagYear = $this->academyPurchaseController->validateEnrollmentTagYear($academyUser->user_id, date('Y'));
                if (!$validateEnrollmentTagYear) {
                    $isRenewable = true;
                }
            }
            $academyUser->isRenewable = $isRenewable;
        }
        return response()->json($academyUsers, 200);
    }

    public function createUserAcademy(Request $request)
    {
        $validation = $this->validateCreateAcademyUser($request);
        if ($validation) {
            return $validation;
        }

        $user = AcademyUser::where('id', $request['id'])->first();
        $user_id = Auth::user()->id;

        if (!isset($request["track1"])) {
            $direction = $request["studentAddress"];
        } else {
            $direction = ($request['typeTrack'] . ' ' .
                $request['track1'] . ' # ' .
                $request['track2'] . ' - ' .
                $request['track3']
            );
        }

        if (!isset($request["advisorTrack1"])) {
            $directionAdvisor = $request["advisorAddress"];
        } else {
            $directionAdvisor = ($request['advisorTypeTrack'] . ' ' .
                $request['advisorTrack1'] . ' # ' .
                $request['advisorTrack2'] . ' - ' .
                $request['advisorTrack3']
            );
        }
        $addressData = [
            'direction' => $direction,
            'user_id' => $user_id,
            'active' => true,
            'tag' => 'academy_users'
        ];
        if (!isset($request["track1"])) {
            $addressData['lat'] = $request['studentLatitude'];
            $addressData['long'] = $request['studentLongitude'];
        }

        $address = null;

        if ($addressData['lat'] && $addressData['long'] && $addressData['direction']) {
            $address = Address::updateOrCreate(['user_id' => $user_id, 'tag' => 'academy_users'], $addressData);
        }

        $academy_user_data = [
            'user_id' =>  $user_id,
            'student_name' => $request['studentName'],
            'student_last_name' => $request['studentLastName'],
            'student_document_type_id' => $request['studentDocumentType'],
            'identification' => $request['studentDocument'],
            'school_name' => $request['school'],
            'school_grade' => $request['school_grade'],
            'birthdate' => $request['birthdate'],
            'mail' => $request['email'],
            'phone' => data_get($request, 'phone.nationalNumber', $request['phone'] ?? null),
            'address_id' => $address ? $address->id : null,
            'advisor_name' => $request['advisorName'],
            'advisor_last_name' => $request['advisorLastName'],
            'advisor_document_type_id' => $request['advisorDocumentType'],
            'advisor_identification' => $request['advisorDocument'],
            'advisor_ocupation' => $request['advisorOcupation'] ??  $request['ocupation'],
            'advisor_relation' => $request['relation'],
            'date' => $request['date'],
            'age' => date_diff(new \DateTime(), date_create($request['birthdate']))->y,
            'academy_schedule_id' => $request['academy_schedule_id'],
            'active' => 0,
            'ocupation' =>  $request['ocupation'],
            'type_academy' =>  $request['type_academy'] ?? 'children',
            //Campos de persona juridica
            'type_person' => $request['typePerson'],
            'advisor_nit' => $request['advisorNit'],
            'advisor_business_name' => $request['advisorBusinessName'],
            'advisor_property_name' => $request['advisorPropertyName'],
            'advisor_isic_code' => $request['advisorIsicCode'],
            'advisor_phone' => data_get($request, 'advisorPhone.nationalNumber', $request['advisorPhone'] ?? null),
            'advisor_dial_code' => $request['advisorPhone']['dialCode'] ?? null,
            'advisor_country_code' => $request['advisorPhone']['countryCode'] ?? null,
            'advisor_mail' => $request['advisorMail'],
            'advisor_cell_phone' => data_get($request, 'advisorCellPhone.nationalNumber', $request['advisorCellPhone'] ?? null),
            'dial_code' => $request['phone']['dialCode'] ?? null,
            'country_code' => $request['phone']['countryCode'] ?? null,
            'advisor_cell_dial_code' => $request['advisorCellPhone']['dialCode'] ?? null,
            'advisor_cell_country_code' => $request['advisorCellPhone']['countryCode'] ?? null,
        ];

        if ($request['typePerson'] != "NATURAL_PERSON") {
            $advisorAddressData = [
                'direction' => $directionAdvisor,
                'user_id' => $user_id,
                'active' => true,
                'tag' => 'advisor'
            ];
            if (!isset($request["advisorTrack1"])) {
                $advisorAddressData['lat'] = $request['advisorLatitude'];
                $advisorAddressData['long'] = $request['advisorLongitude'];
            }
            $address_advisor = Address::updateOrCreate(['user_id' => $user_id, 'tag' => 'advisor'], $advisorAddressData);
        }
        $academy_user_data['advisor_address_id'] = $address_advisor->id ?? NULL;
        $file = $request['photo'];

        // Verifica si la entrada es una URL
        if (filter_var($file, FILTER_VALIDATE_URL)) {
            // Es una URL, no necesitas procesarla, simplemente asigna la URL a la propiedad 'photo'
            $academy_user_data['photo'] = $file;
        } else {
            // Es un base64, procede con el procesamiento de la imagen
            if ($file) {
                $academy_user_data['photo'] = $this->savePhoto($file, $request['studentDocument']);
            }
        }

        $academy_user = AcademyUser::updateOrCreate(['id' => $request['id']], $academy_user_data);
        $this->academyUserService->generateCode($academy_user);
        $academyStateRenovation = AcademyState::where('name', 'Renovacion Inscripcion')->first();
        $academyStateRenovationId = $academyStateRenovation ? $academyStateRenovation->id : null;

        if (!$user || $user->academy_state_id == $academyStateRenovationId) {
            $academyState = new AcademyStateController();
            $academyState->assignStateAcademy($academy_user);
        }

        $module = Module::where('route', 'academy')->first();
        $this->registerLog(Auth::user()->id, 'Crear Alumno', json_encode($academy_user), "Create", $module->id);
        return array('r' => true, 'data' => $academy_user, 'm' => 'Alumno registrado exitosamente!');
    }

    private function savePhoto($file, $identifier)
    {
        $extension = explode('/', mime_content_type($file))[1];
        $filenametostore = 'foto_' . $identifier  . '.' . $extension;
        $directory = config('s3.academy') . '/academy_photos/';

        list($baseType, $file) = explode(';', $file);
        list(, $file) = explode(',', $file);
        $file = base64_decode($file);

        if (Storage::disk('s3')->exists($directory . $filenametostore)) {
            Storage::disk('s3')->delete($directory . $filenametostore);
        }

        Storage::disk('s3')->put($directory . $filenametostore, $file, 'public');
        return config('filesystems.disks.s3.url') . '/academy/academy_photos/' . $filenametostore;
    }

    public function completeUserAcademyData(Request $request)
    {
        // Certificado salud app
        if (isset($request['file'])) {
            $academyUserId = $request['id'];
            $academyDocumentId = AcademyDocument::where('name', 'Certificado de salud APP')->pluck('id')->first();
            $file = $request['file'];
            $extension = explode('/', mime_content_type($file))[1];
            $filenametostore = 'document' .  base64_encode(random_bytes(4))  . '.' . $extension;
            list($baseType, $file) = explode(';', $file);
            list(, $file) = explode(',', $file);
            $file = base64_decode($file);
            if (Storage::disk('s3')->exists(config('s3.academy_documents') . $filenametostore)) {
                Storage::disk('s3')->delete(config('s3.academy_documents') . $filenametostore);
            }

            Storage::disk('s3')->put(config('s3.academy_documents') . $filenametostore, fopen($request['file'], 'r+'), 'public');
            $url = config('filesystems.disks.s3.url') . '/academy/academy_documents/' . $filenametostore;
            $data = [
                'academy_user_id'       => $academyUserId,
                'academy_document_id'   => $academyDocumentId,
                'link'                  => $url,
            ];

            AcademyDocumentUser::updateOrCreate(
                ['academy_user_id' => $academyUserId, 'academy_document_id' => $academyDocumentId],
                $data
            );
        }
        $id = $request->input('id');
        $academyUserPrevious    = AcademyUser::find($id);
        $previousAcademyUser    = clone $academyUserPrevious;
        $previousAcademyUser    = json_encode($previousAcademyUser);

        $data = $request->except(['academy_discounts', 'hasHealthDocument', 'file']);
        $academyUser = AcademyUser::where('id', $id)->update($data);
        $this->academyController->validateAcademyLocation($id);

        AcademyUsersDiscount::where('academy_user_id', $id)->delete();
        if ($request->input('academy_discounts')) {
            $discount = new AcademyUsersDiscount();
            $discount->academy_discount_id = $request->input('academy_discounts');
            $discount->academy_user_id = $id;
            $discount->save();
        }

        $academyState = AcademyState::find($academyUserPrevious->academy_state_id);
        $uploadDocumentsButton = 'Botón cargar documentos';
        if (!str_contains($academyState->app_components, $uploadDocumentsButton)) {
            $academyStateController = new AcademyStateController;
            $academyStateController->assignStateAcademy($id);
        }

        $logObj = array(
            'previousAcademyUser'  => json_decode($previousAcademyUser, true),
            'newAcademyUser'       => $academyUser
        );
        $module = Module::where('route', 'academy')->first();
        $this->registerLog(Auth::user()->id, 'Completar Registro Alumno', json_encode($logObj), "Update", $module->id);
        return array('r' => true, 'data' => $academyUser, 'm' => 'Alumno actualizado exitosamente!');
    }

    public function uploadUserAcademyDocument(Request $request)
    {
        $extension = $request->file('document')->getClientOriginalExtension();
        $filenametostore = 'document' . Auth::user()->id . '_' . $request->input('documentId') . '.' . $extension;

        if (Storage::disk('s3')->exists(config('s3.academy_documents') . $filenametostore)) {
            Storage::disk('s3')->delete(config('s3.academy_documents') . $filenametostore);
        }

        Storage::disk('s3')->put(config('s3.academy_documents') . $filenametostore, fopen($request->file('document'), 'r+'), 'public');
        $url = config('filesystems.disks.s3.url') . '/academy/academy_documents/' . $filenametostore;

        $academyDocumentUser                        = new AcademyDocumentUser;
        $academyDocumentUser->academy_user_id       = $request->input('id');
        $academyDocumentUser->academy_document_id   = $request->input('documentId');
        $academyDocumentUser->link                  = $url;
        $academyDocumentUser->save();

        return array('r' => true, 'data' => $academyDocumentUser, 'm' => __('messages.academy_document.document_uploaded_successfully'));
    }

    public function updateAcademyUserPhoto(Request $request)
    {
        $photoPath = $this->savePhoto($request['photo'], $request['academy_user']['identification']);
        if ($photoPath) {
            AcademyUser::where('id', $request['academy_user']['id'])->update(['photo' =>  $photoPath]);
            return array('r' => true, 'data' => null, 'm' => 'Alumno actualizado exitosamente!');
        }
    }

    public function getReportsAcademyUsers($academyUserId)
    {
        $reports = AcademyReport::where('academy_user_id', $academyUserId)->orderBy('created_at', 'DESC')->get();
        return response()->json($reports, 200);
    }

    public function getAcademyUserById($id)
    {
        $academy_user = AcademyUser::where('id', $id)
            ->with('student_document_type')
            ->with('academy_category')
            ->with('address')
            ->with('academy_location')
            ->with('academy_schedule')
            ->with('advisor_address')
            ->with('advisor_address.city')
            ->first();
        return $academy_user;
    }

    public function getAcademyUsersByFilters(Request $request)
    {
        $query = AcademyUser::select(
            'academy_users.*',
            DB::raw('IFNULL(academy_users.advisor_ocupation, "") as advisor_ocupation'),
            DB::raw('IFNULL(academy_users.observations, "") as observations')
        )
            ->where('active', true)
            ->whereHas('academy_schedule.academy_categories_schedules')
            ->whereHas('academy_schedule.academy_categories_schedules.academy_category')
            ->with('student_document_type')
            ->with('academy_schedule')
            ->with('academy_schedule.academy_categories_schedules')
            ->with('academy_schedule.academy_categories_schedules.academy_category')
            ->with('user')
            ->with('academy_state')
            ->with(['academy_attendance' => function ($query) use ($request) {
                $query->whereDate('attendance_date', Carbon::parse($request['date']) ?? Carbon::now());
            }]);

        if ($request['id']) {
            $query->where('id', $request['id']);
        }

        if ($request['scheduleId']) {
            $query->where('academy_schedule_id', $request['scheduleId']);
        }

        // TEMPORAL, remover una vez se actualice el casteo del campo age en el APP
        $results = $query->orderBy('payment_status', 'DESC')->get();
        foreach ($results as $result) {
            $result->age = (string) $result->age;
        }

        return $results;
    }

    public function patchRenewalUser(Request $request)
    {
        if (empty($request->userId)) {
            return response()->json(['userId not provided'], 400);
        }
        $userId = $request->userId;
        $academyUser = AcademyUser::find($userId);
        if (!$academyUser) {
            return response()->json(['User not found'], 404);
        }
        $academyStateRenewal = AcademyState::where('name', 'like', 'Renovacion de matricula')->first();
        if (!$academyStateRenewal) {
            return response()->json(['Academy state not found'], 404);
        }

        $previousAcademyUser    = clone $academyUser;
        $previousAcademyUser    = json_encode($previousAcademyUser);

        $academyUser->academy_state_id      = $academyStateRenewal->id;
        // Limpiar datos de academia
        $academyUser->academy_place         = null;
        $academyUser->academy_location_id   = null;
        $academyUser->academy_category_id   = null;
        $academyUser->academy_schedule_id   = null;
        $academyUser->academy_period_id     = null;
        $academyUser->last_inscription_year = null;
        $academyUser->update();

        $logObj = array(
            'previousAcademyUser'  => json_decode($previousAcademyUser, true),
            'newAcademyUser'       => $academyUser
        );
        $module = Module::where('route', 'academy')->first();
        $this->registerLog(Auth::user()->id, 'Renovar Matricula Alumno', json_encode($logObj), "Update", $module->id);

        return response()->json($academyUser, 200);
    }

    public function validateGuardianInformation(Request $request)
    {
        if (!$request->academyUserId) {
            return array('r' => false, 'm' => __('messages.guardian_information.academy_user_id_not_provided'));
        }
        if (!AcademyUser::where('id', $request->academyUserId)->first()->guardian_information) {
            return array('r' => false, 'm' => __('messages.guardian_information.not_found'));
        }
        return array('r' => true, 'm' => __('messages.updated_successfully'));
    }

    public function updateGuardianInformation(Request $request)
    {
        try {
            $guardianInformation = json_encode($request->except(['academyUserId']));
            AcademyUser::where('id', $request->academyUserId)->update(['guardian_information' => $guardianInformation]);
            return array('r' => true, 'm' => __('messages.updated_successfully'));
        } catch (\Throwable $th) {
            return array('r' => false, 'm' => $th->getMessage());
        }
    }

    private function validateCreateAcademyUser(Request $request)
    {
        if (!$request['id']) {
            $previousUser = AcademyUser::where('identification', $request['studentDocument'])->first();
            if ($previousUser) {
                return array(
                    'r'     => false,
                    'data'  => $previousUser,
                    'm'     => trans('messages.academy_users.student_already_registered')
                );
            }
        }

        if (!$request['typePerson']) {
            return array(
                'r'     => false,
                'm'     => 'Debes completar la información de responsable'
            );
        } else if ($request['typePerson'] == 'NATURAL_PERSON') {
            if (!$request['advisorName']) {
                return array(
                    'r'     => false,
                    'm'     => 'Debes completar el/los nombres de la persona responsable'
                );
            }
            if (!$request['advisorLastName']) {
                return array(
                    'r'     => false,
                    'm'     => 'Debes completar el/los apellidos de la persona responsable'
                );
            }
            if (!$request['advisorDocumentType']) {
                return array(
                    'r'     => false,
                    'm'     => 'Debes completar el tipo de documento de la persona responsable'
                );
            }
            if (!$request['advisorDocument']) {
                return array(
                    'r'     => false,
                    'm'     => 'Debes completar el documento de la persona responsable'
                );
            }
            if ($request->has('advisorOcupation') && !$request['advisorOcupation']) {
                return array(
                    'r'     => false,
                    'm'     => 'Debes completar la ocupación de la persona responsable'
                );
            }
            if ($request->has('relation') && !$request['relation']) {
                return array(
                    'r'     => false,
                    'm'     => 'Debes completar la relación de la persona responsable'
                );
            }
        }
    }

    public function getAcademyUsersByCoach(Request $request)
    {
        $query = AcademyUser::select(
            'academy_users.*',
            DB::raw('IFNULL(GROUP_CONCAT(DISTINCT tags.name), "") AS segmentation'),
            'academy_states.name AS academy_state_name',
            'academy_states.color AS academy_state_color',
            DB::raw('IFNULL(MAX(academy_attendances.attended), 0) AS attended'),
            DB::raw('MAX(academy_attendances.comment) AS attendance_comment'),
            DB::raw('IFNULL(MAX(academy_attendances.attendance_date), "' . Carbon::parse($date ?? now())->toDateString() . '") AS attendance_date')
        )
            ->join('academy_schedules_coaches', 'academy_schedules_coaches.academy_schedule_id', '=', 'academy_users.academy_schedule_id')
            ->leftjoin('user_tags', 'user_tags.academy_user_id', '=', 'academy_users.id')
            ->leftjoin('tags', function ($join) {
                $join->on('tags.id', '=', 'user_tags.tag_id')->where('tags.active', 1);
            })
            ->join('academy_states', 'academy_states.id', '=', 'academy_users.academy_state_id')
            ->leftjoin('academy_attendances', function ($join) use ($request) {
                $join->on('academy_attendances.academy_user_id', '=', 'academy_users.id')
                    ->whereDate('academy_attendances.attendance_date', Carbon::parse($request['date']) ?? Carbon::now());
            })
            ->where('academy_users.active', true)
            ->where('academy_schedules_coaches.user_id', Auth::id())
            ->groupBy('academy_users.id') // Necesario si usas GROUP_CONCAT
            ->orderBy('academy_users.student_name')
            ->orderBy('academy_users.student_last_name');


        if ($request['scheduleId']) {
            $query->where('academy_users.academy_schedule_id', $request['scheduleId']);
        }

        return $query->get();
    }
}