diff --git a/db/migrations/20260715073632_add_export_date_to_datadb.php b/db/migrations/20260715073632_add_export_date_to_datadb.php new file mode 100644 index 00000000..b1d16dc8 --- /dev/null +++ b/db/migrations/20260715073632_add_export_date_to_datadb.php @@ -0,0 +1,25 @@ +table('datadb') + ->addColumn('export_date', 'datetime', [ + 'null' => true, + 'default' => null, + 'after' => 'commessaweb', + 'comment' => 'Data/ora esportazione verso LIMS (valorizzata quando status = l)', + ]) + ->addIndex(['export_date'], ['name' => 'idx_datadb_export_date']) + ->update(); + } +} diff --git a/db/migrations/20260715074428_create_lims_daily_samples_table.php b/db/migrations/20260715074428_create_lims_daily_samples_table.php new file mode 100644 index 00000000..5a59dd0c --- /dev/null +++ b/db/migrations/20260715074428_create_lims_daily_samples_table.php @@ -0,0 +1,57 @@ +table('lims_daily_samples', [ + 'id' => false, + 'primary_key' => ['id'], + 'comment' => 'Totale campioni inseriti nel LIMS per giornata', + ]); + + $table + ->addColumn('id', 'integer', [ + 'identity' => true, + 'signed' => false, + ]) + ->addColumn('sample_date', 'date', [ + 'null' => false, + 'comment' => 'Giornata di riferimento', + ]) + ->addColumn('total_samples', 'integer', [ + 'signed' => false, + 'null' => false, + 'default' => 0, + 'comment' => 'Totale campioni inseriti nel LIMS in quella giornata', + ]) + ->addColumn('note', 'string', [ + 'limit' => 255, + 'null' => true, + 'default' => null, + ]) + ->addColumn('created_at', 'timestamp', [ + 'null' => true, + 'default' => 'CURRENT_TIMESTAMP', + ]) + ->addColumn('updated_at', 'timestamp', [ + 'null' => true, + 'default' => null, + 'update' => 'CURRENT_TIMESTAMP', + ]) + ->addIndex(['sample_date'], [ + 'unique' => true, + 'name' => 'uq_lims_daily_samples_date', + ]) + ->create(); + } +} diff --git a/public/userarea/export_to_lims.php b/public/userarea/export_to_lims.php index 76409d89..45bb9eb7 100644 --- a/public/userarea/export_to_lims.php +++ b/public/userarea/export_to_lims.php @@ -675,10 +675,10 @@ try { } } - // ๐Ÿ”น STEP 8: Update datadb with idcommessaweb, commessaweb, and status + // ๐Ÿ”น STEP 8: Update datadb with idcommessaweb, commessaweb, status and export date $stmt = $pdo->prepare(" UPDATE datadb - SET idcommessaweb = :idcommessaweb, commessaweb = :commessaweb, status = 'l' + SET idcommessaweb = :idcommessaweb, commessaweb = :commessaweb, status = 'l', export_date = NOW() WHERE iddatadb = :iddatadb "); $stmt->execute([ diff --git a/public/userarea/search_clienti.php b/public/userarea/search_clienti.php index 165214ca..436390d0 100644 --- a/public/userarea/search_clienti.php +++ b/public/userarea/search_clienti.php @@ -1,136 +1,416 @@ - + + -if (!Auth::check()) { - http_response_code(401); - echo json_encode(['error' => 'Unauthorized']); - exit; -} - -require_once __DIR__ . '/class/VisualLimsApiClient.class.php'; - -header('Content-Type: application/json'); -ini_set('display_errors', '0'); -error_reporting(E_ALL); - -$q = mb_strtolower(trim($_GET['q'] ?? '')); -$limit = max(1, min(50, intval($_GET['limit'] ?? 20))); -$id = isset($_GET['id']) ? intval($_GET['id']) : null; - -$tipo = $_GET['tipo'] ?? ''; // 'attivo' | 'inattivo' | '' (nessun filtro) - -function isInattivo(array $c): bool -{ - $v = $c['Inattivo'] ?? false; - return $v === true || $v === 1 || $v === '1' || $v === 'true'; -} - -function formatClientLabel(array $client): string -{ - $name = trim($client['Nominativo'] ?? ''); - $id = trim((string)($client['IdCliente'] ?? '')); - $code = trim((string)($client['CodiceCliente'] ?? '')); - - $parts = explode('_', $code); - $suffix = trim($parts[1] ?? ''); - - if ($suffix === '' && $code !== '') { - $suffix = substr($code, 0, 1); - } - - if ($suffix === '') { - $suffix = '--'; - } - - return $name . ' - ' . $suffix . ' - ' . $id; -} - -try { - // Load from cache or API - $cacheFile = __DIR__ . '/cache/clienti.json'; - - if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < 3600)) { - $data = json_decode(file_get_contents($cacheFile), true); - } else { - $api = VisualLimsApiClient::getInstance(); - - $params = [ - '$select' => 'IdCliente,Nominativo,CodiceCliente,Inattivo', - '$orderby' => 'Nominativo asc' - ]; - - $data = $api->get("Cliente?" . http_build_query($params)); - - if (!is_dir(__DIR__ . '/cache')) { - mkdir(__DIR__ . '/cache', 0777, true); + + + + + + TRF-Project - Statistiche Export LIMS + + + + + +
+ + + +
+
+ + +
+
+
+
Statistiche Export LIMS
+
+ + +
+
+ + +
+ +
+
+
+ + +
+
+
+
+
Export (status L)
+
0
+
+
+
+
+
+
+
Campioni inseriti LIMS
+
0
+
+
+
+
+
+
+
% Esportati / inseriti
+
โ€”
+
+
+
+
+
+
+
Clienti distinti
+
0
+
+
+
+
+ + +
+
+
+ Campioni totali inseriti nel LIMS per questa giornata: + + + Un valore al giorno. Usato per calcolare la % di export. +
+
+
+ + +
+
+
+
+
Export per cliente (idclient) โ€” top 15
+
+
+
+
+
+
+
+
+
+
Export per utente (user_id) โ€” top 15
+
+
+
+
+
+
+
+ + +
+
+
+
+
Dettaglio per cliente
+
+
+
+ + + + + + + + + +
ID ClienteClienteExport
+
+
+
+
+
+
+
+
Dettaglio per utente
+
+
+
+ + + + + + + + + +
ID UtenteUtenteExport
+
+
+
+
+
+ +
+
+ +
+ + +
+ + + + + + + + + + \ No newline at end of file diff --git a/public/userarea/stats_export_lims.php b/public/userarea/stats_export_lims.php new file mode 100644 index 00000000..21807c45 --- /dev/null +++ b/public/userarea/stats_export_lims.php @@ -0,0 +1,481 @@ + + + + + + + + + + TRF-Project - Statistiche Export LIMS + + + + + +
+ + + +
+
+ + +
+
+
+
Statistiche Export LIMS
+
+ + +
+
+ + +
+ +
+
+
+ + +
+
+
+
+
Export (status L)
+
0
+
+
+
+
+
+
+
Campioni inseriti LIMS
+
0
+
+
+
+
+
+
+
% Esportati / inseriti
+
โ€”
+
+
+
+
+
+
+
Clienti distinti
+
0
+
+
+
+
+ + +
+
+
+ Campioni totali inseriti nel LIMS per questa giornata: + + + Un valore al giorno. Usato per calcolare la % di export. +
+
+
+ + + + + +
+
+
+
+
Export per cliente (idclient) โ€” top 15
+
+
+
+
+
+
+
+
+
+
Export per utente (user_id) โ€” top 15
+
+
+
+
+
+
+
+ + +
+
+
+
+
Dettaglio per cliente
+
+
+
+ + + + + + + + + +
ID ClienteClienteExport
+
+
+
+
+
+
+
+
Dettaglio per utente
+
+
+
+ + + + + + + + + +
ID UtenteUtenteExport
+
+
+
+
+
+ +
+
+ +
+ + +
+ + + + + + + + + + \ No newline at end of file diff --git a/public/userarea/stats_export_lims_data.php b/public/userarea/stats_export_lims_data.php new file mode 100644 index 00000000..b211abbd --- /dev/null +++ b/public/userarea/stats_export_lims_data.php @@ -0,0 +1,90 @@ +getConnection(); + +try { + // Data richiesta (default oggi). Formato atteso: Y-m-d + $date = $_GET['date'] ?? date('Y-m-d'); + $d = DateTime::createFromFormat('Y-m-d', $date); + if (!$d || $d->format('Y-m-d') !== $date) { + throw new Exception('Data non valida'); + } + + // --- Export per cliente (status = 'l', giornata su export_date) --- + $stmtC = $pdo->prepare(" + SELECT d.idclient AS idclient, + COUNT(*) AS tot + FROM datadb d + WHERE d.status = 'l' + AND DATE(d.export_date) = :d + GROUP BY d.idclient + ORDER BY tot DESC + "); + $stmtC->execute(['d' => $date]); + $byClient = $stmtC->fetchAll(PDO::FETCH_ASSOC); + + // --- Risolvi Nominativo cliente dalla cache locale (search_clienti.php) --- + $clientNames = []; + $cacheFile = __DIR__ . '/cache/clienti.json'; + if (is_file($cacheFile)) { + $cache = json_decode(file_get_contents($cacheFile), true); + foreach (($cache['value'] ?? []) as $c) { + $clientNames[(int)($c['IdCliente'] ?? 0)] = trim($c['Nominativo'] ?? ''); + } + } + + // --- Export per utente (status = 'l', giornata su export_date) --- + $stmtU = $pdo->prepare(" + SELECT d.user_id AS user_id, + TRIM(CONCAT(COALESCE(u.first_name,''),' ',COALESCE(u.last_name,''))) AS username, + COUNT(*) AS tot + FROM datadb d + LEFT JOIN auth_users u ON u.id = d.user_id + WHERE d.status = 'l' + AND DATE(d.export_date) = :d + GROUP BY d.user_id, username + ORDER BY tot DESC + "); + $stmtU->execute(['d' => $date]); + $byUser = $stmtU->fetchAll(PDO::FETCH_ASSOC); + + // Normalizza tipi (COUNT torna stringa in PDO) + foreach ($byClient as &$r) { + $r['idclient'] = $r['idclient'] !== null ? (int)$r['idclient'] : null; + $r['tot'] = (int)$r['tot']; + $nm = $clientNames[$r['idclient']] ?? ''; + $r['clientname'] = $nm !== '' ? $nm : null; + } + unset($r); + foreach ($byUser as &$r) { + $r['user_id'] = $r['user_id'] !== null ? (int)$r['user_id'] : null; + $r['tot'] = (int)$r['tot']; + if (isset($r['username'])) $r['username'] = $r['username'] !== null && $r['username'] !== '' ? $r['username'] : null; + } + unset($r); + + // --- Totale export della giornata --- + $totExport = array_sum(array_column($byClient, 'tot')); + + // --- Campioni totali inseriti nel LIMS per la giornata (tabella lims_daily_samples) --- + $stmtL = $pdo->prepare("SELECT total_samples FROM lims_daily_samples WHERE sample_date = :d LIMIT 1"); + $stmtL->execute(['d' => $date]); + $limsSamples = $stmtL->fetchColumn(); + $limsSamples = ($limsSamples !== false) ? (int)$limsSamples : null; + + echo json_encode([ + 'success' => true, + 'date' => $date, + 'totals' => ['export' => (int)$totExport], + 'byClient' => $byClient, + 'byUser' => $byUser, + 'limsSamples' => $limsSamples, + ]); +} catch (Exception $e) { + error_log('Stats export LIMS error: ' . $e->getMessage()); + echo json_encode(['success' => false, 'message' => $e->getMessage()]); +} diff --git a/public/userarea/stats_save_lims_samples.php b/public/userarea/stats_save_lims_samples.php new file mode 100644 index 00000000..ef412389 --- /dev/null +++ b/public/userarea/stats_save_lims_samples.php @@ -0,0 +1,36 @@ +getConnection(); + +try { + $date = $_POST['date'] ?? null; + $total = $_POST['total_samples'] ?? null; + + $d = $date ? DateTime::createFromFormat('Y-m-d', $date) : null; + if (!$d || $d->format('Y-m-d') !== $date) { + throw new Exception('Data non valida'); + } + if (!is_numeric($total) || (int)$total < 0) { + throw new Exception('Valore campioni non valido'); + } + $total = (int)$total; + + // Upsert: un solo record per giornata (unique su sample_date) + $stmt = $pdo->prepare(" + INSERT INTO lims_daily_samples (sample_date, total_samples) + VALUES (:d, :t) + ON DUPLICATE KEY UPDATE total_samples = VALUES(total_samples) + "); + $stmt->execute(['d' => $date, 't' => $total]); + + echo json_encode(['success' => true, 'date' => $date, 'total_samples' => $total]); +} catch (Exception $e) { + error_log('Save LIMS samples error: ' . $e->getMessage()); + echo json_encode(['success' => false, 'message' => $e->getMessage()]); +}