up
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
<?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.');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user