Feature: Order Updates, Events, Order Flows, Shipment And COD support
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Core\Order\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Lunar\Models\Order;
|
||||
use Modules\Core\Order\Events\OrderCompleted;
|
||||
use Modules\Core\Order\Services\OrderStatusWriter;
|
||||
|
||||
/**
|
||||
* Auto-completes a carrier order once its 14-day return window has
|
||||
* elapsed with no return requested — the automatic counterpart to the
|
||||
* staff "Update Status" action's manual completion. Store-pickup orders
|
||||
* have no return-window step at all (Modules\Core\Order\Listeners\
|
||||
* CompleteOrderOnPickedUp completes them immediately), so this only ever
|
||||
* touches carrier orders sitting in 'delivered' (the status also carrying
|
||||
* "return window is open" — see AdvanceFulfillmentOnDelivered).
|
||||
*
|
||||
* Registered at exactly dailyAt('00:00') in
|
||||
* Modules\Core\Providers\OrderServiceProvider — a compliance requirement
|
||||
* that this run at exact midnight, not Laravel's own arbitrary default
|
||||
* time for a plain daily() schedule.
|
||||
*
|
||||
* "When did the window open" is read from order_status_transitions rather
|
||||
* than Order::updated_at, which any unrelated field write would bump —
|
||||
* this is the concrete reason the audit table exists beyond pure logging.
|
||||
*
|
||||
* Window length is config('core.order.return_window_days') — a legal/
|
||||
* policy value a store may need to change without a code deploy, not a
|
||||
* hardcoded constant.
|
||||
*/
|
||||
class CloseExpiredReturnWindows extends Command
|
||||
{
|
||||
protected $signature = 'boboko:order:close-expired-return-windows';
|
||||
|
||||
protected $description = 'Auto-complete carrier orders whose return window has elapsed with no return requested.';
|
||||
|
||||
public function handle(OrderStatusWriter $writer): void
|
||||
{
|
||||
$cutoff = now()->subDays(config('core.order.return_window_days', 14));
|
||||
|
||||
$orderIds = Order::query()
|
||||
->where('status', 'delivered')
|
||||
->whereHas('statusTransitions', function ($query) use ($cutoff) {
|
||||
$query->where('to_status', 'delivered')
|
||||
->where('created_at', '<=', $cutoff);
|
||||
})
|
||||
->pluck('id');
|
||||
|
||||
$completed = 0;
|
||||
|
||||
foreach ($orderIds as $orderId) {
|
||||
$order = Order::find($orderId);
|
||||
|
||||
if (! $order || $order->status !== 'delivered') {
|
||||
continue; // idempotent no-op — moved on since the query ran
|
||||
}
|
||||
|
||||
$writer->write($order, 'completed', self::class);
|
||||
|
||||
OrderCompleted::dispatch($order);
|
||||
|
||||
$completed++;
|
||||
}
|
||||
|
||||
$this->components->info("Completed {$completed} order(s) past their return window.");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user