449 lines
15 KiB
PHP
449 lines
15 KiB
PHP
<?php
|
|
|
|
// Helpers for JSON -> LIMS value bindings (table json_lims_binding).
|
|
// Supports two kinds: 'custom' (template_mapping list fields, value -> import_data_details)
|
|
// and 'fixed' (template_fixed_mapping list fields, id -> datadb column).
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Fixed-field metadata
|
|
// ---------------------------------------------------------------------------
|
|
|
|
function binding_fixed_alias_map(): array
|
|
{
|
|
return [
|
|
'ClienteResponsabile' => 'cliente_responsabile_id',
|
|
'ClienteFornitore' => 'cliente_fornitore_id',
|
|
'ClienteAnalisi' => 'clienteAnalisi',
|
|
'MoltiplicatorePrezzo' => 'moltiplicatore_prezzo_id',
|
|
'AnagraficaCertestObject' => 'anagrafica_certest_object_id',
|
|
'AnagraficaCertestService' => 'anagrafica_certest_service_id',
|
|
'ConsegnaRichiesta' => 'consegna_richiesta',
|
|
];
|
|
}
|
|
|
|
// Fixed-field keys that are LIMS list dropdowns (bindable). ConsegnaRichiesta is a date.
|
|
function binding_fixed_is_list(string $key): bool
|
|
{
|
|
return in_array($key, [
|
|
'ClienteResponsabile',
|
|
'ClienteFornitore',
|
|
'ClienteAnalisi',
|
|
'MoltiplicatorePrezzo',
|
|
'AnagraficaCertestObject',
|
|
'AnagraficaCertestService',
|
|
], true);
|
|
}
|
|
|
|
function binding_fixed_column(string $key): ?string
|
|
{
|
|
return binding_fixed_alias_map()[$key] ?? null;
|
|
}
|
|
|
|
// Auto-match only the small global lists; the client-based ones are huge / client-specific.
|
|
function binding_fixed_auto_matchable(string $key): bool
|
|
{
|
|
return in_array($key, [
|
|
'MoltiplicatorePrezzo',
|
|
'AnagraficaCertestObject',
|
|
'AnagraficaCertestService',
|
|
], true);
|
|
}
|
|
|
|
function binding_fixed_label(string $key): string
|
|
{
|
|
$labels = [
|
|
'AnagraficaCertestObject' => 'Anagrafica Certest Object',
|
|
'AnagraficaCertestService' => 'Anagrafica Certest Service',
|
|
'MoltiplicatorePrezzo' => 'Moltiplicatore Prezzo',
|
|
'ClienteResponsabile' => 'Cliente Responsabile',
|
|
'ClienteFornitore' => 'Cliente Fornitore',
|
|
'ClienteAnalisi' => 'Cliente Analisi',
|
|
];
|
|
return $labels[$key] ?? $key;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Bindable check (custom mapping row)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
function binding_is_list_field(array $mapping): bool
|
|
{
|
|
$hasList = (int) ($mapping['has_list'] ?? 0) === 1;
|
|
$isMultiChoice = strcasecmp(trim((string) ($mapping['data_type'] ?? '')), 'SceltaMultipla') === 0;
|
|
return $hasList || $isMultiChoice;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Target keys + lookup / upsert
|
|
// ---------------------------------------------------------------------------
|
|
|
|
function binding_target_custom(int $mappingId): string
|
|
{
|
|
return 'cf:' . $mappingId;
|
|
}
|
|
|
|
function binding_target_fixed(int $templateId, string $fixedKey): string
|
|
{
|
|
return 'fx:' . $templateId . ':' . $fixedKey;
|
|
}
|
|
|
|
function binding_lookup_target(PDO $pdo, string $targetKey, string $jsonValue): ?array
|
|
{
|
|
$stmt = $pdo->prepare(
|
|
"SELECT id, lims_value_id, lims_value
|
|
FROM json_lims_binding
|
|
WHERE target_key = ? AND json_value = ?
|
|
LIMIT 1"
|
|
);
|
|
$stmt->execute([$targetKey, $jsonValue]);
|
|
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
return $row ?: null;
|
|
}
|
|
|
|
function binding_lookup(PDO $pdo, int $mappingId, string $jsonValue): ?array
|
|
{
|
|
return binding_lookup_target($pdo, binding_target_custom($mappingId), $jsonValue);
|
|
}
|
|
|
|
function binding_lookup_fixed(PDO $pdo, int $templateId, string $fixedKey, string $jsonValue): ?array
|
|
{
|
|
return binding_lookup_target($pdo, binding_target_fixed($templateId, $fixedKey), $jsonValue);
|
|
}
|
|
|
|
function binding_upsert_row(
|
|
PDO $pdo,
|
|
string $kind,
|
|
int $templateId,
|
|
?int $mappingId,
|
|
?string $fixedFieldKey,
|
|
string $targetKey,
|
|
int $fieldId,
|
|
string $jsonValue,
|
|
int $limsValueId,
|
|
string $limsValue,
|
|
?int $createdBy
|
|
): void {
|
|
$stmt = $pdo->prepare(
|
|
"INSERT INTO json_lims_binding
|
|
(template_id, binding_kind, mapping_id, fixed_field_key, target_key, field_id, json_value, lims_value_id, lims_value, created_by)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
ON DUPLICATE KEY UPDATE
|
|
lims_value_id = VALUES(lims_value_id),
|
|
lims_value = VALUES(lims_value),
|
|
field_id = VALUES(field_id),
|
|
template_id = VALUES(template_id),
|
|
binding_kind = VALUES(binding_kind),
|
|
mapping_id = VALUES(mapping_id),
|
|
fixed_field_key = VALUES(fixed_field_key)"
|
|
);
|
|
$stmt->execute([
|
|
$templateId, $kind, $mappingId, $fixedFieldKey, $targetKey,
|
|
$fieldId, $jsonValue, $limsValueId, $limsValue, $createdBy,
|
|
]);
|
|
}
|
|
|
|
function binding_upsert(
|
|
PDO $pdo,
|
|
int $templateId,
|
|
int $mappingId,
|
|
int $fieldId,
|
|
string $jsonValue,
|
|
int $limsValueId,
|
|
string $limsValue,
|
|
?int $createdBy
|
|
): void {
|
|
binding_upsert_row(
|
|
$pdo, 'custom', $templateId, $mappingId, null,
|
|
binding_target_custom($mappingId), $fieldId, $jsonValue, $limsValueId, $limsValue, $createdBy
|
|
);
|
|
}
|
|
|
|
function binding_upsert_fixed(
|
|
PDO $pdo,
|
|
int $templateId,
|
|
string $fixedKey,
|
|
string $jsonValue,
|
|
int $limsValueId,
|
|
string $limsValue,
|
|
?int $createdBy
|
|
): void {
|
|
binding_upsert_row(
|
|
$pdo, 'fixed', $templateId, null, $fixedKey,
|
|
binding_target_fixed($templateId, $fixedKey), 0, $jsonValue, $limsValueId, $limsValue, $createdBy
|
|
);
|
|
}
|
|
|
|
function binding_delete_target(PDO $pdo, string $targetKey, string $jsonValue): int
|
|
{
|
|
$stmt = $pdo->prepare("DELETE FROM json_lims_binding WHERE target_key = ? AND json_value = ?");
|
|
$stmt->execute([$targetKey, $jsonValue]);
|
|
return $stmt->rowCount();
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Custom-field LIMS values (cache/customfield_{id}.json) + auto-match
|
|
// ---------------------------------------------------------------------------
|
|
|
|
function binding_get_lims_values(int $fieldId): array
|
|
{
|
|
static $memo = [];
|
|
if ($fieldId <= 0) {
|
|
return [];
|
|
}
|
|
if (array_key_exists($fieldId, $memo)) {
|
|
return $memo[$fieldId];
|
|
}
|
|
|
|
$cacheDir = dirname(__DIR__) . '/cache';
|
|
$cacheFile = $cacheDir . '/customfield_' . $fieldId . '.json';
|
|
|
|
try {
|
|
if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < 3600)) {
|
|
$values = json_decode(file_get_contents($cacheFile), true);
|
|
} else {
|
|
require_once __DIR__ . '/VisualLimsApiClient.class.php';
|
|
$api = VisualLimsApiClient::getInstance();
|
|
$data = $api->get("CustomField($fieldId)?\$expand=CustomFieldsValues");
|
|
$values = $data['CustomFieldsValues'] ?? [];
|
|
if (!is_dir($cacheDir)) {
|
|
mkdir($cacheDir, 0777, true);
|
|
}
|
|
file_put_contents($cacheFile, json_encode($values));
|
|
}
|
|
} catch (Throwable $e) {
|
|
error_log("binding_get_lims_values failed for field $fieldId: " . $e->getMessage());
|
|
$values = [];
|
|
}
|
|
|
|
if (!is_array($values)) {
|
|
$values = [];
|
|
}
|
|
|
|
return $memo[$fieldId] = $values;
|
|
}
|
|
|
|
// Exactly one case-insensitive match by Valore -> that value, otherwise null.
|
|
function binding_auto_match(array $limsValues, string $jsonValue): ?array
|
|
{
|
|
$needle = mb_strtolower(trim($jsonValue));
|
|
if ($needle === '') {
|
|
return null;
|
|
}
|
|
|
|
$matches = [];
|
|
foreach ($limsValues as $v) {
|
|
$valore = (string) ($v['Valore'] ?? '');
|
|
if (mb_strtolower(trim($valore)) === $needle) {
|
|
$matches[] = $v;
|
|
}
|
|
}
|
|
|
|
return count($matches) === 1 ? $matches[0] : null;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Fixed-field LIMS values (per-field source) + auto-match
|
|
// ---------------------------------------------------------------------------
|
|
|
|
function binding_template_idclient(PDO $pdo, int $templateId): int
|
|
{
|
|
$stmt = $pdo->prepare("SELECT idclient FROM excel_templates WHERE id = ?");
|
|
$stmt->execute([$templateId]);
|
|
return (int) ($stmt->fetchColumn() ?: 0);
|
|
}
|
|
|
|
function binding_client_label(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 . ')';
|
|
}
|
|
|
|
// Fetch an OData payload with a 1-hour file cache.
|
|
function binding_cached_get($api, string $cacheFile, string $endpoint): array
|
|
{
|
|
if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < 3600)) {
|
|
$data = json_decode(file_get_contents($cacheFile), true);
|
|
} else {
|
|
$data = $api->get($endpoint);
|
|
$dir = dirname($cacheFile);
|
|
if (!is_dir($dir)) {
|
|
mkdir($dir, 0777, true);
|
|
}
|
|
file_put_contents($cacheFile, json_encode($data));
|
|
}
|
|
return is_array($data) ? $data : [];
|
|
}
|
|
|
|
// Normalized LIMS value list for a fixed field: [['id' => int, 'text' => string], ...].
|
|
function binding_get_fixed_values(PDO $pdo, string $fieldKey, int $templateId): array
|
|
{
|
|
static $memo = [];
|
|
$memoKey = $fieldKey . '|' . $templateId;
|
|
if (isset($memo[$memoKey])) {
|
|
return $memo[$memoKey];
|
|
}
|
|
|
|
$cacheDir = dirname(__DIR__) . '/cache';
|
|
$out = [];
|
|
|
|
try {
|
|
require_once __DIR__ . '/VisualLimsApiClient.class.php';
|
|
$api = VisualLimsApiClient::getInstance();
|
|
|
|
switch ($fieldKey) {
|
|
case 'MoltiplicatorePrezzo':
|
|
$data = binding_cached_get($api, "$cacheDir/moltiplicatori_prezzo.json", 'MoltiplicatorePrezzi');
|
|
foreach (($data['value'] ?? []) as $r) {
|
|
$out[] = ['id' => (int) ($r['IdMoltiplicatorePrezzo'] ?? 0), 'text' => (string) ($r['Descrizione'] ?? '')];
|
|
}
|
|
break;
|
|
|
|
case 'AnagraficaCertestObject':
|
|
case 'AnagraficaCertestService':
|
|
$file = $fieldKey === 'AnagraficaCertestObject' ? 'anagrafica_certest_object.json' : 'anagrafica_certest_service.json';
|
|
$data = binding_cached_get($api, "$cacheDir/$file", $fieldKey);
|
|
foreach (($data['value'] ?? []) as $r) {
|
|
$code = trim((string) ($r['Codice'] ?? ''));
|
|
$text = ($code !== '' ? $code . ' - ' : '') . (string) ($r['NomeAnagrafica'] ?? '');
|
|
$out[] = ['id' => (int) ($r['IdAnagrafica'] ?? 0), 'text' => $text];
|
|
}
|
|
break;
|
|
|
|
case 'ClienteResponsabile':
|
|
$idCliente = binding_template_idclient($pdo, $templateId);
|
|
if ($idCliente > 0) {
|
|
$data = binding_cached_get($api, "$cacheDir/cliente_responsabili_$idCliente.json", "Cliente($idCliente)?\$expand=Responsabili");
|
|
foreach (($data['Responsabili'] ?? []) as $r) {
|
|
$out[] = ['id' => (int) ($r['IdClienteResponsabile'] ?? 0), 'text' => (string) ($r['Nominativo'] ?? '')];
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'ClienteFornitore':
|
|
case 'ClienteAnalisi':
|
|
$endpoint = 'Cliente?' . http_build_query(['$select' => 'IdCliente,Nominativo,CodiceCliente', '$orderby' => 'Nominativo asc']);
|
|
$data = binding_cached_get($api, "$cacheDir/clienti.json", $endpoint);
|
|
foreach (($data['value'] ?? []) as $r) {
|
|
$out[] = ['id' => (int) ($r['IdCliente'] ?? 0), 'text' => binding_client_label($r)];
|
|
}
|
|
break;
|
|
}
|
|
} catch (Throwable $e) {
|
|
error_log("binding_get_fixed_values($fieldKey) failed: " . $e->getMessage());
|
|
$out = [];
|
|
}
|
|
|
|
return $memo[$memoKey] = $out;
|
|
}
|
|
|
|
// Exactly one case-insensitive match by text on a [{id,text}] list, otherwise null.
|
|
function binding_auto_match_fixed(array $values, string $jsonValue): ?array
|
|
{
|
|
$needle = mb_strtolower(trim($jsonValue));
|
|
if ($needle === '') {
|
|
return null;
|
|
}
|
|
$matches = [];
|
|
foreach ($values as $v) {
|
|
if (mb_strtolower(trim((string) ($v['text'] ?? ''))) === $needle) {
|
|
$matches[] = $v;
|
|
}
|
|
}
|
|
return count($matches) === 1 ? $matches[0] : null;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// JSON node -> column matching (shared with import_insert custom logic)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
function binding_find_column_index(string $sourceColumn, array $columns): int
|
|
{
|
|
$sourceColumn = trim($sourceColumn);
|
|
if ($sourceColumn === '') {
|
|
return -1;
|
|
}
|
|
|
|
$columnsTrimmed = array_map('trim', $columns);
|
|
$candidates = [
|
|
$sourceColumn,
|
|
preg_replace('/^data\[\]\./', '', $sourceColumn),
|
|
preg_replace('/^data\.0\./', '', $sourceColumn),
|
|
str_replace('data[].', 'data.0.', $sourceColumn),
|
|
str_replace('data.0.', 'data[].', $sourceColumn),
|
|
];
|
|
$candidates = array_values(array_unique(array_filter(array_map('trim', $candidates), function ($v) {
|
|
return $v !== '';
|
|
})));
|
|
|
|
foreach ($candidates as $c) {
|
|
$i = array_search($c, $columnsTrimmed, true);
|
|
if ($i !== false) {
|
|
return (int) $i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Apply resolved values
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// Custom: write the resolved LIMS text into import_data_details for the given datadb ids.
|
|
function binding_apply_to_details(
|
|
PDO $pdo,
|
|
int $mappingId,
|
|
string $limsValue,
|
|
array $datadbIds
|
|
): int {
|
|
$datadbIds = array_values(array_filter(array_map('intval', $datadbIds)));
|
|
if (empty($datadbIds)) {
|
|
return 0;
|
|
}
|
|
|
|
$placeholders = implode(',', array_fill(0, count($datadbIds), '?'));
|
|
$sql = "UPDATE import_data_details
|
|
SET field_value = ?
|
|
WHERE mapping_id = ?
|
|
AND id IN ($placeholders)";
|
|
|
|
$params = array_merge([$limsValue, $mappingId], $datadbIds);
|
|
$stmt = $pdo->prepare($sql);
|
|
$stmt->execute($params);
|
|
return $stmt->rowCount();
|
|
}
|
|
|
|
// Fixed: write the resolved LIMS id into a whitelisted datadb column for the given ids.
|
|
// $limsValueId null clears the column.
|
|
function binding_apply_to_datadb(
|
|
PDO $pdo,
|
|
string $column,
|
|
?int $limsValueId,
|
|
array $datadbIds
|
|
): int {
|
|
if (!in_array($column, array_values(binding_fixed_alias_map()), true)) {
|
|
throw new InvalidArgumentException("Invalid fixed-field column: $column");
|
|
}
|
|
$datadbIds = array_values(array_filter(array_map('intval', $datadbIds)));
|
|
if (empty($datadbIds)) {
|
|
return 0;
|
|
}
|
|
|
|
$placeholders = implode(',', array_fill(0, count($datadbIds), '?'));
|
|
$sql = "UPDATE datadb SET `$column` = ? WHERE iddatadb IN ($placeholders)";
|
|
$stmt = $pdo->prepare($sql);
|
|
$stmt->execute(array_merge([$limsValueId], $datadbIds));
|
|
return $stmt->rowCount();
|
|
}
|