Files
pos_heidiver/app/Console/Commands/VerificarAlertasStock.php
T
2026-01-06 15:35:59 -05:00

153 lines
5.4 KiB
PHP

<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Mail;
use App\Mail\AlertaStockMail;
use App\Models\User;
use App\Models\Producto;
class VerificarAlertasStock extends Command
{
protected $signature = 'stock:verificar-alertas {--email= : Email específico para enviar la alerta}';
protected $description = 'Verificar niveles de stock y enviar alertas por correo cuando se alcance el mínimo o máximo';
public function handle()
{
$this->info('🔍 Iniciando verificación de niveles de stock...');
// Obtener productos con stock mínimo o inferior
$productosStockMinimo = $this->obtenerProductosStockMinimo();
// Obtener productos que exceden el stock máximo
$productosStockMaximo = $this->obtenerProductosStockMaximo();
if ($productosStockMinimo->isEmpty() && $productosStockMaximo->isEmpty()) {
$this->info('✅ Todos los productos están en niveles normales de stock.');
return Command::SUCCESS;
}
// Mostrar resumen en consola
$this->mostrarResumen($productosStockMinimo, $productosStockMaximo);
// Enviar alertas por correo
$this->enviarAlertas($productosStockMinimo, $productosStockMaximo);
return Command::SUCCESS;
}
private function obtenerProductosStockMinimo()
{
return Producto::with(['categoria', 'variants', 'bodegas'])
->where('estado', true)
->get()
->filter(function ($producto) {
// Usar el método getStockEfectivo que considera bodegas
$stockActual = $producto->getStockEfectivo();
return $stockActual <= $producto->stock_minimo;
});
}
private function obtenerProductosStockMaximo()
{
return Producto::with(['categoria', 'variants', 'bodegas'])
->where('estado', true)
->whereNotNull('stock_maximo')
->get()
->filter(function ($producto) {
// Usar el método getStockEfectivo que considera bodegas
$stockActual = $producto->getStockEfectivo();
return $stockActual > $producto->stock_maximo;
});
}
private function mostrarResumen($productosStockMinimo, $productosStockMaximo)
{
if ($productosStockMinimo->isNotEmpty()) {
$this->warn("⚠️ {$productosStockMinimo->count()} productos con stock mínimo o inferior:");
$headers = ['Producto', 'Stock Actual', 'Stock Mínimo', 'Estado'];
$rows = [];
foreach ($productosStockMinimo as $producto) {
$stockActual = $producto->getStockEfectivo();
$estado = $stockActual == 0 ? 'Sin Stock' : ($stockActual < $producto->stock_minimo ? 'Por debajo' : 'En mínimo');
$rows[] = [
$producto->nombre,
$stockActual,
$producto->stock_minimo,
$estado
];
}
$this->table($headers, $rows);
}
if ($productosStockMaximo->isNotEmpty()) {
$this->info("📈 {$productosStockMaximo->count()} productos que exceden el stock máximo:");
$headers = ['Producto', 'Stock Actual', 'Stock Máximo', 'Exceso'];
$rows = [];
foreach ($productosStockMaximo as $producto) {
$stockActual = $producto->getStockEfectivo();
$exceso = $stockActual - $producto->stock_maximo;
$rows[] = [
$producto->nombre,
$stockActual,
$producto->stock_maximo,
"+{$exceso}"
];
}
$this->table($headers, $rows);
}
}
private function enviarAlertas($productosStockMinimo, $productosStockMaximo)
{
// Determinar destinatarios
$email = $this->option('email');
if ($email) {
$destinatarios = collect([$email]);
$this->info("📧 Enviando alerta a email específico: {$email}");
} else {
// Obtener administradores
$administradores = User::role('Administrador')->get();
if ($administradores->isEmpty()) {
$this->warn('⚠️ No se encontraron usuarios con el rol Administrador.');
return;
}
$destinatarios = $administradores->pluck('email');
$this->info("📧 Enviando alertas a {$administradores->count()} administradores...");
}
// Enviar correos
foreach ($destinatarios as $emailDestino) {
try {
Mail::to($emailDestino)->send(new AlertaStockMail(
$productosStockMinimo,
$productosStockMaximo,
$emailDestino
));
$this->info("✅ Alerta enviada a: {$emailDestino}");
} catch (\Exception $e) {
$this->error("❌ Error al enviar a {$emailDestino}: " . $e->getMessage());
}
}
$this->info('🎉 Proceso de envío de alertas completado.');
}
}