up
This commit is contained in:
@@ -107,6 +107,11 @@ class MenuController extends Controller
|
||||
{
|
||||
return view('menu/log_general');
|
||||
}
|
||||
public function showReversarCompra()
|
||||
{
|
||||
return view('menu/reversar-compra');
|
||||
}
|
||||
|
||||
public function showLogHistorial()
|
||||
{
|
||||
return view('menu/log_historial');
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
|
||||
use App\Models\Historiale;
|
||||
use App\Models\Historial_cuenta;
|
||||
use App\Models\Log_general;
|
||||
use App\Models\Saldo;
|
||||
use App\Models\User;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithPagination;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ReversarCompra extends Component
|
||||
{
|
||||
use WithPagination;
|
||||
|
||||
public $buscar;
|
||||
public $confirmando_id = null;
|
||||
|
||||
protected $listeners = ['confirmarReversar'];
|
||||
|
||||
public function render()
|
||||
{
|
||||
$consulta = Historiale::with('vendedor', 'cliente', 'tarifa.servicio', 'promocion', 'cuentas')
|
||||
->where('estado', 'activo')
|
||||
->orderBy('id', 'DESC')
|
||||
->when(!empty($this->buscar), function ($query) {
|
||||
$query->where(function ($q) {
|
||||
$q->where('id', 'ILIKE', '%' . $this->buscar . '%')
|
||||
->orWhere('nombre_cliente', 'ILIKE', '%' . $this->buscar . '%')
|
||||
->orWhereHas('vendedor', function ($sub) {
|
||||
$sub->where('name', 'ILIKE', '%' . $this->buscar . '%')
|
||||
->orWhere('email', 'ILIKE', '%' . $this->buscar . '%');
|
||||
})
|
||||
->orWhereHas('cliente', function ($sub) {
|
||||
$sub->where('name', 'ILIKE', '%' . $this->buscar . '%')
|
||||
->orWhere('email', 'ILIKE', '%' . $this->buscar . '%');
|
||||
})
|
||||
->orWhereHas('cuentas', function ($sub) {
|
||||
$sub->where('correo', 'ILIKE', '%' . $this->buscar . '%');
|
||||
});
|
||||
});
|
||||
})
|
||||
->take(200)
|
||||
->paginate(20);
|
||||
|
||||
$consulta->setCollection($consulta->getCollection()->values());
|
||||
|
||||
return view('livewire.reversar-compra', ['historiales' => $consulta]);
|
||||
}
|
||||
|
||||
public function confirmar($id)
|
||||
{
|
||||
$this->confirmando_id = $id;
|
||||
}
|
||||
|
||||
public function cancelarConfirmacion()
|
||||
{
|
||||
$this->confirmando_id = null;
|
||||
}
|
||||
|
||||
public function reversar($id)
|
||||
{
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
$historial = Historiale::with('vendedor.saldo', 'tarifa', 'promocion')->findOrFail($id);
|
||||
|
||||
if ($historial->estado !== 'activo') {
|
||||
$this->alert('error', 'Solo se pueden reversar compras activas.');
|
||||
DB::rollBack();
|
||||
return;
|
||||
}
|
||||
|
||||
$vendedor = $historial->vendedor;
|
||||
$total_valor = $historial->valor;
|
||||
$utilidad_total = $historial->utilidad ?? 0;
|
||||
|
||||
// 1. Restaurar saldo al vendedor
|
||||
$nuevo_saldo = $vendedor->saldo->valor + $total_valor;
|
||||
Saldo::where('usuario_id', $vendedor->id)->update(['valor' => $nuevo_saldo]);
|
||||
|
||||
// 2. Si el vendedor tiene subvendedor padre, restar la utilidad que se le había dado
|
||||
if ($vendedor->subvendedor_id && $utilidad_total > 0) {
|
||||
$subvendedorPadre = User::with('saldo')->find($vendedor->subvendedor_id);
|
||||
if ($subvendedorPadre && $subvendedorPadre->saldo) {
|
||||
$saldoPadre = $subvendedorPadre->saldo->valor - $utilidad_total;
|
||||
$subvendedorPadre->saldo->update(['valor' => max($saldoPadre, 0)]);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Eliminar registros de cuentas asignadas (las libera)
|
||||
Historial_cuenta::where('historial_id', $historial->id)->delete();
|
||||
|
||||
// 4. Eliminar datos de compatibilidad DGO si existen
|
||||
if ($historial->compatibilidadDgo) {
|
||||
$historial->compatibilidadDgo->delete();
|
||||
}
|
||||
|
||||
// 5. Marcar historial como cancelado
|
||||
$historial->estado = 'cancelado';
|
||||
$historial->save();
|
||||
|
||||
// 6. Actualizar logs
|
||||
Log_general::where('historial_id', $historial->id)
|
||||
->where('tipo', 'compra')
|
||||
->update(['tipo' => 'revertida']);
|
||||
|
||||
Log_general::create([
|
||||
'user_id' => auth()->id(),
|
||||
'historial_id' => $historial->id,
|
||||
'tipo' => 'reversion',
|
||||
'detalle' => 'Reversión manual por ' . auth()->user()->name . ' - Historial #' . $historial->id .
|
||||
' - Valor: $' . $total_valor . ' - Vendedor: ' . $vendedor->name .
|
||||
' - Saldo restaurado: $' . $nuevo_saldo,
|
||||
]);
|
||||
|
||||
DB::commit();
|
||||
|
||||
$this->confirmando_id = null;
|
||||
|
||||
$this->alert('success', 'Compra #' . $historial->id . ' revertida correctamente. Saldo restaurado: $' . number_format($total_valor));
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
$this->alert('error', 'Error al revertir: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -180,6 +180,12 @@
|
||||
</svg>
|
||||
<span>Log Cuentas</span>
|
||||
</a>
|
||||
<a href="{{ route('reversar') }}" class="flex items-center gap-2 py-2 px-3 rounded text-white text-left {{ request()->routeIs('reversar') ? 'bg-white/20' : 'hover:bg-white/10' }}">
|
||||
<svg class="w-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182" />
|
||||
</svg>
|
||||
<span>Reversar Compras</span>
|
||||
</a>
|
||||
|
||||
@if (auth()->user()->rol->nombre == 'super')
|
||||
<a href="{{ route('gestion-rangos') }}" class="flex items-center gap-2 py-2 px-3 rounded text-white text-left {{ request()->routeIs('gestion-rangos') ? 'bg-white/20' : 'hover:bg-white/10' }}">
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
<div class="bg-[#f5f5f5] md:w-[100%] m-auto p-2 md:p-5 rounded-[1.2rem] relative mb-4">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h1 class="text-lg font-bold">Reversar Compras</h1>
|
||||
<input type="text" placeholder="Buscar por ID, vendedor, cliente o cuenta..." wire:model.lazy="buscar"
|
||||
class="border-2 border-neutral-200 rounded-[0.8rem] shadow px-4 py-2 w-72 focus:outline-none focus:border-neutral-400">
|
||||
</div>
|
||||
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-sm bg-white rounded-lg shadow-lg">
|
||||
<thead class="bg-[#000029] text-white">
|
||||
<tr class="text-left">
|
||||
<th class="p-3">ID</th>
|
||||
<th class="p-3">Fecha</th>
|
||||
<th class="p-3">Vendedor</th>
|
||||
<th class="p-3">Cliente</th>
|
||||
<th class="p-3">Servicio</th>
|
||||
<th class="p-3">Valor</th>
|
||||
<th class="p-3">Cuentas Asignadas</th>
|
||||
<th class="p-3 text-center">Acción</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse ($historiales as $item)
|
||||
<tr class="border-b hover:bg-gray-100 {{ $confirmando_id === $item->id ? 'bg-red-50' : '' }}">
|
||||
<td class="p-3 font-semibold">#{{ $item->id }}</td>
|
||||
<td class="p-3">{{ \Carbon\Carbon::parse($item->created_at)->format('d/m/Y h:i a') }}</td>
|
||||
<td class="p-3">{{ $item->vendedor->name ?? 'N/A' }}<br><span class="text-xs text-gray-400">{{ $item->vendedor->email ?? '' }}</span></td>
|
||||
<td class="p-3">{{ $item->nombre_cliente ?? $item->cliente->name ?? 'N/A' }}<br><span class="text-xs text-gray-400">{{ $item->cliente->email ?? '' }}</span></td>
|
||||
<td class="p-3">
|
||||
@if ($item->promocion)
|
||||
{{ $item->promocion->nombre ?? 'Promoción' }}
|
||||
@elseif($item->tarifa && $item->tarifa->servicio)
|
||||
{{ $item->tarifa->servicio->nombre }}
|
||||
@if (!$item->tarifa->servicio->por_tiempo)
|
||||
- {{ $item->tarifa->pantallas }}P
|
||||
@endif
|
||||
- {{ $item->tarifa->dias }}d
|
||||
@else
|
||||
N/A
|
||||
@endif
|
||||
</td>
|
||||
<td class="p-3 font-semibold">${{ number_format($item->valor) }}</td>
|
||||
<td class="p-3 text-xs">
|
||||
@forelse ($item->cuentas->unique() as $cuenta)
|
||||
<div class="mb-1">{{ $cuenta->correo }} - {{ $cuenta->password }}</div>
|
||||
@empty
|
||||
<span class="text-gray-400">Sin cuentas</span>
|
||||
@endforelse
|
||||
</td>
|
||||
<td class="p-3 text-center">
|
||||
@if ($confirmando_id === $item->id)
|
||||
<div class="flex flex-col items-center gap-1">
|
||||
<p class="text-red-600 text-xs font-bold">¿Revertir compra #{{ $item->id }}?</p>
|
||||
<p class="text-xs text-gray-500">Se devolverá ${{ number_format($item->valor) }} al vendedor</p>
|
||||
<div class="flex gap-2 mt-1">
|
||||
<button wire:click="reversar({{ $item->id }})"
|
||||
class="px-3 py-1 bg-red-600 text-white rounded text-xs hover:bg-red-700">
|
||||
Sí, revertir
|
||||
</button>
|
||||
<button wire:click="cancelarConfirmacion"
|
||||
class="px-3 py-1 bg-gray-400 text-white rounded text-xs hover:bg-gray-500">
|
||||
Cancelar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<button wire:click="confirmar({{ $item->id }})"
|
||||
class="px-3 py-1 bg-red-500 text-white rounded text-xs hover:bg-red-600">
|
||||
Reversar
|
||||
</button>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="8" class="p-6 text-center text-gray-400">No hay compras activas para mostrar</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
{{ $historiales->links() }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
<x-app-layout>
|
||||
<livewire:reversar-compra />
|
||||
</x-app-layout>
|
||||
@@ -80,6 +80,7 @@ Route::middleware(["auth", "solo_usuario_administrador"])->group(function () {
|
||||
Route::any('/log-general', [MenuController::class, 'showLogGeneral'])->name('logGeneral');
|
||||
Route::any('/log-historial', [MenuController::class, 'showLogHistorial'])->name('logHistorial'); Route::get('/diagnostico', [MenuController::class, 'showDiagnostico'])->name('diagnostico'); Route::get('/utilidades', [MenuController::class, 'showutilidad'])->name('utilidades');
|
||||
Route::get('/mantenimiento', [MenuController::class, 'mantenimiento'])->name('mantenimiento');
|
||||
Route::get('/reversar', [MenuController::class, 'showReversarCompra'])->name('reversar');
|
||||
Route::get('/rank-management', [MenuController::class, 'showgestionrangos'])->name('gestion-rangos');
|
||||
|
||||
// Módulo WhatsApp
|
||||
|
||||
Reference in New Issue
Block a user