From 376252e263dda3ae5df698487e5d62dd798952a4 Mon Sep 17 00:00:00 2001
From: solocla
Date: Fri, 3 Jul 2026 09:28:21 +0200
Subject: [PATCH] added files for mescole
---
...60703071659_create_mescole_files_table.php | 60 +++
.../config/mescole_file_categories.php | 14 +
public/userarea/delete_mescola_file.php | 36 ++
public/userarea/get_mescola_files.php | 44 ++
public/userarea/get_mescola_general.php | 48 +++
public/userarea/mescole.php | 296 ++++++++++++-
public/userarea/save_mescola_file.php | 80 ++++
public/userarea/scheda_mescola.php | 397 ++++++++++++++++++
.../82/9f4d056703f05feb92601aba29ed4ca3.pdf | Bin 0 -> 87052 bytes
.../82/cb922ad7840a4c7a415c3ab9ab99deaa.pdf | Bin 0 -> 809271 bytes
10 files changed, 955 insertions(+), 20 deletions(-)
create mode 100644 db/migrations/20260703071659_create_mescole_files_table.php
create mode 100644 public/userarea/config/mescole_file_categories.php
create mode 100644 public/userarea/delete_mescola_file.php
create mode 100644 public/userarea/get_mescola_files.php
create mode 100644 public/userarea/get_mescola_general.php
create mode 100644 public/userarea/save_mescola_file.php
create mode 100644 public/userarea/scheda_mescola.php
create mode 100644 public/userarea/uploads/mescole/82/9f4d056703f05feb92601aba29ed4ca3.pdf
create mode 100644 public/userarea/uploads/mescole/82/cb922ad7840a4c7a415c3ab9ab99deaa.pdf
diff --git a/db/migrations/20260703071659_create_mescole_files_table.php b/db/migrations/20260703071659_create_mescole_files_table.php
new file mode 100644
index 0000000..e182194
--- /dev/null
+++ b/db/migrations/20260703071659_create_mescole_files_table.php
@@ -0,0 +1,60 @@
+table('mescole_files', [
+ 'id' => 'id',
+ 'signed' => true,
+ 'engine' => 'InnoDB',
+ 'charset' => 'utf8mb4',
+ 'collation' => 'utf8mb4_general_ci',
+ ]);
+
+ $table
+ ->addColumn('idmescola', 'integer', [
+ 'signed' => true,
+ 'null' => false,
+ ])
+ ->addColumn('categoria', 'string', [
+ 'limit' => 100,
+ 'null' => false,
+ 'comment' => 'slug categoria: schede_tecniche, certificati_analisi, ...',
+ ])
+ ->addColumn('titolo', 'string', [
+ 'limit' => 255,
+ 'null' => false,
+ ])
+ ->addColumn('filename', 'string', [
+ 'limit' => 255,
+ 'null' => false,
+ 'comment' => 'nome fisico del file salvato su disco (random, non l\'originale)',
+ ])
+ ->addColumn('original_filename', 'string', [
+ 'limit' => 255,
+ 'null' => false,
+ ])
+ ->addColumn('mime_type', 'string', [
+ 'limit' => 150,
+ 'null' => true,
+ ])
+ ->addColumn('filesize', 'integer', [
+ 'null' => true,
+ ])
+ ->addColumn('uploaded_at', 'datetime', [
+ 'default' => 'CURRENT_TIMESTAMP',
+ ])
+ ->addIndex(['idmescola'])
+ ->addIndex(['categoria'])
+ ->addForeignKey('idmescola', 'mescole', 'id', [
+ 'delete' => 'CASCADE',
+ 'update' => 'CASCADE',
+ ])
+ ->create();
+ }
+}
diff --git a/public/userarea/config/mescole_file_categories.php b/public/userarea/config/mescole_file_categories.php
new file mode 100644
index 0000000..73fff12
--- /dev/null
+++ b/public/userarea/config/mescole_file_categories.php
@@ -0,0 +1,14 @@
+ 'Schede Tecniche',
+ 'certificati_analisi' => 'Certificati di Analisi',
+];
diff --git a/public/userarea/delete_mescola_file.php b/public/userarea/delete_mescola_file.php
new file mode 100644
index 0000000..3b141b3
--- /dev/null
+++ b/public/userarea/delete_mescola_file.php
@@ -0,0 +1,36 @@
+ false, 'message' => 'ID non valido']);
+ exit;
+}
+
+try {
+ $db = DBHandlerSelect::getInstance();
+ $pdo = $db->getConnection();
+
+ $stmt = $pdo->prepare("SELECT idmescola, filename FROM mescole_files WHERE id = ?");
+ $stmt->execute([$id]);
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ if (!$row) {
+ echo json_encode(['success' => false, 'message' => 'File non trovato']);
+ exit;
+ }
+
+ $del = $pdo->prepare("DELETE FROM mescole_files WHERE id = ?");
+ $del->execute([$id]);
+
+ $path = __DIR__ . '/uploads/mescole/' . $row['idmescola'] . '/' . $row['filename'];
+ if (is_file($path)) {
+ @unlink($path);
+ }
+
+ echo json_encode(['success' => true]);
+} catch (Throwable $e) {
+ echo json_encode(['success' => false, 'message' => 'Errore database: ' . $e->getMessage()]);
+}
diff --git a/public/userarea/get_mescola_files.php b/public/userarea/get_mescola_files.php
new file mode 100644
index 0000000..9c00d80
--- /dev/null
+++ b/public/userarea/get_mescola_files.php
@@ -0,0 +1,44 @@
+ false, 'message' => 'ID mescola non valido']);
+ exit;
+}
+
+$categorie = require __DIR__ . '/config/mescole_file_categories.php';
+
+try {
+ $db = DBHandlerSelect::getInstance();
+ $pdo = $db->getConnection();
+
+ $sql = "SELECT id, idmescola, categoria, titolo, filename, original_filename, mime_type, filesize, uploaded_at
+ FROM mescole_files
+ WHERE idmescola = ?";
+ $params = [$idmescola];
+
+ if (!empty($categoria)) {
+ $sql .= " AND categoria = ?";
+ $params[] = $categoria;
+ }
+
+ $sql .= " ORDER BY uploaded_at DESC";
+
+ $stmt = $pdo->prepare($sql);
+ $stmt->execute($params);
+
+ $rows = [];
+ while ($r = $stmt->fetch(PDO::FETCH_ASSOC)) {
+ $r['categoria_label'] = $categorie[$r['categoria']] ?? $r['categoria'];
+ $r['url'] = 'uploads/mescole/' . $r['idmescola'] . '/' . $r['filename'];
+ $rows[] = $r;
+ }
+
+ echo json_encode(['success' => true, 'rows' => $rows, 'categorie' => $categorie]);
+} catch (Throwable $e) {
+ echo json_encode(['success' => false, 'message' => 'Errore server: ' . $e->getMessage()]);
+}
diff --git a/public/userarea/get_mescola_general.php b/public/userarea/get_mescola_general.php
new file mode 100644
index 0000000..6c8a85e
--- /dev/null
+++ b/public/userarea/get_mescola_general.php
@@ -0,0 +1,48 @@
+ false, 'message' => 'ID non valido']);
+ exit;
+}
+
+try {
+ $db = DBHandlerSelect::getInstance();
+ $pdo = $db->getConnection();
+
+ $sql = "
+ SELECT
+ m.id,
+ m.nome,
+ m.nomeuscita,
+ m.is_active,
+ IFNULL(q.qty_totale, 0) AS qty_totale,
+ GROUP_CONCAT(DISTINCT pl.name SEPARATOR ', ') AS linee
+ FROM mescole m
+ LEFT JOIN (
+ SELECT idmescola, SUM(qty) AS qty_totale
+ FROM mescole_supplier_lots
+ GROUP BY idmescola
+ ) q ON q.idmescola = m.id
+ LEFT JOIN mescole_lines ml ON m.id = ml.idmescola
+ LEFT JOIN production_lines pl ON ml.idlinea = pl.id
+ WHERE m.id = ?
+ GROUP BY m.id
+ ";
+
+ $stmt = $pdo->prepare($sql);
+ $stmt->execute([$id]);
+ $row = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ if (!$row) {
+ echo json_encode(['success' => false, 'message' => 'Mescola non trovata']);
+ exit;
+ }
+
+ echo json_encode(['success' => true, 'data' => $row]);
+} catch (Throwable $e) {
+ echo json_encode(['success' => false, 'message' => 'Errore database: ' . $e->getMessage()]);
+}
diff --git a/public/userarea/mescole.php b/public/userarea/mescole.php
index 5ff3048..3a97411 100644
--- a/public/userarea/mescole.php
+++ b/public/userarea/mescole.php
@@ -106,6 +106,17 @@
max-width: 360px;
}
+ #tabellaMescole td:nth-child(2) a {
+ color: #1f2d3d;
+ text-decoration: none;
+ font-weight: 600;
+ }
+
+ #tabellaMescole td:nth-child(2) a:hover {
+ text-decoration: underline;
+ color: #0d6efd;
+ }
+
/* Q.tà totale */
#tabellaMescole th:nth-child(3),
#tabellaMescole td:nth-child(3) {
@@ -130,8 +141,27 @@
/* Azioni */
#tabellaMescole th:nth-child(6),
#tabellaMescole td:nth-child(6) {
- width: 330px;
- max-width: 330px;
+ width: 190px;
+ max-width: 190px;
+ white-space: normal;
+ }
+
+ .azioni-cell {
+ display: flex;
+ justify-content: center;
+ gap: 6px;
+ flex-wrap: nowrap;
+ }
+
+ .azioni-cell .btn {
+ width: 34px;
+ height: 34px;
+ padding: 0;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 1rem;
+ line-height: 1;
}
@@ -246,33 +276,50 @@
$toggleText = $isActive ? "Disattiva" : "Attiva";
$toggleClass = $isActive ? "btn-outline-warning" : "btn-outline-success";
+ $nomeUscitaSafe = htmlspecialchars($row['nomeuscita']);
+
echo "
| {$row['id']} |
- " . htmlspecialchars($row['nomeuscita']) . " |
+
+
+ {$nomeUscitaSafe}
+
+ |
{$qtyTot} |
{$linee} |
{$badge} |
-
- |
";
@@ -444,6 +491,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ➕ Carica File
+
+
+
+
+
+
+
+ | Categoria |
+ Titolo |
+ Nome File |
+ Caricato il |
+ Azioni |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/userarea/save_mescola_file.php b/public/userarea/save_mescola_file.php
new file mode 100644
index 0000000..687a882
--- /dev/null
+++ b/public/userarea/save_mescola_file.php
@@ -0,0 +1,80 @@
+ false, 'message' => 'ID mescola non valido']);
+ exit;
+}
+if (!array_key_exists($categoria, $categorie)) {
+ echo json_encode(['success' => false, 'message' => 'Categoria non valida']);
+ exit;
+}
+if ($titolo === '') {
+ echo json_encode(['success' => false, 'message' => 'Il titolo del file è obbligatorio']);
+ exit;
+}
+if (!isset($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
+ echo json_encode(['success' => false, 'message' => 'File mancante o upload non riuscito']);
+ exit;
+}
+
+// --- Validazioni di sicurezza sul file ---
+$allowedExt = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'jpg', 'jpeg', 'png'];
+$maxSize = 15 * 1024 * 1024; // 15 MB
+
+$originalName = $_FILES['file']['name'];
+$tmpPath = $_FILES['file']['tmp_name'];
+$size = (int)$_FILES['file']['size'];
+$ext = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
+
+if (!in_array($ext, $allowedExt, true)) {
+ echo json_encode(['success' => false, 'message' => 'Estensione file non consentita (' . $ext . ')']);
+ exit;
+}
+if ($size <= 0 || $size > $maxSize) {
+ echo json_encode(['success' => false, 'message' => 'Il file supera la dimensione massima di 15MB']);
+ exit;
+}
+
+$finfo = finfo_open(FILEINFO_MIME_TYPE);
+$mimeType = finfo_file($finfo, $tmpPath);
+finfo_close($finfo);
+
+// Cartella dedicata per mescola: uploads/mescole/{idmescola}/
+$destDir = __DIR__ . '/uploads/mescole/' . $idmescola . '/';
+if (!is_dir($destDir)) {
+ mkdir($destDir, 0775, true);
+}
+
+// Nome fisico casuale: evita collisioni e path traversal
+$storedName = bin2hex(random_bytes(16)) . '.' . $ext;
+$destPath = $destDir . $storedName;
+
+if (!move_uploaded_file($tmpPath, $destPath)) {
+ echo json_encode(['success' => false, 'message' => 'Impossibile salvare il file sul server']);
+ exit;
+}
+
+try {
+ $db = DBHandlerSelect::getInstance();
+ $pdo = $db->getConnection();
+
+ $stmt = $pdo->prepare("
+ INSERT INTO mescole_files (idmescola, categoria, titolo, filename, original_filename, mime_type, filesize, uploaded_at)
+ VALUES (?, ?, ?, ?, ?, ?, ?, NOW())
+ ");
+ $stmt->execute([$idmescola, $categoria, $titolo, $storedName, $originalName, $mimeType, $size]);
+
+ echo json_encode(['success' => true, 'id' => $pdo->lastInsertId()]);
+} catch (Throwable $e) {
+ // rollback file se il DB fallisce
+ @unlink($destPath);
+ echo json_encode(['success' => false, 'message' => 'Errore database: ' . $e->getMessage()]);
+}
diff --git a/public/userarea/scheda_mescola.php b/public/userarea/scheda_mescola.php
new file mode 100644
index 0000000..435ddf8
--- /dev/null
+++ b/public/userarea/scheda_mescola.php
@@ -0,0 +1,397 @@
+
+
+
+
+
+
+
+
+
+
Scheda Mescola - = htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+