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

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Events\ChatEvent;
use Carbon\Carbon;
use App\User;
use App\UserInformation;
use App\Address;
use App\Carnet;
use App\Mailbox;
use App\Parameter;
use App\Message;
use App\Chat;
use App\ChatMessage;
use App\Core\User\Application\UserService;
use App\Discount;
use App\DiscountOrderUser;
use App\DocumentType;
use App\PreSubscriber;
use App\Module;
use App\Tag;
use App\UserTag;
use App\Http\Controllers\TicketsController;
use App\Http\Controllers\UserController;
use Exception;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Storage;

/**
 * @OA\Info(
 *      version="1.0.0",
 *      title="Documentación SportsCrowd Api"
 * )
 */
class UserApiController extends Controller
{
    private $userService;
    const UNRESTRICTED_USERS = ['invitado@invitado.com', 'test@test.com'];

    public function __construct()
    {
        $this->userService = new UserService();
    }

    public function getAllDeliveries()
    {
        $couriers = User::where('rol_id', 3)
            ->where('id', '!=', Auth::user()->id)
            ->where('active', 1)->where('online', 1)->get();

        return array('r' => true, 'd' => $couriers);
    }

    public function closeDeliverySession(Request $request)
    {
        $obj = User::where('email', $request['email'])->first();
        if (!is_null($obj)) {
            $obj->last_session = null;
            $obj->online = 0;
            $obj->update();
        }
        return array('r' => true);
    }

    public function getClient($document)
    {
        $client = User::where('document', $document)->where('active', 1)->first();
        if (isset($client->id)) {
            $direction = Address::address($client->id)->first();
            $result = array('client' => $client->toArray(), 'address' => $direction);
            return array('r' => true, 'd' => $result);
        } else {
            return array('r' => false, 'd' => null);
        }
    }

    public function infoUser(Request $request)
    {
        $user = User::where("email", $request["email"])->with('userInfo', 'addresses', 'addresses.city', 'documentType')->first();
        $data = array('status' => 'success', 'user' => $user);
        return response()->json($data, 200);
    }

    public function updateUser(Request $request)
    {
        $userId = Auth::user()->id;
        $user                   = User::find($userId);
        $user->first_name       = $request["first_name"];
        $user->last_name        = $request["last_name"];
        $user->document         = $request["document"];
        $user->phone            = $request->input('phone.nationalNumber', $request->input('phone', null));
        $user->dial_code        = $request->input('phone.dialCode', null);
        $user->country_code     = $request->input('phone.countryCode', null);
        $user->email            = $request["email"];
        $user->document_type_id = $request["document_type"];
        $user->update();

        $userInfo      = UserInformation::where('user_id', $userId)->first();
        $userInfo->dob = $request["birthdate"];
        $userInfo->sex = $request["sex"];

        $message = __('messages.user_profile.updated');
        if (isset($request["code"]) && !empty($request["code"])) {
            $code = $request["code"];
            $tag = Tag::where('name', $code)->first();
            if ($tag) {
                UserTag::updateOrCreate(
                    ['tag_id' => $tag->id, 'user_id' => $userId],
                    ['tag_id' => $tag->id, 'user_id' => $userId]
                );
                $userInfo->referred_code = $code;
                $message .= ', código "' . $code . '" activado al usuario.';
            }
        }
        $userInfo->update();

        $this->updateOrCreateAddress($request, $userId);

        if ($user) {
            $clientModule = Module::where('route', 'clients')->first();
            $this->registerLog(Auth::user()->id, 'Actualizar datos APP', json_encode($request->all()), "Update", $clientModule->id);

            $userInfo = User::where("id", $userId)->with('userInfo', 'documentType', 'addresses', 'addresses.city')->first();
            $data = array('status' => 'success', 'user' => $userInfo, 'm' => $message);
            return response()->json($data, 200);
        } else {
            $message = 'Error al actualizar perfil, intente de nuevo.';
            $data = array('status' => 'error', 'user' => null, 'm' => $message);
            return response()->json($data, 200);
        }
    }

    public function savePlayerId(Request $request)
    {
        $id = Auth::user()->id;
        $user = User::find($id);
        $user->pns_id = $request['playerId'];
        $user->update();

        return array('r' => true);
    }

    public function mailbox(Request $request)
    {
        $user_id = Auth::user()->id;
        $mailbox = new Mailbox();
        $mailbox->request_type = $request["request_type"];
        $mailbox->business_unit_id = $request["business_unit_id"];
        $mailbox->message = $request["mailbox"];
        $mailbox->user_id = $user_id;
        $mailbox->save();

        $data = array('status' => 'success');
        return response()->json($data, 200);
    }

    public function getMessages()
    {
        $user_id = Auth::user()->id;
        $chat = Chat::where('user_id', $user_id)->first();
        $messages = array();

        if ($chat != null) {
            $messages = ChatMessage::where('chat_id', $chat->id)->with('messages')->get();
        }

        $data = array('status' => 'success', 'messages' => $messages);
        return response()->json($data, 200);
    }

    public function newMessage(Request $request)
    {
        $user_id = Auth::user()->id;
        $nameUser = Auth::user()->first_name . " " . Auth::user()->last_name;
        $chat = Chat::where('user_id', $user_id)->first();

        if ($chat != null) { // Existe conversación.
            $message = new Message();
            $message->message = $request["message"];
            $message->user_id = $user_id;
            $message->read_user = 1;
            $message->image = '';
            $message->save();

            $chat_message = new ChatMessage;
            $chat_message->chat_id = $chat->id;
            $chat_message->messages_id = $message->id;
            $chat_message->save();
        } else {
            $chat = new Chat;
            $chat->user_id = $user_id;
            $chat->save();

            $message = new Message();
            $message->message = $request["message"];
            $message->user_id = $user_id;
            $message->read_user = 1;
            $message->image = '';
            $message->save();

            $chat_message = new ChatMessage;
            $chat_message->chat_id = $chat->id;
            $chat_message->messages_id = $message->id;
            $chat_message->save();
        }
        $time = $chat_message->messages->time_elapsed_string($chat_message->messages->created_at);
        if ($message) {
            $response = array("message" => $message, "name" => $nameUser, "time" => $time);
            event(new ChatEvent($response, $user_id, 4));
            $data = array('status' => 'success', 'message' => $message);
            return response()->json($data, 200);
        }
    }

    public function getUserPermission()
    {
        $parameters = Parameter::first();
        if ($parameters->deliveryMan_create_order) {
            return array('r' => true, 'city' => $parameters->db_city);
        } else {
            return array('r' => false, 'city' => $parameters->db_city);
        }
    }

    public function updateDelivery(Request $request)
    {
        $id = Auth::user()->id;
        $user =  User::where('id', $id)->with('userInfo')->first();
        $user->first_name = $request['name'];
        $user->last_name = $request['lastname'];
        $user->document =  $request['document'];
        $user->phone = $request['phone'];
        $user->email = $request['email'];
        $user->update();
        return array('r' => true);
    }

    public function updateInfoPermission()
    {
        $parameters = Parameter::first();
        if ($parameters->deliveryMan_update_info) {
            return array('r' => true);
        } else {
            return array('r' => false);
        }
    }

    // Genera Pin aleatorio gane.
    public function generatepin()
    {
        $date = Carbon::now();
        $pin = $date->getTimestamp() . rand(10, 99);
        return $pin;
    }

    public function uploadImageProfile(Request $request)
    {
        try {
            $id = Auth::user()->id;
            $filename = $this->generatepin() . '.jpg';
            $user = UserInformation::select('id', 'user_id', 'photo_social', 'photo')->where('user_id', $id)->first();
            if ($user->photo) {
                Storage::disk('s3')->delete(config('s3.avatars') . $user->photo);
            }
            $user->photo_social = null;
            $user->photo = $filename;
            $user->update();

            list($baseType, $image) = explode(';', $request->file);
            list(, $image) = explode(',', $image);
            $image = base64_decode($image);

            // Subir archivo a AWS S3
            Storage::disk('s3')->put(config('s3.avatars') . $filename, $image, 'public');
            return array('status' => true, 'filename' => $filename);
        } catch (\Exception $exx) {
            return array('status' => false, 'error' => $exx->getMessage());
        }
    }

    public function itIsAuthorized(Request $request)
    {
        $id = Auth::user()->id;
        try {
            $data = array('status' => 'success');
            return response()->json($data, 200);
        } catch (Exception $e) {
            return $e;
        }
    }

    public function updateViewTutorial()
    {
        try {
            UserInformation::where('user_id', Auth::user()->id)->update(['is_tutorial_viewed' => true]);
            return response()->json(array('status' => true, 'm' => ''), 200);
        } catch (Exception $e) {
            return array('status' => false, 'error' => $e->getMessage());
        }
    }

    public function registerDiscountShipments(Request $request)
    {
        $user_id = Auth::user()->id;
        $discount = Discount::where([['active', true], ['discount_type_id', 1]])->first();
        if (isset($discount->id)) {

            $date = Carbon::now();
            $finalDate = $date->addDays($discount->days_register_discount_delivery);

            $discountOrderUser = new DiscountOrderUser();
            $discountOrderUser->user_id = $user_id;
            $discountOrderUser->discount_id = $discount->id;
            $discountOrderUser->limit_discount = $finalDate;
            $discountOrderUser->save();

            $data = array('status' => 'success');
            return response()->json($data, 200);
        } else {
            $data = array('status' => 'there_is_no_discount');
            return response()->json($data, 200);
        }
    }

    public function updateSucursalUser(Request $request)
    {
        $user_id = Auth::user()->id;
        $updateUser = UserInformation::where('user_id', $user_id)
            ->update(['current_sucursal_id' => $request["sucursal_id"]]);
        if ($updateUser) {
            $data = array('status' => 'success');
            return response()->json($data, 200);
        } else {
            $data = array('status' => 'error');
            return response()->json($data, 200);
        }
    }

    public function getDocumentTypes(Request $request)
    {
        $showIn = $request->showIn;
        if (!Cache::get('documentTypes-' . $showIn)) {
            $documentTypes = DocumentType::select('id', 'name', 'alias', 'pattern')
                ->where('active', 1)
                ->when($showIn, function ($query) use ($showIn) {
                    return $query->whereIn('show_in', [$showIn, 'all']);
                })
                ->get();
            $lang = $this->requestLanguage($request);
            if ($lang != 'es') {
                foreach ($documentTypes as $type) {
                    $type->name = $this->translate($type->name, 'es', $lang);
                }
            }
            Cache::put('documentTypes-' . $showIn, $documentTypes, config('cache.time'));
        } else {
            $documentTypes = Cache::get('documentTypes-' . $showIn);
        }
        $data = array('status' => 'success', 'documents_types' => $documentTypes);
        return response()->json($data, 200);
    }

    public function updateLastSession(Request $request)
    {
        try {
            return $this->userService->updateLastSession($request);
        } catch (Exception $th) {
            return array('r' => false, 'm' => $th->getMessage());
        }
    }

    public function deleteSystemUser(Request $request)
    {
        $user = $request->user();
        $userId = $request->userId;
        if (in_array($user->email, self::UNRESTRICTED_USERS)) {
            return array('r' => false, 'm' => 'No se puede eliminar este usuario porque es un usuario de pruebas.');
        } else if ($user->id != intval($userId)) {
            $userId = $user->id;
        }

        $controller = new UserController();
        $controller->deleteUser($userId);
        $this->registerLog(Auth::user()->id, 'Eliminó usuario desde APP', json_encode($user), "Delete", $this->getModule($request));
        $data = array('status' => 'success');
        return response()->json($data, 200);
    }

    public function cards($take, $offset, $show_in)
    {
        $userId = Auth::user()->id;
        $now = Carbon::now();
        $carnetsForUser = Carnet::select('carnets.*')
            ->where('carnets.active', true)
            ->whereIn('carnets.show_in', ['all', $show_in])
            ->leftjoin('carnet_tags', 'carnets.id', '=', 'carnet_tags.carnet_id')
            ->leftjoin('user_tags', 'user_tags.tag_id', '=', 'carnet_tags.tag_id')
            ->leftjoin('tags', function ($join) {
                $join->on('tags.id', '=', 'user_tags.tag_id')->where('tags.active', 1);
            })
            ->where(function ($query) use ($userId) {
                $query->where('user_tags.user_id', '=', $userId)->orWhereNull('user_tags.user_id');
            })
            ->where(function ($query) use ($now) {
                $query->whereNull('carnets.start_date')  // NO PROGRAMADOS
                    ->orWhere(function ($subQuery) use ($now) {    // PROGRAMADOS
                        $subQuery->where('carnets.start_date', '<=', $now)
                            ->where('carnets.end_date', '>=', $now);
                    });
            })
            ->take($take)->offset($offset)
            ->orderBy('created_at', 'desc')
            ->get();

        $carnetsForAll = Carnet::select('carnets.*')
            ->where('carnets.active', true)
            ->whereIn('carnets.show_in', ['all', $show_in])
            ->leftjoin('carnet_tags', 'carnets.id', '=', 'carnet_tags.carnet_id')
            ->whereNull('carnet_tags.id')
            ->where(function ($query) use ($now) {
                $query->whereNull('carnets.start_date')  // NO PROGRAMADOS
                    ->orWhere(function ($subQuery) use ($now) {    // PROGRAMADOS
                        $subQuery->where('carnets.start_date', '<=', $now)
                            ->where('carnets.end_date', '>=', $now);
                    });
            })
            ->take($take)->offset($offset)
            ->orderBy('created_at', 'desc')
            ->get();

        $carnets = $carnetsForAll->merge($carnetsForUser);
        $data = array();
        foreach ($carnets as $carnet) {
            $carnet->identification = $carnet->id;
            if ($carnet->optional && $carnet->optional == '{{seat}}') {
                $pre_subscribers = PreSubscriber::where('document', Auth::user()->document)
                    ->where(function ($query) {
                        $query->where('payment', true)
                            ->orWhere('is_credit', true);
                    })
                    ->with('seat')->get();
                $tickets = new TicketsController();
                if (count($pre_subscribers) > 0) {
                    foreach ($pre_subscribers as $key => $pre_subscriber) {
                        $optionalCard = clone $carnet;
                        $optionalCard->identification = $optionalCard->id . '_' . ($key + 1);
                        $optionalCard->optionalSeat = $pre_subscriber->seat->id;
                        $optionalCard->optional = $tickets->ticketSeatLocationFullText($pre_subscriber);
                        $data[] = $optionalCard;
                    }
                } else {
                    $carnet->optional = '';
                    $data[] = $carnet;
                }
            } else {
                $data[] = $carnet;
            }
        }
        return response()->json($data, 200);
    }

    public function getById($userId)
    {
        return User::select('id', 'first_name', 'last_name', 'document')->where('id', $userId)->with('userInfo')->first();
    }

    /**
     * Consultar si un usuario pertenece a una segmentación.
     * @return \Illuminate\Http\Response
     *
     * @OA\Get(
     *     path="/api/user/getBySegmentation/{segmentation}/{offset}/{take}/{document}",
     *     tags={"users"},
     *     summary="Consultar si un usuario pertence a una segmentación",
     *     @OA\Parameter(
     *          name="segmentation",
     *          in="path",
     *          description="Segmentación o etiqueta del usuario",
     *          required=true,
     *          @OA\Schema(
     *              type="string",
     *          )
     *      ),
     *      @OA\Parameter(
     *          name="offset",
     *          in="path",
     *          description="Index de inicio consulta. Ejemplo: 1000. Consulta a partir del registro 1000",
     *          required=true,
     *          @OA\Schema(
     *              type="integer",
     *          )
     *      ),
     *     @OA\Parameter(
     *          name="take",
     *          in="path",
     *          description="Cantidad de registros a obtener. Ejemplo: 250",
     *          required=true,
     *          @OA\Schema(
     *              type="integer",
     *          )
     *      ),
     *      @OA\Parameter(
     *         name="document",
     *         in="path",
     *         description="Documento del usuario",
     *         required=true,
     *          @OA\Schema(
     *              type="string",
     *          )
     *      ),
     *     @OA\Response(
     *        response="200",
     *        description="Successful response",
     *     )
     * ),
     */
    public function getBySegmentation($segmentation, $offset, $take, $document = null)
    {
        $query = User::select('users.id', 'first_name', 'last_name', 'document', 'document_type_id', 'phone', 'email')
            ->join('user_tags', 'user_tags.user_id', '=', 'users.id')
            ->leftjoin('tags', function ($join) {
                $join->on('tags.id', '=', 'user_tags.tag_id')->where('tags.active', 1);
            })
            ->where('tags.name', $segmentation);

        if ($document) {
            $query->where('document', $document);
        }
        $query->take($take)->offset($offset);

        return $query->get();
    }

    /**
     * Consultar listado de usuarios pertenecientes a una segmentación.
     * @return \Illuminate\Http\Response
     *
     * @OA\Get(
     *     path="/api/user/getBySegmentation/{segmentation}/{offset}/{take}",
     *     tags={"users"},
     *     summary="Consultar listado de usuarios pertenecientes a una segmentación.",
     *     @OA\Parameter(
     *         name="segmentation",
     *         in="path",
     *         description="Segmentación o etiqueta del usuario",
     *         required=true,
     *          @OA\Schema(
     *              type="string",
     *          )
     *      ),
     *      @OA\Parameter(
     *          name="offset",
     *          in="path",
     *          description="Index de inicio consulta. Ejemplo: 1000. Consulta a partir del registro 1000",
     *          required=true,
     *          @OA\Schema(
     *              type="integer",
     *          )
     *      ),
     *     @OA\Parameter(
     *          name="take",
     *          in="path",
     *          description="Cantidad de registros a obtener. Ejemplo: 250",
     *          required=true,
     *          @OA\Schema(
     *              type="integer",
     *          )
     *      ),
     *     @OA\Response(
     *        response="200",
     *        description="Successful response",
     *     )
     * ),
     */
    public function getBySegmentationSecondaryPath() {}

    public function setLastUsedAddress(Request $request, Address $address)
    {
        $user = $request->user();
        $this->userService->setLastUsedAddress($user, $address);
        return response()->json('', Response::HTTP_NO_CONTENT);
    }

    public function getMemberships()
    {
        $user = Auth::user();
        return response()->json(['data' => $user->memberships]);
    }

    public function updateOrCreateAddress(Request $request, $userId)
    {
        if (
            !$request->has('addressLat') ||
            !$request->has('addressLong') ||
            !$request->has('addressDirection')
        ) {
            return;
        }

        Address::where('user_id', $userId)->update(['last_used' => 0]);

        $addressData = [
            'lat' => $request->addressLat,
            'long' => $request->addressLong,
            'direction' => $request->addressDirection,
            'coverage_id' => $request->addressCoverageId,
            'user_id' => $userId,
            'active' => 1,
            'last_used' => 1,
        ];

        if ($request->filled('addressId')) {
            Address::where('id', $request->addressId)->update($addressData);
        } else {
            Address::create($addressData);
        }
    }

    public function checkAvailabilityByEmail(Request $request)
    {
        if (is_null($request->input('email'))) {
            return response()->json(null);
        }

        $email = $request->input('email');
        $user = User::select('id', 'first_name', 'last_name', 'document', 'phone', 'email')
            ->where(['email' => $email],['active' => true])
            ->first();

        if (is_null($user)) {
            return response()->json(null);
        }

        $obfuscatedUsers = [
                'id' => $user->id,
                'first_name' => $this->obfuscateValue((string) $user->first_name),
                'last_name' => $this->obfuscateValue((string) $user->last_name),
                'document' => $this->obfuscateValue((string) $user->document),
                'phone' => $this->obfuscateValue((string) $user->phone),
                'email' => $this->obfuscateEmail((string) $user->email),
            ];

        return response()->json($obfuscatedUsers);
    }

    protected function obfuscateValue(string $value): string
    {
        $length = strlen($value);

        if ($length <= 4) {
            return str_repeat('*', $length);
        }

        return str_repeat('*', $length - 4) . substr($value, -4);
    }

    protected function obfuscateEmail(string $email): string
    {
        if (!str_contains($email, '@')) {
            return $this->obfuscateValue($email);
        }

        [$localPart, $domain] = explode('@', $email, 2);

        $obfuscatedLocal = $this->obfuscateValue($localPart);

        return $obfuscatedLocal . '@' . $domain;
    }
}