diff --git a/app/Filament/Resources/OcrValidationResource.php b/app/Filament/Resources/OcrValidationResource.php new file mode 100644 index 0000000..67897e7 --- /dev/null +++ b/app/Filament/Resources/OcrValidationResource.php @@ -0,0 +1,308 @@ +schema([ + Forms\Components\Select::make('plant_id') + ->label('Plant') + ->reactive() + ->relationship('plant', 'name') + ->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(); + }) + ->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\Textarea::make('gr_number') + ->label('GR Number') + ->minLength(7) + ->required(), + Forms\Components\FileUpload::make('photo') + ->dehydrated(false) + ->label('Capture from Webcam') + ->disk('local') + ->directory('uploads') + ->preserveFilenames() + ->image() + ->helperText('You can take a picture from your webcam') + ->reactive(), + Forms\Components\Actions::make([ + Action::make('uploadNow1') + ->label('Upload OCR') + ->action(function ($get, callable $set) { + $uploadedFiles = $get('photo'); + + 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 . '.jpg'; + $finalPath = 'uploads/OCR/' . $finalFileName; + + $storedPath = $uploaded->storeAs( + 'uploads/OCR', + $finalFileName, + 'local' + ); + + // $storedPath = $uploaded->storeAs('uploads/OCR', $finalFileName, 'local'); + // $fullPath = storage_path('app/' . $storedPath); + $storedPath = $uploaded->storeAs('uploads/OCR', $finalFileName, 'local'); + + $fullPath = storage_path('app/private/' . $storedPath); + + $text = (new TesseractOCR($fullPath))->lang('eng')->run(); + + $rawText = $text; + + preg_match_all('/\d+/', $rawText, $matches); + + $serialNumbers = $matches[0]; + + $serialNumbers = array_slice($serialNumbers, 0, 4); + + //dd($serialNumbers); + + $processOrder = $get('gr_number'); + + $itemId = $get('item_id'); + + $plant = $get('plant_id'); + + $item = Item::find($itemId); + + $plant = Plant::find($plant); + + $templatePath = storage_path('app/private/uploads/StickerTemplateOcr/multi.pdf'); + + $outputPath = storage_path('app/private/uploads/StickerTemplateOcr/multi_filled.pdf'); + + $storedPath = $uploaded->storeAs( + 'uploads/GRNumber', + $finalFileName, + 'local' + ); + + $pdf = new Fpdi('P', 'mm', [90, 90]); + + $templateId = $pdf->setSourceFile($templatePath); + $templatePage = $pdf->importPage(1); + + $pdf->AddPage(); + $pdf->useTemplate($templatePage, 0, 0, 90, 90); + + $pdf->SetFont('Helvetica', '', 10); + $pdf->SetTextColor(0, 0, 0); + + $slots = [ + ['x' => 5.7, 'y' => 41.9, 'w' => 46.5, 'h' => 3.5], // 1st serial + ['x' => 50, 'y' => 41.5, 'w' => 46.6, 'h' => 3.9], // 2nd serial + ['x' => 5.7, 'y' => 60, 'w' => 46.5, 'h' => 3.5], // 3rd serial + ['x' => 50, 'y' => 60, 'w' => 46.6, 'h' => 3.5], // 4rd serial + ]; + + $qrSlots = [ + ['x' => 17.3, 'y' => 29.2, 'size' => 11.4], + ['x' => 61.5, 'y' => 29, 'size' => 11.5], + ['x' => 17.7, 'y' => 46.7, 'size' => 11.4], + ['x' => 61.7, 'y' => 46.7, 'size' => 11.4], + ]; + + foreach ($serialNumbers as $i => $serial) { + if (!isset($slots[$i]) || !isset($qrSlots[$i])) continue; + + // Erase old QR completely (slightly larger) + $pdf->SetFillColor(255, 255, 255); + $pdf->Rect($qrSlots[$i]['x']-1, $qrSlots[$i]['y']-1, $qrSlots[$i]['size']+2, $qrSlots[$i]['size']+2, 'F'); + + // Generate new QR code + $qrPath = storage_path("app/private/uploads/QR/qr_$serial.png"); + $qrDir = storage_path('app/private/uploads/QR'); + if (!file_exists($qrDir)) mkdir($qrDir, 0777, true); + QrCode::format('png')->size(100)->generate($serial, $qrPath); + + // Place QR code + $pdf->Image($qrPath, $qrSlots[$i]['x'], $qrSlots[$i]['y'], $qrSlots[$i]['size'], $qrSlots[$i]['size']); + + // Erase old serial + $pdf->SetFillColor(255, 255, 255); + $pdf->Rect($slots[$i]['x'], $slots[$i]['y'], $slots[$i]['w'], $slots[$i]['h'], 'F'); + + // Write new serial + $pdf->SetXY($slots[$i]['x'], $slots[$i]['y']); + $pdf->Cell($slots[$i]['w'], $slots[$i]['h'], $serial, 0, 0, 'L'); + } + + // Save the final PDF + $pdf->Output('F', $outputPath); + + // Download + return response()->download($outputPath); + } + } + 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\Field::make('camera_capture') + ->view('fields.camera-capture'), + 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('id') + ->label('ID') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('plant.name') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('item.id') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('created_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('updated_at') + ->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(), + ]), + ]); + } + + public static function getRelations(): array + { + return [ + // + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListOcrValidations::route('/'), + 'create' => Pages\CreateOcrValidation::route('/create'), + 'view' => Pages\ViewOcrValidation::route('/{record}'), + 'edit' => Pages\EditOcrValidation::route('/{record}/edit'), + ]; + } + + public static function getEloquentQuery(): Builder + { + return parent::getEloquentQuery() + ->withoutGlobalScopes([ + SoftDeletingScope::class, + ]); + } +} diff --git a/app/Filament/Resources/OcrValidationResource/Pages/CreateOcrValidation.php b/app/Filament/Resources/OcrValidationResource/Pages/CreateOcrValidation.php new file mode 100644 index 0000000..437b722 --- /dev/null +++ b/app/Filament/Resources/OcrValidationResource/Pages/CreateOcrValidation.php @@ -0,0 +1,12 @@ +