schema([ Section::make('') ->schema([ Forms\Components\Select::make('plant_id') ->label('Plant') ->reactive() ->relationship('plant', 'name') ->disabled(fn (Get $get) => $get('invoice_number')) ->required() ->afterStateUpdated(function ($state, callable $set, callable $get) { $plantId = $get('plant_id'); if ($plantId) { $set('plant', $plantId); $set('invoice_number', null); $set('pallet_number', null); $set('serial_number', null); $set('sno_quantity', null); } else { $set('plant', null); $set('invoice_number', null); $set('pallet_number', null); $set('serial_number', null); $set('sno_quantity', null); } }), Forms\Components\Hidden::make('plant') ->reactive(), Forms\Components\TextInput::make('invoice_number') ->label('Scan Invoice No') ->required() ->reactive() ->extraAttributes([ 'x-data' => '{ value: "" }', 'x-model' => 'value', 'x-on:keydown.enter.prevent' => '$wire.processinvoiceSNo()', ]) ->readOnly(fn (callable $get) => !$get('plant') || $get('pallet_number') || $get('serial_number')) ->afterStateUpdated(function ($state, callable $set, callable $get) { $plantId = $get('plant'); if (!$plantId) { $set('invoice_number', null); $set('pallet_number', null); } $set('update_invoice', null); $set('pallet_number', null); $set('serial_number', null); }), Forms\Components\TextInput::make('pallet_number') ->label('Scan Pallet No') ->reactive() // ->readOnly(fn (callable $get) => !$get('plant') || !$get('invoice_number') || $get('serial_number')) ->readOnly(function (callable $get) { $invoiceNumber = $get('invoice_number'); $plantId = $get('plant'); $invoiceExist = false; if (!empty($invoiceNumber) && !empty($plantId)) { $records = LocatorInvoiceValidation::where('plant_id', $plantId) ->where('invoice_number', $invoiceNumber) ->get(); $allScanned = true; foreach ($records as $record) { if (($record->scanned_status == null) || trim($record->scanned_status) == '') { $allScanned = false; break; } } if (count($records) > 0 && !$allScanned) { $invoiceExist = true; } } return $invoiceExist == false || !$get('plant') || !$get('invoice_number') || $get('serial_number'); }) ->extraAttributes([ 'wire:keydown.enter.prevent' => 'processPalletNo()', ]) ->afterStateUpdated(function ($state, callable $set, callable $get) { $plantId = $get('plant'); if (!$plantId) { $set('invoice_number', null); $set('pallet_number', null); } $set('update_locator_invoice', null); }), Forms\Components\TextInput::make('serial_number') ->label('Scan Serial No') ->reactive() // ->readOnly(fn (callable $get) => !$get('plant') || !$get('invoice_number') || $get('pallet_number')) ->readOnly(function (callable $get) { $invoiceNumber = $get('invoice_number'); $plantId = $get('plant'); $invoiceExist = false; if (!empty($invoiceNumber) && !empty($plantId)) { $records = LocatorInvoiceValidation::where('plant_id', $plantId) ->where('invoice_number', $invoiceNumber) ->get(); $allScanned = true; foreach ($records as $record) { if (($record->scanned_status == null) || trim($record->scanned_status) == '') { $allScanned = false; break; } } if (count($records) > 0 && !$allScanned) { $invoiceExist = true; } } return $invoiceExist == false || !$get('plant') || !$get('invoice_number') || $get('pallet_number'); }) ->extraAttributes([ 'x-data' => '{ value: "" }', 'x-model' => 'value', 'x-on:keydown.enter.prevent' => '$wire.processSerialNo()', ]), Forms\Components\TextInput::make('sno_quantity') ->label('SNo. Quantity') ->readOnly(), //Forms\Components\View::make('forms.components.update-invoice-button'), ToggleButtons::make('update_invoice') ->label('Update Invoice?') ->boolean() ->grouped() ->reactive() ->hidden(function (callable $get) { $invoiceNumber = $get('invoice_number'); $plantId = $get('plant'); $invoiceExist = false; if (!empty($invoiceNumber) && !empty($plantId)) { $records = LocatorInvoiceValidation::where('plant_id', $plantId) ->where('invoice_number', $invoiceNumber) ->get(); $allScanned = true; foreach ($records as $record) { if (($record->scanned_status == null) || trim($record->scanned_status) == '') { $allScanned = false; break; } } if (count($records) > 0 && !$allScanned) { $invoiceExist = true; } } return $get('update_invoice') == '0' || $invoiceExist == false || !empty($get('pallet_number')) || !empty($get('serial_number')); //$get('invoice_number') == null }), Forms\Components\TextInput::make('id') ->hidden() ->readOnly(), ToggleButtons::make('update_locator_invoice') ->label('Update Partial Pallet?') ->boolean() ->grouped() ->reactive() ->hidden(function (callable $get) { $palletNumber = $get('pallet_number'); $plantId = $get('plant'); $isPalletValid = false; if (!empty($palletNumber) && !empty($plantId)) { $pallet = PalletValidation::where('plant_id', $plantId) ->where('pallet_number', $palletNumber) ->first(); $isPalletValid = $pallet !== null; } return !$isPalletValid || $get('update_locator_invoice') == '0' || !empty($get('serial_number')); }) ->afterStateUpdated(function ($state, callable $set, callable $get, $livewire) { $plantId = $get('plant'); $palletNumber = $get('pallet_number'); $serialNumber = $get('serial_number'); $invoiceNumber = $get('invoice_number'); $operatorName = Filament::auth()->user()->name; if ($state !== '1') { $set('update_locator_invoice', '0'); $set('pallet_number', null); return; } $palletRecord = PalletValidation::where('plant_id', $plantId) ->where('pallet_number', $palletNumber) ->first(); if (!$palletRecord) { Notification::make() ->title("Pallet number '{$palletNumber}' does not exist.") ->danger() ->send(); return; } $palletRecords = PalletValidation::where('plant_id', $plantId) ->where('pallet_number', $palletNumber) ->get(); $allCompleted = true; foreach ($palletRecords as $record) { if ($record->pallet_status != 'Completed') { $allCompleted = false; break; } } if (!$allCompleted) { Notification::make() ->title("Pallet number '{$palletNumber}' is not completed in masters") ->danger() ->send(); return; } // if ($allCompleted) // { // $serialNumbers = $palletRecords->pluck('serial_number') // ->map(function ($serial) { // return trim($serial); // }) // ->all(); // $InvoiceSerialNumbers = LocatorInvoiceValidation::where('plant_id', $plantId) // ->where('invoice_number', $invoiceNumber) // ->pluck('serial_number') // ->all(); // $missingSerialNumbers = array_diff($InvoiceSerialNumbers, $serialNumbers); // $allmatchedSerialNumbers = array_unique(array_merge($InvoiceSerialNumbers, $serialNumbers)); // if (!empty($missingSerialNumbers)) // { // $matchedSerialNumbers = array_diff($serialNumbers, $missingSerialNumbers); // foreach ($matchedSerialNumbers as $serial) // { // $invoiceRecord = LocatorInvoiceValidation::where('plant_id', $plantId) // ->where('invoice_number', $invoiceNumber) // ->where('serial_number', $serial) // ->first(); // if ($invoiceRecord) // { // $invoiceRecord->scanned_status = 'Scanned'; // $invoiceRecord->pallet_number = $palletNumber; // $invoiceRecord->scanned_at = now(); // $invoiceRecord->scanned_by = $operatorName; // $invoiceRecord->save(); // Notification::make() // ->title("Pallet number '{$palletNumber}' scanned successfully") // ->success() // ->send(); // } // PalletValidation::where('plant_id', $plantId) // ->where('pallet_number', $palletNumber) // ->where('serial_number', $serial) // ->forceDelete(); // $livewire('loadData', $invoiceNumber, $plantId); // } // } // else // { // foreach ($allmatchedSerialNumbers as $serial) // { // $invoiceRecord = LocatorInvoiceValidation::where('plant_id', $plantId) // ->where('invoice_number', $invoiceNumber) // ->where('serial_number', $serial) // ->first(); // if ($invoiceRecord) // { // $invoiceRecord->scanned_status = 'Scanned'; // $invoiceRecord->pallet_number = $palletNumber; // $invoiceRecord->scanned_at = now(); // $invoiceRecord->scanned_by = $operatorName; // $invoiceRecord->save(); // Notification::make() // ->title("Pallet number '{$palletNumber}' scanned successfully") // ->success() // ->send(); // } // PalletValidation::where('plant_id', $plantId) // ->where('pallet_number', $palletNumber) // ->where('serial_number', $serial) // ->forceDelete(); // $this->dispatch('loadData', $invoiceNumber, $plantId); // } // } // } }) ]) ->columns(5), ]); } public static function table(Table $table): Table { return $table ->columns([ Tables\Columns\TextColumn::make('No.') ->label('No.') ->alignCenter() ->getStateUsing(function ($record, $livewire, $column, $rowLoop) { $paginator = $livewire->getTableRecords(); $perPage = method_exists($paginator, 'perPage') ? $paginator->perPage() : 10; $currentPage = method_exists($paginator, 'currentPage') ? $paginator->currentPage() : 1; return ($currentPage - 1) * $perPage + $rowLoop->iteration; }), Tables\Columns\TextColumn::make('plant.name') ->label('Plant') ->alignCenter() ->searchable() ->sortable(), Tables\Columns\TextColumn::make('invoice_number') ->label('Invoice Number') ->searchable() ->alignCenter() ->sortable(), Tables\Columns\TextColumn::make('serial_number') ->label('Serial Number') ->searchable() ->alignCenter() ->sortable(), Tables\Columns\TextColumn::make('pallet_number') ->label('Pallet Number') ->searchable() ->alignCenter() ->sortable(), Tables\Columns\TextColumn::make('locator_number') ->label('Locator Number') ->searchable() ->alignCenter() ->sortable(), Tables\Columns\TextColumn::make('scanned_status') ->label('Scanned Status') ->searchable() ->alignCenter() ->sortable(), Tables\Columns\TextColumn::make('upload_status') ->label('Upload Status') ->searchable() ->alignCenter(), Tables\Columns\TextColumn::make('created_by') ->label('Created By') ->alignCenter() ->sortable(), Tables\Columns\TextColumn::make('created_at') ->label('Created At') ->dateTime() ->alignCenter() ->sortable(), Tables\Columns\TextColumn::make('updated_by') ->label('Updated By') ->alignCenter() ->sortable() ->toggleable(isToggledHiddenByDefault: true), Tables\Columns\TextColumn::make('updated_at') ->label('Updated At') ->dateTime() ->alignCenter() ->sortable() ->toggleable(isToggledHiddenByDefault: true), Tables\Columns\TextColumn::make('scanned_by') ->label('Scanned By') ->alignCenter() ->sortable(), Tables\Columns\TextColumn::make('scanned_at') ->label('Scanned At') ->dateTime() ->alignCenter() ->sortable(), Tables\Columns\TextColumn::make('deleted_at') ->dateTime() ->alignCenter() ->sortable() ->toggleable(isToggledHiddenByDefault: true), ]) ->headerActions([ Tables\Actions\Action::make('import_invoice') ->label('Import Invoice') ->form([ Select::make('plant_id') ->options(Plant::pluck('name', 'id')->toArray()) ->label('Select Plant') ->required() ->default(function () { return optional(InvoiceValidation::latest()->first())->plant_id; }) ->afterStateUpdated(function ($state, callable $set, callable $get) { $set('invoice_serial_number', null); }) ->reactive(), FileUpload::make('invoice_serial_number') ->label('Invoice Serial Number') // ->required() ->preserveFilenames() // <- this keeps the original filename ->storeFiles(false) ->reactive() ->required() ->disk('local') ->visible(fn (Get $get) => !empty($get('plant_id'))) ->directory('uploads/temp'), ]) ->action(function (array $data) { $uploadedFile = $data['invoice_serial_number']; $disk = Storage::disk('local'); $plantId = $data['plant_id']; $originalName = $uploadedFile->getClientOriginalName(); // e.g. 3RA0018732.xlsx $invoiceNumber = pathinfo($originalName, PATHINFO_FILENAME); // $invoiceNumber = trim(str_replace('.xlsx', '', $originalName)); // $originalNameOnly = pathinfo($originalName, PATHINFO_FILENAME); $folderPath = Configuration::where('c_name', 'INVOICE_FOLDER_PATH') ->value('c_value'); $fullFolderPath = "uploads/$folderPath"; // Check if the folder exists, if not, create it if (!Storage::disk('local')->exists($fullFolderPath)) { Storage::disk('local')->makeDirectory($fullFolderPath); } $path = $uploadedFile->storeAs($fullFolderPath, $originalName, 'local'); $fullPath = Storage::disk('local')->path($path); if ($fullPath && file_exists($fullPath)) { $rows = Excel::toArray(null, $fullPath)[0]; if((count($rows) - 1) <= 0) { Notification::make() ->title('Invalid Locator Invoice Found') ->body('Uploaded excel sheet is empty or
contains no valid data.') ->danger() ->send(); if ($disk->exists($path)) { $disk->delete($path); } return; } $invalidSerialCodes=[]; $duplicateSerials = []; $seenSerialNumbers = []; $validRowsFound = false; foreach ($rows as $index => $row) { if ($index === 0) continue; // Skip header $serialNumber = trim($row[0]); if (empty($serialNumber)) { continue; } else { if(Str::length($serialNumber) < 13 || !ctype_alnum($serialNumber)) { $invalidSerialCodes[] = $serialNumber; } else { if (in_array($serialNumber, $seenSerialNumbers)) { $duplicateSerials[] = $serialNumber; } else { $seenSerialNumbers[] = $serialNumber; $validRowsFound = true; } } } } $uniqueSerialCodes = array_unique($invalidSerialCodes); if (!empty($uniqueSerialCodes)) { Notification::make() ->title('Invalid Serial Numbers Found') ->body('The following serial numbers should contain minimum 13 digit alpha numeric values:
' . implode(', ', $uniqueSerialCodes)) ->danger() ->send(); if ($disk->exists($path)) { $disk->delete($path); } return; } $duplicateSerialCodes = array_unique($duplicateSerials); if (!empty($duplicateSerialCodes)) { Notification::make() ->title('Duplicate Serial Numbers Found') ->body('The following serial numbers are already exist in imported excel:
' . implode(', ', $duplicateSerialCodes)) ->danger() ->send(); if ($disk->exists($path)) { $disk->delete($path); } return; } if (!$validRowsFound) { Notification::make() ->title('Invalid Locator Invoice Found') ->body('Uploaded excel sheet is empty or
contains no valid data.') ->danger() ->send(); if ($disk->exists($path)) { $disk->delete($path); } return; } $serialsToCheck = $seenSerialNumbers; $existingSerials = LocatorInvoiceValidation::whereIn('serial_number', $serialsToCheck) ->where('invoice_number', '!=', $invoiceNumber) ->where('plant_id', $plantId) ->pluck('serial_number') ->toArray(); if (!empty($existingSerials)) { Notification::make() ->title('Duplicate Serial Numbers Found') ->body('The following serial numbers already exist with a different invoice number:
' . implode(', ', $existingSerials)) ->danger() ->send(); if ($disk->exists($path)) { $disk->delete($path); } return; } else { // Save full file path to session session(['uploaded_invoice_path' => $fullPath]); Notification::make() ->title('Success: Invoice imported successfully.') ->success() ->send(); } } }) ->visible(function() { return Filament::auth()->user()->can('view import dispatch serial invoice validation'); }), ImportAction::make() ->importer(LocatorInvoiceValidationImporter::class) ->visible(function() { return Filament::auth()->user()->can('view import locator invoice validation'); }), ExportAction::make() ->exporter(LocatorInvoiceValidationExporter::class) ->visible(function() { return Filament::auth()->user()->can('view export locator invoice validation'); }), ]) ->filters([ Tables\Filters\TrashedFilter::make(), ]) ->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 { return [ // ]; } public static function getPages(): array { return [ 'index' => Pages\ListLocatorInvoiceValidations::route('/'), 'create' => Pages\CreateLocatorInvoiceValidation::route('/create'), 'view' => Pages\ViewLocatorInvoiceValidation::route('/{record}'), 'edit' => Pages\EditLocatorInvoiceValidation::route('/{record}/edit'), ]; } public static function getEloquentQuery(): Builder { return parent::getEloquentQuery() ->withoutGlobalScopes([ SoftDeletingScope::class, ]); } }