From 232befdf8ff0bdc756dcc5509378a1fb5210da84 Mon Sep 17 00:00:00 2001 From: dhanabalan Date: Mon, 24 Nov 2025 09:27:56 +0530 Subject: [PATCH] added filter logic and upload part validation image --- .../Resources/StickerMasterResource.php | 313 +++++++++++++++++- 1 file changed, 311 insertions(+), 2 deletions(-) diff --git a/app/Filament/Resources/StickerMasterResource.php b/app/Filament/Resources/StickerMasterResource.php index 9e2a64b..66b20ac 100644 --- a/app/Filament/Resources/StickerMasterResource.php +++ b/app/Filament/Resources/StickerMasterResource.php @@ -6,12 +6,14 @@ use App\Filament\Exports\StickerMasterExporter; //use App\Filament\Imports\ShiftImporter; use App\Filament\Imports\StickerMasterImporter; use App\Filament\Resources\StickerMasterResource\Pages; +use App\Models\Item; use App\Models\Plant; //use App\Filament\Resources\StickerMasterResource\RelationManagers; use App\Models\StickerMaster; //use Closure; use Filament\Facades\Filament; use Filament\Forms; +use Filament\Forms\Components\Select; use Filament\Forms\Form; use Filament\Resources\Resource; use Filament\Tables; @@ -22,6 +24,15 @@ use Filament\Forms\Get; use Filament\Forms\Set; use Filament\Tables\Actions\ExportAction; use Filament\Tables\Actions\ImportAction; +use Illuminate\Support\Facades\Storage; +use Filament\Forms\Components\FileUpload; +use Filament\Notifications\Notification; +use Filament\Forms\Components\DateTimePicker; +use Filament\Forms\Components\Radio; +use Filament\Forms\Components\TextInput; +use Filament\Tables\Filters\Filter; +use App\Models\InvoiceValidation; + // use Illuminate\Validation\Rule; class StickerMasterResource extends Resource @@ -593,9 +604,131 @@ class StickerMasterResource extends Resource ->sortable() ->toggleable(isToggledHiddenByDefault: true), ]) + // ->filters([ + // Tables\Filters\TrashedFilter::make(), + // ]) ->filters([ - Tables\Filters\TrashedFilter::make(), - ]) + Tables\Filters\TrashedFilter::make(), + Filter::make('advanced_filters') + ->label('Advanced Filters') + ->form([ + Select::make('Plant') + ->label('Select Plant') + ->nullable() + ->options(function (callable $get) { + $userHas = Filament::auth()->user()->plant_id; + return ($userHas && strlen($userHas) > 0) ? Plant::where('id', $userHas)->pluck('name', 'id')->toArray() : Plant::pluck('name', 'id')->toArray(); + }) + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get): void { + $set('item_id', null); + $set('operator_id', null); + }), + Select::make('item_id') + ->label('Search by Item Code') + ->nullable() + // ->options(function (callable $get) { + // $plantId = $get('Plant'); + // return $plantId + // ? Item::where('plant_id', $plantId)->pluck('code', 'id') + // : Item::pluck('code', 'id'); + // }) + ->options(function (callable $get) { + $plantId = $get('Plant'); + return $plantId + ? Item::where('plant_id', $plantId)->pluck('code', 'id') + : []; + }) + ->searchable() + ->reactive(), + Select::make('material_type') + ->label('Material Type') + ->options([ + 1 => 'Individual', + 2 => 'Bundle', + 3 => 'Quantity', + ]) + ->reactive(), + + TextInput::make('panel_box_code') + ->label('Panel Box Code') + ->placeholder(placeholder: 'Enter Panel Box Code'), + DateTimePicker::make(name: 'created_from') + ->label('Created From') + ->placeholder(placeholder: 'Select From DateTime') + ->reactive() + ->native(false), + DateTimePicker::make('created_to') + ->label('Created To') + ->placeholder(placeholder: 'Select To DateTime') + ->reactive() + ->native(false), + ]) + ->query(function ($query, array $data) { + // Hide all records initially if no filters are applied + if ( + empty($data['material_type']) && + empty($data['Plant']) && + empty($data['item_id']) && + empty($data['panel_box_code']) && + empty($data['created_from']) && + empty($data['created_to']) + ) { + return $query->whereRaw('1 = 0'); + } + + if (!empty($data['Plant'])) { //$plant = $data['Plant'] ?? null + $query->where('plant_id', $data['Plant']); + } + + if (!empty($data['item_id'])) { + $query->where('item_id', $data['item_id']); + } + + if (!empty($data['material_type'])) { + $query->where('material_type', $data['material_type']); + } + + if (!empty($data['panel_box_code'])) { + $query->where('panel_box_code', 'like', '%' . $data['panel_box_code'] . '%'); + } + + if (!empty($data['created_from'])) { + $query->where('created_at', '>=', $data['created_from']); + } + + if (!empty($data['created_to'])) { + $query->where('created_at', '<=', $data['created_to']); + } + + }) + ->indicateUsing(function (array $data) { + $indicators = []; + + if (!empty($data['Plant'])) { + $indicators[] = 'Plant: ' . Plant::where('id', $data['Plant'])->value('name'); + } + + if (!empty($data['item_id'])) { + $indicators[] = 'Item Code: ' . $data['item_id']; + } + + if (!empty($data['panel_box_code'])) { + $indicators[] = 'Panel Box Code: ' . $data['panel_box_code']; + } + + if (!empty($data['created_from'])) { + $indicators[] = 'From: ' . $data['created_from']; + } + + if (!empty($data['created_to'])) { + $indicators[] = 'To: ' . $data['created_to']; + } + + return $indicators; + }) + ]) + ->filtersFormMaxHeight('280px') ->actions([ Tables\Actions\ViewAction::make(), Tables\Actions\EditAction::make(), @@ -608,6 +741,182 @@ class StickerMasterResource extends Resource ]), ]) ->headerActions([ + Tables\Actions\Action::make('upload_part_validation_image') + ->label('Upload Part Validation Image') + ->form([ + Select::make('plant_id') + ->options(function (callable $get) { + $userHas = Filament::auth()->user()->plant_id; + return ($userHas && strlen($userHas) > 0) ? Plant::where('id', $userHas)->pluck('name', 'id')->toArray() : Plant::pluck('name', 'id')->toArray(); + }) + ->label('Select Plant') + ->required() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $set('item_id', null); + $set('part_validation_upload', null); + }) + ->reactive(), + Select::make('item_id') + ->options(function (callable $get) { + $plantId = $get('plant_id'); + + if (!$plantId) { + return []; + } + + return StickerMaster::where('plant_id', $plantId) + ->where(function ($q) { + $q->whereNotNull('part_validation1') + ->orWhereNotNull('part_validation2') + ->orWhereNotNull('part_validation3') + ->orWhereNotNull('part_validation4'); + }) + ->with('item') + ->get() + ->pluck('item.code', 'item_id') + ->toArray(); + }) + ->label('Item Code') + ->required() + ->searchable() + ->afterStateUpdated(fn ($state, callable $set) => $set('part_validation_upload', null)) + ->reactive(), + + Select::make('validation_type') + ->label('Select Validation') + ->options(function (callable $get) { + + $plantId = $get('plant_id'); + $itemId = $get('item_id'); + + if (!$plantId || !$itemId) { + return []; + } + + $sticker = StickerMaster::where('plant_id', $plantId) + ->where('item_id', $itemId) + ->first(); + + if (!$sticker) { + return []; + } + + $options = []; + + if (!empty($sticker->part_validation1)) { + $options['part_validation1'] = 'Part Validation 1'; + } + + if (!empty($sticker->part_validation2)) { + $options['part_validation2'] = 'Part Validation 2'; + } + + if (!empty($sticker->part_validation3)) { + $options['part_validation3'] = 'Part Validation 3'; + } + + if (!empty($sticker->part_validation4)) { + $options['part_validation4'] = 'Part Validation 4'; + } + + // if (!empty($sticker->part_validation5)) { + // $options['part_validation5'] = 'Part Validation 5'; + // } + + return $options; + }) + ->reactive() + ->required(), + + FileUpload::make('part_validation_upload') + ->label('Part Validation Upload') + // ->required() + ->preserveFilenames() // <- this keeps the original filename + ->storeFiles(false) // prevent auto-storing, we will store manually + ->reactive() + ->required() + ->disk('local') //'local' refers to the local storage disk defined in config/filesystems.php, typically pointing to storage/app. + ->visible(fn (Get $get) => !empty($get('plant_id'))) + ->directory('uploads/PartValidation'), + ]) + ->action(function (array $data) { + $uploadedFile = $data['part_validation_upload']; + $plantId = $data['plant_id']; + $itemId = $data['item_id']; + $column = $data['validation_type']; + + $plant = Plant::find($plantId); + + $plantCode = $plant->code; + + $sticker = StickerMaster::where('plant_id', $plantId) + ->where('item_id', $itemId) + ->first(); + + if (!$sticker) { + Notification::make() + ->title('Unknown Sticker Master') + ->body("Sticker Master data not found.") + ->danger() + ->seconds(2) + ->send(); + } + + $value = $sticker->{$column}; + + if (empty($value)) { + Notification::make() + ->title('Unknown Part validation') + ->body("Selected validation '$column' has no value.") + ->danger() + ->seconds(2) + ->send(); + } + + $newFileName = $value . '.png'; + + $directory = "uploads/PartValidation/{$plantCode}"; + + $disk = Storage::disk('local'); + if (!$disk->exists($directory)) { + $disk->makeDirectory($directory, 0755, true); + } + + // $path = $uploadedFile->storeAs( + // $directory, + // $newFileName, + // 'local' + // ); + try + { + $path = $uploadedFile->storeAs( + $directory, + $newFileName, + 'local' + ); + } + catch (\Exception $e) { + Notification::make() + ->title('Upload Failed') + ->body("Failed to upload image: " . $e->getMessage()) + ->danger() + ->seconds(3) + ->send(); + return; + } + + $fullPath = Storage::disk('local')->path($path); + + Notification::make() + ->title('Success') + ->body("Uploaded part validation image successfully") + ->success() + ->seconds(2) + ->send(); + }) + ->visible(function() { + return Filament::auth()->user()->can('view import part validation'); + }), ImportAction::make() ->label('Import Sticker Masters') ->color('warning')