edit templtae lingue e colori
This commit is contained in:
@@ -40,10 +40,13 @@ yarn-error.log
|
|||||||
/public/userarea/logaspi/
|
/public/userarea/logaspi/
|
||||||
/public/userarea/logs/api/
|
/public/userarea/logs/api/
|
||||||
/public/userarea/logs/api/**
|
/public/userarea/logs/api/**
|
||||||
|
/public/userarea/logs/
|
||||||
|
/public/userarea/logs/**
|
||||||
/public/userarea/photostrf/
|
/public/userarea/photostrf/
|
||||||
/public/userarea/class/*.log
|
/public/userarea/class/*.log
|
||||||
/public/userarea/class/curl_auth_debug.log
|
/public/userarea/class/curl_auth_debug.log
|
||||||
/public/userarea/class/curl_request_debug.log
|
/public/userarea/class/curl_request_debug.log
|
||||||
|
/public/userarea/schema_dettagli_response.json
|
||||||
|
|
||||||
# File XLSX temporanei importati
|
# File XLSX temporanei importati
|
||||||
/public/userarea/imported_trf/*.xlsx
|
/public/userarea/imported_trf/*.xlsx
|
||||||
|
|||||||
@@ -255,4 +255,39 @@ class VisualLimsApiClient
|
|||||||
{
|
{
|
||||||
return $this->baseUrl;
|
return $this->baseUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recupera contenuto binario - Adattato per https://bvcpsitaly-elims.com/limsapi
|
||||||
|
*/
|
||||||
|
public function getRaw($endpoint)
|
||||||
|
{
|
||||||
|
$token = $this->getToken();
|
||||||
|
|
||||||
|
// IMPORTANTE: usa /odata/ e NON /api/odata/
|
||||||
|
$url = "{$this->baseUrl}/odata/{$endpoint}";
|
||||||
|
|
||||||
|
$ch = curl_init($url);
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||||
|
"Authorization: Bearer {$token}",
|
||||||
|
"Accept: */*"
|
||||||
|
]);
|
||||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||||
|
|
||||||
|
$response = curl_exec($ch);
|
||||||
|
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
|
$curl_error = curl_error($ch);
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
if ($response === false) {
|
||||||
|
throw new Exception("Errore cURL: " . $curl_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($http_code !== 200) {
|
||||||
|
throw new Exception("HTTP {$http_code} su endpoint: " . $url);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,112 @@
|
|||||||
|
<?php
|
||||||
|
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
|
||||||
|
require_once dirname(__FILE__) . '/class/VisualLimsApiClient.class.php';
|
||||||
|
|
||||||
|
ini_set('display_errors', '0');
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uso:
|
||||||
|
* download_rapporto_file.php?id=123
|
||||||
|
*/
|
||||||
|
|
||||||
|
try {
|
||||||
|
$api = VisualLimsApiClient::getInstance();
|
||||||
|
|
||||||
|
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
|
||||||
|
|
||||||
|
if (!$id) {
|
||||||
|
throw new Exception("ID RapportoFile mancante");
|
||||||
|
}
|
||||||
|
|
||||||
|
$debugDir = __DIR__ . '/logs/lims_get_commessa/';
|
||||||
|
|
||||||
|
if (!is_dir($debugDir)) {
|
||||||
|
mkdir($debugDir, 0755, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recupero il record RapportoFile.
|
||||||
|
*/
|
||||||
|
$data = $api->get("RapportoFile({$id})", []);
|
||||||
|
|
||||||
|
file_put_contents(
|
||||||
|
$debugDir . "rapporto_file_{$id}.json",
|
||||||
|
json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provo vari nomi campo possibili per il contenuto PDF.
|
||||||
|
* Dopo il primo test potremo adattarlo al nome esatto.
|
||||||
|
*/
|
||||||
|
$possibleContentFields = [
|
||||||
|
'File',
|
||||||
|
'file',
|
||||||
|
'Content',
|
||||||
|
'content',
|
||||||
|
'FileContent',
|
||||||
|
'fileContent',
|
||||||
|
'Contenuto',
|
||||||
|
'contenuto',
|
||||||
|
'Bytes',
|
||||||
|
'bytes'
|
||||||
|
];
|
||||||
|
|
||||||
|
$base64 = null;
|
||||||
|
|
||||||
|
foreach ($possibleContentFields as $field) {
|
||||||
|
if (!empty($data[$field])) {
|
||||||
|
$base64 = $data[$field];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$base64) {
|
||||||
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Record RapportoFile recuperato, ma non ho trovato un campo base64 del PDF.',
|
||||||
|
'hint' => 'Apri logs/lims_get_commessa/rapporto_file_' . $id . '.json e controlla il nome reale del campo file.',
|
||||||
|
'data' => $data
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Se il contenuto ha prefisso data URI, lo pulisco.
|
||||||
|
*/
|
||||||
|
if (strpos($base64, 'base64,') !== false) {
|
||||||
|
$parts = explode('base64,', $base64);
|
||||||
|
$base64 = end($parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
$pdfBinary = base64_decode($base64, true);
|
||||||
|
|
||||||
|
if ($pdfBinary === false) {
|
||||||
|
throw new Exception("Il contenuto trovato non è un base64 valido");
|
||||||
|
}
|
||||||
|
|
||||||
|
$filename = $data['NomeFile']
|
||||||
|
?? $data['nomeFile']
|
||||||
|
?? $data['FileName']
|
||||||
|
?? $data['fileName']
|
||||||
|
?? "rapporto_{$id}.pdf";
|
||||||
|
|
||||||
|
if (!str_ends_with(strtolower($filename), '.pdf')) {
|
||||||
|
$filename .= '.pdf';
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Content-Type: application/pdf');
|
||||||
|
header('Content-Disposition: inline; filename="' . basename($filename) . '"');
|
||||||
|
header('Content-Length: ' . strlen($pdfBinary));
|
||||||
|
|
||||||
|
echo $pdfBinary;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
http_response_code(500);
|
||||||
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||||
|
}
|
||||||
@@ -25,6 +25,41 @@ if (!$template) {
|
|||||||
$stmt = $pdo->prepare("SELECT * FROM routine");
|
$stmt = $pdo->prepare("SELECT * FROM routine");
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
$routines = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
$routines = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
$buttonBgPalette = [
|
||||||
|
'#0d6efd' => 'Blue',
|
||||||
|
'#6610f2' => 'Indigo',
|
||||||
|
'#6f42c1' => 'Purple',
|
||||||
|
'#d63384' => 'Pink',
|
||||||
|
'#dc3545' => 'Red',
|
||||||
|
'#fd7e14' => 'Orange',
|
||||||
|
'#ffc107' => 'Yellow',
|
||||||
|
'#198754' => 'Green',
|
||||||
|
'#20c997' => 'Teal',
|
||||||
|
'#0dcaf0' => 'Cyan',
|
||||||
|
'#212529' => 'Dark',
|
||||||
|
'#6c757d' => 'Gray',
|
||||||
|
'#495057' => 'Slate',
|
||||||
|
'#795548' => 'Brown',
|
||||||
|
'#2f5d50' => 'Sage Green',
|
||||||
|
];
|
||||||
|
|
||||||
|
$buttonTextPalette = [
|
||||||
|
'#ffffff' => 'White',
|
||||||
|
'#6c757d' => 'Gray',
|
||||||
|
'#000000' => 'Black',
|
||||||
|
];
|
||||||
|
|
||||||
|
$currentButtonBgColor = strtolower($template['button_bg_color'] ?? '#007bff');
|
||||||
|
$currentButtonTextColor = strtolower($template['button_text_color'] ?? '#ffffff');
|
||||||
|
|
||||||
|
if (!array_key_exists($currentButtonBgColor, array_change_key_case($buttonBgPalette, CASE_LOWER))) {
|
||||||
|
$currentButtonBgColor = '#0d6efd';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!array_key_exists($currentButtonTextColor, array_change_key_case($buttonTextPalette, CASE_LOWER))) {
|
||||||
|
$currentButtonTextColor = '#ffffff';
|
||||||
|
}
|
||||||
?>
|
?>
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
@@ -35,6 +70,64 @@ $routines = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|||||||
<link rel="icon" href="assets/images/favicon-32x32.png" type="image/png" />
|
<link rel="icon" href="assets/images/favicon-32x32.png" type="image/png" />
|
||||||
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
|
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
|
||||||
<?php include('cssinclude.php'); ?>
|
<?php include('cssinclude.php'); ?>
|
||||||
|
<style>
|
||||||
|
.color-palette {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-option {
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-option input {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-swatch {
|
||||||
|
width: 42px;
|
||||||
|
height: 42px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 2px solid #d6dbe0;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
|
||||||
|
transition: all 0.18s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-option input:checked+.color-swatch {
|
||||||
|
border: 3px solid #111827;
|
||||||
|
transform: scale(1.08);
|
||||||
|
box-shadow: 0 0 0 4px rgba(13, 110, 253, 0.18);
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-swatch .check-mark {
|
||||||
|
display: none;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #ffffff;
|
||||||
|
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-option input:checked+.color-swatch .check-mark {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-name {
|
||||||
|
display: block;
|
||||||
|
font-size: 11px;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 4px;
|
||||||
|
color: #555;
|
||||||
|
max-width: 55px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
||||||
<title>Edit Template <?= htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?></title>
|
<title>Edit Template <?= htmlspecialchars($titlewebsite, ENT_QUOTES, 'UTF-8'); ?></title>
|
||||||
@@ -123,12 +216,46 @@ $routines = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label">Button Background Color</label>
|
<label class="form-label">Button Background Color</label>
|
||||||
<input type="color" name="button_bg_color" class="form-control form-control-color" value="<?php echo htmlspecialchars($template['button_bg_color'] ?? '#007bff'); ?>">
|
|
||||||
|
<div class="color-palette">
|
||||||
|
<?php foreach ($buttonBgPalette as $colorValue => $colorLabel): ?>
|
||||||
|
<?php $isChecked = strtolower($colorValue) === $currentButtonBgColor; ?>
|
||||||
|
|
||||||
|
<label class="color-option" title="<?= htmlspecialchars($colorLabel, ENT_QUOTES, 'UTF-8'); ?>">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="button_bg_color"
|
||||||
|
value="<?= htmlspecialchars($colorValue, ENT_QUOTES, 'UTF-8'); ?>"
|
||||||
|
<?= $isChecked ? 'checked' : ''; ?>>
|
||||||
|
<span class="color-swatch" style="background-color: <?= htmlspecialchars($colorValue, ENT_QUOTES, 'UTF-8'); ?>;">
|
||||||
|
<span class="check-mark">✓</span>
|
||||||
|
</span>
|
||||||
|
<span class="color-name"><?= htmlspecialchars($colorLabel, ENT_QUOTES, 'UTF-8'); ?></span>
|
||||||
|
</label>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label">Button Text Color</label>
|
<label class="form-label">Button Text Color</label>
|
||||||
<input type="color" name="button_text_color" class="form-control form-control-color" value="<?php echo htmlspecialchars($template['button_text_color'] ?? '#ffffff'); ?>">
|
|
||||||
|
<div class="color-palette">
|
||||||
|
<?php foreach ($buttonTextPalette as $colorValue => $colorLabel): ?>
|
||||||
|
<?php $isChecked = strtolower($colorValue) === $currentButtonTextColor; ?>
|
||||||
|
|
||||||
|
<label class="color-option" title="<?= htmlspecialchars($colorLabel, ENT_QUOTES, 'UTF-8'); ?>">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="button_text_color"
|
||||||
|
value="<?= htmlspecialchars($colorValue, ENT_QUOTES, 'UTF-8'); ?>"
|
||||||
|
<?= $isChecked ? 'checked' : ''; ?>>
|
||||||
|
<span class="color-swatch" style="background-color: <?= htmlspecialchars($colorValue, ENT_QUOTES, 'UTF-8'); ?>;">
|
||||||
|
<span class="check-mark">✓</span>
|
||||||
|
</span>
|
||||||
|
<span class="color-name"><?= htmlspecialchars($colorLabel, ENT_QUOTES, 'UTF-8'); ?></span>
|
||||||
|
</label>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
@@ -258,6 +385,16 @@ $routines = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|||||||
sourceType.addEventListener('change', updateSourceFields);
|
sourceType.addEventListener('change', updateSourceFields);
|
||||||
updateSourceFields();
|
updateSourceFields();
|
||||||
|
|
||||||
|
function formatClientLabel(client) {
|
||||||
|
const nome = client.Nominativo || "Name not available";
|
||||||
|
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 loadClients() {
|
async function loadClients() {
|
||||||
try {
|
try {
|
||||||
clientLoadingStatus.style.display = 'inline';
|
clientLoadingStatus.style.display = 'inline';
|
||||||
@@ -280,9 +417,8 @@ $routines = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|||||||
select.innerHTML = '<option value="">Select a client...</option>';
|
select.innerHTML = '<option value="">Select a client...</option>';
|
||||||
|
|
||||||
data.value.forEach(client => {
|
data.value.forEach(client => {
|
||||||
const nome = client.Nominativo || "Name not available";
|
|
||||||
const id = client.IdCliente || "";
|
const id = client.IdCliente || "";
|
||||||
const option = new Option(`${nome.trim()} (ID: ${id})`, id);
|
const option = new Option(formatClientLabel(client), id);
|
||||||
|
|
||||||
if (parseInt(id) === parseInt(selectedClientId)) {
|
if (parseInt(id) === parseInt(selectedClientId)) {
|
||||||
option.selected = true;
|
option.selected = true;
|
||||||
|
|||||||
@@ -328,3 +328,6 @@
|
|||||||
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: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: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"}
|
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"}
|
||||||
|
2026-04-30 15:01:25 - Errore nel recupero dati: HTTP 404, Risposta: {"title":"Not Found","status":404,"detail":"Not Found","instance":"GET /api/odata/Rapporto(2621521)","errorCode":"d25cbd678"}
|
||||||
|
2026-04-30 15:02:04 - Errore nel recupero dati: HTTP 404, Risposta:
|
||||||
|
2026-04-30 15:03:19 - Errore nella richiesta: URL rejected: Malformed input to a URL function
|
||||||
|
|||||||
@@ -0,0 +1,256 @@
|
|||||||
|
<?php
|
||||||
|
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
|
||||||
|
require_once dirname(__FILE__) . '/class/VisualLimsApiClient.class.php';
|
||||||
|
|
||||||
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
|
||||||
|
ini_set('display_errors', '0');
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uso:
|
||||||
|
* rapporto_full_by_codice.php?codice=2621521
|
||||||
|
* rapporto_full_by_codice.php?codice=2621521&download=1
|
||||||
|
*/
|
||||||
|
|
||||||
|
try {
|
||||||
|
$api = VisualLimsApiClient::getInstance();
|
||||||
|
|
||||||
|
$codiceRapporto = trim($_GET['codice'] ?? '');
|
||||||
|
$downloadPdf = isset($_GET['download']) && $_GET['download'] == '1';
|
||||||
|
|
||||||
|
if ($codiceRapporto === '') {
|
||||||
|
throw new Exception("Parametro codice mancante. Usa ?codice=2621521");
|
||||||
|
}
|
||||||
|
|
||||||
|
$debugDir = __DIR__ . '/logs/lims_rapporti/';
|
||||||
|
$pdfDir = __DIR__ . '/pdf/rapporti/';
|
||||||
|
|
||||||
|
if (!is_dir($debugDir)) mkdir($debugDir, 0755, true);
|
||||||
|
if (!is_dir($pdfDir)) mkdir($pdfDir, 0755, true);
|
||||||
|
|
||||||
|
$codiceRapportoSafe = str_replace("'", "''", $codiceRapporto);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* STEP 1 - Search IdRapporto
|
||||||
|
*/
|
||||||
|
$searchParams = [
|
||||||
|
'$filter' => "CodiceRapporto eq '{$codiceRapportoSafe}'",
|
||||||
|
'$select' => 'IdRapporto,CodiceRapporto,Data,Versione,Firmato,DataStampa',
|
||||||
|
'$top' => 1
|
||||||
|
];
|
||||||
|
|
||||||
|
$searchEndpoint = "Rapporto?" . http_build_query($searchParams);
|
||||||
|
$searchData = $api->get($searchEndpoint);
|
||||||
|
|
||||||
|
$rapporti = $searchData['value'] ?? [];
|
||||||
|
|
||||||
|
if (empty($rapporti)) {
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Nessun rapporto trovato per questo CodiceRapporto.',
|
||||||
|
'codice_rapporto' => $codiceRapporto
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rapportoBase = $rapporti[0];
|
||||||
|
$idRapporto = intval($rapportoBase['IdRapporto'] ?? 0);
|
||||||
|
|
||||||
|
if (!$idRapporto) {
|
||||||
|
throw new Exception("IdRapporto non trovato nella risposta.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* STEP 2 - Dettaglio Rapporto
|
||||||
|
*/
|
||||||
|
$clienteExpandError = null;
|
||||||
|
$detailEndpoint = "Rapporto({$idRapporto})?\$expand=Cliente,RapportiFiles,CampioniDatiRapporto";
|
||||||
|
|
||||||
|
try {
|
||||||
|
$detailData = $api->get($detailEndpoint);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$clienteExpandError = $e->getMessage();
|
||||||
|
$detailEndpoint = "Rapporto({$idRapporto})?\$expand=RapportiFiles,CampioniDatiRapporto";
|
||||||
|
$detailData = $api->get($detailEndpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
file_put_contents(
|
||||||
|
$debugDir . "rapporto_{$codiceRapportoSafe}_light.json",
|
||||||
|
json_encode($detailData, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)
|
||||||
|
);
|
||||||
|
|
||||||
|
$cliente = $detailData['Cliente'] ?? null;
|
||||||
|
$rapportiFiles = $detailData['RapportiFiles'] ?? [];
|
||||||
|
$campioniDatiRapporto = $detailData['CampioniDatiRapporto'] ?? [];
|
||||||
|
|
||||||
|
// ====================== CLIENTE ======================
|
||||||
|
$clienteInfo = [
|
||||||
|
'found' => is_array($cliente),
|
||||||
|
'id_cliente' => $cliente['IdCliente'] ?? $cliente['Id'] ?? null,
|
||||||
|
'codice_cliente' => $cliente['CodiceCliente'] ?? $cliente['Codice'] ?? null,
|
||||||
|
'nome_cliente' => $cliente['Nominativo'] ?? $cliente['RagioneSociale'] ?? $cliente['Nome'] ?? $cliente['Descrizione'] ?? null,
|
||||||
|
'partita_iva' => $cliente['PartitaIva'] ?? null,
|
||||||
|
'codice_fiscale' => $cliente['CodiceFiscale'] ?? null
|
||||||
|
];
|
||||||
|
|
||||||
|
// ====================== FILE PDF ======================
|
||||||
|
$selectedRapportoFile = null;
|
||||||
|
$idRapportoFile = null;
|
||||||
|
$pdfFileName = $codiceRapporto . '.pdf';
|
||||||
|
$pdfFullPath = $pdfDir . $pdfFileName;
|
||||||
|
|
||||||
|
if (is_array($rapportiFiles) && count($rapportiFiles) > 0) {
|
||||||
|
foreach ($rapportiFiles as $file) {
|
||||||
|
$fileName = $file['FileName'] ?? '';
|
||||||
|
$tipoRapporto = $file['TipoRapporto'] ?? '';
|
||||||
|
$categoria = $file['Categoria'] ?? '';
|
||||||
|
|
||||||
|
if (
|
||||||
|
stripos($fileName, '.pdf') !== false ||
|
||||||
|
stripos($tipoRapporto, 'Rapporto') !== false ||
|
||||||
|
stripos($categoria, 'Rapporti') !== false
|
||||||
|
) {
|
||||||
|
$selectedRapportoFile = $file;
|
||||||
|
$idRapportoFile = $file['IdRapportoFile'] ?? null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$selectedRapportoFile && count($rapportiFiles) > 0) {
|
||||||
|
$selectedRapportoFile = $rapportiFiles[0];
|
||||||
|
$idRapportoFile = $rapportiFiles[0]['IdRapportoFile'] ?? null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================== DOWNLOAD PDF - DEBUG AVANZATO ======================
|
||||||
|
$pdfDownloaded = false;
|
||||||
|
$pdfError = null;
|
||||||
|
$endpointUsato = null;
|
||||||
|
|
||||||
|
if ($downloadPdf && $idRapportoFile) {
|
||||||
|
|
||||||
|
$tentativi = [
|
||||||
|
"RapportoFile({$idRapportoFile})/\$value",
|
||||||
|
"RapportoFile({$idRapportoFile})/Contenuto/\$value",
|
||||||
|
"RapportoFile({$idRapportoFile})/File/\$value",
|
||||||
|
"Rapporto({$idRapporto})/RapportiFiles({$idRapportoFile})/\$value",
|
||||||
|
"Rapporto({$idRapporto})/RapportoFile/\$value",
|
||||||
|
"GetRapportoFile?IdRapportoFile={$idRapportoFile}",
|
||||||
|
"RapportoFile/Download?Id={$idRapportoFile}",
|
||||||
|
"Rapporto/DownloadFile?IdRapporto={$idRapporto}"
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($tentativi as $ep) {
|
||||||
|
try {
|
||||||
|
$pdfContent = $api->getRaw($ep);
|
||||||
|
|
||||||
|
if (strlen($pdfContent) > 2000) { // PDF decente deve essere più grande
|
||||||
|
file_put_contents($pdfFullPath, $pdfContent);
|
||||||
|
$pdfDownloaded = true;
|
||||||
|
$endpointUsato = $ep;
|
||||||
|
$pdfError = "SUCCESSO con: " . $ep;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
$pdfError = "Contenuto troppo piccolo con: " . $ep;
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$pdfError = "Fallito con " . $ep . " → " . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================== CAMPIONI + RATING (ripristinato dal tuo originale) ======================
|
||||||
|
$campioniSintesi = [];
|
||||||
|
$ratingFinale = null;
|
||||||
|
$ratingSource = null;
|
||||||
|
$hasIrregolare = false;
|
||||||
|
$hasPositiveResults = false;
|
||||||
|
|
||||||
|
if (is_array($campioniDatiRapporto)) {
|
||||||
|
foreach ($campioniDatiRapporto as $campione) {
|
||||||
|
$giudizioRapporto = $campione['GiudizioRapporto'] ?? null;
|
||||||
|
$giudizioCertificato = $campione['GiudizioCertificato'] ?? null;
|
||||||
|
$esitoGiudizioLMR = $campione['EsitoGiudizioLMR'] ?? null;
|
||||||
|
$esitoGiudizioImpiego = $campione['EsitoGiudizioImpiego'] ?? null;
|
||||||
|
$risultatiIrregolari = ($campione['RisultatiIrregolari'] ?? false) === true;
|
||||||
|
$risultatiPositivi = ($campione['RisultatiPositivi'] ?? false) === true;
|
||||||
|
|
||||||
|
$campioniSintesi[] = [
|
||||||
|
'id_campione_dati_rapporto' => $campione['IdCampioneDatiRapporto'] ?? null,
|
||||||
|
'codice_campione' => $campione['CodiceCampione'] ?? null,
|
||||||
|
'stato_campione' => $campione['StatoCampione'] ?? null,
|
||||||
|
'stato_campione_web' => $campione['StatoCampioneWeb'] ?? null,
|
||||||
|
'matrice' => $campione['Matrice'] ?? null,
|
||||||
|
'macro_matrice' => $campione['MacroMatrice'] ?? null,
|
||||||
|
'giudizio_rapporto' => $giudizioRapporto,
|
||||||
|
'giudizio_certificato' => $giudizioCertificato,
|
||||||
|
'esito_giudizio_lmr' => $esitoGiudizioLMR,
|
||||||
|
'esito_giudizio_impiego' => $esitoGiudizioImpiego,
|
||||||
|
'risultati_positivi' => $risultatiPositivi,
|
||||||
|
'risultati_irregolari' => $risultatiIrregolari
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!$ratingFinale && !empty($giudizioRapporto)) {
|
||||||
|
$ratingFinale = $giudizioRapporto;
|
||||||
|
$ratingSource = 'CampioniDatiRapporto.GiudizioRapporto';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$ratingFinale && !empty($giudizioCertificato)) {
|
||||||
|
$ratingFinale = $giudizioCertificato;
|
||||||
|
$ratingSource = 'CampioniDatiRapporto.GiudizioCertificato';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($risultatiIrregolari) $hasIrregolare = true;
|
||||||
|
if ($risultatiPositivi) $hasPositiveResults = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback rating
|
||||||
|
if (!$ratingFinale) {
|
||||||
|
if ($hasIrregolare) {
|
||||||
|
$ratingFinale = 'Irregolare';
|
||||||
|
$ratingSource = 'RisultatiIrregolari';
|
||||||
|
} elseif ($hasPositiveResults || count($campioniSintesi) > 0) {
|
||||||
|
$ratingFinale = 'Regolare';
|
||||||
|
$ratingSource = 'fallback';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================== RISPOSTA FINALE ======================
|
||||||
|
echo json_encode([
|
||||||
|
'success' => true,
|
||||||
|
|
||||||
|
'codice_rapporto' => $codiceRapporto,
|
||||||
|
'id_rapporto' => $idRapporto,
|
||||||
|
|
||||||
|
'search_endpoint' => $searchEndpoint,
|
||||||
|
'detail_endpoint' => $detailEndpoint,
|
||||||
|
'cliente_expand_error' => $clienteExpandError,
|
||||||
|
|
||||||
|
'rapporto_base' => $rapportoBase,
|
||||||
|
'cliente' => $clienteInfo,
|
||||||
|
|
||||||
|
'rating_finale' => $ratingFinale,
|
||||||
|
'rating_source' => $ratingSource,
|
||||||
|
|
||||||
|
'rapporti_files_count' => count($rapportiFiles),
|
||||||
|
'selected_rapporto_file' => $selectedRapportoFile,
|
||||||
|
|
||||||
|
'pdf_file_name' => $pdfFileName,
|
||||||
|
'pdf_path' => $pdfDownloaded ? $pdfFullPath : null,
|
||||||
|
'pdf_downloaded' => $pdfDownloaded,
|
||||||
|
'pdf_error' => $pdfError,
|
||||||
|
|
||||||
|
'campioni_count' => count($campioniSintesi),
|
||||||
|
'campioni_sintesi' => $campioniSintesi,
|
||||||
|
|
||||||
|
'download_requested' => $downloadPdf
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
http_response_code(500);
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
<?php
|
||||||
|
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
|
||||||
|
require_once dirname(__FILE__) . '/class/VisualLimsApiClient.class.php';
|
||||||
|
|
||||||
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
|
||||||
|
ini_set('display_errors', '0');
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$api = VisualLimsApiClient::getInstance();
|
||||||
|
|
||||||
|
$commessa = trim($_GET['commessa'] ?? '');
|
||||||
|
|
||||||
|
if ($commessa === '') {
|
||||||
|
throw new Exception("Parametro commessa mancante");
|
||||||
|
}
|
||||||
|
|
||||||
|
$debugDir = __DIR__ . '/logs/lims_rapporto/';
|
||||||
|
if (!is_dir($debugDir)) {
|
||||||
|
mkdir($debugDir, 0755, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* STEP 1
|
||||||
|
* Provo a cercare il rapporto con filtri leggeri.
|
||||||
|
* NIENTE expand pesanti.
|
||||||
|
*/
|
||||||
|
$attempts = [];
|
||||||
|
|
||||||
|
$filters = [
|
||||||
|
'CodiceCommessa' => "CodiceCommessa eq '{$commessa}'",
|
||||||
|
'Commessa_CodiceCommessa' => "Commessa/CodiceCommessa eq '{$commessa}'",
|
||||||
|
'Commessa_IdCommessa' => is_numeric($commessa) ? "Commessa/IdCommessa eq {$commessa}" : null,
|
||||||
|
'Codice' => "Codice eq '{$commessa}'"
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($filters as $label => $filter) {
|
||||||
|
if (!$filter) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$options = [
|
||||||
|
'$filter' => $filter,
|
||||||
|
'$top' => 10
|
||||||
|
];
|
||||||
|
|
||||||
|
$data = $api->get('Rapporto', $options);
|
||||||
|
|
||||||
|
$attempts[$label] = [
|
||||||
|
'success' => true,
|
||||||
|
'filter' => $filter,
|
||||||
|
'records' => isset($data['value']) && is_array($data['value']) ? count($data['value']) : null,
|
||||||
|
'data' => $data
|
||||||
|
];
|
||||||
|
|
||||||
|
file_put_contents(
|
||||||
|
$debugDir . "rapporto_{$commessa}_{$label}.json",
|
||||||
|
json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
|
||||||
|
);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$attempts[$label] = [
|
||||||
|
'success' => false,
|
||||||
|
'filter' => $filter,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* STEP 2
|
||||||
|
* Prendo solo eventuali rapporti trovati.
|
||||||
|
*/
|
||||||
|
$rapportiFound = [];
|
||||||
|
|
||||||
|
foreach ($attempts as $label => $attempt) {
|
||||||
|
if (!$attempt['success']) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$items = $attempt['data']['value'] ?? [];
|
||||||
|
|
||||||
|
if (!is_array($items)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$rapportiFound[] = [
|
||||||
|
'matched_by' => $label,
|
||||||
|
'rapporto' => $item
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'success' => true,
|
||||||
|
'input_commessa' => $commessa,
|
||||||
|
'message' => 'Ricerca leggera su Rapporto completata. Se trovi un rapporto, poi recuperiamo RapportiFiles solo per quello.',
|
||||||
|
'rapporti_found_count' => count($rapportiFound),
|
||||||
|
'rapporti_found' => $rapportiFound,
|
||||||
|
'attempts_summary' => array_map(function ($a) {
|
||||||
|
return [
|
||||||
|
'success' => $a['success'],
|
||||||
|
'filter' => $a['filter'],
|
||||||
|
'records' => $a['records'] ?? null,
|
||||||
|
'error' => $a['error'] ?? null
|
||||||
|
];
|
||||||
|
}, $attempts)
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
http_response_code(500);
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||||
|
}
|
||||||
@@ -2,25 +2,140 @@
|
|||||||
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
|
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
|
||||||
require_once dirname(__FILE__) . '/class/VisualLimsApiClient.class.php';
|
require_once dirname(__FILE__) . '/class/VisualLimsApiClient.class.php';
|
||||||
|
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
|
||||||
ini_set('display_errors', '0');
|
ini_set('display_errors', '0');
|
||||||
error_reporting(E_ALL);
|
error_reporting(E_ALL);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$api = VisualLimsApiClient::getInstance();
|
$api = VisualLimsApiClient::getInstance();
|
||||||
$rapporto_id = 533329;
|
|
||||||
|
|
||||||
// Costruzione manuale dell'endpoint con espansione annidata
|
// Esempi:
|
||||||
$endpoint = "Rapporto($rapporto_id)?\$expand=CampioniDatiRapporto(\$expand=AnalisiDatiRapporto,CustomFieldsDatiRapporto)";
|
// rapporto_by_codice_expand_step.php?codice=2541111&step=base
|
||||||
|
// rapporto_by_codice_expand_step.php?codice=2541111&step=files
|
||||||
|
// rapporto_by_codice_expand_step.php?codice=2541111&step=campioni
|
||||||
|
// rapporto_by_codice_expand_step.php?codice=2541111&step=files_campioni
|
||||||
|
|
||||||
// Non passiamo options, già incluso nell'endpoint
|
$codiceRapporto = trim($_GET['codice'] ?? '');
|
||||||
$data = $api->get($endpoint);
|
$step = trim($_GET['step'] ?? 'base');
|
||||||
|
|
||||||
file_put_contents(__DIR__ . '/rapporto_expanded.json', json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
if ($codiceRapporto === '') {
|
||||||
echo json_encode($data);
|
throw new Exception("Parametro codice mancante. Usa ?codice=2541111");
|
||||||
|
}
|
||||||
|
|
||||||
|
$allowedSteps = [
|
||||||
|
'base' => '',
|
||||||
|
'files' => 'RapportiFiles',
|
||||||
|
'allegati' => 'RapportiAllegati',
|
||||||
|
'campioni' => 'CampioniDatiRapporto',
|
||||||
|
'files_campioni' => 'RapportiFiles,CampioniDatiRapporto'
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!array_key_exists($step, $allowedSteps)) {
|
||||||
|
throw new Exception("Step non valido. Usa: " . implode(', ', array_keys($allowedSteps)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Escape OData per eventuali apostrofi
|
||||||
|
$codiceRapportoSafe = str_replace("'", "''", $codiceRapporto);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* STEP 1 - Trova IdRapporto partendo da CodiceRapporto.
|
||||||
|
* Query leggera, con $select e $top=1.
|
||||||
|
*/
|
||||||
|
$searchParams = [
|
||||||
|
'$filter' => "CodiceRapporto eq '{$codiceRapportoSafe}'",
|
||||||
|
'$select' => 'IdRapporto,CodiceRapporto,Data,Versione,Firmato,DataStampa',
|
||||||
|
'$top' => 1
|
||||||
|
];
|
||||||
|
|
||||||
|
$searchEndpoint = "Rapporto?" . http_build_query($searchParams);
|
||||||
|
|
||||||
|
$searchData = $api->get($searchEndpoint);
|
||||||
|
|
||||||
|
$items = $searchData['value'] ?? [];
|
||||||
|
|
||||||
|
if (!is_array($items) || count($items) === 0) {
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Nessun rapporto trovato per questo CodiceRapporto.',
|
||||||
|
'codice_rapporto' => $codiceRapporto,
|
||||||
|
'search_endpoint' => $searchEndpoint,
|
||||||
|
'search_data' => $searchData
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rapportoBase = $items[0];
|
||||||
|
$rapportoId = intval($rapportoBase['IdRapporto'] ?? 0);
|
||||||
|
|
||||||
|
if (!$rapportoId) {
|
||||||
|
throw new Exception("IdRapporto non trovato nella risposta.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* STEP 2 - Se step=base, restituisco solo la ricerca base.
|
||||||
|
*/
|
||||||
|
if ($step === 'base') {
|
||||||
|
echo json_encode([
|
||||||
|
'success' => true,
|
||||||
|
'codice_rapporto' => $codiceRapporto,
|
||||||
|
'id_rapporto' => $rapportoId,
|
||||||
|
'step' => $step,
|
||||||
|
'search_endpoint' => $searchEndpoint,
|
||||||
|
'rapporto_base' => $rapportoBase
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* STEP 3 - Espande SOLO il rapporto trovato.
|
||||||
|
*/
|
||||||
|
$expandValue = $allowedSteps[$step];
|
||||||
|
|
||||||
|
$detailParams = [
|
||||||
|
'$expand' => $expandValue
|
||||||
|
];
|
||||||
|
|
||||||
|
$detailEndpoint = "Rapporto({$rapportoId})?" . http_build_query($detailParams);
|
||||||
|
|
||||||
|
file_put_contents(
|
||||||
|
__DIR__ . '/last_rapporto_by_codice_expand_endpoint.txt',
|
||||||
|
'[' . date('Y-m-d H:i:s') . '] SEARCH: ' . $searchEndpoint . PHP_EOL .
|
||||||
|
'[' . date('Y-m-d H:i:s') . '] DETAIL: ' . $detailEndpoint . PHP_EOL,
|
||||||
|
FILE_APPEND
|
||||||
|
);
|
||||||
|
|
||||||
|
$detailData = $api->get($detailEndpoint);
|
||||||
|
|
||||||
|
file_put_contents(
|
||||||
|
__DIR__ . "/rapporto_codice_{$codiceRapportoSafe}_{$step}.json",
|
||||||
|
json_encode([
|
||||||
|
'search' => $searchData,
|
||||||
|
'detail' => $detailData
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)
|
||||||
|
);
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'success' => true,
|
||||||
|
'codice_rapporto' => $codiceRapporto,
|
||||||
|
'id_rapporto' => $rapportoId,
|
||||||
|
'step' => $step,
|
||||||
|
'search_endpoint' => $searchEndpoint,
|
||||||
|
'detail_endpoint' => $detailEndpoint,
|
||||||
|
'rapporto_base' => $rapportoBase,
|
||||||
|
'data' => $detailData
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
file_put_contents(__DIR__ . '/error_log.txt', date('Y-m-d H:i:s') . ' - ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
|
file_put_contents(
|
||||||
|
__DIR__ . '/error_log.txt',
|
||||||
|
date('Y-m-d H:i:s') . ' - ' . $e->getMessage() . PHP_EOL,
|
||||||
|
FILE_APPEND
|
||||||
|
);
|
||||||
|
|
||||||
http_response_code(500);
|
http_response_code(500);
|
||||||
echo json_encode(['error' => $e->getMessage()]);
|
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,20 @@
|
|||||||
// ── Client data (AJAX Select2, no bulk loading) ──────────────────────
|
// ── Client data (AJAX Select2, no bulk loading) ──────────────────────
|
||||||
|
|
||||||
function formatClientLabel(client) {
|
function formatClientLabel(client) {
|
||||||
return (client.Nominativo || "").trim();
|
const nome = client.Nominativo || client.text || "Nome non disponibile";
|
||||||
|
const id = client.IdCliente || client.id || "";
|
||||||
|
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})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache of resolved client names: id → name
|
// Cache of resolved client names: id → name
|
||||||
@@ -102,7 +115,9 @@
|
|||||||
);
|
);
|
||||||
const json = await resp.json();
|
const json = await resp.json();
|
||||||
const item = (json.results || [])[0];
|
const item = (json.results || [])[0];
|
||||||
if (item) clientNameCache[id] = item.text;
|
if (item) {
|
||||||
|
clientNameCache[id] = formatClientLabel(item);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
/* ignore */
|
/* ignore */
|
||||||
}
|
}
|
||||||
@@ -125,7 +140,12 @@
|
|||||||
return { q: params.term || "", limit: 20 };
|
return { q: params.term || "", limit: 20 };
|
||||||
},
|
},
|
||||||
processResults: function (data) {
|
processResults: function (data) {
|
||||||
return { results: data.results || [] };
|
const results = (data.results || []).map((item) => ({
|
||||||
|
...item,
|
||||||
|
text: formatClientLabel(item),
|
||||||
|
}));
|
||||||
|
|
||||||
|
return { results: results };
|
||||||
},
|
},
|
||||||
cache: true,
|
cache: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,7 +7,26 @@ if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
|
|||||||
$id = intval($_GET['id']);
|
$id = intval($_GET['id']);
|
||||||
$db = DBHandlerSelect::getInstance();
|
$db = DBHandlerSelect::getInstance();
|
||||||
$pdo = $db->getConnection();
|
$pdo = $db->getConnection();
|
||||||
$stmt = $pdo->prepare("SELECT name, header_row, start_column, target_table, sample_xlsx, idclient, clientname, idschema, schemaname, schemajson, xls_headers FROM excel_templates WHERE id = ?");
|
|
||||||
|
$stmt = $pdo->prepare("
|
||||||
|
SELECT
|
||||||
|
name,
|
||||||
|
header_row,
|
||||||
|
start_column,
|
||||||
|
target_table,
|
||||||
|
source_type,
|
||||||
|
sample_xlsx,
|
||||||
|
idclient,
|
||||||
|
clientname,
|
||||||
|
idschema,
|
||||||
|
schemaname,
|
||||||
|
schemajson,
|
||||||
|
xls_headers,
|
||||||
|
api_sample_json,
|
||||||
|
json_nodes
|
||||||
|
FROM excel_templates
|
||||||
|
WHERE id = ?
|
||||||
|
");
|
||||||
$stmt->execute([$id]);
|
$stmt->execute([$id]);
|
||||||
$template = $stmt->fetch(PDO::FETCH_ASSOC);
|
$template = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
@@ -15,13 +34,43 @@ if (!$template) {
|
|||||||
die("Template not found");
|
die("Template not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$sourceType = strtoupper($template['source_type'] ?? 'XLS');
|
||||||
|
if (!in_array($sourceType, ['XLS', 'API', 'PDF'], true)) {
|
||||||
|
$sourceType = 'XLS';
|
||||||
|
}
|
||||||
|
|
||||||
$clientName = $template['clientname'] ?: '';
|
$clientName = $template['clientname'] ?: '';
|
||||||
$schemaName = $template['schemaname'] ?: '';
|
$schemaName = $template['schemaname'] ?: '';
|
||||||
$schemajson = $template['schemajson'] ? json_decode($template['schemajson'], true) : [];
|
$schemajson = $template['schemajson'] ? json_decode($template['schemajson'], true) : [];
|
||||||
$isSchemajsonEmpty = empty(trim($template['schemajson']));
|
$isSchemajsonEmpty = empty(trim($template['schemajson'] ?? ''));
|
||||||
|
|
||||||
// Recupera i campi dalla tabella template_mapping
|
// Recupera i campi dalla tabella template_mapping
|
||||||
$stmt = $pdo->prepare("SELECT id, field_id, excel_column, is_manual, manual_default, auto_value, data_type, is_required, default_value, has_list, length, decimals, min_value, max_value, default_curr_date, tablename, field_label, main_field, is_visible_import, is_visible_parts FROM template_mapping WHERE template_id = ?");
|
$stmt = $pdo->prepare("
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
field_id,
|
||||||
|
excel_column,
|
||||||
|
json_node,
|
||||||
|
is_manual,
|
||||||
|
manual_default,
|
||||||
|
auto_value,
|
||||||
|
data_type,
|
||||||
|
is_required,
|
||||||
|
default_value,
|
||||||
|
has_list,
|
||||||
|
length,
|
||||||
|
decimals,
|
||||||
|
min_value,
|
||||||
|
max_value,
|
||||||
|
default_curr_date,
|
||||||
|
tablename,
|
||||||
|
field_label,
|
||||||
|
main_field,
|
||||||
|
is_visible_import,
|
||||||
|
is_visible_parts
|
||||||
|
FROM template_mapping
|
||||||
|
WHERE template_id = ?
|
||||||
|
");
|
||||||
$stmt->execute([$id]);
|
$stmt->execute([$id]);
|
||||||
$mappings = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
$mappings = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
@@ -37,11 +86,25 @@ $fixedMappings = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|||||||
|
|
||||||
$hasFixedMappings = !empty($fixedMappings);
|
$hasFixedMappings = !empty($fixedMappings);
|
||||||
|
|
||||||
// Recupera le colonne già associate nel database
|
// Recupera le colonne XLS già associate nel database
|
||||||
$usedColumnsFromDB = array_filter(array_column($mappings, 'excel_column'));
|
$usedColumnsFromDB = array_filter(array_column($mappings, 'excel_column'));
|
||||||
|
|
||||||
|
// Recupera i nodi JSON già associati nel database
|
||||||
|
$usedJsonNodesFromDB = array_filter(array_column($mappings, 'json_node'));
|
||||||
|
|
||||||
// Decodifica l'header XLS salvato, se presente
|
// Decodifica l'header XLS salvato, se presente
|
||||||
$xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], true) : [];
|
$xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], true) : [];
|
||||||
|
if (!is_array($xlsHeaders)) {
|
||||||
|
$xlsHeaders = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decodifica nodi JSON API salvati, se presenti
|
||||||
|
$jsonNodes = $template['json_nodes'] ? json_decode($template['json_nodes'], true) : [];
|
||||||
|
if (!is_array($jsonNodes)) {
|
||||||
|
$jsonNodes = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$apiSampleJson = $template['api_sample_json'] ?? '';
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
@@ -163,7 +226,8 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.xls-columns option.used-option {
|
.xls-columns option.used-option,
|
||||||
|
.json-nodes option.used-option {
|
||||||
background-color: #fff3cd;
|
background-color: #fff3cd;
|
||||||
color: #856404;
|
color: #856404;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@@ -176,6 +240,11 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#apiJsonExample {
|
||||||
|
font-family: Consolas, Monaco, monospace;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@@ -195,13 +264,19 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
<p>
|
<p>
|
||||||
Client: <span id="clientName"><?php echo htmlspecialchars($clientName); ?></span> |
|
Client: <span id="clientName"><?php echo htmlspecialchars($clientName); ?></span> |
|
||||||
Schema: <span id="schemaName"><?php echo htmlspecialchars($schemaName); ?></span> |
|
Schema: <span id="schemaName"><?php echo htmlspecialchars($schemaName); ?></span> |
|
||||||
|
Source: <strong><?php echo htmlspecialchars($sourceType); ?></strong>
|
||||||
|
<?php if ($sourceType === 'XLS'): ?>
|
||||||
|
|
|
||||||
Header Row: <span id="headerRow"><?php echo $template['header_row']; ?></span> |
|
Header Row: <span id="headerRow"><?php echo $template['header_row']; ?></span> |
|
||||||
Start Column: <span id="startColumn"><?php echo htmlspecialchars($template['start_column']); ?></span>
|
Start Column: <span id="startColumn"><?php echo htmlspecialchars($template['start_column']); ?></span>
|
||||||
|
<?php endif; ?>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
|
||||||
|
<?php if ($sourceType === 'XLS'): ?>
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label class="form-label">Upload XLS Example:</label>
|
<label class="form-label">Upload XLS Example:</label>
|
||||||
<div class="d-flex align-items-center gap-3">
|
<div class="d-flex align-items-center gap-3">
|
||||||
@@ -219,6 +294,33 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
|
<?php elseif ($sourceType === 'API'): ?>
|
||||||
|
<div class="mb-4">
|
||||||
|
<label class="form-label">API JSON Example:</label>
|
||||||
|
<textarea id="apiJsonExample"
|
||||||
|
class="form-control"
|
||||||
|
rows="12"
|
||||||
|
placeholder='Paste here an example JSON returned by the API'><?php echo htmlspecialchars($apiSampleJson ?? '', ENT_QUOTES, 'UTF-8'); ?></textarea>
|
||||||
|
|
||||||
|
<div class="d-flex align-items-center gap-2 mt-2">
|
||||||
|
<button type="button" id="loadJsonNodesButton" class="btn btn-primary">
|
||||||
|
Load JSON Nodes
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<small id="jsonStatus" class="text-muted">
|
||||||
|
<?php if (!empty($jsonNodes)): ?>
|
||||||
|
✅ JSON nodes already loaded: <?php echo count($jsonNodes); ?>
|
||||||
|
<?php else: ?>
|
||||||
|
No JSON nodes loaded yet.
|
||||||
|
<?php endif; ?>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php elseif ($sourceType === 'PDF'): ?>
|
||||||
|
<div class="alert alert-warning">
|
||||||
|
PDF source type is not implemented yet.
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
@@ -236,15 +338,11 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
<th style="width:45px; text-align:center;">Parts</th>
|
<th style="width:45px; text-align:center;">Parts</th>
|
||||||
<th style="width:320px;">Title</th>
|
<th style="width:320px;">Title</th>
|
||||||
<th style="width:120px;">Type</th>
|
<th style="width:120px;">Type</th>
|
||||||
<th>Mapping</th>
|
<th><?php echo $sourceType === 'API' ? 'JSON Mapping' : 'Mapping'; ?></th>
|
||||||
<th>Default Value</th>
|
<th>Default Value</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tbody id="schemaFieldsBody">
|
<tbody id="schemaFieldsBody">
|
||||||
<?php foreach ($mappings as $mapping): ?>
|
<?php foreach ($mappings as $mapping): ?>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -268,7 +366,6 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
<?php echo ((int)($mapping['is_visible_parts'] ?? 0) === 1) ? 'checked' : ''; ?>>
|
<?php echo ((int)($mapping['is_visible_parts'] ?? 0) === 1) ? 'checked' : ''; ?>>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
<td class="title-col">
|
<td class="title-col">
|
||||||
<?php echo htmlspecialchars($mapping['field_label'] ?? 'N/A'); ?>
|
<?php echo htmlspecialchars($mapping['field_label'] ?? 'N/A'); ?>
|
||||||
<?php if ((int)$mapping['is_required'] === 1): ?>
|
<?php if ((int)$mapping['is_required'] === 1): ?>
|
||||||
@@ -276,7 +373,6 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
<td><?php echo htmlspecialchars($mapping['data_type'] ?? 'N/A'); ?></td>
|
<td><?php echo htmlspecialchars($mapping['data_type'] ?? 'N/A'); ?></td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
@@ -286,9 +382,19 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
$autoValue = $mapping['auto_value'] ?? 'none';
|
$autoValue = $mapping['auto_value'] ?? 'none';
|
||||||
$hasAuto = ($autoValue && $autoValue !== 'none');
|
$hasAuto = ($autoValue && $autoValue !== 'none');
|
||||||
|
|
||||||
$mappingValue = $isSceltaMultipla
|
if ($isSceltaMultipla) {
|
||||||
? 'manual'
|
$mappingValue = 'manual';
|
||||||
: ($hasAuto ? 'auto' : ($mapping['excel_column'] ? 'xls' : ((int)$mapping['is_manual'] === 1 ? 'manual' : '')));
|
} elseif ($hasAuto) {
|
||||||
|
$mappingValue = 'auto';
|
||||||
|
} elseif ($sourceType === 'XLS' && !empty($mapping['excel_column'])) {
|
||||||
|
$mappingValue = 'xls';
|
||||||
|
} elseif ($sourceType === 'API' && !empty($mapping['json_node'])) {
|
||||||
|
$mappingValue = 'json';
|
||||||
|
} elseif ((int)$mapping['is_manual'] === 1) {
|
||||||
|
$mappingValue = 'manual';
|
||||||
|
} else {
|
||||||
|
$mappingValue = '';
|
||||||
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<select class="form-select mapping-select"
|
<select class="form-select mapping-select"
|
||||||
@@ -298,18 +404,34 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
|
|
||||||
<?php if (!$isSceltaMultipla): ?>
|
<?php if (!$isSceltaMultipla): ?>
|
||||||
<option value="">Select Option</option>
|
<option value="">Select Option</option>
|
||||||
|
|
||||||
|
<?php if ($sourceType === 'XLS'): ?>
|
||||||
<option value="xls" <?php echo ($mappingValue === 'xls') ? 'selected' : ''; ?>>Map to XLS Column</option>
|
<option value="xls" <?php echo ($mappingValue === 'xls') ? 'selected' : ''; ?>>Map to XLS Column</option>
|
||||||
|
<?php elseif ($sourceType === 'API'): ?>
|
||||||
|
<option value="json" <?php echo ($mappingValue === 'json') ? 'selected' : ''; ?>>Map to JSON Node</option>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<option value="auto" <?php echo ($mappingValue === 'auto') ? 'selected' : ''; ?>>Auto value</option>
|
<option value="auto" <?php echo ($mappingValue === 'auto') ? 'selected' : ''; ?>>Auto value</option>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<option value="manual" <?php echo ($mappingValue === 'manual') ? 'selected' : ''; ?>>Manual Entry</option>
|
<option value="manual" <?php echo ($mappingValue === 'manual') ? 'selected' : ''; ?>>Manual Entry</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<?php if ($sourceType === 'XLS'): ?>
|
||||||
<select class="form-select xls-columns"
|
<select class="form-select xls-columns"
|
||||||
style="display:<?php echo ($mappingValue === 'xls') ? 'block' : 'none'; ?>"
|
style="display:<?php echo ($mappingValue === 'xls') ? 'block' : 'none'; ?>"
|
||||||
data-id="<?php echo (int)$mapping['id']; ?>"
|
data-id="<?php echo (int)$mapping['id']; ?>"
|
||||||
<?php echo $mapping['excel_column'] ? 'data-current-xls="' . htmlspecialchars($mapping['excel_column']) . '"' : ''; ?>>
|
<?php echo $mapping['excel_column'] ? 'data-current-xls="' . htmlspecialchars($mapping['excel_column'], ENT_QUOTES, 'UTF-8') . '"' : ''; ?>>
|
||||||
</select>
|
</select>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ($sourceType === 'API'): ?>
|
||||||
|
<select class="form-select json-nodes"
|
||||||
|
style="display:<?php echo ($mappingValue === 'json') ? 'block' : 'none'; ?>; margin-top:6px;"
|
||||||
|
data-id="<?php echo (int)$mapping['id']; ?>"
|
||||||
|
<?php echo !empty($mapping['json_node']) ? 'data-current-json="' . htmlspecialchars($mapping['json_node'], ENT_QUOTES, 'UTF-8') . '"' : ''; ?>>
|
||||||
|
</select>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<select class="form-select auto-value-select"
|
<select class="form-select auto-value-select"
|
||||||
style="display:<?php echo ($mappingValue === 'auto') ? 'block' : 'none'; ?>; margin-top:6px;"
|
style="display:<?php echo ($mappingValue === 'auto') ? 'block' : 'none'; ?>; margin-top:6px;"
|
||||||
@@ -321,7 +443,7 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
<option value="export_time" <?php echo ($autoValue === 'export_time') ? 'selected' : ''; ?>>Current time (export)</option>
|
<option value="export_time" <?php echo ($autoValue === 'export_time') ? 'selected' : ''; ?>>Current time (export)</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<?php if (!empty($mapping['excel_column'])): ?>
|
<?php if ($sourceType === 'XLS' && !empty($mapping['excel_column'])): ?>
|
||||||
<span class="mapped-column" style="margin-left:5px;">
|
<span class="mapped-column" style="margin-left:5px;">
|
||||||
(<?php echo htmlspecialchars($mapping['excel_column']); ?>)
|
(<?php echo htmlspecialchars($mapping['excel_column']); ?>)
|
||||||
</span>
|
</span>
|
||||||
@@ -330,6 +452,15 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
style="margin-left:5px;">
|
style="margin-left:5px;">
|
||||||
X
|
X
|
||||||
</button>
|
</button>
|
||||||
|
<?php elseif ($sourceType === 'API' && !empty($mapping['json_node'])): ?>
|
||||||
|
<span class="mapped-json-node" style="margin-left:5px;">
|
||||||
|
(<?php echo htmlspecialchars($mapping['json_node']); ?>)
|
||||||
|
</span>
|
||||||
|
<button class="btn btn-danger btn-sm remove-json"
|
||||||
|
data-id="<?php echo (int)$mapping['id']; ?>"
|
||||||
|
style="margin-left:5px;">
|
||||||
|
X
|
||||||
|
</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
@@ -412,7 +543,6 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
<strong><?php echo htmlspecialchars($fm['fixed_field_key']); ?></strong>
|
<strong><?php echo htmlspecialchars($fm['fixed_field_key']); ?></strong>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
<td><?php echo htmlspecialchars($fm['data_type']); ?></td>
|
<td><?php echo htmlspecialchars($fm['data_type']); ?></td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
@@ -461,8 +591,6 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="mt-4 text-end">
|
<div class="mt-4 text-end">
|
||||||
<a href="templates_dashboard.php" class="btn btn-primary">⬅ Back to Template Dashboard</a>
|
<a href="templates_dashboard.php" class="btn btn-primary">⬅ Back to Template Dashboard</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -479,10 +607,18 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
<?php include('jsinclude.php'); ?>
|
<?php include('jsinclude.php'); ?>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
const sourceType = <?php echo json_encode($sourceType); ?>;
|
||||||
|
|
||||||
let availableXlsColumns = <?php echo json_encode($xlsHeaders); ?> || [];
|
let availableXlsColumns = <?php echo json_encode($xlsHeaders); ?> || [];
|
||||||
let usedColumnsFromDB = <?php echo json_encode($usedColumnsFromDB); ?> || [];
|
let usedColumnsFromDB = <?php echo json_encode($usedColumnsFromDB); ?> || [];
|
||||||
|
|
||||||
document.getElementById('xlsUpload').addEventListener('change', function(event) {
|
let availableJsonNodes = <?php echo json_encode($jsonNodes); ?> || [];
|
||||||
|
let usedJsonNodesFromDB = <?php echo json_encode($usedJsonNodesFromDB); ?> || [];
|
||||||
|
|
||||||
|
const xlsUploadEl = document.getElementById('xlsUpload');
|
||||||
|
|
||||||
|
if (xlsUploadEl) {
|
||||||
|
xlsUploadEl.addEventListener('change', function(event) {
|
||||||
let file = event.target.files[0];
|
let file = event.target.files[0];
|
||||||
if (!file) return;
|
if (!file) return;
|
||||||
|
|
||||||
@@ -511,6 +647,7 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function processXLSX(file) {
|
function processXLSX(file) {
|
||||||
let reader = new FileReader();
|
let reader = new FileReader();
|
||||||
@@ -534,8 +671,14 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
|
|
||||||
// Track merged cell ranges — adjust for column offset
|
// Track merged cell ranges — adjust for column offset
|
||||||
const merges = (sheet['!merges'] || []).map(m => ({
|
const merges = (sheet['!merges'] || []).map(m => ({
|
||||||
s: { r: m.s.r, c: m.s.c - colOffset },
|
s: {
|
||||||
e: { r: m.e.r, c: m.e.c - colOffset }
|
r: m.s.r,
|
||||||
|
c: m.s.c - colOffset
|
||||||
|
},
|
||||||
|
e: {
|
||||||
|
r: m.e.r,
|
||||||
|
c: m.e.c - colOffset
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
console.log('Sheet column offset:', colOffset, '(first col:', String.fromCharCode(65 + colOffset) + ')');
|
console.log('Sheet column offset:', colOffset, '(first col:', String.fromCharCode(65 + colOffset) + ')');
|
||||||
|
|
||||||
@@ -642,7 +785,14 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
matched.push(cellVal);
|
matched.push(cellVal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rowScores.push({ row: r + 1, score, nonEmpty: nonEmptyCount, matched, firstNonEmpty: firstNonEmpty + 1, cells: cellValues });
|
rowScores.push({
|
||||||
|
row: r + 1,
|
||||||
|
score,
|
||||||
|
nonEmpty: nonEmptyCount,
|
||||||
|
matched,
|
||||||
|
firstNonEmpty: firstNonEmpty + 1,
|
||||||
|
cells: cellValues
|
||||||
|
});
|
||||||
if (score > bestScore) {
|
if (score > bestScore) {
|
||||||
bestScore = score;
|
bestScore = score;
|
||||||
bestRow = r;
|
bestRow = r;
|
||||||
@@ -765,16 +915,22 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
let currentValue = select.value || select.dataset.currentXls || '';
|
let currentValue = select.value || select.dataset.currentXls || '';
|
||||||
|
|
||||||
let options = availableXlsColumns
|
let options = availableXlsColumns
|
||||||
.map((col, origIdx) => ({ col, origIdx }))
|
.map((col, origIdx) => ({
|
||||||
.map(({ col, origIdx }) => {
|
col,
|
||||||
|
origIdx
|
||||||
|
}))
|
||||||
|
.map(({
|
||||||
|
col,
|
||||||
|
origIdx
|
||||||
|
}) => {
|
||||||
const clean = col.replace(/[\r\n\t]+/g, ' ').trim();
|
const clean = col.replace(/[\r\n\t]+/g, ' ').trim();
|
||||||
const isEmpty = clean === '';
|
const isEmpty = clean === '';
|
||||||
const colNum = origIdx + 1;
|
const colNum = origIdx + 1;
|
||||||
const val = isEmpty ? `__empty_${colNum}__` : clean;
|
const val = isEmpty ? `__empty_${colNum}__` : clean;
|
||||||
const isUsed = uniqueUsedColumns.includes(col) && col !== currentValue;
|
const isUsed = uniqueUsedColumns.includes(col) && col !== currentValue;
|
||||||
const label = isEmpty
|
const label = isEmpty ?
|
||||||
? `(empty column ${colNum})`
|
`(empty column ${colNum})` :
|
||||||
: (isUsed ? `⚠ ${clean} (already used)` : clean);
|
(isUsed ? `⚠ ${clean} (already used)` : clean);
|
||||||
const isSelected = (isEmpty ? val === currentValue : col === currentValue) ? 'selected' : '';
|
const isSelected = (isEmpty ? val === currentValue : col === currentValue) ? 'selected' : '';
|
||||||
return `<option value="${val}" class="${isUsed ? 'used-option' : ''}" ${isSelected}>${label}</option>`;
|
return `<option value="${val}" class="${isUsed ? 'used-option' : ''}" ${isSelected}>${label}</option>`;
|
||||||
})
|
})
|
||||||
@@ -785,6 +941,88 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function escapeHtmlText(str) {
|
||||||
|
return String(str ?? '')
|
||||||
|
.replaceAll('&', '&')
|
||||||
|
.replaceAll('<', '<')
|
||||||
|
.replaceAll('>', '>')
|
||||||
|
.replaceAll('"', '"')
|
||||||
|
.replaceAll("'", ''');
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeHtmlAttr(str) {
|
||||||
|
return escapeHtmlText(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
function flattenJsonNodes(obj, prefix = '') {
|
||||||
|
let nodes = [];
|
||||||
|
|
||||||
|
if (Array.isArray(obj)) {
|
||||||
|
if (obj.length > 0) {
|
||||||
|
nodes = nodes.concat(flattenJsonNodes(obj[0], prefix ? `${prefix}[]` : '[]'));
|
||||||
|
}
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj !== null && typeof obj === 'object') {
|
||||||
|
Object.keys(obj).forEach(key => {
|
||||||
|
const path = prefix ? `${prefix}.${key}` : key;
|
||||||
|
const value = obj[key];
|
||||||
|
|
||||||
|
if (value !== null && typeof value === 'object') {
|
||||||
|
nodes = nodes.concat(flattenJsonNodes(value, path));
|
||||||
|
} else {
|
||||||
|
nodes.push(path);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateJsonDropdowns() {
|
||||||
|
let usedNodes = Array.from(document.querySelectorAll('select.json-nodes'))
|
||||||
|
.map(select => select.value || select.dataset.currentJson || '')
|
||||||
|
.filter(Boolean)
|
||||||
|
.concat(usedJsonNodesFromDB);
|
||||||
|
|
||||||
|
let uniqueUsedNodes = [...new Set(usedNodes)];
|
||||||
|
|
||||||
|
document.querySelectorAll('select.json-nodes').forEach(select => {
|
||||||
|
let currentValue = select.value || select.dataset.currentJson || '';
|
||||||
|
|
||||||
|
let options = availableJsonNodes
|
||||||
|
.map(node => {
|
||||||
|
const clean = String(node || '').trim();
|
||||||
|
if (!clean) return '';
|
||||||
|
|
||||||
|
const isUsed = uniqueUsedNodes.includes(clean) && clean !== currentValue;
|
||||||
|
const label = isUsed ? `⚠ ${clean} (already used)` : clean;
|
||||||
|
const isSelected = clean === currentValue ? 'selected' : '';
|
||||||
|
|
||||||
|
return `<option value="${escapeHtmlAttr(clean)}" class="${isUsed ? 'used-option' : ''}" ${isSelected}>${escapeHtmlText(label)}</option>`;
|
||||||
|
})
|
||||||
|
.join('');
|
||||||
|
|
||||||
|
select.innerHTML = '<option value="">Select JSON Node</option>' + options;
|
||||||
|
select.dataset.currentJson = currentValue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveJsonNodes(sampleJson, nodes) {
|
||||||
|
return fetch('update_api_json_nodes.php', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
template_id: <?php echo $id; ?>,
|
||||||
|
api_sample_json: sampleJson,
|
||||||
|
json_nodes: JSON.stringify(nodes)
|
||||||
|
})
|
||||||
|
}).then(response => response.json());
|
||||||
|
}
|
||||||
|
|
||||||
function initSelect2ForSchemaDropdowns() {
|
function initSelect2ForSchemaDropdowns() {
|
||||||
// dropdown-select = SceltaMultipla (manual default)
|
// dropdown-select = SceltaMultipla (manual default)
|
||||||
if (window.jQuery && $.fn.select2) {
|
if (window.jQuery && $.fn.select2) {
|
||||||
@@ -858,7 +1096,6 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
let templateId = <?php echo $id; ?>;
|
let templateId = <?php echo $id; ?>;
|
||||||
let schemaId = <?php echo json_encode($template['idschema'] ?? 0); ?>;
|
let schemaId = <?php echo json_encode($template['idschema'] ?? 0); ?>;
|
||||||
@@ -870,6 +1107,72 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
loadingOverlay.innerHTML = '<div>Loading Dropdown Options...</div>';
|
loadingOverlay.innerHTML = '<div>Loading Dropdown Options...</div>';
|
||||||
document.body.appendChild(loadingOverlay);
|
document.body.appendChild(loadingOverlay);
|
||||||
|
|
||||||
|
const loadJsonNodesButton = document.getElementById('loadJsonNodesButton');
|
||||||
|
|
||||||
|
if (loadJsonNodesButton) {
|
||||||
|
loadJsonNodesButton.addEventListener('click', async function() {
|
||||||
|
const textarea = document.getElementById('apiJsonExample');
|
||||||
|
const status = document.getElementById('jsonStatus');
|
||||||
|
|
||||||
|
if (!textarea || !status) {
|
||||||
|
console.error('Missing API JSON textarea or status element.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rawJson = textarea.value.trim();
|
||||||
|
|
||||||
|
if (!rawJson) {
|
||||||
|
status.textContent = '❌ Paste a JSON example first.';
|
||||||
|
status.classList.remove('text-muted');
|
||||||
|
status.classList.add('text-danger');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let parsedJson;
|
||||||
|
|
||||||
|
try {
|
||||||
|
parsedJson = JSON.parse(rawJson);
|
||||||
|
} catch (error) {
|
||||||
|
status.textContent = '❌ Invalid JSON: ' + error.message;
|
||||||
|
status.classList.remove('text-muted');
|
||||||
|
status.classList.add('text-danger');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let nodes = flattenJsonNodes(parsedJson);
|
||||||
|
nodes = [...new Set(nodes)].sort();
|
||||||
|
|
||||||
|
if (!nodes.length) {
|
||||||
|
status.textContent = '❌ No usable JSON nodes found.';
|
||||||
|
status.classList.remove('text-muted');
|
||||||
|
status.classList.add('text-danger');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
availableJsonNodes = nodes;
|
||||||
|
usedJsonNodesFromDB = [];
|
||||||
|
updateJsonDropdowns();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = await saveJsonNodes(rawJson, nodes);
|
||||||
|
|
||||||
|
if (!data.success) {
|
||||||
|
throw new Error(data.message || 'Save failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
status.textContent = `✅ JSON nodes loaded: ${nodes.length}`;
|
||||||
|
status.classList.remove('text-danger');
|
||||||
|
status.classList.add('text-muted');
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
status.textContent = '❌ Error saving JSON nodes: ' + error.message;
|
||||||
|
status.classList.remove('text-muted');
|
||||||
|
status.classList.add('text-danger');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async function populateDropdowns() {
|
async function populateDropdowns() {
|
||||||
const dropdowns = document.querySelectorAll('.dropdown-select');
|
const dropdowns = document.querySelectorAll('.dropdown-select');
|
||||||
if (dropdowns.length === 0) {
|
if (dropdowns.length === 0) {
|
||||||
@@ -982,6 +1285,7 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
tr?.querySelector('.mapping-select')?.getAttribute('data-id');
|
tr?.querySelector('.mapping-select')?.getAttribute('data-id');
|
||||||
|
|
||||||
const xlsSelect = tr?.querySelector('.xls-columns');
|
const xlsSelect = tr?.querySelector('.xls-columns');
|
||||||
|
const jsonSelect = tr?.querySelector('.json-nodes');
|
||||||
|
|
||||||
console.log('[SceltaMultipla change] saving', {
|
console.log('[SceltaMultipla change] saving', {
|
||||||
mappingId,
|
mappingId,
|
||||||
@@ -993,7 +1297,14 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
saveMapping(mappingId, 'manual', el.value, xlsSelect ? xlsSelect.value : null);
|
saveMapping(
|
||||||
|
mappingId,
|
||||||
|
'manual',
|
||||||
|
el.value,
|
||||||
|
xlsSelect ? xlsSelect.value : null,
|
||||||
|
null,
|
||||||
|
jsonSelect ? jsonSelect.value : null
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 2) eventi Select2 (quando Select2 “mangia” il change)
|
// 2) eventi Select2 (quando Select2 “mangia” il change)
|
||||||
@@ -1006,6 +1317,7 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
tr?.querySelector('.mapping-select')?.getAttribute('data-id');
|
tr?.querySelector('.mapping-select')?.getAttribute('data-id');
|
||||||
|
|
||||||
const xlsSelect = tr?.querySelector('.xls-columns');
|
const xlsSelect = tr?.querySelector('.xls-columns');
|
||||||
|
const jsonSelect = tr?.querySelector('.json-nodes');
|
||||||
|
|
||||||
console.log('[SceltaMultipla select2] saving', {
|
console.log('[SceltaMultipla select2] saving', {
|
||||||
mappingId,
|
mappingId,
|
||||||
@@ -1017,11 +1329,17 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
saveMapping(mappingId, 'manual', el.value, xlsSelect ? xlsSelect.value : null);
|
saveMapping(
|
||||||
|
mappingId,
|
||||||
|
'manual',
|
||||||
|
el.value,
|
||||||
|
xlsSelect ? xlsSelect.value : null,
|
||||||
|
null,
|
||||||
|
jsonSelect ? jsonSelect.value : null
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function loadClientAndSchemaNames() {
|
async function loadClientAndSchemaNames() {
|
||||||
if (<?php echo json_encode($template['idclient'] ?? 0); ?> > 0) {
|
if (<?php echo json_encode($template['idclient'] ?? 0); ?> > 0) {
|
||||||
let response = await fetch(`get_clienti.php?id=<?php echo $template['idclient']; ?>`);
|
let response = await fetch(`get_clienti.php?id=<?php echo $template['idclient']; ?>`);
|
||||||
@@ -1084,60 +1402,118 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
if (event.target.classList.contains('mapping-select')) {
|
if (event.target.classList.contains('mapping-select')) {
|
||||||
let tr = event.target.closest('tr');
|
let tr = event.target.closest('tr');
|
||||||
let mappingId = event.target.getAttribute('data-id');
|
let mappingId = event.target.getAttribute('data-id');
|
||||||
|
|
||||||
let xlsSelect = tr.querySelector('.xls-columns');
|
let xlsSelect = tr.querySelector('.xls-columns');
|
||||||
|
let jsonSelect = tr.querySelector('.json-nodes');
|
||||||
let manualInput = tr.querySelector('.manual-default');
|
let manualInput = tr.querySelector('.manual-default');
|
||||||
let autoSelect = tr.querySelector('.auto-value-select');
|
let autoSelect = tr.querySelector('.auto-value-select');
|
||||||
|
|
||||||
let mappedColumn = tr.querySelector('.mapped-column');
|
let mappedColumn = tr.querySelector('.mapped-column');
|
||||||
|
let mappedJsonNode = tr.querySelector('.mapped-json-node');
|
||||||
|
|
||||||
let removeBtn = tr.querySelector('.remove-xls');
|
let removeBtn = tr.querySelector('.remove-xls');
|
||||||
|
let removeJsonBtn = tr.querySelector('.remove-json');
|
||||||
|
|
||||||
if (event.target.value === 'xls') {
|
if (event.target.value === 'xls') {
|
||||||
xlsSelect.style.display = 'block';
|
if (xlsSelect) xlsSelect.style.display = 'block';
|
||||||
|
if (jsonSelect) jsonSelect.style.display = 'none';
|
||||||
if (autoSelect) autoSelect.style.display = 'none';
|
if (autoSelect) autoSelect.style.display = 'none';
|
||||||
|
|
||||||
|
if (manualInput) {
|
||||||
manualInput.style.display = 'none';
|
manualInput.style.display = 'none';
|
||||||
manualInput.value = '';
|
manualInput.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
if (mappedColumn) mappedColumn.style.display = 'none';
|
if (mappedColumn) mappedColumn.style.display = 'none';
|
||||||
if (removeBtn) removeBtn.style.display = xlsSelect.value ? 'inline-block' : 'none';
|
if (mappedJsonNode) mappedJsonNode.style.display = 'none';
|
||||||
|
|
||||||
|
if (removeBtn) removeBtn.style.display = xlsSelect && xlsSelect.value ? 'inline-block' : 'none';
|
||||||
|
if (removeJsonBtn) removeJsonBtn.style.display = 'none';
|
||||||
|
|
||||||
|
} else if (event.target.value === 'json') {
|
||||||
|
if (xlsSelect) xlsSelect.style.display = 'none';
|
||||||
|
if (jsonSelect) jsonSelect.style.display = 'block';
|
||||||
|
if (autoSelect) autoSelect.style.display = 'none';
|
||||||
|
|
||||||
|
if (manualInput) {
|
||||||
|
manualInput.style.display = 'none';
|
||||||
|
manualInput.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mappedColumn) mappedColumn.style.display = 'none';
|
||||||
|
if (mappedJsonNode) mappedJsonNode.style.display = 'none';
|
||||||
|
|
||||||
|
if (removeBtn) removeBtn.style.display = 'none';
|
||||||
|
if (removeJsonBtn) removeJsonBtn.style.display = jsonSelect && jsonSelect.value ? 'inline-block' : 'none';
|
||||||
|
|
||||||
} else if (event.target.value === 'manual') {
|
} else if (event.target.value === 'manual') {
|
||||||
xlsSelect.style.display = 'none';
|
if (xlsSelect) xlsSelect.style.display = 'none';
|
||||||
|
if (jsonSelect) jsonSelect.style.display = 'none';
|
||||||
if (autoSelect) autoSelect.style.display = 'none';
|
if (autoSelect) autoSelect.style.display = 'none';
|
||||||
|
|
||||||
|
if (manualInput) {
|
||||||
manualInput.style.display = 'block';
|
manualInput.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
if (mappedColumn) mappedColumn.style.display = 'none';
|
if (mappedColumn) mappedColumn.style.display = 'none';
|
||||||
|
if (mappedJsonNode) mappedJsonNode.style.display = 'none';
|
||||||
|
|
||||||
if (removeBtn) removeBtn.style.display = 'none';
|
if (removeBtn) removeBtn.style.display = 'none';
|
||||||
|
if (removeJsonBtn) removeJsonBtn.style.display = 'none';
|
||||||
|
|
||||||
} else if (event.target.value === 'auto') {
|
} else if (event.target.value === 'auto') {
|
||||||
|
if (xlsSelect) {
|
||||||
xlsSelect.style.display = 'none';
|
xlsSelect.style.display = 'none';
|
||||||
xlsSelect.value = ''; // libera UI
|
xlsSelect.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonSelect) {
|
||||||
|
jsonSelect.style.display = 'none';
|
||||||
|
jsonSelect.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (manualInput) {
|
||||||
manualInput.style.display = 'none';
|
manualInput.style.display = 'none';
|
||||||
manualInput.value = '';
|
manualInput.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
if (mappedColumn) mappedColumn.style.display = 'none';
|
if (mappedColumn) mappedColumn.style.display = 'none';
|
||||||
|
if (mappedJsonNode) mappedJsonNode.style.display = 'none';
|
||||||
|
|
||||||
if (removeBtn) removeBtn.style.display = 'none';
|
if (removeBtn) removeBtn.style.display = 'none';
|
||||||
|
if (removeJsonBtn) removeJsonBtn.style.display = 'none';
|
||||||
|
|
||||||
if (autoSelect) autoSelect.style.display = 'block';
|
if (autoSelect) autoSelect.style.display = 'block';
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
xlsSelect.style.display = 'none';
|
if (xlsSelect) xlsSelect.style.display = 'none';
|
||||||
|
if (jsonSelect) jsonSelect.style.display = 'none';
|
||||||
if (autoSelect) autoSelect.style.display = 'none';
|
if (autoSelect) autoSelect.style.display = 'none';
|
||||||
|
|
||||||
|
if (manualInput) {
|
||||||
manualInput.style.display = 'none';
|
manualInput.style.display = 'none';
|
||||||
manualInput.value = '';
|
manualInput.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
if (mappedColumn) mappedColumn.style.display = 'none';
|
if (mappedColumn) mappedColumn.style.display = 'none';
|
||||||
|
if (mappedJsonNode) mappedJsonNode.style.display = 'none';
|
||||||
|
|
||||||
if (removeBtn) removeBtn.style.display = 'none';
|
if (removeBtn) removeBtn.style.display = 'none';
|
||||||
|
if (removeJsonBtn) removeJsonBtn.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
saveMapping(
|
saveMapping(
|
||||||
mappingId,
|
mappingId,
|
||||||
event.target.value,
|
event.target.value,
|
||||||
manualInput.value,
|
manualInput ? manualInput.value : '',
|
||||||
xlsSelect.value,
|
xlsSelect ? xlsSelect.value : null,
|
||||||
autoSelect ? autoSelect.value : null
|
autoSelect ? autoSelect.value : null,
|
||||||
|
jsonSelect ? jsonSelect.value : null
|
||||||
);
|
);
|
||||||
updateXlsDropdowns();
|
|
||||||
|
if (sourceType === 'XLS') updateXlsDropdowns();
|
||||||
|
if (sourceType === 'API') updateJsonDropdowns();
|
||||||
|
|
||||||
} else if (event.target.classList.contains('main-field-checkbox')) {
|
} else if (event.target.classList.contains('main-field-checkbox')) {
|
||||||
const checkbox = event.target;
|
const checkbox = event.target;
|
||||||
const mappingId = checkbox.dataset.mappingId;
|
const mappingId = checkbox.dataset.mappingId;
|
||||||
@@ -1236,6 +1612,7 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
document.querySelectorAll('.main-field-checkbox').forEach(cb => {
|
document.querySelectorAll('.main-field-checkbox').forEach(cb => {
|
||||||
cb.dataset.originalChecked = cb.checked;
|
cb.dataset.originalChecked = cb.checked;
|
||||||
});
|
});
|
||||||
|
|
||||||
// AUTO VALUE select change -> save auto_value
|
// AUTO VALUE select change -> save auto_value
|
||||||
document.getElementById('schemaFieldsBody').addEventListener('change', function(event) {
|
document.getElementById('schemaFieldsBody').addEventListener('change', function(event) {
|
||||||
if (!event.target.classList.contains('auto-value-select')) return;
|
if (!event.target.classList.contains('auto-value-select')) return;
|
||||||
@@ -1244,6 +1621,7 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
const mappingId = event.target.getAttribute('data-id');
|
const mappingId = event.target.getAttribute('data-id');
|
||||||
|
|
||||||
const xlsSelect = tr.querySelector('.xls-columns');
|
const xlsSelect = tr.querySelector('.xls-columns');
|
||||||
|
const jsonSelect = tr.querySelector('.json-nodes');
|
||||||
const manualInput = tr.querySelector('.manual-default');
|
const manualInput = tr.querySelector('.manual-default');
|
||||||
|
|
||||||
saveMapping(
|
saveMapping(
|
||||||
@@ -1251,9 +1629,11 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
'auto',
|
'auto',
|
||||||
manualInput ? manualInput.value : '',
|
manualInput ? manualInput.value : '',
|
||||||
xlsSelect ? xlsSelect.value : null,
|
xlsSelect ? xlsSelect.value : null,
|
||||||
event.target.value
|
event.target.value,
|
||||||
|
jsonSelect ? jsonSelect.value : null
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('schemaFieldsBody').addEventListener('change', function(event) {
|
document.getElementById('schemaFieldsBody').addEventListener('change', function(event) {
|
||||||
if (event.target.classList.contains('xls-columns')) {
|
if (event.target.classList.contains('xls-columns')) {
|
||||||
let tr = event.target.closest('tr');
|
let tr = event.target.closest('tr');
|
||||||
@@ -1286,7 +1666,7 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
mappingSelect.value = '';
|
mappingSelect.value = '';
|
||||||
if (mappedColumn) mappedColumn.style.display = 'none';
|
if (mappedColumn) mappedColumn.style.display = 'none';
|
||||||
e.target.style.display = 'none';
|
e.target.style.display = 'none';
|
||||||
saveMapping(mappingId, '', '', null);
|
saveMapping(mappingId, '', '', null, null, null);
|
||||||
updateXlsDropdowns();
|
updateXlsDropdowns();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1304,21 +1684,75 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
if (mappingSelect && mappingSelect.value !== 'xls') {
|
if (mappingSelect && mappingSelect.value !== 'xls') {
|
||||||
return; // non salvare XLS se non siamo in modalità XLS
|
return; // non salvare XLS se non siamo in modalità XLS
|
||||||
}
|
}
|
||||||
saveMapping(mappingId, 'xls', manualInput.value, event.target.value);
|
saveMapping(mappingId, 'xls', manualInput ? manualInput.value : '', event.target.value, autoSelect ? autoSelect.value : null, null);
|
||||||
updateXlsDropdowns();
|
updateXlsDropdowns();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.getElementById('schemaFieldsBody').addEventListener('change', function(event) {
|
||||||
|
if (event.target.classList.contains('json-nodes')) {
|
||||||
|
let tr = event.target.closest('tr');
|
||||||
|
let mappingId = event.target.getAttribute('data-id');
|
||||||
|
let manualInput = tr.querySelector('.manual-default');
|
||||||
|
let mappedJsonNode = tr.querySelector('.mapped-json-node');
|
||||||
|
let removeJsonBtn = tr.querySelector('.remove-json');
|
||||||
|
|
||||||
|
if (!mappedJsonNode) {
|
||||||
|
mappedJsonNode = document.createElement('span');
|
||||||
|
mappedJsonNode.className = 'mapped-json-node';
|
||||||
|
mappedJsonNode.style.marginLeft = '5px';
|
||||||
|
tr.querySelector('td:nth-child(6)').appendChild(mappedJsonNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!removeJsonBtn) {
|
||||||
|
removeJsonBtn = document.createElement('button');
|
||||||
|
removeJsonBtn.className = 'btn btn-danger btn-sm remove-json';
|
||||||
|
removeJsonBtn.textContent = 'X';
|
||||||
|
removeJsonBtn.style.marginLeft = '5px';
|
||||||
|
removeJsonBtn.setAttribute('data-id', mappingId);
|
||||||
|
tr.querySelector('td:nth-child(6)').appendChild(removeJsonBtn);
|
||||||
|
}
|
||||||
|
|
||||||
|
mappedJsonNode.textContent = event.target.value ? `(${event.target.value})` : '';
|
||||||
|
mappedJsonNode.style.display = event.target.value ? 'inline' : 'none';
|
||||||
|
removeJsonBtn.style.display = event.target.value ? 'inline-block' : 'none';
|
||||||
|
|
||||||
|
const mappingSelect = tr.querySelector('.mapping-select');
|
||||||
|
if (mappingSelect && mappingSelect.value !== 'json') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
saveMapping(
|
||||||
|
mappingId,
|
||||||
|
'json',
|
||||||
|
manualInput ? manualInput.value : '',
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
event.target.value
|
||||||
|
);
|
||||||
|
|
||||||
|
updateJsonDropdowns();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
document.getElementById('schemaFieldsBody').addEventListener('change', function(event) {
|
document.getElementById('schemaFieldsBody').addEventListener('change', function(event) {
|
||||||
if (event.target.classList.contains('manual-default') && event.target.tagName === 'SELECT') {
|
if (event.target.classList.contains('manual-default') && event.target.tagName === 'SELECT') {
|
||||||
let tr = event.target.closest('tr');
|
let tr = event.target.closest('tr');
|
||||||
let mappingId = event.target.getAttribute('data-id');
|
let mappingId = event.target.getAttribute('data-id');
|
||||||
let xlsSelect = tr.querySelector('.xls-columns');
|
let xlsSelect = tr.querySelector('.xls-columns');
|
||||||
|
let jsonSelect = tr.querySelector('.json-nodes');
|
||||||
console.log("Manual default dropdown changed:", {
|
console.log("Manual default dropdown changed:", {
|
||||||
id: mappingId,
|
id: mappingId,
|
||||||
value: event.target.value
|
value: event.target.value
|
||||||
});
|
});
|
||||||
saveMapping(mappingId, 'manual', event.target.value, xlsSelect.value);
|
saveMapping(
|
||||||
|
mappingId,
|
||||||
|
'manual',
|
||||||
|
event.target.value,
|
||||||
|
xlsSelect ? xlsSelect.value : null,
|
||||||
|
null,
|
||||||
|
jsonSelect ? jsonSelect.value : null
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1327,11 +1761,19 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
let tr = event.target.closest('tr');
|
let tr = event.target.closest('tr');
|
||||||
let mappingId = tr.querySelector('.mapping-select').getAttribute('data-id');
|
let mappingId = tr.querySelector('.mapping-select').getAttribute('data-id');
|
||||||
let xlsSelect = tr.querySelector('.xls-columns');
|
let xlsSelect = tr.querySelector('.xls-columns');
|
||||||
|
let jsonSelect = tr.querySelector('.json-nodes');
|
||||||
console.log("Manual default input changed:", {
|
console.log("Manual default input changed:", {
|
||||||
id: mappingId,
|
id: mappingId,
|
||||||
value: event.target.value
|
value: event.target.value
|
||||||
});
|
});
|
||||||
saveMapping(mappingId, 'manual', event.target.value, xlsSelect.value);
|
saveMapping(
|
||||||
|
mappingId,
|
||||||
|
'manual',
|
||||||
|
event.target.value,
|
||||||
|
xlsSelect ? xlsSelect.value : null,
|
||||||
|
null,
|
||||||
|
jsonSelect ? jsonSelect.value : null
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1350,17 +1792,49 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
console.log("Removing XLS mapping:", {
|
console.log("Removing XLS mapping:", {
|
||||||
id: mappingId
|
id: mappingId
|
||||||
});
|
});
|
||||||
saveMapping(mappingId, '', '', null);
|
saveMapping(mappingId, '', '', null, null, null);
|
||||||
updateXlsDropdowns();
|
updateXlsDropdowns();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function saveMapping(mappingId, mappingType, defaultValue, excelColumn, autoValue) {
|
document.getElementById('schemaFieldsBody').addEventListener('click', function(event) {
|
||||||
|
if (event.target.classList.contains('remove-json')) {
|
||||||
|
let mappingId = event.target.getAttribute('data-id');
|
||||||
|
let tr = event.target.closest('tr');
|
||||||
|
|
||||||
|
let jsonSelect = tr.querySelector('.json-nodes');
|
||||||
|
let mappingSelect = tr.querySelector('.mapping-select');
|
||||||
|
let mappedJsonNode = tr.querySelector('.mapped-json-node');
|
||||||
|
|
||||||
|
if (jsonSelect) {
|
||||||
|
jsonSelect.value = '';
|
||||||
|
jsonSelect.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mappingSelect) {
|
||||||
|
mappingSelect.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mappedJsonNode) {
|
||||||
|
mappedJsonNode.textContent = '';
|
||||||
|
mappedJsonNode.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
event.target.style.display = 'none';
|
||||||
|
|
||||||
|
saveMapping(mappingId, '', '', null, null, null);
|
||||||
|
updateJsonDropdowns();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function saveMapping(mappingId, mappingType, defaultValue, excelColumn, autoValue, jsonNode) {
|
||||||
console.log("Saving mapping:", {
|
console.log("Saving mapping:", {
|
||||||
id: mappingId,
|
id: mappingId,
|
||||||
mapping_type: mappingType,
|
mapping_type: mappingType,
|
||||||
excel_column: excelColumn,
|
excel_column: excelColumn,
|
||||||
manual_default: defaultValue
|
json_node: jsonNode,
|
||||||
|
manual_default: defaultValue,
|
||||||
|
auto_value: autoValue
|
||||||
});
|
});
|
||||||
fetch('save_mapping_json.php', {
|
fetch('save_mapping_json.php', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -1371,6 +1845,7 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
id: mappingId,
|
id: mappingId,
|
||||||
mapping_type: mappingType,
|
mapping_type: mappingType,
|
||||||
excel_column: mappingType === 'xls' ? excelColumn : null,
|
excel_column: mappingType === 'xls' ? excelColumn : null,
|
||||||
|
json_node: mappingType === 'json' ? jsonNode : null,
|
||||||
manual_default: mappingType === 'manual' ? defaultValue : null,
|
manual_default: mappingType === 'manual' ? defaultValue : null,
|
||||||
auto_value: mappingType === 'auto' ? (autoValue || 'none') : 'none',
|
auto_value: mappingType === 'auto' ? (autoValue || 'none') : 'none',
|
||||||
tablename: "<?php echo $template['target_table']; ?>"
|
tablename: "<?php echo $template['target_table']; ?>"
|
||||||
@@ -1379,11 +1854,17 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
.then(data => {
|
.then(data => {
|
||||||
console.log("Save response:", data);
|
console.log("Save response:", data);
|
||||||
if (!data.success) console.error("❌ Error saving mapping:", data.message);
|
if (!data.success) console.error("❌ Error saving mapping:", data.message);
|
||||||
if (data.success && excelColumn) {
|
if (data.success && mappingType === 'xls' && excelColumn) {
|
||||||
usedColumnsFromDB = usedColumnsFromDB.filter(col => col !== excelColumn);
|
usedColumnsFromDB = usedColumnsFromDB.filter(col => col !== excelColumn);
|
||||||
usedColumnsFromDB.push(excelColumn);
|
usedColumnsFromDB.push(excelColumn);
|
||||||
updateXlsDropdowns();
|
updateXlsDropdowns();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.success && mappingType === 'json' && jsonNode) {
|
||||||
|
usedJsonNodesFromDB = usedJsonNodesFromDB.filter(node => node !== jsonNode);
|
||||||
|
usedJsonNodesFromDB.push(jsonNode);
|
||||||
|
updateJsonDropdowns();
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch(error => console.error("❌ Fetch error:", error));
|
.catch(error => console.error("❌ Fetch error:", error));
|
||||||
}
|
}
|
||||||
@@ -1478,8 +1959,6 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
}).join('');
|
}).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Button: Add Fixed Fields
|
// Button: Add Fixed Fields
|
||||||
const btnAddFixedFields = document.getElementById('btnAddFixedFields');
|
const btnAddFixedFields = document.getElementById('btnAddFixedFields');
|
||||||
if (btnAddFixedFields) {
|
if (btnAddFixedFields) {
|
||||||
@@ -1508,8 +1987,6 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
renderFixedRows(data.rows);
|
renderFixedRows(data.rows);
|
||||||
await fillFixedDropdowns();
|
await fillFixedDropdowns();
|
||||||
initSelect2ForFixedDropdowns();
|
initSelect2ForFixedDropdowns();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fixedStatus('✅ Fixed fields created');
|
fixedStatus('✅ Fixed fields created');
|
||||||
@@ -1581,7 +2058,6 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Autosave: manual_default (debounce)
|
// Autosave: manual_default (debounce)
|
||||||
let fixedTimer = null;
|
let fixedTimer = null;
|
||||||
document.addEventListener('input', (e) => {
|
document.addEventListener('input', (e) => {
|
||||||
@@ -1616,8 +2092,13 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
}, 350);
|
}, 350);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (sourceType === 'XLS' && availableXlsColumns.length) {
|
||||||
|
updateXlsDropdowns();
|
||||||
|
}
|
||||||
|
|
||||||
if (availableXlsColumns.length) updateXlsDropdowns();
|
if (sourceType === 'API' && availableJsonNodes.length) {
|
||||||
|
updateJsonDropdowns();
|
||||||
|
}
|
||||||
|
|
||||||
fillFixedDropdowns().then(() => {
|
fillFixedDropdowns().then(() => {
|
||||||
initSelect2ForFixedDropdowns();
|
initSelect2ForFixedDropdowns();
|
||||||
@@ -1765,7 +2246,6 @@ $xlsHeaders = $template['xls_headers'] ? json_decode($template['xls_headers'], t
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
|
||||||
|
require_once dirname(__FILE__) . '/class/VisualLimsApiClient.class.php';
|
||||||
|
|
||||||
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
|
||||||
|
ini_set('display_errors', '0');
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
set_time_limit(20);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$api = VisualLimsApiClient::getInstance();
|
||||||
|
|
||||||
|
$start = microtime(true);
|
||||||
|
|
||||||
|
// Chiamata minima: 1 solo record, 1 solo campo
|
||||||
|
$data = $api->get('Rapporto', [
|
||||||
|
'$top' => 1,
|
||||||
|
'$select' => 'IdRapporto'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$elapsed = round(microtime(true) - $start, 3);
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'success' => true,
|
||||||
|
'elapsed_seconds' => $elapsed,
|
||||||
|
'data' => $data
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
http_response_code(500);
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||||
|
}
|
||||||
@@ -16,9 +16,11 @@ if (!$data || !isset($data['id'])) {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$mappingId = $data['id'];
|
$mappingId = (int)$data['id'];
|
||||||
$mappingType = $data['mapping_type'] ?? '';
|
$mappingType = $data['mapping_type'] ?? '';
|
||||||
|
|
||||||
$excelColumn = $data['excel_column'] ?? null;
|
$excelColumn = $data['excel_column'] ?? null;
|
||||||
|
$jsonNode = $data['json_node'] ?? null;
|
||||||
$manualDefault = $data['manual_default'] ?? null;
|
$manualDefault = $data['manual_default'] ?? null;
|
||||||
|
|
||||||
$autoValue = $data['auto_value'] ?? 'none';
|
$autoValue = $data['auto_value'] ?? 'none';
|
||||||
@@ -26,7 +28,7 @@ $tablename = $data['tablename'] ?? '';
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Normalize mapping type
|
// Normalize mapping type
|
||||||
$allowedTypes = ['', 'xls', 'manual', 'auto'];
|
$allowedTypes = ['', 'xls', 'json', 'manual', 'auto'];
|
||||||
if (!in_array($mappingType, $allowedTypes, true)) {
|
if (!in_array($mappingType, $allowedTypes, true)) {
|
||||||
echo json_encode(["success" => false, "message" => "Invalid mapping_type"]);
|
echo json_encode(["success" => false, "message" => "Invalid mapping_type"]);
|
||||||
exit;
|
exit;
|
||||||
@@ -41,28 +43,44 @@ try {
|
|||||||
// Decide what to persist based on mapping_type
|
// Decide what to persist based on mapping_type
|
||||||
$isManual = 0;
|
$isManual = 0;
|
||||||
$excelToSave = null;
|
$excelToSave = null;
|
||||||
|
$jsonNodeToSave = null;
|
||||||
$manualToSave = null;
|
$manualToSave = null;
|
||||||
$autoToSave = 'none';
|
$autoToSave = 'none';
|
||||||
|
|
||||||
if ($mappingType === 'xls') {
|
if ($mappingType === 'xls') {
|
||||||
|
|
||||||
$isManual = 0;
|
$isManual = 0;
|
||||||
$excelToSave = $excelColumn ?: null;
|
$excelToSave = $excelColumn ?: null;
|
||||||
|
$jsonNodeToSave = null;
|
||||||
|
$manualToSave = null;
|
||||||
|
$autoToSave = 'none';
|
||||||
|
} elseif ($mappingType === 'json') {
|
||||||
|
|
||||||
|
$isManual = 0;
|
||||||
|
$excelToSave = null;
|
||||||
|
$jsonNodeToSave = $jsonNode ?: null;
|
||||||
$manualToSave = null;
|
$manualToSave = null;
|
||||||
$autoToSave = 'none';
|
$autoToSave = 'none';
|
||||||
} elseif ($mappingType === 'manual') {
|
} elseif ($mappingType === 'manual') {
|
||||||
|
|
||||||
$isManual = 1;
|
$isManual = 1;
|
||||||
$excelToSave = null;
|
$excelToSave = null;
|
||||||
|
$jsonNodeToSave = null;
|
||||||
$manualToSave = $manualDefault;
|
$manualToSave = $manualDefault;
|
||||||
$autoToSave = 'none';
|
$autoToSave = 'none';
|
||||||
} elseif ($mappingType === 'auto') {
|
} elseif ($mappingType === 'auto') {
|
||||||
|
|
||||||
$isManual = 0;
|
$isManual = 0;
|
||||||
$excelToSave = null;
|
$excelToSave = null;
|
||||||
|
$jsonNodeToSave = null;
|
||||||
$manualToSave = null;
|
$manualToSave = null;
|
||||||
$autoToSave = $autoValue ?: 'none';
|
$autoToSave = $autoValue ?: 'none';
|
||||||
} else {
|
} else {
|
||||||
// reset
|
|
||||||
|
// Reset mapping
|
||||||
$isManual = 0;
|
$isManual = 0;
|
||||||
$excelToSave = null;
|
$excelToSave = null;
|
||||||
|
$jsonNodeToSave = null;
|
||||||
$manualToSave = null;
|
$manualToSave = null;
|
||||||
$autoToSave = 'none';
|
$autoToSave = 'none';
|
||||||
}
|
}
|
||||||
@@ -72,12 +90,20 @@ try {
|
|||||||
SET
|
SET
|
||||||
is_manual = ?,
|
is_manual = ?,
|
||||||
excel_column = ?,
|
excel_column = ?,
|
||||||
|
json_node = ?,
|
||||||
manual_default = ?,
|
manual_default = ?,
|
||||||
auto_value = ?
|
auto_value = ?
|
||||||
WHERE id = ?
|
WHERE id = ?
|
||||||
");
|
");
|
||||||
|
|
||||||
$result = $stmt->execute([$isManual, $excelToSave, $manualToSave, $autoToSave, $mappingId]);
|
$result = $stmt->execute([
|
||||||
|
$isManual,
|
||||||
|
$excelToSave,
|
||||||
|
$jsonNodeToSave,
|
||||||
|
$manualToSave,
|
||||||
|
$autoToSave,
|
||||||
|
$mappingId
|
||||||
|
]);
|
||||||
|
|
||||||
if (!$result) {
|
if (!$result) {
|
||||||
echo json_encode(["success" => false, "message" => "Database update failed"]);
|
echo json_encode(["success" => false, "message" => "Database update failed"]);
|
||||||
@@ -88,15 +114,17 @@ try {
|
|||||||
"success" => true,
|
"success" => true,
|
||||||
"message" => "Mapping updated successfully",
|
"message" => "Mapping updated successfully",
|
||||||
"saved" => [
|
"saved" => [
|
||||||
"id" => (int)$mappingId,
|
"id" => $mappingId,
|
||||||
"mapping_type" => $mappingType,
|
"mapping_type" => $mappingType,
|
||||||
"is_manual" => $isManual,
|
"is_manual" => $isManual,
|
||||||
"excel_column" => $excelToSave,
|
"excel_column" => $excelToSave,
|
||||||
|
"json_node" => $jsonNodeToSave,
|
||||||
"manual_default" => $manualToSave,
|
"manual_default" => $manualToSave,
|
||||||
"auto_value" => $autoToSave
|
"auto_value" => $autoToSave
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
} catch (Exception $e) {
|
} catch (Throwable $e) {
|
||||||
echo json_encode(["success" => false, "message" => "Error: " . $e->getMessage()]);
|
echo json_encode(["success" => false, "message" => "Error: " . $e->getMessage()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit;
|
exit;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -2,7 +2,12 @@
|
|||||||
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
|
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
|
||||||
require_once __DIR__ . '/class/db-functions.php';
|
require_once __DIR__ . '/class/db-functions.php';
|
||||||
include dirname(__DIR__) . '/../extra/auth.php';
|
include dirname(__DIR__) . '/../extra/auth.php';
|
||||||
if (!Auth::check()) { http_response_code(401); echo json_encode(['error' => 'Unauthorized']); exit; }
|
|
||||||
|
if (!Auth::check()) {
|
||||||
|
http_response_code(401);
|
||||||
|
echo json_encode(['error' => 'Unauthorized']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
require_once __DIR__ . '/class/VisualLimsApiClient.class.php';
|
require_once __DIR__ . '/class/VisualLimsApiClient.class.php';
|
||||||
|
|
||||||
@@ -14,44 +19,95 @@ $q = mb_strtolower(trim($_GET['q'] ?? ''));
|
|||||||
$limit = max(1, min(50, intval($_GET['limit'] ?? 20)));
|
$limit = max(1, min(50, intval($_GET['limit'] ?? 20)));
|
||||||
$id = isset($_GET['id']) ? intval($_GET['id']) : null;
|
$id = isset($_GET['id']) ? intval($_GET['id']) : null;
|
||||||
|
|
||||||
|
function formatClientLabel(array $client): string
|
||||||
|
{
|
||||||
|
$name = trim($client['Nominativo'] ?? '');
|
||||||
|
$id = trim((string)($client['IdCliente'] ?? ''));
|
||||||
|
$code = trim((string)($client['CodiceCliente'] ?? ''));
|
||||||
|
|
||||||
|
$parts = explode('_', $code);
|
||||||
|
$suffix = trim($parts[1] ?? '');
|
||||||
|
|
||||||
|
if ($suffix === '' && $code !== '') {
|
||||||
|
$suffix = substr($code, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($suffix === '') {
|
||||||
|
$suffix = '--';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $name . ' - ' . $suffix . ' (ID: ' . $id . ')';
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Load from cache or API
|
// Load from cache or API
|
||||||
$cacheFile = __DIR__ . '/cache/clienti.json';
|
$cacheFile = __DIR__ . '/cache/clienti.json';
|
||||||
|
|
||||||
if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < 3600)) {
|
if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < 3600)) {
|
||||||
$data = json_decode(file_get_contents($cacheFile), true);
|
$data = json_decode(file_get_contents($cacheFile), true);
|
||||||
} else {
|
} else {
|
||||||
$api = VisualLimsApiClient::getInstance();
|
$api = VisualLimsApiClient::getInstance();
|
||||||
|
|
||||||
$params = [
|
$params = [
|
||||||
'$select' => 'IdCliente,Nominativo,CodiceCliente',
|
'$select' => 'IdCliente,Nominativo,CodiceCliente',
|
||||||
'$orderby' => 'Nominativo asc'
|
'$orderby' => 'Nominativo asc'
|
||||||
];
|
];
|
||||||
|
|
||||||
$data = $api->get("Cliente?" . http_build_query($params));
|
$data = $api->get("Cliente?" . http_build_query($params));
|
||||||
if (!is_dir(__DIR__ . '/cache')) mkdir(__DIR__ . '/cache', 0777, true);
|
|
||||||
|
if (!is_dir(__DIR__ . '/cache')) {
|
||||||
|
mkdir(__DIR__ . '/cache', 0777, true);
|
||||||
|
}
|
||||||
|
|
||||||
file_put_contents($cacheFile, json_encode($data));
|
file_put_contents($cacheFile, json_encode($data));
|
||||||
}
|
}
|
||||||
|
|
||||||
$clients = $data['value'] ?? [];
|
$clients = $data['value'] ?? [];
|
||||||
|
|
||||||
// If requesting by specific ID (for loading selected value)
|
// If requesting by specific ID, used for loading selected value
|
||||||
if ($id !== null) {
|
if ($id !== null) {
|
||||||
foreach ($clients as $c) {
|
foreach ($clients as $c) {
|
||||||
if ((int)$c['IdCliente'] === $id) {
|
if ((int)$c['IdCliente'] === $id) {
|
||||||
echo json_encode(['results' => [['id' => $c['IdCliente'], 'text' => trim($c['Nominativo'] ?? '')]]]);
|
echo json_encode([
|
||||||
|
'results' => [[
|
||||||
|
'id' => $c['IdCliente'],
|
||||||
|
'text' => formatClientLabel($c),
|
||||||
|
'IdCliente' => $c['IdCliente'],
|
||||||
|
'Nominativo' => trim($c['Nominativo'] ?? ''),
|
||||||
|
'CodiceCliente' => trim($c['CodiceCliente'] ?? '')
|
||||||
|
]]
|
||||||
|
]);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
echo json_encode(['results' => []]);
|
echo json_encode(['results' => []]);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search by query
|
// Search by query
|
||||||
$results = [];
|
$results = [];
|
||||||
|
|
||||||
foreach ($clients as $c) {
|
foreach ($clients as $c) {
|
||||||
$name = trim($c['Nominativo'] ?? '');
|
$name = trim($c['Nominativo'] ?? '');
|
||||||
$code = trim($c['CodiceCliente'] ?? '');
|
$code = trim($c['CodiceCliente'] ?? '');
|
||||||
if ($q === '' || mb_strpos(mb_strtolower($name), $q) !== false || mb_strpos(mb_strtolower($code), $q) !== false) {
|
|
||||||
$results[] = ['id' => $c['IdCliente'], 'text' => $name];
|
if (
|
||||||
if (count($results) >= $limit) break;
|
$q === '' ||
|
||||||
|
mb_strpos(mb_strtolower($name), $q) !== false ||
|
||||||
|
mb_strpos(mb_strtolower($code), $q) !== false
|
||||||
|
) {
|
||||||
|
$results[] = [
|
||||||
|
'id' => $c['IdCliente'],
|
||||||
|
'text' => formatClientLabel($c),
|
||||||
|
'IdCliente' => $c['IdCliente'],
|
||||||
|
'Nominativo' => $name,
|
||||||
|
'CodiceCliente' => $code
|
||||||
|
];
|
||||||
|
|
||||||
|
if (count($results) >= $limit) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
|
||||||
|
require_once dirname(__FILE__) . '/class/VisualLimsApiClient.class.php';
|
||||||
|
|
||||||
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
|
||||||
|
ini_set('display_errors', '0');
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$api = VisualLimsApiClient::getInstance();
|
||||||
|
|
||||||
|
// Esempio: search_rapporto_min.php?codice=2621716
|
||||||
|
$codice = trim($_GET['codice'] ?? '');
|
||||||
|
|
||||||
|
if ($codice === '') {
|
||||||
|
throw new Exception("Parametro codice mancante. Usa ?codice=2621716");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Minimal:
|
||||||
|
* - niente expand
|
||||||
|
* - max 5 record
|
||||||
|
* - pochi campi
|
||||||
|
*
|
||||||
|
* Se il campo Codice non è quello giusto, sotto proviamo anche CodiceRapporto.
|
||||||
|
*/
|
||||||
|
$attempts = [];
|
||||||
|
|
||||||
|
$filters = [
|
||||||
|
'Codice' => "Codice eq '{$codice}'",
|
||||||
|
'CodiceRapporto' => "CodiceRapporto eq '{$codice}'",
|
||||||
|
'Numero' => "Numero eq '{$codice}'"
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($filters as $label => $filter) {
|
||||||
|
try {
|
||||||
|
$data = $api->get('Rapporto', [
|
||||||
|
'$filter' => $filter,
|
||||||
|
'$top' => 5,
|
||||||
|
'$select' => 'IdRapporto,Codice,CodiceRapporto,Numero,Data,Versione,Cliente'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$attempts[$label] = [
|
||||||
|
'success' => true,
|
||||||
|
'filter' => $filter,
|
||||||
|
'records' => isset($data['value']) && is_array($data['value']) ? count($data['value']) : null,
|
||||||
|
'data' => $data
|
||||||
|
];
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$attempts[$label] = [
|
||||||
|
'success' => false,
|
||||||
|
'filter' => $filter,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'success' => true,
|
||||||
|
'input_codice' => $codice,
|
||||||
|
'attempts' => $attempts
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
http_response_code(500);
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||||
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
<?php
|
||||||
|
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
|
||||||
|
require_once dirname(__FILE__) . '/class/VisualLimsApiClient.class.php';
|
||||||
|
|
||||||
|
ini_set('display_errors', '1');
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
set_time_limit(60);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uso: get_pdf.php?id=591749
|
||||||
|
*/
|
||||||
|
|
||||||
|
try {
|
||||||
|
$api = VisualLimsApiClient::getInstance();
|
||||||
|
|
||||||
|
$idRapportoFile = isset($_GET['id']) ? intval($_GET['id']) : 0;
|
||||||
|
|
||||||
|
if (!$idRapportoFile) {
|
||||||
|
throw new Exception("Parametro id mancante. Usa ?id=591749");
|
||||||
|
}
|
||||||
|
|
||||||
|
// STEP 1: leggi metadati entita
|
||||||
|
$entityData = $api->get("RapportoFile(" . $idRapportoFile . ")");
|
||||||
|
|
||||||
|
$pdfBody = null;
|
||||||
|
$strategyUsed = null;
|
||||||
|
$debugLog = array();
|
||||||
|
|
||||||
|
// Strategia A - campo FileContent base64
|
||||||
|
if (!empty($entityData['FileContent'])) {
|
||||||
|
$decoded = base64_decode($entityData['FileContent'], true);
|
||||||
|
if ($decoded !== false && substr($decoded, 0, 4) === '%PDF') {
|
||||||
|
$pdfBody = $decoded;
|
||||||
|
$strategyUsed = 'A: FileContent base64';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strategia B - campo Contenuto base64
|
||||||
|
if (!$pdfBody && !empty($entityData['Contenuto'])) {
|
||||||
|
$decoded = base64_decode($entityData['Contenuto'], true);
|
||||||
|
if ($decoded !== false && substr($decoded, 0, 4) === '%PDF') {
|
||||||
|
$pdfBody = $decoded;
|
||||||
|
$strategyUsed = 'B: Contenuto base64';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recupera token e baseUrl dalla classe
|
||||||
|
$token = $api->getToken();
|
||||||
|
$baseUrl = rtrim($api->getBaseUrl(), '/');
|
||||||
|
|
||||||
|
$rawEndpoints = array(
|
||||||
|
'C: $value' => $baseUrl . '/api/odata/RapportoFile(' . $idRapportoFile . ')/$value',
|
||||||
|
'D: FileContent/$value' => $baseUrl . '/api/odata/RapportoFile(' . $idRapportoFile . ')/FileContent/$value',
|
||||||
|
'E: Contenuto/$value' => $baseUrl . '/api/odata/RapportoFile(' . $idRapportoFile . ')/Contenuto/$value',
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($rawEndpoints as $label => $url) {
|
||||||
|
if ($pdfBody) break;
|
||||||
|
|
||||||
|
$ch = curl_init($url);
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||||
|
'Authorization: Bearer ' . $token,
|
||||||
|
'Accept: application/pdf, application/octet-stream, */*',
|
||||||
|
));
|
||||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||||
|
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
|
||||||
|
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
|
||||||
|
|
||||||
|
$body = curl_exec($ch);
|
||||||
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
|
$ct = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
$debugLog[$label] = array(
|
||||||
|
'url' => $url,
|
||||||
|
'http_code' => $httpCode,
|
||||||
|
'content_type' => $ct,
|
||||||
|
'body_start' => substr((string)$body, 0, 300),
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($httpCode === 200 && is_string($body) && substr($body, 0, 4) === '%PDF') {
|
||||||
|
$pdfBody = $body;
|
||||||
|
$strategyUsed = $label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RISPOSTA
|
||||||
|
if ($pdfBody) {
|
||||||
|
$fileName = isset($entityData['FileName']) ? $entityData['FileName'] : 'rapporto_' . $idRapportoFile . '.pdf';
|
||||||
|
header('Content-Type: application/pdf');
|
||||||
|
header('Content-Disposition: inline; filename="' . $fileName . '"');
|
||||||
|
header('Content-Length: ' . strlen($pdfBody));
|
||||||
|
header('Cache-Control: private, max-age=0, must-revalidate');
|
||||||
|
echo $pdfBody;
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nessuna strategia ha funzionato
|
||||||
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
echo json_encode(array(
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Nessuna strategia ha restituito un PDF valido.',
|
||||||
|
'id_rapporto_file' => $idRapportoFile,
|
||||||
|
'entity_fields' => array_keys($entityData ? $entityData : array()),
|
||||||
|
'entity_data' => $entityData,
|
||||||
|
'strategies_debug' => $debugLog,
|
||||||
|
), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
http_response_code(500);
|
||||||
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
echo json_encode(array(
|
||||||
|
'success' => false,
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
include('include/headscript.php');
|
||||||
|
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$input = json_decode(file_get_contents('php://input'), true);
|
||||||
|
|
||||||
|
if (!$input) {
|
||||||
|
throw new Exception('Invalid JSON payload');
|
||||||
|
}
|
||||||
|
|
||||||
|
$templateId = isset($input['template_id']) ? (int)$input['template_id'] : 0;
|
||||||
|
$apiSampleJson = $input['api_sample_json'] ?? '';
|
||||||
|
$jsonNodes = $input['json_nodes'] ?? '';
|
||||||
|
|
||||||
|
if ($templateId <= 0) {
|
||||||
|
throw new Exception('Invalid template ID');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trim($apiSampleJson) === '') {
|
||||||
|
throw new Exception('API sample JSON is empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
json_decode($apiSampleJson, true);
|
||||||
|
|
||||||
|
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||||
|
throw new Exception('Invalid API sample JSON: ' . json_last_error_msg());
|
||||||
|
}
|
||||||
|
|
||||||
|
$decodedNodes = json_decode($jsonNodes, true);
|
||||||
|
|
||||||
|
if (!is_array($decodedNodes)) {
|
||||||
|
throw new Exception('Invalid JSON nodes array');
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = DBHandlerSelect::getInstance();
|
||||||
|
$pdo = $db->getConnection();
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("
|
||||||
|
UPDATE excel_templates
|
||||||
|
SET
|
||||||
|
api_sample_json = ?,
|
||||||
|
json_nodes = ?
|
||||||
|
WHERE id = ?
|
||||||
|
");
|
||||||
|
|
||||||
|
$stmt->execute([
|
||||||
|
$apiSampleJson,
|
||||||
|
json_encode($decodedNodes, JSON_UNESCAPED_UNICODE),
|
||||||
|
$templateId
|
||||||
|
]);
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'success' => true,
|
||||||
|
'nodes_count' => count($decodedNodes)
|
||||||
|
]);
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
echo json_encode([
|
||||||
|
'success' => false,
|
||||||
|
'message' => $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user