Introduce a template-based system for shipment checklists to automate the creation of required inspection items upon shipment approval. - Add `ShipmentChecklistTemplate` model and migration to define reusable checklist structures. - Extend `ShipmentChecklist` schema to support item titles, requirement flags, sorting, and attachment paths. - Implement `instantiateChecklist` in `ShipmentReviewService` to automatically generate checklist items from active templates based on shipment direction (import/export). - Refactor `ShipmentChecklistResource` and `ChecklistsRelationManager` in Filament to support the new data structure and improved UI. - Update `ShipmentChecklist` model with helper methods for completion tracking and improved relationship handling.
197 lines
7.1 KiB
PHP
197 lines
7.1 KiB
PHP
<?php
|
||
|
||
namespace App\Filament\Resources;
|
||
|
||
use App\Filament\Resources\ShipmentChecklistResource\Pages;
|
||
use App\Models\ShipmentChecklist;
|
||
use Filament\Forms;
|
||
use Filament\Forms\Form;
|
||
use Filament\Notifications\Notification;
|
||
use Filament\Resources\Resource;
|
||
use Filament\Tables;
|
||
use Filament\Tables\Table;
|
||
use Filament\Tables\Actions\Action;
|
||
|
||
/**
|
||
* چکلیست سفارشات — نمای گزارش (reporting).
|
||
* instanceها هنگام approve سفارش از قالبها خودکار ساخته میشوند.
|
||
*/
|
||
class ShipmentChecklistResource extends Resource
|
||
{
|
||
protected static ?string $model = ShipmentChecklist::class;
|
||
protected static ?string $navigationIcon = 'heroicon-o-clipboard-document-check';
|
||
protected static ?string $navigationGroup = 'عملیات';
|
||
protected static ?string $navigationLabel = 'چکلیست سفارشات';
|
||
protected static ?string $modelLabel = 'آیتم چکلیست';
|
||
protected static ?string $pluralModelLabel = 'چکلیست سفارشات';
|
||
protected static ?int $navigationSort = 2;
|
||
|
||
public static function form(Form $form): Form
|
||
{
|
||
return $form->schema([
|
||
Forms\Components\Section::make('اطلاعات آیتم')->schema([
|
||
Forms\Components\TextInput::make('item_title')
|
||
->label('عنوان آیتم')
|
||
->disabled(),
|
||
|
||
Forms\Components\Select::make('shipment_id')
|
||
->label('سفارش')
|
||
->relationship('shipment', 'awb_no')
|
||
->disabled(),
|
||
|
||
Forms\Components\Toggle::make('is_required')
|
||
->label('الزامی')
|
||
->disabled(),
|
||
|
||
Forms\Components\Toggle::make('is_completed')
|
||
->label('تکمیل شده')
|
||
->disabled(),
|
||
|
||
Forms\Components\Textarea::make('notes')
|
||
->label('یادداشتها')
|
||
->rows(3)
|
||
->columnSpanFull(),
|
||
|
||
Forms\Components\TextInput::make('attachment')
|
||
->label('پیوست (مسیر فایل)')
|
||
->maxLength(255),
|
||
])->columns(2),
|
||
]);
|
||
}
|
||
|
||
public static function table(Table $table): Table
|
||
{
|
||
return $table
|
||
->columns([
|
||
Tables\Columns\TextColumn::make('shipment.awb_no')
|
||
->label('شماره سفارش')
|
||
->searchable()
|
||
->sortable(),
|
||
|
||
Tables\Columns\TextColumn::make('item_title')
|
||
->label('آیتم')
|
||
->searchable()
|
||
->weight('bold'),
|
||
|
||
Tables\Columns\IconColumn::make('is_required')
|
||
->label('الزامی')
|
||
->boolean()
|
||
->trueIcon('heroicon-o-exclamation-circle')
|
||
->falseIcon('heroicon-o-minus-circle')
|
||
->trueColor('danger')
|
||
->falseColor('gray'),
|
||
|
||
Tables\Columns\IconColumn::make('is_completed')
|
||
->label('تکمیل')
|
||
->boolean()
|
||
->trueIcon('heroicon-o-check-circle')
|
||
->falseIcon('heroicon-o-x-circle')
|
||
->trueColor('success')
|
||
->falseColor('danger'),
|
||
|
||
Tables\Columns\TextColumn::make('completedBy.name')
|
||
->label('انجامدهنده')
|
||
->toggleable(),
|
||
|
||
Tables\Columns\TextColumn::make('completed_at')
|
||
->label('تاریخ تکمیل')
|
||
->dateTime('Y/m/d H:i')
|
||
->sortable()
|
||
->toggleable(),
|
||
|
||
Tables\Columns\TextColumn::make('notes')
|
||
->label('یادداشت')
|
||
->limit(40)
|
||
->toggleable(),
|
||
])
|
||
->defaultSort('is_completed', 'asc') // ناقصها اول
|
||
->filters([
|
||
Tables\Filters\TernaryFilter::make('is_completed')
|
||
->label('تکمیل')
|
||
->placeholder('همه')
|
||
->trueLabel('تکمیلشده')
|
||
->falseLabel('ناقص'),
|
||
|
||
Tables\Filters\TernaryFilter::make('is_required')
|
||
->label('الزامی')
|
||
->placeholder('همه')
|
||
->trueLabel('الزامی')
|
||
->falseLabel('اختیاری'),
|
||
])
|
||
->actions([
|
||
Action::make('complete')
|
||
->label('تکمیل')
|
||
->icon('heroicon-o-check-circle')
|
||
->color('success')
|
||
->visible(fn ($record) => !$record->is_completed)
|
||
->form([
|
||
Forms\Components\Textarea::make('note')
|
||
->label('یادداشت (اختیاری)')
|
||
->rows(2),
|
||
])
|
||
->action(function ($record, array $data) {
|
||
$record->complete(auth()->id(), $data['note'] ?? null);
|
||
Notification::make()->title('آیتم تکمیل شد')->success()->send();
|
||
}),
|
||
|
||
Tables\Actions\ViewAction::make(),
|
||
Tables\Actions\EditAction::make()
|
||
->visible(fn () => auth()->user()?->hasRole('super_admin')),
|
||
])
|
||
->bulkActions([
|
||
Tables\Actions\BulkActionGroup::make([
|
||
Tables\Actions\DeleteBulkAction::make()
|
||
->visible(fn () => auth()->user()?->hasRole('super_admin')),
|
||
]),
|
||
]);
|
||
}
|
||
|
||
public static function getRelations(): array
|
||
{
|
||
return [];
|
||
}
|
||
|
||
public static function getPages(): array
|
||
{
|
||
return [
|
||
'index' => Pages\ListShipmentChecklists::route('/'),
|
||
'view' => Pages\ViewShipmentChecklist::route('/{record}'),
|
||
'edit' => Pages\EditShipmentChecklist::route('/{record}/edit'),
|
||
];
|
||
}
|
||
|
||
public static function canViewAny(): bool
|
||
{
|
||
return auth()->user()?->hasAnyRole(['super_admin', 'admin', 'staff']) ?? false;
|
||
}
|
||
|
||
public static function canCreate(): bool
|
||
{
|
||
// instanceها خودکار از قالب ساخته میشوند
|
||
return false;
|
||
}
|
||
|
||
public static function canEdit($record): bool
|
||
{
|
||
return auth()->user()?->hasRole('super_admin') ?? false;
|
||
}
|
||
|
||
public static function canDelete($record): bool
|
||
{
|
||
return auth()->user()?->hasRole('super_admin') ?? false;
|
||
}
|
||
|
||
/**
|
||
* badge: تعداد آیتمهای الزامیِ ناقص (نشانگر سفارشهای مشکلدار).
|
||
*/
|
||
public static function getNavigationBadge(): ?string
|
||
{
|
||
$count = static::getModel()::where('is_completed', false)->where('is_required', true)->count();
|
||
return $count > 0 ? (string) $count : null;
|
||
}
|
||
|
||
public static function getNavigationBadgeColor(): ?string
|
||
{
|
||
return 'danger';
|
||
}
|
||
} |