124 lines
4.7 KiB
PHP
124 lines
4.7 KiB
PHP
<?php
|
|
|
|
namespace Modules\Core\Shipping\Filament\Pages;
|
|
|
|
use Filament\Actions\Action;
|
|
use Filament\Actions\BulkAction;
|
|
use Filament\Notifications\Notification;
|
|
use Filament\Pages\Page;
|
|
use Filament\Tables\Columns\TextColumn;
|
|
use Filament\Tables\Concerns\InteractsWithTable;
|
|
use Filament\Tables\Contracts\HasTable;
|
|
use Filament\Tables\Table;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Support\Collection;
|
|
use Lunar\Shipping\Facades\Shipping;
|
|
use Modules\Core\Shipping\Contracts\CarrierFulfillmentInterface;
|
|
use Modules\Core\Shipping\Contracts\SupportsManifestBatching;
|
|
use Modules\Core\Shipping\Models\Shipment;
|
|
|
|
class ManagePickupManifests extends Page implements HasTable
|
|
{
|
|
use InteractsWithTable;
|
|
|
|
protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-truck';
|
|
|
|
protected static ?string $navigationLabel = 'Pickup Manifests';
|
|
|
|
/**
|
|
* Without an explicit group, this page had no navigation group at all —
|
|
* Filament's Panel::getUrl() falls back to "first item in the first
|
|
* navigation group" when no homeUrl is set (neither Lunar nor CorePlugin
|
|
* sets one), and an ungrouped page sorted ahead of every one of Lunar's
|
|
* own grouped resources (Sales, Catalog, etc.), making this page the
|
|
* panel's de facto home instead of the real Dashboard. Grouping it under
|
|
* Sales — alongside CartResource, OrderResource — fixes that by letting
|
|
* a legitimate item sort first again. Sorted last within the group
|
|
* deliberately (a high explicit navigationSort — Lunar's own
|
|
* OrderResource uses 1) so this page never competes to be first even as
|
|
* more Sales-group items are added later.
|
|
*/
|
|
protected static string | \UnitEnum | null $navigationGroup = 'Sales';
|
|
|
|
protected static ?int $navigationSort = 100;
|
|
|
|
protected string $view = 'core::shipping.filament.pages.manage-pickup-manifests';
|
|
|
|
public function table(Table $table): Table
|
|
{
|
|
return $table
|
|
->query($this->pendingQuery())
|
|
->columns([
|
|
TextColumn::make('carrier')->badge(),
|
|
TextColumn::make('tracking_reference')->label('Tracking #'),
|
|
TextColumn::make('order.reference')->label('Order'),
|
|
TextColumn::make('label_printed_at')->label('Printed')->dateTime()->placeholder('Not printed'),
|
|
])
|
|
->recordActions([
|
|
Action::make('print')
|
|
->label('Print')
|
|
->icon('heroicon-o-printer')
|
|
->action(fn (Shipment $record) => $this->printShipment($record)),
|
|
])
|
|
->toolbarActions([
|
|
BulkAction::make('print_selected')
|
|
->label('Print selected')
|
|
->icon('heroicon-o-printer')
|
|
->action(fn (Collection $records) => $records->each(fn (Shipment $shipment) => $this->printShipment($shipment))),
|
|
BulkAction::make('issue_manifest')
|
|
->label('Issue Manifest')
|
|
->icon('heroicon-o-check-circle')
|
|
->action(fn (Collection $records) => $this->issueManifest($records)),
|
|
]);
|
|
}
|
|
|
|
private function pendingQuery(): Builder
|
|
{
|
|
$carriers = collect(Shipping::getSupportedDrivers())->keys()->filter(
|
|
fn (string $carrier) => $this->fulfillmentService($carrier) instanceof SupportsManifestBatching
|
|
);
|
|
|
|
return Shipment::query()
|
|
->whereIn('carrier', $carriers)
|
|
->whereNull('manifest_reference')
|
|
->whereNull('cancelled_at');
|
|
}
|
|
|
|
private function printShipment(Shipment $shipment): void
|
|
{
|
|
$this->fulfillmentService($shipment->carrier)?->printLabel($shipment);
|
|
}
|
|
|
|
private function issueManifest(Collection $shipments): void
|
|
{
|
|
$shipments->groupBy('carrier')->each(function (Collection $group, string $carrier) {
|
|
$service = $this->fulfillmentService($carrier);
|
|
|
|
if (! $service instanceof SupportsManifestBatching) {
|
|
return;
|
|
}
|
|
|
|
$result = $service->issueManifest($group);
|
|
|
|
if (! $result->success) {
|
|
Notification::make()
|
|
->title("Manifest blocked for {$carrier}: {$result->reason}")
|
|
->danger()
|
|
->send();
|
|
|
|
return;
|
|
}
|
|
|
|
Notification::make()
|
|
->title("Manifest issued for {$carrier}: {$result->reference}")
|
|
->success()
|
|
->send();
|
|
});
|
|
}
|
|
|
|
private function fulfillmentService(string $carrier): ?CarrierFulfillmentInterface
|
|
{
|
|
return app(CarrierFulfillmentInterface::class, ['carrier' => $carrier]);
|
|
}
|
|
}
|