Update ShowPromociones.php

This commit is contained in:
lizandrogd
2025-09-03 18:29:19 -05:00
parent 7b0aeb6f56
commit 6611c5b812
+74 -117
View File
@@ -234,60 +234,50 @@ class ShowPromociones extends Component
$intento = 0; $intento = 0;
while ($intento < $maxIntentos) { while ($intento < $maxIntentos) {
DB::beginTransaction();
try { try {
$intento++; $intento++;
DB::transaction(function () {
$this->validate(); $this->validate();
// === Validaciones iniciales ===
if ($this->cantidad_comprarPromo == 0) { if ($this->cantidad_comprarPromo == 0) {
$this->alert('error', 'La cantidad debe ser mayor a 0', ['position' => 'top']); throw new \Exception('La cantidad debe ser mayor a 0', 400);
DB::rollBack();
return;
} }
if (auth()->user()->saldo->valor < $this->precioAhora * $this->cantidad_comprarPromo) { $costoTotal = $this->precioAhora * $this->cantidad_comprarPromo;
$this->alert('error', 'Saldo insuficiente', ['position' => 'top']); $saldoDisponible = auth()->user()->saldo->valor;
DB::rollBack();
return; if ($saldoDisponible < $costoTotal) {
throw new \Exception('Saldo insuficiente', 400);
} }
// === Crear o buscar usuario === // === Crear o buscar usuario ===
$usuario_existe = User::firstWhere('email', $this->email_comprarPromo)->id ?? null; $usuario = User::firstWhere('email', $this->email_comprarPromo);
if (is_null($usuario_existe)) { if (!$usuario) {
$usuario = new User; $usuario = User::create([
$usuario->name = $this->nombre_comprarPromo; 'name' => $this->nombre_comprarPromo,
$usuario->email = $this->email_comprarPromo; 'email' => $this->email_comprarPromo,
$usuario->password = bcrypt('123'); // ✅ importante: encriptar 'password' => bcrypt(Str::random(12)), // 🔒 contraseña aleatoria
$usuario->celular = $this->celular_comprarPromo; 'celular' => $this->celular_comprarPromo,
$usuario->save(); ]);
$usuario_id = $usuario->id;
} else {
$usuario_id = $usuario_existe;
} }
// === Historial === // === Historial ===
$historial = new Historiale(); $historial = Historiale::create([
$historial->fecha_inicio = $this->fechaHoy; 'fecha_inicio' => $this->fechaHoy,
$historial->fecha_final = $this->fechaFinal; 'fecha_final' => $this->fechaFinal,
$historial->valor = $this->precioAhora * $this->cantidad_comprarPromo; 'valor' => $costoTotal,
$historial->tipo_pago = 'manual'; 'tipo_pago' => 'manual',
$historial->estado = 'pendiente'; 'estado' => 'pendiente',
$historial->vendedor_id = Auth()->user()->id; 'vendedor_id' => Auth()->user()->id,
$historial->promocion_id = $this->consulta->id; 'promocion_id' => $this->consulta->id,
$historial->cliente_id = $usuario_id; 'cliente_id' => $usuario->id,
$historial->cantidad = $this->cantidad_comprarPromo; 'cantidad' => $this->cantidad_comprarPromo,
$historial->nombre_cliente = $this->nombre_comprarPromo; 'nombre_cliente' => $this->nombre_comprarPromo,
$historial->utilidad = $this->utilidad * $this->cantidad_comprarPromo; 'utilidad' => $this->utilidad * $this->cantidad_comprarPromo,
$historial->save(); ]);
$utilidad_total = (int) $this->utilidad * (int) $this->cantidad_comprarPromo; $utilidad_total = (int) $this->utilidad * (int) $this->cantidad_comprarPromo;
$this->historial = $historial; $this->historial = $historial;
@@ -305,40 +295,43 @@ class ShowPromociones extends Component
$faltante = $pantalla_servicio - $pantallas_tarifa; $faltante = $pantalla_servicio - $pantallas_tarifa;
if ($pantalla_servicio_completa == $pantallas_tarifa) { if ($pantalla_servicio_completa == $pantallas_tarifa) {
$this->fecha_final_1 = Carbon::now()->addDays($tarifa->dias - 20); $fecha_final_1 = Carbon::now()->addDays($tarifa->dias - 20);
$this->fecha_final_2 = Carbon::now()->addDays($tarifa->dias + 20); $fecha_final_2 = Carbon::now()->addDays($tarifa->dias + 20);
$baseQuery = Cuentas::where('servicio_id', $servicio_id) $baseQuery = Cuentas::where('servicio_id', $servicio_id)
->whereDate('inicio', '>=', $this->fecha) ->whereDate('inicio', '>=', $this->fecha)
->whereDate('vencimiento', '>=', $this->fecha_final_1) ->whereDate('vencimiento', '>=', $fecha_final_1)
->whereDate('vencimiento', '<=', $this->fecha_final_2) ->whereDate('vencimiento', '<=', $fecha_final_2)
->orderBy('inicio', 'ASC') ->where('estado', 'pendiente')
->withCount('historiales') ->withCount('historiales')
->where('estado', 'pendiente'); ->orderBy('inicio', 'ASC');
$cuenta = Cuentas::fromSub($baseQuery, 'alias') $cuenta = Cuentas::fromSub($baseQuery, 'alias')
->where('historiales_count', '=', 0) ->where('historiales_count', '=', 0)
->lockForUpdate()
->first(); ->first();
} else { } else {
$baseQuery = Cuentas::where('servicio_id', $servicio_id) $baseQuery = Cuentas::where('servicio_id', $servicio_id)
->whereDate('inicio', '>=', $this->fecha) ->whereDate('inicio', '>=', $this->fecha)
->orderBy('inicio', 'ASC') ->where('estado', 'activo')
->withCount('historiales') ->withCount('historiales')
->where('estado', 'activo'); ->orderBy('inicio', 'ASC');
$cuenta = Cuentas::fromSub($baseQuery, 'alias') $cuenta = Cuentas::fromSub($baseQuery, 'alias')
->where('historiales_count', '<=', (int) $faltante) ->where('historiales_count', '<=', (int) $faltante)
->lockForUpdate()
->first(); ->first();
} }
if ($cuenta) { if ($cuenta) {
$perfil = Historial_cuenta::where('cuenta_id', $cuenta->id)->max('perfil') ?? 0; $perfil = Historial_cuenta::where('cuenta_id', $cuenta->id)->max('perfil') ?? 0;
for ($y = 0; $y < (int) $pantallas_tarifa; $y++) { for ($y = 0; $y < (int) $pantallas_tarifa; $y++) {
$historial_cuenta = new Historial_cuenta(); $historial_cuenta = Historial_cuenta::create([
$historial_cuenta->historial_id = $historial->id; 'historial_id' => $historial->id,
$historial_cuenta->cuenta_id = $cuenta->id; 'cuenta_id' => $cuenta->id,
$historial_cuenta->perfil = (int) $perfil + (int) $y + 1; 'perfil' => (int) $perfil + (int) $y + 1,
$historial_cuenta->save(); ]);
if ($historial_cuenta->id) { if ($historial_cuenta->id) {
$this->n[] = $historial_cuenta->id; $this->n[] = $historial_cuenta->id;
@@ -346,109 +339,73 @@ class ShowPromociones extends Component
} }
} else { } else {
$this->f[] = $servicio_id; $this->f[] = $servicio_id;
$this->alert('warning', 'No hay cuentas disponibles de ' . $tarifa->servicio->nombre, ['position' => 'top']); throw new \Exception('No hay cuentas disponibles de ' . $tarifa->servicio->nombre, 409);
} }
} }
} }
// === Validación de disponibilidad ===
if (count($this->f) > 0) {
DB::rollBack(); // no se descuenta saldo
$resultados = Servicio::whereIn('id', $this->f)->get();
if ($resultados->count() > 0) {
$nombresServicios = $resultados->pluck('nombre')->toArray();
$message = implode(', ', $nombresServicios);
$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;
}
// === Cobro de saldo === // === Cobro de saldo ===
$descuento = Saldo::where('usuario_id', Auth::user()->id)->first(); $descuento = Saldo::where('usuario_id', Auth::user()->id)->first();
$saldo_anterior = $descuento->valor; $saldo_anterior = $descuento->valor;
$nuevo_saldo = $saldo_anterior - ($this->precioAhora * $this->cantidad_comprarPromo); $nuevo_saldo = $saldo_anterior - $costoTotal;
if ($descuento->update(['valor' => $nuevo_saldo])) { 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']); $historial->update(['estado' => 'activo']);
// Registrar logs // Registrar logs
$logsGeneral = new Log_general(); Log_general::create([
$logsGeneral->user_id = Auth::user()->id; 'user_id' => Auth::user()->id,
$logsGeneral->detalle = 'El usuario ' . Auth::user()->name . ' - ' . Auth::user()->email . 'detalle' => 'El usuario ' . Auth::user()->name . ' - ' . Auth::user()->email .
' ha comprado la promoción ' . $this->consulta->nombre . ' - ' . $this->consulta->descripcion . ' ha comprado la promoción ' . $this->consulta->nombre . ' - ' . $this->consulta->descripcion .
' cantidad de ' . $this->historial->cantidad . ' cantidad de ' . $this->historial->cantidad .
' por un valor de $' . $this->historial->valor . ' por un valor de $' . $this->historial->valor .
', Saldo anterior: $' . $saldo_anterior . ', Saldo anterior: $' . $saldo_anterior .
', Nuevo saldo disponible: $' . $nuevo_saldo; ', Nuevo saldo disponible: $' . $nuevo_saldo,
$logsGeneral->tipo = 'compra'; 'tipo' => 'compra',
$logsGeneral->historial_id = $historial->id; 'historial_id' => $historial->id,
$logsGeneral->save(); ]);
// utilidad para el padre // Utilidad para el padre
if (Auth::user()->subvendedor_id && $utilidad_total > 0) { if (Auth::user()->subvendedor_id && $utilidad_total > 0) {
$subvendedorPadre = User::with('saldo')->find(Auth::user()->subvendedor_id); $subvendedorPadre = User::with('saldo')->find(Auth::user()->subvendedor_id);
if ($subvendedorPadre && $subvendedorPadre->saldo) { if ($subvendedorPadre && $subvendedorPadre->saldo) {
$nuevoSaldo = $subvendedorPadre->saldo->valor + $utilidad_total; $nuevoSaldo = $subvendedorPadre->saldo->valor + $utilidad_total;
$subvendedorPadre->saldo->update(['valor' => $nuevoSaldo]); $subvendedorPadre->saldo->update(['valor' => $nuevoSaldo]);
$logsGeneral = new Log_general(); Log_general::create([
$logsGeneral->user_id = Auth::user()->id; 'user_id' => Auth::user()->id,
$logsGeneral->detalle = 'Compra generó utilidad de $' . $utilidad_total . 'detalle' => 'Compra generó utilidad de $' . $utilidad_total .
' al usuario padre ' . $subvendedorPadre->name . ' - ' . $subvendedorPadre->email; ' al usuario padre ' . $subvendedorPadre->name . ' - ' . $subvendedorPadre->email,
$logsGeneral->historial_id = $historial->id; 'historial_id' => $historial->id,
$logsGeneral->tipo = 'compra'; 'tipo' => 'compra',
$logsGeneral->save(); ]);
} }
} }
$this->modalComprarPromo = false; $this->modalComprarPromo = false;
$this->credenciales($historial); $this->credenciales($historial);
}, 3); // Laravel volverá a intentar hasta 3 veces si hay deadlocks
DB::commit(); // ✅ si llega aquí es que todo salió bien
break; // ✅ salir del while (ya se completó la compra) break;
} else {
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) { } catch (QueryException $e) {
DB::rollBack(); if (in_array($e->getCode(), ['23505', '1062'])) { // PostgreSQL o MySQL
if ($e->getCode() == '23505') {
if ($intento >= $maxIntentos) { if ($intento >= $maxIntentos) {
$this->alert('warning', 'Otra persona tomó la cuenta al mismo tiempo. Intenta nuevamente.', ['position' => 'top']); $this->alert('warning', 'Otra persona tomó la cuenta al mismo tiempo. Intenta nuevamente.', ['position' => 'top']);
return; return;
} }
usleep(200000); // 200ms y reintentar usleep(200000); // esperar 200ms antes de reintentar
continue; 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; return;
} catch (\Throwable $e) { } catch (\Throwable $e) {
DB::rollBack();
$this->alert('error', 'Error inesperado: ' . $e->getMessage(), ['position' => 'top']); $this->alert('error', 'Error inesperado: ' . $e->getMessage(), ['position' => 'top']);
return; return;
} }