From 3f1b46873e98d8abe0403e91496f685465770125 Mon Sep 17 00:00:00 2001 From: dhanabalan Date: Sat, 27 Sep 2025 14:00:31 +0530 Subject: [PATCH] Add GrMaster resource with CRUD pages and functionality for managing GR records --- app/Filament/Resources/GrMasterResource.php | 339 ++++++++++++++++++ .../GrMasterResource/Pages/CreateGrMaster.php | 12 + .../GrMasterResource/Pages/EditGrMaster.php | 22 ++ .../GrMasterResource/Pages/ListGrMasters.php | 19 + .../GrMasterResource/Pages/ViewGrMaster.php | 19 + 5 files changed, 411 insertions(+) create mode 100644 app/Filament/Resources/GrMasterResource.php create mode 100644 app/Filament/Resources/GrMasterResource/Pages/CreateGrMaster.php create mode 100644 app/Filament/Resources/GrMasterResource/Pages/EditGrMaster.php create mode 100644 app/Filament/Resources/GrMasterResource/Pages/ListGrMasters.php create mode 100644 app/Filament/Resources/GrMasterResource/Pages/ViewGrMaster.php diff --git a/app/Filament/Resources/GrMasterResource.php b/app/Filament/Resources/GrMasterResource.php new file mode 100644 index 0000000..0aa5ea3 --- /dev/null +++ b/app/Filament/Resources/GrMasterResource.php @@ -0,0 +1,339 @@ +schema([ + Forms\Components\Select::make('plant_id') + ->label('Plant') + ->reactive() + ->relationship('plant', 'name') + ->required(), + Forms\Components\Select::make('item_id') + ->label('Item Code') + //->relationship('item', 'id') + ->reactive() + ->searchable() + ->options(function (callable $get) { + $plantId = $get('plant_id'); + if (empty($plantId)) { + return []; + } + return Item::where('plant_id', $plantId)->pluck('code', 'id'); + }) + ->required(), + Forms\Components\TextInput::make('gr_number') + ->label('GR Number') + ->required(), + Forms\Components\TextInput::make('serial_number') + ->label('Serial Number') + ->rule(function (callable $get) { + return Rule::unique('gr_masters', 'serial_number') + ->where('plant_id', $get('plant_id')) + ->ignore($get('id')); // Ignore current record during updates + }), + + Forms\Components\FileUpload::make('attachment') + ->label('PDF Upload') + ->acceptedFileTypes(['application/pdf']) + ->storeFiles(false) + ->disk('local') + ->directory('uploads/temp') + ->preserveFilenames() + ->reactive(), + Forms\Components\Actions::make([ + Action::make('uploadNow') + ->label('Upload PDF Now') + ->action(function ($get, callable $set) { + $uploadedFiles = $get('attachment'); + + if (is_array($uploadedFiles) && count($uploadedFiles) > 0) + { + $uploaded = reset($uploadedFiles); + + if ($uploaded instanceof TemporaryUploadedFile) { + $grNumber = $get('gr_number'); + $safeName = preg_replace('/[^A-Za-z0-9_\-]/', '_', $grNumber); + // $originalName = $uploaded->getClientOriginalName(); + // $path = 'uploads/GRNumber/' . $originalName; + $finalFileName = $safeName . '.pdf'; + $finalPath = 'uploads/GRNumber/' . $finalFileName; + + if (Storage::disk('local')->exists($finalPath)) { + Notification::make() + ->title('Duplicate File') + ->body("The file '{$finalFileName}' already exists in uploads/GRNumber.") + ->warning() + ->send(); + return; // Stop here + } + + $storedPath = $uploaded->storeAs( + 'uploads/GRNumber', + $finalFileName, + 'local' + ); + + + // $fullPath = storage_path('app/' . $storedPath); + $fullPath = storage_path('app/private/' . $storedPath); + $parser = new Parser(); + //$pdf = $parser->parseContent(file_get_contents($uploaded->getRealPath())); + $pdf = $parser->parseFile($fullPath); + $text = $pdf->getText(); + + //dd($text); + + if (preg_match('/Item code\s*:\s*(\S+)/i', $text, $matches)) { + $item1 = $matches[1]; + } + else + { + Notification::make() + ->title('Item Code Not Found') + ->body('Could not find Item code in uploaded PDF.') + ->warning() + ->send(); + return; + } + + $processOrder = $get('gr_number'); + + $itemId = $get('item_id'); + + $plant = $get('plant_id'); + + $item = Item::find($itemId); + + $plant = Plant::find($plant); + + if ($item) + { + $itemCode = $item->code; + } + else + { + $itemCode = null; + Notification::make() + ->title('Item Not Found') + ->body("Item not found in uploaded pdf.") + ->warning() + ->send(); + return; + } + + $storedPath = $uploaded->storeAs( + 'uploads/GRNumber', + $finalFileName, + 'local' + ); + + if($itemCode == $item1) + { + Notification::make() + ->title('Success') + ->body("Gr Number '$processOrder' PDF uploaded successfully.") + ->success() + ->send(); + return; + } + else + { + + if (Storage::disk('local')->exists($storedPath)) { + Storage::disk('local')->delete($storedPath); + } + + Notification::make() + ->title('Item Code not matched') + ->body("Item Code: {$item->code} not matched with the uploaded pdf code $item1.") + ->danger() + ->send(); + return; + } + } + } + else + { + Notification::make() + ->title('No file selected to upload') + ->warning() + ->send(); + return; + } + }), + + Action::make('downloadAttachment') + ->label('Download PDF') + ->action(function ($get) { + $equipmentNumber = $get('gr_number'); + + if (!$equipmentNumber) { + Notification::make() + ->title('No GR Number entered') + ->danger() + ->send(); + return; + } + + $files = Storage::disk('local')->files('uploads/GRNumber'); + + $fileToDownload = null; + foreach ($files as $file) { + if (str_contains($file, $equipmentNumber)) { + $fileToDownload = $file; + break; + } + } + + if (!$fileToDownload) { + Notification::make() + ->title('PDF not found for this process order') + ->danger() + ->send(); + return; + } + + return response()->download(Storage::disk('local')->path($fileToDownload)); + }), + ]), + Forms\Components\Hidden::make('created_by') + ->label('Created By') + ->default(Filament::auth()->user()?->name), + Forms\Components\Hidden::make('updated_by') + ->default(Filament::auth()->user()?->name), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('No.') + ->label('No.') + ->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() + ->sortable(), + Tables\Columns\TextColumn::make('item.code') + ->label('Item Code') + ->alignCenter() + ->sortable(), + Tables\Columns\TextColumn::make('gr_number') + ->label('GR Number') + ->alignCenter() + ->sortable(), + Tables\Columns\TextColumn::make('serial_number') + ->label('Serial Number') + ->alignCenter() + ->sortable(), + Tables\Columns\TextColumn::make('created_at') + ->label('Created At') + ->alignCenter() + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('updated_at') + ->label('Updated At') + ->alignCenter() + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('deleted_at') + ->label('Deleted At') + ->alignCenter() + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->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(), + ]), + ]) + ->headerActions([ + ImportAction::make() + ->importer(GrMasterImporter::class) + ->visible(function() { + return Filament::auth()->user()->can('view import gr master'); + }), + ExportAction::make() + ->exporter(GrMasterExporter::class) + ->visible(function() { + return Filament::auth()->user()->can('view export gr master'); + }), + ]); + } + + public static function getRelations(): array + { + return [ + // + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListGrMasters::route('/'), + 'create' => Pages\CreateGrMaster::route('/create'), + 'view' => Pages\ViewGrMaster::route('/{record}'), + 'edit' => Pages\EditGrMaster::route('/{record}/edit'), + ]; + } + + public static function getEloquentQuery(): Builder + { + return parent::getEloquentQuery() + ->withoutGlobalScopes([ + SoftDeletingScope::class, + ]); + } +} diff --git a/app/Filament/Resources/GrMasterResource/Pages/CreateGrMaster.php b/app/Filament/Resources/GrMasterResource/Pages/CreateGrMaster.php new file mode 100644 index 0000000..2da5b89 --- /dev/null +++ b/app/Filament/Resources/GrMasterResource/Pages/CreateGrMaster.php @@ -0,0 +1,12 @@ +