Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 490786731a | |||
| e96f538a47 | |||
| cc96ecb67f | |||
| 4cf03ae742 | |||
| 7a486e9dcf | |||
| a05d9fed2b | |||
| 65170a0a7c | |||
| 223688c372 | |||
| b562eb4033 | |||
| 0645a0c675 | |||
| a02a6b2c4c | |||
| 45dd8d6907 | |||
| 755f6812d4 | |||
| 5e59ae2162 | |||
| 71a19144c8 | |||
| 381a05341b | |||
| 5a58decd40 | |||
| eb21910ef3 | |||
| 5dedc779df | |||
| f4e0074a73 | |||
| 9c850e4ea6 | |||
| f300811341 | |||
| 48387a9945 | |||
| 0e90db8219 | |||
| eaf70d5a46 |
+3
-1
@@ -33,11 +33,13 @@ yarn-error.log
|
||||
/public/userarea/*.log
|
||||
/public/userarea/*.txt
|
||||
/public/userarea/*_response.json
|
||||
/public/userarea/customfield_values_response.json
|
||||
/public/userarea/error_log.txt
|
||||
/public/userarea/import_debug.log
|
||||
/public/userarea/last_url.txt
|
||||
/public/userarea/logaspi/
|
||||
/public/userarea/logsapi/
|
||||
/public/userarea/logs/api/
|
||||
/public/userarea/logs/api/**
|
||||
/public/userarea/photostrf/
|
||||
/public/userarea/class/*.log
|
||||
/public/userarea/class/curl_auth_debug.log
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
||||
# DB LOCALE (Windows 11)
|
||||
url=jdbc:mysql://localhost:3306/trfcertest
|
||||
username=solocla
|
||||
password=!Massarosa2
|
||||
driver=com.mysql.cj.jdbc.Driver
|
||||
changeLogFile=liquibase/changelog/db.changelog-master.yaml
|
||||
@@ -30,6 +30,8 @@ if ((int)$stmt->fetchColumn() > 0) {
|
||||
$fixedFields = [
|
||||
// fixed_field_key, data_type
|
||||
['ClienteResponsabile', 'INT'],
|
||||
['ClienteFornitore', 'INT'],
|
||||
['ClienteAnalisi', 'INT'],
|
||||
['MoltiplicatorePrezzo', 'INT'],
|
||||
['AnagraficaCertestObject', 'INT'],
|
||||
['AnagraficaCertestService', 'INT'],
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,290 @@
|
||||
<?php
|
||||
require_once "class/VisualLimsApiClient.class.php";
|
||||
include('include/headscript.php');
|
||||
|
||||
// Force HTML response
|
||||
header('Content-Type: text/html; charset=UTF-8');
|
||||
|
||||
// Initialize variables
|
||||
$error = null;
|
||||
$result = null;
|
||||
$entityType = $_GET['entity_type'] ?? 'CommessaWeb';
|
||||
$entityId = isset($_GET['entity_id']) ? (int)$_GET['entity_id'] : 0;
|
||||
$customExpand = trim($_GET['expand'] ?? '');
|
||||
$rawEndpoint = null;
|
||||
|
||||
function h($value)
|
||||
{
|
||||
return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
|
||||
function renderArrayAsTable(array $items)
|
||||
{
|
||||
if (empty($items)) {
|
||||
echo '<div class="alert alert-secondary">No records found</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
$firstRow = reset($items);
|
||||
if (!is_array($firstRow)) {
|
||||
echo '<pre class="bg-light p-3 border rounded">' . h(json_encode($items, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)) . '</pre>';
|
||||
return;
|
||||
}
|
||||
|
||||
$headers = [];
|
||||
foreach ($items as $row) {
|
||||
if (is_array($row)) {
|
||||
$headers = array_unique(array_merge($headers, array_keys($row)));
|
||||
}
|
||||
}
|
||||
|
||||
echo '<div class="table-responsive">';
|
||||
echo '<table class="table table-striped table-bordered table-sm align-middle">';
|
||||
echo '<thead class="table-dark"><tr>';
|
||||
foreach ($headers as $header) {
|
||||
echo '<th>' . h($header) . '</th>';
|
||||
}
|
||||
echo '</tr></thead><tbody>';
|
||||
|
||||
foreach ($items as $row) {
|
||||
echo '<tr>';
|
||||
foreach ($headers as $header) {
|
||||
$value = $row[$header] ?? '';
|
||||
if (is_array($value) || is_object($value)) {
|
||||
$value = json_encode($value, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
echo '<td><pre style="white-space:pre-wrap; margin:0;">' . h($value) . '</pre></td>';
|
||||
} else {
|
||||
echo '<td>' . h($value) . '</td>';
|
||||
}
|
||||
}
|
||||
echo '</tr>';
|
||||
}
|
||||
|
||||
echo '</tbody></table>';
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
try {
|
||||
if ($entityId > 0) {
|
||||
$api = VisualLimsApiClient::getInstance();
|
||||
|
||||
// Default expands for better debugging
|
||||
if ($customExpand !== '') {
|
||||
$expand = $customExpand;
|
||||
} else {
|
||||
if ($entityType === 'CommessaWeb') {
|
||||
$expand = implode(',', [
|
||||
'CommesseCustomFields($expand=CustomField)',
|
||||
'Campioni'
|
||||
]);
|
||||
} else {
|
||||
$expand = implode(',', [
|
||||
'CommesseCustomFields($expand=CustomField)',
|
||||
'Campioni'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$rawEndpoint = $entityType . '(' . $entityId . ')?$expand=' . $expand;
|
||||
$result = $api->get($rawEndpoint);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$error = $e->getMessage();
|
||||
}
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Debug Commessa API</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
body {
|
||||
background: #f5f7fb;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
.debug-card {
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 18px rgba(0, 0, 0, 0.08);
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: #f8f9fa;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.label-box {
|
||||
display: inline-block;
|
||||
padding: 6px 10px;
|
||||
border-radius: 8px;
|
||||
background: #eef3ff;
|
||||
color: #2446a8;
|
||||
font-weight: 600;
|
||||
margin-right: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.mini-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.mini-box {
|
||||
background: #f8fafc;
|
||||
border: 1px solid #e4e7eb;
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.mini-box strong {
|
||||
display: block;
|
||||
margin-bottom: 6px;
|
||||
color: #1f2937;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container py-4">
|
||||
<div class="debug-card">
|
||||
<h2 class="mb-3">Commessa / CommessaWeb API Inspector</h2>
|
||||
|
||||
<form method="GET" class="row g-3">
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Entity Type</label>
|
||||
<select name="entity_type" class="form-select">
|
||||
<option value="CommessaWeb" <?= $entityType === 'CommessaWeb' ? 'selected' : '' ?>>CommessaWeb</option>
|
||||
<option value="Commessa" <?= $entityType === 'Commessa' ? 'selected' : '' ?>>Commessa</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-2">
|
||||
<label class="form-label">Entity ID</label>
|
||||
<input type="number" name="entity_id" class="form-control" value="<?= h($entityId) ?>" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-5">
|
||||
<label class="form-label">Expand</label>
|
||||
<input type="text" name="expand" class="form-control" value="<?= h($customExpand) ?>" placeholder="CommesseCustomFields($expand=CustomField),Campioni">
|
||||
</div>
|
||||
|
||||
<div class="col-md-2 d-flex align-items-end">
|
||||
<button type="submit" class="btn btn-primary w-100">Load Data</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php if ($rawEndpoint): ?>
|
||||
<div class="debug-card">
|
||||
<div class="section-title">Requested Endpoint</div>
|
||||
<pre><?= h($rawEndpoint) ?></pre>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($error): ?>
|
||||
<div class="debug-card">
|
||||
<div class="alert alert-danger mb-0">
|
||||
<strong>API Error:</strong><br>
|
||||
<?= h($error) ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($result && is_array($result)): ?>
|
||||
<div class="debug-card">
|
||||
<div class="section-title">Main Information</div>
|
||||
<div class="mini-grid">
|
||||
<div class="mini-box">
|
||||
<strong>ID</strong>
|
||||
<?= h($result['IdCommessa'] ?? $result['IdCommessaWeb'] ?? '') ?>
|
||||
</div>
|
||||
<div class="mini-box">
|
||||
<strong>Code</strong>
|
||||
<?= h($result['CodiceCommessa'] ?? '') ?>
|
||||
</div>
|
||||
<div class="mini-box">
|
||||
<strong>Cliente</strong>
|
||||
<?= h($result['Cliente'] ?? '') ?>
|
||||
</div>
|
||||
<div class="mini-box">
|
||||
<strong>SchemaCustomField</strong>
|
||||
<?= h($result['SchemaCustomField'] ?? '') ?>
|
||||
</div>
|
||||
<div class="mini-box">
|
||||
<strong>Richiedente</strong>
|
||||
<?= h($result['Richiedente'] ?? '') ?>
|
||||
</div>
|
||||
<div class="mini-box">
|
||||
<strong>Descrizione</strong>
|
||||
<?= h($result['Descrizione'] ?? '') ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="debug-card">
|
||||
<div class="section-title">Direct Properties</div>
|
||||
<pre><?= h(json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)) ?></pre>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($result['CommesseCustomFields']) && is_array($result['CommesseCustomFields'])): ?>
|
||||
<div class="debug-card">
|
||||
<div class="section-title">CommesseCustomFields</div>
|
||||
<?php
|
||||
$fieldsRows = [];
|
||||
foreach ($result['CommesseCustomFields'] as $field) {
|
||||
$fieldsRows[] = [
|
||||
'IdCommesseCustomFields' => $field['IdCommesseCustomFields'] ?? '',
|
||||
'Valore' => $field['Valore'] ?? '',
|
||||
'CustomFieldId' => $field['CustomField']['IdCustomField'] ?? '',
|
||||
'Label' => $field['CustomField']['Descrizione'] ?? ($field['CustomField']['Name'] ?? ''),
|
||||
'Tipo' => $field['CustomField']['Tipo'] ?? '',
|
||||
];
|
||||
}
|
||||
renderArrayAsTable($fieldsRows);
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($result['Campioni']) && is_array($result['Campioni'])): ?>
|
||||
<div class="debug-card">
|
||||
<div class="section-title">Campioni</div>
|
||||
<?php renderArrayAsTable($result['Campioni']); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="debug-card">
|
||||
<div class="section-title">Raw JSON</div>
|
||||
<pre><?= h(json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)) ?></pre>
|
||||
</div>
|
||||
<?php elseif ($entityId > 0 && !$error): ?>
|
||||
<div class="debug-card">
|
||||
<div class="alert alert-warning mb-0">No data returned from API</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
<!-- Example of use
|
||||
debug_commessa_api.php?entity_type=CommessaWeb&entity_id=564779
|
||||
debug_commessa_api.php?entity_type=Commessa&entity_id=12345
|
||||
debug_commessa_api.php?entity_type=CommessaWeb&entity_id=564779&expand=CommesseCustomFields($expand=CustomField),Campioni
|
||||
-->
|
||||
@@ -314,3 +314,17 @@
|
||||
2026-02-26 15:01:32 [AnagraficaCertestObject] Autenticazione fallita: HTTP 400, Errore cURL: , Risposta: {"title":"Bad Request","status":400,"detail":"Cannot persist the object. It was modified or deleted (purged) by another application.","instance":"POST /api/authentication/authenticate","errorCode":"96bfc1252b"}
|
||||
2026-02-28 21:01:27 [AnagraficaCertestService] Autenticazione fallita: HTTP 400, Errore cURL: , Risposta: {"title":"Bad Request","status":400,"detail":"Cannot persist the object. It was modified or deleted (purged) by another application.","instance":"POST /api/authentication/authenticate","errorCode":"96bfc1252b"}
|
||||
2026-03-01 19:11:58 [AnagraficaCertestObject] Autenticazione fallita: HTTP 400, Errore cURL: , Risposta: {"title":"Bad Request","status":400,"detail":"Cannot persist the object. It was modified or deleted (purged) by another application.","instance":"POST /api/authentication/authenticate","errorCode":"96bfc1252b"}
|
||||
2026-03-18 15:51:45 [AnagraficaCertestService] Autenticazione fallita: HTTP 400, Errore cURL: , Risposta: {"title":"Bad Request","status":400,"detail":"Cannot persist the object. It was modified or deleted (purged) by another application.","instance":"POST /api/authentication/authenticate","errorCode":"96bfc1252b"}
|
||||
2026-03-19 09:50:34 [AnagraficaCertestService] Autenticazione fallita: HTTP 400, Errore cURL: , Risposta: {"title":"Bad Request","status":400,"detail":"Cannot persist the object. It was modified or deleted (purged) by another application.","instance":"POST /api/authentication/authenticate","errorCode":"96bfc1252b"}
|
||||
2026-03-25 14:13:34 - Autenticazione fallita: HTTP 503, Errore cURL: , Risposta: The service is unavailable.
|
||||
2026-03-25 14:13:34 - Autenticazione fallita: HTTP 503, Errore cURL: , Risposta: The service is unavailable.
|
||||
2026-03-26 10:57:18 [AnagraficaCertestObject] Autenticazione fallita: HTTP 500, Errore cURL: , Risposta: {"title":"Internal Server Error","status":500,"detail":"Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.","instance":"POST /api/authentication/authenticate","errorCode":"63ab532c6"}
|
||||
2026-03-26 10:57:21 [AnagraficaCertestObject] Autenticazione fallita: HTTP 500, Errore cURL: , Risposta: {"title":"Internal Server Error","status":500,"detail":"Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.","instance":"POST /api/authentication/authenticate","errorCode":"63ab532c6"}
|
||||
2026-03-26 10:57:21 [AnagraficaCertestService] Autenticazione fallita: HTTP 500, Errore cURL: , Risposta: {"title":"Internal Server Error","status":500,"detail":"Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.","instance":"POST /api/authentication/authenticate","errorCode":"63ab532c6"}
|
||||
2026-03-26 10:57:21 [MoltiplicatorePrezzo] Autenticazione fallita: HTTP 500, Errore cURL: , Risposta: {"title":"Internal Server Error","status":500,"detail":"Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.","instance":"POST /api/authentication/authenticate","errorCode":"63ab532c6"}
|
||||
2026-03-26 10:57:36 [AnagraficaCertestObject] Autenticazione fallita: HTTP 500, Errore cURL: , Risposta: {"title":"Internal Server Error","status":500,"detail":"Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.","instance":"POST /api/authentication/authenticate","errorCode":"63ab532c6"}
|
||||
2026-03-26 10:57:36 [AnagraficaCertestService] Autenticazione fallita: HTTP 500, Errore cURL: , Risposta: {"title":"Internal Server Error","status":500,"detail":"Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.","instance":"POST /api/authentication/authenticate","errorCode":"63ab532c6"}
|
||||
2026-03-26 10:57:36 [MoltiplicatorePrezzo] Autenticazione fallita: HTTP 500, Errore cURL: , Risposta: {"title":"Internal Server Error","status":500,"detail":"Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.","instance":"POST /api/authentication/authenticate","errorCode":"63ab532c6"}
|
||||
2026-03-26 10:57:41 [MoltiplicatorePrezzo] Autenticazione fallita: HTTP 500, Errore cURL: , Risposta: {"title":"Internal Server Error","status":500,"detail":"Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.","instance":"POST /api/authentication/authenticate","errorCode":"63ab532c6"}
|
||||
2026-03-26 10:57:56 [AnagraficaCertestObject] Autenticazione fallita: HTTP 500, Errore cURL: , Risposta: {"title":"Internal Server Error","status":500,"detail":"Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.","instance":"POST /api/authentication/authenticate","errorCode":"63ab532c6"}
|
||||
2026-03-26 10:58:11 [AnagraficaCertestService] Autenticazione fallita: HTTP 500, Errore cURL: , Risposta: {"title":"Internal Server Error","status":500,"detail":"Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.","instance":"POST /api/authentication/authenticate","errorCode":"63ab532c6"}
|
||||
|
||||
@@ -330,8 +330,16 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
// Validate first
|
||||
clearValidationErrors();
|
||||
|
||||
// Show validating state on the row
|
||||
setRowExporting(gridRow, true);
|
||||
const spinner = gridRow.querySelector(".batch-row-spinner");
|
||||
if (spinner) spinner.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Validating...';
|
||||
|
||||
validateRows([{ iddatadb: parseInt(iddatadb), index: parseInt(rowIndex) }])
|
||||
.then((validationData) => {
|
||||
setRowExporting(gridRow, false);
|
||||
gridRow.classList.remove("batch-disabled");
|
||||
|
||||
if (!validationData.success) {
|
||||
showExportResult({ success: false, message: validationData.message || "Errore di validazione" });
|
||||
return;
|
||||
@@ -348,6 +356,9 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
showConfirmAndExport(iddatadb, btn);
|
||||
})
|
||||
.catch((error) => {
|
||||
setRowExporting(gridRow, false);
|
||||
gridRow.classList.remove("batch-disabled");
|
||||
|
||||
console.error("Validation error:", error);
|
||||
showExportResult({ success: false, message: "Errore di validazione: " + error.message });
|
||||
});
|
||||
@@ -379,13 +390,29 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
console.log(`Confirmed export for iddatadb: ${iddatadb}`);
|
||||
confirmModal.hide();
|
||||
|
||||
const gridRow = btn.closest(".grid-row");
|
||||
setRowExporting(gridRow, true);
|
||||
|
||||
try {
|
||||
const gridRow = btn.closest(".grid-row");
|
||||
const data = await sendExport(iddatadb, gridRow);
|
||||
console.log("Export response:", data);
|
||||
|
||||
// Stop spinner, fully restore row
|
||||
setRowExporting(gridRow, false);
|
||||
gridRow.classList.remove("batch-disabled");
|
||||
|
||||
if (!data.success) {
|
||||
showRowError(gridRow, iddatadb, data.message || "Errore sconosciuto");
|
||||
}
|
||||
showExportResult(data);
|
||||
} catch (error) {
|
||||
console.error("Export error:", error);
|
||||
|
||||
// Stop spinner, fully restore row so user can retry
|
||||
setRowExporting(gridRow, false);
|
||||
gridRow.classList.remove("batch-disabled");
|
||||
|
||||
showRowError(gridRow, iddatadb, error.message);
|
||||
showExportResult({
|
||||
success: false,
|
||||
message: error.message,
|
||||
|
||||
@@ -49,6 +49,16 @@ function validateDate($value)
|
||||
return null; // Imposta null se non è una data valida
|
||||
}
|
||||
|
||||
// 🔹 Funzione per validare e convertire date
|
||||
function formatDateToExport($value)
|
||||
{
|
||||
$date = DateTime::createFromFormat('Y-m-d', $value) ?: DateTime::createFromFormat('Y-m-d H:i:s', $value);
|
||||
if ($date) {
|
||||
return $date->format('d/m/Y');
|
||||
}
|
||||
return null; // Imposta null se non è una data valida
|
||||
}
|
||||
|
||||
try {
|
||||
$iddatadb = $_POST['iddatadb'] ?? null;
|
||||
if (!$iddatadb) {
|
||||
@@ -69,6 +79,7 @@ try {
|
||||
d.anagrafica_certest_object_id,
|
||||
d.anagrafica_certest_service_id,
|
||||
d.cliente_fornitore_id,
|
||||
d.clienteAnalisi,
|
||||
d.consegna_richiesta
|
||||
FROM datadb as d
|
||||
INNER JOIN excel_templates as et ON d.templateid = et.id
|
||||
@@ -91,17 +102,35 @@ try {
|
||||
$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;
|
||||
$clienteAnalisi = !empty($result['clienteAnalisi']) ? (int) $result['clienteAnalisi'] : null;
|
||||
$consegnaRichiesta = !empty($result['consegna_richiesta']) ? $result['consegna_richiesta'] : null;
|
||||
|
||||
// 🔹 STEP 3: Fetch Parts (including idmatrice)
|
||||
// 🔹 STEP 3: Fetch Parts (including idmatrice and part id for custom fields)
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT part_number, part_description, material, color, mix, idmatrice
|
||||
FROM identification_parts
|
||||
WHERE iddatadb = :iddatadb
|
||||
SELECT id AS part_id, part_number, part_description, material, color, mix, idmatrice, dateexpiry
|
||||
FROM identification_parts
|
||||
WHERE iddatadb = :iddatadb
|
||||
ORDER BY CAST(part_number AS UNSIGNED) ASC, part_number ASC
|
||||
");
|
||||
$stmt->execute(['iddatadb' => $iddatadb]);
|
||||
$parts = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// 🔹 STEP 3.1: Fetch custom field values per part from identification_parts_customfields
|
||||
$partIds = array_column($parts, 'part_id');
|
||||
$partsCustomFields = []; // part_id => [ { field_id, value_id, value_text }, ... ]
|
||||
if (!empty($partIds)) {
|
||||
$placeholders = implode(',', array_fill(0, count($partIds), '?'));
|
||||
$cfStmt = $pdo->prepare("
|
||||
SELECT part_id, field_id, value_id, value_text
|
||||
FROM identification_parts_customfields
|
||||
WHERE part_id IN ({$placeholders})
|
||||
");
|
||||
$cfStmt->execute($partIds);
|
||||
foreach ($cfStmt->fetchAll(PDO::FETCH_ASSOC) as $cfRow) {
|
||||
$partsCustomFields[(int)$cfRow['part_id']][] = $cfRow;
|
||||
}
|
||||
}
|
||||
|
||||
// 🔹 STEP 4a: Auto-populate export_date / export_time fields
|
||||
$stmt = $pdo->prepare("
|
||||
UPDATE import_data_details idd
|
||||
@@ -165,6 +194,7 @@ try {
|
||||
"AnagraficaCertestObject" => $anagraficaObject,
|
||||
"AnagraficaCertestService" => $anagraficaService,
|
||||
"ClienteFornitore" => $clienteFornitore, // PLACEHOLDER — to be implemented
|
||||
"ClienteAnalisi" => $clienteAnalisi, // PLACEHOLDER — to be implemented
|
||||
// DeliveryRequest goes to Campione, not CommessaWeb
|
||||
];
|
||||
|
||||
@@ -202,9 +232,9 @@ try {
|
||||
"Matrice" => $matriceId,
|
||||
"SottoMatrice" => null,
|
||||
"SchemaCustomField" => $schemaId,
|
||||
"Riferimento" => $part["part_description"] ?? "",
|
||||
// "Riferimento" => $part["part_description"] ?? "",
|
||||
"NoteWeb" => $part["part_description"] ?? "",
|
||||
"ConsegnaRichiesta" => $consegnaRichiesta,
|
||||
"ConsegnaRichiesta" => !empty($part["dateexpiry"]) ? $part["dateexpiry"] : $consegnaRichiesta,
|
||||
];
|
||||
|
||||
// Costruisci curl-like per questo campione
|
||||
@@ -231,6 +261,83 @@ try {
|
||||
$logFileStep6 = $logDir . "commessa_{$commessaId}_campioni_step6_" . time() . ".txt";
|
||||
$writeLog($logFileStep6, $logContentStep6, "STEP 6 - Campioni (commessa={$commessaId})");
|
||||
|
||||
// 🔹 STEP 6.0: PATCH each Campione custom fields:
|
||||
// - field 189 (Tested Component) = part_description
|
||||
// - additional fields from identification_parts_customfields (field_id → value_id/value_text)
|
||||
$logContentStep63 = "";
|
||||
foreach ($campioni as $index => $campione) {
|
||||
$campioneId = (int)($campione['IdCampione'] ?? 0);
|
||||
$partDescription = $parts[$index]['part_description'] ?? '';
|
||||
$partId = (int)($parts[$index]['part_id'] ?? 0);
|
||||
|
||||
if ($campioneId <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Build a map of overrides: IdCustomField => value
|
||||
$overrides = [];
|
||||
|
||||
// Override 1: Tested Component (field 189) = part_description
|
||||
if ($partDescription !== '') {
|
||||
$overrides[189] = $partDescription;
|
||||
}
|
||||
|
||||
// Override 2: values from identification_parts_customfields
|
||||
$partCFs = $partsCustomFields[$partId] ?? [];
|
||||
foreach ($partCFs as $pcf) {
|
||||
$cfFieldId = (int)$pcf['field_id'];
|
||||
$cfValue = $pcf['value_text'] ?? $pcf['value_id'] ?? null;
|
||||
if ($cfFieldId > 0 && $cfValue !== null && $cfValue !== '') {
|
||||
$overrides[$cfFieldId] = (string)$cfValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Skip if nothing to override
|
||||
if (empty($overrides)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// GET campione custom fields
|
||||
$campioneWithFields = $api->get("Campione({$campioneId})?\$expand=CampioniCustomFields(\$expand=CustomField)");
|
||||
|
||||
$logContentStep63 .= "GET Campione({$campioneId}) CustomFields:\n" .
|
||||
json_encode($campioneWithFields['CampioniCustomFields'] ?? [], JSON_PRETTY_PRINT) . "\n\n";
|
||||
$logContentStep63 .= "Overrides for part {$partId}: " . json_encode($overrides) . "\n\n";
|
||||
|
||||
// Build PATCH payload — apply overrides where IdCustomField matches
|
||||
$campioniCustomFields = [];
|
||||
foreach ($campioneWithFields["CampioniCustomFields"] ?? [] as $cf) {
|
||||
$definitionId = (int)($cf["CustomField"]["IdCustomField"] ?? 0);
|
||||
$fieldInstanceId = (int)$cf["IdCampioniCustomFields"];
|
||||
$currentValue = $cf["Valore"] ?? '';
|
||||
|
||||
$newValue = $overrides[$definitionId] ?? $currentValue;
|
||||
|
||||
$campioniCustomFields[] = [
|
||||
"IdCampioniCustomFields" => $fieldInstanceId,
|
||||
"Valore" => $newValue
|
||||
];
|
||||
}
|
||||
|
||||
if (!empty($campioniCustomFields)) {
|
||||
$patchPayload = ["CampioniCustomFields" => $campioniCustomFields];
|
||||
$patchJson = json_encode($patchPayload, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||||
|
||||
$logContentStep63 .= "PATCH Campione({$campioneId}):\n" .
|
||||
"curl --location --request PATCH '{$apiBaseUrl}Campione({$campioneId})' \\\n" .
|
||||
"--header 'Content-Type: application/json' \\\n" .
|
||||
"--header 'Authorization: Bearer ••••••' \\\n" .
|
||||
"--data '{$patchJson}'\n\n";
|
||||
|
||||
$patchResult = $api->patch("Campione({$campioneId})", $patchPayload);
|
||||
|
||||
$logContentStep63 .= "RESPONSE:\n" . json_encode($patchResult, JSON_PRETTY_PRINT) . "\n\n---\n";
|
||||
}
|
||||
}
|
||||
|
||||
$logFileStep63 = $logDir . "commessa_{$commessaId}_campioni_customfields_step60_" . time() . ".txt";
|
||||
$writeLog($logFileStep63, $logContentStep63, "STEP 6.0 - Campioni CustomFields (commessa={$commessaId})");
|
||||
|
||||
// 🔹 STEP 6.1: Fetch photos linked to this iddatadb
|
||||
$stmtPhotos = $pdo->prepare("
|
||||
SELECT id, file_path, file_name, StampaNelRapporto, PrimaPagina
|
||||
@@ -242,15 +349,28 @@ try {
|
||||
$photos = $stmtPhotos->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
|
||||
// 🔹 STEP 6.2: Upload photos to the first (main) Campione only
|
||||
// 🔹 STEP 6.2: Upload photos to Campione .01 (fetched from API)
|
||||
$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];
|
||||
// Fetch campioni list from API to find the .01 campione
|
||||
$commessaCampioni = $api->get("CommessaWeb({$commessaId})?\$expand=Campioni");
|
||||
$apiCampioni = $commessaCampioni['Campioni'] ?? [];
|
||||
|
||||
// Sort by CodiceCampione to find .01
|
||||
usort($apiCampioni, fn($a, $b) => strcmp($a['CodiceCampione'] ?? '', $b['CodiceCampione'] ?? ''));
|
||||
|
||||
$mainCampione = $apiCampioni[0] ?? null;
|
||||
$campioneId = (int)($mainCampione['IdCampione'] ?? 0);
|
||||
|
||||
$logContentPhotos .= "API Campioni order:\n";
|
||||
foreach ($apiCampioni as $ac) {
|
||||
$logContentPhotos .= " - {$ac['CodiceCampione']} (IdCampione: {$ac['IdCampione']})\n";
|
||||
}
|
||||
$logContentPhotos .= "Selected .01 campione: IdCampione={$campioneId}\n\n";
|
||||
|
||||
if ($campioneId > 0) {
|
||||
$logContentPhotos .= "=== Campione {$campioneId} (main) ===\n";
|
||||
|
||||
@@ -264,21 +384,42 @@ try {
|
||||
}
|
||||
|
||||
$photoEndpoint = "Campione({$campioneId})/UploadCampioneFile";
|
||||
$stampaNelRapporto = !empty($photo['StampaNelRapporto']) ? 'true' : 'false';
|
||||
$primaPagina = !empty($photo['PrimaPagina']) ? 'true' : 'false';
|
||||
$stampaNelRapporto = !empty($photo['StampaNelRapporto']);
|
||||
$primaPagina = !empty($photo['PrimaPagina']);
|
||||
|
||||
$logContentPhotos .= "curl --location --request POST '{$apiBaseUrl}{$photoEndpoint}' \\\n" .
|
||||
"--header 'Authorization: Bearer ••••••' \\\n" .
|
||||
"--form 'file=@{$fullPath}' \\\n" .
|
||||
"--form 'StampaNelRapporto={$stampaNelRapporto}' \\\n" .
|
||||
"--form 'PrimaPagina={$primaPagina}'\n\n";
|
||||
"--form 'file=@{$fullPath}'\n\n";
|
||||
|
||||
$extraFields = [
|
||||
'StampaNelRapporto' => $stampaNelRapporto,
|
||||
'PrimaPagina' => $primaPagina,
|
||||
];
|
||||
$photoResult = $api->postMultipart($photoEndpoint, $fullPath, $photo['file_name'], $extraFields);
|
||||
$logContentPhotos .= "RESPONSE:\n" . json_encode($photoResult, JSON_PRETTY_PRINT) . "\n\n---\n";
|
||||
// Step 1: Upload file (flags are ignored by API during upload)
|
||||
$photoResult = $api->postMultipart($photoEndpoint, $fullPath, $photo['file_name']);
|
||||
$logContentPhotos .= "UPLOAD RESPONSE:\n" . json_encode($photoResult, JSON_PRETTY_PRINT) . "\n\n";
|
||||
|
||||
// Step 2: PATCH CampioneFile to set flags (StampaNelRapporto, PrimaPagina)
|
||||
$campioneFileId = (int)($photoResult['IdCampioneFile'] ?? 0);
|
||||
if ($campioneFileId > 0 && ($stampaNelRapporto || $primaPagina)) {
|
||||
$patchPayload = [];
|
||||
|
||||
if ($stampaNelRapporto) {
|
||||
$patchPayload['StampaNelRapporto'] = true;
|
||||
}
|
||||
|
||||
if ($primaPagina) {
|
||||
$patchPayload['PrimaPagina'] = true;
|
||||
}
|
||||
|
||||
$patchEndpoint = "CampioneFile({$campioneFileId})";
|
||||
$patchJsonLog = json_encode($patchPayload, JSON_PRETTY_PRINT);
|
||||
$logContentPhotos .= "curl --location --request PATCH '{$apiBaseUrl}{$patchEndpoint}' \\\n" .
|
||||
"--header 'Content-Type: application/json' \\\n" .
|
||||
"--header 'Authorization: Bearer ••••••' \\\n" .
|
||||
"--data '{$patchJsonLog}'\n\n";
|
||||
|
||||
$patchResult = $api->patch($patchEndpoint, $patchPayload);
|
||||
$logContentPhotos .= "PATCH RESPONSE:\n" . json_encode($patchResult, JSON_PRETTY_PRINT) . "\n\n";
|
||||
}
|
||||
|
||||
$logContentPhotos .= "---\n";
|
||||
$photosUploaded++;
|
||||
}
|
||||
} else {
|
||||
@@ -315,7 +456,7 @@ try {
|
||||
|
||||
// Valida se il campo è di tipo Data
|
||||
if ($fieldType === 'Data' && $newValue !== $currentValue) {
|
||||
$newValue = validateDate($newValue);
|
||||
$newValue = formatDateToExport($newValue);
|
||||
}
|
||||
|
||||
$commessaCustomFields[] = [
|
||||
@@ -372,7 +513,13 @@ try {
|
||||
// 🔹 STEP 9.5: Importazione da CommessaWeb a Commessa (commentato come richiesto)
|
||||
// Supplier call: POST api/odata/CommessaWeb(XXX)/ImportaCommessa
|
||||
|
||||
$importPayload = ["IdUtente" => 285]; // user-id
|
||||
$importUserId = (!empty($lims_global_user_id) && is_numeric($lims_global_user_id))
|
||||
? (int) $lims_global_user_id
|
||||
: 285;
|
||||
|
||||
$importPayload = [
|
||||
"IdUtente" => $importUserId
|
||||
];
|
||||
$importResult = $api->post("CommessaWeb({$commessaId})/ImportaCommessa", $importPayload);
|
||||
|
||||
$importPayloadLog = json_encode($importPayload, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
|
||||
require_once dirname(__FILE__) . '/class/VisualLimsApiClient.class.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
ini_set('display_errors', '0');
|
||||
error_reporting(E_ALL);
|
||||
|
||||
try {
|
||||
$api = VisualLimsApiClient::getInstance();
|
||||
|
||||
// Endpoint per recuperare le Analisi
|
||||
$endpoint = 'Analisi';
|
||||
|
||||
// Opzioni OData
|
||||
$options = [
|
||||
// Restituisce solo i campi principali utili
|
||||
'$select' => 'IdAnalisi,Codice,NomeAnalisi,ClientiAbilitati,MatriciAbilitate,IsGenerico,Tipo,ParentKey,SelezionabileSuWeb',
|
||||
|
||||
// Solo analisi effettivamente selezionabili sul web
|
||||
'$filter' => 'SelezionabileSuWeb eq true',
|
||||
|
||||
// Ordinamento alfabetico per nome analisi
|
||||
'$orderby' => 'NomeAnalisi asc'
|
||||
];
|
||||
|
||||
// Debug: salva URL usato
|
||||
$base_url = 'https://93.43.5.102/limsapi/api/odata/';
|
||||
$query = http_build_query($options);
|
||||
$full_url = $base_url . $endpoint . ($query ? '?' . $query : '');
|
||||
file_put_contents(__DIR__ . '/last_analisi_url.txt', $full_url . PHP_EOL, FILE_APPEND);
|
||||
|
||||
// Chiamata API
|
||||
$data = $api->get($endpoint, $options);
|
||||
|
||||
// Salva il JSON in locale
|
||||
file_put_contents(__DIR__ . '/analisi_response.json', json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
|
||||
|
||||
echo json_encode($data, JSON_UNESCAPED_UNICODE);
|
||||
} catch (Exception $e) {
|
||||
file_put_contents(
|
||||
__DIR__ . '/analisi_error_log.txt',
|
||||
date('Y-m-d H:i:s') . ' - ' . $e->getMessage() . PHP_EOL,
|
||||
FILE_APPEND
|
||||
);
|
||||
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => $e->getMessage()], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
|
||||
require_once __DIR__ . '/class/VisualLimsApiClient.class.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// Disable PHP error display
|
||||
ini_set('display_errors', '0');
|
||||
error_reporting(E_ALL);
|
||||
|
||||
try {
|
||||
$api = VisualLimsApiClient::getInstance(); // also loads dotenv
|
||||
|
||||
// In simulate mode: return fake clients built from idclient values already in datadb.
|
||||
if (($_ENV['SIMULATE_EXPORT_LIMS'] ?? '') === 'true') {
|
||||
require_once __DIR__ . '/class/db-functions.php';
|
||||
$pdo = DBHandlerSelect::getInstance()->getConnection();
|
||||
|
||||
$stmt = $pdo->query("
|
||||
SELECT DISTINCT idclient
|
||||
FROM datadb
|
||||
WHERE idclient IS NOT NULL
|
||||
AND idclient > 0
|
||||
ORDER BY idclient ASC
|
||||
");
|
||||
|
||||
$ids = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||
|
||||
$fakeClients = array_map(fn($id) => [
|
||||
'IdCliente' => (int) $id,
|
||||
'Nominativo' => "Cliente Simulato {$id}",
|
||||
'CodiceCliente' => "SIM_{$id}",
|
||||
], $ids);
|
||||
|
||||
echo json_encode(['value' => $fakeClients], JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Endpoint senza filtri: recupera tutto
|
||||
$endpoint = 'Cliente?$top=50';
|
||||
|
||||
// Funzione per eseguire la chiamata con retry
|
||||
function makeApiRequest($api, $endpoint, $maxRetries = 3)
|
||||
{
|
||||
for ($retry = 0; $retry < $maxRetries; $retry++) {
|
||||
try {
|
||||
$data = $api->get($endpoint);
|
||||
|
||||
// Save response for debug
|
||||
file_put_contents(
|
||||
__DIR__ . '/clienti_response.json',
|
||||
json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
|
||||
);
|
||||
|
||||
return $data;
|
||||
} catch (Exception $e) {
|
||||
$errorMessage = $e->getMessage();
|
||||
|
||||
// Retry only for specific auth/token related issue
|
||||
if (
|
||||
strpos($errorMessage, 'HTTP 400') !== false &&
|
||||
strpos($errorMessage, 'Cannot persist the object') !== false
|
||||
) {
|
||||
try {
|
||||
if (method_exists($api, 'refreshToken')) {
|
||||
$api->refreshToken();
|
||||
error_log("Tentativo {$retry}: refresh token eseguito per endpoint {$endpoint}");
|
||||
} else {
|
||||
throw new Exception('Il metodo refreshToken() non esiste in VisualLimsApiClient');
|
||||
}
|
||||
} catch (Exception $refreshEx) {
|
||||
error_log("Errore durante il refresh del token: " . $refreshEx->getMessage());
|
||||
throw new Exception("Impossibile eseguire il refresh del token: " . $refreshEx->getMessage());
|
||||
}
|
||||
|
||||
usleep(500000); // 500ms
|
||||
continue;
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception("Massimo numero di tentativi raggiunto per {$endpoint}");
|
||||
}
|
||||
|
||||
// Esegui la chiamata
|
||||
$data = makeApiRequest($api, $endpoint);
|
||||
|
||||
echo json_encode($data, JSON_UNESCAPED_UNICODE);
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
|
||||
$errorResponse = [
|
||||
'error' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
];
|
||||
|
||||
error_log("Errore in get_clienti.php: " . json_encode($errorResponse, JSON_UNESCAPED_UNICODE));
|
||||
echo json_encode($errorResponse, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
+190
-176
@@ -167,6 +167,8 @@ $fixedFieldsRaw = $fixedStmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
// Ordine desiderato: Cliente Responsabile prima, poi gli altri, ConsegnaRichiesta prima delle 3 speciali
|
||||
$desiredOrder = [
|
||||
'ClienteResponsabile',
|
||||
'ClienteFornitore',
|
||||
'ClienteAnalisi',
|
||||
'AnagraficaCertestObject',
|
||||
'AnagraficaCertestService',
|
||||
'MoltiplicatorePrezzo',
|
||||
@@ -174,9 +176,13 @@ $desiredOrder = [
|
||||
// se ci sono altri campi fixed li mettiamo dopo
|
||||
];
|
||||
|
||||
// No exclusions: fixed fields will be rendered together at the end
|
||||
$excludeFromFixed = [];
|
||||
|
||||
$fixedFields = [];
|
||||
$tempMap = [];
|
||||
foreach ($fixedFieldsRaw as $f) {
|
||||
if (in_array($f['fixed_field_key'], $excludeFromFixed, true)) continue;
|
||||
$tempMap[$f['fixed_field_key']] = $f;
|
||||
}
|
||||
|
||||
@@ -195,10 +201,11 @@ foreach ($tempMap as $f) {
|
||||
// Maps logical fixed_field_key → real datadb column name (mirrors JS fixedAliasMap)
|
||||
$fixedAliasMap = [
|
||||
'ClienteResponsabile' => 'cliente_responsabile_id',
|
||||
'ClienteFornitore' => 'cliente_fornitore_id',
|
||||
'ClienteAnalisi' => 'clienteAnalisi',
|
||||
'MoltiplicatorePrezzo' => 'moltiplicatore_prezzo_id',
|
||||
'AnagraficaCertestObject' => 'anagrafica_certest_object_id',
|
||||
'AnagraficaCertestService' => 'anagrafica_certest_service_id',
|
||||
'ClienteFornitore' => 'cliente_fornitore_id',
|
||||
'ConsegnaRichiesta' => 'consegna_richiesta',
|
||||
];
|
||||
|
||||
@@ -360,8 +367,15 @@ function fixedDefaultValue(array $f): string
|
||||
}
|
||||
|
||||
@keyframes batch-pulse {
|
||||
0%, 100% { background-position: 0% 50%; }
|
||||
50% { background-position: 100% 50%; }
|
||||
|
||||
0%,
|
||||
100% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
|
||||
50% {
|
||||
background-position: 100% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.batch-row-spinner {
|
||||
@@ -946,14 +960,15 @@ function fixedDefaultValue(array $f): string
|
||||
|
||||
$topColIndex = $mainFieldMapping ? 2 : 1; ?>
|
||||
|
||||
<div class="grid-cell grid-top-cell" style="flex: 0 0 300px;" data-index="<?= $mainFieldMapping ? 2 : 1 ?>">
|
||||
<div class="grid-cell grid-top-cell" style="flex: 0 0 150px;" data-index="<?= $mainFieldMapping ? 2 : 1 ?>"></div>
|
||||
|
||||
<div class="grid-cell grid-top-cell" style="flex: 0 0 300px;" data-index="<?= $mainFieldMapping ? 3 : 2 ?>">
|
||||
<select class="custom-field dropdown-select client-select searchable-client" data-column="idclient" id="clientSelect" name="idclient">
|
||||
<option value="">Select a client...</option>
|
||||
</select>
|
||||
<button type="button" class="propagate-btn" data-column="idclient"><i class="fas fa-arrow-down"></i></button>
|
||||
<span id="clientLoadingStatus" class="text-muted" style="margin-left: 10px; display: none;">Recupero clienti in corso...</span>
|
||||
</div>
|
||||
<div class="grid-cell grid-top-cell" style="flex: 0 0 150px;" data-index="<?= $mainFieldMapping ? 3 : 2 ?>"></div>
|
||||
<?php
|
||||
|
||||
$topColIndex = $mainFieldMapping ? 4 : 3;
|
||||
@@ -1065,6 +1080,8 @@ function fixedDefaultValue(array $f): string
|
||||
$isApiField = in_array($key, [
|
||||
'MoltiplicatorePrezzo',
|
||||
'ClienteResponsabile',
|
||||
'ClienteFornitore',
|
||||
'ClienteAnalisi',
|
||||
'AnagraficaCertestObject',
|
||||
'AnagraficaCertestService'
|
||||
], true);
|
||||
@@ -1118,9 +1135,9 @@ function fixedDefaultValue(array $f): string
|
||||
<div class="resizer"></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="grid-header" data-index="<?= $mainFieldMapping ? 2 : 1 ?>" style="flex: 0 0 300px; position: relative;">Client<div class="resizer"></div>
|
||||
<div class="grid-header" data-index="<?= $mainFieldMapping ? 2 : 1 ?>" style="flex: 0 0 150px; position: relative;">Status<div class="resizer"></div>
|
||||
</div>
|
||||
<div class="grid-header" data-index="<?= $mainFieldMapping ? 3 : 2 ?>" style="flex: 0 0 150px; position: relative;">Status<div class="resizer"></div>
|
||||
<div class="grid-header" data-index="<?= $mainFieldMapping ? 3 : 2 ?>" style="flex: 0 0 300px; position: relative;">Client<div class="resizer"></div>
|
||||
</div>
|
||||
<?php
|
||||
$headerIndex = $mainFieldMapping ? 4 : 3;
|
||||
@@ -1151,6 +1168,16 @@ function fixedDefaultValue(array $f): string
|
||||
$key = $f['fixed_field_key'];
|
||||
$label = $slugMapping[$key] ?? $key;
|
||||
|
||||
if ($key === 'ClienteFornitore') {
|
||||
$label = 'Fornitore';
|
||||
}
|
||||
|
||||
if ($key === 'ClienteAnalisi') {
|
||||
$label = 'Buyer';
|
||||
}
|
||||
|
||||
|
||||
|
||||
echo "<div class='grid-header' data-index='$headerIndex' style='flex: 0 0 180px; position: relative;'>"
|
||||
. htmlspecialchars($label) .
|
||||
"<div class='resizer'></div></div>";
|
||||
@@ -1178,7 +1205,7 @@ function fixedDefaultValue(array $f): string
|
||||
<!-- commented only for admin roles -->
|
||||
<?php if ((Auth::user()->hasRole('Admin'))) : ?>
|
||||
<?php $isExported = (($row['status'] ?? '') === 'l'); ?>
|
||||
<button type="button" class="export-lims-btn action-btn" data-row="<?= $index ?>" data-iddatadb="<?= $row['iddatadb'] ?>" title="<?= $isExported ? 'Già esportato' : 'Export to LIMS' ?>" style="background: <?= $isExported ? '#ccc' : '#eb0b0b' ?>; color: white; border: none; border-radius: 5px; cursor: <?= $isExported ? 'not-allowed' : 'pointer' ?>; <?= $isExported ? 'opacity: 0.5;' : '' ?>"<?= $isExported ? ' disabled' : '' ?>><i class="fas fa-upload"></i></button>
|
||||
<button type="button" class="export-lims-btn action-btn" data-row="<?= $index ?>" data-iddatadb="<?= $row['iddatadb'] ?>" title="<?= $isExported ? 'Già esportato' : 'Export to LIMS' ?>" style="background: <?= $isExported ? '#ccc' : '#eb0b0b' ?>; color: white; border: none; border-radius: 5px; cursor: <?= $isExported ? 'not-allowed' : 'pointer' ?>; <?= $isExported ? 'opacity: 0.5;' : '' ?>" <?= $isExported ? ' disabled' : '' ?>><i class="fas fa-upload"></i></button>
|
||||
<?php endif; ?>
|
||||
|
||||
<button type="button" class="save-btn action-btn" data-row="<?= $index ?>" title="Save" style="background: #28a745; color: white; border: none; border-radius: 5px; cursor: pointer;"><i class="fas fa-save"></i></button>
|
||||
@@ -1211,20 +1238,21 @@ function fixedDefaultValue(array $f): string
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="grid-cell editable-cell" data-col="idclient" data-row="<?= $index ?>" data-index="<?= $mainFieldMapping ? 2 : 1 ?>" style="flex: 0 0 300px;">
|
||||
<select name="rows[<?= $index ?>][idclient]" class="cell-input dropdown-select client-select searchable-client" data-current-value="<?= htmlspecialchars($row['idclient'] ?? $default_idclient) ?>">
|
||||
<option value="">Select a client...</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="grid-cell editable-cell" data-col="status" data-row="<?= $index ?>" data-index="<?= $mainFieldMapping ? 3 : 2 ?>" style="flex: 0 0 150px;">
|
||||
<div class="grid-cell editable-cell" data-col="status" data-row="<?= $index ?>" data-index="<?= $mainFieldMapping ? 2 : 1 ?>" style="flex: 0 0 150px;">
|
||||
<span class="status-badge status-<?= htmlspecialchars($row['status'] ?? 'i') ?>">
|
||||
<?= htmlspecialchars($row['status'] === 'i' ? 'Imported' : ($row['status'] === 'P' ? 'In Progress' : 'To LIMS')) ?>
|
||||
</span>
|
||||
<?php if (!empty($row['commessaweb'])): ?>
|
||||
<span class="commessaweb-code" style="display:block; font-size:0.75em; color:#555; margin-top:2px;" title="CommessaWeb"><?= htmlspecialchars($row['commessaweb']) ?></span>
|
||||
<span class="commessaweb-code" style="display:block; font-size:0.75em; color:#555; margin-top:2px;" title="CommessaWeb"><?= htmlspecialchars($row['commessaweb']) ?></span>
|
||||
<?php endif; ?>
|
||||
<input type="hidden" name="rows[<?= $index ?>][status]" value="<?= htmlspecialchars($row['status'] ?? 'i') ?>">
|
||||
</div>
|
||||
<div class="grid-cell editable-cell" data-col="idclient" data-row="<?= $index ?>" data-index="<?= $mainFieldMapping ? 3 : 2 ?>" style="flex: 0 0 300px;">
|
||||
<select name="rows[<?= $index ?>][idclient]" class="cell-input dropdown-select client-select searchable-client" data-current-value="<?= htmlspecialchars($row['idclient'] ?? $default_idclient) ?>">
|
||||
<option value="">Select a client...</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
$cellIndex = $mainFieldMapping ? 4 : 3;
|
||||
$rowDetails = array_filter($manualDetails, fn($d) => $d['datadb_id'] == $row['iddatadb']);
|
||||
@@ -1351,7 +1379,7 @@ function fixedDefaultValue(array $f): string
|
||||
. (((int)$f['is_required'] === 1) ? "required" : "")
|
||||
. ">";
|
||||
} else {
|
||||
$isApiField = in_array($key, ['MoltiplicatorePrezzo', 'ClienteResponsabile', 'AnagraficaCertestObject', 'AnagraficaCertestService'], true);
|
||||
$isApiField = in_array($key, ['MoltiplicatorePrezzo', 'ClienteResponsabile', 'ClienteFornitore', 'ClienteAnalisi', 'AnagraficaCertestObject', 'AnagraficaCertestService'], true);
|
||||
$selectClass = $isApiField ? 'api-fixed-select' : '';
|
||||
echo "<select
|
||||
name='rows[$index][$key]'
|
||||
@@ -1418,6 +1446,60 @@ function fixedDefaultValue(array $f): string
|
||||
<script src="partsTable.js"></script>
|
||||
<script src="tracking.js"></script>
|
||||
<script src="export_to_lims.js"></script>
|
||||
<script>
|
||||
let globalClientData = [];
|
||||
let globalClientPromise = null;
|
||||
|
||||
function formatClientLabel(client) {
|
||||
const nome = client.Nominativo || "Nome non disponibile";
|
||||
const id = client.IdCliente || "";
|
||||
const codiceCliente = (client.CodiceCliente ?? client.codiceCliente ?? '').toString().trim();
|
||||
const suffix = (codiceCliente.split('_')[1] || '').trim();
|
||||
const shortCode = suffix || (codiceCliente ? codiceCliente.charAt(0) : '--');
|
||||
return `${nome.trim()} - ${shortCode} (ID: ${id})`;
|
||||
}
|
||||
|
||||
async function ensureClientsLoaded(retryCount = 0, maxRetries = 3) {
|
||||
if (globalClientData.length > 0) {
|
||||
return globalClientData;
|
||||
}
|
||||
|
||||
if (globalClientPromise) {
|
||||
return globalClientPromise;
|
||||
}
|
||||
|
||||
globalClientPromise = (async () => {
|
||||
const response = await fetch("get_clienti.php", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
if (
|
||||
response.status === 500 &&
|
||||
data.error &&
|
||||
data.error.includes('Cannot persist the object') &&
|
||||
retryCount < maxRetries
|
||||
) {
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
globalClientPromise = null;
|
||||
return ensureClientsLoaded(retryCount + 1, maxRetries);
|
||||
}
|
||||
|
||||
throw new Error(data.error || `Errore HTTP: ${response.status}`);
|
||||
}
|
||||
|
||||
globalClientData = data.value || [];
|
||||
return globalClientData;
|
||||
})();
|
||||
|
||||
return globalClientPromise;
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
function expandColumn(cell, expand) {
|
||||
const columnIndex = cell.getAttribute('data-index');
|
||||
@@ -1525,6 +1607,14 @@ function fixedDefaultValue(array $f): string
|
||||
const rowIndex = btn.dataset.row;
|
||||
const row = btn.closest('.grid-row');
|
||||
const iddatadb = row.getAttribute('data-id');
|
||||
|
||||
// Show spinner on save button
|
||||
const origHtml = btn.innerHTML;
|
||||
btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
|
||||
btn.disabled = true;
|
||||
row.style.opacity = '0.6';
|
||||
row.style.pointerEvents = 'none';
|
||||
|
||||
const formData = new FormData();
|
||||
|
||||
const inputs = row.querySelectorAll(`input[name^="rows[${rowIndex}][details]"], select[name^="rows[${rowIndex}][details]"]`);
|
||||
@@ -1555,6 +1645,8 @@ function fixedDefaultValue(array $f): string
|
||||
// Map: fixed key (logical) -> datadb real column
|
||||
const fixedAliasMap = {
|
||||
ClienteResponsabile: 'cliente_responsabile_id',
|
||||
ClienteFornitore: 'cliente_fornitore_id',
|
||||
ClienteAnalisi: 'clienteAnalisi',
|
||||
MoltiplicatorePrezzo: 'moltiplicatore_prezzo_id',
|
||||
AnagraficaCertestObject: 'anagrafica_certest_object_id',
|
||||
AnagraficaCertestService: 'anagrafica_certest_service_id',
|
||||
@@ -1608,6 +1700,12 @@ function fixedDefaultValue(array $f): string
|
||||
})
|
||||
.catch(error => {
|
||||
alert('Errore durante il salvataggio: ' + error.message);
|
||||
})
|
||||
.finally(() => {
|
||||
btn.innerHTML = origHtml;
|
||||
btn.disabled = false;
|
||||
row.style.opacity = '';
|
||||
row.style.pointerEvents = '';
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1616,7 +1714,9 @@ function fixedDefaultValue(array $f): string
|
||||
document.querySelector('.save-all-btn').addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
if (saveAllRunning || window.batchRunning) return;
|
||||
const confirmModal = new bootstrap.Modal(document.getElementById('saveAllConfirmModal'), { keyboard: false });
|
||||
const confirmModal = new bootstrap.Modal(document.getElementById('saveAllConfirmModal'), {
|
||||
keyboard: false
|
||||
});
|
||||
confirmModal.show();
|
||||
});
|
||||
|
||||
@@ -1634,7 +1734,11 @@ function fixedDefaultValue(array $f): string
|
||||
// Disable all row buttons
|
||||
document.querySelectorAll('.grid-row[data-id]').forEach(r => r.classList.add('batch-disabled'));
|
||||
const toggle = document.querySelector('.actions-dropdown .dropdown-toggle');
|
||||
if (toggle) { toggle.disabled = true; toggle.style.opacity = '0.5'; toggle.style.pointerEvents = 'none'; }
|
||||
if (toggle) {
|
||||
toggle.disabled = true;
|
||||
toggle.style.opacity = '0.5';
|
||||
toggle.style.pointerEvents = 'none';
|
||||
}
|
||||
|
||||
// Show status bar
|
||||
const bar = document.getElementById('batchExportBar');
|
||||
@@ -1651,10 +1755,14 @@ function fixedDefaultValue(array $f): string
|
||||
|
||||
for (const row of rows) {
|
||||
const saveBtn = row.querySelector('.save-btn');
|
||||
if (!saveBtn) { continue; }
|
||||
if (!saveBtn) {
|
||||
continue;
|
||||
}
|
||||
const rowIndex = saveBtn.dataset.row;
|
||||
const iddatadb = row.getAttribute('data-id');
|
||||
if (!rowIndex || !iddatadb) { continue; }
|
||||
if (!rowIndex || !iddatadb) {
|
||||
continue;
|
||||
}
|
||||
|
||||
processed++;
|
||||
statusEl.textContent = `Salvataggio ${processed} / ${total} (id: ${iddatadb})...`;
|
||||
@@ -1664,7 +1772,10 @@ function fixedDefaultValue(array $f): string
|
||||
row.classList.add('batch-exporting');
|
||||
const btnCell = row.querySelector('.button-cell');
|
||||
if (btnCell) {
|
||||
btnCell.querySelectorAll('.action-btn').forEach(b => { b.dataset.prevDisplay = b.style.display; b.style.display = 'none'; });
|
||||
btnCell.querySelectorAll('.action-btn').forEach(b => {
|
||||
b.dataset.prevDisplay = b.style.display;
|
||||
b.style.display = 'none';
|
||||
});
|
||||
const spinner = document.createElement('span');
|
||||
spinner.className = 'batch-row-spinner';
|
||||
spinner.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Saving...';
|
||||
@@ -1696,6 +1807,8 @@ function fixedDefaultValue(array $f): string
|
||||
const m = inp.name.match(/rows\[\d+\]\[([^\]]+)\]/);
|
||||
const fixedAliasMap = {
|
||||
ClienteResponsabile: 'cliente_responsabile_id',
|
||||
ClienteFornitore: 'cliente_fornitore_id',
|
||||
ClienteAnalisi: 'clienteAnalisi',
|
||||
MoltiplicatorePrezzo: 'moltiplicatore_prezzo_id',
|
||||
AnagraficaCertestObject: 'anagrafica_certest_object_id',
|
||||
AnagraficaCertestService: 'anagrafica_certest_service_id',
|
||||
@@ -1758,7 +1871,10 @@ function fixedDefaultValue(array $f): string
|
||||
if (btnCell) {
|
||||
const sp = btnCell.querySelector('.batch-row-spinner');
|
||||
if (sp) sp.remove();
|
||||
btnCell.querySelectorAll('.action-btn').forEach(b => { b.style.display = b.dataset.prevDisplay || ''; delete b.dataset.prevDisplay; });
|
||||
btnCell.querySelectorAll('.action-btn').forEach(b => {
|
||||
b.style.display = b.dataset.prevDisplay || '';
|
||||
delete b.dataset.prevDisplay;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1771,7 +1887,11 @@ function fixedDefaultValue(array $f): string
|
||||
|
||||
// Re-enable all row buttons
|
||||
document.querySelectorAll('.grid-row[data-id]').forEach(r => r.classList.remove('batch-disabled'));
|
||||
if (toggle) { toggle.disabled = false; toggle.style.opacity = ''; toggle.style.pointerEvents = ''; }
|
||||
if (toggle) {
|
||||
toggle.disabled = false;
|
||||
toggle.style.opacity = '';
|
||||
toggle.style.pointerEvents = '';
|
||||
}
|
||||
|
||||
const resultEl = document.getElementById('saveAllResultMessage');
|
||||
const resultLabel = document.getElementById('saveAllResultModalLabel');
|
||||
@@ -1782,7 +1902,9 @@ function fixedDefaultValue(array $f): string
|
||||
resultLabel.textContent = 'Salvataggio con Errori';
|
||||
resultEl.innerHTML = `<i class="fas fa-exclamation-triangle" style="color:#ffc107;"></i> Salvate <strong>${successCount}</strong> righe con successo.<br><br><strong>Errori:</strong><br>` + errorMessages.join('<br>');
|
||||
}
|
||||
new bootstrap.Modal(document.getElementById('saveAllResultModal'), { keyboard: false }).show();
|
||||
new bootstrap.Modal(document.getElementById('saveAllResultModal'), {
|
||||
keyboard: false
|
||||
}).show();
|
||||
});
|
||||
|
||||
window.addEventListener("beforeunload", function(e) {
|
||||
@@ -1814,50 +1936,31 @@ function fixedDefaultValue(array $f): string
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const inputs = document.querySelectorAll('.cell-input');
|
||||
let clientData = []; // Dichiarazione di clientData qui
|
||||
let clientData = globalClientData;
|
||||
|
||||
// Funzione per caricare i client
|
||||
async function loadClients(retryCount = 0, maxRetries = 3) {
|
||||
async function loadClients() {
|
||||
const clientLoadingStatus = document.getElementById("clientLoadingStatus");
|
||||
try {
|
||||
clientLoadingStatus.style.display = 'inline';
|
||||
clientLoadingStatus.textContent = 'Recupero clienti in corso...';
|
||||
const response = await fetch("get_clienti.php", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
});
|
||||
const data = await response.json();
|
||||
if (!response.ok) {
|
||||
if (response.status === 500 && data.error.includes('Cannot persist the object') && retryCount < maxRetries) {
|
||||
console.log(`Tentativo ${retryCount + 1}/${maxRetries}: Riprovo a caricare i clienti...`);
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
return loadClients(retryCount + 1, maxRetries);
|
||||
}
|
||||
throw new Error(data.error || `Errore HTTP: ${response.status}`);
|
||||
}
|
||||
|
||||
clientData = data.value || [];
|
||||
clientData = await ensureClientsLoaded();
|
||||
|
||||
const select = document.getElementById("clientSelect");
|
||||
select.innerHTML = '<option value="">Select a client...</option>';
|
||||
clientData.forEach(client => {
|
||||
const nome = client.Nominativo || "Nome non disponibile";
|
||||
const id = client.IdCliente || "ID non disponibile";
|
||||
const codiceCliente = (client.CodiceCliente || '').toString().trim();
|
||||
const suffix = (codiceCliente.split('_')[1] || '').trim();
|
||||
const shortCode = suffix || (codiceCliente ? codiceCliente.charAt(0) : '--');
|
||||
|
||||
const option = new Option(`${nome.trim()} - ${shortCode} (ID: ${id})`, id);
|
||||
if (parseInt(id) === parseInt(<?php echo json_encode($default_idclient ?? 0); ?>)) {
|
||||
clientData.forEach(client => {
|
||||
const option = new Option(formatClientLabel(client), client.IdCliente);
|
||||
if (parseInt(client.IdCliente) === parseInt(<?php echo json_encode($default_idclient ?? 0); ?>)) {
|
||||
option.selected = true;
|
||||
}
|
||||
select.add(option);
|
||||
});
|
||||
|
||||
populateClientDropdowns();
|
||||
|
||||
clientLoadingStatus.textContent = "Clienti caricati.";
|
||||
// ✅ force refresh of header dependent fixed fields
|
||||
$('#clientSelect').trigger('change');
|
||||
$('.grid-top .api-fixed-select[data-fixed-key="ClienteResponsabile"]').trigger('fixed:reload');
|
||||
|
||||
@@ -2245,121 +2348,6 @@ function fixedDefaultValue(array $f): string
|
||||
|
||||
populateDropdowns();
|
||||
});
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
let clientData = [];
|
||||
|
||||
async function loadClients(retryCount = 0, maxRetries = 3) {
|
||||
const clientLoadingStatus = document.getElementById("clientLoadingStatus");
|
||||
try {
|
||||
clientLoadingStatus.style.display = 'inline';
|
||||
clientLoadingStatus.textContent = 'Recupero clienti in corso...';
|
||||
const response = await fetch("get_clienti.php", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
});
|
||||
const data = await response.json();
|
||||
if (!response.ok) {
|
||||
if (response.status === 500 && data.error.includes('Cannot persist the object') && retryCount < maxRetries) {
|
||||
console.log(`Tentativo ${retryCount + 1}/${maxRetries}: Riprovo a caricare i clienti...`);
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
return loadClients(retryCount + 1, maxRetries);
|
||||
}
|
||||
throw new Error(data.error || `Errore HTTP: ${response.status}`);
|
||||
}
|
||||
|
||||
clientData = data.value || [];
|
||||
const select = document.getElementById("clientSelect");
|
||||
select.innerHTML = '<option value="">Select a client...</option>';
|
||||
clientData.forEach(client => {
|
||||
const nome = client.Nominativo || "Nome non disponibile";
|
||||
const id = client.IdCliente || "ID non disponibile";
|
||||
|
||||
// CodiceCliente es: "Bl01858_E" -> vogliamo "E"
|
||||
const codiceCliente = (client.CodiceCliente ?? client.codiceCliente ?? '').toString().trim();
|
||||
const suffix = (codiceCliente.split('_')[1] || '').trim(); // parte dopo "_"
|
||||
const shortCode = suffix || '--';
|
||||
|
||||
const option = new Option(`${nome.trim()} - ${shortCode} (ID: ${id})`, id);
|
||||
|
||||
if (parseInt(id) === parseInt(<?php echo json_encode($default_idclient ?? 0); ?>)) {
|
||||
option.selected = true;
|
||||
}
|
||||
select.add(option);
|
||||
});
|
||||
|
||||
populateClientDropdowns();
|
||||
clientLoadingStatus.textContent = "Clienti caricati.";
|
||||
} catch (error) {
|
||||
clientLoadingStatus.textContent = "Errore nel caricamento.";
|
||||
Swal.fire({
|
||||
title: "Errore!",
|
||||
text: "Impossibile caricare i clienti: " + error.message,
|
||||
icon: "error",
|
||||
confirmButtonText: "OK"
|
||||
});
|
||||
} finally {
|
||||
setTimeout(() => clientLoadingStatus.style.display = 'none', 2000);
|
||||
}
|
||||
}
|
||||
|
||||
function populateClientDropdowns() {
|
||||
const clientDropdowns = document.querySelectorAll('select[name^="rows"][name$="[idclient]"]');
|
||||
clientDropdowns.forEach(dropdown => {
|
||||
const currentValue = dropdown.getAttribute('data-current-value') || '';
|
||||
dropdown.innerHTML = '<option value="">Select a client...</option>';
|
||||
clientData.forEach(client => {
|
||||
const nome = client.Nominativo || "Nome non disponibile";
|
||||
const id = client.IdCliente || "ID non disponibile";
|
||||
|
||||
// CodiceCliente es: "Bl01858_E" -> vogliamo "E"
|
||||
const codiceCliente = (client.CodiceCliente || '').toString().trim();
|
||||
const suffix = (codiceCliente.split('_')[1] || '').trim(); // parte dopo "_"
|
||||
const shortCode = suffix || '--';
|
||||
|
||||
const option = new Option(`${nome.trim()} - ${shortCode} (ID: ${id})`, id);
|
||||
|
||||
if (String(id) === String(currentValue)) {
|
||||
option.selected = true;
|
||||
}
|
||||
dropdown.add(option);
|
||||
});
|
||||
|
||||
// Ripristina il valore corrente
|
||||
if (currentValue) {
|
||||
dropdown.value = currentValue;
|
||||
dropdown.setAttribute('data-restoring', '');
|
||||
const event = new Event('change', {
|
||||
bubbles: true
|
||||
});
|
||||
dropdown.dispatchEvent(event);
|
||||
dropdown.removeAttribute('data-restoring');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
loadClients();
|
||||
|
||||
document.getElementById('clientSelect').addEventListener('change', function() {
|
||||
const gridCell = this.closest('.grid-cell');
|
||||
const event = new Event('change', {
|
||||
bubbles: true
|
||||
});
|
||||
gridCell.dispatchEvent(event);
|
||||
});
|
||||
|
||||
document.addEventListener('change', function(e) {
|
||||
if (e.target.matches('select[name^="rows"][name$="[idclient]"]')) {
|
||||
const gridCell = e.target.closest('.grid-cell');
|
||||
const event = new Event('change', {
|
||||
bubbles: true
|
||||
});
|
||||
gridCell.dispatchEvent(event);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
@@ -2381,6 +2369,13 @@ function fixedDefaultValue(array $f): string
|
||||
});
|
||||
gridCell.dispatchEvent(event);
|
||||
}
|
||||
if (e.target.matches('select[name^="rows"][name$="[cliente_fornitore_id]"]')) {
|
||||
const gridCell = e.target.closest('.grid-cell');
|
||||
const event = new Event('change', {
|
||||
bubbles: true
|
||||
});
|
||||
gridCell.dispatchEvent(event);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -2397,11 +2392,12 @@ function fixedDefaultValue(array $f): string
|
||||
|
||||
// Ensure Select2 dropdowns trigger change events for unsaved changes tracking
|
||||
$('.searchable-client').on('select2:select select2:clear', function(e) {
|
||||
const gridCell = this.closest('.grid-cell');
|
||||
const event = new Event('change', {
|
||||
// Trigger native change on the real <select> element so
|
||||
// addEventListener('change') handlers can detect modifications.
|
||||
const nativeEvent = new Event('change', {
|
||||
bubbles: true
|
||||
});
|
||||
gridCell.dispatchEvent(event);
|
||||
this.dispatchEvent(nativeEvent);
|
||||
});
|
||||
|
||||
// Update propagate functionality for client dropdown
|
||||
@@ -2415,7 +2411,7 @@ function fixedDefaultValue(array $f): string
|
||||
const event = new Event('change', {
|
||||
bubbles: true
|
||||
});
|
||||
clientSelect.closest('.grid-cell').dispatchEvent(event);
|
||||
clientSelect.dispatchEvent(event);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -2438,10 +2434,7 @@ function fixedDefaultValue(array $f): string
|
||||
.map(s => s.trim())
|
||||
.filter(s => s.length > 0);
|
||||
|
||||
// (opzionale) dedup per evitare doppioni tipo "Cap | Cap"
|
||||
const uniqueParts = [...new Set(parts)];
|
||||
|
||||
if (!uniqueParts.length) {
|
||||
if (!parts.length) {
|
||||
alert('⚠️ Inserisci prima una descrizione nel campo Tested Component.');
|
||||
$input.focus();
|
||||
return;
|
||||
@@ -2452,7 +2445,7 @@ function fixedDefaultValue(array $f): string
|
||||
const errors = [];
|
||||
|
||||
// ✅ esegue una chiamata per ogni parte (compatibile con l’attuale add_part_quick.php)
|
||||
for (const p of uniqueParts) {
|
||||
for (const p of parts) {
|
||||
const formData = new FormData();
|
||||
formData.append('iddatadb', iddatadb);
|
||||
formData.append('part_description', p);
|
||||
@@ -2626,6 +2619,12 @@ function fixedDefaultValue(array $f): string
|
||||
getParams: (clientId) => ({
|
||||
id_cliente: clientId
|
||||
})
|
||||
},
|
||||
'ClienteFornitore': {
|
||||
source: 'clients'
|
||||
},
|
||||
'ClienteAnalisi': {
|
||||
source: 'clients'
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2649,6 +2648,21 @@ function fixedDefaultValue(array $f): string
|
||||
const config = apiFields[fieldKey];
|
||||
if (!config) return [];
|
||||
|
||||
if (config.source === 'clients') {
|
||||
const clients = await ensureClientsLoaded();
|
||||
const results = clients.map(client => ({
|
||||
id: client.IdCliente,
|
||||
text: formatClientLabel(client)
|
||||
}));
|
||||
|
||||
results.sort((a, b) => String(a.text || '').localeCompare(String(b.text || ''), 'it', {
|
||||
sensitivity: 'base'
|
||||
}));
|
||||
|
||||
fixedFieldDataCache[fieldKey] = results;
|
||||
return results;
|
||||
}
|
||||
|
||||
const cacheKey = fieldKey + (clientId ? '_' + clientId : '');
|
||||
if (fixedFieldDataCache[cacheKey]) {
|
||||
return fixedFieldDataCache[cacheKey];
|
||||
@@ -3073,4 +3087,4 @@ function fixedDefaultValue(array $f): string
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
@@ -374,16 +374,32 @@ error_log("Loaded template: " . print_r($template, true));
|
||||
}
|
||||
|
||||
selectAllCheckbox.addEventListener('change', function() {
|
||||
checkboxes.forEach(checkbox => {
|
||||
checkbox.checked = this.checked;
|
||||
const visibleRows = Array.from(document.querySelectorAll('.table tbody tr'))
|
||||
.filter(row => row.style.display !== 'none');
|
||||
|
||||
visibleRows.forEach(row => {
|
||||
const checkbox = row.querySelector('.row-checkbox');
|
||||
if (checkbox) {
|
||||
checkbox.checked = this.checked;
|
||||
}
|
||||
});
|
||||
|
||||
updateProceedButton();
|
||||
});
|
||||
|
||||
checkboxes.forEach(checkbox => {
|
||||
checkbox.addEventListener('change', function() {
|
||||
console.log('Checkbox changed, checked:', this.checked, 'excelrow:', this.dataset.excelrow);
|
||||
selectAllCheckbox.checked = Array.from(checkboxes).every(cb => cb.checked);
|
||||
|
||||
const visibleCheckboxes = Array.from(document.querySelectorAll('.table tbody tr'))
|
||||
.filter(row => row.style.display !== 'none')
|
||||
.map(row => row.querySelector('.row-checkbox'))
|
||||
.filter(cb => cb !== null);
|
||||
|
||||
selectAllCheckbox.checked =
|
||||
visibleCheckboxes.length > 0 &&
|
||||
visibleCheckboxes.every(cb => cb.checked);
|
||||
|
||||
updateProceedButton();
|
||||
});
|
||||
});
|
||||
@@ -431,12 +447,11 @@ error_log("Loaded template: " . print_r($template, true));
|
||||
|
||||
function applyColumnFilters() {
|
||||
rows.forEach(row => {
|
||||
// Le celle di data partono da index 1 (perché index 0 è checkbox)
|
||||
let visible = true;
|
||||
|
||||
for (const [colIndexStr, filterValue] of Object.entries(activeFilters)) {
|
||||
const colIndex = parseInt(colIndexStr, 10); // 0..N-1 sulle colonne dati
|
||||
const cell = row.cells[colIndex + 1]; // +1 per saltare la colonna checkbox
|
||||
const colIndex = parseInt(colIndexStr, 10);
|
||||
const cell = row.cells[colIndex + 1];
|
||||
|
||||
const cellText = (cell?.textContent || '').toLowerCase();
|
||||
const searchText = (filterValue || '').toLowerCase().trim();
|
||||
@@ -449,6 +464,17 @@ error_log("Loaded template: " . print_r($template, true));
|
||||
|
||||
row.style.display = visible ? '' : 'none';
|
||||
});
|
||||
|
||||
const visibleCheckboxes = Array.from(document.querySelectorAll('.table tbody tr'))
|
||||
.filter(row => row.style.display !== 'none')
|
||||
.map(row => row.querySelector('.row-checkbox'))
|
||||
.filter(cb => cb !== null);
|
||||
|
||||
selectAllCheckbox.checked =
|
||||
visibleCheckboxes.length > 0 &&
|
||||
visibleCheckboxes.every(cb => cb.checked);
|
||||
|
||||
updateProceedButton();
|
||||
}
|
||||
|
||||
filterInputs.forEach(input => {
|
||||
|
||||
@@ -26,6 +26,8 @@ $nameuser = $user->present()->first_name;
|
||||
$surnameuser = $user->present()->last_name;
|
||||
$emailuser = $user->present()->email;
|
||||
$avatar = $user->present()->avatar;
|
||||
$lims_user_id = $user->lims_user_id ?? '';
|
||||
$lims_global_user_id = $user->lims_global_user_id ?? '';
|
||||
|
||||
$kindofrole = $user->present()->role_id;
|
||||
|
||||
|
||||
@@ -236,7 +236,15 @@ $routines = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
if (!response.ok) throw new Error(data.error || `Errore HTTP: ${response.status}`);
|
||||
const select = document.getElementById("schemaSelect");
|
||||
select.innerHTML = '<option value="">Select a schema...</option>';
|
||||
data.value.forEach(schema => {
|
||||
const sortedSchemas = [...data.value].sort((a, b) => {
|
||||
const nomeA = (a.Nome || "").trim().toLowerCase();
|
||||
const nomeB = (b.Nome || "").trim().toLowerCase();
|
||||
return nomeA.localeCompare(nomeB, 'it', {
|
||||
sensitivity: 'base'
|
||||
});
|
||||
});
|
||||
|
||||
sortedSchemas.forEach(schema => {
|
||||
const nome = schema.Nome || "Nome non disponibile";
|
||||
const id = schema.IdSchemaCustomFields || "ID non disponibile";
|
||||
const option = new Option(`${nome.trim()} (ID: ${id})`, id);
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
CAMPIONE #0
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/Campione' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{
|
||||
"Commessa": 564663,
|
||||
"Matrice": 3028,
|
||||
"SottoMatrice": null,
|
||||
"SchemaCustomField": 82,
|
||||
"NoteWeb": "Parte 1",
|
||||
"ConsegnaRichiesta": "2026-03-31"
|
||||
}'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#Campione\/$entity",
|
||||
"IdCampione": 736244,
|
||||
"CodiceCampione": "11004",
|
||||
"CodiceCampioneWeb": "11004",
|
||||
"StatoCampione": "Nuovo",
|
||||
"DataCreazioneWeb": "2026-03-17T14:52:30.3143366+01:00",
|
||||
"RiferimentoWeb": "",
|
||||
"ConsegnaRichiesta": "2026-03-31T00:00:00+02:00",
|
||||
"DataAccettazioneLims": null,
|
||||
"Riferimento": null,
|
||||
"NoteWeb": "Parte 1",
|
||||
"GruppiRicercati": null
|
||||
}
|
||||
|
||||
---
|
||||
CAMPIONE #1
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/Campione' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{
|
||||
"Commessa": 564663,
|
||||
"Matrice": 3028,
|
||||
"SottoMatrice": null,
|
||||
"SchemaCustomField": 82,
|
||||
"NoteWeb": "Parte 2",
|
||||
"ConsegnaRichiesta": "2026-03-31"
|
||||
}'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#Campione\/$entity",
|
||||
"IdCampione": 736245,
|
||||
"CodiceCampione": "11005",
|
||||
"CodiceCampioneWeb": "11005",
|
||||
"StatoCampione": "Nuovo",
|
||||
"DataCreazioneWeb": "2026-03-17T14:52:31.9631757+01:00",
|
||||
"RiferimentoWeb": "",
|
||||
"ConsegnaRichiesta": "2026-03-31T00:00:00+02:00",
|
||||
"DataAccettazioneLims": null,
|
||||
"Riferimento": null,
|
||||
"NoteWeb": "Parte 2",
|
||||
"GruppiRicercati": null
|
||||
}
|
||||
|
||||
---
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/CommessaWeb(564663)/ImportaCommessa' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{
|
||||
"IdUtente": 285
|
||||
}'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#CommessaWeb\/$entity",
|
||||
"IdCommessa": 564663,
|
||||
"CodiceCommessa": "26C0059",
|
||||
"RiferimentoCertificato": null,
|
||||
"StatoCommessaWeb": "Elaborata",
|
||||
"DataCreazioneWeb": "2026-03-17T14:52:29.347+01:00",
|
||||
"CodiceCommessaWeb": "26C0059",
|
||||
"DataInviatoWeb": "2026-03-17T14:52:38.99+01:00",
|
||||
"Richiedente": "From TRFSmart Application",
|
||||
"Descrizione": "From TRFSmart Application"
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
Photos for CommessaWeb 564663 (iddatadb=1268):
|
||||
Total photos found: 2, campioni: 2
|
||||
|
||||
=== Campione 736244 (main) ===
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/Campione(736244)/UploadCampioneFile' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--form 'file=@C:\xampp\htdocs\trf_certest\public\photostrf\1268-20260317134828-1e672dd9-5420-4432-b422-02d8d271c178.jpg' \
|
||||
--form 'StampaNelRapporto=true' \
|
||||
--form 'PrimaPagina=true'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#CampioneFiles\/$entity",
|
||||
"IdCampioneFile": 1784768,
|
||||
"FileName": "1268-20260317134828-1e672dd9-5420-4432-b422-02d8d271c178.jpg",
|
||||
"Web": false,
|
||||
"AllegaAlRapporto": false,
|
||||
"StampaNelRapporto": false,
|
||||
"ReportGermania": false,
|
||||
"PrimaPagina": false,
|
||||
"Duplica": false,
|
||||
"LastUpdate": "2026-03-17T14:52:33.9816658+01:00",
|
||||
"Titolo": null
|
||||
}
|
||||
|
||||
---
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/Campione(736244)/UploadCampioneFile' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--form 'file=@C:\xampp\htdocs\trf_certest\public\photostrf\1268-20260317134828-104a2ca5-8a4c-4df8-b2ca-a28f518b7b25.jpg' \
|
||||
--form 'StampaNelRapporto=false' \
|
||||
--form 'PrimaPagina=false'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#CampioneFiles\/$entity",
|
||||
"IdCampioneFile": 1784769,
|
||||
"FileName": "1268-20260317134828-104a2ca5-8a4c-4df8-b2ca-a28f518b7b25.jpg",
|
||||
"Web": false,
|
||||
"AllegaAlRapporto": false,
|
||||
"StampaNelRapporto": false,
|
||||
"ReportGermania": false,
|
||||
"PrimaPagina": false,
|
||||
"Duplica": false,
|
||||
"LastUpdate": "2026-03-17T14:52:35.2759882+01:00",
|
||||
"Titolo": null
|
||||
}
|
||||
|
||||
---
|
||||
@@ -0,0 +1,18 @@
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/CommessaWeb(564663)/InviaCommessa' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{}'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#CommessaWeb\/$entity",
|
||||
"IdCommessa": 564663,
|
||||
"CodiceCommessa": "26C0059",
|
||||
"RiferimentoCertificato": null,
|
||||
"StatoCommessaWeb": "Nuova",
|
||||
"DataCreazioneWeb": "2026-03-17T14:52:29.347+01:00",
|
||||
"CodiceCommessaWeb": "26C0059",
|
||||
"DataInviatoWeb": "2026-03-17T14:52:38.9894528+01:00",
|
||||
"Richiedente": "From TRFSmart Application",
|
||||
"Descrizione": "From TRFSmart Application"
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
curl --location --request PATCH 'https://93.43.5.102/limsapi/api/odata/CommessaWeb(564663)' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{
|
||||
"CommesseCustomFields": [
|
||||
{
|
||||
"IdCommesseCustomFields": 23308665,
|
||||
"Valore": "2026-03-17T13:52:36+00:00"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308666,
|
||||
"Valore": "13:52"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308667,
|
||||
"Valore": "9299"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308668,
|
||||
"Valore": "2026-03-17T13:52:36+00:00"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308669,
|
||||
"Valore": "aaa"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308670,
|
||||
"Valore": "1"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308676,
|
||||
"Valore": "673"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308677,
|
||||
"Valore": "674"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308678,
|
||||
"Valore": "4410"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308680,
|
||||
"Valore": "1468"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308681,
|
||||
"Valore": "1604"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308682,
|
||||
"Valore": "12875"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308683,
|
||||
"Valore": "8755"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308684,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308644,
|
||||
"Valore": "13497"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308645,
|
||||
"Valore": "AAA"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308646,
|
||||
"Valore": "Example Description"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308685,
|
||||
"Valore": "1892"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308686,
|
||||
"Valore": "1111"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308687,
|
||||
"Valore": "2026-03-02T13:52:36+00:00"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308688,
|
||||
"Valore": "2026-03-17T13:52:36+00:00"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308689,
|
||||
"Valore": "2026-03-17T13:52:36+00:00"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308690,
|
||||
"Valore": "1978"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308691,
|
||||
"Valore": "13:52"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308692,
|
||||
"Valore": "14:44"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308693,
|
||||
"Valore": "14:00"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308694,
|
||||
"Valore": "2026-03-17T13:52:36+00:00"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308695,
|
||||
"Valore": "8596"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308696,
|
||||
"Valore": "8600"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308697,
|
||||
"Valore": "8605"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308647,
|
||||
"Valore": "L209A4M00130M7280"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308648,
|
||||
"Valore": "1"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308649,
|
||||
"Valore": "1"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308650,
|
||||
"Valore": "264"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308651,
|
||||
"Valore": "1589"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308652,
|
||||
"Valore": "AAA"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308653,
|
||||
"Valore": "3055"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308654,
|
||||
"Valore": "aaa"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308655,
|
||||
"Valore": "qqq"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308656,
|
||||
"Valore": "1"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308657,
|
||||
"Valore": "1"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308658,
|
||||
"Valore": "qqq"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308659,
|
||||
"Valore": "236"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308660,
|
||||
"Valore": "1208"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308661,
|
||||
"Valore": "ciao"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308662,
|
||||
"Valore": "bbb"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308663,
|
||||
"Valore": "12234"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308664,
|
||||
"Valore": "MONCLER"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308671,
|
||||
"Valore": "L209A4M00130M7280 - PACEY2"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308672,
|
||||
"Valore": "4678"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308673,
|
||||
"Valore": "1"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308674,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308675,
|
||||
"Valore": "2450"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23308679,
|
||||
"Valore": "744"
|
||||
}
|
||||
]
|
||||
}'
|
||||
|
||||
RESPONSE:
|
||||
null
|
||||
@@ -0,0 +1,120 @@
|
||||
CAMPIONE #0
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/Campione' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{
|
||||
"Commessa": 564817,
|
||||
"Matrice": 3028,
|
||||
"SottoMatrice": null,
|
||||
"SchemaCustomField": 82,
|
||||
"NoteWeb": "AAA",
|
||||
"ConsegnaRichiesta": "2026-01-29"
|
||||
}'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#Campione\/$entity",
|
||||
"IdCampione": 736487,
|
||||
"CodiceCampione": "11016",
|
||||
"CodiceCampioneWeb": "11016",
|
||||
"StatoCampione": "Nuovo",
|
||||
"DataCreazioneWeb": "2026-03-18T10:54:03.4537462+01:00",
|
||||
"RiferimentoWeb": "",
|
||||
"ConsegnaRichiesta": "2026-01-29T00:00:00+01:00",
|
||||
"DataAccettazioneLims": null,
|
||||
"Riferimento": null,
|
||||
"NoteWeb": "AAA",
|
||||
"GruppiRicercati": null
|
||||
}
|
||||
|
||||
---
|
||||
CAMPIONE #1
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/Campione' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{
|
||||
"Commessa": 564817,
|
||||
"Matrice": 3028,
|
||||
"SottoMatrice": null,
|
||||
"SchemaCustomField": 82,
|
||||
"NoteWeb": "CCC",
|
||||
"ConsegnaRichiesta": "2026-01-29"
|
||||
}'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#Campione\/$entity",
|
||||
"IdCampione": 736488,
|
||||
"CodiceCampione": "11017",
|
||||
"CodiceCampioneWeb": "11017",
|
||||
"StatoCampione": "Nuovo",
|
||||
"DataCreazioneWeb": "2026-03-18T10:54:04.8623753+01:00",
|
||||
"RiferimentoWeb": "",
|
||||
"ConsegnaRichiesta": "2026-01-29T00:00:00+01:00",
|
||||
"DataAccettazioneLims": null,
|
||||
"Riferimento": null,
|
||||
"NoteWeb": "CCC",
|
||||
"GruppiRicercati": null
|
||||
}
|
||||
|
||||
---
|
||||
CAMPIONE #2
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/Campione' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{
|
||||
"Commessa": 564817,
|
||||
"Matrice": 3028,
|
||||
"SottoMatrice": null,
|
||||
"SchemaCustomField": 82,
|
||||
"NoteWeb": "DDD",
|
||||
"ConsegnaRichiesta": "2026-01-29"
|
||||
}'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#Campione\/$entity",
|
||||
"IdCampione": 736489,
|
||||
"CodiceCampione": "11018",
|
||||
"CodiceCampioneWeb": "11018",
|
||||
"StatoCampione": "Nuovo",
|
||||
"DataCreazioneWeb": "2026-03-18T10:54:06.2840533+01:00",
|
||||
"RiferimentoWeb": "",
|
||||
"ConsegnaRichiesta": "2026-01-29T00:00:00+01:00",
|
||||
"DataAccettazioneLims": null,
|
||||
"Riferimento": null,
|
||||
"NoteWeb": "DDD",
|
||||
"GruppiRicercati": null
|
||||
}
|
||||
|
||||
---
|
||||
CAMPIONE #3
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/Campione' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{
|
||||
"Commessa": 564817,
|
||||
"Matrice": 3028,
|
||||
"SottoMatrice": null,
|
||||
"SchemaCustomField": 82,
|
||||
"NoteWeb": "EEE",
|
||||
"ConsegnaRichiesta": "2026-01-29"
|
||||
}'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#Campione\/$entity",
|
||||
"IdCampione": 736490,
|
||||
"CodiceCampione": "11019",
|
||||
"CodiceCampioneWeb": "11019",
|
||||
"StatoCampione": "Nuovo",
|
||||
"DataCreazioneWeb": "2026-03-18T10:54:07.8853452+01:00",
|
||||
"RiferimentoWeb": "",
|
||||
"ConsegnaRichiesta": "2026-01-29T00:00:00+01:00",
|
||||
"DataAccettazioneLims": null,
|
||||
"Riferimento": null,
|
||||
"NoteWeb": "EEE",
|
||||
"GruppiRicercati": null
|
||||
}
|
||||
|
||||
---
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/CommessaWeb(564817)/ImportaCommessa' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{
|
||||
"IdUtente": 285
|
||||
}'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#CommessaWeb\/$entity",
|
||||
"IdCommessa": 564817,
|
||||
"CodiceCommessa": "26C0071",
|
||||
"RiferimentoCertificato": null,
|
||||
"StatoCommessaWeb": "Elaborata",
|
||||
"DataCreazioneWeb": "2026-03-18T10:54:02.187+01:00",
|
||||
"CodiceCommessaWeb": "26C0071",
|
||||
"DataInviatoWeb": "2026-03-18T10:54:14.727+01:00",
|
||||
"Richiedente": "From TRFSmart Application",
|
||||
"Descrizione": "From TRFSmart Application"
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
Photos for CommessaWeb 564817 (iddatadb=1270):
|
||||
Total photos found: 2, campioni: 4
|
||||
|
||||
=== Campione 736487 (main) ===
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/Campione(736487)/UploadCampioneFile' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--form 'file=@C:\xampp\htdocs\trf_certest\public\photostrf\1270-20260318095305-1e672dd9-5420-4432-b422-02d8d271c178.jpg' \
|
||||
--form 'StampaNelRapporto=true' \
|
||||
--form 'PrimaPagina=true'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#CampioneFiles\/$entity",
|
||||
"IdCampioneFile": 1785492,
|
||||
"FileName": "1270-20260318095305-1e672dd9-5420-4432-b422-02d8d271c178.jpg",
|
||||
"Web": false,
|
||||
"AllegaAlRapporto": false,
|
||||
"StampaNelRapporto": false,
|
||||
"ReportGermania": false,
|
||||
"PrimaPagina": false,
|
||||
"Duplica": false,
|
||||
"LastUpdate": "2026-03-18T10:54:09.5438326+01:00",
|
||||
"Titolo": null
|
||||
}
|
||||
|
||||
---
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/Campione(736487)/UploadCampioneFile' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--form 'file=@C:\xampp\htdocs\trf_certest\public\photostrf\1270-20260318095305-104a2ca5-8a4c-4df8-b2ca-a28f518b7b25.jpg' \
|
||||
--form 'StampaNelRapporto=false' \
|
||||
--form 'PrimaPagina=false'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#CampioneFiles\/$entity",
|
||||
"IdCampioneFile": 1785493,
|
||||
"FileName": "1270-20260318095305-104a2ca5-8a4c-4df8-b2ca-a28f518b7b25.jpg",
|
||||
"Web": false,
|
||||
"AllegaAlRapporto": false,
|
||||
"StampaNelRapporto": false,
|
||||
"ReportGermania": false,
|
||||
"PrimaPagina": false,
|
||||
"Duplica": false,
|
||||
"LastUpdate": "2026-03-18T10:54:10.8237002+01:00",
|
||||
"Titolo": null
|
||||
}
|
||||
|
||||
---
|
||||
@@ -0,0 +1,18 @@
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/CommessaWeb(564817)/InviaCommessa' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{}'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#CommessaWeb\/$entity",
|
||||
"IdCommessa": 564817,
|
||||
"CodiceCommessa": "26C0071",
|
||||
"RiferimentoCertificato": null,
|
||||
"StatoCommessaWeb": "Nuova",
|
||||
"DataCreazioneWeb": "2026-03-18T10:54:02.187+01:00",
|
||||
"CodiceCommessaWeb": "26C0071",
|
||||
"DataInviatoWeb": "2026-03-18T10:54:14.7252132+01:00",
|
||||
"Richiedente": "From TRFSmart Application",
|
||||
"Descrizione": "From TRFSmart Application"
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
curl --location --request PATCH 'https://93.43.5.102/limsapi/api/odata/CommessaWeb(564817)' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{
|
||||
"CommesseCustomFields": [
|
||||
{
|
||||
"IdCommesseCustomFields": 23315543,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315544,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315545,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315546,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315547,
|
||||
"Valore": "/"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315548,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315554,
|
||||
"Valore": "673"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315555,
|
||||
"Valore": "674"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315556,
|
||||
"Valore": "669"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315558,
|
||||
"Valore": "1469"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315559,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315560,
|
||||
"Valore": "12875"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315561,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315562,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315522,
|
||||
"Valore": "13497"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315523,
|
||||
"Valore": "20262"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315524,
|
||||
"Valore": "ART. PEACH"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315563,
|
||||
"Valore": "1892"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315564,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315565,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315566,
|
||||
"Valore": "2026-03-18T09:54:11+00:00"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315567,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315568,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315569,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315570,
|
||||
"Valore": "09:53"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315571,
|
||||
"Valore": "10:37"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315572,
|
||||
"Valore": "2026-03-18T09:54:11+00:00"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315573,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315574,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315575,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315525,
|
||||
"Valore": "L209A4M00130M7280"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315526,
|
||||
"Valore": "BLACK"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315527,
|
||||
"Valore": "PE007J"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315528,
|
||||
"Valore": "264"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315529,
|
||||
"Valore": "420"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315530,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315531,
|
||||
"Valore": "15357"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315532,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315533,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315534,
|
||||
"Valore": "P"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315535,
|
||||
"Valore": "RM-ACC"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315536,
|
||||
"Valore": " CONCERIA M2 SRL"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315537,
|
||||
"Valore": "344"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315538,
|
||||
"Valore": "520"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315539,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315540,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315541,
|
||||
"Valore": "Not provided"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315542,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315549,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315550,
|
||||
"Valore": "4678"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315551,
|
||||
"Valore": "Leather&amp;Fur"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315552,
|
||||
"Valore": "278"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315553,
|
||||
"Valore": "2089"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23315557,
|
||||
"Valore": "745"
|
||||
}
|
||||
]
|
||||
}'
|
||||
|
||||
RESPONSE:
|
||||
null
|
||||
@@ -0,0 +1,90 @@
|
||||
CAMPIONE #0
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/Campione' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{
|
||||
"Commessa": 565085,
|
||||
"Matrice": 7714,
|
||||
"SottoMatrice": null,
|
||||
"SchemaCustomField": 82,
|
||||
"NoteWeb": "Parte AAA",
|
||||
"ConsegnaRichiesta": "2026-04-08"
|
||||
}'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#Campione\/$entity",
|
||||
"IdCampione": 736899,
|
||||
"CodiceCampione": "11038",
|
||||
"CodiceCampioneWeb": "11038",
|
||||
"StatoCampione": "Nuovo",
|
||||
"DataCreazioneWeb": "2026-03-19T10:03:19.8547279+01:00",
|
||||
"RiferimentoWeb": "",
|
||||
"ConsegnaRichiesta": "2026-04-08T00:00:00+02:00",
|
||||
"DataAccettazioneLims": null,
|
||||
"Riferimento": null,
|
||||
"NoteWeb": "Parte AAA",
|
||||
"GruppiRicercati": null
|
||||
}
|
||||
|
||||
---
|
||||
CAMPIONE #1
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/Campione' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{
|
||||
"Commessa": 565085,
|
||||
"Matrice": 7714,
|
||||
"SottoMatrice": null,
|
||||
"SchemaCustomField": 82,
|
||||
"NoteWeb": "Parte BBB",
|
||||
"ConsegnaRichiesta": "2026-04-08"
|
||||
}'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#Campione\/$entity",
|
||||
"IdCampione": 736900,
|
||||
"CodiceCampione": "11039",
|
||||
"CodiceCampioneWeb": "11039",
|
||||
"StatoCampione": "Nuovo",
|
||||
"DataCreazioneWeb": "2026-03-19T10:03:22.0431135+01:00",
|
||||
"RiferimentoWeb": "",
|
||||
"ConsegnaRichiesta": "2026-04-08T00:00:00+02:00",
|
||||
"DataAccettazioneLims": null,
|
||||
"Riferimento": null,
|
||||
"NoteWeb": "Parte BBB",
|
||||
"GruppiRicercati": null
|
||||
}
|
||||
|
||||
---
|
||||
CAMPIONE #2
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/Campione' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{
|
||||
"Commessa": 565085,
|
||||
"Matrice": 7714,
|
||||
"SottoMatrice": null,
|
||||
"SchemaCustomField": 82,
|
||||
"NoteWeb": "Parte CCC",
|
||||
"ConsegnaRichiesta": "2026-04-08"
|
||||
}'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#Campione\/$entity",
|
||||
"IdCampione": 736901,
|
||||
"CodiceCampione": "11040",
|
||||
"CodiceCampioneWeb": "11040",
|
||||
"StatoCampione": "Nuovo",
|
||||
"DataCreazioneWeb": "2026-03-19T10:03:23.6170597+01:00",
|
||||
"RiferimentoWeb": "",
|
||||
"ConsegnaRichiesta": "2026-04-08T00:00:00+02:00",
|
||||
"DataAccettazioneLims": null,
|
||||
"Riferimento": null,
|
||||
"NoteWeb": "Parte CCC",
|
||||
"GruppiRicercati": null
|
||||
}
|
||||
|
||||
---
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/CommessaWeb(565085)/ImportaCommessa' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{
|
||||
"IdUtente": 285
|
||||
}'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#CommessaWeb\/$entity",
|
||||
"IdCommessa": 565085,
|
||||
"CodiceCommessa": "26C0089",
|
||||
"RiferimentoCertificato": null,
|
||||
"StatoCommessaWeb": "Elaborata",
|
||||
"DataCreazioneWeb": "2026-03-19T10:03:18.653+01:00",
|
||||
"CodiceCommessaWeb": "26C0089",
|
||||
"DataInviatoWeb": "2026-03-19T10:03:30.603+01:00",
|
||||
"Richiedente": "From TRFSmart Application",
|
||||
"Descrizione": "From TRFSmart Application"
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
Photos for CommessaWeb 565085 (iddatadb=1279):
|
||||
Total photos found: 2, campioni: 3
|
||||
|
||||
=== Campione 736899 (main) ===
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/Campione(736899)/UploadCampioneFile' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--form 'file=@C:\xampp\htdocs\trf_certest\public\photostrf\1279-20260319090037-1e672dd9-5420-4432-b422-02d8d271c178.jpg' \
|
||||
--form 'StampaNelRapporto=true' \
|
||||
--form 'PrimaPagina=true'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#CampioneFiles\/$entity",
|
||||
"IdCampioneFile": 1786602,
|
||||
"FileName": "1279-20260319090037-1e672dd9-5420-4432-b422-02d8d271c178.jpg",
|
||||
"Web": false,
|
||||
"AllegaAlRapporto": false,
|
||||
"StampaNelRapporto": false,
|
||||
"ReportGermania": false,
|
||||
"PrimaPagina": false,
|
||||
"Duplica": false,
|
||||
"LastUpdate": "2026-03-19T10:03:25.2757049+01:00",
|
||||
"Titolo": null
|
||||
}
|
||||
|
||||
---
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/Campione(736899)/UploadCampioneFile' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--form 'file=@C:\xampp\htdocs\trf_certest\public\photostrf\1279-20260319090037-104a2ca5-8a4c-4df8-b2ca-a28f518b7b25.jpg' \
|
||||
--form 'StampaNelRapporto=false' \
|
||||
--form 'PrimaPagina=false'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#CampioneFiles\/$entity",
|
||||
"IdCampioneFile": 1786603,
|
||||
"FileName": "1279-20260319090037-104a2ca5-8a4c-4df8-b2ca-a28f518b7b25.jpg",
|
||||
"Web": false,
|
||||
"AllegaAlRapporto": false,
|
||||
"StampaNelRapporto": false,
|
||||
"ReportGermania": false,
|
||||
"PrimaPagina": false,
|
||||
"Duplica": false,
|
||||
"LastUpdate": "2026-03-19T10:03:26.7566613+01:00",
|
||||
"Titolo": null
|
||||
}
|
||||
|
||||
---
|
||||
@@ -0,0 +1,18 @@
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/CommessaWeb(565085)/InviaCommessa' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{}'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#CommessaWeb\/$entity",
|
||||
"IdCommessa": 565085,
|
||||
"CodiceCommessa": "26C0089",
|
||||
"RiferimentoCertificato": null,
|
||||
"StatoCommessaWeb": "Nuova",
|
||||
"DataCreazioneWeb": "2026-03-19T10:03:18.653+01:00",
|
||||
"CodiceCommessaWeb": "26C0089",
|
||||
"DataInviatoWeb": "2026-03-19T10:03:30.6022436+01:00",
|
||||
"Richiedente": "From TRFSmart Application",
|
||||
"Descrizione": "From TRFSmart Application"
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
curl --location --request PATCH 'https://93.43.5.102/limsapi/api/odata/CommessaWeb(565085)' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{
|
||||
"CommesseCustomFields": [
|
||||
{
|
||||
"IdCommesseCustomFields": 23328248,
|
||||
"Valore": "18/03/2026"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328249,
|
||||
"Valore": "09:00"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328250,
|
||||
"Valore": "9299"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328251,
|
||||
"Valore": "17/03/2026"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328252,
|
||||
"Valore": "/"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328253,
|
||||
"Valore": "5"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328259,
|
||||
"Valore": "673"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328260,
|
||||
"Valore": "674"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328261,
|
||||
"Valore": "669"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328263,
|
||||
"Valore": "1469"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328264,
|
||||
"Valore": "1604"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328265,
|
||||
"Valore": "12875"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328266,
|
||||
"Valore": "8755"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328267,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328227,
|
||||
"Valore": "13497"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328228,
|
||||
"Valore": "20262"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328229,
|
||||
"Valore": "ART. PEACH"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328268,
|
||||
"Valore": "1892"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328269,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328270,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328271,
|
||||
"Valore": "19/03/2026"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328272,
|
||||
"Valore": "18/03/2026"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328273,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328274,
|
||||
"Valore": "09:00"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328275,
|
||||
"Valore": "09:03"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328276,
|
||||
"Valore": "09:58"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328277,
|
||||
"Valore": "19/03/2026"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328278,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328279,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328280,
|
||||
"Valore": ""
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328230,
|
||||
"Valore": "L209B4M00110M7280"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328231,
|
||||
"Valore": "BLACK"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328232,
|
||||
"Valore": "PE007J"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328233,
|
||||
"Valore": "264"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328234,
|
||||
"Valore": "420"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328235,
|
||||
"Valore": "AAA"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328236,
|
||||
"Valore": "3055"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328237,
|
||||
"Valore": "AAA"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328238,
|
||||
"Valore": "AAA"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328239,
|
||||
"Valore": "P"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328240,
|
||||
"Valore": "RM-ACC"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328241,
|
||||
"Valore": "\u00a0CONCERIA M2 SRL"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328242,
|
||||
"Valore": "344"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328243,
|
||||
"Valore": "1208"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328244,
|
||||
"Valore": "AAA"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328245,
|
||||
"Valore": "AAA"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328246,
|
||||
"Valore": "Not provided"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328247,
|
||||
"Valore": "AAA"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328254,
|
||||
"Valore": "aaa"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328255,
|
||||
"Valore": "4678"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328256,
|
||||
"Valore": "Leather&amp;Fur"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328257,
|
||||
"Valore": "278"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328258,
|
||||
"Valore": "2089"
|
||||
},
|
||||
{
|
||||
"IdCommesseCustomFields": 23328262,
|
||||
"Valore": "745"
|
||||
}
|
||||
]
|
||||
}'
|
||||
|
||||
RESPONSE:
|
||||
null
|
||||
@@ -0,0 +1,28 @@
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/CommessaWeb' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{
|
||||
"Cliente": 3378,
|
||||
"SchemaCustomField": 82,
|
||||
"Richiedente": "From TRFSmart Application",
|
||||
"Descrizione": "From TRFSmart Application",
|
||||
"ClienteResponsabile": 7598,
|
||||
"MoltiplicatorePrezzo": 2,
|
||||
"AnagraficaCertestObject": 8964,
|
||||
"AnagraficaCertestService": 9012,
|
||||
"ClienteFornitore": 11208
|
||||
}'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#CommessaWeb\/$entity",
|
||||
"IdCommessa": 564662,
|
||||
"CodiceCommessa": "26C0058",
|
||||
"RiferimentoCertificato": null,
|
||||
"StatoCommessaWeb": "Nuova",
|
||||
"DataCreazioneWeb": "2026-03-17T14:49:39.4933462+01:00",
|
||||
"CodiceCommessaWeb": "26C0058",
|
||||
"DataInviatoWeb": null,
|
||||
"Richiedente": "From TRFSmart Application",
|
||||
"Descrizione": "From TRFSmart Application"
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/CommessaWeb' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{
|
||||
"Cliente": 3378,
|
||||
"SchemaCustomField": 82,
|
||||
"Richiedente": "From TRFSmart Application",
|
||||
"Descrizione": "From TRFSmart Application",
|
||||
"ClienteResponsabile": 7598,
|
||||
"MoltiplicatorePrezzo": 2,
|
||||
"AnagraficaCertestObject": 8964,
|
||||
"AnagraficaCertestService": 9012,
|
||||
"ClienteFornitore": 11208
|
||||
}'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#CommessaWeb\/$entity",
|
||||
"IdCommessa": 564663,
|
||||
"CodiceCommessa": "26C0059",
|
||||
"RiferimentoCertificato": null,
|
||||
"StatoCommessaWeb": "Nuova",
|
||||
"DataCreazioneWeb": "2026-03-17T14:52:29.3463415+01:00",
|
||||
"CodiceCommessaWeb": "26C0059",
|
||||
"DataInviatoWeb": null,
|
||||
"Richiedente": "From TRFSmart Application",
|
||||
"Descrizione": "From TRFSmart Application"
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/CommessaWeb' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{
|
||||
"Cliente": 3378,
|
||||
"SchemaCustomField": 82,
|
||||
"Richiedente": "From TRFSmart Application",
|
||||
"Descrizione": "From TRFSmart Application",
|
||||
"ClienteResponsabile": 7586,
|
||||
"MoltiplicatorePrezzo": null,
|
||||
"AnagraficaCertestObject": 8973,
|
||||
"AnagraficaCertestService": 9007,
|
||||
"ClienteFornitore": 11208
|
||||
}'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#CommessaWeb\/$entity",
|
||||
"IdCommessa": 564817,
|
||||
"CodiceCommessa": "26C0071",
|
||||
"RiferimentoCertificato": null,
|
||||
"StatoCommessaWeb": "Nuova",
|
||||
"DataCreazioneWeb": "2026-03-18T10:54:02.1867227+01:00",
|
||||
"CodiceCommessaWeb": "26C0071",
|
||||
"DataInviatoWeb": null,
|
||||
"Richiedente": "From TRFSmart Application",
|
||||
"Descrizione": "From TRFSmart Application"
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
curl --location --request POST 'https://93.43.5.102/limsapi/api/odata/CommessaWeb' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ••••••' \
|
||||
--data '{
|
||||
"Cliente": 3378,
|
||||
"SchemaCustomField": 82,
|
||||
"Richiedente": "From TRFSmart Application",
|
||||
"Descrizione": "From TRFSmart Application",
|
||||
"ClienteResponsabile": 7586,
|
||||
"MoltiplicatorePrezzo": 2,
|
||||
"AnagraficaCertestObject": 8973,
|
||||
"AnagraficaCertestService": 9007,
|
||||
"ClienteFornitore": 4505,
|
||||
"ClienteAnalisi": null
|
||||
}'
|
||||
|
||||
RESPONSE:
|
||||
{
|
||||
"@odata.context": "https:\/\/bvcpsitaly-elims.com\/limsapi\/api\/odata\/$metadata#CommessaWeb\/$entity",
|
||||
"IdCommessa": 565085,
|
||||
"CodiceCommessa": "26C0089",
|
||||
"RiferimentoCertificato": null,
|
||||
"StatoCommessaWeb": "Nuova",
|
||||
"DataCreazioneWeb": "2026-03-19T10:03:18.6527414+01:00",
|
||||
"CodiceCommessaWeb": "26C0089",
|
||||
"DataInviatoWeb": null,
|
||||
"Richiedente": "From TRFSmart Application",
|
||||
"Descrizione": "From TRFSmart Application"
|
||||
}
|
||||
@@ -163,6 +163,12 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.xls-columns option.used-option {
|
||||
background-color: #fff3cd;
|
||||
color: #856404;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Make Title column narrower + ellipsis */
|
||||
#schemaFieldsTable td.title-col {
|
||||
max-width: 320px;
|
||||
@@ -414,6 +420,8 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
||||
|
||||
<?php elseif (in_array($fm['fixed_field_key'], [
|
||||
'ClienteResponsabile',
|
||||
'ClienteFornitore',
|
||||
'ClienteAnalisi',
|
||||
'MoltiplicatorePrezzo',
|
||||
'AnagraficaCertestObject',
|
||||
'AnagraficaCertestService'
|
||||
@@ -552,21 +560,25 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
||||
|
||||
function updateXlsDropdowns() {
|
||||
let usedColumns = Array.from(document.querySelectorAll('select.xls-columns'))
|
||||
.filter(select => select.style.display === 'block' && select.value)
|
||||
.map(select => select.value)
|
||||
.map(select => select.value || select.dataset.currentXls || '')
|
||||
.filter(Boolean)
|
||||
.concat(usedColumnsFromDB);
|
||||
|
||||
let uniqueUsedColumns = [...new Set(usedColumns)];
|
||||
|
||||
document.querySelectorAll('select.xls-columns').forEach(select => {
|
||||
let currentValue = select.value || select.dataset.currentXls || '';
|
||||
|
||||
let options = availableXlsColumns
|
||||
.filter(col => !usedColumns.includes(col) || col === currentValue)
|
||||
.map(col => `<option value="${col}" ${col === currentValue ? 'selected' : ''}>${col}</option>`)
|
||||
.map(col => {
|
||||
const isUsed = uniqueUsedColumns.includes(col) && col !== currentValue;
|
||||
const label = isUsed ? `⚠ ${col} (already used)` : col;
|
||||
return `<option value="${col}" class="${isUsed ? 'used-option' : ''}" ${col === currentValue ? 'selected' : ''}>${label}</option>`;
|
||||
})
|
||||
.join('');
|
||||
|
||||
select.innerHTML = '<option value="">Select XLS Column</option>' + options;
|
||||
select.dataset.currentXls = currentValue;
|
||||
if (currentValue && !options.includes(currentValue)) {
|
||||
select.value = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1013,33 +1025,6 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
||||
checkbox.checked = !prevChecked;
|
||||
location.reload();
|
||||
});
|
||||
} else if (event.target.classList.contains('visible-parts-checkbox')) {
|
||||
const checkbox = event.target;
|
||||
const mappingId = checkbox.dataset.mappingId;
|
||||
const value = checkbox.checked ? 1 : 0;
|
||||
|
||||
fetch('update_visible_parts.php', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
template_id: <?php echo $id; ?>,
|
||||
mapping_id: mappingId,
|
||||
value: value
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (!data.success) {
|
||||
console.error("❌ Error updating is_visible_parts:", data.message);
|
||||
checkbox.checked = !checkbox.checked;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("❌ Fetch error:", error);
|
||||
checkbox.checked = !checkbox.checked;
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
@@ -1079,7 +1064,7 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
||||
mappedColumn = document.createElement('span');
|
||||
mappedColumn.className = 'mapped-column';
|
||||
mappedColumn.style.marginLeft = '5px';
|
||||
tr.querySelector('td:nth-child(5)').appendChild(mappedColumn);
|
||||
tr.querySelector('td:nth-child(6)').appendChild(mappedColumn);
|
||||
}
|
||||
if (!removeBtn) {
|
||||
removeBtn = document.createElement('button');
|
||||
@@ -1087,7 +1072,7 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
||||
removeBtn.textContent = 'X';
|
||||
removeBtn.style.marginLeft = '5px';
|
||||
removeBtn.setAttribute('data-id', mappingId);
|
||||
tr.querySelector('td:nth-child(5)').appendChild(removeBtn);
|
||||
tr.querySelector('td:nth-child(6)').appendChild(removeBtn);
|
||||
|
||||
removeBtn.addEventListener('click', function(e) {
|
||||
let tr = e.target.closest('tr');
|
||||
@@ -1230,6 +1215,8 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
||||
|
||||
const keysWithDropdown = [
|
||||
'ClienteResponsabile',
|
||||
'ClienteFornitore',
|
||||
'ClienteAnalisi',
|
||||
'MoltiplicatorePrezzo',
|
||||
'AnagraficaCertestObject',
|
||||
'AnagraficaCertestService'
|
||||
@@ -1443,15 +1430,25 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
||||
|
||||
const clientId = <?php echo (int)($template['idclient'] ?? 0); ?>;
|
||||
|
||||
const requestCache = {};
|
||||
|
||||
async function fetchJson(url) {
|
||||
const r = await fetch(url);
|
||||
const text = await r.text();
|
||||
if (!r.ok) throw new Error(`HTTP ${r.status} on ${url}: ${text.slice(0, 200)}`);
|
||||
try {
|
||||
return JSON.parse(text);
|
||||
} catch (e) {
|
||||
throw new Error(`Invalid JSON from ${url}: ${text.slice(0, 200)}`);
|
||||
if (requestCache[url]) {
|
||||
return requestCache[url];
|
||||
}
|
||||
|
||||
requestCache[url] = (async () => {
|
||||
const r = await fetch(url);
|
||||
const text = await r.text();
|
||||
if (!r.ok) throw new Error(`HTTP ${r.status} on ${url}: ${text.slice(0, 200)}`);
|
||||
try {
|
||||
return JSON.parse(text);
|
||||
} catch (e) {
|
||||
throw new Error(`Invalid JSON from ${url}: ${text.slice(0, 200)}`);
|
||||
}
|
||||
})();
|
||||
|
||||
return requestCache[url];
|
||||
}
|
||||
|
||||
function normalizeList(j, key) {
|
||||
@@ -1465,6 +1462,16 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
||||
return [];
|
||||
}
|
||||
|
||||
function formatClientLabel(x) {
|
||||
const nome = x.Nominativo ?? x.Nome ?? x.name ?? 'Nome non disponibile';
|
||||
const id = x.IdCliente ?? x.Id ?? x.id ?? '';
|
||||
const codiceCliente = (x.CodiceCliente ?? x.codiceCliente ?? '').toString().trim();
|
||||
const suffix = (codiceCliente.split('_')[1] || '').trim();
|
||||
const shortCode = suffix || (codiceCliente ? codiceCliente.charAt(0) : '--');
|
||||
|
||||
return `${nome.trim()} - ${shortCode} (ID: ${id})`;
|
||||
}
|
||||
|
||||
async function loadData(key) {
|
||||
if (key === 'MoltiplicatorePrezzo') {
|
||||
const j = await fetchJson('get_moltiplicatoreprezzo.php');
|
||||
@@ -1507,6 +1514,16 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
||||
})).filter(x => x.id != null && x.label);
|
||||
}
|
||||
|
||||
if (key === 'ClienteFornitore' || key === 'ClienteAnalisi') {
|
||||
const j = await fetchJson('get_clienti.php');
|
||||
const list = normalizeList(j, key);
|
||||
|
||||
return list.map(x => ({
|
||||
id: x.IdCliente ?? x.Id ?? x.id,
|
||||
label: formatClientLabel(x)
|
||||
})).filter(x => x.id != null && x.label);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
@@ -307,4 +307,23 @@
|
||||
width: 250px !important;
|
||||
min-width: 250px !important;
|
||||
}
|
||||
|
||||
#partsTableBody .extra-field-td .select2-container {
|
||||
width: 100% !important;
|
||||
min-width: 180px !important;
|
||||
}
|
||||
|
||||
#partsTableBody .extra-field-td .select2-selection--single {
|
||||
height: 31px !important;
|
||||
padding: 0.15rem 0.35rem !important;
|
||||
border: 1px solid #ced4da !important;
|
||||
}
|
||||
|
||||
#partsTableBody .extra-field-td .select2-selection__rendered {
|
||||
line-height: 28px !important;
|
||||
}
|
||||
|
||||
#partsTableBody .extra-field-td .select2-selection__arrow {
|
||||
height: 29px !important;
|
||||
}
|
||||
</style>
|
||||
@@ -81,10 +81,19 @@ $(document).ready(function () {
|
||||
data: { field_ids: fieldId },
|
||||
success: function (res) {
|
||||
const arr = res && res[fieldId] ? res[fieldId] : [];
|
||||
extraFieldOptions = (arr || []).map((x) => ({
|
||||
id: x.IdCustomFieldsValue,
|
||||
label: x.Valore,
|
||||
}));
|
||||
|
||||
extraFieldOptions = (arr || [])
|
||||
.map((x) => ({
|
||||
id: x.IdCustomFieldsValue,
|
||||
label: x.Valore || "",
|
||||
}))
|
||||
.sort((a, b) =>
|
||||
a.label.localeCompare(b.label, "it", {
|
||||
sensitivity: "base",
|
||||
numeric: true,
|
||||
}),
|
||||
);
|
||||
|
||||
done();
|
||||
},
|
||||
error: function () {
|
||||
@@ -127,6 +136,50 @@ $(document).ready(function () {
|
||||
</td>`;
|
||||
}
|
||||
|
||||
function initializeExtraFieldSelect2($context) {
|
||||
if (typeof $.fn.select2 === "undefined") return;
|
||||
|
||||
$context.find(".part-extra-select").each(function () {
|
||||
const $select = $(this);
|
||||
|
||||
if ($select.hasClass("select2-hidden-accessible")) {
|
||||
$select.select2("destroy");
|
||||
}
|
||||
|
||||
$select.select2({
|
||||
placeholder: "Seleziona...",
|
||||
allowClear: true,
|
||||
width: "100%",
|
||||
dropdownParent: $("#partsModal"),
|
||||
minimumResultsForSearch: 0,
|
||||
sorter: function (data) {
|
||||
return data.sort(function (a, b) {
|
||||
const textA = (a.text || "").toLowerCase();
|
||||
const textB = (b.text || "").toLowerCase();
|
||||
return textA.localeCompare(textB, "it", {
|
||||
sensitivity: "base",
|
||||
numeric: true,
|
||||
});
|
||||
});
|
||||
},
|
||||
matcher: function (params, data) {
|
||||
if ($.trim(params.term) === "") return data;
|
||||
if (typeof data.text === "undefined") return null;
|
||||
|
||||
const term = params.term.toLowerCase();
|
||||
const text = data.text.toLowerCase();
|
||||
|
||||
return text.indexOf(term) > -1 ? data : null;
|
||||
},
|
||||
});
|
||||
|
||||
const selected = ($select.attr("data-selected") || "").toString();
|
||||
if (selected) {
|
||||
$select.val(selected).trigger("change.select2");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$(document).on("change", ".part-extra-select", function () {
|
||||
const valId = $(this).val() || "";
|
||||
const $row = $(this).closest("tr");
|
||||
@@ -164,13 +217,14 @@ $(document).ready(function () {
|
||||
const $row = $(this);
|
||||
$row.find("td:last").before(buildExtraFieldCellHtml($row));
|
||||
|
||||
// ripristina selezione se già presente nello stato riga
|
||||
const selected = ($row.data("extra-value-id") || "").toString();
|
||||
if (selected) {
|
||||
$row.find(".part-extra-value-id").val(selected);
|
||||
$row.find(".part-extra-select").val(selected);
|
||||
$row.find(".part-extra-select").attr("data-selected", selected);
|
||||
}
|
||||
});
|
||||
|
||||
initializeExtraFieldSelect2($("#partsTableBody"));
|
||||
}
|
||||
|
||||
function setPartId($row, id) {
|
||||
@@ -902,9 +956,13 @@ $(document).ready(function () {
|
||||
</td>
|
||||
</tr>`;
|
||||
$("#partsTableBody").append(newRow);
|
||||
const $select = $("#partsTableBody tr:last .part-matrice");
|
||||
const $newRow = $("#partsTableBody tr:last");
|
||||
const $select = $newRow.find(".part-matrice");
|
||||
const selectedMacro = $("#macro-matrice-filter").val() || "";
|
||||
|
||||
initializeSelect2($select, nextPartNumber, "", null, selectedMacro);
|
||||
initializeExtraFieldSelect2($newRow);
|
||||
|
||||
updateRowButtons();
|
||||
markUnsaved();
|
||||
}
|
||||
@@ -1407,8 +1465,14 @@ $(document).ready(function () {
|
||||
const vid = String(part.extra_value_id);
|
||||
$row.data("extra-value-id", vid);
|
||||
$row.find(".part-extra-value-id").val(vid);
|
||||
$row.find(".part-extra-select").val(vid);
|
||||
$row.find(".part-extra-select").attr(
|
||||
"data-selected",
|
||||
vid,
|
||||
);
|
||||
}
|
||||
|
||||
initializeExtraFieldSelect2($row);
|
||||
|
||||
const $select = $("#partsTableBody").find(
|
||||
`tr[data-part-id="${part.id}"] .part-matrice`,
|
||||
);
|
||||
|
||||
@@ -475,6 +475,11 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (canvas) {
|
||||
canvas.dispose();
|
||||
}
|
||||
|
||||
canvas = new fabric.Canvas("collageCanvas", {
|
||||
backgroundColor: "#fff",
|
||||
selection: true,
|
||||
@@ -583,6 +588,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
if (isCropping || isRemovingBackground) {
|
||||
return;
|
||||
}
|
||||
|
||||
const state = JSON.stringify(
|
||||
canvas.toJSON([
|
||||
"cornerColor",
|
||||
@@ -590,12 +596,16 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
"cornerSize",
|
||||
"borderColor",
|
||||
"transparentCorners",
|
||||
"backgroundImage",
|
||||
]),
|
||||
);
|
||||
|
||||
history.push(state);
|
||||
|
||||
if (history.length > maxHistory) {
|
||||
history.shift();
|
||||
}
|
||||
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
@@ -603,10 +613,11 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
if (history.length <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
history.pop();
|
||||
const previousState = history[history.length - 1];
|
||||
|
||||
if (previousState) {
|
||||
canvas.clear();
|
||||
canvas.loadFromJSON(previousState, () => {
|
||||
canvas.renderAll();
|
||||
updateLayersPanel();
|
||||
@@ -615,8 +626,11 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
} else {
|
||||
console.warn("Nessuno stato precedente disponibile");
|
||||
canvas.clear();
|
||||
canvas.setBackgroundColor("#fff");
|
||||
canvas.renderAll();
|
||||
canvas.backgroundImage = null;
|
||||
canvas.setBackgroundColor(
|
||||
"#fff",
|
||||
canvas.renderAll.bind(canvas),
|
||||
);
|
||||
updateLayersPanel();
|
||||
updateButtons();
|
||||
}
|
||||
@@ -909,6 +923,61 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
canvas.renderAll();
|
||||
}
|
||||
|
||||
function setCanvasBackground(imgPath) {
|
||||
console.log("setCanvasBackground chiamata con:", imgPath);
|
||||
|
||||
if (!canvas) {
|
||||
console.error("Canvas non inizializzato");
|
||||
return;
|
||||
}
|
||||
|
||||
fabric.Image.fromURL(
|
||||
imgPath,
|
||||
(img) => {
|
||||
const canvasWidth = canvas.getWidth();
|
||||
const canvasHeight = canvas.getHeight();
|
||||
|
||||
const imgWidth = img.width;
|
||||
const imgHeight = img.height;
|
||||
|
||||
if (!imgWidth || !imgHeight) {
|
||||
alert(
|
||||
"Impossibile leggere le dimensioni dell'immagine.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Scale to cover: l'immagine copre tutto il canvas mantenendo il ratio
|
||||
const scale = Math.max(
|
||||
canvasWidth / imgWidth,
|
||||
canvasHeight / imgHeight,
|
||||
);
|
||||
|
||||
img.set({
|
||||
originX: "left",
|
||||
originY: "top",
|
||||
scaleX: scale,
|
||||
scaleY: scale,
|
||||
left: (canvasWidth - imgWidth * scale) / 2,
|
||||
top: (canvasHeight - imgHeight * scale) / 2,
|
||||
selectable: false,
|
||||
evented: false,
|
||||
hasControls: false,
|
||||
hasBorders: false,
|
||||
excludeFromExport: false,
|
||||
});
|
||||
|
||||
canvas.setBackgroundImage(img, () => {
|
||||
canvas.requestRenderAll();
|
||||
saveCanvasState();
|
||||
updateLayersPanel();
|
||||
updateButtons();
|
||||
});
|
||||
},
|
||||
{ crossOrigin: "anonymous" },
|
||||
);
|
||||
}
|
||||
|
||||
const addToCanvasBtn = document.getElementById("addToCanvasBtn");
|
||||
if (addToCanvasBtn) {
|
||||
addToCanvasBtn.addEventListener("click", () => {
|
||||
@@ -948,6 +1017,32 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
});
|
||||
}
|
||||
|
||||
const setBackgroundBtn = document.getElementById("setBackgroundBtn");
|
||||
if (setBackgroundBtn) {
|
||||
setBackgroundBtn.addEventListener("click", () => {
|
||||
const checkboxes = document.querySelectorAll(
|
||||
".photo-checkbox:checked",
|
||||
);
|
||||
|
||||
if (checkboxes.length === 0) {
|
||||
alert("Seleziona una foto da usare come sfondo!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkboxes.length > 1) {
|
||||
alert("Seleziona una sola foto per lo sfondo!");
|
||||
return;
|
||||
}
|
||||
|
||||
const imgPath = checkboxes[0].getAttribute("data-path");
|
||||
setCanvasBackground(imgPath);
|
||||
|
||||
checkboxes.forEach((cb) => {
|
||||
cb.checked = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const saveCollageBtn = document.getElementById("saveCollageBtn");
|
||||
if (saveCollageBtn) {
|
||||
saveCollageBtn.addEventListener("click", async () => {
|
||||
|
||||
@@ -298,8 +298,11 @@ $result->saveToFile($qrCodeFile);
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<!-- Bottone per aggiungere selezionate al canvas -->
|
||||
<button id="addToCanvasBtn">Aggiungi Selezionate al Canvas</button>
|
||||
<!-- Bottoni azioni collage -->
|
||||
<div style="display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 10px;">
|
||||
<button id="addToCanvasBtn">Aggiungi Selezionate al Canvas</button>
|
||||
<button id="setBackgroundBtn" type="button">Imposta Selezionata come Sfondo</button>
|
||||
</div>
|
||||
|
||||
<!-- Canvas per editing -->
|
||||
<canvas id="collageCanvas" width="960" height="720" style="border: 1px solid #ccc; margin-top: 20px;"></canvas>
|
||||
|
||||
@@ -5,102 +5,211 @@ ini_set('error_log', __DIR__ . '/routine_debug.log');
|
||||
function applyRoutine(&$excelData, $routineData)
|
||||
{
|
||||
try {
|
||||
// Log iniziale
|
||||
// Initial log
|
||||
error_log("Inizio esecuzione routine Moncler: " . date('Y-m-d H:i:s'));
|
||||
error_log("Dati routine: " . print_r($routineData, true));
|
||||
error_log("Dati excel_data: " . print_r($excelData, true));
|
||||
|
||||
// Verifica se excelData è vuoto
|
||||
// Check if excelData is empty
|
||||
if (empty($excelData)) {
|
||||
throw new Exception("excelData è vuoto o non valido.");
|
||||
}
|
||||
|
||||
// Estrai informazioni dalla routine con valori predefiniti
|
||||
// Extract routine settings with default values
|
||||
$action1 = trim($routineData['action1'] ?? 'K');
|
||||
$action2 = trim($routineData['action2'] ?? 'STYLE CODE + STYLE DESCRIPTION');
|
||||
$action3 = trim($routineData['action3'] ?? 'STYLE CODE');
|
||||
$action4 = trim($routineData['action4'] ?? 'STYLE DESCRIPTION');
|
||||
$headers = $routineData['xls_headers'] ?? [];
|
||||
|
||||
// Package-related headers
|
||||
$package_header = 'PACKAGE';
|
||||
$other_test_header = 'Other test from Control Matrix';
|
||||
$only_colorfastness_header = 'Only Colorfastness package';
|
||||
$only_chemical_header = 'Only Chemical package';
|
||||
|
||||
if (empty($headers)) {
|
||||
throw new Exception("Nessun header trovato per la routine Moncler.");
|
||||
}
|
||||
|
||||
// If headers arrive as JSON string, decode them
|
||||
if (!is_array($headers) && is_string($headers)) {
|
||||
$decoded_headers = json_decode($headers, true);
|
||||
if (json_last_error() === JSON_ERROR_NONE && is_array($decoded_headers)) {
|
||||
$headers = $decoded_headers;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_array($headers) || empty($headers)) {
|
||||
throw new Exception("Gli header della routine non sono validi.");
|
||||
}
|
||||
|
||||
error_log("Header ricevuti: " . print_r($headers, true));
|
||||
|
||||
// Normalizza gli header (solo trim)
|
||||
$normalized_headers = array_map('trim', $headers);
|
||||
// Normalize headers
|
||||
$normalized_headers = array_map(function ($header) {
|
||||
return trim((string)$header);
|
||||
}, $headers);
|
||||
|
||||
error_log("Header normalizzati: " . print_r($normalized_headers, true));
|
||||
error_log("Action values - action1: '$action1', action2: '$action2', action3: '$action3', action4: '$action4'");
|
||||
|
||||
// Trova gli indici delle colonne
|
||||
$action1_index = array_search($action1, $normalized_headers);
|
||||
$action2_index = array_search($action2, $normalized_headers);
|
||||
$action3_index = array_search($action3, $normalized_headers);
|
||||
$action4_index = array_search($action4, $normalized_headers);
|
||||
// Find package-related column indexes
|
||||
$package_index = array_search($package_header, $normalized_headers, true);
|
||||
$other_test_index = array_search($other_test_header, $normalized_headers, true);
|
||||
$only_colorfastness_index = array_search($only_colorfastness_header, $normalized_headers, true);
|
||||
$only_chemical_index = array_search($only_chemical_header, $normalized_headers, true);
|
||||
|
||||
if ($package_index === false) {
|
||||
throw new Exception("Colonna PACKAGE non trovata.");
|
||||
}
|
||||
|
||||
error_log(
|
||||
"Indici package - PACKAGE: " . var_export($package_index, true) .
|
||||
", Other test from Control Matrix: " . var_export($other_test_index, true) .
|
||||
", Only Colorfastness package: " . var_export($only_colorfastness_index, true) .
|
||||
", Only Chemical package: " . var_export($only_chemical_index, true)
|
||||
);
|
||||
|
||||
/**
|
||||
* PART 1
|
||||
* Aggregate rows by action1 and split action2 into action3 + action4
|
||||
* If it fails, continue with PART 2 only
|
||||
*/
|
||||
$part1_applied = false;
|
||||
|
||||
$action1_index = array_search($action1, $normalized_headers, true);
|
||||
$action2_index = array_search($action2, $normalized_headers, true);
|
||||
$action3_index = array_search($action3, $normalized_headers, true);
|
||||
$action4_index = array_search($action4, $normalized_headers, true);
|
||||
|
||||
if ($action1_index === false || $action2_index === false || $action3_index === false || $action4_index === false) {
|
||||
throw new Exception("Colonne non trovate - action1: '$action1' (index: " . var_export($action1_index, true) . "), action2: '$action2' (index: " . var_export($action2_index, true) . "), action3: '$action3' (index: " . var_export($action3_index, true) . "), action4: '$action4' (index: " . var_export($action4_index, true) . ")");
|
||||
error_log(
|
||||
"Unable to apply routine part 1. Package merge logic has been applied only. " .
|
||||
"Missing columns - action1: '$action1' (index: " . var_export($action1_index, true) . ")" .
|
||||
", action2: '$action2' (index: " . var_export($action2_index, true) . ")" .
|
||||
", action3: '$action3' (index: " . var_export($action3_index, true) . ")" .
|
||||
", action4: '$action4' (index: " . var_export($action4_index, true) . ")"
|
||||
);
|
||||
} else {
|
||||
error_log("Indici colonne part 1 - action1: $action1_index, action2: $action2_index, action3: $action3_index, action4: $action4_index");
|
||||
|
||||
$grouped_data = [];
|
||||
|
||||
foreach ($excelData as $row) {
|
||||
if (!isset($row['data']) || !is_array($row['data'])) {
|
||||
error_log("Riga non valida, manca 'data' per excelrow " . ($row['excelrow'] ?? 'N/A'));
|
||||
continue;
|
||||
}
|
||||
|
||||
$key = $row['data'][$action1_index] ?? '';
|
||||
$key = trim((string)$key);
|
||||
$key = $key === '' ? '_empty_' : $key;
|
||||
|
||||
if (!isset($grouped_data[$key])) {
|
||||
$grouped_data[$key] = [
|
||||
'data' => $row['data'],
|
||||
'excelrow' => [($row['excelrow'] ?? '')],
|
||||
'style_codes' => [],
|
||||
'style_descriptions' => []
|
||||
];
|
||||
} else {
|
||||
$grouped_data[$key]['excelrow'][] = ($row['excelrow'] ?? '');
|
||||
}
|
||||
|
||||
// Split STYLE CODE + STYLE DESCRIPTION
|
||||
$action2_value = trim((string)($row['data'][$action2_index] ?? ''));
|
||||
|
||||
if ($action2_value !== '') {
|
||||
$parts = explode(' - ', $action2_value, 2);
|
||||
$style_code = trim((string)($parts[0] ?? ''));
|
||||
$style_description = trim((string)($parts[1] ?? ''));
|
||||
|
||||
if ($style_code !== '') {
|
||||
$grouped_data[$key]['style_codes'][] = $style_code;
|
||||
}
|
||||
if ($style_description !== '') {
|
||||
$grouped_data[$key]['style_descriptions'][] = $style_description;
|
||||
}
|
||||
} else {
|
||||
error_log("Valore vuoto in action2 per excelrow " . ($row['excelrow'] ?? 'N/A'));
|
||||
}
|
||||
}
|
||||
|
||||
$new_excel_data = [];
|
||||
|
||||
foreach ($grouped_data as $key => $group) {
|
||||
$row_data = $group['data'];
|
||||
|
||||
// Update STYLE CODE and STYLE DESCRIPTION with aggregated unique values
|
||||
$row_data[$action3_index] = implode(' - ', array_unique($group['style_codes']));
|
||||
$row_data[$action4_index] = implode(' - ', array_unique($group['style_descriptions']));
|
||||
|
||||
// Concatenate excelrow values with "+"
|
||||
$excelrow_clean = array_filter($group['excelrow'], function ($value) {
|
||||
return $value !== null && $value !== '';
|
||||
});
|
||||
|
||||
$excelrow_value = count($excelrow_clean) > 1
|
||||
? implode('+', $excelrow_clean)
|
||||
: (reset($excelrow_clean) ?: '');
|
||||
|
||||
$new_excel_data[] = [
|
||||
'data' => $row_data,
|
||||
'excelrow' => $excelrow_value
|
||||
];
|
||||
}
|
||||
|
||||
$excelData = $new_excel_data;
|
||||
$part1_applied = true;
|
||||
|
||||
error_log("Routine part 1 completata - Righe aggregate: " . count($new_excel_data));
|
||||
error_log("Excelrow aggregati part 1: " . print_r(array_column($new_excel_data, 'excelrow'), true));
|
||||
}
|
||||
|
||||
error_log("Indici colonne - action1: $action1_index, action2: $action2_index, action3: $action3_index, action4: $action4_index");
|
||||
|
||||
// Raggruppa le righe per il valore in action1 (colonna K)
|
||||
$grouped_data = [];
|
||||
foreach ($excelData as $row) {
|
||||
/**
|
||||
* PART 2
|
||||
* Merge package-related columns into PACKAGE
|
||||
* Always applied if PACKAGE exists
|
||||
*/
|
||||
foreach ($excelData as $index => $row) {
|
||||
if (!isset($row['data']) || !is_array($row['data'])) {
|
||||
error_log("Riga non valida, manca 'data' per excelrow {$row['excelrow']}");
|
||||
error_log("Riga non valida nella part 2, manca 'data' all'indice $index");
|
||||
continue;
|
||||
}
|
||||
$key = $row['data'][$action1_index] ?? '';
|
||||
$key = empty($key) ? '_empty_' : $key;
|
||||
if (!isset($grouped_data[$key])) {
|
||||
$grouped_data[$key] = [
|
||||
'data' => $row['data'],
|
||||
'excelrow' => [$row['excelrow']],
|
||||
'style_codes' => [],
|
||||
'style_descriptions' => []
|
||||
];
|
||||
} else {
|
||||
$grouped_data[$key]['excelrow'][] = $row['excelrow'];
|
||||
|
||||
$package_values = [];
|
||||
|
||||
$value_package = trim((string)($row['data'][$package_index] ?? ''));
|
||||
$value_other_test = $other_test_index !== false ? trim((string)($row['data'][$other_test_index] ?? '')) : '';
|
||||
$value_only_colorfastness = $only_colorfastness_index !== false ? trim((string)($row['data'][$only_colorfastness_index] ?? '')) : '';
|
||||
$value_only_chemical = $only_chemical_index !== false ? trim((string)($row['data'][$only_chemical_index] ?? '')) : '';
|
||||
|
||||
if ($value_package !== '') {
|
||||
$package_values[] = $value_package;
|
||||
}
|
||||
if ($value_other_test !== '') {
|
||||
$package_values[] = $value_other_test;
|
||||
}
|
||||
if ($value_only_colorfastness !== '') {
|
||||
$package_values[] = $value_only_colorfastness;
|
||||
}
|
||||
if ($value_only_chemical !== '') {
|
||||
$package_values[] = $value_only_chemical;
|
||||
}
|
||||
|
||||
// Separa il valore in action2 (STYLE CODE + STYLE DESCRIPTION)
|
||||
$action2_value = $row['data'][$action2_index] ?? '';
|
||||
if (!empty($action2_value)) {
|
||||
$parts = explode(' - ', trim($action2_value));
|
||||
$style_code = $parts[0] ?? '';
|
||||
$style_description = $parts[1] ?? '';
|
||||
if (!empty($style_code)) {
|
||||
$grouped_data[$key]['style_codes'][] = $style_code;
|
||||
}
|
||||
if (!empty($style_description)) {
|
||||
$grouped_data[$key]['style_descriptions'][] = $style_description;
|
||||
}
|
||||
} else {
|
||||
error_log("Valore vuoto in action2 per excelrow {$row['excelrow']}");
|
||||
}
|
||||
$package_values = array_unique($package_values);
|
||||
|
||||
$excelData[$index]['data'][$package_index] = implode(' - ', $package_values);
|
||||
}
|
||||
|
||||
// Crea il nuovo array excel_data aggregato
|
||||
$new_excel_data = [];
|
||||
foreach ($grouped_data as $key => $group) {
|
||||
$row_data = $group['data'];
|
||||
// Aggiorna action3 (STYLE CODE) e action4 (STYLE DESCRIPTION) con valori aggregati
|
||||
$row_data[$action3_index] = implode(' - ', array_unique($group['style_codes']));
|
||||
$row_data[$action4_index] = implode(' - ', array_unique($group['style_descriptions']));
|
||||
// Concatena gli excelrow con '+' per le righe aggregate
|
||||
$excelrow_value = count($group['excelrow']) > 1 ? implode('+', $group['excelrow']) : $group['excelrow'][0];
|
||||
$new_excel_data[] = [
|
||||
'data' => $row_data,
|
||||
'excelrow' => $excelrow_value
|
||||
];
|
||||
error_log("Routine part 2 completata - Merge package applicato su " . count($excelData) . " righe");
|
||||
|
||||
if (!$part1_applied) {
|
||||
error_log("Warning finale: routine part 1 non applicata, routine part 2 applicata correttamente");
|
||||
}
|
||||
|
||||
// Modifica excelData in-place
|
||||
$excelData = $new_excel_data;
|
||||
|
||||
error_log("Routine Moncler completata - Righe aggregate: " . count($new_excel_data));
|
||||
error_log("Excelrow aggregati: " . print_r(array_column($new_excel_data, 'excelrow'), true));
|
||||
error_log("Routine Moncler completata con successo");
|
||||
} catch (Exception $e) {
|
||||
error_log("Eccezione nella routine Moncler: " . $e->getMessage());
|
||||
throw $e;
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
ini_set('log_errors', 1);
|
||||
ini_set('error_log', __DIR__ . '/routine_debug.log');
|
||||
|
||||
function applyRoutine(&$excelData, $routineData)
|
||||
{
|
||||
try {
|
||||
// Initial log
|
||||
error_log("Inizio esecuzione nuova routine: " . date('Y-m-d H:i:s'));
|
||||
error_log("Dati routine: " . print_r($routineData, true));
|
||||
error_log("Dati excel_data: " . print_r($excelData, true));
|
||||
|
||||
// Check if excelData is empty
|
||||
if (empty($excelData)) {
|
||||
throw new Exception("excelData è vuoto o non valido.");
|
||||
}
|
||||
|
||||
// Get headers from routine data
|
||||
$headers = $routineData['xls_headers'] ?? [];
|
||||
|
||||
if (empty($headers)) {
|
||||
throw new Exception("Nessun header trovato per la routine.");
|
||||
}
|
||||
|
||||
// If headers arrive as JSON string, decode them
|
||||
if (!is_array($headers) && is_string($headers)) {
|
||||
$decoded_headers = json_decode($headers, true);
|
||||
if (json_last_error() === JSON_ERROR_NONE && is_array($decoded_headers)) {
|
||||
$headers = $decoded_headers;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_array($headers) || empty($headers)) {
|
||||
throw new Exception("Gli header della routine non sono validi.");
|
||||
}
|
||||
|
||||
error_log("Header ricevuti: " . print_r($headers, true));
|
||||
|
||||
// Normalize headers
|
||||
$normalized_headers = array_map(function ($header) {
|
||||
return trim((string)$header);
|
||||
}, $headers);
|
||||
|
||||
error_log("Header normalizzati: " . print_r($normalized_headers, true));
|
||||
|
||||
/**
|
||||
* Define source and target headers
|
||||
*/
|
||||
$parte_moncler_header = 'PARTE MONCLER';
|
||||
$parte_fornitore_header = 'PARTE FORNITORE';
|
||||
|
||||
$descr_parte_moncler_header = 'DESCRIZIONE PARTE MONCLER';
|
||||
$descr_parte_fornitore_header = 'DESCRIZIONE PARTE FORNITORE';
|
||||
|
||||
$colore_moncler_header = 'COLORE MONCLER';
|
||||
$colore_fornitore_header = 'COLORE FORNITORE';
|
||||
|
||||
$composizione_tessile_header = 'COMPOSIZIONE TESSILE';
|
||||
$composizione_totale_header = 'COMPOSIZIONE TOTALE';
|
||||
|
||||
$pacchetti_test_header = 'PACCHETTI TEST';
|
||||
$test_addizionali_header = 'TEST ADDIZIONALI (A5 solo se richiesti dal cliente)';
|
||||
|
||||
/**
|
||||
* Find indexes
|
||||
*/
|
||||
$parte_moncler_index = array_search($parte_moncler_header, $normalized_headers, true);
|
||||
$parte_fornitore_index = array_search($parte_fornitore_header, $normalized_headers, true);
|
||||
|
||||
$descr_parte_moncler_index = array_search($descr_parte_moncler_header, $normalized_headers, true);
|
||||
$descr_parte_fornitore_index = array_search($descr_parte_fornitore_header, $normalized_headers, true);
|
||||
|
||||
$colore_moncler_index = array_search($colore_moncler_header, $normalized_headers, true);
|
||||
$colore_fornitore_index = array_search($colore_fornitore_header, $normalized_headers, true);
|
||||
|
||||
$composizione_tessile_index = array_search($composizione_tessile_header, $normalized_headers, true);
|
||||
$composizione_totale_index = array_search($composizione_totale_header, $normalized_headers, true);
|
||||
|
||||
$pacchetti_test_index = array_search($pacchetti_test_header, $normalized_headers, true);
|
||||
$test_addizionali_index = array_search($test_addizionali_header, $normalized_headers, true);
|
||||
|
||||
error_log(
|
||||
"Indici trovati - " .
|
||||
"PARTE MONCLER: " . var_export($parte_moncler_index, true) .
|
||||
", PARTE FORNITORE: " . var_export($parte_fornitore_index, true) .
|
||||
", DESCRIZIONE PARTE MONCLER: " . var_export($descr_parte_moncler_index, true) .
|
||||
", DESCRIZIONE PARTE FORNITORE: " . var_export($descr_parte_fornitore_index, true) .
|
||||
", COLORE MONCLER: " . var_export($colore_moncler_index, true) .
|
||||
", COLORE FORNITORE: " . var_export($colore_fornitore_index, true) .
|
||||
", COMPOSIZIONE TESSILE: " . var_export($composizione_tessile_index, true) .
|
||||
", COMPOSIZIONE TOTALE: " . var_export($composizione_totale_index, true) .
|
||||
", PACCHETTI TEST: " . var_export($pacchetti_test_index, true) .
|
||||
", TEST ADDIZIONALI: " . var_export($test_addizionali_index, true)
|
||||
);
|
||||
|
||||
// Required target columns must exist
|
||||
if ($parte_moncler_index === false) {
|
||||
throw new Exception("Colonna PARTE MONCLER non trovata.");
|
||||
}
|
||||
|
||||
if ($descr_parte_moncler_index === false) {
|
||||
throw new Exception("Colonna DESCRIZIONE PARTE MONCLER non trovata.");
|
||||
}
|
||||
|
||||
if ($colore_moncler_index === false) {
|
||||
throw new Exception("Colonna COLORE MONCLER non trovata.");
|
||||
}
|
||||
|
||||
if ($composizione_tessile_index === false) {
|
||||
throw new Exception("Colonna COMPOSIZIONE TESSILE non trovata.");
|
||||
}
|
||||
|
||||
if ($pacchetti_test_index === false) {
|
||||
throw new Exception("Colonna PACCHETTI TEST non trovata.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply merge row by row
|
||||
*/
|
||||
foreach ($excelData as $index => $row) {
|
||||
if (!isset($row['data']) || !is_array($row['data'])) {
|
||||
error_log("Riga non valida, manca 'data' all'indice $index");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 1. PARTE MONCLER + PARTE FORNITORE -> PARTE MONCLER
|
||||
$parte_values = [];
|
||||
|
||||
$value_parte_moncler = trim((string)($row['data'][$parte_moncler_index] ?? ''));
|
||||
$value_parte_fornitore = $parte_fornitore_index !== false ? trim((string)($row['data'][$parte_fornitore_index] ?? '')) : '';
|
||||
|
||||
if ($value_parte_moncler !== '') {
|
||||
$parte_values[] = $value_parte_moncler;
|
||||
}
|
||||
if ($value_parte_fornitore !== '') {
|
||||
$parte_values[] = $value_parte_fornitore;
|
||||
}
|
||||
|
||||
$parte_values = array_unique($parte_values);
|
||||
$excelData[$index]['data'][$parte_moncler_index] = implode(' - ', $parte_values);
|
||||
|
||||
// 2. DESCRIZIONE PARTE MONCLER + DESCRIZIONE PARTE FORNITORE -> DESCRIZIONE PARTE MONCLER
|
||||
$descr_values = [];
|
||||
|
||||
$value_descr_moncler = trim((string)($row['data'][$descr_parte_moncler_index] ?? ''));
|
||||
$value_descr_fornitore = $descr_parte_fornitore_index !== false ? trim((string)($row['data'][$descr_parte_fornitore_index] ?? '')) : '';
|
||||
|
||||
if ($value_descr_moncler !== '') {
|
||||
$descr_values[] = $value_descr_moncler;
|
||||
}
|
||||
if ($value_descr_fornitore !== '') {
|
||||
$descr_values[] = $value_descr_fornitore;
|
||||
}
|
||||
|
||||
$descr_values = array_unique($descr_values);
|
||||
$excelData[$index]['data'][$descr_parte_moncler_index] = implode(' - ', $descr_values);
|
||||
|
||||
// 3. COLORE MONCLER + COLORE FORNITORE -> COLORE MONCLER
|
||||
$colore_values = [];
|
||||
|
||||
$value_colore_moncler = trim((string)($row['data'][$colore_moncler_index] ?? ''));
|
||||
$value_colore_fornitore = $colore_fornitore_index !== false ? trim((string)($row['data'][$colore_fornitore_index] ?? '')) : '';
|
||||
|
||||
if ($value_colore_moncler !== '') {
|
||||
$colore_values[] = $value_colore_moncler;
|
||||
}
|
||||
if ($value_colore_fornitore !== '') {
|
||||
$colore_values[] = $value_colore_fornitore;
|
||||
}
|
||||
|
||||
$colore_values = array_unique($colore_values);
|
||||
$excelData[$index]['data'][$colore_moncler_index] = implode(' - ', $colore_values);
|
||||
|
||||
// 4. COMPOSIZIONE TESSILE + COMPOSIZIONE TOTALE -> COMPOSIZIONE TESSILE
|
||||
$composizione_values = [];
|
||||
|
||||
$value_composizione_tessile = trim((string)($row['data'][$composizione_tessile_index] ?? ''));
|
||||
$value_composizione_totale = $composizione_totale_index !== false ? trim((string)($row['data'][$composizione_totale_index] ?? '')) : '';
|
||||
|
||||
if ($value_composizione_tessile !== '') {
|
||||
$composizione_values[] = $value_composizione_tessile;
|
||||
}
|
||||
if ($value_composizione_totale !== '') {
|
||||
$composizione_values[] = $value_composizione_totale;
|
||||
}
|
||||
|
||||
$composizione_values = array_unique($composizione_values);
|
||||
$excelData[$index]['data'][$composizione_tessile_index] = implode(' - ', $composizione_values);
|
||||
|
||||
// 5. PACCHETTI TEST + TEST ADDIZIONALI -> PACCHETTI TEST
|
||||
$pacchetti_values = [];
|
||||
|
||||
$value_pacchetti_test = trim((string)($row['data'][$pacchetti_test_index] ?? ''));
|
||||
$value_test_addizionali = $test_addizionali_index !== false ? trim((string)($row['data'][$test_addizionali_index] ?? '')) : '';
|
||||
|
||||
if ($value_pacchetti_test !== '') {
|
||||
$pacchetti_values[] = $value_pacchetti_test;
|
||||
}
|
||||
if ($value_test_addizionali !== '') {
|
||||
$pacchetti_values[] = $value_test_addizionali;
|
||||
}
|
||||
|
||||
$pacchetti_values = array_unique($pacchetti_values);
|
||||
$excelData[$index]['data'][$pacchetti_test_index] = implode(' - ', $pacchetti_values);
|
||||
}
|
||||
|
||||
error_log("Nuova routine completata con successo. Righe elaborate: " . count($excelData));
|
||||
} catch (Exception $e) {
|
||||
error_log("Eccezione nella nuova routine: " . $e->getMessage());
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ try {
|
||||
|
||||
$iddatadb = intval($_POST['iddatadb']);
|
||||
$idclient = isset($_POST['idclient']) ? (is_numeric($_POST['idclient']) ? intval($_POST['idclient']) : null) : null;
|
||||
$clienteFornitoreId = isset($_POST['cliente_fornitore_id']) ? (is_numeric($_POST['cliente_fornitore_id']) ? intval($_POST['cliente_fornitore_id']) : null) : null;
|
||||
|
||||
$db = DBHandlerSelect::getInstance();
|
||||
$pdo = $db->getConnection();
|
||||
@@ -22,10 +23,11 @@ try {
|
||||
// (NON tocchiamo MySQL, gestiamo solo qui la traduzione)
|
||||
$fixedAliasMap = [
|
||||
'ClienteResponsabile' => 'cliente_responsabile_id',
|
||||
'ClienteFornitore' => 'cliente_fornitore_id',
|
||||
'ClienteAnalisi' => 'clienteAnalisi',
|
||||
'MoltiplicatorePrezzo' => 'moltiplicatore_prezzo_id',
|
||||
'AnagraficaCertestObject' => 'anagrafica_certest_object_id',
|
||||
'AnagraficaCertestService' => 'anagrafica_certest_service_id',
|
||||
'ClienteFornitore' => 'cliente_fornitore_id',
|
||||
'ConsegnaRichiesta' => 'consegna_richiesta',
|
||||
];
|
||||
|
||||
@@ -137,6 +139,12 @@ try {
|
||||
$params[] = $idclient;
|
||||
}
|
||||
|
||||
// 5a2) cliente_fornitore_id (se presente)
|
||||
if (isset($clienteFornitoreId)) {
|
||||
$setParts[] = "cliente_fornitore_id = ?";
|
||||
$params[] = $clienteFornitoreId;
|
||||
}
|
||||
|
||||
// 5b) fixed fields dal POST
|
||||
// QUI è il punto chiave: accettiamo SOLO colonne reali (realWhitelist),
|
||||
// ma se dal JS arrivassero ancora key logiche, funzionerebbe uguale
|
||||
|
||||
@@ -761,7 +761,7 @@
|
||||
"IdSchemaCustomFields": 182,
|
||||
"ConteggioClienti": 0,
|
||||
"Nome": "Ralph Lauren - All testing V.6",
|
||||
"Descrizione": null
|
||||
"Descrizione": "AGGIORNAMENTO AL 16\/03\/2026 per estrazione fatturazione"
|
||||
},
|
||||
{
|
||||
"IdSchemaCustomFields": 183,
|
||||
|
||||
@@ -6,47 +6,88 @@ if (!Auth::check()) {
|
||||
redirectTo('../public/login');
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
$id = $_POST['iduserlogin'];
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$first_name = $_POST['first_name'];
|
||||
$last_name = $_POST['last_name'];
|
||||
$email = $_POST['email'];
|
||||
$password = $_POST['password'] ?: null;
|
||||
|
||||
$db = DBHandlerSelect::getInstance()->getConnection();
|
||||
|
||||
// Gestione avatar
|
||||
$avatar = $user->present()->avatar;
|
||||
if (isset($_FILES['avatar']) && $_FILES['avatar']['error'] === UPLOAD_ERR_OK) {
|
||||
$avatar = time() . '_' . basename($_FILES['avatar']['name']);
|
||||
$uploadDir = __DIR__ . '/../../public/upload/users/';
|
||||
if (!is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0755, true);
|
||||
}
|
||||
move_uploaded_file($_FILES['avatar']['tmp_name'], $uploadDir . $avatar);
|
||||
}
|
||||
|
||||
// Aggiornamento dati
|
||||
$sql = "UPDATE auth_users SET first_name = ?, last_name = ?, email = ?, avatar = ? WHERE id = ?";
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->execute([$first_name, $last_name, $email, $avatar, $id]);
|
||||
|
||||
// Aggiornamento password se fornita
|
||||
if ($password) {
|
||||
$hashedPassword = password_hash($password, PASSWORD_BCRYPT);
|
||||
$sql = "UPDATE auth_users SET password = ? WHERE id = ?";
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->execute([$hashedPassword, $id]);
|
||||
}
|
||||
|
||||
// Aggiorna la sessione con i nuovi dati
|
||||
$_SESSION["nameuser"] = $first_name;
|
||||
$_SESSION["surnameuser"] = $last_name;
|
||||
$_SESSION["emailuser"] = $email;
|
||||
$_SESSION["photouser"] = $avatar;
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
header('Location: user-profile.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
$id = isset($_POST['iduserlogin']) ? (int)$_POST['iduserlogin'] : 0;
|
||||
|
||||
$first_name = trim($_POST['first_name'] ?? '');
|
||||
$last_name = trim($_POST['last_name'] ?? '');
|
||||
$email = trim($_POST['email'] ?? '');
|
||||
$password = trim($_POST['password'] ?? '');
|
||||
|
||||
$lims_user_id = isset($_POST['lims_user_id']) && $_POST['lims_user_id'] !== ''
|
||||
? (int)$_POST['lims_user_id']
|
||||
: null;
|
||||
|
||||
$lims_global_user_id = isset($_POST['lims_global_user_id']) && $_POST['lims_global_user_id'] !== ''
|
||||
? (int)$_POST['lims_global_user_id']
|
||||
: null;
|
||||
|
||||
if ($id <= 0) {
|
||||
die('Invalid user ID');
|
||||
}
|
||||
|
||||
$db = DBHandlerSelect::getInstance()->getConnection();
|
||||
|
||||
// Current avatar
|
||||
$avatar = $user->present()->avatar;
|
||||
|
||||
// Avatar upload
|
||||
if (isset($_FILES['avatar']) && $_FILES['avatar']['error'] === UPLOAD_ERR_OK) {
|
||||
$originalName = basename($_FILES['avatar']['name']);
|
||||
$safeName = preg_replace('/[^A-Za-z0-9_\.-]/', '_', $originalName);
|
||||
$avatar = time() . '_' . $safeName;
|
||||
|
||||
$uploadDir = __DIR__ . '/../../public/upload/users/';
|
||||
if (!is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0755, true);
|
||||
}
|
||||
|
||||
move_uploaded_file($_FILES['avatar']['tmp_name'], $uploadDir . $avatar);
|
||||
}
|
||||
|
||||
// Update main user data
|
||||
$sql = "UPDATE auth_users
|
||||
SET first_name = ?,
|
||||
last_name = ?,
|
||||
email = ?,
|
||||
avatar = ?,
|
||||
lims_user_id = ?,
|
||||
lims_global_user_id = ?
|
||||
WHERE id = ?";
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->execute([
|
||||
$first_name,
|
||||
$last_name,
|
||||
$email,
|
||||
$avatar,
|
||||
$lims_user_id,
|
||||
$lims_global_user_id,
|
||||
$id
|
||||
]);
|
||||
|
||||
// Update password only if provided
|
||||
if ($password !== '') {
|
||||
$hashedPassword = password_hash($password, PASSWORD_BCRYPT);
|
||||
|
||||
$sql = "UPDATE auth_users SET password = ? WHERE id = ?";
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->execute([$hashedPassword, $id]);
|
||||
}
|
||||
|
||||
// Update session
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
$_SESSION["nameuser"] = $first_name;
|
||||
$_SESSION["surnameuser"] = $last_name;
|
||||
$_SESSION["emailuser"] = $email;
|
||||
$_SESSION["photouser"] = $avatar;
|
||||
|
||||
header('Location: user-profile.php');
|
||||
exit;
|
||||
|
||||
@@ -48,6 +48,17 @@
|
||||
<label for="email" class="form-label">Email</label>
|
||||
<input type="email" class="form-control" id="email" name="email" value="<?= htmlspecialchars($emailuser); ?>" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="lims_user_id" class="form-label">Accettatore</label>
|
||||
<input type="number" class="form-control" id="lims_user_id" name="lims_user_id" value="<?= htmlspecialchars($lims_user_id ?? ''); ?>">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="lims_global_user_id" class="form-label">LIMS Global</label>
|
||||
<input type="number" class="form-control" id="lims_global_user_id" name="lims_global_user_id" value="<?= htmlspecialchars($lims_global_user_id ?? ''); ?>">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="avatar" class="form-label">Profile Picture</label>
|
||||
<input type="file" class="form-control" id="avatar" name="avatar">
|
||||
|
||||
@@ -59,6 +59,35 @@ $validators[] = function (int $iddatadb, array $ctx): array {
|
||||
return [];
|
||||
};
|
||||
|
||||
// 2. ConsegnaRichiesta must be filled and >= today
|
||||
$validators[] = function (int $iddatadb, array $ctx): array {
|
||||
$record = $ctx['record'] ?? null;
|
||||
if (!$record) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$consegna = $record['consegna_richiesta'] ?? null;
|
||||
|
||||
if (empty($consegna)) {
|
||||
return [[
|
||||
'field' => 'ConsegnaRichiesta',
|
||||
'message' => 'ConsegnaRichiesta è obbligatorio.',
|
||||
]];
|
||||
}
|
||||
|
||||
$consegnaDate = DateTime::createFromFormat('Y-m-d', $consegna) ?: DateTime::createFromFormat('Y-m-d H:i:s', $consegna);
|
||||
$today = new DateTime('today');
|
||||
|
||||
if ($consegnaDate && $consegnaDate < $today) {
|
||||
return [[
|
||||
'field' => 'ConsegnaRichiesta',
|
||||
'message' => 'ConsegnaRichiesta deve essere uguale o superiore alla data odierna (' . $today->format('Y-m-d') . ').',
|
||||
]];
|
||||
}
|
||||
|
||||
return [];
|
||||
};
|
||||
|
||||
// ── Main ────────────────────────────────────────────────────────────────────
|
||||
|
||||
try {
|
||||
@@ -75,6 +104,18 @@ try {
|
||||
$iddatadbList = array_column($rows, 'iddatadb');
|
||||
$placeholders = implode(',', array_fill(0, count($iddatadbList), '?'));
|
||||
|
||||
// Records (datadb) for fixed field validation
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT iddatadb, consegna_richiesta
|
||||
FROM datadb
|
||||
WHERE iddatadb IN ($placeholders)
|
||||
");
|
||||
$stmt->execute($iddatadbList);
|
||||
$recordsInfo = [];
|
||||
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $r) {
|
||||
$recordsInfo[(int)$r['iddatadb']] = $r;
|
||||
}
|
||||
|
||||
// Parts (full rows, so validators can report which parts have issues)
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT iddatadb, part_number, part_description, idmatrice
|
||||
@@ -97,7 +138,8 @@ try {
|
||||
|
||||
// Build context for validators
|
||||
$ctx = [
|
||||
'parts' => $partsInfo[$iddatadb] ?? [],
|
||||
'record' => $recordsInfo[$iddatadb] ?? null,
|
||||
'parts' => $partsInfo[$iddatadb] ?? [],
|
||||
];
|
||||
|
||||
$errors = [];
|
||||
|
||||
Reference in New Issue
Block a user