Fix 5 bugs in chat and Telegram purchase flows

1. PublicChat::comprarPromoConSaldo — double saldo subtraction: $saldo->update()
   already updates the model in memory, so $this->saldoUsuario = $saldo->valor - precio
   was subtracting twice. Fixed by computing $nuevoSaldo before the update.
   Also wrapped in DB::transaction (was missing unlike pagarConSaldo).

2. TelegramBotService::listServices — showed all services without filtering by the
   user's rol_id, so users could see services with no plans for their role.
   Now uses whereHas('tarifas', rol_id) like PublicChat and the web.

3. TelegramBotService::payWithSaldo — no DB::transaction; if saldo update failed
   after historial was created, user got a free service. Now wrapped atomically.

4. TelegramBotService::buyPromoSaldo — same missing transaction + fecha_final was
   hardcoded to 30 days instead of promo->dias. Both fixed.

5. TelegramBotService::showCredentials — N+1 queries loading cuentas lazily per
   historial. Added cuentas to the eager-load list.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro
2026-07-18 16:06:20 +00:00
co-authored by Claude Sonnet 4.6
parent 1f25c31603
commit 2f5be9253b
2 changed files with 58 additions and 39 deletions
+9 -4
View File
@@ -909,10 +909,15 @@ class PublicChat extends Component
'nombre_cliente' => $user->name,
]);
Historial_cuenta::create(['historial_id' => $historial->id, 'cuenta_id' => $cuenta->id]);
$cuenta->update(['estado' => 'ocupado']);
$saldo->update(['valor' => $saldo->valor - $precio]);
$this->saldoUsuario = $saldo->valor - $precio;
$nuevoSaldo = $saldo->valor - $precio;
DB::transaction(function () use ($historial, $cuenta, $saldo, $nuevoSaldo) {
Historial_cuenta::create(['historial_id' => $historial->id, 'cuenta_id' => $cuenta->id]);
$cuenta->update(['estado' => 'ocupado']);
$saldo->update(['valor' => $nuevoSaldo]);
});
$this->saldoUsuario = $nuevoSaldo;
ChatMessage::create([
'conversation_id' => $this->convId,
+49 -35
View File
@@ -24,6 +24,7 @@ use App\Models\Tarifas;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
@@ -611,7 +612,15 @@ class TelegramBotService
private function listServices(string $chatId): void
{
$servicios = Servicio::where('estado', 'activo')->orderBy('ubicacion')->get();
$state = $this->getState($chatId);
$rolId = isset($state['user_id'])
? (User::find($state['user_id'])?->rol_id ?? Role::where('nombre', 'cliente')->value('id'))
: Role::where('nombre', 'cliente')->value('id');
$servicios = Servicio::where('estado', 'activo')
->whereHas('tarifas', fn ($q) => $q->where('estado', 'activo')->where('rol_id', $rolId))
->orderBy('ubicacion')
->get();
if ($servicios->isEmpty()) {
$this->send($chatId, "No hay servicios disponibles en este momento.");
@@ -736,23 +745,25 @@ class TelegramBotService
return;
}
$historial = Historiale::create([
'fecha_inicio' => now(),
'fecha_final' => now()->addDays($tarifa->dias),
'valor' => $precio,
'utilidad' => $tarifa->utilidad ?? 0,
'tipo_pago' => 'saldo',
'estado' => 'entregado',
'vendedor_id' => $state['user_id'],
'tarifa_id' => $tarifa->id,
'cliente_id' => $state['user_id'],
'nombre_cliente' => $user->name,
]);
Historial_cuenta::create(['historial_id' => $historial->id, 'cuenta_id' => $cuenta->id]);
$cuenta->update(['estado' => 'ocupado']);
$nuevoSaldo = $saldo->valor - $precio;
$saldo->update(['valor' => $nuevoSaldo]);
DB::transaction(function () use ($tarifa, $user, $saldo, $cuenta, $precio, $nuevoSaldo, $state) {
$historial = Historiale::create([
'fecha_inicio' => now(),
'fecha_final' => now()->addDays($tarifa->dias),
'valor' => $precio,
'utilidad' => $tarifa->utilidad ?? 0,
'tipo_pago' => 'saldo',
'estado' => 'entregado',
'vendedor_id' => $state['user_id'],
'tarifa_id' => $tarifa->id,
'cliente_id' => $state['user_id'],
'nombre_cliente' => $user->name,
]);
Historial_cuenta::create(['historial_id' => $historial->id, 'cuenta_id' => $cuenta->id]);
$cuenta->update(['estado' => 'ocupado']);
$saldo->update(['valor' => $nuevoSaldo]);
});
$text = "✅ *¡Compra exitosa!*\n\n";
$text .= "🎬 *{$tarifa->servicio->nombre}*\n";
@@ -920,29 +931,32 @@ class TelegramBotService
return;
}
$historial = Historiale::create([
'fecha_inicio' => now(),
'fecha_final' => now()->addDays(30),
'valor' => $precio,
'utilidad' => $utilidad,
'tipo_pago' => 'saldo',
'estado' => 'entregado',
'vendedor_id' => $user->id,
'promocion_id' => $promoId,
'cliente_id' => $user->id,
'nombre_cliente' => $user->name,
]);
Historial_cuenta::create(['historial_id' => $historial->id, 'cuenta_id' => $cuenta->id]);
$cuenta->update(['estado' => 'ocupado']);
$dias = (int) ($promo->dias ?? 30);
$nuevoSaldo = $saldo->valor - $precio;
$saldo->update(['valor' => $nuevoSaldo]);
DB::transaction(function () use ($promo, $user, $saldo, $cuenta, $precio, $utilidad, $promoId, $dias, $nuevoSaldo) {
$historial = Historiale::create([
'fecha_inicio' => now(),
'fecha_final' => now()->addDays($dias),
'valor' => $precio,
'utilidad' => $utilidad,
'tipo_pago' => 'saldo',
'estado' => 'entregado',
'vendedor_id' => $user->id,
'promocion_id' => $promoId,
'cliente_id' => $user->id,
'nombre_cliente' => $user->name,
]);
Historial_cuenta::create(['historial_id' => $historial->id, 'cuenta_id' => $cuenta->id]);
$cuenta->update(['estado' => 'ocupado']);
$saldo->update(['valor' => $nuevoSaldo]);
});
$text = "✅ *¡Promo activada!*\n\n";
$text .= "🎬 *{$promo->nombre}*\n";
$text .= "📧 Email: `{$cuenta->correo}`\n";
$text .= "🔑 Password: `{$cuenta->password}`\n";
$text .= "📅 Vence: " . now()->addDays(30)->format('d/m/Y') . "\n";
$text .= "📅 Vence: " . now()->addDays($dias)->format('d/m/Y') . "\n";
$text .= "\nSaldo restante: *\$" . number_format($nuevoSaldo) . "*";
$this->send($chatId, $text);
@@ -1123,7 +1137,7 @@ class TelegramBotService
$historiales = Historiale::where('cliente_id', $state['user_id'])
->where('estado', 'entregado')
->where('fecha_final', '>=', now())
->with('tarifa.servicio')
->with(['tarifa.servicio', 'cuentas'])
->orderBy('fecha_final', 'desc')
->limit(10)
->get();