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/comfama.sports-crowd.com/app/Services/ExperienceService.php
<?php

namespace App\Services;

use App\Models\Experience\Experience;
use App\Models\Experience\ExperiencePayment;
use App\Models\Experience\ExperiencePlanPrice;
use App\Models\Experience\ExperienceUser;
use App\Http\Controllers\PushNotificationController;
use App\Http\Controllers\ServiceChargeController;
use DateInterval;
use DateTime;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;

class ExperienceService
{

    private $academyService;

    public function __construct()
    {
        $this->academyService = new AcademyService;
    }

    public function get(Request $request)
    {
        $experiences = Experience::select(
            'experiences.id',
            'experiences.name',
            'experiences.icon',
            'experiences.short_description',
        )->where('experiences.active', 1)
            ->where('experiences.experience_type', $request->type)
            ->whereHas('plans')->orwhereHas('academy_plans')
            ->get();
        return $experiences;
    }

    public function detail(Request $request)
    {
        $query = Experience::select(
            'experiences.id',
            'experiences.name',
            'experiences.icon',
            'experiences.description',
            'experiences.apply_to',
            'experiences.includes',
            'experiences.when',
        )->with('plans', 'plans.prices');

        if ($this->validateAcademyStudents()) {
            $query->with('academy_plans', 'academy_plans.prices');
        }
        $experience = $query->findorFail($request->id);

        if ($experience && $experience->plans) {
            $uniquePlan = true;
            foreach ($experience->plans as $plan) {
                if ($plan->prices && $plan->prices->count() > 1) {
                    $uniquePlan = false;
                    break;
                }
            }
            $experience->unique_plan = $uniquePlan;
        }

        return $experience;
    }

    public function payments(Request $request)
    {
        DB::statement("SET sql_mode = ''");
        $payments = ExperiencePayment::select(
            'experience_payments.id',
            'experiences.name AS name',
            'experiences.icon AS icon',
            'experience_payments.description AS plan',
            DB::raw('IFNULL(payment_transactions.payment_date, "") AS payment_date'),
            'experience_payments.subtotal',
            'experience_payments.service_charge',
            'experience_payments.total',
            'experience_users.name AS student',
            'experience_users.document AS document',
            'experience_payments.payment_due_date',
            DB::raw('IF(experience_payments.payment_due_date IS NOT NULL, experience_payments.payment_due_date >= CURDATE(), true) AS active',),
            DB::raw('IF(payment_transactions.state = "CONFIRMED", true, false) AS confirmed'),
            DB::raw('true AS enable_pay'),
            DB::raw('true AS enable_renew'),
        )
            ->leftjoin('payment_transactions', 'payment_transactions.id', '=', 'experience_payments.payment_transaction_id')
            ->join('experience_users', 'experience_users.id', '=', 'experience_payments.experience_user_id')
            ->join('experience_plan_prices', 'experience_plan_prices.experience_plan_id', '=', 'experience_payments.experience_plan_price_id')
            ->join('experience_plans', 'experience_plans.id', '=', 'experience_plan_prices.experience_plan_id')
            ->join('experiences', 'experiences.id', '=', 'experience_plans.experience_id')
            ->where('experience_users.experience_type', $request->type)
            ->where('experience_users.user_id', Auth::user()->id)
            ->groupBy('experience_payments.id')
            ->orderBy('active', 'DESC')
            ->orderBy('experience_payments.id', 'DESC')
            ->get();
        DB::statement("SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'");
        return $payments;
    }

    public function enroll(Request $request)
    {
        $data = $this->getData($request);
        $validation = $this->validateData($data);
        $validation = json_decode(json_encode($validation), true);
        if ($validation && !$validation['original']['r']) {
            return $validation['original'];
        }
        $experienceUser = $this->createExperienceUser($data);
        $payment = $this->createPayment($data, $experienceUser);
        return response(array('r' => true, 'd' => $payment));
    }

    public function renew(Request $request)
    {
        $data = $this->getData($request);
        $experiencePaymentId = $data['experiencePaymentId'];
        $payment = $this->renewPayment($experiencePaymentId);
        return response(array('r' => true, 'd' => $payment));
    }

    public function students(Request $request)
    {
        $students = [];
        if ($request->planType == 'academy') {
            $students = $this->academyStudents();
        } else {
            $students = ExperienceUser::select(
                'experience_users.name',
                'document_types.alias AS document_type',
                'document',
            )->join('document_types', 'document_types.id', '=', 'experience_users.document_type_id')
                ->where('user_id', Auth::user()->id)
                ->where('experience_type', $request->type)
                ->orderBy('name', 'ASC')
                ->get();

            if (count($students)) {
                $students[] = [
                    'name'      => 'Nuevo',
                    'document'  => 0
                ];
            }
        }
        return $students;
    }

    public function guardians(Request $request)
    {
        $guardians = ExperienceUser::select(
            'guardian_name',
            'guardian_document',
            'guardian_email',
            'guardian_phone',
        )->where('user_id', Auth::user()->id)
            ->where('experience_type', $request->type)
            ->whereNotNull('guardian_document')
            ->groupBy([
                'guardian_name',
                'guardian_document',
                'guardian_email',
                'guardian_phone'
            ])
            ->orderBy('guardian_name', 'ASC')
            ->get();
        return $guardians;
    }

    public function finishPayment($paymentTransaction)
    {
        if ($paymentTransaction->state == 'CONFIRMED') {
            $experiencePayment = ExperiencePayment::with('experience_user', 'payment_transaction')->where('payment_transaction_id', $paymentTransaction->id)->first();
            $experienceUser = $experiencePayment->experience_user;
            $user = $experienceUser->user;
            $this->updatePaymentDueDate($experiencePayment);

            $message = 'Se confirma pago ' . $paymentTransaction->reference . ', asociado al Pago Experiencia ' . $experiencePayment->description . ' estudiante: ' . $experienceUser->name . ' (' . $experienceUser->document . ')';
            $push = new PushNotificationController();
            $push->sendToUser($message, $user->pns_id, null, null, null, null, 'U');

            // $this->syncERP($academyTournamentPayment);
        }
    }

    private function updatePaymentDueDate($experiencePayment)
    {
        $experiencePayment->payment_due_date = \Carbon\Carbon::now()->addDays($experiencePayment->experience_plan_price->duration)->toDateString();
        $experiencePayment->save();
    }

    private function validateData($data)
    {
        // Agregar validaciones de información y si ya existe el estudiante
        if (!isset($data['plan']) || ExperiencePlanPrice::find($data['plan']['id']) == null) {
            return response(array('r' => false, 'm' => 'No existe un plan de experiencia seleccionado/disponible'));
        }
        if ($data['document'] && ExperienceUser::where('document', $data['document'])->where('user_id', '!=', Auth::user()->id)->exists()) {
            return response(array('r' => false, 'm' => 'Ya existe un estudiante registrado con este documento'));
        }
        return response(array('r' => true));
    }

    private function getData($request)
    {
        return $request->all();
    }

    private function createExperienceUser($data)
    {
        if (ExperienceUser::where('document', $data['document'])->exists())
            return ExperienceUser::where('document', $data['document'])->first();
        else if (isset($data['planType']) && $data['planType'] == 'academy') {
            $data = $this->mapAcademyData($data);
        }

        $experienceUser                         = new ExperienceUser;
        $experienceUser->name                   = $data['name'];
        $experienceUser->birthdate              = $data['dob'];
        $experienceUser->document_type_id       = $data['document_type'];
        $experienceUser->document               = $data['document'];

        // Enviar almacenar el base64 de la imagen
        $experienceUser->identification_file    = $this->validateDataDocument($data['fileIdentificationDocument'], $data['document'] . '_identification_document');
        $experienceUser->insurance_file         = $this->validateDataDocument($data['fileInsuranceDocument'], $data['document'] . '_insurance_document');

        if ($this->isUnder18YearsOld($data['dob'])) {
            if (isset($data['guardianName']) && $data['guardianName'])
                $experienceUser->guardian_name  = $data['guardianName'];

            if (isset($data['guardianDocument']) && $data['guardianDocument'])
                $experienceUser->guardian_document  = $data['guardianDocument'];

            if (isset($data['guardianEmail']) && $data['guardianEmail'])
                $experienceUser->guardian_email = $data['guardianEmail'];

            if (isset($data['guardianPhone']) && $data['guardianPhone'])
                $experienceUser->guardian_phone = $data['guardianPhone'];
        }

        $experienceUser->user_id = Auth::user()->id;
        $experienceUser->save();
        return $experienceUser;
    }

    private function createPayment($data, $experienceUser)
    {
        if (ExperiencePayment::join('payment_transactions', 'experience_payments.payment_transaction_id', '=', 'payment_transactions.id')
            ->where([['experience_plan_price_id', $data['plan']['id']], ['experience_user_id', $experienceUser->id], ['payment_transactions.state', '!=', 'CONFIRMED']])
            ->exists()
        ) {
            return ExperiencePayment::select('experience_payments.*')->join('payment_transactions', 'experience_payments.payment_transaction_id', '=', 'payment_transactions.id')
                ->where([['experience_plan_price_id', $data['plan']['id']], ['experience_user_id', $experienceUser->id], ['payment_transactions.state', '!=', 'CONFIRMED']])->first();
        }

        $experiencePlanPrice = ExperiencePlanPrice::find($data['plan']['id']);
        $controller = new ServiceChargeController;
        $serviceCharge = 0;
        $serviceChargeEnabled = $controller->validateServiceCharge();
        if ($serviceChargeEnabled) {
            $request = new Request([
                'services'      => 'experience',
            ]);
            $serviceCharge = $controller->calculateServiceCharge($request);
        }
        $price = floatval($data['plan']['price']);

        $payment = ExperiencePayment::create(
            [
                'payment_identifier'        => intval(\Carbon\Carbon::now()->getPreciseTimestamp(3)),
                'description'               => $data['plan']['name'] . " (" . $experiencePlanPrice->description . ")",
                'price'                     => $price,
                'price_discount'            => 0,
                'discount'                  => 0,
                'subtotal'                  => $price,
                'service_charge'            => $serviceCharge,
                'total'                     => $price + $serviceCharge,
                'payment_due_date'          => \Carbon\Carbon::now()->addDays($experiencePlanPrice->duration)->toDateString(),
                'experience_plan_price_id'  => $experiencePlanPrice->id,
                'experience_user_id'        => $experienceUser->id,
                'sync_with_erp'             => false,
            ]
        );
        return $payment;
    }

    private function renewPayment($experiencePaymentId)
    {
        $experiencePayment = ExperiencePayment::find($experiencePaymentId);
        $data = $experiencePayment->toArray();

        $data['id']                         = null;
        $data['payment_identifier']         = intval(\Carbon\Carbon::now()->getPreciseTimestamp(3));
        $data['payment_due_date']           = null;
        $data['payment_transaction_id']     = null;
        $data['sync_with_erp']              = false;

        $newExperiencePayment = ExperiencePayment::create($data);
        return $newExperiencePayment;
    }

    private function isUnder18YearsOld($birthdate)
    {
        $birthdateFormat = new DateTime($birthdate);
        $now = new DateTime();
        $minimumDate = $now->sub(new DateInterval('P18Y'));
        return $birthdateFormat > $minimumDate;
    }

    private function validateDataDocument($fileBase64, $fileName)
    {
        if (!str_contains($fileBase64, 'data:image')) {
            return $fileBase64;
        }
        return $this->storeObjectToS3($fileBase64, $fileName);
    }

    private function storeObjectToS3($fileBase64, $fileName)
    {
        $streamResource = $this->storeBase64ResourceToStreamResource($fileBase64);
        $extension = $this->extensionFromBase64Resource($fileBase64);
        $filenameToStore = $fileName . '.' . $extension;

        Storage::disk('s3')->put(config('s3.default') . '/experience/' . $filenameToStore, $streamResource, 'public');
        $url = config('filesystems.disks.s3.url') . '/experience/' . $filenameToStore;

        return $url;
    }

    private function storeBase64ResourceToStreamResource($dataUrl)
    {
        $base64String = preg_replace('#^data:image/\w+;base64,#i', '', $dataUrl);
        $binaryData = base64_decode($base64String);
        $stream = fopen('php://memory', 'r+');
        fwrite($stream, $binaryData);
        rewind($stream);
        return $stream;
    }

    private function extensionFromBase64Resource($dataUrl)
    {
        preg_match('#^data:image/(\w+);base64,#i', $dataUrl, $matches);
        $extension = isset($matches[1]) ? $matches[1] : null;
        return $extension;
    }

    private function validateAcademyStudents()
    {
        return $this->academyService->validateAcademyStudents();
    }

    private function academyStudents()
    {
        return $this->academyService->academyStudents();
    }

    private function mapAcademyData($data)
    {
        return $this->academyService->mapAcademyData($data);
    }
}