358 lines
14 KiB
PHP
358 lines
14 KiB
PHP
<?php
|
|
ini_set('display_errors', 1);
|
|
ini_set('display_startup_errors', 1);
|
|
error_reporting(E_ALL);
|
|
ini_set('log_errors', 1);
|
|
ini_set('error_log', __DIR__ . '/import_debug.log');
|
|
if (!file_exists(__DIR__ . '/import_debug.log')) {
|
|
file_put_contents(__DIR__ . '/import_debug.log', "Inizio importazione alle " . date('Y-m-d H:i:s') . "\n", FILE_APPEND);
|
|
}
|
|
|
|
// Log iniziale
|
|
error_log("Inizio importazione alle " . date('Y-m-d H:i:s'));
|
|
|
|
include('include/headscript.php');
|
|
require_once(__DIR__ . '/class/binding-functions.php');
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_POST['template_id']) || !isset($_POST['selected_rows']) || !isset($_POST['filename'])) {
|
|
header("Location: xlstemplates_grid.php?status=error&message=" . urlencode("Richiesta non valida"));
|
|
exit;
|
|
}
|
|
|
|
$template_id = intval($_POST['template_id']);
|
|
$selected_rows = array_map('intval', $_POST['selected_rows']);
|
|
$columns = json_decode(urldecode($_POST['columns'] ?? '[]'), true);
|
|
$rows = json_decode(urldecode($_POST['rows'] ?? '[]'), true);
|
|
$excelrows = json_decode(urldecode($_POST['excelrows'] ?? '[]'), true);
|
|
|
|
$newFilename = $_POST['filename'];
|
|
$source_type = strtolower(trim($_POST['source_type'] ?? 'xls'));
|
|
|
|
$_SESSION['template_id'] = $template_id;
|
|
$_SESSION['selected_rows'] = $selected_rows;
|
|
$_SESSION['columns'] = $columns;
|
|
$_SESSION['rows'] = $rows;
|
|
$_SESSION['excelrows'] = $excelrows;
|
|
$_SESSION['filename'] = $newFilename;
|
|
|
|
error_log("Received Data - Template ID: $template_id, Selected Rows: " . json_encode($selected_rows));
|
|
error_log("Columns: " . json_encode($columns));
|
|
error_log("Rows: " . json_encode($rows));
|
|
error_log("Excelrows: " . json_encode($excelrows));
|
|
error_log("Source type: " . $source_type);
|
|
|
|
$user_id = $iduserlogin ?? 1;
|
|
|
|
$db = DBHandlerSelect::getInstance();
|
|
$pdo = $db->getConnection();
|
|
|
|
// Genera un UUID univoco per importreferencecode
|
|
$importReferenceCode = date('YmdHis') . '-' . uniqid();
|
|
|
|
// Recupera tutti i mapping dal template
|
|
$stmt = $pdo->prepare("
|
|
SELECT
|
|
id,
|
|
excel_column,
|
|
json_node,
|
|
data_type,
|
|
is_required,
|
|
manual_default,
|
|
is_manual,
|
|
field_label,
|
|
field_id,
|
|
main_field,
|
|
auto_value,
|
|
has_list
|
|
FROM template_mapping
|
|
WHERE template_id = ?
|
|
");
|
|
$stmt->execute([$template_id]);
|
|
$allMappings = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
if (empty($allMappings)) {
|
|
header("Location: import_xls.php?id=$template_id&status=error&message=" . urlencode("Nessun mapping trovato per il template"));
|
|
exit;
|
|
}
|
|
|
|
// Trova il campo main_field
|
|
$mainFieldMapping = null;
|
|
foreach ($allMappings as $mapping) {
|
|
if ($mapping['main_field'] == 1) {
|
|
$mainFieldMapping = $mapping;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Inserisci le righe selezionate in datadb
|
|
$insertedIds = [];
|
|
|
|
// Binding JSON -> LIMS senza corrispondenza salvata, per "mapping_id|json_value".
|
|
$pendingBindings = [];
|
|
// Binding risolti in automatico durante questo import (solo per visualizzazione).
|
|
$autoBindings = [];
|
|
// Binding gia' salvati in precedenza, usati su questo import (visualizzazione + modifica).
|
|
$savedBindings = [];
|
|
foreach ($selected_rows as $loopIndex => $rowIndex) {
|
|
|
|
if ($source_type === 'json') {
|
|
// JSON import sends only selected rows in rows/excelrows
|
|
$row = $rows[$loopIndex] ?? null;
|
|
$excelrow = $excelrows[$loopIndex] ?? ('JSON-' . ($loopIndex + 1));
|
|
} else {
|
|
// XLS import keeps original row indexes
|
|
$row = $rows[$rowIndex] ?? null;
|
|
$excelrow = $excelrows[$rowIndex] ?? null;
|
|
}
|
|
|
|
if ($row === null || $excelrow === null) {
|
|
error_log("Errore: riga o excelrow mancante. Source type: $source_type, loopIndex: $loopIndex, rowIndex: $rowIndex");
|
|
continue;
|
|
}
|
|
|
|
// Recupera l'idclient di default dal template
|
|
$template_stmt = $pdo->prepare("SELECT idclient FROM excel_templates WHERE id = ?");
|
|
$template_stmt->execute([$template_id]);
|
|
$template = $template_stmt->fetch(PDO::FETCH_ASSOC);
|
|
$default_idclient = $template['idclient'] ?? null;
|
|
|
|
// excelrow e' INT: dal JSON arriva tipo 'JSON-1', tengo solo la parte numerica.
|
|
if (is_numeric($excelrow)) {
|
|
$excelrowDb = (int) $excelrow;
|
|
} else {
|
|
$digits = preg_replace('/\D+/', '', (string) $excelrow);
|
|
$excelrowDb = $digits !== '' ? (int) $digits : ($loopIndex + 1);
|
|
}
|
|
|
|
$values = [
|
|
$template_id,
|
|
$importReferenceCode,
|
|
$newFilename,
|
|
'i',
|
|
$user_id,
|
|
null,
|
|
date('Y-m-d'),
|
|
$excelrowDb,
|
|
$default_idclient // Aggiungi idclient
|
|
];
|
|
$sql = "INSERT INTO datadb (templateid, importreferencecode, filename_import, status, user_id, limscode, importdate, excelrow, idclient) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
|
$stmt = $pdo->prepare($sql);
|
|
$stmt->execute($values);
|
|
|
|
$iddatadb = $pdo->lastInsertId();
|
|
$insertedIds[] = $iddatadb;
|
|
|
|
// Inserisci tutti i campi in import_data_details
|
|
foreach ($allMappings as $mapping) {
|
|
$fieldValue = null;
|
|
if (!$mapping['is_manual']) {
|
|
$sourceColumn = '';
|
|
|
|
if ($source_type === 'json') {
|
|
$sourceColumn = trim($mapping['json_node'] ?? '');
|
|
} else {
|
|
$sourceColumn = trim($mapping['excel_column'] ?? '');
|
|
}
|
|
|
|
// Fallback: if JSON node is empty, try excel_column
|
|
if ($sourceColumn === '') {
|
|
$sourceColumn = trim($mapping['excel_column'] ?? '');
|
|
}
|
|
|
|
$columnsTrimmed = array_map('trim', $columns);
|
|
|
|
$candidateColumns = [];
|
|
|
|
if ($sourceColumn !== '') {
|
|
$candidateColumns[] = $sourceColumn;
|
|
|
|
if ($source_type === 'json') {
|
|
// Common JSON path variants
|
|
$candidateColumns[] = preg_replace('/^data\[\]\./', '', $sourceColumn);
|
|
$candidateColumns[] = preg_replace('/^data\.0\./', '', $sourceColumn);
|
|
$candidateColumns[] = str_replace('data[].', 'data.0.', $sourceColumn);
|
|
$candidateColumns[] = str_replace('data.0.', 'data[].', $sourceColumn);
|
|
}
|
|
}
|
|
|
|
// Remove empty and duplicate candidates
|
|
$candidateColumns = array_values(array_unique(array_filter($candidateColumns, function ($value) {
|
|
return trim((string)$value) !== '';
|
|
})));
|
|
|
|
$sourceColumnIndex = false;
|
|
$matchedColumn = '';
|
|
|
|
foreach ($candidateColumns as $candidateColumn) {
|
|
$candidateColumn = trim($candidateColumn);
|
|
$index = array_search($candidateColumn, $columnsTrimmed);
|
|
|
|
if ($index !== false) {
|
|
$sourceColumnIndex = $index;
|
|
$matchedColumn = $candidateColumn;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($sourceColumnIndex !== false && isset($row[$sourceColumnIndex]) && $row[$sourceColumnIndex] !== '') {
|
|
$fieldValue = $row[$sourceColumnIndex];
|
|
|
|
error_log(
|
|
"Found source column. Original: '$sourceColumn', Matched: '$matchedColumn', Index: $sourceColumnIndex, Value: " .
|
|
var_export($fieldValue, true)
|
|
);
|
|
} else {
|
|
$fieldValue = $mapping['manual_default'] ?? '';
|
|
|
|
error_log(
|
|
"Source column not found or empty. Original: '$sourceColumn'. Candidates: " .
|
|
json_encode($candidateColumns) .
|
|
". Available columns: " .
|
|
json_encode($columnsTrimmed) .
|
|
". Using default: " .
|
|
var_export($fieldValue, true)
|
|
);
|
|
}
|
|
switch ($mapping['data_type']) {
|
|
case 'INT':
|
|
$fieldValue = is_numeric($fieldValue) ? (int)$fieldValue : ($mapping['manual_default'] ?? 0);
|
|
break;
|
|
case 'DATE':
|
|
$fieldValue = !empty($fieldValue) ? date('Y-m-d', strtotime($fieldValue)) : ($mapping['manual_default'] === 'today' ? date('Y-m-d') : ($mapping['manual_default'] ?? ''));
|
|
break;
|
|
case 'CHAR':
|
|
$fieldValue = !empty($fieldValue) ? substr((string)$fieldValue, 0, 1) : ($mapping['manual_default'] ?? '');
|
|
break;
|
|
case 'Testo':
|
|
case 'VARCHAR':
|
|
default:
|
|
$fieldValue = !empty($fieldValue) ? (string)$fieldValue : ($mapping['manual_default'] ?? '');
|
|
break;
|
|
}
|
|
} else {
|
|
$fieldValue = $mapping['manual_default'] ?? '';
|
|
if ($mapping['data_type'] === 'DATE' && $mapping['manual_default'] === 'today') {
|
|
$fieldValue = date('Y-m-d');
|
|
}
|
|
}
|
|
// Apply auto_value if field is still empty
|
|
if (($fieldValue === null || $fieldValue === '') && !empty($mapping['auto_value']) && $mapping['auto_value'] !== 'none') {
|
|
if ($mapping['auto_value'] === 'import_date') {
|
|
$fieldValue = date('Y-m-d');
|
|
} elseif ($mapping['auto_value'] === 'import_time') {
|
|
$fieldValue = date('H:i');
|
|
}
|
|
}
|
|
|
|
// Binding JSON -> LIMS solo per i campi a lista importati da JSON.
|
|
if (
|
|
$source_type === 'json'
|
|
&& !$mapping['is_manual']
|
|
&& binding_is_list_field($mapping)
|
|
&& $fieldValue !== null
|
|
&& $fieldValue !== ''
|
|
) {
|
|
$jsonValue = (string) $fieldValue;
|
|
$existing = binding_lookup($pdo, (int) $mapping['id'], $jsonValue);
|
|
|
|
if ($existing) {
|
|
$fieldValue = $existing['lims_value'];
|
|
|
|
$key = $mapping['id'] . '|' . $jsonValue;
|
|
if (!isset($savedBindings[$key])) {
|
|
$savedBindings[$key] = [
|
|
'mapping_id' => (int) $mapping['id'],
|
|
'field_id' => (int) $mapping['field_id'],
|
|
'field_label' => $mapping['field_label'],
|
|
'json_value' => $jsonValue,
|
|
'lims_value' => (string) $existing['lims_value'],
|
|
'lims_value_id' => (int) $existing['lims_value_id'],
|
|
'datadb_ids' => [],
|
|
];
|
|
}
|
|
$savedBindings[$key]['datadb_ids'][] = (int) $iddatadb;
|
|
} else {
|
|
// Nessun binding salvato: provo l'auto-match 1-a-1 sui valori LIMS.
|
|
$limsValues = binding_get_lims_values((int) $mapping['field_id']);
|
|
$autoMatch = binding_auto_match($limsValues, $jsonValue);
|
|
|
|
if ($autoMatch) {
|
|
binding_upsert(
|
|
$pdo,
|
|
(int) $template_id,
|
|
(int) $mapping['id'],
|
|
(int) $mapping['field_id'],
|
|
$jsonValue,
|
|
(int) $autoMatch['IdCustomFieldsValue'],
|
|
(string) $autoMatch['Valore'],
|
|
$user_id
|
|
);
|
|
$fieldValue = (string) $autoMatch['Valore'];
|
|
|
|
$key = $mapping['id'] . '|' . $jsonValue;
|
|
if (!isset($autoBindings[$key])) {
|
|
$autoBindings[$key] = [
|
|
'mapping_id' => (int) $mapping['id'],
|
|
'field_id' => (int) $mapping['field_id'],
|
|
'field_label' => $mapping['field_label'],
|
|
'json_value' => $jsonValue,
|
|
'lims_value' => (string) $autoMatch['Valore'],
|
|
'lims_value_id' => (int) $autoMatch['IdCustomFieldsValue'],
|
|
'datadb_ids' => [],
|
|
];
|
|
}
|
|
$autoBindings[$key]['datadb_ids'][] = (int) $iddatadb;
|
|
} else {
|
|
$key = $mapping['id'] . '|' . $jsonValue;
|
|
if (!isset($pendingBindings[$key])) {
|
|
$pendingBindings[$key] = [
|
|
'mapping_id' => (int) $mapping['id'],
|
|
'field_id' => (int) $mapping['field_id'],
|
|
'field_label' => $mapping['field_label'],
|
|
'json_value' => $jsonValue,
|
|
'datadb_ids' => [],
|
|
];
|
|
}
|
|
$pendingBindings[$key]['datadb_ids'][] = (int) $iddatadb;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($mapping['is_required'] && (is_null($fieldValue) || $fieldValue === '')) {
|
|
error_log("Required field missing for mapping ID: " . $mapping['id'] . ", field: " . $mapping['field_label']);
|
|
}
|
|
error_log("Inserting into import_data_details - Mapping ID: " . $mapping['id'] . ", Field Value: " . var_export($fieldValue, true) . ", Is Manual: " . $mapping['is_manual'] . ", Source Column: " . ($sourceColumn ?? 'N/A') . ", Source Type: " . $source_type . ", Manual Default: " . ($mapping['manual_default'] ?? 'N/A'));
|
|
$stmt = $pdo->prepare("INSERT INTO import_data_details (id, mapping_id, field_value) VALUES (?, ?, ?)");
|
|
$stmt->execute([$iddatadb, $mapping['id'], $fieldValue]);
|
|
error_log("Inserted into import_data_details for ID $iddatadb, Mapping ID: " . $mapping['id'] . ", Field Value: " . var_export($fieldValue, true));
|
|
}
|
|
}
|
|
|
|
$_SESSION['inserted_ids'] = $insertedIds;
|
|
|
|
$importedUrl = "imported.php?id=" . urlencode($template_id) . "&importref=" . urlencode($importReferenceCode);
|
|
|
|
// Solo se restano binding da risolvere mostro la pagina (con anche gli auto, modificabili).
|
|
if (!empty($pendingBindings)) {
|
|
$_SESSION['pending_bindings'] = [
|
|
'template_id' => $template_id,
|
|
'importref' => $importReferenceCode,
|
|
'items' => array_values($pendingBindings),
|
|
'auto' => array_values($autoBindings),
|
|
'saved' => array_values($savedBindings),
|
|
];
|
|
|
|
header("Location: resolve_bindings.php");
|
|
exit;
|
|
}
|
|
|
|
unset($_SESSION['pending_bindings']);
|
|
|
|
// Solo auto-collegati: vado diretto alla griglia, segnalando quanti.
|
|
if (!empty($autoBindings)) {
|
|
$importedUrl .= "&autobound=" . count($autoBindings);
|
|
}
|
|
|
|
header("Location: " . $importedUrl);
|
|
exit;
|