diff --git a/composer.json b/composer.json index c38cbe7..e0cb6ff 100644 --- a/composer.json +++ b/composer.json @@ -30,6 +30,7 @@ "ext-json": "*", "akaunting/laravel-setting": "^1.2.9", "anhskohbo/no-captcha": "3.*", + "endroid/qr-code": "^6.0", "guzzlehttp/guzzle": "^7.2", "intervention/image": "^2.3", "jenssegers/agent": "^2.5", diff --git a/composer.lock b/composer.lock index 8a6ece5..5291d9b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a7749f3b43e37d8fb607bcccd227f5ee", + "content-hash": "ef3e05e7260284f5b7c7b4b6f93b252b", "packages": [ { "name": "akaunting/laravel-setting", @@ -820,6 +820,78 @@ ], "time": "2023-10-06T06:47:41+00:00" }, + { + "name": "endroid/qr-code", + "version": "6.0.6", + "source": { + "type": "git", + "url": "https://github.com/endroid/qr-code.git", + "reference": "11e6a94458dab8dd18736c11892130ec788b5028" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/endroid/qr-code/zipball/11e6a94458dab8dd18736c11892130ec788b5028", + "reference": "11e6a94458dab8dd18736c11892130ec788b5028", + "shasum": "" + }, + "require": { + "bacon/bacon-qr-code": "^3.0", + "php": "^8.2" + }, + "require-dev": { + "endroid/quality": "dev-main", + "ext-gd": "*", + "khanamiryan/qrcode-detector-decoder": "^2.0.2", + "setasign/fpdf": "^1.8.2" + }, + "suggest": { + "ext-gd": "Enables you to write PNG images", + "khanamiryan/qrcode-detector-decoder": "Enables you to use the image validator", + "roave/security-advisories": "Makes sure package versions with known security issues are not installed", + "setasign/fpdf": "Enables you to use the PDF writer" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Endroid\\QrCode\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jeroen van den Enden", + "email": "info@endroid.nl" + } + ], + "description": "Endroid QR Code", + "homepage": "https://github.com/endroid/qr-code", + "keywords": [ + "code", + "endroid", + "php", + "qr", + "qrcode" + ], + "support": { + "issues": "https://github.com/endroid/qr-code/issues", + "source": "https://github.com/endroid/qr-code/tree/6.0.6" + }, + "funding": [ + { + "url": "https://github.com/endroid", + "type": "github" + } + ], + "time": "2025-03-14T23:29:08+00:00" + }, { "name": "firebase/php-jwt", "version": "v6.10.1", diff --git a/public/languages/en/general.php b/public/languages/en/general.php index 1ddad96..82a67da 100644 --- a/public/languages/en/general.php +++ b/public/languages/en/general.php @@ -1,6 +1,6 @@ false, 'message' => 'Richiesta non valida']); + exit; +} + +$photoId = intval($_POST['photo_id']); + +$db = DBHandlerSelect::getInstance(); +$pdo = $db->getConnection(); + +// Recupera il percorso del file +$stmt = $pdo->prepare("SELECT file_path FROM datadb_photos WHERE id = ?"); +$stmt->execute([$photoId]); +$photo = $stmt->fetch(PDO::FETCH_ASSOC); + +if (!$photo) { + echo json_encode(['success' => false, 'message' => 'Foto non trovata']); + exit; +} + +// Elimina il file dal server +$filePath = '../photostrf/' . $photo['file_path']; +if (file_exists($filePath)) { + unlink($filePath); +} + +// Elimina il record dal database +$stmt = $pdo->prepare("DELETE FROM datadb_photos WHERE id = ?"); +$stmt->execute([$photoId]); + +echo json_encode(['success' => true, 'message' => 'Foto eliminata con successo']); diff --git a/public/userarea/fetch_tracking_info.php b/public/userarea/fetch_tracking_info.php new file mode 100644 index 0000000..1ed680c --- /dev/null +++ b/public/userarea/fetch_tracking_info.php @@ -0,0 +1,150 @@ + false, 'message' => 'Numero di tracking o corriere non fornito']); +} + +$trackingNumber = $_POST['tracking_number']; +$courierCode = $_POST['courier_code']; + +// Lista dei corrieri validi per validazione +$validCarriers = ['tnt-it', 'dhl', 'gls', 'sda', 'ups']; +if (!in_array($courierCode, $validCarriers)) { + sendResponse(['success' => false, 'message' => 'Corriere non valido']); +} + +// Imposta il nome del corriere in base al codice +$carrierNames = [ + 'tnt-it' => 'TNT Italy', + 'dhl' => 'DHL', + 'gls' => 'GLS', + 'sda' => 'SDA', + 'ups' => 'UPS' +]; +$courierName = $carrierNames[$courierCode]; + +// Funzione per fare una richiesta cURL a TrackingMore +function makeRequest($url, $data, $apiKey, $method = 'POST') +{ + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Tracking-Api-Key: ' . $apiKey, + 'Content-Type: application/json' + ]); + if ($method === 'POST') { + curl_setopt($ch, CURLOPT_POST, true); + $jsonData = json_encode($data, JSON_PRETTY_PRINT); + curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData); + file_put_contents('debug.log', "Encoded JSON Data: $jsonData\n", FILE_APPEND); + } + curl_setopt($ch, CURLOPT_TIMEOUT, 10); + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $error = curl_error($ch); + curl_close($ch); + + file_put_contents('debug.log', "Request URL: $url\nRequest Data: " . json_encode($data) . "\nResponse: $response\nHTTP Code: $httpCode\nError: $error\n", FILE_APPEND); + + if ($response === false) { + return [ + 'success' => false, + 'code' => $httpCode, + 'message' => 'Errore nella richiesta API: ' . $error + ]; + } + + $decodedResponse = json_decode($response, true); + if ($decodedResponse === null) { + return [ + 'success' => false, + 'code' => $httpCode, + 'message' => 'Risposta API non valida (non è JSON)' + ]; + } + + $decodedResponse['success'] = isset($decodedResponse['meta']['code']) && ($decodedResponse['meta']['code'] === 200 || $decodedResponse['meta']['code'] === 201); + $decodedResponse['http_code'] = $httpCode; + return $decodedResponse; +} + +// Step 1: Prova a creare il tracking +$createUrl = 'https://api.trackingmore.com/v4/trackings/create'; +$createData = [ + 'tracking_number' => $trackingNumber, + 'courier_code' => $courierCode +]; +$createResponse = makeRequest($createUrl, $createData, $apiKey); +file_put_contents('debug.log', "Create Response: " . json_encode($createResponse) . "\n", FILE_APPEND); + +$trackingInfo = null; +if ($createResponse['success']) { + // Creazione riuscita, usa i dati restituiti + $trackingInfo = $createResponse['data']; +} else { + // Controlla se l'errore è "Tracking No. already exists" (4101) + if (isset($createResponse['meta']['code']) && $createResponse['meta']['code'] === 4101) { + // Il tracking esiste già, usa /trackings (GET) con tracking_number e courier_code + $getUrl = 'https://api.trackingmore.com/v4/get?tracking_numbers=' . urlencode($trackingNumber); + $getResponse = makeRequest($getUrl, [], $apiKey, 'GET'); + file_put_contents('debug.log', "Get Response: " . json_encode($getResponse) . "\n", FILE_APPEND); + + if ($getResponse['success'] && !empty($getResponse['data']['items']) && !empty($getResponse['data']['items'][0])) { + $trackingInfo = $getResponse['data']['items'][0]; + } else { + $errorMessage = isset($getResponse['meta']['message']) ? $getResponse['meta']['message'] : 'Errore sconosciuto'; + sendResponse(['success' => false, 'message' => 'Errore nel recupero del tracking esistente: ' . $errorMessage]); + } + } else { + // Altro errore nella creazione + $errorMessage = isset($createResponse['meta']['message']) ? $createResponse['meta']['message'] : 'Errore sconosciuto'; + sendResponse(['success' => false, 'message' => 'Errore nella creazione del tracking: ' . $errorMessage]); + } +} + +if (!$trackingInfo) { + sendResponse(['success' => false, 'message' => 'Nessuna informazione di tracking trovata']); +} + +// Estrai la data di consegna e il firmatario +$deliveryDate = 'Non disponibile'; +$signedBy = 'Non disponibile'; +if (isset($trackingInfo['origin_info']['trackinfo']) && is_array($trackingInfo['origin_info']['trackinfo'])) { + foreach ($trackingInfo['origin_info']['trackinfo'] as $checkpoint) { + if (isset($checkpoint['checkpoint_delivery_status']) && $checkpoint['checkpoint_delivery_status'] === 'delivered') { + $deliveryDate = $checkpoint['checkpoint_date'] ?? 'Non disponibile'; + $signedBy = $trackingInfo['signed_by'] ?? 'Non disponibile'; + break; + } + } +} + +// Restituisci i dati al frontend +sendResponse([ + 'success' => true, + 'deliveryDate' => $deliveryDate, + 'signedBy' => $signedBy, + 'carrierName' => $courierName +]); diff --git a/public/userarea/fetch_tracking_info17track.php b/public/userarea/fetch_tracking_info17track.php new file mode 100644 index 0000000..381ce14 --- /dev/null +++ b/public/userarea/fetch_tracking_info17track.php @@ -0,0 +1,166 @@ + false, 'message' => 'Numero di tracking non fornito']); +} + +$trackingNumber = $_POST['tracking_number']; + +// Funzione per fare una richiesta cURL a 17Track +function makeRequest($url, $data, $apiKey, $method = 'POST') +{ + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + '17token: ' . $apiKey, + 'Content-Type: application/json' + ]); + if ($method === 'POST') { + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); + } + curl_setopt($ch, CURLOPT_TIMEOUT, 10); + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $error = curl_error($ch); + curl_close($ch); + + file_put_contents('debug.log', "Request URL: $url\nRequest Data: " . json_encode($data) . "\nResponse: $response\nHTTP Code: $httpCode\nError: $error\n", FILE_APPEND); + + if ($response === false || $httpCode !== 200) { + return [ + 'success' => false, + 'code' => $httpCode, + 'message' => 'Errore nella richiesta API: HTTP ' . $httpCode . ' - ' . $error + ]; + } + + $decodedResponse = json_decode($response, true); + if ($decodedResponse === null) { + return [ + 'success' => false, + 'code' => $httpCode, + 'message' => 'Risposta API non valida (non è JSON)' + ]; + } + + return $decodedResponse; +} + +// Step 1: Prova con auto-detection +$trackUrl = 'https://api.17track.net/track/v2/register'; +$trackData = [ + [ + 'number' => $trackingNumber, + 'carrier' => null, + 'auto_detection' => true + ] +]; +$registerResponse = makeRequest($trackUrl, $trackData, $apiKey); + +file_put_contents('debug.log', "Register Response (Auto-detect): " . json_encode($registerResponse) . "\n", FILE_APPEND); + +if (!isset($registerResponse['data']['accepted']) || empty($registerResponse['data']['accepted'])) { + $errorMessage = $registerResponse['data']['rejected'][0]['error']['message'] ?? 'Errore sconosciuto'; + sendResponse(['success' => false, 'message' => 'Errore nella registrazione del tracking: ' . $errorMessage]); +} + +// Step 2: Recupera i dettagli con riprova +$getUrl = 'https://api.17track.net/track/v2/gettrackinfo'; +$getData = [['number' => $trackingNumber]]; +$maxAttempts = 3; +$delaySeconds = 5; + +for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) { + $trackResponse = makeRequest($getUrl, $getData, $apiKey); + file_put_contents('debug.log', "Track Response (Attempt $attempt): " . json_encode($trackResponse) . "\n", FILE_APPEND); + + if (isset($trackResponse['data']['accepted']) && !empty($trackResponse['data']['accepted'])) { + break; + } + + if ($attempt < $maxAttempts) { + sleep($delaySeconds); + } +} + +// Se auto-detection ha successo, procedi +if (isset($trackResponse['data']['accepted']) && !empty($trackResponse['data']['accepted'])) { + $trackingInfo = $trackResponse['data']['accepted'][0]['track'] ?? null; + if (!$trackingInfo) { + sendResponse(['success' => false, 'message' => 'Nessuna informazione di tracking trovata']); + } + + $deliveryDate = 'Non disponibile'; + $signedBy = 'Non disponibile'; + $carrierName = $trackingInfo['carrier']['name'] ?? 'Sconosciuto'; + + if (isset($trackingInfo['z0']['e']) && $trackingInfo['z0']['e'] == 40) { + $deliveryDate = $trackingInfo['z0']['z'] ?? 'Non disponibile'; + $signedBy = $trackingInfo['z0']['d'] ?? 'Non disponibile'; + } + + sendResponse([ + 'success' => true, + 'deliveryDate' => $deliveryDate, + 'signedBy' => $signedBy, + 'carrierName' => $carrierName + ]); +} + +// Step 3: Se auto-detection fallisce, prova una lista di corrieri comuni +$commonCarriers = [ + ['code' => 100003, 'name' => 'TNT'], // TNT + ['code' => 100001, 'name' => 'DHL'], // DHL Express + ['code' => 100065, 'name' => 'DHL eCommerce'], // DHL eCommerce + ['code' => 100002, 'name' => 'UPS'] // UPS +]; + +$possibleCarriers = []; +foreach ($commonCarriers as $carrier) { + $trackData = [ + [ + 'number' => $trackingNumber, + 'carrier' => $carrier['code'], + 'auto_detection' => false + ] + ]; + $registerResponse = makeRequest($trackUrl, $trackData, $apiKey); + + if (isset($registerResponse['data']['accepted']) && !empty($registerResponse['data']['accepted'])) { + $possibleCarriers[] = $carrier['name']; + } + sleep(1); // Piccolo ritardo per evitare limiti di rate +} + +if (!empty($possibleCarriers)) { + sendResponse([ + 'success' => false, + 'message' => 'Auto-detection fallita. Seleziona un corriere tra quelli possibili.', + 'possibleCarriers' => $possibleCarriers + ]); +} else { + sendResponse(['success' => false, 'message' => 'Nessun corriere identificato per questo numero di tracking']); +} diff --git a/public/userarea/fetch_tracking_infotracking.php b/public/userarea/fetch_tracking_infotracking.php new file mode 100644 index 0000000..08ee258 --- /dev/null +++ b/public/userarea/fetch_tracking_infotracking.php @@ -0,0 +1,166 @@ + false, 'message' => 'Numero di tracking non fornito']); +} + +$trackingNumber = $_POST['tracking_number']; + +// Funzione per fare una richiesta cURL a TrackingMore +function makeRequest($url, $data, $apiKey, $method = 'POST') +{ + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Tracking-Api-Key: ' . $apiKey, + 'Content-Type: application/json' + ]); + if ($method === 'POST') { + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); + } + curl_setopt($ch, CURLOPT_TIMEOUT, 10); + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $error = curl_error($ch); + curl_close($ch); + + file_put_contents('debug.log', "Request URL: $url\nRequest Data: " . json_encode($data) . "\nResponse: $response\nHTTP Code: $httpCode\nError: $error\n", FILE_APPEND); + + if ($response === false || ($httpCode !== 200 && $httpCode !== 201)) { + return [ + 'success' => false, + 'code' => $httpCode, + 'message' => 'Errore nella richiesta API: HTTP ' . $httpCode . ' - ' . $error + ]; + } + + $decodedResponse = json_decode($response, true); + if ($decodedResponse === null) { + return [ + 'success' => false, + 'code' => $httpCode, + 'message' => 'Risposta API non valida (non è JSON)' + ]; + } + + $decodedResponse['success'] = isset($decodedResponse['meta']['code']) && ($decodedResponse['meta']['code'] === 200 || $decodedResponse['meta']['code'] === 201); + return $decodedResponse; +} + +// Step 1: Identifica il corriere +$detectUrl = 'https://api.trackingmore.com/v4/couriers/detect'; +$detectData = ['tracking_number' => $trackingNumber]; +$detectResponse = makeRequest($detectUrl, $detectData, $apiKey); +file_put_contents('debug.log', "Detect Response: " . json_encode($detectResponse) . "\n", FILE_APPEND); + +if (!$detectResponse['success']) { + $errorMessage = isset($detectResponse['meta']['message']) ? $detectResponse['meta']['message'] : 'Errore sconosciuto'; + sendResponse(['success' => false, 'message' => 'Errore nella rilevazione del corriere: ' . $errorMessage]); +} + +$couriers = $detectResponse['data'] ?? []; +if (empty($couriers)) { + sendResponse(['success' => false, 'message' => 'Corriere non identificato per il numero di tracking']); +} + +// Prendi il primo corriere per ora +$courierCode = $couriers[0]['courier_code'] ?? null; +$courierName = $couriers[0]['courier_name'] ?? 'Sconosciuto'; +if (!$courierCode) { + sendResponse(['success' => false, 'message' => 'Corriere non identificato']); +} + +// Step 2: Crea un tracking +$createUrl = 'https://api.trackingmore.com/v4/trackings/create'; +$createData = [ + 'tracking_number' => $trackingNumber, + 'courier_code' => $courierCode +]; +$createResponse = makeRequest($createUrl, $createData, $apiKey); +file_put_contents('debug.log', "Create Response: " . json_encode($createResponse) . "\n", FILE_APPEND); + +if (!$createResponse['success']) { + $errorMessage = isset($createResponse['meta']['message']) ? $createResponse['meta']['message'] : 'Errore sconosciuto'; + sendResponse(['success' => false, 'message' => 'Errore nella creazione del tracking: ' . $errorMessage]); +} + +// Step 3: Recupera i dettagli del tracking con riprova +$getUrl = 'https://api.trackingmore.com/v4/trackings/get?tracking_number=' . urlencode($trackingNumber); +$maxAttempts = 3; +$delaySeconds = 5; + +for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) { + $trackResponse = makeRequest($getUrl, [], $apiKey, 'GET'); + file_put_contents('debug.log', "Track Response (Attempt $attempt): " . json_encode($trackResponse) . "\n", FILE_APPEND); + + if ($trackResponse['success'] && !empty($trackResponse['data'])) { + break; + } + + if ($attempt < $maxAttempts) { + sleep($delaySeconds); + } +} + +if (!$trackResponse['success']) { + $errorMessage = isset($trackResponse['meta']['message']) ? $trackResponse['meta']['message'] : 'Errore sconosciuto'; + sendResponse(['success' => false, 'message' => 'Errore nel recupero delle informazioni: ' . $errorMessage]); +} + +$trackingInfo = $trackResponse['data'] ?? null; +if (!$trackingInfo) { + // Se ci sono più corrieri rilevati, restituisci una lista per la tendina + if (count($couriers) > 1) { + $possibleCarriers = array_map(function ($courier) { + return ['code' => $courier['courier_code'], 'name' => $courier['courier_name']]; + }, $couriers); + sendResponse([ + 'success' => false, + 'message' => 'Dati non trovati. Seleziona un corriere tra quelli rilevati.', + 'possibleCarriers' => $possibleCarriers + ]); + } + sendResponse(['success' => false, 'message' => 'Nessuna informazione di tracking trovata']); +} + +// Estrai la data di consegna e il firmatario +$deliveryDate = 'Non disponibile'; +$signedBy = 'Non disponibile'; +foreach ($trackingInfo['trackinfo'] as $checkpoint) { + if ($checkpoint['status'] === 'delivered') { + $deliveryDate = $checkpoint['Date']; + $signedBy = $checkpoint['signed_by'] ?? 'Non disponibile'; + break; + } +} + +// Restituisci i dati al frontend +sendResponse([ + 'success' => true, + 'deliveryDate' => $deliveryDate, + 'signedBy' => $signedBy, + 'carrierName' => $courierName +]); diff --git a/public/userarea/import_dashboard.php b/public/userarea/import_dashboard.php index b3c0ad0..7c1f5b7 100644 --- a/public/userarea/import_dashboard.php +++ b/public/userarea/import_dashboard.php @@ -20,12 +20,19 @@ padding: 20px; } + /* Definizione delle dimensioni */ /* Definizione delle dimensioni */ .btn-small { font-size: 12px; padding: 6px 12px; min-width: 100px; min-height: 30px; + display: flex; + /* Aggiunto */ + justify-content: center; + /* Aggiunto */ + align-items: center; + /* Aggiunto */ } .btn-medium { @@ -33,6 +40,12 @@ padding: 10px 20px; min-width: 130px; min-height: 45px; + display: flex; + /* Aggiunto */ + justify-content: center; + /* Aggiunto */ + align-items: center; + /* Aggiunto */ } .btn-large { @@ -40,6 +53,12 @@ padding: 14px 28px; min-width: 180px; min-height: 60px; + display: flex; + /* Aggiunto */ + justify-content: center; + /* Aggiunto */ + align-items: center; + /* Aggiunto */ } /* Stile della barra di ricerca */ diff --git a/public/userarea/import_edit.php b/public/userarea/import_edit.php new file mode 100644 index 0000000..41cd30b --- /dev/null +++ b/public/userarea/import_edit.php @@ -0,0 +1,1006 @@ +getConnection(); + +// Genera un UUID univoco per importreferencecode +$importReferenceCode = date('YmdHis') . '-' . uniqid(); + +// Recupera il mapping per il template +$stmt = $pdo->prepare("SELECT excel_column, mysql_column, data_type, is_required, default_value FROM excel_column_mappings WHERE template_id = ?"); +$stmt->execute([$template_id]); +$mappings = $stmt->fetchAll(PDO::FETCH_ASSOC); + +if (empty($mappings)) { + header("Location: import_xls.php?id=$template_id&status=error&message=" . urlencode("Nessun mapping trovato per il template")); + exit; +} + +// Recupera il client_specific_fields dal template +$stmt = $pdo->prepare("SELECT client_specific_fields FROM excel_templates WHERE id = ?"); +$stmt->execute([$template_id]); +$template = $stmt->fetch(PDO::FETCH_ASSOC); +$clientSpecificFields = $template && !empty($template['client_specific_fields']) ? json_decode($template['client_specific_fields'], true) : []; + +// Crea un array per il mapping +$columnMapping = []; +foreach ($mappings as $mapping) { + $excelColumnIndex = array_search($mapping['excel_column'], $columns); + if ($excelColumnIndex !== false) { + $columnMapping[$excelColumnIndex] = [ + 'mysql_column' => $mapping['mysql_column'], + 'data_type' => $mapping['data_type'], + 'is_required' => $mapping['is_required'], + 'default_value' => $mapping['default_value'] + ]; + } +} + +// Inserisci le righe selezionate in datadb +$insertedIds = []; +foreach ($selected_rows as $rowIndex) { + $row = $rows[$rowIndex]; + $values = []; + $placeholders = []; + $columnsToInsert = []; + + foreach ($columnMapping as $excelIndex => $mapping) { + $mysqlColumn = $mapping['mysql_column']; + $value = $row[$excelIndex] ?? $mapping['default_value']; + + if ($mapping['is_required'] && (is_null($value) || $value === '')) { + $value = $mapping['default_value']; + if (is_null($value)) { + header("Location: import_xls.php?id=$template_id&status=error&message=" . urlencode("Valore richiesto mancante per la colonna $mysqlColumn")); + exit; + } + } + + switch ($mapping['data_type']) { + case 'INT': + $value = is_numeric($value) ? (int)$value : ($mapping['default_value'] ?? null); + break; + case 'DATE': + $value = !empty($value) ? date('Y-m-d', strtotime($value)) : ($mapping['default_value'] ?? null); + break; + case 'CHAR': + $value = !empty($value) ? substr($value, 0, 1) : ($mapping['default_value'] ?? null); + break; + case 'VARCHAR': + default: + $value = !empty($value) ? htmlspecialchars($value) : ($mapping['default_value'] ?? null); + break; + } + + if (!is_null($value)) { + $columnsToInsert[] = $mysqlColumn; + $placeholders[] = '?'; + $values[] = $value; + } + } + + $columnsToInsert[] = 'importreferencecode'; + $placeholders[] = '?'; + $values[] = $importReferenceCode; + + $columnsToInsert[] = 'filename_import'; + $placeholders[] = '?'; + $values[] = $newFilename; + + $columnsToInsert[] = 'status'; + $placeholders[] = '?'; + $values[] = 'i'; + + $columnsToInsert[] = 'user_id'; + $placeholders[] = '?'; + $values[] = $user_id; + + $columnsToInsert[] = 'limscode'; + $placeholders[] = '?'; + $values[] = null; + + $columnsToInsert[] = 'importdate'; + $placeholders[] = '?'; + $values[] = date('Y-m-d'); + + $sql = "INSERT INTO datadb (" . implode(', ', $columnsToInsert) . ") VALUES (" . implode(', ', $placeholders) . ")"; + $stmt = $pdo->prepare($sql); + $stmt->execute($values); + + $insertedIds[] = $pdo->lastInsertId(); +} + +// Recupera i dati appena inseriti con i nomi degli utenti +$stmt = $pdo->prepare(" + SELECT d.*, CONCAT(u.first_name, ' ', u.last_name) AS user_name + FROM datadb d + LEFT JOIN auth_users u ON d.user_id = u.id + WHERE d.iddatadb IN (" . implode(',', array_fill(0, count($insertedIds), '?')) . ") +"); +$stmt->execute($insertedIds); +$importedData = $stmt->fetchAll(PDO::FETCH_ASSOC); + +// Recupera il mapping globale per mostrare gli slug leggibili +$stmt = $pdo->query("SELECT mysql_column_name, user_friendly_slug FROM column_mapping"); +$slugMapping = []; +foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) { + $slugMapping[$row['mysql_column_name']] = $row['user_friendly_slug']; +} +?> + + + + + + + + + + + + Modifica Dati Importati - <?= htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?> + + + +
+ + +
+
+ + +
+
+
+
+
Modifica Dati Importati
+
+
+
+
+
+
+ +
+
+
+
"; + $headerIndex++; + } + } + // Aggiungi gli input per i campi aggiuntivi sopra l'header + foreach ($clientSpecificFields as $fieldName => $fieldDetails) { + $fieldValue = $fieldDetails['default_value']; + if ($fieldDetails['type'] === 'date' && $fieldDetails['default_value'] === 'today') { + $fieldValue = date('Y-m-d'); + } + $requiredAttr = $fieldDetails['is_required'] ? 'required' : ''; + echo "
"; + if ($fieldDetails['type'] === 'date') { + echo ""; + } elseif ($fieldDetails['type'] === 'boolean') { + echo ""; + } else { + echo ""; + } + echo ""; + echo "
"; + $headerIndex++; + } + // Spazi vuoti per AWB Number e Tracking Info + echo "
"; + echo "
"; + ?> +
+ + +
+
Salva
+
Photos
+ $displayName
"; + $headerIndex++; + } + } + // Aggiungi gli header per i campi aggiuntivi + foreach ($clientSpecificFields as $fieldName => $fieldDetails) { + echo "
$fieldName
"; + $headerIndex++; + } + ?> +
AWB Number
+
+
Tracking Info
+
+
+ + + $row): ?> +
+
+ +
+
+ +
+ $value) { + $visible = !in_array($col, ['iddatadb', 'importreferencecode', 'limscode', 'user_name']); + if ($visible) { + ?> +
+ + + + + File + + + + + + + + + + + + +
+ + + $fieldDetails) { + ?> +
+ "; + } elseif ($fieldDetails['type'] === 'boolean') { + echo ""; + } else { + echo ""; + } + ?> +
+ + +
+ + + +
+
+ Data e corriere qui + +
+
+ +
+ + + + +
+
+
+ + +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/public/userarea/import_xls.php b/public/userarea/import_xls.php index e519fde..6eb9a39 100644 --- a/public/userarea/import_xls.php +++ b/public/userarea/import_xls.php @@ -51,9 +51,7 @@ error_log("Loaded template: " . print_r($template, true)); text-align: left; border: 1px solid #dee2e6; min-width: 100px; - /* Larghezza minima per tutte le colonne */ max-width: 200px; - /* Larghezza massima iniziale */ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; @@ -62,7 +60,6 @@ error_log("Loaded template: " . print_r($template, true)); .table th:first-child, .table td:first-child { min-width: 50px; - /* Colonna "Seleziona" più stretta */ max-width: 50px; } @@ -73,7 +70,6 @@ error_log("Loaded template: " . print_r($template, true)); user-select: none; } - /* Handle di ridimensionamento */ .table th .resize-handle { position: absolute; top: 0; @@ -199,16 +195,7 @@ error_log("Loaded template: " . print_r($template, true)); method: 'POST', body: formData }) - .then(response => { - return response.text().then(text => { - console.log('Risposta grezza:', text); - try { - return JSON.parse(text); - } catch (e) { - throw new Error('Risposta non valida: ' + text); - } - }); - }) + .then(response => response.json()) .then(data => { loader.style.display = 'none'; if (data.error) { @@ -218,6 +205,9 @@ error_log("Loaded template: " . print_r($template, true)); let html = `
+ + +
@@ -256,12 +246,11 @@ error_log("Loaded template: " . print_r($template, true)); const startWidth = th.offsetWidth; const onMouseMove = (e) => { - const newWidth = Math.max(50, startWidth + (e.clientX - startX)); // Min 50px + const newWidth = Math.max(50, startWidth + (e.clientX - startX)); th.style.width = `${newWidth}px`; th.style.minWidth = `${newWidth}px`; th.style.maxWidth = `${newWidth}px`; - // Aggiorna anche le celle della colonna corrispondente const cells = document.querySelectorAll(`.table td:nth-child(${index + 1})`); cells.forEach(cell => { cell.style.width = `${newWidth}px`; diff --git a/public/userarea/imported_trf/1-20250308144333-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/1-20250308144333-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/1-20250308144333-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/1-20250308144500-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/1-20250308144500-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/1-20250308144500-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/1-20250310151936-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/1-20250310151936-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/1-20250310151936-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/1-20250310152759-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/1-20250310152759-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/1-20250310152759-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/1-20250310153202-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/1-20250310153202-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/1-20250310153202-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/1-20250310153759-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/1-20250310153759-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/1-20250310153759-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/1-20250310154159-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/1-20250310154159-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/1-20250310154159-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/1-20250310155024-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/1-20250310155024-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/1-20250310155024-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/1-20250310155252-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/1-20250310155252-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/1-20250310155252-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/1-20250312084239-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/1-20250312084239-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/1-20250312084239-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/1-20250312102018-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/1-20250312102018-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/1-20250312102018-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/1-20250312103756-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/1-20250312103756-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/1-20250312103756-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/1-20250312104614-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/1-20250312104614-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/1-20250312104614-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/1-20250312114708-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/1-20250312114708-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/1-20250312114708-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/1-20250312135908-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/1-20250312135908-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/1-20250312135908-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/1-20250312152433-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/1-20250312152433-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/1-20250312152433-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/1-20250325111922-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/1-20250325111922-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/1-20250325111922-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/1-20250325141003-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/1-20250325141003-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/1-20250325141003-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/1-20250326091743-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/1-20250326091743-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/1-20250326091743-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/1-20250327152621-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/1-20250327152621-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/1-20250327152621-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/2-20250308134022-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/2-20250308134022-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/2-20250308134022-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/2-20250308134035-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/2-20250308134035-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/2-20250308134035-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/imported_trf/2-20250308134137-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx b/public/userarea/imported_trf/2-20250308134137-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/imported_trf/2-20250308134137-MONCLER TRF - 21.11.2024_CHIARA_SS25_2C PER PELLI.xlsx differ diff --git a/public/userarea/photos_popup.php b/public/userarea/photos_popup.php new file mode 100644 index 0000000..e5baeaa --- /dev/null +++ b/public/userarea/photos_popup.php @@ -0,0 +1,140 @@ +getConnection(); + +// Verifica che l'iddatadb sia stato passato +if (!isset($_GET['iddatadb']) || empty($_GET['iddatadb'])) { + echo json_encode(['error' => 'ID riga non fornito']); + exit; +} + +$iddatadb = intval($_GET['iddatadb']); + +// Recupera i dettagli della riga (idriga e sample_code) +$stmt = $pdo->prepare("SELECT iddatadb, sample_code FROM datadb WHERE iddatadb = ?"); +$stmt->execute([$iddatadb]); +$row = $stmt->fetch(PDO::FETCH_ASSOC); + +if (!$row) { + echo json_encode(['error' => 'Riga non trovata']); + exit; +} + +$idriga = $row['iddatadb']; +$sampleCode = $row['sample_code'] ?? 'Non disponibile'; + +// Recupera le foto associate alla riga +$stmt = $pdo->prepare("SELECT id, file_path, file_name, description, uploaded_at FROM datadb_photos WHERE iddatadb = ? ORDER BY uploaded_at DESC"); +$stmt->execute([$iddatadb]); +$photos = $stmt->fetchAll(PDO::FETCH_ASSOC); + +// Definisci il percorso base per le foto +$photoBasePath = '../photostrf/'; + +// Genera l'URL per il QR code +$baseUrl = "http://localhost/trf_certest/public/userarea/"; // Sostituisci con il tuo dominio +$uploadUrl = $baseUrl . "upload_photos_mobile.php?iddatadb=" . $iddatadb; + +// Genera il QR code con endroid/qr-code 6.0.6 +$qrCodeDir = '../photostrf/qrcodes/'; +if (!is_dir($qrCodeDir)) { + mkdir($qrCodeDir, 0755, true); +} +$qrCodeFile = $qrCodeDir . "qrcode_{$iddatadb}.png"; + +$writer = new PngWriter(); + +// Crea il QR code usando il costruttore +$qrCode = new QrCode( + data: $uploadUrl, + encoding: new Encoding('UTF-8'), + errorCorrectionLevel: ErrorCorrectionLevel::Low, + size: 150, + margin: 10, + roundBlockSizeMode: RoundBlockSizeMode::Margin, + foregroundColor: new Color(0, 0, 0), + backgroundColor: new Color(255, 255, 255) +); + +$result = $writer->write($qrCode); +$result->saveToFile($qrCodeFile); +?> + + + + \ No newline at end of file diff --git a/public/userarea/process_import_xls.php b/public/userarea/process_import_xls.php index 5a2dc3a..7ea091c 100644 --- a/public/userarea/process_import_xls.php +++ b/public/userarea/process_import_xls.php @@ -10,7 +10,7 @@ session_start(); // Includi PHPSpreadsheet require_once '../../vendor/autoload.php'; -$response = ['error' => '', 'rows' => [], 'columns' => [], 'template_id' => 0]; +$response = ['error' => '', 'rows' => [], 'columns' => [], 'template_id' => 0, 'filename' => '']; try { if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['excel_file'])) { @@ -22,7 +22,30 @@ try { $fileError = $file['error']; if ($fileError === UPLOAD_ERR_OK) { - $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file['tmp_name']); + // Recupera l'ID dell'utente loggato (assumiamo sia disponibile in $iduserlogin) + if (!isset($iduserlogin)) { + $iduserlogin = 1; // Valore di default + error_log("Warning: iduserlogin non definito, usando 1 come default"); + } + + // Genera il nome del file rinominato + $timestamp = date('YmdHis'); + $originalFilename = basename($file['name']); + $newFilename = "{$iduserlogin}-{$timestamp}-{$originalFilename}"; + $importFolder = __DIR__ . '/imported_trf/'; + if (!file_exists($importFolder)) { + mkdir($importFolder, 0777, true); + } + $destination = $importFolder . $newFilename; + + // Sposta il file + if (!move_uploaded_file($file['tmp_name'], $destination)) { + throw new Exception("Errore durante lo spostamento del file in $destination"); + } + error_log("File spostato con successo in: $destination"); + + // Carica il file rinominato con PHPSpreadsheet + $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($destination); $worksheet = $spreadsheet->getActiveSheet(); $highestRow = $worksheet->getHighestRow(); $highestColumn = $worksheet->getHighestColumn(); @@ -72,6 +95,7 @@ try { $response['rows'] = $excelData; $response['columns'] = $headerRowData; // Usa gli header reali $response['template_id'] = $template_id; + $response['filename'] = $newFilename; // Aggiungi il nome del file rinominato } } else { $response['error'] = "Errore nell'upload del file: Codice errore $fileError."; diff --git a/public/userarea/save_edited_data.php b/public/userarea/save_edited_data.php new file mode 100644 index 0000000..35a8ce0 --- /dev/null +++ b/public/userarea/save_edited_data.php @@ -0,0 +1,47 @@ + false, 'message' => '']; + +try { + if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_POST['iddatadb'])) { + throw new Exception('Richiesta non valida'); + } + + $iddatadb = intval($_POST['iddatadb']); + $db = DBHandlerSelect::getInstance(); + $pdo = $db->getConnection(); + + // Campi non modificabili + $excludeFields = ['importdate', 'status', 'user_id', 'filename_import', 'importreferencecode', 'limscode']; + + // Prepara i dati da aggiornare + $updates = []; + $values = []; + foreach ($_POST as $key => $value) { + if ($key !== 'iddatadb' && !in_array($key, $excludeFields)) { + $updates[] = "$key = ?"; + $values[] = htmlspecialchars($value); + } + } + $values[] = $iddatadb; + + if (empty($updates)) { + throw new Exception('Nessun dato da aggiornare'); + } + + $sql = "UPDATE datadb SET " . implode(', ', $updates) . " WHERE iddatadb = ?"; + $stmt = $pdo->prepare($sql); + $stmt->execute($values); + + $response['success'] = true; + $response['message'] = 'Riga aggiornata con successo'; +} catch (Exception $e) { + $response['message'] = $e->getMessage(); + error_log("Errore in save_edited_row.php: " . $e->getMessage()); +} + +echo json_encode($response); +exit; diff --git a/public/userarea/save_edited_row.php b/public/userarea/save_edited_row.php new file mode 100644 index 0000000..e395bed --- /dev/null +++ b/public/userarea/save_edited_row.php @@ -0,0 +1,44 @@ + false, 'message' => '']; + +try { + if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_POST['iddatadb'])) { + throw new Exception('Richiesta non valida'); + } + + $iddatadb = intval($_POST['iddatadb']); + $db = DBHandlerSelect::getInstance(); + $pdo = $db->getConnection(); + + // Prepara i dati da aggiornare + $updates = []; + $values = []; + foreach ($_POST as $key => $value) { + if ($key !== 'iddatadb') { + $updates[] = "$key = ?"; + $values[] = htmlspecialchars($value); + } + } + $values[] = $iddatadb; + + if (empty($updates)) { + throw new Exception('Nessun dato da aggiornare'); + } + + $sql = "UPDATE datadb SET " . implode(', ', $updates) . " WHERE iddatadb = ?"; + $stmt = $pdo->prepare($sql); + $stmt->execute($values); + + $response['success'] = true; + $response['message'] = 'Riga aggiornata con successo'; +} catch (Exception $e) { + $response['message'] = $e->getMessage(); + error_log("Errore in save_edited_row.php: " . $e->getMessage()); +} + +echo json_encode($response); +exit; diff --git a/public/userarea/top_stat_widget.php b/public/userarea/top_stat_widget.php index e4d9551..2217cfa 100644 --- a/public/userarea/top_stat_widget.php +++ b/public/userarea/top_stat_widget.php @@ -5,9 +5,9 @@
-

Revenue

-

$4805

-

$34 from last week

+

Imported XLS

+

4805

+

34 from last week

@@ -22,7 +22,7 @@

Total Customers

8.4K

-

$24 from last week

+

24 from last week

@@ -35,9 +35,9 @@
-

Store Visitors

+

Exported to LIMS

59K

-

$34 from last week

+

34 from last week

diff --git a/public/userarea/upload_photo.php b/public/userarea/upload_photo.php new file mode 100644 index 0000000..086aa6f --- /dev/null +++ b/public/userarea/upload_photo.php @@ -0,0 +1,79 @@ + false, 'message' => 'Richiesta non valida']); + exit; +} + +$iddatadb = intval($_POST['iddatadb']); +$photo = $_FILES['photo']; + +// Verifica che l'utente loggato esista in auth_users +$db = DBHandlerSelect::getInstance(); +$pdo = $db->getConnection(); + +$stmt = $pdo->prepare("SELECT id FROM auth_users WHERE id = ?"); +$stmt->execute([$iduserlogin]); +$userExists = $stmt->fetch(PDO::FETCH_ASSOC); + +if (!$userExists) { + echo json_encode(['success' => false, 'message' => 'Utente non valido']); + exit; +} + +// Usa un percorso assoluto per la cartella photostrf +$uploadDir = realpath(__DIR__ . '/../photostrf') . '/'; +if (!is_dir($uploadDir)) { + if (!mkdir($uploadDir, 0755, true)) { + echo json_encode(['success' => false, 'message' => 'Impossibile creare la cartella photostrf']); + exit; + } +} + +// Verifica i permessi della cartella +if (!is_writable($uploadDir)) { + echo json_encode(['success' => false, 'message' => 'La cartella photostrf non è scrivibile']); + exit; +} + +// Verifica che il file sia un'immagine +$allowedTypes = ['image/jpeg', 'image/png', 'image/gif']; +if (!in_array($photo['type'], $allowedTypes)) { + echo json_encode(['success' => false, 'message' => 'Il file deve essere un\'immagine (JPEG, PNG, GIF)']); + exit; +} + +// Verifica che il file temporaneo esista +if (!file_exists($photo['tmp_name']) || !is_uploaded_file($photo['tmp_name'])) { + echo json_encode(['success' => false, 'message' => 'File temporaneo non valido']); + exit; +} + +// Rinomina il file: idriga-timestamp-nomeoriginale.estensione +$timestamp = date('YmdHis'); +$originalName = pathinfo($photo['name'], PATHINFO_FILENAME); +$extension = pathinfo($photo['name'], PATHINFO_EXTENSION); +$newFileName = "{$iddatadb}-{$timestamp}-{$originalName}.{$extension}"; +$destination = $uploadDir . $newFileName; + +// Debug: verifica i percorsi +error_log("Upload directory: $uploadDir"); +error_log("Destination: $destination"); +error_log("Temp file: " . $photo['tmp_name']); + +// Salva il file +if (!move_uploaded_file($photo['tmp_name'], $destination)) { + $error = error_get_last(); + echo json_encode(['success' => false, 'message' => 'Errore durante il caricamento del file: ' . (isset($error['message']) ? $error['message'] : 'Sconosciuto')]); + exit; +} + +// Salva il riferimento nel database +$stmt = $pdo->prepare("INSERT INTO datadb_photos (iddatadb, file_path, file_name, uploaded_by) VALUES (?, ?, ?, ?)"); +$stmt->execute([$iddatadb, $newFileName, $photo['name'], $iduserlogin]); + +echo json_encode(['success' => true, 'message' => 'Foto caricata con successo']); diff --git a/public/userarea/upload_photos_mobile.php b/public/userarea/upload_photos_mobile.php new file mode 100644 index 0000000..946708f --- /dev/null +++ b/public/userarea/upload_photos_mobile.php @@ -0,0 +1,145 @@ +getConnection(); + +// Verifica che l'iddatadb sia stato passato +if (!isset($_GET['iddatadb']) || empty($_GET['iddatadb'])) { + die('ID riga non fornito'); +} + +$iddatadb = intval($_GET['iddatadb']); + +// Recupera i dettagli della riga (idriga e sample_code) +$stmt = $pdo->prepare("SELECT iddatadb, sample_code FROM datadb WHERE iddatadb = ?"); +$stmt->execute([$iddatadb]); +$row = $stmt->fetch(PDO::FETCH_ASSOC); + +if (!$row) { + die('Riga non trovata'); +} + +$idriga = $row['iddatadb']; +$sampleCode = $row['sample_code'] ?? 'Non disponibile'; +?> + + + + + + + + Carica Foto da Mobile + + + + +

Carica Foto per ID Riga:

+

Sample Code:

+ +
+

Scatta una foto o seleziona un'immagine

+ +
+ +
+ +
+ + + + + \ No newline at end of file diff --git a/public/userarea/xlstemplates/15-1741439534-MONCLERTRF-21112024_CHIARA_SS25_2CPERPELLI.xlsx b/public/userarea/xlstemplates/15-1741439534-MONCLERTRF-21112024_CHIARA_SS25_2CPERPELLI.xlsx new file mode 100644 index 0000000..8c3b7e0 Binary files /dev/null and b/public/userarea/xlstemplates/15-1741439534-MONCLERTRF-21112024_CHIARA_SS25_2CPERPELLI.xlsx differ diff --git a/trackingmore_response.json b/trackingmore_response.json new file mode 100644 index 0000000..e69de29