Feature: Minor Updates to Order Shipping And Order Statuses
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Core\Order\Listeners;
|
||||
|
||||
use Modules\Core\Order\Events\OrderDelivered;
|
||||
|
||||
/**
|
||||
* Writes Order.status to 'completed' once a carrier confirms delivery —
|
||||
* the terminal status a carrier-fulfilled order reaches on its own,
|
||||
* without a human picking it from the dropdown, mirroring the store-pickup
|
||||
* order's own terminal transition (Modules\Core\Shipping\Extensions\
|
||||
* OrderViewExtension::markPickedUpAction()).
|
||||
*
|
||||
* Kept separate from Modules\Core\Order\Listeners\
|
||||
* DeriveOrderDeliveredFromShipment, which only ever dispatches
|
||||
* OrderDelivered — see that event's own docblock ("Order.status itself is
|
||||
* left untouched here") for why deriving "was this delivered" and acting
|
||||
* on it by writing status are deliberately two different listeners, same
|
||||
* separation Modules\Core\Order\Listeners\ApplyResolvedPaymentStatus
|
||||
* already has from the Payment* events it reacts to.
|
||||
*
|
||||
* Guarded to only fire from 'dispatched' — a checkpoint arriving out of
|
||||
* order, or against an order some other status flow has already moved
|
||||
* past, shouldn't silently force it to 'completed'.
|
||||
*/
|
||||
class CompleteOrderOnDelivered
|
||||
{
|
||||
public function handle(OrderDelivered $event): void
|
||||
{
|
||||
if ($event->order->status !== 'dispatched') {
|
||||
return;
|
||||
}
|
||||
|
||||
$event->order->update(['status' => 'completed']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Core\Order\Notifications;
|
||||
|
||||
use Illuminate\Notifications\AnonymousNotifiable;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Support\Facades\Notification as NotificationFacade;
|
||||
use Modules\Core\Notification\BaseNotification;
|
||||
use Modules\Core\Order\Events\OrderStatusUpdated;
|
||||
|
||||
/**
|
||||
* "Your order is ready to collect" — fires on the same OrderStatusUpdated
|
||||
* event Modules\Core\Order\Notifications\OrderStatusUpdatedNotification
|
||||
* listens to, but only for the 'ready-for-pickup' transition; that other
|
||||
* notification suppresses itself for this same transition (see its own
|
||||
* via()) so a customer gets this richer, pickup-specific email instead of
|
||||
* the generic "order updated" one, not both.
|
||||
*/
|
||||
class OrderPickupReadyNotification extends BaseNotification
|
||||
{
|
||||
public function __construct(private readonly OrderStatusUpdated $event) {}
|
||||
|
||||
public static function getKey(): string
|
||||
{
|
||||
return 'order.pickup_ready.customer.mail';
|
||||
}
|
||||
|
||||
public static function listensTo(): string
|
||||
{
|
||||
return OrderStatusUpdated::class;
|
||||
}
|
||||
|
||||
public function via(object $notifiable): array
|
||||
{
|
||||
if ($this->event->newStatus !== 'ready-for-pickup') {
|
||||
return [];
|
||||
}
|
||||
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
public function notifiable(): AnonymousNotifiable
|
||||
{
|
||||
$order = $this->event->order;
|
||||
|
||||
$email = $order->billingAddress?->contact_email ?? $order->shippingAddress?->contact_email;
|
||||
|
||||
return NotificationFacade::route('mail', $email);
|
||||
}
|
||||
|
||||
public function toMail(object $notifiable): MailMessage
|
||||
{
|
||||
$order = $this->event->order;
|
||||
|
||||
return (new MailMessage)
|
||||
->subject(__('Your order :reference is ready for pickup', ['reference' => $order->reference]))
|
||||
->view('core::order.notifications.pickup-ready', [
|
||||
'reference' => $order->reference,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,20 @@ class OrderStatusUpdatedNotification extends BaseNotification
|
||||
return OrderStatusUpdated::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* 'ready-for-pickup' has its own, richer notification
|
||||
* (Modules\Core\Order\Notifications\OrderPickupReadyNotification) —
|
||||
* both listen to the same OrderStatusUpdated event via
|
||||
* NotificationRegistry, so without this the customer would get two
|
||||
* emails for that one transition. Returning no channels is the
|
||||
* standard Laravel way to suppress a notification outright.
|
||||
*/
|
||||
public function via(object $notifiable): array
|
||||
{
|
||||
if ($this->event->newStatus === 'ready-for-pickup') {
|
||||
return [];
|
||||
}
|
||||
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user