Feature: Minor Updates to Order Shipping And Order Statuses

This commit is contained in:
2026-09-10 22:50:40 +03:00
parent 99e55902ac
commit 78bbd8390a
8 changed files with 207 additions and 5 deletions
+33 -1
View File
@@ -21,6 +21,7 @@ class OrderViewExtension extends ViewPageExtension
public function headerActions(array $actions): array
{
$actions[] = $this->createShipmentAction();
$actions[] = $this->markPickedUpAction();
return $actions;
}
@@ -93,10 +94,41 @@ class OrderViewExtension extends ViewPageExtension
->success()
->send();
})
->visible(fn (Order $record) => $record->shipments()->exists() === false
->visible(fn (Order $record) => $record->status === 'ready-for-dispatch'
&& ! $record->isStorePickupOrder()
&& $record->shipments()->exists() === false
&& $this->resolveFulfillmentService($record) !== null);
}
/**
* The store-pickup mirror of createShipmentAction() — a store-pickup
* order never gets a Shipment record (no carrier is ever involved), so
* it needs its own way to close out of 'ready-for-pickup' once the
* customer has actually collected it. Sets status directly to
* 'completed', same terminal status DeriveOrderDeliveredFromShipment
* writes for a carrier order once tracking confirms delivery — see
* that listener's own docblock.
*/
private function markPickedUpAction(): Action
{
return Action::make('mark_picked_up')
->label('Mark Picked Up')
->icon('heroicon-o-check-circle')
->color('success')
->requiresConfirmation()
->modalDescription('Confirms the customer has collected this order in store.')
->action(function (Order $record) {
$record->update(['status' => 'completed']);
Notification::make()
->title('Order marked as picked up.')
->success()
->send();
})
->visible(fn (Order $record) => $record->status === 'ready-for-pickup'
&& $record->isStorePickupOrder());
}
private function resolveCarrier(Order $record): ?string
{
$code = $record->shippingAddress?->shipping_option;
@@ -18,11 +18,41 @@ class ShippingMethodResourceExtension extends ResourceExtension
{
public function extendForm(Schema $schema): Schema
{
return $schema->components(
$this->replaceChargeByField(
return $schema->components([
...$this->replaceChargeByField(
$this->replaceDriverField($schema->getComponents())
)
);
),
$this->fulfillmentTypeSelect(),
]);
}
/**
* ShippingMethod.data['fulfillment_type'] — 'carrier' (default) or
* 'store_pickup'. Same free-form-`data`-column pattern as charge_by
* above, not a migrated column: ShippingMethod is a vendor
* (lunarphp/table-rate-shipping) table, and this codebase avoids
* forking vendor migrations for a merchant-configurable extra (see
* PaymentMethod.data.fee for the same convention on a different
* vendor-adjacent model).
*
* What this actually gates: Modules\Core\Shipping\Extensions\
* OrderViewExtension's "Create Shipment" action only makes sense for
* a 'carrier' method (it books a real carrier voucher) — a
* 'store_pickup' order instead moves through Order.status
* 'ready-for-pickup' -> a staff "Mark Picked Up" action, no shipment
* ever created. See docs/checkout.md for the full status-flow design.
*/
private function fulfillmentTypeSelect(): Select
{
return Select::make('data.fulfillment_type')
->label('Fulfillment type')
->options([
'carrier' => 'Carrier delivery',
'store_pickup' => 'Collect in store',
])
->default('carrier')
->required()
->helperText('Whether an order using this method is handed to a carrier, or collected by the customer in person.');
}
/**