diff --git a/public/userarea/class/VisualLimsApiClient.class.php b/public/userarea/class/VisualLimsApiClient.class.php index f2d992d..b3d3944 100644 --- a/public/userarea/class/VisualLimsApiClient.class.php +++ b/public/userarea/class/VisualLimsApiClient.class.php @@ -206,13 +206,12 @@ class VisualLimsApiClient /** * POST a file as multipart/form-data (used for photo/attachment uploads). * - * @param string $endpoint OData endpoint, e.g. "AllegatoCommessaWeb" - * @param string $filePath Absolute path to the file on disk - * @param string $fileName Original file name to send - * @param int $commessaId CommessaWeb ID to link the attachment to - * @return array|null Decoded JSON response + * @param string $endpoint OData endpoint, e.g. "Campione(613388)/UploadCampioneFile" + * @param string $filePath Absolute path to the file on disk + * @param string $fileName Original file name to send + * @return array|null Decoded JSON response */ - public function postMultipart($endpoint, $filePath, $fileName, $commessaId) + public function postMultipart($endpoint, $filePath, $fileName) { $token = $this->getToken(); $url = "{$this->baseUrl}/api/odata/{$endpoint}"; @@ -220,9 +219,7 @@ class VisualLimsApiClient $cfile = new CURLFile($filePath, mime_content_type($filePath) ?: 'application/octet-stream', $fileName); $payload = [ - 'IdCommessa' => $commessaId, - 'NomeFile' => $fileName, - 'file' => $cfile, + 'file' => $cfile, ]; $ch = curl_init($url); diff --git a/public/userarea/class/VisualLimsApiClientMock.class.php b/public/userarea/class/VisualLimsApiClientMock.class.php index 2f5be33..71cd270 100644 --- a/public/userarea/class/VisualLimsApiClientMock.class.php +++ b/public/userarea/class/VisualLimsApiClientMock.class.php @@ -126,9 +126,9 @@ class VisualLimsApiClientMock return []; } - public function postMultipart(string $endpoint, string $filePath, string $fileName, int $commessaId): array + public function postMultipart(string $endpoint, string $filePath, string $fileName): array { - error_log("[SIMULATE] POST multipart {$endpoint} file={$fileName} commessaId={$commessaId}"); + error_log("[SIMULATE] POST multipart {$endpoint} file={$fileName}"); return ['simulated' => true, 'file' => $fileName]; } diff --git a/public/userarea/export_to_lims.php b/public/userarea/export_to_lims.php index 3a75007..268b855 100644 --- a/public/userarea/export_to_lims.php +++ b/public/userarea/export_to_lims.php @@ -43,7 +43,8 @@ try { d.moltiplicatore_prezzo_id, d.anagrafica_certest_object_id, d.anagrafica_certest_service_id, - d.cliente_fornitore_id + d.cliente_fornitore_id, + d.consegna_richiesta FROM datadb as d INNER JOIN excel_templates as et ON d.templateid = et.id WHERE d.iddatadb = :iddatadb @@ -63,8 +64,9 @@ try { $clienteResponsabile = !empty($result['cliente_responsabile_id']) ? (int) $result['cliente_responsabile_id'] : null; $moltiplicatorePrezzo = !empty($result['moltiplicatore_prezzo_id']) ? (int) $result['moltiplicatore_prezzo_id'] : null; $anagraficaObject = !empty($result['anagrafica_certest_object_id']) ? (int) $result['anagrafica_certest_object_id'] : null; - $anagraficaService = !empty($result['anagrafica_certest_service_id']) ? (int) $result['anagrafica_certest_service_id'] : null; - $clienteFornitore = !empty($result['cliente_fornitore_id']) ? (int) $result['cliente_fornitore_id'] : null; + $anagraficaService = !empty($result['anagrafica_certest_service_id'])? (int) $result['anagrafica_certest_service_id']: null; + $clienteFornitore = !empty($result['cliente_fornitore_id'])? (int) $result['cliente_fornitore_id']: null; + $consegnaRichiesta = !empty($result['consegna_richiesta']) ? $result['consegna_richiesta'] : null; // 🔹 STEP 3: Fetch Parts (including idmatrice) $stmt = $pdo->prepare(" @@ -108,19 +110,20 @@ try { // 🔹 Initialize API client $api = VisualLimsApiClient::getInstance(); - // 🔹 STEP 5: Create CommessaWeb (NOT WebOrder) - // Includes fixed fields fetched from datadb in STEP 1+2 + // 🔹 STEP 5: Create CommessaWeb + // Fixed fields are sent as direct properties — they are navigation properties on Commessa + // accepted by the XAF API even though not explicitly listed in OData $metadata $commessaWebPayload = [ - "Cliente" => $clienteId, - "SchemaCustomField" => $schemaId, - "Richiedente" => "Test Web Import", - "Descrizione" => "TEST CommessaWeb", - // Fixed fields from datadb - "ClienteResponsabile" => $clienteResponsabile, - "MoltiplicatorePrezzo" => $moltiplicatorePrezzo, + "Cliente" => $clienteId, + "SchemaCustomField" => $schemaId, + "Richiedente" => "Test Web Import", // TODO: replace with real value + "Descrizione" => "TEST CommessaWeb", // TODO: replace with real value + "ClienteResponsabile" => $clienteResponsabile, + "MoltiplicatorePrezzo" => $moltiplicatorePrezzo, "AnagraficaCertestObject" => $anagraficaObject, "AnagraficaCertestService" => $anagraficaService, - "ClienteFornitore" => $clienteFornitore, // PLACEHOLDER — to be implemented + "ClienteFornitore" => $clienteFornitore, // PLACEHOLDER — to be implemented + // DeliveryRequest goes to Campione, not CommessaWeb ]; // Costruisci log curl-like per STEP 5 @@ -141,49 +144,6 @@ try { $commessaId = $commessaWeb["IdCommessa"]; $commessaWebCode = substr($commessaWeb["CodiceCommessa"] ?? "TEST CommessaWeb", 0, 30); // Limite a 30 caratteri - // 🔹 STEP 5.1: Fetch photos linked to this iddatadb - $stmtPhotos = $pdo->prepare(" - SELECT id, file_path, file_name - FROM datadb_photos - WHERE iddatadb = :iddatadb - ORDER BY id ASC - "); - $stmtPhotos->execute(['iddatadb' => $iddatadb]); - $photos = $stmtPhotos->fetchAll(PDO::FETCH_ASSOC); - - // 🔹 STEP 5.2: Upload photos to CommessaWeb - // NOTE: The sample number corresponds to the CommessaWeb ID ($commessaId). - // Photos may be multiple or may not exist at all. - - $photosUploaded = 0; - $logContentPhotos = "Photos for CommessaWeb {$commessaId} (iddatadb={$iddatadb}):\n"; - $logContentPhotos .= "Total photos found: " . count($photos) . "\n\n"; - - foreach ($photos as $photo) { - // Build absolute path from the relative path stored in DB - $photoPath = $uploadDir . '/' . ltrim($photo['file_path'], './'); - $fullPath = realpath($photoPath); - - if (!$fullPath || !file_exists($fullPath)) { - $logContentPhotos .= "SKIP (file not found): full - $photoPath " . $photo['file_path'] . "\n"; - continue; - } - - // Construct curl-like log entry - $logContentPhotos .= "curl --location --request POST '{$apiBaseUrl}AllegatoCommessaWeb' \\\n" . - "--header 'Authorization: Bearer ••••••' \\\n" . - "--form 'IdCommessa={$commessaId}' \\\n" . - "--form 'file=@{$fullPath}'\n\n"; - - // ENDPOINT NAME TO BE CONFIRMED - $photoResult = $api->postMultipart("AllegatoCommessaWeb", $fullPath, $photo['file_name'], $commessaId); - $logContentPhotos .= "RESPONSE:\n" . json_encode($photoResult, JSON_PRETTY_PRINT) . "\n\n---\n"; - $photosUploaded++; - } - - $logFilePhotos = $logDir . "commessa_{$commessaId}_photos_step5_2_" . time() . ".txt"; - file_put_contents($logFilePhotos, $logContentPhotos); - // 🔹 STEP 6: Create Campioni (Samples) for each part $campioni = []; $logContentStep6 = ""; @@ -196,11 +156,12 @@ try { } $campionePayload = [ - "Commessa" => $commessaId, - "Matrice" => $matriceId, - "SottoMatrice" => null, + "Commessa" => $commessaId, + "Matrice" => $matriceId, + "SottoMatrice" => null, "SchemaCustomField" => $schemaId, - "NoteWeb" => $part["part_description"] ?? "" + "NoteWeb" => $part["part_description"] ?? "", + "DeliveryRequest" => $consegnaRichiesta, ]; // Costruisci curl-like per questo campione @@ -227,11 +188,62 @@ try { $logFileStep6 = $logDir . "commessa_{$commessaId}_campioni_step6_" . time() . ".txt"; file_put_contents($logFileStep6, $logContentStep6); + // 🔹 STEP 6.1: Fetch photos linked to this iddatadb + $stmtPhotos = $pdo->prepare(" + SELECT id, file_path, file_name + FROM datadb_photos + WHERE iddatadb = :iddatadb + ORDER BY id ASC + "); + $stmtPhotos->execute(['iddatadb' => $iddatadb]); + $photos = $stmtPhotos->fetchAll(PDO::FETCH_ASSOC); + + + // 🔹 STEP 6.2: Upload photos to the first (main) Campione only + $photosUploaded = 0; + $logContentPhotos = "Photos for CommessaWeb {$commessaId} (iddatadb={$iddatadb}):\n"; + $logContentPhotos .= "Total photos found: " . count($photos) . ", campioni: " . count($campioni) . "\n\n"; + + if (!empty($campioni) && !empty($photos)) { + $mainCampione = $campioni[0]; + $campioneId = (int)($mainCampione['IdCampione'] ?? 0); + + if ($campioneId > 0) { + $logContentPhotos .= "=== Campione {$campioneId} (main) ===\n"; + + foreach ($photos as $photo) { + $photoPath = $uploadDir . '/' . ltrim($photo['file_path'], './'); + $fullPath = realpath($photoPath); + + if (!$fullPath || !file_exists($fullPath)) { + $logContentPhotos .= "SKIP (file not found): {$photoPath}\n"; + continue; + } + + $photoEndpoint = "Campione({$campioneId})/UploadCampioneFile"; + $logContentPhotos .= "curl --location --request POST '{$apiBaseUrl}{$photoEndpoint}' \\\n" . + "--header 'Authorization: Bearer ••••••' \\\n" . + "--form 'file=@{$fullPath}'\n\n"; + + $photoResult = $api->postMultipart($photoEndpoint, $fullPath, $photo['file_name']); + $logContentPhotos .= "RESPONSE:\n" . json_encode($photoResult, JSON_PRETTY_PRINT) . "\n\n---\n"; + $photosUploaded++; + } + } else { + $logContentPhotos .= "SKIP: main campione has invalid IdCampione\n"; + } + } elseif (empty($campioni)) { + $logContentPhotos .= "SKIP: no campioni created, cannot upload photos\n"; + } + + $logFilePhotos = $logDir . "commessa_{$commessaId}_photos_step5_2_" . time() . ".txt"; + file_put_contents($logFilePhotos, $logContentPhotos); + // 🔹 STEP 7: Update Custom Fields for CommessaWeb if (!empty($fieldValues)) { // GET con espansione per CustomField $expand = "CommesseCustomFields(\$expand=CustomField)"; - $commessaWithFields = $api->get("CommessaWeb(" . $commessaId . ")?\$expand=" . $expand); + $commessaWithFields = $api->get("CommessaWeb({$commessaId})?\$expand={$expand}"); // Logga il GET $logContentGet = "curl --location --request GET '{$apiBaseUrl}CommessaWeb({$commessaId})?\$expand=CommesseCustomFields(\$expand=CustomField)' \\\n" . @@ -260,6 +272,7 @@ try { ]; } + $logFileStep7 = null; if (!empty($commessaCustomFields)) { $updatePayload = ["CommesseCustomFields" => $commessaCustomFields]; @@ -311,10 +324,10 @@ try { // Logga il POST $logContentStep91 = "curl --location --request POST '{$apiBaseUrl}CommessaWeb({$commessaId})/ImportaCommessa' \\\n" . - "--header 'Content-Type: application/json' \\\n" . - "--header 'Authorization: Bearer ••••••' \\\n" . - "--data '{}'\n\n" . - "RESPONSE:\n" . json_encode($importResult, JSON_PRETTY_PRINT); + "--header 'Content-Type: application/json' \\\n" . + "--header 'Authorization: Bearer ••••••' \\\n" . + "--data '{}'\n\n" . + "RESPONSE:\n" . json_encode($importResult, JSON_PRETTY_PRINT); $logFileStep91 = $logDir . "commessa_{$commessaId}_importa_step91_" . time() . ".txt"; file_put_contents($logFileStep91, $logContentStep91);