Início
NexoPOS

Evento de Campos Disparáveis do Modelo

O evento de campos despacháveis é um conceito que garante o disparo de eventos quando uma propriedade do modelo é alterada. Diferentemente dos eventos regulares do Model, que são despachados quando uma ação específica é realizada (salvar, atualizar, excluir, etc.), aqui temos uma implementação mais profunda que só é acionada se um atributo específico de um modelo tiver sido alterado.

O motivo dessa implementação foi evitar despachar e escutar eventos quando isso não é necessário. Por exemplo, um pedido no NexoPOS pode ser atualizado de várias maneiras. Toda vez que o pedido é atualizado, temos listeners padrão prontos para executar uma ação específica. Não seria melhor, quando o cliente atribuído for alterado, calcular relatórios para os clientes anteriores e recentes? Não seria melhor se pudéssemos notificar o motorista apenas quando o status da entrega passar de “pendente” para “pronto para entrega”? É exatamente para isso que serve este recurso.

Implementação

A implementação dessa funcionalidade consiste apenas em fornecer um array $dispatchableFieldsEvents no modelo em que queremos disparar o evento. Nesse modelo, forneceremos propriedades e eventos relacionados assim:

<?php
namespace Modules\YourModule\Models;

use App\Models\NsModel;
use Modules\YourModule\Events\DeliveryChangedEvent;

class Order extends NsModel
{
    public $dispatchableFieldsEvents  = [
      'delivery_status' =>  DeliveryChangedEvent::class
    ];
}

Agora precisamos definir o evento, pois ele não apenas recebe o modelo como parâmetro, mas também o valor anterior e o novo da propriedade:

<?php
namespace Modules\YourModule\Events;

use App\Models\Order;

class DeliveryChangedEvent
{
    public function __construct( public Order $order, public mixed $previous, public mixed $new )
    {
        // ...
    }
}

A partir daqui, você pode ouvir com segurança este evento do nosso listener de eventos assim:

<?php 
namespace Modules\YourModule\Listeners;

use Modules\YourModule\Events\DeliveryChangedEvent;
use Moduels\YourModules\Services\DriverService;

class DeliveryChangedEventListener
{
    public function __construct( public DriverService $driverService ){
    {
        // ...
    }
      
    public function handle( DeliveryChangedEvent $event )
    {
          if ( $event->previous === 'pending' && $event->new === 'ready-for-delivery' ) {
              $this->driverService->notifyAssignedDriver( $event->order );
          }
    }
}