From 49a49cdb08b78b052891bdb07817ac80e6641f61 Mon Sep 17 00:00:00 2001 From: michele Date: Wed, 22 Apr 2026 21:54:56 +0000 Subject: [PATCH] fix: refine archive label printing and public qr --- README.md | 3 +- .../Pages/Strumenti/DocumentiArchivio.php | 324 ++++++++++-------- .../Filament/DocumentiPrintController.php | 54 ++- app/Models/DocumentoArchivioFisicoItem.php | 56 +-- .../Filament/AdminFilamentPanelProvider.php | 16 +- config/app.php | 2 + docs/DOCUMENTI-NFC-E-ACQUISIZIONE.md | 44 +++ .../strumenti/documenti-archivio.blade.php | 39 ++- .../print/etichetta-archivio-fisico.blade.php | 182 ++++++++-- routes/web.php | 2 +- 10 files changed, 475 insertions(+), 247 deletions(-) diff --git a/README.md b/README.md index 79527b9..a1abbc0 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,8 @@ ## Struttura documentazione ## Stato operativo recente - Strumenti > Documenti apre ora una dashboard `Protocollo comunicazioni` con ricerca, filtri e anteprima PDF. -- Le etichette archivio fisico generano il QR in locale e supportano i formati DYMO `11354` e `99014`. +- Le etichette archivio fisico generano il QR in locale, supportano i formati DYMO `11354` e `99014` e usano un URL pubblico configurabile tramite `APP_PUBLIC_URL`. +- La vista `Archivio digitale` usa ora una tabella a tutta larghezza con riepilogo rapido della cartella corrente. - La topbar contestuale Filament usa layout a capo, senza scrollbar orizzontale. ## Contribuire diff --git a/app/Filament/Pages/Strumenti/DocumentiArchivio.php b/app/Filament/Pages/Strumenti/DocumentiArchivio.php index cf9cc02..89007d6 100644 --- a/app/Filament/Pages/Strumenti/DocumentiArchivio.php +++ b/app/Filament/Pages/Strumenti/DocumentiArchivio.php @@ -49,7 +49,7 @@ class DocumentiArchivio extends Page implements HasTable public string $protocolloView = 'cards'; - #[Url(as: 'folder')] + #[Url( as : 'folder')] public ?int $currentFolderId = null; public array $physicalArchiveForm = []; @@ -292,15 +292,15 @@ public function table(Table $table): Table ->hiddenLabel() ->icon('heroicon-o-archive-box') ->tooltip('Collega archivio fisico') - ->fillForm(fn(Documento $record): array => [ - 'supporto_fisico' => data_get($record->metadati_archivio ?? [], 'supporto_fisico'), - 'modello_etichetta' => data_get($record->metadati_archivio ?? [], 'modello_etichetta', '11354'), - 'busta_numero' => data_get($record->metadati_archivio ?? [], 'busta_numero'), - 'fascicolo_numero' => data_get($record->metadati_archivio ?? [], 'fascicolo_numero'), - 'contenitore_numero' => data_get($record->metadati_archivio ?? [], 'contenitore_numero'), + ->fillForm(fn(Documento $record): array=> [ + 'supporto_fisico' => data_get($record->metadati_archivio ?? [], 'supporto_fisico'), + 'modello_etichetta' => data_get($record->metadati_archivio ?? [], 'modello_etichetta', '11354'), + 'busta_numero' => data_get($record->metadati_archivio ?? [], 'busta_numero'), + 'fascicolo_numero' => data_get($record->metadati_archivio ?? [], 'fascicolo_numero'), + 'contenitore_numero' => data_get($record->metadati_archivio ?? [], 'contenitore_numero'), 'periodo_riferimento_da' => data_get($record->metadati_archivio ?? [], 'periodo_da'), - 'periodo_riferimento_a' => data_get($record->metadati_archivio ?? [], 'periodo_a'), - 'watermark_predefinito' => (bool) data_get($record->metadati_archivio ?? [], 'watermark_predefinito', false), + 'periodo_riferimento_a' => data_get($record->metadati_archivio ?? [], 'periodo_a'), + 'watermark_predefinito' => (bool) data_get($record->metadati_archivio ?? [], 'watermark_predefinito', false), ]) ->form([ Select::make('supporto_fisico') @@ -327,16 +327,16 @@ public function table(Table $table): Table ->default(false), ]) ->action(function (Documento $record, array $data): void { - $meta = is_array($record->metadati_archivio ?? null) ? $record->metadati_archivio : []; - $meta['supporto_fisico'] = $this->normalizeNullableText($data['supporto_fisico'] ?? null); - $meta['modello_etichetta'] = $this->normalizeNullableText($data['modello_etichetta'] ?? null); - $meta['contenitore_numero'] = $this->normalizeNullableText($data['contenitore_numero'] ?? null); - $meta['busta_numero'] = $this->normalizeNullableText($data['busta_numero'] ?? null); - $meta['fascicolo_numero'] = $this->normalizeNullableText($data['fascicolo_numero'] ?? null); - $meta['periodo_da'] = $data['periodo_riferimento_da'] ?? null; - $meta['periodo_a'] = $data['periodo_riferimento_a'] ?? null; + $meta = is_array($record->metadati_archivio ?? null) ? $record->metadati_archivio : []; + $meta['supporto_fisico'] = $this->normalizeNullableText($data['supporto_fisico'] ?? null); + $meta['modello_etichetta'] = $this->normalizeNullableText($data['modello_etichetta'] ?? null); + $meta['contenitore_numero'] = $this->normalizeNullableText($data['contenitore_numero'] ?? null); + $meta['busta_numero'] = $this->normalizeNullableText($data['busta_numero'] ?? null); + $meta['fascicolo_numero'] = $this->normalizeNullableText($data['fascicolo_numero'] ?? null); + $meta['periodo_da'] = $data['periodo_riferimento_da'] ?? null; + $meta['periodo_a'] = $data['periodo_riferimento_a'] ?? null; $meta['watermark_predefinito'] = (bool) ($data['watermark_predefinito'] ?? false); - $record->metadati_archivio = $meta; + $record->metadati_archivio = $meta; $record->save(); Notification::make() @@ -434,6 +434,30 @@ public function getDigitalArchiveCurrentFolderProperty(): ?DocumentoArchivioCart return DocumentoArchivioCartella::query()->find($this->currentFolderId); } + public function getDigitalArchiveCurrentFolderDocumentCountProperty(): int + { + $stabileId = (int) ($this->resolveActiveStabile()?->id ?? 0); + if ($stabileId <= 0 || ! $this->currentFolderId) { + return 0; + } + + return (int) Documento::query() + ->where('stabile_id', $stabileId) + ->where('tipo_documento', 'fattura') + ->where('cartella_archivio_id', $this->currentFolderId) + ->count(); + } + + public function getDigitalArchiveCurrentFolderHintProperty(): string + { + $folder = $this->digitalArchiveCurrentFolder; + if (! $folder instanceof DocumentoArchivioCartella) { + return 'Seleziona la cartella annuale per vedere l’elenco dei PDF già ordinati per protocollo e data.'; + } + + return trim((string) ($folder->percorso_logico ?: $folder->nome)); + } + public function getDigitalArchiveFoldersProperty(): array { $stabile = $this->resolveActiveStabile(); @@ -448,10 +472,10 @@ public function getDigitalArchiveFoldersProperty(): array if (! $this->currentFolderId) { return [[ - 'id' => (int) $root->id, - 'nome' => (string) $root->nome, + 'id' => (int) $root->id, + 'nome' => (string) $root->nome, 'descrizione' => 'Cartella fatture PDF', - 'conteggio' => (int) Documento::query() + 'conteggio' => (int) Documento::query() ->where('stabile_id', $stabile->id) ->where('tipo_documento', 'fattura') ->count(), @@ -464,11 +488,11 @@ public function getDigitalArchiveFoldersProperty(): array ->orderBy('sort_order') ->orderBy('nome') ->get() - ->map(fn(DocumentoArchivioCartella $folder): array => [ - 'id' => (int) $folder->id, - 'nome' => (string) $folder->nome, + ->map(fn(DocumentoArchivioCartella $folder): array=> [ + 'id' => (int) $folder->id, + 'nome' => (string) $folder->nome, 'descrizione' => (string) ($folder->percorso_logico ?: $folder->nome), - 'conteggio' => (int) $folder->documenti()->count(), + 'conteggio' => (int) $folder->documenti()->count(), ]) ->all(); } @@ -476,7 +500,7 @@ public function getDigitalArchiveFoldersProperty(): array public function getDigitalArchiveBreadcrumbsProperty(): array { $items = [[ - 'label' => $this->digitalArchiveRootLabel, + 'label' => $this->digitalArchiveRootLabel, 'folder_id' => null, ]]; @@ -488,7 +512,7 @@ public function getDigitalArchiveBreadcrumbsProperty(): array $chain = collect(); while ($current instanceof DocumentoArchivioCartella) { $chain->prepend([ - 'label' => (string) $current->nome, + 'label' => (string) $current->nome, 'folder_id' => (int) $current->id, ]); $current = $current->parent; @@ -546,26 +570,26 @@ public function getArchivioFisicoTypesProperty(): array public function getArchivioClasseOptions(): array { return [ - 'libro_verbali' => 'Libro verbali', - 'planimetria_stabile' => 'Planimetria stabile', - 'elaborato_planimetrico' => 'Elaborato planimetrico', + 'libro_verbali' => 'Libro verbali', + 'planimetria_stabile' => 'Planimetria stabile', + 'elaborato_planimetrico' => 'Elaborato planimetrico', 'scheda_anagrafica_condominiale' => 'Scheda anagrafica condominiale', - 'fascicolo_fabbricato' => 'Fascicolo fabbricato', - 'polizza_fabbricato' => 'Polizza global fabbricato', - 'certificazioni_impianti' => 'Certificazioni e conformita impianti', - 'decreti_vincolo' => 'Decreti di vincolo', - 'tabelle_millesimali' => 'Tabelle millesimali', - 'regolamento_condominio' => 'Regolamento di condominio', - 'rendiconti_approvati' => 'Rendiconti approvati', - 'raccolta_contratti' => 'Raccolta contratti stipulati', - 'servitu_diritti_terzi' => 'Servitu e diritti di terzi', - 'giustificativi_spesa' => 'Giustificativi di spesa', - 'scritture_contabili' => 'Scritture contabili e sostituto imposta', - 'codice_fiscale' => 'Codice fiscale', - 'partita_iva_amministratore' => 'Partita IVA amministratore', - 'chiavi_stabile' => 'Chiavi stabile', - 'timbri_stabile' => 'Timbri stabile', - 'altro' => 'Altro contenuto archivio', + 'fascicolo_fabbricato' => 'Fascicolo fabbricato', + 'polizza_fabbricato' => 'Polizza global fabbricato', + 'certificazioni_impianti' => 'Certificazioni e conformita impianti', + 'decreti_vincolo' => 'Decreti di vincolo', + 'tabelle_millesimali' => 'Tabelle millesimali', + 'regolamento_condominio' => 'Regolamento di condominio', + 'rendiconti_approvati' => 'Rendiconti approvati', + 'raccolta_contratti' => 'Raccolta contratti stipulati', + 'servitu_diritti_terzi' => 'Servitu e diritti di terzi', + 'giustificativi_spesa' => 'Giustificativi di spesa', + 'scritture_contabili' => 'Scritture contabili e sostituto imposta', + 'codice_fiscale' => 'Codice fiscale', + 'partita_iva_amministratore' => 'Partita IVA amministratore', + 'chiavi_stabile' => 'Chiavi stabile', + 'timbri_stabile' => 'Timbri stabile', + 'altro' => 'Altro contenuto archivio', ]; } @@ -620,7 +644,7 @@ public function getPhysicalArchiveParentOptionsProperty(): array ->whereIn('tipo_item', ['busta_trasparente', 'cartella_tre_lembi', 'faldone_anelli', 'faldone_lacci', 'scatola']) ->orderBy('codice_univoco') ->get(['id', 'codice_univoco', 'titolo']) - ->mapWithKeys(fn(DocumentoArchivioFisicoItem $item): array => [ + ->mapWithKeys(fn(DocumentoArchivioFisicoItem $item): array=> [ (string) $item->id => trim($item->codice_univoco . ' · ' . $item->titolo), ]) ->all(); @@ -682,17 +706,17 @@ public function getPhysicalArchiveRowsProperty(): array ->get() ->map(function (DocumentoArchivioFisicoItem $item): array { return [ - 'id' => (int) $item->id, - 'codice_univoco' => (string) $item->codice_univoco, - 'tipo' => (string) $item->tipo_label, - 'titolo' => (string) $item->titolo, - 'voce' => trim(collect([$item->voce_numero ? ('Voce ' . $item->voce_numero) : null, $item->voce_titolo])->filter()->implode(' · ')), + 'id' => (int) $item->id, + 'codice_univoco' => (string) $item->codice_univoco, + 'tipo' => (string) $item->tipo_label, + 'titolo' => (string) $item->titolo, + 'voce' => trim(collect([$item->voce_numero ? ('Voce ' . $item->voce_numero) : null, $item->voce_titolo])->filter()->implode(' · ')), 'data_archiviazione' => $item->data_archiviazione?->format('d-m-Y') ?: '—', - 'parent' => $item->parent ? trim($item->parent->codice_univoco . ' · ' . $item->parent->titolo) : 'Radice', - 'percorso' => (string) $item->percorso_fisico, - 'documento' => $item->documento ? trim((string) ($item->documento->nome_file ?: $item->documento->nome ?: ('Documento #' . $item->documento->id))) : null, - 'ubicazione' => collect([$item->magazzino, $item->scaffale, $item->ripiano, $item->ubicazione_dettaglio])->filter()->implode(' · '), - 'modello_etichetta' => (string) ($item->modello_etichetta ?: '11354'), + 'parent' => $item->parent ? trim($item->parent->codice_univoco . ' · ' . $item->parent->titolo) : 'Radice', + 'percorso' => (string) $item->percorso_fisico, + 'documento' => $item->documento ? trim((string) ($item->documento->nome_file ?: $item->documento->nome ?: ('Documento #' . $item->documento->id))): null, + 'ubicazione' => collect([$item->magazzino, $item->scaffale, $item->ripiano, $item->ubicazione_dettaglio])->filter()->implode(' · '), + 'modello_etichetta' => (string) ($item->modello_etichetta ?: '11354'), ]; }) ->all(); @@ -712,10 +736,10 @@ public function getPhysicalArchiveContainerTreeProperty(): array ->get() ->map(function (DocumentoArchivioFisicoItem $item): array { return [ - 'id' => (int) $item->id, + 'id' => (int) $item->id, 'codice_univoco' => (string) $item->codice_univoco, - 'titolo' => (string) $item->titolo, - 'tipo' => (string) $item->tipo_label, + 'titolo' => (string) $item->titolo, + 'tipo' => (string) $item->tipo_label, 'children_count' => (int) $item->children()->count(), ]; }) @@ -736,7 +760,7 @@ public function savePhysicalArchiveEntry(): void return; } - $titolo = trim((string) ($this->physicalArchiveForm['titolo'] ?? '')); + $titolo = trim((string) ($this->physicalArchiveForm['titolo'] ?? '')); $tipoItem = trim((string) ($this->physicalArchiveForm['tipo_item'] ?? 'documento')); if ($titolo === '' || ! array_key_exists($tipoItem, DocumentoArchivioFisicoItem::TIPI)) { Notification::make()->title('Titolo e tipologia sono obbligatori')->danger()->send(); @@ -744,7 +768,7 @@ public function savePhysicalArchiveEntry(): void } $parentId = is_numeric($this->physicalArchiveForm['parent_id'] ?? null) ? (int) $this->physicalArchiveForm['parent_id'] : null; - $parent = $parentId + $parent = $parentId ? DocumentoArchivioFisicoItem::query()->where('stabile_id', $stabileId)->find($parentId) : null; @@ -756,34 +780,34 @@ public function savePhysicalArchiveEntry(): void } $item = DocumentoArchivioFisicoItem::query()->create([ - 'stabile_id' => $stabileId, - 'parent_id' => $parent?->id, - 'documento_id' => is_numeric($this->physicalArchiveForm['documento_id'] ?? null) ? (int) $this->physicalArchiveForm['documento_id'] : null, - 'voce_numero' => $voceNumero, - 'voce_titolo' => $voceTitolo !== '' ? $voceTitolo : null, - 'tipo_item' => $tipoItem, - 'titolo' => $titolo, - 'note' => $this->normalizeNullableText($this->physicalArchiveForm['note'] ?? null), - 'data_archiviazione' => $this->physicalArchiveForm['data_archiviazione'] ?? now()->toDateString(), - 'supporto_fisico' => $this->normalizeNullableText($this->physicalArchiveForm['supporto_fisico'] ?? null), - 'modello_etichetta' => $this->normalizeNullableText($this->physicalArchiveForm['modello_etichetta'] ?? null) ?: '11354', - 'magazzino' => $this->normalizeNullableText($this->physicalArchiveForm['magazzino'] ?? null), - 'scaffale' => $this->normalizeNullableText($this->physicalArchiveForm['scaffale'] ?? null), - 'ripiano' => $this->normalizeNullableText($this->physicalArchiveForm['ripiano'] ?? null), + 'stabile_id' => $stabileId, + 'parent_id' => $parent?->id, + 'documento_id' => is_numeric($this->physicalArchiveForm['documento_id'] ?? null) ? (int) $this->physicalArchiveForm['documento_id'] : null, + 'voce_numero' => $voceNumero, + 'voce_titolo' => $voceTitolo !== '' ? $voceTitolo : null, + 'tipo_item' => $tipoItem, + 'titolo' => $titolo, + 'note' => $this->normalizeNullableText($this->physicalArchiveForm['note'] ?? null), + 'data_archiviazione' => $this->physicalArchiveForm['data_archiviazione'] ?? now()->toDateString(), + 'supporto_fisico' => $this->normalizeNullableText($this->physicalArchiveForm['supporto_fisico'] ?? null), + 'modello_etichetta' => $this->normalizeNullableText($this->physicalArchiveForm['modello_etichetta'] ?? null) ?: '11354', + 'magazzino' => $this->normalizeNullableText($this->physicalArchiveForm['magazzino'] ?? null), + 'scaffale' => $this->normalizeNullableText($this->physicalArchiveForm['scaffale'] ?? null), + 'ripiano' => $this->normalizeNullableText($this->physicalArchiveForm['ripiano'] ?? null), 'ubicazione_dettaglio' => $this->normalizeNullableText($this->physicalArchiveForm['ubicazione_dettaglio'] ?? null), - 'created_by' => (int) $user->id, - 'updated_by' => (int) $user->id, - 'metadati' => [ + 'created_by' => (int) $user->id, + 'updated_by' => (int) $user->id, + 'metadati' => [ 'origine_digitale' => is_numeric($this->physicalArchiveForm['documento_id'] ?? null), ], ]); if ($item->documento instanceof Documento) { - $meta = is_array($item->documento->metadati_archivio ?? null) ? $item->documento->metadati_archivio : []; + $meta = is_array($item->documento->metadati_archivio ?? null) ? $item->documento->metadati_archivio : []; $meta['physical_archive_item_id'] = (int) $item->id; - $meta['physical_archive_code'] = (string) $item->codice_univoco; - $meta['contenitore_numero'] = $parent?->codice_univoco; - $meta['supporto_fisico'] = $item->supporto_fisico; + $meta['physical_archive_code'] = (string) $item->codice_univoco; + $meta['contenitore_numero'] = $parent?->codice_univoco; + $meta['supporto_fisico'] = $item->supporto_fisico; $item->documento->forceFill([ 'metadati_archivio' => $meta, ])->save(); @@ -827,7 +851,7 @@ public function movePhysicalArchiveItem(): void } $source->forceFill([ - 'parent_id' => (int) $target->id, + 'parent_id' => (int) $target->id, 'updated_by' => Auth::id(), ])->save(); @@ -902,8 +926,8 @@ public function getProtocolloComunicazioniStatsProperty(): array $query = $this->getProtocolloComunicazioniQuery(); return [ - 'totale' => (clone $query)->count(), - 'con_pdf' => (clone $query) + 'totale' => (clone $query)->count(), + 'con_pdf' => (clone $query) ->where(function (Builder $builder): void { $builder->whereNotNull('percorso_file') ->orWhereNotNull('path_file'); @@ -912,7 +936,7 @@ public function getProtocolloComunicazioniStatsProperty(): array 'questo_mese' => (clone $query) ->whereDate('created_at', '>=', now()->startOfMonth()->toDateString()) ->count(), - 'categorie' => (clone $query) + 'categorie' => (clone $query) ->reorder() ->select('tipo_documento') ->distinct() @@ -935,13 +959,13 @@ public function getProtocolloComunicazioniCategoryOptionsProperty(): array $labels = $this->getCategorieOptions(); return collect($visibleCategories) - ->mapWithKeys(fn(string $value): array => [$value => $labels[$value] ?? Str::headline($value)]) + ->mapWithKeys(fn(string $value): array=> [$value => $labels[$value] ?? Str::headline($value)]) ->all(); } public function getProtocolloComunicazioniRowsProperty(): array { - $limit = $this->protocolloView === 'list' ? 80 : 18; + $limit = $this->protocolloView === 'list' ? 80 : 18; $labels = $this->getCategorieOptions(); return $this->getProtocolloComunicazioniQuery() @@ -950,23 +974,23 @@ public function getProtocolloComunicazioniRowsProperty(): array ->get() ->map(function (Documento $documento) use ($labels): array { $openUrl = route('filament.documenti.download', $documento) . '?inline=1'; - $tipo = trim((string) ($documento->tipo_documento ?? '')); + $tipo = trim((string) ($documento->tipo_documento ?? '')); return [ - 'id' => (int) $documento->id, - 'protocollo' => trim((string) ($documento->numero_protocollo ?: 'DOC-' . $documento->id)), - 'titolo' => trim((string) ($documento->nome ?: $documento->nome_file ?: ('Documento #' . $documento->id))), - 'descrizione' => trim((string) ($documento->descrizione ?: Str::limit((string) ($documento->contenuto_ocr ?? ''), 140, '...'))), - 'categoria' => $labels[$tipo] ?? ($tipo !== '' ? Str::headline($tipo) : 'Protocollo generale'), - 'fornitore' => trim((string) ($documento->fornitore ?? '')), - 'data' => $documento->data_documento?->format('d/m/Y') + 'id' => (int) $documento->id, + 'protocollo' => trim((string) ($documento->numero_protocollo ?: 'DOC-' . $documento->id)), + 'titolo' => trim((string) ($documento->nome ?: $documento->nome_file ?: ('Documento #' . $documento->id))), + 'descrizione' => trim((string) ($documento->descrizione ?: Str::limit((string) ($documento->contenuto_ocr ?? ''), 140, '...'))), + 'categoria' => $labels[$tipo] ?? ($tipo !== '' ? Str::headline($tipo) : 'Protocollo generale'), + 'fornitore' => trim((string) ($documento->fornitore ?? '')), + 'data' => $documento->data_documento?->format('d/m/Y') ?: ($documento->created_at?->format('d/m/Y') ?: '—'), - 'cartella' => trim((string) ($documento->cartellaArchivio?->nome ?? 'Protocollo generale')), + 'cartella' => trim((string) ($documento->cartellaArchivio?->nome ?? 'Protocollo generale')), 'archive_reference' => trim((string) ($documento->archive_reference ?? '')), - 'has_pdf' => $this->hasPdf($documento), - 'preview_url' => $openUrl, - 'download_url' => route('filament.documenti.download', $documento), - 'print_url' => $openUrl, + 'has_pdf' => $this->hasPdf($documento), + 'preview_url' => $openUrl, + 'download_url' => route('filament.documenti.download', $documento), + 'print_url' => $openUrl, ]; }) ->all(); @@ -1160,20 +1184,20 @@ private function getStabiliOptions(): array private function initializePhysicalArchiveForms(): void { $this->physicalArchiveForm = [ - 'data_archiviazione' => now()->toDateString(), - 'voce_numero' => null, - 'voce_titolo' => '', - 'titolo' => '', - 'note' => '', - 'tipo_item' => 'documento', - 'supporto_fisico' => 'Busta trasparente con anelli da archiviare', - 'parent_id' => null, - 'documento_id' => null, - 'magazzino' => '', - 'scaffale' => '', - 'ripiano' => '', + 'data_archiviazione' => now()->toDateString(), + 'voce_numero' => null, + 'voce_titolo' => '', + 'titolo' => '', + 'note' => '', + 'tipo_item' => 'documento', + 'supporto_fisico' => 'Busta trasparente con anelli da archiviare', + 'parent_id' => null, + 'documento_id' => null, + 'magazzino' => '', + 'scaffale' => '', + 'ripiano' => '', 'ubicazione_dettaglio' => '', - 'modello_etichetta' => '11354', + 'modello_etichetta' => '11354', ]; $this->physicalArchiveMoveForm = [ @@ -1279,7 +1303,7 @@ private function syncInvoiceFolders(): void ->orderBy('id') ->get(['id', 'data_documento', 'cartella_archivio_id']) ->each(function (Documento $documento) use ($stabile, $root): void { - $year = (int) (($documento->data_documento?->format('Y')) ?: now()->format('Y')); + $year = (int) (($documento->data_documento?->format('Y')) ?: now()->format('Y')); $yearFolder = $this->ensureInvoiceYearFolder((int) $stabile->id, $root, $year); if (! $yearFolder instanceof DocumentoArchivioCartella) { return; @@ -1313,16 +1337,16 @@ private function ensureInvoiceRootFolder(int $stabileId): ?DocumentoArchivioCart return DocumentoArchivioCartella::query()->firstOrCreate( [ 'stabile_id' => $stabileId, - 'parent_id' => null, - 'slug' => 'fatture-pdf', + 'parent_id' => null, + 'slug' => 'fatture-pdf', ], [ - 'nome' => 'fatture_PDF', - 'codice' => 'FATTURE', - 'percorso_logico' => 'fatture_PDF', + 'nome' => 'fatture_PDF', + 'codice' => 'FATTURE', + 'percorso_logico' => 'fatture_PDF', 'visibility_scope' => 'interno', - 'created_by' => Auth::id(), - 'updated_by' => Auth::id(), + 'created_by' => Auth::id(), + 'updated_by' => Auth::id(), ] ); } @@ -1336,16 +1360,16 @@ private function ensureInvoiceYearFolder(int $stabileId, DocumentoArchivioCartel return DocumentoArchivioCartella::query()->firstOrCreate( [ 'stabile_id' => $stabileId, - 'parent_id' => (int) $root->id, - 'slug' => (string) $year, + 'parent_id' => (int) $root->id, + 'slug' => (string) $year, ], [ - 'nome' => (string) $year, - 'codice' => 'FATT-' . $year, - 'percorso_logico' => trim((string) $root->nome) . '/' . $year, + 'nome' => (string) $year, + 'codice' => 'FATT-' . $year, + 'percorso_logico' => trim((string) $root->nome) . '/' . $year, 'visibility_scope' => 'interno', - 'created_by' => Auth::id(), - 'updated_by' => Auth::id(), + 'created_by' => Auth::id(), + 'updated_by' => Auth::id(), ] ); } @@ -1604,8 +1628,8 @@ private function createDocumentoFromForm(array $data, bool $isDemo): void $note = 'Faldone: ' . $faldone; } - $tipologia = $this->mapCategoriaToTipologia($categoria); - $archivioClasse = trim((string) ($data['archivio_classe'] ?? '')); + $tipologia = $this->mapCategoriaToTipologia($categoria); + $archivioClasse = trim((string) ($data['archivio_classe'] ?? '')); $archiveReference = $this->buildArchiveReference($stabileId, $categoria, $year, $data); $doc = Documento::query()->create([ @@ -1632,18 +1656,18 @@ private function createDocumentoFromForm(array $data, bool $isDemo): void 'estensione' => 'pdf', 'dimensione_file' => $size, 'metadati_archivio' => [ - 'classe' => $archivioClasse !== '' ? $archivioClasse : null, - 'classe_label' => $this->getArchivioClasseOptions()[$archivioClasse] ?? null, - 'supporto_fisico' => $this->normalizeNullableText($data['supporto_fisico'] ?? null), - 'modello_etichetta' => $this->normalizeNullableText($data['modello_etichetta'] ?? null), - 'busta_numero' => $this->normalizeNullableText($data['busta_numero'] ?? null), - 'fascicolo_numero' => $this->normalizeNullableText($data['fascicolo_numero'] ?? null), + 'classe' => $archivioClasse !== '' ? $archivioClasse : null, + 'classe_label' => $this->getArchivioClasseOptions()[$archivioClasse] ?? null, + 'supporto_fisico' => $this->normalizeNullableText($data['supporto_fisico'] ?? null), + 'modello_etichetta' => $this->normalizeNullableText($data['modello_etichetta'] ?? null), + 'busta_numero' => $this->normalizeNullableText($data['busta_numero'] ?? null), + 'fascicolo_numero' => $this->normalizeNullableText($data['fascicolo_numero'] ?? null), 'contenitore_numero' => $this->normalizeNullableText($data['contenitore_numero'] ?? null), - 'periodo_da' => $data['periodo_riferimento_da'] ?? null, - 'periodo_a' => $data['periodo_riferimento_a'] ?? null, - 'codice_etichetta' => $archiveReference, - 'qr_ready' => true, - 'nfc_ready' => true, + 'periodo_da' => $data['periodo_riferimento_da'] ?? null, + 'periodo_a' => $data['periodo_riferimento_a'] ?? null, + 'codice_etichetta' => $archiveReference, + 'qr_ready' => true, + 'nfc_ready' => true, ], 'visibility_scope' => (string) ($data['visibility_scope'] ?? 'interno'), 'visibility_roles' => $this->normalizeStringArray($data['visibility_roles'] ?? []), @@ -1807,18 +1831,18 @@ private function generateProtocollo(string $categoria, int $year): string private function buildArchiveReference(int $stabileId, string $categoria, int $year, array $data): string { - $stabile = Stabile::query()->find($stabileId); + $stabile = Stabile::query()->find($stabileId); $mnemonic = $this->mnemonicCodeHint; if (! $mnemonic && $stabile instanceof Stabile) { - $label = Str::upper((string) ($stabile->denominazione ?? 'STABILE')); - $letters = preg_replace('/[^A-Z]/', '', Str::ascii($label)) ?: 'STB'; - $digits = preg_replace('/\D/', '', $label); + $label = Str::upper((string) ($stabile->denominazione ?? 'STABILE')); + $letters = preg_replace('/[^A-Z]/', '', Str::ascii($label)) ?: 'STB'; + $digits = preg_replace('/\D/', '', $label); $mnemonic = str_pad(substr($letters, 0, 3), 3, 'X') . str_pad(substr($digits !== '' ? $digits : (string) $stabile->id, -5), 5, '0', STR_PAD_LEFT); } $contenitore = $this->normalizeNullableText($data['contenitore_numero'] ?? $data['faldone'] ?? null) ?: '00'; - $fascicolo = $this->normalizeNullableText($data['fascicolo_numero'] ?? null) ?: '00/' . $year; + $fascicolo = $this->normalizeNullableText($data['fascicolo_numero'] ?? null) ?: '00/' . $year; return implode(' · ', array_filter([ $mnemonic ?: 'STB00000', @@ -1846,8 +1870,8 @@ private function buildDocumentStorageFilename(string $categoria, mixed $dataDocu ? ($fornitore !== '' ? $fornitore : $titolo) : $titolo; - $safeLabel = trim((string) Str::of($sourceLabel)->ascii()->replaceMatches('/[^A-Za-z0-9]+/', ' ')->squish()); - $safeLabel = str_replace(' ', '_', Str::limit($safeLabel !== '' ? $safeLabel : 'documento', 60, '')); + $safeLabel = trim((string) Str::of($sourceLabel)->ascii()->replaceMatches('/[^A-Za-z0-9]+/', ' ')->squish()); + $safeLabel = str_replace(' ', '_', Str::limit($safeLabel !== '' ? $safeLabel : 'documento', 60, '')); $safeProtocollo = str_replace(['/', ' '], '-', trim($protocollo)); if ($categoria === 'fattura') { diff --git a/app/Http/Controllers/Filament/DocumentiPrintController.php b/app/Http/Controllers/Filament/DocumentiPrintController.php index ce50381..676fb0d 100644 --- a/app/Http/Controllers/Filament/DocumentiPrintController.php +++ b/app/Http/Controllers/Filament/DocumentiPrintController.php @@ -164,9 +164,19 @@ public function etichettaArchivioFisico(Request $request, DocumentoArchivioFisic abort(403); } - $format = $request->query('format', '11354'); - $format = in_array($format, ['11354', '99014'], true) ? $format : '11354'; - $defaults = $this->getDymoDefaultsForUser($format); + $format = $request->query('format', '11354'); + $format = in_array($format, ['11354', '99014'], true) ? $format : '11354'; + $labelPrinterMode = $request->boolean('autoprint') + || $request->has('dymo_fix') + || $request->has('dymo_rot') + || $request->has('dymo_dx') + || $request->has('dymo_dy'); + $defaults = $labelPrinterMode ? $this->getDymoDefaultsForUser($format) : [ + 'fix' => false, + 'rot' => 0, + 'dx' => 0.0, + 'dy' => 0.0, + ]; $dymoFix = $request->query('dymo_fix'); if ($dymoFix === null) { @@ -181,24 +191,38 @@ public function etichettaArchivioFisico(Request $request, DocumentoArchivioFisic $dymoDx = $request->has('dymo_dx') ? (float) $request->query('dymo_dx') : (float) ($defaults['dx'] ?? 0); $dymoDy = $request->has('dymo_dy') ? (float) $request->query('dymo_dy') : (float) ($defaults['dy'] ?? 0); + if ($format === '11354' && $dymoFix) { + if (! in_array($dymoRot, [-90, 90], true)) { + $dymoRot = -90; + } + } else { + if (! in_array($dymoRot, [-180, -90, 0, 90, 180], true)) { + $dymoRot = 0; + } + } + + $dymoDx = max(-15.0, min(15.0, $dymoDx)); + $dymoDy = max(-15.0, min(15.0, $dymoDy)); + return view('filament.print.etichetta-archivio-fisico', [ - 'item' => $item->load(['parent', 'children', 'stabile', 'documento']), - 'format' => $format, - 'dymoFix' => $dymoFix, - 'dymoRot' => $dymoRot, - 'dymoDx' => $dymoDx, - 'dymoDy' => $dymoDy, - 'publicUrl' => $item->qr_code_data, + 'item' => $item->load(['parent', 'children', 'stabile', 'documento']), + 'format' => $format, + 'labelPrinterMode' => $labelPrinterMode, + 'dymoFix' => $dymoFix, + 'dymoRot' => $dymoRot, + 'dymoDx' => $dymoDx, + 'dymoDy' => $dymoDy, + 'publicUrl' => $item->buildPublicQrUrl(), ]); } public function showPublicArchivioFisicoItem(Request $request, DocumentoArchivioFisicoItem $item) { - if (! $request->hasValidSignature()) { + if (! $request->hasValidSignature(false)) { abort(403); } - $chain = collect(); + $chain = collect(); $current = $item; while ($current instanceof DocumentoArchivioFisicoItem) { $chain->prepend($current); @@ -206,7 +230,7 @@ public function showPublicArchivioFisicoItem(Request $request, DocumentoArchivio } return view('filament.pages.strumenti.archivio-fisico-show', [ - 'item' => $item->load(['children.children', 'stabile', 'documento', 'parent']), + 'item' => $item->load(['children.children', 'stabile', 'documento', 'parent']), 'chain' => $chain, ]); } @@ -301,7 +325,7 @@ private function buildWatermarkedPdf(string $inputPath, Documento $documento): ? @unlink($outputPath); $postScript = '<< /BeginPage { gsave 0.90 setgray /Helvetica-Bold findfont 14 scalefont setfont 140 90 translate 38 rotate 0 0 moveto (' - . $this->escapePostScriptString($watermarkText) + . $this->escapePostScriptString($watermarkText) . ') show grestore } >> setpagedevice'; $process = new Process([ @@ -332,7 +356,7 @@ private function buildWatermarkedPdf(string $inputPath, Documento $documento): ? private function buildWatermarkText(Documento $documento): string { $archiveReference = trim((string) ($documento->archive_reference ?? '')); - $meta = is_array($documento->metadati_archivio ?? null) ? $documento->metadati_archivio : []; + $meta = is_array($documento->metadati_archivio ?? null) ? $documento->metadati_archivio : []; $physicalParts = array_filter([ trim((string) ($meta['supporto_fisico'] ?? '')), diff --git a/app/Models/DocumentoArchivioFisicoItem.php b/app/Models/DocumentoArchivioFisicoItem.php index 6771b34..35b9f91 100644 --- a/app/Models/DocumentoArchivioFisicoItem.php +++ b/app/Models/DocumentoArchivioFisicoItem.php @@ -1,5 +1,4 @@ 'date', - 'sort_order' => 'integer', - 'metadati' => 'array', - 'created_at' => 'datetime', - 'updated_at' => 'datetime', + 'sort_order' => 'integer', + 'metadati' => 'array', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', ]; public const TIPI = [ - 'documento' => 'Documento cartaceo', - 'busta_trasparente' => 'Busta trasparente con anelli da archiviare', + 'documento' => 'Documento cartaceo', + 'busta_trasparente' => 'Busta trasparente con anelli da archiviare', 'cartella_tre_lembi' => 'Cartella a tre lembi', - 'faldone_anelli' => 'Faldone con anelli', - 'faldone_lacci' => 'Faldone con lacci', - 'scatola' => 'Scatola', + 'faldone_anelli' => 'Faldone con anelli', + 'faldone_lacci' => 'Faldone con lacci', + 'scatola' => 'Scatola', ]; public function stabile(): BelongsTo @@ -94,7 +93,7 @@ public function getTipoLabelAttribute(): string public function getPercorsoFisicoAttribute(): string { - $parts = []; + $parts = []; $current = $this; while ($current instanceof self) { @@ -107,15 +106,15 @@ public function getPercorsoFisicoAttribute(): string public function getQrCodeImageAttribute(): string { - $data = trim((string) $this->qr_code_data); + $data = $this->buildPublicQrUrl(); if ($data !== '' && class_exists(\chillerlan\QRCode\QROptions::class) && class_exists(\chillerlan\QRCode\QRCode::class)) { $options = new \chillerlan\QRCode\QROptions([ - 'outputType' => \chillerlan\QRCode\QRCode::OUTPUT_MARKUP_SVG, - 'eccLevel' => \chillerlan\QRCode\QRCode::ECC_M, - 'addQuietzone' => true, + 'outputType' => \chillerlan\QRCode\QRCode::OUTPUT_MARKUP_SVG, + 'eccLevel' => \chillerlan\QRCode\QRCode::ECC_M, + 'addQuietzone' => true, 'quietzoneSize' => 1, - 'connectPaths' => true, + 'connectPaths' => true, ]); $svg = (new \chillerlan\QRCode\QRCode($options))->render($data); @@ -142,11 +141,11 @@ public function getQrCodeImageAttribute(): string public static function generateCodice(int $stabileId): string { - $prefix = 'AF-' . $stabileId . '-'; + $prefix = 'AF-' . $stabileId . '-'; $sequence = 1; do { - $code = $prefix . str_pad((string) $sequence, 4, '0', STR_PAD_LEFT); + $code = $prefix . str_pad((string) $sequence, 4, '0', STR_PAD_LEFT); $exists = self::query()->where('codice_univoco', $code)->exists(); $sequence++; } while ($exists); @@ -156,15 +155,26 @@ public static function generateCodice(int $stabileId): string public function refreshQrCodeData(): void { - $url = URL::temporarySignedRoute( + $this->forceFill([ + 'qr_code_data' => $this->buildPublicQrUrl(), + ])->saveQuietly(); + } + + public function buildPublicQrUrl(): string + { + $relativeSignedPath = URL::temporarySignedRoute( 'public.archivio-fisico.show', now()->addYears(5), - ['item' => $this->id] + ['item' => $this->id], + false, ); - $this->forceFill([ - 'qr_code_data' => $url, - ])->saveQuietly(); + $baseUrl = rtrim((string) config('app.public_url', config('app.url')), '/'); + if ($baseUrl === '') { + return $relativeSignedPath; + } + + return $baseUrl . '/' . ltrim($relativeSignedPath, '/'); } protected static function booted(): void diff --git a/app/Providers/Filament/AdminFilamentPanelProvider.php b/app/Providers/Filament/AdminFilamentPanelProvider.php index 8288869..85c42dc 100644 --- a/app/Providers/Filament/AdminFilamentPanelProvider.php +++ b/app/Providers/Filament/AdminFilamentPanelProvider.php @@ -60,7 +60,7 @@ public function panel(Panel $panel): Panel $user = Auth::user(); return $user instanceof User - && $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore']); + && $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore']); }), NavigationItem::make('Cellulare / WebApp') ->group('NetGescon') @@ -70,7 +70,7 @@ public function panel(Panel $panel): Panel $user = Auth::user(); return $user instanceof User - && $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore']); + && $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore']); }), NavigationItem::make('Ticket Mobile') ->group('NetGescon') @@ -80,7 +80,7 @@ public function panel(Panel $panel): Panel $user = Auth::user(); return $user instanceof User - && $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore']); + && $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore']); }), NavigationItem::make('Scheda Stabile') ->group('NetGescon') @@ -90,7 +90,7 @@ public function panel(Panel $panel): Panel $user = Auth::user(); return $user instanceof User - && $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore']); + && $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore']); }), NavigationItem::make('Catalogo Fornitore') ->group('Fornitore') @@ -102,8 +102,8 @@ public function panel(Panel $panel): Panel return $user instanceof User && $user->hasRole('fornitore'); }), ]) - ->discoverResources(in: app_path('Filament/Resources'), for : 'App\\Filament\\Resources') - ->discoverPages(in: app_path('Filament/Pages'), for : 'App\\Filament\\Pages') + ->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources') + ->discoverPages(in: app_path('Filament/Pages'), for: 'App\\Filament\\Pages') ->pages([ Dashboard::class, SupportoDashboard::class, @@ -111,7 +111,7 @@ public function panel(Panel $panel): Panel PrimaNotaModifica::class, ContoMastrino::class, ]) - ->discoverWidgets(in: app_path('Filament/Widgets'), for : 'App\\Filament\\Widgets') + ->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\Filament\\Widgets') ->widgets([ AccountWidget::class, TicketMobileOverview::class, @@ -171,4 +171,4 @@ protected function resolveSupplierCatalogUrl(): string return TicketOperativi::getUrl(panel: 'admin-filament'); } -} \ No newline at end of file +} diff --git a/config/app.php b/config/app.php index 3423674..49335df 100755 --- a/config/app.php +++ b/config/app.php @@ -37,6 +37,8 @@ 'url' => env('APP_URL', 'http://localhost'), + 'public_url' => env('APP_PUBLIC_URL', env('APP_URL', 'http://localhost')), + 'asset_url' => env('ASSET_URL'), /* diff --git a/docs/DOCUMENTI-NFC-E-ACQUISIZIONE.md b/docs/DOCUMENTI-NFC-E-ACQUISIZIONE.md index 5f80e60..2bf2af6 100644 --- a/docs/DOCUMENTI-NFC-E-ACQUISIZIONE.md +++ b/docs/DOCUMENTI-NFC-E-ACQUISIZIONE.md @@ -53,6 +53,12 @@ ## Archivio fisico ed etichette - stampa etichette nei formati `DYMO 11354` e `DYMO 99014`; - pagina pubblica firmata per dettaglio contenitore o documento tramite QR. +Taratura operativa corrente: + +- `11354`: layout orizzontale principale con correzione verticale leggera verso l'alto; +- `11354 verticale`: variante dedicata ai driver che ruotano l'etichetta, ora con rotazione corretta lato stampa; +- `99014`: QR spostato in basso a destra per liberare spazio scrivibile nella parte alta. + Per i documenti digitali resta disponibile anche l'assegnazione dei metadati fisici principali: - supporto fisico; @@ -75,6 +81,26 @@ ## QR locale sulle etichette Questo elimina la dipendenza da URL esterni per il QR e rende piu stabile il preview di stampa. +## QR pubblico e dominio esterno + +Il QR dell'archivio fisico non deve piu dipendere dall'IP interno del server. + +Implementazione attuale: + +- la firma della route pubblica viene generata in forma relativa; +- il link finale viene costruito usando `APP_PUBLIC_URL`, con fallback su `APP_URL`; +- la validazione avviene lato controller con firma relativa, cosi il QR resta valido anche dietro dominio pubblico o reverse proxy. + +Configurazione richiesta in ambiente: + +1. impostare `APP_PUBLIC_URL` con il dominio realmente raggiungibile dall'esterno; +2. lasciare `APP_URL` per il contesto applicativo interno se serve; +3. rigenerare o aggiornare i QR gia salvati solo se si vuole riallineare anche il dato persistito nel database. + +Esempio: + +- `APP_PUBLIC_URL=https://netgescon.example.it` + ## Stampa PDF e watermark archivio Per i documenti PDF sono ora previste due aperture distinte dalla tab archivio: @@ -208,6 +234,24 @@ ## Scanner Epson da pagina web 2. upload/ingestione rapida in NetGescon; 3. OCR e archiviazione automatica. +Per il modello Epson WF-C5710 la direzione pratica da testare non e il browser puro, ma una di queste due: + +- scansione verso cartella di rete osservata da NetGescon; +- piccolo bridge locale o di rete che espone una chiamata HTTP interna e usa il canale scanner disponibile sul dispositivo. + +Questo evita il vincolo dei browser su TWAIN/WIA e mantiene il flusso pilotabile dalla pagina archivio. + +## Archivio digitale + +La vista `Strumenti > Documenti > Archivio digitale` e stata alleggerita per lavorare meglio dentro la cartella corrente. + +Stato attuale: + +- breadcrumb e cartelle restano in alto; +- la tabella documenti ora usa tutta la larghezza utile; +- le informazioni laterali sono state compattate in tre card sintetiche sopra la tabella; +- la pagina mostra nome cartella attiva, numero documenti del livello e stato operativo digitale/fisico. + ## Dymo LAN 11354 Domani si puo provare una stampa etichetta su rete con formato `11354` usando: diff --git a/resources/views/filament/pages/strumenti/documenti-archivio.blade.php b/resources/views/filament/pages/strumenti/documenti-archivio.blade.php index dec6724..aabd210 100644 --- a/resources/views/filament/pages/strumenti/documenti-archivio.blade.php +++ b/resources/views/filament/pages/strumenti/documenti-archivio.blade.php @@ -283,24 +283,26 @@ class="rounded-2xl border border-slate-200 bg-white p-4 text-left shadow-sm tran @endforelse -
-
- {{ $this->table }} +
+
+
Cartella attiva
+
{{ $this->digitalArchiveCurrentFolder?->nome ?? 'Nessuna cartella selezionata' }}
+
{{ $this->digitalArchiveCurrentFolderHint }}
-
-
-
Flusso digitale e fisico
-
Usa l'icona archivio per assegnare contenitore, busta, fascicolo ed etichetta del documento cartaceo. La posizione verra poi richiamata anche nel watermark PDF.
-
-
-
Stampa
-
Icona stampante: PDF senza timbro. Icona duplicato: PDF con watermark archivio digitale e fisico, se la codifica e presente.
-
-
-
Scanner
-
La struttura attuale e pronta per il prossimo aggancio scanner: acquisizione PDF, naming ordinato, assegnazione immediata a cartella digitale e posizione fisica.
-
+
+
Documenti nel livello
+
{{ $this->digitalArchiveCurrentFolderDocumentCount }}
+
Solo fatture PDF collegate alla cartella corrente.
+
+
Operatività
+
Archivio digitale e fisico allineati
+
Da qui puoi aprire, stampare, watermarkare e assegnare subito la collocazione cartacea.
+
+
+ +
+ {{ $this->table }}
@@ -509,8 +511,9 @@ class="rounded-2xl border border-slate-200 bg-white p-4 text-left shadow-sm tran @endif
diff --git a/resources/views/filament/print/etichetta-archivio-fisico.blade.php b/resources/views/filament/print/etichetta-archivio-fisico.blade.php index 26cd11d..6a91d9a 100644 --- a/resources/views/filament/print/etichetta-archivio-fisico.blade.php +++ b/resources/views/filament/print/etichetta-archivio-fisico.blade.php @@ -10,17 +10,60 @@ @php($dymoDx = isset($dymoDx) ? (float) $dymoDx : 0.0) @php($dymoDy = isset($dymoDy) ? (float) $dymoDy : 0.0) @php($autoPrint = request()->has('autoprint') && filter_var(request()->query('autoprint'), FILTER_VALIDATE_BOOL)) + @php($labelPrinterMode = isset($labelPrinterMode) ? (bool) $labelPrinterMode : false) + @php($pageWidth = $fmt === '99014' ? '54mm' : '57mm') + @php($pageHeight = $fmt === '99014' ? '101mm' : '32mm') @@ -76,27 +184,39 @@ @endif -
-
-
-
{{ $item->codice_univoco }}
-
{{ $item->titolo }}
-
-
Tipo: {{ $item->tipo_label }}
- @if($item->voce_numero || $item->voce_titolo) -
Voce: {{ $item->voce_numero ? 'Voce ' . $item->voce_numero : '' }} {{ $item->voce_titolo }}
- @endif - @if($item->parent) -
Dentro: {{ $item->parent->codice_univoco }}
- @endif - @if($item->documento) -
Digitale: {{ $item->documento->nome_file ?: $item->documento->nome }}
- @endif +
+
+
+
+
$fmt === '99014'])> +
+
{{ $item->codice_univoco }}
+
{{ $item->titolo }}
+
+ @if($item->stabile) +
Stabile: {{ $item->stabile->denominazione }}
+ @endif +
Tipo: {{ $item->tipo_label }}
+ @if($item->voce_numero || $item->voce_titolo) +
Voce: {{ $item->voce_numero ? 'Voce ' . $item->voce_numero : '' }} {{ $item->voce_titolo }}
+ @endif + @if($item->data_archiviazione) +
Data: {{ $item->data_archiviazione->format('d-m-Y') }}
+ @endif + @if($item->parent) +
Dentro: {{ $item->parent->codice_univoco }}
+ @endif + @if($item->documento) +
Digitale: {{ $item->documento->nome_file ?: $item->documento->nome }}
+ @endif +
+
{{ $item->percorso_fisico }}
+
+
+ {!! $item->qr_code_image !!} +
+
-
{{ $item->percorso_fisico }}
-
-
- {!! $item->qr_code_image !!}
diff --git a/routes/web.php b/routes/web.php index 7a94f27..5b074a2 100755 --- a/routes/web.php +++ b/routes/web.php @@ -727,7 +727,7 @@ // --- AUTHENTICATION ROUTES --- require __DIR__ . '/auth.php'; -Route::middleware('signed')->get('/archivio-fisico/{item}', [\App\Http\Controllers\Filament\DocumentiPrintController::class, 'showPublicArchivioFisicoItem']) +Route::get('/archivio-fisico/{item}', [\App\Http\Controllers\Filament\DocumentiPrintController::class, 'showPublicArchivioFisicoItem']) ->name('public.archivio-fisico.show'); Route::middleware(['auth'])->group(function () {