From 6611c5b812c6a66b8baa76905d86cf62e0a43c23 Mon Sep 17 00:00:00 2001 From: lizandrogd <77708265+lizandrogd@users.noreply.github.com> Date: Wed, 3 Sep 2025 18:29:19 -0500 Subject: [PATCH] Update ShowPromociones.php --- app/Http/Livewire/ShowPromociones.php | 313 +++++++++++--------------- 1 file changed, 135 insertions(+), 178 deletions(-) diff --git a/app/Http/Livewire/ShowPromociones.php b/app/Http/Livewire/ShowPromociones.php index b87150b..e1ecaff 100755 --- a/app/Http/Livewire/ShowPromociones.php +++ b/app/Http/Livewire/ShowPromociones.php @@ -154,7 +154,7 @@ class ShowPromociones extends Component ->first(); - // dd($consulta_verpromocion, Auth::user()->rol->id, Auth::user()->id); + // dd($consulta_verpromocion, Auth::user()->rol->id, Auth::user()->id); //dd($consulta_verpromocion); //$cuentas_creadas = Cuentas::whereDate('inicio','>=',$this->fecha)->where('servicio_id',$tarifas->servicio->id)->where('estado','!=','inactivo')->where('estado','!=','delete')->get(); @@ -234,221 +234,178 @@ class ShowPromociones extends Component $intento = 0; while ($intento < $maxIntentos) { - DB::beginTransaction(); - try { - - $intento++; - $this->validate(); + DB::transaction(function () { + $this->validate(); - 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($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(); - - $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']); - } + // === Validaciones iniciales === + if ($this->cantidad_comprarPromo == 0) { + throw new \Exception('La cantidad debe ser mayor a 0', 400); } - } - // === Validación de disponibilidad === - if (count($this->f) > 0) { - DB::rollBack(); // no se descuenta saldo - $resultados = Servicio::whereIn('id', $this->f)->get(); + $costoTotal = $this->precioAhora * $this->cantidad_comprarPromo; + $saldoDisponible = auth()->user()->saldo->valor; - if ($resultados->count() > 0) { - $nombresServicios = $resultados->pluck('nombre')->toArray(); - $message = implode(', ', $nombresServicios); + if ($saldoDisponible < $costoTotal) { + throw new \Exception('Saldo insuficiente', 400); + } - $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', - ] + // === Crear o buscar usuario === + $usuario = User::firstWhere('email', $this->email_comprarPromo); + + if (!$usuario) { + $usuario = User::create([ + 'name' => $this->nombre_comprarPromo, + 'email' => $this->email_comprarPromo, + 'password' => bcrypt(Str::random(12)), // 🔒 contraseña aleatoria + 'celular' => $this->celular_comprarPromo, ]); } - return; - } - // === 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); + // === Historial === + $historial = Historiale::create([ + 'fecha_inicio' => $this->fechaHoy, + 'fecha_final' => $this->fechaFinal, + 'valor' => $costoTotal, + 'tipo_pago' => 'manual', + 'estado' => 'pendiente', + 'vendedor_id' => Auth()->user()->id, + 'promocion_id' => $this->consulta->id, + 'cliente_id' => $usuario->id, + 'cantidad' => $this->cantidad_comprarPromo, + 'nombre_cliente' => $this->nombre_comprarPromo, + 'utilidad' => $this->utilidad * $this->cantidad_comprarPromo, + ]); - if ($descuento->update(['valor' => $nuevo_saldo])) { + $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) { + $fecha_final_1 = Carbon::now()->addDays($tarifa->dias - 20); + $fecha_final_2 = Carbon::now()->addDays($tarifa->dias + 20); + + $baseQuery = Cuentas::where('servicio_id', $servicio_id) + ->whereDate('inicio', '>=', $this->fecha) + ->whereDate('vencimiento', '>=', $fecha_final_1) + ->whereDate('vencimiento', '<=', $fecha_final_2) + ->where('estado', 'pendiente') + ->withCount('historiales') + ->orderBy('inicio', 'ASC'); + + $cuenta = Cuentas::fromSub($baseQuery, 'alias') + ->where('historiales_count', '=', 0) + ->lockForUpdate() + ->first(); + } else { + $baseQuery = Cuentas::where('servicio_id', $servicio_id) + ->whereDate('inicio', '>=', $this->fecha) + ->where('estado', 'activo') + ->withCount('historiales') + ->orderBy('inicio', 'ASC'); + + $cuenta = Cuentas::fromSub($baseQuery, 'alias') + ->where('historiales_count', '<=', (int) $faltante) + ->lockForUpdate() + ->first(); + } + + if ($cuenta) { + $perfil = Historial_cuenta::where('cuenta_id', $cuenta->id)->max('perfil') ?? 0; + + for ($y = 0; $y < (int) $pantallas_tarifa; $y++) { + $historial_cuenta = Historial_cuenta::create([ + 'historial_id' => $historial->id, + 'cuenta_id' => $cuenta->id, + 'perfil' => (int) $perfil + (int) $y + 1, + ]); + + if ($historial_cuenta->id) { + $this->n[] = $historial_cuenta->id; + } + } + } else { + $this->f[] = $servicio_id; + throw new \Exception('No hay cuentas disponibles de ' . $tarifa->servicio->nombre, 409); + } + } + } + + // === Cobro de saldo === + $descuento = Saldo::where('usuario_id', Auth::user()->id)->first(); + $saldo_anterior = $descuento->valor; + $nuevo_saldo = $saldo_anterior - $costoTotal; + + if (!$descuento->update(['valor' => $nuevo_saldo])) { + Historial_cuenta::whereIn('id', $this->n)->delete(); + throw new \Exception('Error en el cobro, comuníquese con soporte!', 500); + } + + // Activar historial $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(); + Log_general::create([ + 'user_id' => Auth::user()->id, + '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, + 'tipo' => 'compra', + 'historial_id' => $historial->id, + ]); - // utilidad para el padre + // 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) { $nuevoSaldo = $subvendedorPadre->saldo->valor + $utilidad_total; $subvendedorPadre->saldo->update(['valor' => $nuevoSaldo]); - $logsGeneral = new Log_general(); - $logsGeneral->user_id = Auth::user()->id; - $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(); + Log_general::create([ + 'user_id' => Auth::user()->id, + 'detalle' => 'Compra generó utilidad de $' . $utilidad_total . + ' al usuario padre ' . $subvendedorPadre->name . ' - ' . $subvendedorPadre->email, + 'historial_id' => $historial->id, + 'tipo' => 'compra', + ]); } } $this->modalComprarPromo = false; $this->credenciales($historial); + }, 3); // Laravel volverá a intentar hasta 3 veces si hay deadlocks - DB::commit(); - break; // ✅ salir del while (ya se completó la compra) - } else { - Historial_cuenta::whereIn('id', $this->n)->delete(); - DB::rollBack(); - $this->alert('warning', 'Error en el cobro, comuníquese con soporte!', ['position' => 'top']); - return; - } + // ✅ si llega aquí es que todo salió bien + break; } catch (QueryException $e) { - DB::rollBack(); - - if ($e->getCode() == '23505') { + if (in_array($e->getCode(), ['23505', '1062'])) { // PostgreSQL o MySQL if ($intento >= $maxIntentos) { $this->alert('warning', 'Otra persona tomó la cuenta al mismo tiempo. Intenta nuevamente.', ['position' => 'top']); return; } - usleep(200000); // 200ms y reintentar + usleep(200000); // esperar 200ms antes de reintentar continue; } - $this->alert('error', 'Error inesperado en la compra: ' . $e->getMessage(), ['position' => 'top']); + $this->alert('error', 'Error en la compra: ' . $e->getMessage(), ['position' => 'top']); return; } catch (\Throwable $e) { - DB::rollBack(); $this->alert('error', 'Error inesperado: ' . $e->getMessage(), ['position' => 'top']); return; }