From 83412247a7fec2eff4c50bd5d39b3ddf65859514 Mon Sep 17 00:00:00 2001 From: Carmine Savino Date: Mon, 18 May 2026 16:23:12 +0200 Subject: [PATCH] Aggiungi campi per immagini e diametro del foro nel modello Articolo e nelle relative migrazioni; aggiorna i form e le viste per gestire i nuovi campi --- CLAUDE.md | 82 ++++++++++++++++++ STRUTTURA DATABASE.xlsx | Bin 11527 -> 17004 bytes .../Controllers/Admin/ArticoloController.php | 74 +++++++++++----- app/Models/Articolo.php | 4 + ..._132945_add_immagini_to_articoli_table.php | 27 ++++++ ...00_add_hole_diameter_to_articoli_table.php | 25 ++++++ resources/css/app.css | 2 + resources/views/admin/articoli/edit.blade.php | 80 ++++++++++++++++- .../views/admin/articoli/index.blade.php | 2 +- resources/views/admin/articoli/show.blade.php | 45 +++++++++- resources/views/public/articolo.blade.php | 65 ++++++++++++-- 11 files changed, 373 insertions(+), 33 deletions(-) create mode 100644 CLAUDE.md create mode 100644 database/migrations/2026_04_28_132945_add_immagini_to_articoli_table.php create mode 100644 database/migrations/2026_04_28_133200_add_hole_diameter_to_articoli_table.php diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..e5cbccb --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,82 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +**HTT QRCode** is a Laravel 12 web application for managing industrial articles with QR code generation and scanning. Key capabilities: article catalog CRUD, unique QR code generation per article, PDF label printing, public QR scanner (no auth required), and Excel import. + +**Stack**: Laravel 12 / PHP 8.2+ · Blade + TailwindCSS 3 + Alpine.js · SQLite (default) or MySQL · Vite · SimpleSoftwareIO/simple-qrcode · Barryvdh/laravel-dompdf · PHPOffice/PhpSpreadsheet + +## Development Commands + +```bash +# Start everything (PHP server + queue + logs + Vite HMR) +composer run dev + +# Or separately: +php artisan serve # http://localhost:8000 +npm run dev # Vite with hot reload + +# Build for production +npm run build + +# Run tests +composer run test +# or +php artisan test +php artisan test --filter NomeTest # single test + +# Database +php artisan migrate +php artisan migrate:fresh --seed # reset + re-seed +php artisan db:seed --class=AdminUserSeeder # admin@example.com / password + +# Code style (Laravel Pint) +./vendor/bin/pint + +# Clear caches +php artisan cache:clear && php artisan config:clear && php artisan view:clear + +# View all routes +php artisan route:list + +# Real-time logs +php artisan pail +``` + +## Architecture + +### Route → Controller → View mapping + +| Route | Controller | View | +|---|---|---| +| `GET /` | closure | `welcome.blade.php` | +| `GET /scanner` | `PublicArticoloController@scanner` | `public/scanner.blade.php` | +| `GET /articolo/{qr_code}` | `PublicArticoloController@show` | `public/articolo.blade.php` | +| `admin/articoli` (resource) | `Admin/ArticoloController` | `admin/articoli/*.blade.php` | + +Admin routes are grouped under `middleware(['auth'])` with prefix `admin/` and name prefix `admin.`. The `/dashboard` route simply redirects to `admin.articoli.index`. + +### Articolo Model + +`qr_code` is auto-generated on `created` event using the format `{id}-{timestamp}`. The `codice_articolo` field is unique. The public scanner URL resolves articles via `qr_code`, not `id`. + +### QR Code features in `ArticoloController` + +- `qrCode()` — renders QR inline as SVG/PNG +- `downloadQrCode()` — streams PNG (300×300px, error correction H) +- `printQrCodes()` — generates multi-article PDF via dompdf using `pdf-qrcodes.blade.php` +- `import()` — Excel import via PhpSpreadsheet; supports "merge" (default) and "clean import" modes + +### Layouts + +- `layouts/app.blade.php` — authenticated area (uses ``) +- `layouts/guest.blade.php` — public/auth pages (uses ``) +- Blade components live in `resources/views/components/` and `app/View/Components/` + +## Database + +Default is **SQLite** (`database/database.sqlite`). The `articoli` table has two unique constraints: `codice_articolo` and `qr_code`. + +Excel import expects these column groups: `UBICAZIONE` (Codice Articolo, Ciclo, Diametro, Descrizione, Posizione, Quantita) and `PARAMETRI TECNOLOGICI` (Tipo Lavorazione, Materiale da lavorare, Maximum Thickness, Speed RPM, Feed, Max Thrust A, Min Torque A, Quantita Fori). diff --git a/STRUTTURA DATABASE.xlsx b/STRUTTURA DATABASE.xlsx index 4e174c431344d9aafe1d783c48e79ea573a0983f..1496bf38631fd6690faa98ea2346996a966a1cef 100644 GIT binary patch delta 14021 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[ 'codice_articolo' => 'required|string|max:255|unique:articoli', 'ciclo' => 'nullable|string|max:255', + 'hole_diameter' => 'nullable|string|max:255', 'diametro' => 'nullable|string|max:255', 'descrizione' => 'nullable|string', 'posizione' => 'nullable|string|max:255', @@ -75,6 +76,7 @@ class ArticoloController extends Controller $validated = $request->validate([ 'codice_articolo' => 'required|string|max:255|unique:articoli,codice_articolo,' . $articolo->id, 'ciclo' => 'nullable|string|max:255', + 'hole_diameter' => 'nullable|string|max:255', 'diametro' => 'nullable|string|max:255', 'descrizione' => 'nullable|string', 'posizione' => 'nullable|string|max:255', @@ -87,8 +89,36 @@ class ArticoloController extends Controller 'max_thrust_a' => 'nullable|string|max:255', 'min_torque_a' => 'nullable|string|max:255', 'quantita_fori' => 'nullable|integer|min:0', + 'immagine_articolo' => 'nullable|image|mimes:jpeg,png,jpg,gif,webp|max:4096', + 'immagine_thrust' => 'nullable|image|mimes:jpeg,png,jpg,gif,webp|max:4096', + 'immagine_tourque' => 'nullable|image|mimes:jpeg,png,jpg,gif,webp|max:4096', + 'rimuovi_immagine_articolo' => 'nullable|boolean', + 'rimuovi_immagine_thrust' => 'nullable|boolean', + 'rimuovi_immagine_tourque' => 'nullable|boolean', ]); + $imageFields = ['immagine_articolo', 'immagine_thrust', 'immagine_tourque']; + + foreach ($imageFields as $field) { + $removeKey = 'rimuovi_' . $field; + + if ($request->boolean($removeKey)) { + if ($articolo->$field) { + Storage::disk('public')->delete($articolo->$field); + } + $validated[$field] = null; + } elseif ($request->hasFile($field)) { + if ($articolo->$field) { + Storage::disk('public')->delete($articolo->$field); + } + $validated[$field] = $request->file($field)->store('articoli', 'public'); + } else { + unset($validated[$field]); + } + + unset($validated[$removeKey]); + } + $articolo->update($validated); return redirect()->route('admin.articoli.show', $articolo) @@ -164,7 +194,7 @@ class ArticoloController extends Controller public function import(Request $request) { $request->validate([ - 'file' => 'required|file|mimes:xlsx,xls', + 'file' => 'required|file|mimetypes:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel,application/octet-stream', 'clean_import' => 'nullable|boolean', ]); @@ -172,7 +202,6 @@ class ArticoloController extends Controller $cleanImport = $request->boolean('clean_import', false); try { - $seeder = new ArticoloSeeder(); $result = $this->importFromExcel($file->getPathname(), $cleanImport); $message = "Import completato! "; @@ -216,6 +245,11 @@ class ArticoloController extends Controller } // Skip header rows (first 2 rows) + // Column layout (v2): 0=Codice Articolo, 1=Immagine Articolo (skip), 2=Ciclo, + // 3=Hole Diameter, 4=Diametro, 5=Descrizione, 6=Posizione, 7=Quantità, + // 8=Tipo lavorazione, 9=Materiale, 10=Max Thickness, 11=Speed RPM, 12=Feed, + // 13=Max Thrust A, 14=Immagine Thrust (skip), 15=Min Torque A, + // 16=Immagine Tourque (skip), 17=Quantità fori foreach (array_slice($rows, 2) as $index => $row) { // Skip empty rows if (empty($row[0])) { @@ -228,19 +262,20 @@ class ArticoloController extends Controller Articolo::updateOrCreate( ['codice_articolo' => $row[0]], [ - 'ciclo' => $row[1] ?? null, - 'diametro' => $row[2] ?? null, - 'descrizione' => $row[3] ?? null, - 'posizione' => $row[4] ?? null, - 'quantita' => is_numeric($row[5]) ? (int) $row[5] : 0, - 'tipo_lavorazione' => $row[6] ?? null, - 'materiale_lavorare' => $row[7] ?? null, - 'maximum_thickness' => $row[8] ?? null, - 'speed_rpm' => is_numeric($row[9]) ? (int) $row[9] : null, - 'feed' => is_numeric($row[10]) ? (float) $row[10] : null, - 'max_thrust_a' => $row[11] ?? null, - 'min_torque_a' => $row[12] ?? null, - 'quantita_fori' => is_numeric($row[13]) ? (int) $row[13] : null, + 'ciclo' => $row[2] ?? null, + 'hole_diameter' => $row[3] ?? null, + 'diametro' => $row[4] ?? null, + 'descrizione' => $row[5] ?? null, + 'posizione' => $row[6] ?? null, + 'quantita' => is_numeric($row[7]) ? (int) round((float) $row[7]) : 0, + 'tipo_lavorazione' => $row[8] ?? null, + 'materiale_lavorare' => $row[9] ?? null, + 'maximum_thickness' => $row[10] ?? null, + 'speed_rpm' => is_numeric($row[11]) ? (int) round((float) $row[11]) : null, + 'feed' => is_numeric($row[12]) ? round((float) $row[12], 2) : null, + 'max_thrust_a' => $row[13] ?? null, + 'min_torque_a' => $row[15] ?? null, + 'quantita_fori' => is_numeric($row[17]) ? (int) round((float) $row[17]) : null, ] ); @@ -250,18 +285,11 @@ class ArticoloController extends Controller $imported++; } - if (isset($this->command)) { - $this->command->info('Importato articolo: ' . $row[0]); - } } catch (\Exception $e) { $errors[] = "Riga " . ($index + 3) . ": " . $e->getMessage(); } } - if (isset($this->command)) { - $this->command->info('Import completato! Totale articoli: ' . Articolo::count()); - } - return [ 'imported' => $imported, 'updated' => $updated, diff --git a/app/Models/Articolo.php b/app/Models/Articolo.php index 6155c4e..a6c92d8 100644 --- a/app/Models/Articolo.php +++ b/app/Models/Articolo.php @@ -9,7 +9,9 @@ class Articolo extends Model protected $fillable = [ 'codice_articolo', + 'immagine_articolo', 'ciclo', + 'hole_diameter', 'diametro', 'descrizione', 'posizione', @@ -20,7 +22,9 @@ class Articolo extends Model 'speed_rpm', 'feed', 'max_thrust_a', + 'immagine_thrust', 'min_torque_a', + 'immagine_tourque', 'quantita_fori', 'qr_code', ]; diff --git a/database/migrations/2026_04_28_132945_add_immagini_to_articoli_table.php b/database/migrations/2026_04_28_132945_add_immagini_to_articoli_table.php new file mode 100644 index 0000000..39ce191 --- /dev/null +++ b/database/migrations/2026_04_28_132945_add_immagini_to_articoli_table.php @@ -0,0 +1,27 @@ +string('immagine_articolo')->nullable()->after('codice_articolo'); + $table->string('immagine_thrust')->nullable()->after('max_thrust_a'); + $table->string('immagine_tourque')->nullable()->after('min_torque_a'); + }); + } + + public function down(): void + { + Schema::table('articoli', function (Blueprint $table) { + $table->dropColumn(['immagine_articolo', 'immagine_thrust', 'immagine_tourque']); + }); + } +}; diff --git a/database/migrations/2026_04_28_133200_add_hole_diameter_to_articoli_table.php b/database/migrations/2026_04_28_133200_add_hole_diameter_to_articoli_table.php new file mode 100644 index 0000000..13c354b --- /dev/null +++ b/database/migrations/2026_04_28_133200_add_hole_diameter_to_articoli_table.php @@ -0,0 +1,25 @@ +string('hole_diameter')->nullable()->after('ciclo'); + }); + } + + public function down(): void + { + Schema::table('articoli', function (Blueprint $table) { + $table->dropColumn('hole_diameter'); + }); + } +}; diff --git a/resources/css/app.css b/resources/css/app.css index b5c61c9..de7488b 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -1,3 +1,5 @@ @tailwind base; @tailwind components; @tailwind utilities; + +[x-cloak] { display: none !important; } diff --git a/resources/views/admin/articoli/edit.blade.php b/resources/views/admin/articoli/edit.blade.php index ccb2030..df844ff 100644 --- a/resources/views/admin/articoli/edit.blade.php +++ b/resources/views/admin/articoli/edit.blade.php @@ -1,3 +1,4 @@ +@use('Illuminate\Support\Facades\Storage')
@@ -15,11 +16,11 @@
-
+
-
+ @csrf @method('PUT') @@ -42,6 +43,12 @@ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
+
+ + +
+
{{ old('descrizione', $articolo->descrizione) }}
+ +
+ + @if ($articolo->immagine_articolo) +
+ Immagine Articolo + +
+ @endif + + @error('immagine_articolo') +

{{ $message }}

+ @enderror +
@@ -108,12 +135,52 @@ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500">
+
+ + @if ($articolo->immagine_thrust) +
+ Immagine Thrust + +
+ @endif + + @error('immagine_thrust') +

{{ $message }}

+ @enderror +
+
+
+ + @if ($articolo->immagine_tourque) +
+ Immagine Tourque + +
+ @endif + + @error('immagine_tourque') +

{{ $message }}

+ @enderror +
+
+ + +
+ +
+
diff --git a/resources/views/admin/articoli/index.blade.php b/resources/views/admin/articoli/index.blade.php index 8d601e7..26515cf 100644 --- a/resources/views/admin/articoli/index.blade.php +++ b/resources/views/admin/articoli/index.blade.php @@ -288,7 +288,7 @@ } function handleFileSelect(file) { - if (file && (file.name.endsWith('.xlsx') || file.name.endsWith('.xls'))) { + if (file && (file.name.toLowerCase().endsWith('.xlsx') || file.name.toLowerCase().endsWith('.xls'))) { const dataTransfer = new DataTransfer(); dataTransfer.items.add(file); fileInput.files = dataTransfer.files; diff --git a/resources/views/admin/articoli/show.blade.php b/resources/views/admin/articoli/show.blade.php index 1c36ab7..ead053b 100644 --- a/resources/views/admin/articoli/show.blade.php +++ b/resources/views/admin/articoli/show.blade.php @@ -1,3 +1,4 @@ +@use('Illuminate\Support\Facades\Storage')
@@ -15,7 +16,7 @@
-
+
@if (session('success'))
@@ -39,6 +40,10 @@
Ciclo
{{ $articolo->ciclo ?? '-' }}
+
+
Hole Diameter
+
{{ $articolo->hole_diameter ?? '-' }}
+
Diametro
{{ $articolo->diametro ?? '-' }}
@@ -55,6 +60,16 @@
Descrizione
{{ $articolo->descrizione ?? '-' }}
+ @if ($articolo->immagine_articolo) +
+
Immagine Articolo
+
+ Immagine Articolo +
+
+ @endif
@@ -88,10 +103,30 @@
Max Thrust (A)
{{ $articolo->max_thrust_a ?? '-' }}
+ @if ($articolo->immagine_thrust) +
+
Immagine Thrust
+
+ Immagine Thrust +
+
+ @endif
Min Torque (A)
{{ $articolo->min_torque_a ?? '-' }}
+ @if ($articolo->immagine_tourque) +
+
Immagine Tourque
+
+ Immagine Tourque +
+
+ @endif
Quantita Fori
{{ $articolo->quantita_fori ?? '-' }}
@@ -146,5 +181,13 @@
+ + +
+ +
diff --git a/resources/views/public/articolo.blade.php b/resources/views/public/articolo.blade.php index d1b6e89..046e4c0 100644 --- a/resources/views/public/articolo.blade.php +++ b/resources/views/public/articolo.blade.php @@ -1,3 +1,4 @@ +@use('Illuminate\Support\Facades\Storage') @@ -5,13 +6,15 @@ {{ $articolo->codice_articolo }} - HTT Locator + - +
@@ -35,7 +38,7 @@
-
+

@@ -46,12 +49,26 @@

+ @if($articolo->immagine_articolo) +
+ Immagine + Immagine Articolo +
+ @endif @if($articolo->ciclo)
Ciclo {{ $articolo->ciclo }}
@endif + @if($articolo->hole_diameter) +
+ Hole Diameter + {{ $articolo->hole_diameter }} +
+ @endif @if($articolo->diametro)
Diametro @@ -121,12 +138,28 @@ {{ $articolo->max_thrust_a }}
@endif + @if($articolo->immagine_thrust) +
+ Immagine Thrust + Immagine Thrust +
+ @endif @if($articolo->min_torque_a)
Min Torque (A) {{ $articolo->min_torque_a }}
@endif + @if($articolo->immagine_tourque) +
+ Immagine Tourque + Immagine Tourque +
+ @endif @if($articolo->quantita_fori)
Quantita Fori @@ -136,8 +169,13 @@
+ +
+

Ultimo aggiornamento: {{ $articolo->updated_at->format('d/m/Y H:i') }}

+
+ -
+ - -
-

Ultimo aggiornamento: {{ $articolo->updated_at->format('d/m/Y H:i') }}

+ + + + + + +
+ +