diff --git a/app/Filament/Resources/QualityValidationResource.php b/app/Filament/Resources/QualityValidationResource.php index 0d9e3ceda..fe9301513 100644 --- a/app/Filament/Resources/QualityValidationResource.php +++ b/app/Filament/Resources/QualityValidationResource.php @@ -5,10 +5,12 @@ namespace App\Filament\Resources; use App\Filament\Resources\QualityValidationResource\Pages; use App\Filament\Resources\QualityValidationResource\RelationManagers; use App\Models\QualityValidation; +use Carbon\Carbon; use Closure; use Filament\Forms; use Filament\Forms\Components\DatePicker; use Filament\Forms\Components\DateTimePicker; +use Filament\Forms\Components\Select; use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; @@ -19,6 +21,7 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\Relationship; use Illuminate\Database\Eloquent\SoftDeletingScope; use Filament\Tables\Filters\Filter; +use Illuminate\Validation\ValidationException; @@ -48,6 +51,9 @@ class QualityValidationResource extends Resource ->required(), Forms\Components\TextInput::make('production_order') ->required(), + // ->unique('quality_validations', 'production_order'), // Ensures unique values, + + //.. Forms\Components\TextInput::make('item_id') ->label('Item Code') ->placeholder('Scan the valid QR code') @@ -55,7 +61,6 @@ class QualityValidationResource extends Resource ->required() ->afterStateUpdated(function (callable $set, callable $get, ?string $state) { - // Reset visibility of all serial and part validation fields $serialFields = [ 'serial_number_motor', 'serial_number_pump', 'serial_number_pumpset', 'pack_slip_motor', 'pack_slip_pump', 'pack_slip_pumpset', @@ -87,7 +92,7 @@ class QualityValidationResource extends Resource return; } - // Check if QR format contains '|' + // // Check if QR format contains '|' if (strpos($state, '|') === false) { $set('validationError', 'Scan valid QR code. (Ex: Item_Code|Serial_Number )'); return; @@ -125,8 +130,6 @@ class QualityValidationResource extends Resource } } - $set('validationError', 'Scan valid QR code. (Ex: Item_Code|Serial_Number )'); - return; } else { @@ -178,14 +181,12 @@ class QualityValidationResource extends Resource $set('item_id', null); return; } - // Check if the item exists for the selected plant $stickerMaster = \App\Models\StickerMaster::where('plant_id', $plantId) ->whereHas('item', function ($query) use ($itemCode) { $query->where('code', $itemCode); })->first(); - if (!$stickerMaster) { $set('validationError', 'Item code does not exist in master data.'); $set('sticker_master_id', null); @@ -196,13 +197,11 @@ class QualityValidationResource extends Resource $set('sticker_master_id', $stickerMaster->id); $set('item_id', $itemCode); } - - // Check if user input matches the database values foreach ($partValidationColumns as $field) { - if ($get("{$field}_visible")) { // Only validate visible fields - $userInput = $get($field); // Get user input - $expectedValue = $stickerMaster->$field; // Get expected value from DB + if ($get("{$field}_visible")) { + $userInput = $get($field); + $expectedValue = $stickerMaster->$field; if ($userInput !== null && $userInput !== $expectedValue) { $set('validationError', "Invalid input for $field. Expected: $expectedValue"); @@ -211,19 +210,6 @@ class QualityValidationResource extends Resource } } - // $serialExists = QualityValidation::where('sticker_master_id', $stickerMaster->id) - // ->where(function ($query) use ($serialNumber, $serialFields) { - // foreach ($serialFields as $column) { - // $query->orWhere($column, $serialNumber); - // } - // })->exists(); - - // if ($serialExists) { - // $set('validationError', 'Already scanning process completed.'); - // $set('item_id', "$previousItemCode|$previousSerialNumber"); // Restore original QR code - // return; - // } - $serialExists = QualityValidation::where(function ($query) use ($serialNumber, $serialFields) { foreach ($serialFields as $column) { $query->orWhere($column, $serialNumber); @@ -233,15 +219,13 @@ class QualityValidationResource extends Resource if ($serialExists) { $set('validationError', 'Serial number already exists in quality validation.'); - // Restore the serial number before returning - $set('item_id', "$itemCode|$previousSerialNumber"); // Reinsert full QR code + $set('item_id', "$itemCode|$previousSerialNumber"); return; } // Clear validation error if all inputs match $set('validationError', null); - // Filter columns with value `1` $visibleColumns = []; foreach ($serialFields as $column) { if ($stickerMaster->$column === 1) { @@ -272,7 +256,6 @@ class QualityValidationResource extends Resource } } - // Assign serial number to only visible text inputs foreach ($serialnumber as $field) { if ($get("{$field}_visible")) { $set($field, $serialNumber); @@ -280,6 +263,7 @@ class QualityValidationResource extends Resource } }) + ->extraAttributes(fn ($get) => [ 'class' => $get('validationError') ? 'border-red-500' : '', ]) @@ -289,7 +273,7 @@ class QualityValidationResource extends Resource Forms\Components\TextInput::make('serial_number_motor') ->hidden(fn (callable $get) => !$get('serial_number_motor_visible')) // Controls visibility - ->default(''), // Keeps input empty + ->default(''), Forms\Components\TextInput::make('serial_number_pump') ->hidden(fn (callable $get) => !$get('serial_number_pump_visible')) @@ -383,24 +367,26 @@ class QualityValidationResource extends Resource if (!$isMatch) { $set('pack_slip_motor_error', 'Serial number does not match.'); + return; } else { $set('pack_slip_motor_error', null); $set('pack_slip_motor', $serialNumber); } - }) - ->extraAttributes(fn ($get) => [ - 'class' => $get('pack_slip_motor_error') ? 'border-red-500' : '', - ]) - ->hint(fn ($get) => $get('pack_slip_motor_error') ? $get('pack_slip_motor_error') : null) - ->hintColor('danger'), + + ->extraAttributes(fn ($get) => [ + 'class' => $get('pack_slip_motor_error') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('pack_slip_motor_error') ? $get('pack_slip_motor_error') : null) + ->hintColor('danger'), Forms\Components\TextInput::make('pack_slip_pump') ->hidden(fn (callable $get) => !$get('pack_slip_pump_visible')) ->default('') ->required() + ->reactive() ->afterStateUpdated(function (callable $set, callable $get, ?string $state) { $set('pack_slip_pump_error', null); @@ -480,12 +466,12 @@ class QualityValidationResource extends Resource if (!$isMatch) { $set('pack_slip_pump_error', 'Serial number does not match.'); + return; } else { $set('pack_slip_pump_error', null); $set('pack_slip_pump', $serialNumber); } - }) ->extraAttributes(fn ($get) => [ 'class' => $get('pack_slip_pump_error') ? 'border-red-500' : '', @@ -497,6 +483,7 @@ class QualityValidationResource extends Resource ->hidden(fn (callable $get) => !$get('pack_slip_pumpset_visible')) ->default('') ->required() + ->reactive() ->afterStateUpdated(function (callable $set, callable $get, ?string $state) { $set('pack_slip_pumpset_error', null); @@ -576,6 +563,7 @@ class QualityValidationResource extends Resource if (!$isMatch) { $set('pack_slip_pumpset_error', 'Serial number does not match.'); + return; } else { $set('pack_slip_pumpset_error', null); @@ -593,6 +581,7 @@ class QualityValidationResource extends Resource ->hidden(fn (callable $get) => !$get('name_plate_motor_visible')) ->default('') ->required() + ->reactive() ->afterStateUpdated(function (callable $set, callable $get, ?string $state) { $set('name_plate_motor_error', null); @@ -672,6 +661,7 @@ class QualityValidationResource extends Resource if (!$isMatch) { $set('name_plate_motor_error', 'Serial number does not match.'); + return; } else { $set('name_plate_motor_error', null); @@ -689,6 +679,7 @@ class QualityValidationResource extends Resource ->hidden(fn (callable $get) => !$get('name_plate_pump_visible')) ->default('') ->required() + ->reactive() ->afterStateUpdated(function (callable $set, callable $get, ?string $state) { $set('name_plate_pump_error', null); @@ -768,6 +759,7 @@ class QualityValidationResource extends Resource if (!$isMatch) { $set('name_plate_pump_error', 'Serial number does not match.'); + return; } else { $set('name_plate_pump_error', null); @@ -785,6 +777,7 @@ class QualityValidationResource extends Resource ->hidden(fn (callable $get) => !$get('name_plate_pumpset_visible')) ->default('') ->required() + ->reactive() ->afterStateUpdated(function (callable $set, callable $get, ?string $state) { $set('name_plate_pumpset_error', null); @@ -864,6 +857,7 @@ class QualityValidationResource extends Resource if (!$isMatch) { $set('name_plate_pumpset_error', 'Serial number does not match.'); + return; } else { $set('name_plate_pumpset_error', null); @@ -881,6 +875,7 @@ class QualityValidationResource extends Resource ->hidden(fn (callable $get) => !$get('tube_sticker_motor_visible')) ->default('') ->required() + ->reactive() ->afterStateUpdated(function (callable $set, callable $get, ?string $state) { $set('tube_sticker_motor_error', null); @@ -960,6 +955,7 @@ class QualityValidationResource extends Resource if (!$isMatch) { $set('tube_sticker_motor_error', 'Serial number does not match.'); + return; } else { $set('tube_sticker_motor_error', null); @@ -977,6 +973,7 @@ class QualityValidationResource extends Resource ->hidden(fn (callable $get) => !$get('tube_sticker_pump_visible')) ->default('') ->required() + ->reactive() ->afterStateUpdated(function (callable $set, callable $get, ?string $state) { $set('tube_sticker_pump_error', null); @@ -1056,6 +1053,7 @@ class QualityValidationResource extends Resource if (!$isMatch) { $set('tube_sticker_pump_error', 'Serial number does not match.'); + return; } else { $set('tube_sticker_pump_error', null); @@ -1073,6 +1071,7 @@ class QualityValidationResource extends Resource ->hidden(fn (callable $get) => !$get('tube_sticker_pumpset_visible')) ->default('') ->required() + ->reactive() ->afterStateUpdated(function (callable $set, callable $get, ?string $state) { $set('tube_sticker_pumpset_error', null); @@ -1152,6 +1151,7 @@ class QualityValidationResource extends Resource if (!$isMatch) { $set('tube_sticker_pumpset_error', 'Serial number does not match.'); + return; } else { $set('tube_sticker_pumpset_error', null); @@ -1169,6 +1169,7 @@ class QualityValidationResource extends Resource ->hidden(fn (callable $get) => !$get('warranty_card_visible')) ->default('') ->required() + ->reactive() ->afterStateUpdated(function (callable $set, callable $get, ?string $state) { $set('warranty_card_error', null); @@ -1248,6 +1249,7 @@ class QualityValidationResource extends Resource if (!$isMatch) { $set('warranty_card_error', 'Serial number does not match.'); + return; } else { $set('warranty_card_error', null); @@ -1290,7 +1292,8 @@ class QualityValidationResource extends Resource } else { - $set('part_validation1_error', "Invalid input for part validation 1."); // Expected: $expectedValue + $set('part_validation1_error', "Invalid input for part validation 1."); + return; } }) ->extraAttributes(fn ($get) => [ @@ -1299,7 +1302,6 @@ class QualityValidationResource extends Resource ->hint(fn ($get) => $get('part_validation1_error')) ->hintColor('danger'), - Forms\Components\TextInput::make('part_validation2') ->hidden(fn (callable $get) => !$get('part_validation2_visible')) ->default('') @@ -1330,7 +1332,8 @@ class QualityValidationResource extends Resource } else { - $set('part_validation2_error', "Invalid input for part validation 2."); // Expected: $expectedValue + $set('part_validation2_error', "Invalid input for part validation 2."); + return; } }) @@ -1369,9 +1372,11 @@ class QualityValidationResource extends Resource } else { - $set('part_validation3_error', "Invalid input for part validation 3."); // Expected: $expectedValue + $set('part_validation3_error', "Invalid input for part validation 3."); + return; } }) + ->extraAttributes(fn ($get) => [ 'class' => $get('part_validation3_error') ? 'border-red-500' : '', ]) @@ -1402,18 +1407,18 @@ class QualityValidationResource extends Resource return; } - // If input is empty, do not show an error - if ($state === $expectedValue) { $set('part_validation4_error', null); } else { - $set('part_validation4_error', "Invalid input for part validation 4."); // Expected: $expectedValue + $set('part_validation4_error', "Invalid input for part validation 4."); + return; } }) + ->extraAttributes(fn ($get) => [ 'class' => $get('part_validation4_error') ? 'border-red-500' : '', ]) @@ -1444,18 +1449,18 @@ class QualityValidationResource extends Resource return; } - // If input is empty, do not show an error - if ($state === $expectedValue) { $set('part_validation5_error', null); } else { - $set('part_validation5_error', "Invalid input for part validation 5."); // Expected: $expectedValue + $set('part_validation5_error', "Invalid input for part validation 5."); + return; } }) + ->extraAttributes(fn ($get) => [ 'class' => $get('part_validation5_error') ? 'border-red-500' : '', ]) @@ -1467,7 +1472,7 @@ class QualityValidationResource extends Resource public static function table(Table $table): Table { return $table - + ->query(QualityValidation::query()) ->columns([ Tables\Columns\TextColumn::make('id') ->label('ID') @@ -1534,89 +1539,91 @@ class QualityValidationResource extends Resource ->filters([ Tables\Filters\TrashedFilter::make(), - SelectFilter::make('sticker_master_id') - ->label('Filter by item code') - // ->options(function () { - // return \App\Models\Item::whereIn('id', function ($query) { - // $query->select('item_id') - // ->from('sticker_masters') - // ->whereIn('id', function ($subQuery) { - // $subQuery->select('sticker_master_id') - // ->from('quality_validations'); - // }); - // }) - - // ->pluck('code', 'id'); - // }) - ->relationship('stickerMaster.item','code') + Filter::make('advanced_filters') + ->label('Advanced Filters') + ->form([ + TextInput::make('production_order') + ->placeholder('Enter Production Order'), + Select::make('sticker_master_id') + ->label('Filter by Item Code') + ->options(function () { + return \App\Models\Item::whereHas('stickerMasters', function ($query) { + $query->whereHas('qualityValidations'); + })->pluck('code', 'id'); + }) ->searchable(), + DateTimePicker::make('created_from') + ->label('Created From') + ->native(false), + DateTimePicker::make('created_to') + ->label('Created To') + ->native(false), + ]) + ->query(function ($query, array $data) { + // Hide all records initially if no filters are applied + if (empty($data['production_order']) && empty($data['created_from']) && empty($data['created_to']) && empty($data['sticker_master_id'])) { + return $query->whereRaw('1 = 0'); + } - Filter::make('production_order') - ->label('Filter by Production Order') - ->form([ - TextInput::make('production_order') - ->placeholder('Enter Production Order'), + if (!empty($data['production_order'])) { + $query->where('production_order', 'like', '%' . $data['production_order'] . '%'); + } - ]) - ->query(function ($query, array $data) { - return $query - ->when( - $data['production_order'] ?? null, - fn ($q) => $q->where('production_order', 'like', '%' . $data['production_order'] . '%') - ); - }) + if (!empty($data['created_from'])) { + $query->where('created_at', '>=', $data['created_from']); + } - ->indicateUsing(function (array $data) { - return empty($data['production_order']) ? [] : ['Production Order: ' . $data['production_order']]; - }), + if (!empty($data['created_to'])) { + $query->where('created_at', '<=', $data['created_to']); + } - // Created Date Range Filter - Filter::make('created_at') - ->form([ - DateTimePicker::make('created_from') - ->label('Created From') - ->native(false), // Optional: Use a nice date picker UI + if (!empty($data['sticker_master_id'])) { + $stickerMasterIds = \App\Models\StickerMaster::where('item_id', $data['sticker_master_id']) + ->pluck('id') + ->toArray(); - DateTimePicker::make('created_to') - ->label('Created To') - ->native(false), - ]) - ->query(function ($query, array $data) { - return $query - ->when( - $data['created_from'] ?? null, - fn ($q) => $q->where('created_at', '>=', $data['created_from']) - ) - ->when( - $data['created_to'] ?? null, - fn ($q) => $q->where('created_at', '<=', $data['created_to']) - ); - }) - ->indicateUsing(function (array $data) { - $indicators = []; - if (!empty($data['created_from'])) { - $indicators[] = 'From: ' . $data['created_from']; - } - if (!empty($data['created_to'])) { - $indicators[] = 'To: ' . $data['created_to']; - } - return $indicators; - }), - ]) + if (!empty($stickerMasterIds)) { + $query->whereIn('sticker_master_id', $stickerMasterIds); + } + } + }) + ->indicateUsing(function (array $data) { + $indicators = []; - ->actions([ - Tables\Actions\ViewAction::make(), - Tables\Actions\EditAction::make(), - ]) + if (!empty($data['production_order'])) { + $indicators[] = 'Production Order: ' . $data['production_order']; + } - ->bulkActions([ - Tables\Actions\BulkActionGroup::make([ - Tables\Actions\DeleteBulkAction::make(), - Tables\Actions\ForceDeleteBulkAction::make(), - Tables\Actions\RestoreBulkAction::make(), - ]), - ]); + if (!empty($data['created_from'])) { + $indicators[] = 'From: ' . $data['created_from']; + } + + if (!empty($data['created_to'])) { + $indicators[] = 'To: ' . $data['created_to']; + } + + if (!empty($data['sticker_master_id'])) { + $itemCode = \App\Models\Item::find($data['sticker_master_id'])->code ?? 'Unknown'; + $indicators[] = 'Item Code: ' . $itemCode; + } + + return $indicators; + }) + ]) + + ->actions([ + Tables\Actions\ViewAction::make(), + Tables\Actions\EditAction::make(), + ]) + + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\DeleteBulkAction::make(), + Tables\Actions\ForceDeleteBulkAction::make(), + Tables\Actions\RestoreBulkAction::make(), + ]), + ]); } public static function getRelations(): array