From 9971109968fbc311b1a4eed5915f08bcea694678 Mon Sep 17 00:00:00 2001 From: lizandrogd <77708265+lizandrogd@users.noreply.github.com> Date: Tue, 2 Sep 2025 22:48:43 -0500 Subject: [PATCH] Update ShowPromociones.php --- app/Http/Livewire/ShowPromociones.php | 379 +++++++++++++------------- 1 file changed, 187 insertions(+), 192 deletions(-) diff --git a/app/Http/Livewire/ShowPromociones.php b/app/Http/Livewire/ShowPromociones.php index fffd437..aef0e28 100755 --- a/app/Http/Livewire/ShowPromociones.php +++ b/app/Http/Livewire/ShowPromociones.php @@ -27,6 +27,7 @@ use Jantinnerezo\LivewireAlert\LivewireAlert; use Intervention\Image\ImageManagerStatic as Img; use Illuminate\Support\Str; use Illuminate\Support\Facades\Storage; +use Illuminate\Support\Facades\DB; use Exception; use Twilio\Rest\Client; @@ -217,235 +218,229 @@ class ShowPromociones extends Component public $n = []; public $f = []; public $r = 0; - public function pagar() { - $this->validate(); + $maxIntentos = 3; // cantidad de veces que se intentará + $intento = 0; - if ($this->cantidad_comprarPromo == 0) { - $this->alert('error', 'La cantidad debe ser mayor a 0', [ - 'position' => 'top' - ]); - return; - } + while ($intento < $maxIntentos) { + DB::beginTransaction(); - if (auth()->user()->saldo->valor < $this->precioAhora * $this->cantidad_comprarPromo) { - $this->alert('error', 'Saldo insuficiente', [ - 'position' => 'top' - ]); - return; - } + try { + $intento++; - $usuario_existe = User::firstWhere('email', $this->email_comprarPromo)->id ?? null; + $this->validate(); - if (is_null($usuario_existe)) { - $usuario = new User; - $usuario->name = $this->nombre_comprarPromo; - $usuario->email = $this->email_comprarPromo; - $usuario->password = '123'; - $usuario->celular = $this->celular_comprarPromo; - $usuario->save(); - - $usuario_id = $usuario->id; - } else { - $usuario_id = $usuario_existe; - } - - $historial = new Historiale(); - $historial->fecha_inicio = $this->fechaHoy; - $historial->fecha_final = $this->fechaFinal; - $historial->valor = $this->precioAhora * $this->cantidad_comprarPromo; - $historial->tipo_pago = 'manual'; - $historial->estado = 'pendiente'; - $historial->vendedor_id = Auth()->user()->id; - $historial->promocion_id = $this->consulta->id; - $historial->cliente_id = $usuario_id; - $historial->cantidad = $this->cantidad_comprarPromo; - $historial->nombre_cliente = $this->nombre_comprarPromo; - $historial->utilidad = $this->utilidad * $this->cantidad_comprarPromo; - $historial->save(); - - $utilidad_total = (int) $this->utilidad * (int) $this->cantidad_comprarPromo; - - $this->historial = $historial; - - for ($p = 0; $p < (int) $this->cantidad_comprarPromo; $p++) { - //dd($this->cantidad_comprarPromo); - $this->n = []; - $this->f = []; - $this->r = 0; - - foreach ($this->consulta->tarifas as $tarifa) { - $this->r = $this->r + $tarifa->pantallas; - $pantallas_tarifa = $tarifa->pantallas; - $servicio_id = $tarifa->servicio_id; - $pantalla_servicio = $tarifa->servicio->pantallas; - $pantalla_servicio_completa = $tarifa->servicio->completa; - $faltante = $pantalla_servicio - $pantallas_tarifa; - - //dd($tarifa); - if ($pantalla_servicio_completa == $pantallas_tarifa) { - - $this->fecha_final_1 = $today = Carbon::now()->addDays($tarifa->dias - 20); - $this->fecha_final_2 = $today = Carbon::now()->addDays($tarifa->dias + 20); - - $baseQuery = Cuentas::select('*')->where('servicio_id', $servicio_id) - ->whereDate('inicio', '>=', $this->fecha) - ->whereDate('vencimiento', '>=', $this->fecha_final_1) - ->whereDate('vencimiento', '<=', $this->fecha_final_2) - ->Orderby('inicio', 'ASC')->with('historiales') - ->withCount('historiales') - ->where('estado', 'pendiente'); - - $cuenta = Cuentas::fromSub($baseQuery, 'alias') - ->where('historiales_count', '=', 0) - ->orderBy('inicio', 'ASC') - ->first(); - } else { - $baseQuery = Cuentas::select('*')->where('servicio_id', $servicio_id) - ->whereDate('inicio', '>=', $this->fecha) - ->Orderby('inicio', 'ASC') - ->with('historiales') - ->withCount('historiales') - ->where('estado', 'activo'); - - $cuenta = Cuentas::fromSub($baseQuery, 'alias') - ->where('historiales_count', '<=', (int) $faltante) - ->orderBy('inicio', 'ASC') - ->first(); + if ($this->cantidad_comprarPromo == 0) { + $this->alert('error', 'La cantidad debe ser mayor a 0', ['position' => 'top']); + DB::rollBack(); + return; } + if (auth()->user()->saldo->valor < $this->precioAhora * $this->cantidad_comprarPromo) { + $this->alert('error', 'Saldo insuficiente', ['position' => 'top']); + DB::rollBack(); + return; + } + // === Crear o buscar usuario === + $usuario_existe = User::firstWhere('email', $this->email_comprarPromo)->id ?? null; - if (!is_null($cuenta)) { - //$perfil = $cuenta->historiales_count; - $perfil = Historial_cuenta::where('cuenta_id', $cuenta->id)->max('perfil') ?? 0; - for ($y = 0; $y < (int) $pantallas_tarifa; $y++) { + if (is_null($usuario_existe)) { + $usuario = new User; + $usuario->name = $this->nombre_comprarPromo; + $usuario->email = $this->email_comprarPromo; + $usuario->password = bcrypt('123'); // ✅ importante: encriptar + $usuario->celular = $this->celular_comprarPromo; + $usuario->save(); - $historial_cuenta = new Historial_cuenta(); - $historial_cuenta->historial_id = $historial->id; - $historial_cuenta->cuenta_id = $cuenta->id; - $historial_cuenta->perfil = (int) $perfil + (int) $y + 1; - $historial_cuenta->save(); - if (!empty($historial_cuenta->id)) { - array_push($this->n, $historial_cuenta->id); + $usuario_id = $usuario->id; + } else { + $usuario_id = $usuario_existe; + } + + // === Historial === + $historial = new Historiale(); + $historial->fecha_inicio = $this->fechaHoy; + $historial->fecha_final = $this->fechaFinal; + $historial->valor = $this->precioAhora * $this->cantidad_comprarPromo; + $historial->tipo_pago = 'manual'; + $historial->estado = 'pendiente'; + $historial->vendedor_id = Auth()->user()->id; + $historial->promocion_id = $this->consulta->id; + $historial->cliente_id = $usuario_id; + $historial->cantidad = $this->cantidad_comprarPromo; + $historial->nombre_cliente = $this->nombre_comprarPromo; + $historial->utilidad = $this->utilidad * $this->cantidad_comprarPromo; + $historial->save(); + + $utilidad_total = (int) $this->utilidad * (int) $this->cantidad_comprarPromo; + $this->historial = $historial; + + // === Asignar cuentas === + $this->n = []; + $this->f = []; + + for ($p = 0; $p < (int) $this->cantidad_comprarPromo; $p++) { + foreach ($this->consulta->tarifas as $tarifa) { + $pantallas_tarifa = $tarifa->pantallas; + $servicio_id = $tarifa->servicio_id; + $pantalla_servicio = $tarifa->servicio->pantallas; + $pantalla_servicio_completa = $tarifa->servicio->completa; + $faltante = $pantalla_servicio - $pantallas_tarifa; + + if ($pantalla_servicio_completa == $pantallas_tarifa) { + $this->fecha_final_1 = Carbon::now()->addDays($tarifa->dias - 20); + $this->fecha_final_2 = Carbon::now()->addDays($tarifa->dias + 20); + + $baseQuery = Cuentas::where('servicio_id', $servicio_id) + ->whereDate('inicio', '>=', $this->fecha) + ->whereDate('vencimiento', '>=', $this->fecha_final_1) + ->whereDate('vencimiento', '<=', $this->fecha_final_2) + ->orderBy('inicio', 'ASC') + ->withCount('historiales') + ->where('estado', 'pendiente'); + + $cuenta = Cuentas::fromSub($baseQuery, 'alias') + ->where('historiales_count', '=', 0) + ->first(); + } else { + $baseQuery = Cuentas::where('servicio_id', $servicio_id) + ->whereDate('inicio', '>=', $this->fecha) + ->orderBy('inicio', 'ASC') + ->withCount('historiales') + ->where('estado', 'activo'); + + $cuenta = Cuentas::fromSub($baseQuery, 'alias') + ->where('historiales_count', '<=', (int) $faltante) + ->first(); + } + + if ($cuenta) { + $perfil = Historial_cuenta::where('cuenta_id', $cuenta->id)->max('perfil') ?? 0; + for ($y = 0; $y < (int) $pantallas_tarifa; $y++) { + $historial_cuenta = new Historial_cuenta(); + $historial_cuenta->historial_id = $historial->id; + $historial_cuenta->cuenta_id = $cuenta->id; + $historial_cuenta->perfil = (int) $perfil + (int) $y + 1; + $historial_cuenta->save(); + + if ($historial_cuenta->id) { + $this->n[] = $historial_cuenta->id; + } + } + } else { + $this->f[] = $servicio_id; + $this->alert('warning', 'No hay cuentas disponibles de ' . $tarifa->servicio->nombre, ['position' => 'top']); } } - } else { - array_push($this->f, $servicio_id); - $this->alert('warning', 'No hay cuentas disponibles de ' . $tarifa->servicio->nombre, [ - 'position' => 'top' - ]); } - $cuenta = null; - $this->modalComprarPromo = false; - } - } - if (count($this->f) > 0) { - $resultados = Servicio::whereIn('id', $this->f)->get(); - // $eliminar = Historial_cuenta::whereIn('id', $n)->delete(); - $message = ''; - if ($resultados->count() > 0) { - $nombresServicios = $resultados->pluck('nombre')->toArray(); - $message = implode(', ', $nombresServicios); + // === Validación de disponibilidad === + if (count($this->f) > 0) { + DB::rollBack(); // no se descuenta saldo + $resultados = Servicio::whereIn('id', $this->f)->get(); - $this->alert('warning', 'No hay disponibilidad de ' . $message . ' en este momento.', [ - 'position' => 'center', - 'timer' => '60000', - 'toast' => false, - 'text' => '¿Te gustaría realizar la compra ahora y recibir tu pedido tan pronto como haya disponibilidad?.', - 'allowOutsideClick' => false, - 'allowEscapeKey' => false, - 'showConfirmButton' => true, - 'showCancelButton' => false, - 'showDenyButton' => true, - 'onConfirmed' => 'confirmarCompra', - 'onDenied' => 'denegarCompra', - // 'cancelButtonText' => 'No, abandonar.', - 'denyButtonText' => 'No, abandonar.', - 'confirmButtonText' => 'Sí, comprar.', - 'customClass' => [ - 'confirmButton' => 'bg-green-500', - 'denyButton' => 'bg-red-500', - 'cancelButton' => 'bg-gray-500', - ] - ]); - } - } else { - $descuento = Saldo::where('usuario_id', Auth::user()->id)->first(); - $saldo_anterior = $descuento->valor; - $nuevo_saldo = $saldo_anterior - ($this->precioAhora * $this->cantidad_comprarPromo); - $cobro = $descuento->update(['valor' => $nuevo_saldo]); + if ($resultados->count() > 0) { + $nombresServicios = $resultados->pluck('nombre')->toArray(); + $message = implode(', ', $nombresServicios); - if ($cobro) { - $historial->update(['estado' => 'activo']); + $this->alert('warning', 'No hay disponibilidad de ' . $message . ' en este momento.', [ + 'position' => 'center', + 'timer' => '60000', + 'toast' => false, + 'text' => '¿Te gustaría realizar la compra ahora y recibir tu pedido tan pronto como haya disponibilidad?.', + 'allowOutsideClick' => false, + 'allowEscapeKey' => false, + 'showConfirmButton' => true, + 'showCancelButton' => false, + 'showDenyButton' => true, + 'onConfirmed' => 'confirmarCompra', + 'onDenied' => 'denegarCompra', + 'denyButtonText' => 'No, abandonar.', + 'confirmButtonText' => 'Sí, comprar.', + 'customClass' => [ + 'confirmButton' => 'bg-green-500', + 'denyButton' => 'bg-red-500', + 'cancelButton' => 'bg-gray-500', + ] + ]); + } + return; + } - $logsGeneral = new Log_general(); - $logsGeneral->user_id = Auth::user()->id; - $logsGeneral->detalle = 'El usuario ' . Auth::user()->name . ' - ' . Auth::user()->email . ' ha comprado la promocion ' . $this->consulta->nombre . ' - ' . $this->consulta->descripcion . ' cantidad de ' . $this->historial->cantidad . ' por un valor de $' . $this->historial->valor . ', Saldo anterior: $' . $saldo_anterior . ', Nuevo saldo disponible: $' . $nuevo_saldo; - $logsGeneral->tipo = 'compra'; - $logsGeneral->historial_id = $historial->id; - $logsGeneral->save(); + // === Cobro de saldo === + $descuento = Saldo::where('usuario_id', Auth::user()->id)->first(); + $saldo_anterior = $descuento->valor; + $nuevo_saldo = $saldo_anterior - ($this->precioAhora * $this->cantidad_comprarPromo); - // Si el campo subvendedor tiene id entonces la utilidad va a su subvendedor padre - if (Auth::user()->subvendedor_id) { - if ($utilidad_total > 0) { + if ($descuento->update(['valor' => $nuevo_saldo])) { + $historial->update(['estado' => 'activo']); + + // Registrar logs + $logsGeneral = new Log_general(); + $logsGeneral->user_id = Auth::user()->id; + $logsGeneral->detalle = 'El usuario ' . Auth::user()->name . ' - ' . Auth::user()->email . + ' ha comprado la promoción ' . $this->consulta->nombre . ' - ' . $this->consulta->descripcion . + ' cantidad de ' . $this->historial->cantidad . + ' por un valor de $' . $this->historial->valor . + ', Saldo anterior: $' . $saldo_anterior . + ', Nuevo saldo disponible: $' . $nuevo_saldo; + $logsGeneral->tipo = 'compra'; + $logsGeneral->historial_id = $historial->id; + $logsGeneral->save(); + + // utilidad para el padre + if (Auth::user()->subvendedor_id && $utilidad_total > 0) { $subvendedorPadre = User::with('saldo')->find(Auth::user()->subvendedor_id); - if ($subvendedorPadre && $subvendedorPadre->saldo) { - // Sumar la utilidad al saldo actual $nuevoSaldo = $subvendedorPadre->saldo->valor + $utilidad_total; + $subvendedorPadre->saldo->update(['valor' => $nuevoSaldo]); - // Actualizar el saldo - $subvendedorPadre->saldo->update([ - 'valor' => $nuevoSaldo - ]); - - // Registrar en el log la utilidad generada $logsGeneral = new Log_general(); $logsGeneral->user_id = Auth::user()->id; - $logsGeneral->detalle = 'El usuario ' . Auth::user()->name . ' - ' . Auth::user()->email . - ' ha comprado la promocion ' . $this->consulta->nombre . ' - ' . $this->consulta->descripcion . - ' cantidad de ' . $this->historial->cantidad . - ' por un valor de $' . $this->historial->valor . - ', Saldo anterior: $' . $saldo_anterior . - ', Nuevo saldo disponible: $' . $nuevo_saldo . - '. Esta compra generó una utilidad de $' . $utilidad_total . - ' al usuario padre ' . $subvendedorPadre->name . ' - ' . $subvendedorPadre->email . '.'; + $logsGeneral->detalle = 'Compra generó utilidad de $' . $utilidad_total . + ' al usuario padre ' . $subvendedorPadre->name . ' - ' . $subvendedorPadre->email; $logsGeneral->historial_id = $historial->id; $logsGeneral->tipo = 'compra'; $logsGeneral->save(); } } + + $this->modalComprarPromo = false; + $this->credenciales($historial); + + DB::commit(); + break; // ✅ salir del while (ya se completó la compra) } else { - // Log sin utilidad al padre - $logsGeneral = new Log_general(); - $logsGeneral->user_id = Auth::user()->id; - $logsGeneral->detalle = 'El usuario ' . Auth::user()->name . ' - ' . Auth::user()->email . - ' ha comprado la promocion ' . $this->consulta->nombre . ' - ' . $this->consulta->descripcion . - ' cantidad de ' . $this->historial->cantidad . - ' por un valor de $' . $this->historial->valor . - ', Saldo anterior: $' . $saldo_anterior . - ', Nuevo saldo disponible: $' . $nuevo_saldo; - $logsGeneral->historial_id = $historial->id; - $logsGeneral->tipo = 'compra'; - $logsGeneral->save(); + Historial_cuenta::whereIn('id', $this->n)->delete(); + DB::rollBack(); + $this->alert('warning', 'Error en el cobro, comuníquese con soporte!', ['position' => 'top']); + return; + } + } catch (QueryException $e) { + DB::rollBack(); + + if ($e->getCode() == '23505') { + if ($intento >= $maxIntentos) { + $this->alert('warning', 'Otra persona tomó la cuenta al mismo tiempo. Intenta nuevamente.', ['position' => 'top']); + return; + } + usleep(200000); // 200ms y reintentar + continue; } - - $this->modalComprarPromo = false; - $this->credenciales($historial); - } else { - $eliminar = Historial_cuenta::whereIn('id', $this->n)->delete(); - - $this->alert('warning', 'Error en el cobro, comuniquese con soporte!', [ - 'position' => 'top' - ]); + $this->alert('error', 'Error inesperado en la compra: ' . $e->getMessage(), ['position' => 'top']); + return; + } catch (\Throwable $e) { + DB::rollBack(); + $this->alert('error', 'Error inesperado: ' . $e->getMessage(), ['position' => 'top']); + return; } } } + public function confirmarCompra() { $descuento = Saldo::where('usuario_id', Auth::user()->id)->first();