OrderStatus::payment($this)); Order::macro('fulfillmentStatus', fn () => OrderStatus::fulfillment($this)); Order::resolveRelationUsing('statusTransitions', function ($order) { return $order->hasMany(OrderStatusTransition::class); }); Event::listen(ShipmentStatusUpdatedByCarrier::class, DeriveOrderDeliveredFromShipment::class); Event::listen(ShipmentStatusUpdatedByCarrier::class, AdvanceFulfillmentOnCarrierCheckpoint::class); Event::listen(ShipmentStatusUpdatedByCarrier::class, MarkDeliveryFailedOnCarrierCheckpoint::class); Event::listen(OrderDelivered::class, AdvanceFulfillmentOnDelivered::class); Event::listen(OrderPickedUp::class, CompleteOrderOnPickedUp::class); Event::listen(PaymentCaptured::class, ApplyResolvedPaymentStatus::class); Event::listen(PaymentAuthorized::class, ApplyResolvedPaymentStatus::class); Event::listen(PaymentCaptured::class, RecordPaymentTransaction::class); Event::listen(PaymentAuthorized::class, RecordPaymentTransaction::class); Event::listen(PaymentVoided::class, RecordPaymentTransaction::class); // RecordPaymentTransaction must run before ApplyResolvedPaymentStatus // for PaymentRefunded specifically — the latter now reads // $order->transactions (via OrderStatus::payment()) to resolve // Refunded vs PartiallyRefunded, which requires the refund // Transaction row to already exist. Event::listen(PaymentRefunded::class, RecordPaymentTransaction::class); Event::listen(PaymentRefunded::class, ApplyResolvedPaymentStatus::class); Event::listen(PaymentDeferred::class, MarkOrderPlacedOnDeferredPayment::class); Event::listen(OrderPlaced::class, DecrementStockOnOrderPlaced::class); Event::listen(OrderStatusChanged::class, [RecordStatusTransition::class, 'handleStatusChanged']); Event::listen(OrderPaidChanged::class, [RecordStatusTransition::class, 'handlePaidChanged']); NotificationRegistry::get()->register([ OrderDeliveredNotification::class, OrderStatusUpdatedNotification::class, OrderRefundedNotification::class, OrderCapturedNotification::class, OrderPlacedNotification::class, OrderPickupReadyNotification::class, OrderDispatchedNotification::class, OrderCompletedNotification::class, ]); // Lets the consuming app override copy/markup without forking core // — published into resources/views/vendor/core/order/notifications, // which loadViewsFrom() (CoreServiceProvider) already resolves // ahead of the package's own views for the `core::` namespace. $this->publishes([ __DIR__ . '/../../resources/views/order/notifications' => resource_path('views/vendor/core/order/notifications'), ], 'core-views'); if ($this->app->runningInConsole()) { $this->commands([CloseExpiredReturnWindows::class]); } // Exact midnight per an explicit compliance requirement — not a // loose dailyAt() offset or plain daily(). $this->app->booted(function () { $this->app->make(ConsoleSchedule::class) ->command(CloseExpiredReturnWindows::class) ->dailyAt('00:00'); }); } }