Files
trf_certest/public/userarea/import_insert.php
T
2026-06-13 20:19:36 +03:00

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;