File: /var/www/vhost/disk-apps/demo.sports-crowd.com/app/Http/Controllers/Api/TicketApiController.php
<?php
namespace App\Http\Controllers\Api;
use App\Core\Ticket\TicketStatusEnum;
use App\Core\Ticket\TicketTypesEnum;
use App\GatewayPayment;
use App\Parameter;
use App\PaymentCoin;
use App\Team;
use App\Ticket;
use App\TicketMain;
use App\TicketUserBlock;
use App\TicketUserBlockBackup;
use App\TokenUserTicket;
use App\Zone;
use App\Http\Controllers\CollectionInvoiceController;
use App\Http\Controllers\Controller;
use App\Http\Controllers\FlashTicketController;
use App\Http\Controllers\MatchEventsController;
use App\Http\Controllers\PrintTicketController;
use App\Http\Controllers\TicketsController;
use App\Http\Controllers\UserController;
use App\Http\Controllers\UtilController;
use App\Http\Controllers\WompiController;
use App\Services\TicketsService;
use App\Services\TicketParametersService;
use App\TicketUserLog;
use App\User;
use Carbon\Carbon;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Crypt;
class TicketApiController extends Controller
{
public $url_ws;
private $private_key;
public $gateway_data;
private $ticketsService;
private $ticketParametersService;
public function __construct()
{
$this->ticketsService = new TicketsService;
$this->ticketParametersService = new TicketParametersService;
}
public function matchEvents(Request $request)
{
$tickets = new TicketsController();
$data = $tickets->getMatchEvents($request);
return response()->json($data, 200);
}
public function getSeatPrice($zone_id, $event_id)
{
$tickets = new TicketsController();
$data = $tickets->getSeatPrice($zone_id, $event_id);
return response()->json($data, 200);
}
public function getSubZones($zone_id)
{
try {
$zones = Zone::where('zone_id', $zone_id)->where('active', 1)->get();
return response(array("r" => true, "type" => "success", "title" => "", "m" => "", "data" => $zones));
} catch (\Throwable $th) {
return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "getZones", "m" => __('messages.error_creating'), "data" => $th->getMessage()));
}
}
public function getSeats($sub_zone_id, $event_id)
{
$tickets = new TicketsController();
$data = $tickets->getSeats($sub_zone_id, $event_id);
return response()->json($data, 200);
}
public function validateSell(Request $request)
{
$tickets = new TicketsController();
$data = $tickets->validateSell($request->zone_id, $request->event_id, $request->seat_id, Auth::user()->id, $request->ticket_type_id, null, $request->type_process, 0, true);
return response()->json($data, 200);
}
public function getMatchEventsSuscription(Request $request)
{
$tickets = new TicketsController();
return $tickets->getMatchEventsSuscription($request);
}
public function isPreabonado($document)
{
$tickets = new TicketsController();
return $tickets->isPreabonado($document);
}
public function createBlocks(Request $request, $user_id_abono = null, $show_in = 'app')
{
DB::beginTransaction();
try {
$user_id = $user_id_abono ?? Auth::user()->id;
$tickets = new TicketsController();
$parameters = Parameter::select('maximum_number_ballots', 'maximum_number_suscription')->first();
// se valida la capacidad de la localidad no este superada
if (!$tickets->salableCapacityZone($request->input('tickets')[0]["seat"]["zone_id"], $request->input('tickets')[0]["match_event_id"], count($request->input('tickets')), $user_id)) {
DB::rollback();
return $tickets->responseCapacityZone;
}
$sumTicketsBlocks = $tickets->getSumBlocksAndTicketsByUser($request->input('ticket_type_id'), $user_id, $request->input('tickets')[0]["match_event_id"]) + count($request->input('tickets'));
$flashController = new FlashTicketController;
$matchEventsController = new MatchEventsController;
$maximum = !$matchEventsController->validateSaleByCapacity($request->input('tickets')[0]["match_event_id"]) ? $parameters->maximum_number_ballots : $flashController->getMaximumTicketsToBuy($request->input('tickets')[0]["match_event_id"], $show_in);
// Valida el numero maximo de boletas que puede comprar el usuario.
if ($request->input('ticket_type_id') == TicketTypesEnum::FREE_SALE && $sumTicketsBlocks > $maximum) {
DB::rollback();
$available = $maximum - ($sumTicketsBlocks - count($request->input('tickets')));
if ($available < 0) $available = 0;
return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "createBlocks", "m" => __('messages.error_validation_5', ['number' => $available]), "data" => null));
}
// Valida el numero máximo de abonos.
if ($request->input('ticket_type_id') == TicketTypesEnum::SUBSCRIBER && $sumTicketsBlocks > $parameters->maximum_number_suscription) {
DB::rollback();
$available = $parameters->maximum_number_suscription - ($sumTicketsBlocks - count($request->input('tickets')));
if ($available < 0) $available = 0;
return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "createBlocks", "m" => __('messages.error_validation_6', ['number' => $available]), "data" => null));
}
$payment_coins = null;
if ($request->input('payWithCoins')) {
$payment = PaymentCoin::create([
'pay_with_coins' => $request->input('payWithCoins'),
'coins_in_money' => $request->input('coinsInMoney'),
'coins_used' => $request->input('coinsUsed'),
'current_value_point' => $request->input('currentValuePoint'),
]);
if ($payment) {
$payment_coins = $payment->id;
}
}
$subtotal = $request->input('subtotal') ?? 0;
$serviceCharge = $request->input('serviceCharge') ?? 0;
$total = $request->input('amount') ?? $request->input('total') ?? 0;
if ($subtotal == 0 && $total != 0) {
$subtotal = $total - $serviceCharge;
}
$main = TicketMain::create([
'payment_reference' => "PENDING",
'payment_state' => "PENDING",
'subtotal' => $subtotal,
'service_charge' => $serviceCharge,
'total' => $total,
'pin' => $this->gen_uid(),
'user_id_log' => $user_id,
'payment_coins_id' => $payment_coins,
'origin' => $show_in,
]);
$log_tickets_main = "";
if ($request->input('ticket_type_id') != TicketTypesEnum::SUBSCRIBER) {
foreach ($request->input('tickets') as $ticket) {
$zone_id = $ticket["seat"]["zone_id"];
$event_id = $ticket["match_event_id"];
$seat_id = $ticket["seat"]["id"];
$log_tickets_main = $log_tickets_main . "zone: " . $zone_id . "event: " . $event_id . "seat: " . $seat_id . "\n";
// creamos los bloqueos
$data = $tickets->validateSell($zone_id, $event_id, $seat_id, $user_id, $ticket["ticket_type_id"], $main->id, $request->input('type_process'), $ticket['price'] ?? 0);
$response = json_decode($data->getContent());
if (!$response->r) {
DB::rollback();
return $data;
break;
}
}
} else {
$log_tickets_main = 'Abonado, user_id: ' . $user_id;
$listEvents = $tickets->getEventsSubscription($request->input('season_id'), $request->input('match_event_id'));
$ticketSeats = [];
$ticketPrices = [];
$ticketUsers = [];
if ($listEvents && count($listEvents) > 0) {
foreach ($request->input('tickets') as $ticket) {
$userBlockingTickets = $user_id;
$zone_id = $ticket["seat"]["zone_id"];
$seat_id = $ticket["seat"]["id"];
$seasonTicketPrice = ROUND(($ticket["price"] ?? 0) / count($listEvents), 2);
$ticketSeats[] = $seat_id;
$ticketPrices[] = $seasonTicketPrice;
foreach ($listEvents as $key => $event) {
$event_id = $event->id;
if (isset($ticket["dataTicket"]) && !$ticket["dataTicket"]["checkedCtrl"] && !$user_id_abono) {
$userController = new UserController($request);
$user = $userController->searchUser($ticket["dataTicket"]["document"], $ticket["dataTicket"]["email"], $ticket["dataTicket"]["first_name"], $ticket["dataTicket"]["last_name"], $ticket["dataTicket"]["phone"], true);
if (!$user) {
$custom_request = new Request([
'first_name' => $ticket["dataTicket"]["first_name"],
'last_name' => $ticket["dataTicket"]["last_name"],
'phone' => $ticket["dataTicket"]["phone"],
'email' => $ticket["dataTicket"]["email"],
'password' => $ticket["dataTicket"]["phone"] + $ticket["dataTicket"]["document"],
'document' => $ticket["dataTicket"]["document"],
]);
$current_user = $userController->createClient($custom_request, true);
if ($current_user["r"]) {
$user = $current_user["d"];
$userBlockingTickets = $user->id;
} else {
DB::rollback();
return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "validateUserByTicket", "m" => __('messages.error_global'), "data" => $current_user));
break;
}
} else {
$userBlockingTickets = $user->id;
}
$ticket["dataTicket"]["checkedCtrl"] = true;
}
// creamos los bloqueos
$data = $tickets->validateSell($zone_id, $event_id, $seat_id, $userBlockingTickets, $ticket["ticket_type_id"], $main->id, $request->input('type_process'), $seasonTicketPrice);
$response = json_decode($data->getContent());
if (!$response->r) {
DB::rollback();
return $data;
break;
}
}
$ticketUsers[] = $userBlockingTickets;
}
$log_tickets_main .= (', ticketSeats: ' . json_encode($ticketSeats));
$log_tickets_main .= (', ticketPrices: ' . json_encode($ticketPrices));
$log_tickets_main .= (', ticketUsers: ' . json_encode($ticketUsers));
}
}
$ticketPrice = TicketUserBlock::select(DB::raw('SUM(price) AS price'))->where('ticket_main_id', $main->id)->first()->price;
if ($request->input('ticket_type_id') == TicketTypesEnum::FREE_SALE && $subtotal != $ticketPrice) {
$main->subtotal = $ticketPrice;
$main->total = $main->service_charge + $main->subtotal;
}
$main->comment_purchase_log = $log_tickets_main;
$main->update();
DB::commit();
if ($show_in == 'web') {
return response(array("r" => true, "type" => "", "title" => "ok", "m" => $response->m, "data" => Crypt::encrypt($main->id)));
} else {
return response(array("r" => true, "type" => "", "title" => "ok", "m" => $response->m, "data" => $main->id));
}
} catch (\Throwable $th) {
DB::rollback();
return response(array("r" => false, "type" => "error", "title" => "Oops...", "m" => __('messages.error_global'), "data" => $th->getMessage()));
}
}
public function updateStatusOrderFromReference($id)
{
$o = TicketMain::where('id', $id)
->with(['ticket_user_blocks' => function ($q) {
$q->where('ticket_user_blocks.is_social_distancing', false);
}])
->first();
$client = new \GuzzleHttp\Client();
$response = $client->get($this->url_ws . "/transactions?reference=" . $o->payment_reference, [
'headers' => ['Authorization' => 'Bearer ' . $this->private_key]
]);
$body = $response->getBody()->getContents();
$body = json_decode($body);
if ($body->data && count($body->data)) {
$ticket = end($body->data);
$isApproved = collect($body->data)->where('status', "APPROVED")->first();
if ($isApproved) {
$ticket = $isApproved;
}
if ($ticket->status == "APPROVED") {
$paymentState = true;
if (!$o->ticket_user_blocks->isEmpty()) {
$tickets = new TicketsController();
$paymentState = $tickets->generateTickets($o->ticket_user_blocks, $o->id);
}
if ($paymentState) {
$o->payment_state = "CONFIRMED";
$o->payment_comment = $ticket->status;
$o->update();
}
}
}
}
public function inactiveBlockBackups($ticket_user_block_backups)
{
foreach ($ticket_user_block_backups as $block) {
$current_block = TicketUserBlockBackup::where('id', $block->id)->with('match_event')->first();
if ($current_block->match_event->event_start < Carbon::now()->format('Y-m-d H:i:s')) {
$current_block->active = false;
$current_block->update();
}
}
}
public function determinateWebService()
{
$parameters = Parameter::first();
$is_production = $parameters->is_production_gateway; // TRUE: Production ; FALSE: Test
$this->gateway_data = GatewayPayment::where("name", "wompiTicketOffice")
->where("is_productive", $is_production)
->first();
$this->private_key = $this->gateway_data->client_secret;
if ($is_production) { // Si se encuentra en producción el gateway.
$this->url_ws = $this->gateway_data->gw_url_prd;
} else {
$this->url_ws = $this->gateway_data->gw_url_sandbox;
}
}
function purchase(Request $request)
{
$wompiController = new WompiController;
$this->determinateWebService();
$id = $request->input("id");
// Verifico sin consultar a Wompi.
$ticket = TicketMain::where('id', $id)->first();
if ($ticket->payment_state == 'CONFIRMED') {
return view("wompi.webcheckout-done");
}
// Consulto a Wompi el estado
$this->updateStatusOrderFromReference($id);
$ticket = TicketMain::where('id', $id)->first();
if ($ticket->payment_state == 'CONFIRMED') {
return view("wompi.webcheckout-done");
}
// actualizamos ticket con la referencia de pago
$ticket->payment_reference = strtoupper(hash("md5", $ticket->id)) . '_' . $ticket->pin;
$ticket->payment_state = "PENDING";
$ticket->update();
$amountInCents = $ticket->total * 100;
$expirationTime = $wompiController->expirationTime(25);
$signature = $wompiController->generateSignature($ticket->payment_reference, $amountInCents, $this->gateway_data->currency, $this->gateway_data->client_signature, $expirationTime);
return view("wompi.webcheckout")
->with('gateway_data', $this->gateway_data)
->with('amountInCents', $amountInCents)
->with('reference', $ticket->payment_reference)
->with('confirm_url', config('app.url') . '/store/wompi/confirm_ticket')
->with('signature', $signature)
->with('expirationTime', $expirationTime);
}
public function get_tickets($take, $offset)
{
try {
$data = Ticket::select('tickets.*', 'ticket_mains.invoice_link', 'ticket_mains.cufe')->with('match_event', 'seat')
->join('ticket_mains', 'tickets.ticket_main_id', '=', 'ticket_mains.id')
->join('match_events', 'tickets.match_event_id', '=', 'match_events.id')
->join('seasons', 'match_events.season_id', '=', 'seasons.id')
->join('tournaments', 'seasons.tournament_id', '=', 'tournaments.id')
->where('tickets.user_id', Auth::user()->id)
->whereIn('tickets.ticket_status_id', [TicketStatusEnum::PURCHASED, TicketStatusEnum::CREATED])
->whereHas('match_event', function (Builder $query) {
$query->where('event_start', '>', Carbon::now()->startOfDay());
})
->groupBy('tickets.id')
->orderBy('tickets.match_event_id', 'ASC')
->orderBy('tickets.created_at', 'DESC')
->take($take)
->skip($offset)
->get();
return response()->json($data, 200);
} catch (\Throwable $th) {
return response(array("r" => false, "type" => "error", "title" => "Oops...", "m" => __('messages.error_global'), "data" => $th->getMessage()));
}
}
public function team_main()
{
if (!Cache::get('team-main')) {
$data = Team::select('id', 'name', 'display_name', 'abbreviation', 'logo')->where([['is_main', true], ['active', true]])->first();
Cache::put('team-main', $data, config('cache.time'));
} else {
$data = Cache::get('team-main');
}
return response()->json($data, 200);
}
public function generateTokenTicket(Request $request)
{
try {
if ($request->platform == "android") {
$token = str_random(30);
$print = new PrintTicketController();
$print->printTicket($request->code, Auth::user()->id, $token);
return response(array("r" => true, "type" => "", "title" => "ok", "m" => "", "data" => $token));
} else {
$token = TokenUserTicket::create(['user_id' => Auth::user()->id, 'token' => str_random(30), 'code' => $request->code]);
return response(array("r" => true, "type" => "", "title" => "ok", "m" => "", "data" => $token->token));
}
} catch (\Throwable $th) {
return response(array("r" => false, "type" => "error", "title" => "Oops...", "m" => __('messages.error_global'), "data" => $th->getMessage()));
}
}
public function updatePendingStatusTicket($ticket, $short_order_id = false, $add_time = false)
{
$add_time_text = $add_time ? '_' . microtime(true) : '';
$ticket->payment_reference = strtoupper(hash("md5", $ticket->id)) . '_' . $ticket->pin . $add_time_text;
if ($short_order_id) {
$ticket->payment_reference = $ticket->pin;
}
$ticket->payment_state = 'PENDING';
$ticket->update();
}
public function updateTicketMainByPaymentReference(
$paymentReference,
$paymentState,
$paymentComment,
$paymentTransactionId
) {
$ticketMain = TicketMain::when($paymentReference, function ($query) use ($paymentReference) {
return $query->where('payment_reference', $paymentReference);
})
->when($paymentTransactionId, function ($query) use ($paymentTransactionId) {
return $query->orWhere('payment_transaction_id', $paymentTransactionId);
})
->first();
if ($ticketMain == null || $ticketMain->payment_state == $paymentState) {
return false;
}
$ticketMain->payment_state = $paymentState;
$ticketMain->payment_comment .= ($ticketMain->payment_comment ? ', ' : '') . $paymentComment;
$ticketMain->payment_transaction_id = $paymentTransactionId;
$ticketMain->payment_reference = $paymentReference;
$ticketMain->update();
if ($paymentState == 'CONFIRMED') {
$controller = new TicketsController();
if (!$ticketMain->tickets->isEmpty()) {
Ticket::where('ticket_main_id', $ticketMain->id)->update(['ticket_status_id' => TicketStatusEnum::PURCHASED]); // ESTADO TIQUETES CONFIRMADOS COMPRA
}
if (!$ticketMain->ticket_user_blocks->isEmpty()) {
$controller->generateTickets($ticketMain->ticket_user_blocks, $ticketMain->id);
} else if (!$ticketMain->ticket_user_block_backups->isEmpty()) {
$controller->generateTickets($ticketMain->ticket_user_block_backups, $ticketMain->id, true);
}
try {
$invoice = new CollectionInvoiceController();
$invoice->validateCreditCollectionInvoice($ticketMain->gateway_payments_id, $paymentReference, $paymentTransactionId, 'ticket', $ticketMain->total);
/*
$pay = new LealPayController();
$pay->validateUserPointsAccumulation($ticketMain);
*/
} catch (\Throwable $th) {
$data = [
'ticket' => $ticketMain,
'message' => $th->getMessage(),
'getFile' => $th->getFile(),
'getLine' => $th->getLine(),
];
$util = new UtilController;
$util->logFile(json_encode($data));
}
} else if ($paymentState != 'PENDING') {
$this->inactiveBlockBackups($ticketMain->ticket_user_block_backups);
Ticket::where('ticket_main_id', $ticketMain->id)->update(['ticket_status_id' => 4]); // ESTADO TIQUETES REVERSADOS
}
return true;
}
public function getAllUserInformation(Request $request)
{
$user = User::where([["document", $request->document], ["document_type_id", $request->document_type], ["email", $request->email], ["active", 1]])->first();
if ($user) {
$data = array('status' => 'success', 'user' => $user);
return response()->json($data, 200);
} else {
$data = array('status' => 'error', 'user' => null);
return response()->json($data, 200);
}
}
public function transferTickets(Request $request)
{
$createTicketUserLogs = [];
$amount = 0;
$ticketParameter = $this->ticketParametersService->getParameterObject();
$user = User::where([["document", $request->document], ["document_type_id", $request->document_type], ["email", $request->email], ["active", 1]])->first();
if ($user) {
$ticket = Ticket::where('id', $request->ticket_id)->first();
if ($ticket->number_transfers == null) {
$amount = 1;
} else {
$amount = 1;
$amount += $ticket->number_transfers;
}
if (property_exists($ticketParameter, 'number_transfers') && ($amount <= $ticketParameter->number_transfers)) {
if ($ticket) {
$ticketUpdate = Ticket::updateOrCreate(['id' => $ticket->id], [
'user_id' => $user->id,
'number_transfers' => $amount
]);
if ($ticketUpdate->id) {
$ticketMain = TicketMain::where('id', $ticket->ticket_main_id)->first();
$createTicketUserLogs = [
'ticket_id' => $ticket->id,
'previous_user_id' => $ticket->user_id,
'new_user_id' => $user->id,
'payment_reference' => $ticketMain->payment_reference,
'number_transfers' => $amount,
];
TicketUserLog::updateOrCreate(
$createTicketUserLogs
);
}
} else {
$data = array('status' => 'error', 'ticket' => 'ticketError');
return response()->json($data, 200);
}
} else {
$data = array('status' => 'error', 'ticketParameter' => 'ticketParameterError');
return response()->json($data, 200);
}
$data = array('status' => 'success', 'user' => $user);
return response()->json($data, 200);
} else {
$data = array('status' => 'error', 'user' => null);
return response()->json($data, 200);
}
}
public function parameters()
{
$parameters = $this->ticketParametersService->getParameterObject();
$data = array('status' => 'success', 'parameters' => $parameters);
return response()->json($data, 200);
}
public function loadStadiumZones(Request $request)
{
return $this->ticketsService->loadStadiumZones($request);
}
public function getComplimentaryTicketsByUser(Request $request)
{
try {
$tickets = $this->ticketsService->getComplimentaryTicketsByUser(
$request->match_event_id,
$request->zone
);
return response()->json([
'status' => 'success',
'data' => $tickets
]);
} catch (Exception $e) {
return response()->json([
'status' => 'fail',
'message' => $e->getMessage()
], Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
public function getComplimentaryTicketsSummaryByZoneByUser()
{
try {
$user = Auth::user();
$tickets = $this->ticketsService->getComplimentaryTicketsSummaryByZoneByUser($user->id);
foreach ($tickets as $ticket) {
$complimentaries = $this->ticketsService->getComplimentaryTicketsByUser(
$ticket->match_event_id,
$ticket->zone
);
if (!$complimentaries) {
continue;
}
$ticket->complimentaries = $complimentaries;
}
return response()->json([
'status' => 'success',
'data' => $tickets
]);
} catch (Exception $e) {
return response()->json([
'status' => 'fail',
'message' => $e->getMessage()
], Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
}