pdv.backend/app/Observers/InventoryWarehouseObserver.php

70 lines
2.3 KiB
PHP

<?php namespace App\Observers;
/**
* @copyright (c) 2025 Notsoweb Software (https://notsoweb.com) - All Rights Reserved
*/
use App\Models\InventoryWarehouse;
use App\Models\User;
use App\Notifications\UserNotification;
/**
* Observer de stock por almacén
*
* Envía notificación a administradores cuando el stock de un producto
* cruza el umbral mínimo (de disponible a bajo stock).
*
* @author Moisés Cortés C. <moises.cortes@notsoweb.com>
*
* @version 1.0.0
*/
class InventoryWarehouseObserver
{
/**
* Roles que reciben alertas de stock bajo
*/
protected array $notifiableRoles = ['developer', 'admin'];
/**
* Umbral por defecto cuando min_stock no está configurado
*/
protected int $defaultThreshold = 5;
/**
* Detectar cuando el stock cruza el umbral mínimo hacia abajo
*/
public function updated(InventoryWarehouse $inventoryWarehouse): void
{
$previousStock = (float) $inventoryWarehouse->getOriginal('stock');
$currentStock = (float) $inventoryWarehouse->stock;
$threshold = (float) ($inventoryWarehouse->min_stock ?? $this->defaultThreshold);
// Solo notificar si el stock CRUZÓ el umbral (no en cada update mientras ya esté bajo)
if ($previousStock >= $threshold && $currentStock < $threshold) {
$this->notifyLowStock($inventoryWarehouse, $currentStock);
}
}
/**
* Enviar notificación de stock bajo a usuarios con rol relevante
*/
protected function notifyLowStock(InventoryWarehouse $inventoryWarehouse, float $currentStock): void
{
$inventoryWarehouse->load('inventory', 'warehouse');
$productName = $inventoryWarehouse->inventory?->name ?? 'Producto desconocido';
$warehouseName = $inventoryWarehouse->warehouse?->name ?? 'Almacén desconocido';
$users = User::role($this->notifiableRoles)->get();
foreach ($users as $user) {
$user->notify(new UserNotification(
title: 'Stock bajo: ' . $productName,
description: "El producto \"{$productName}\" tiene {$currentStock} unidad(es) disponible(s) en \"{$warehouseName}\".",
type: 'warning',
timeout: 30,
save: true,
));
}
}
}