Merge branch 'main' into features/jsonintegration
This commit is contained in:
@@ -477,6 +477,71 @@ try {
|
|||||||
$logFilePhotos = $logDir . "commessa_{$commessaId}_photos_step5_2_" . time() . ".txt";
|
$logFilePhotos = $logDir . "commessa_{$commessaId}_photos_step5_2_" . time() . ".txt";
|
||||||
$writeLog($logFilePhotos, $logContentPhotos, "STEP 6.2 - Photos (commessa={$commessaId})");
|
$writeLog($logFilePhotos, $logContentPhotos, "STEP 6.2 - Photos (commessa={$commessaId})");
|
||||||
|
|
||||||
|
// 🔹 STEP 6.3: Add Analyses (AnalisiCampione) via Campione({id})/AddAnalisi bound action
|
||||||
|
$stmt = $pdo->prepare("
|
||||||
|
SELECT part_id, analysis_recordkey, analysis_name, analysis_method
|
||||||
|
FROM identification_parts_analyses
|
||||||
|
WHERE iddatadb = :iddatadb
|
||||||
|
ORDER BY part_id, id
|
||||||
|
");
|
||||||
|
$stmt->execute(['iddatadb' => $iddatadb]);
|
||||||
|
$analysesRows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
$partIdToIndex = [];
|
||||||
|
foreach ($parts as $idx => $part) {
|
||||||
|
$partIdToIndex[(int)$part['part_id']] = $idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
$totalAnalyses = count($analysesRows);
|
||||||
|
$addedAnalyses = 0;
|
||||||
|
$failedAnalyses = [];
|
||||||
|
$logContentStep63Analisi = "Analyses for iddatadb={$iddatadb}: total={$totalAnalyses}\n\n";
|
||||||
|
|
||||||
|
foreach ($analysesRows as $a) {
|
||||||
|
$partId = (int)$a['part_id'];
|
||||||
|
$recordKey = trim((string)($a['analysis_recordkey'] ?? ''));
|
||||||
|
$idx = $partIdToIndex[$partId] ?? null;
|
||||||
|
|
||||||
|
if ($idx === null || !isset($campioni[$idx]) || $recordKey === '') {
|
||||||
|
$logContentStep63Analisi .= "SKIP (no campione for part_id={$partId} / empty recordkey): '{$recordKey}'\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$campioneId = (int)($campioni[$idx]['IdCampione'] ?? 0);
|
||||||
|
if ($campioneId <= 0) {
|
||||||
|
$logContentStep63Analisi .= "SKIP (invalid IdCampione for part_id={$partId}): '{$recordKey}'\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$payload = ['RecordKey' => $recordKey];
|
||||||
|
$jsonPayload = json_encode($payload, JSON_UNESCAPED_SLASHES);
|
||||||
|
|
||||||
|
$logContentStep63Analisi .= "curl --location --request POST '{$apiBaseUrl}Campione({$campioneId})/AddAnalisi' \\\n" .
|
||||||
|
"--header 'Content-Type: application/json' \\\n" .
|
||||||
|
"--header 'Authorization: Bearer ••••••' \\\n" .
|
||||||
|
"--data '{$jsonPayload}'\n";
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $api->post("Campione({$campioneId})/AddAnalisi", $payload);
|
||||||
|
$logContentStep63Analisi .= "OK (part_id={$partId}, campione={$campioneId}): " .
|
||||||
|
($a['analysis_name'] ?? '') . "\n---\n";
|
||||||
|
$addedAnalyses++;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$errMsg = $e->getMessage();
|
||||||
|
$logContentStep63Analisi .= "FAIL: {$errMsg}\n---\n";
|
||||||
|
$failedAnalyses[] = [
|
||||||
|
'part_id' => $partId,
|
||||||
|
'campione_id' => $campioneId,
|
||||||
|
'analysis_recordkey' => $recordKey,
|
||||||
|
'analysis_name' => $a['analysis_name'] ?? '',
|
||||||
|
'error' => $errMsg,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$logFileStep63Analisi = $logDir . "commessa_{$commessaId}_analyses_step63_" . time() . ".txt";
|
||||||
|
$writeLog($logFileStep63Analisi, $logContentStep63Analisi, "STEP 6.3 - AddAnalisi (commessa={$commessaId})");
|
||||||
|
|
||||||
// 🔹 STEP 7: Update Custom Fields for CommessaWeb
|
// 🔹 STEP 7: Update Custom Fields for CommessaWeb
|
||||||
if (!empty($fieldValues)) {
|
if (!empty($fieldValues)) {
|
||||||
// GET con espansione per CustomField
|
// GET con espansione per CustomField
|
||||||
@@ -629,11 +694,15 @@ try {
|
|||||||
"totalCampioni" => count($campioni),
|
"totalCampioni" => count($campioni),
|
||||||
"totalCustomFields" => count($commessaAfterPatch["CommesseCustomFields"] ?? []),
|
"totalCustomFields" => count($commessaAfterPatch["CommesseCustomFields"] ?? []),
|
||||||
"totalPhotos" => count($photos),
|
"totalPhotos" => count($photos),
|
||||||
|
"totalAnalyses" => $totalAnalyses,
|
||||||
|
"addedAnalyses" => $addedAnalyses,
|
||||||
|
"failedAnalyses" => $failedAnalyses,
|
||||||
"message" => "Export successful",
|
"message" => "Export successful",
|
||||||
"logFiles" => [
|
"logFiles" => [
|
||||||
"step5_create" => $logFileStep5,
|
"step5_create" => $logFileStep5,
|
||||||
"step5_2_photos" => $logFilePhotos,
|
"step5_2_photos" => $logFilePhotos,
|
||||||
"step6_campioni" => $logFileStep6,
|
"step6_campioni" => $logFileStep6,
|
||||||
|
"step63_analyses" => $logFileStep63Analisi,
|
||||||
"step7_patch" => $logFileStep7 ?? null,
|
"step7_patch" => $logFileStep7 ?? null,
|
||||||
"step9_1_importa" => $logFileStep91,
|
"step9_1_importa" => $logFileStep91,
|
||||||
"step10_get" => $logFileStep10
|
"step10_get" => $logFileStep10
|
||||||
@@ -649,6 +718,7 @@ try {
|
|||||||
"step5_create" => $logFileStep5 ?? null,
|
"step5_create" => $logFileStep5 ?? null,
|
||||||
"step5_2_photos" => $logFilePhotos ?? null,
|
"step5_2_photos" => $logFilePhotos ?? null,
|
||||||
"step6_campioni" => $logFileStep6 ?? null,
|
"step6_campioni" => $logFileStep6 ?? null,
|
||||||
|
"step63_analyses" => $logFileStep63Analisi ?? null,
|
||||||
"step7_patch" => $logFileStep7 ?? null,
|
"step7_patch" => $logFileStep7 ?? null,
|
||||||
"step9_1_importa" => $logFileStep91 ?? null,
|
"step9_1_importa" => $logFileStep91 ?? null,
|
||||||
"step10_get" => $logFileStep10 ?? null
|
"step10_get" => $logFileStep10 ?? null
|
||||||
|
|||||||
@@ -88,6 +88,58 @@ $validators[] = function (int $iddatadb, array $ctx): array {
|
|||||||
return [];
|
return [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 3. All LIMS-mandatory fields must be filled.
|
||||||
|
$validators[] = function (int $iddatadb, array $ctx): array {
|
||||||
|
$record = $ctx['record'] ?? null;
|
||||||
|
if (!$record) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$errors = [];
|
||||||
|
|
||||||
|
// Fixed fields (stored as columns in datadb)
|
||||||
|
foreach (($ctx['requiredFixed'] ?? []) as $key => $label) {
|
||||||
|
$col = $ctx['fixedAliasMap'][$key] ?? null;
|
||||||
|
$val = $col !== null ? ($record[$col] ?? null) : null;
|
||||||
|
if ($val === null || $val === '' || (int) $val === 0) {
|
||||||
|
$errors[] = [
|
||||||
|
'field' => $key,
|
||||||
|
'message' => $label . ' è obbligatorio.',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom fields (values stored in import_data_details, keyed by mapping_id)
|
||||||
|
foreach (($ctx['requiredCustom'] ?? []) as $cf) {
|
||||||
|
$val = $ctx['customValues'][(int) $cf['mapping_id']] ?? null;
|
||||||
|
if ($val === null || trim((string) $val) === '') {
|
||||||
|
$errors[] = [
|
||||||
|
'field' => 'field_label:' . $cf['field_label'],
|
||||||
|
'message' => rtrim($cf['field_label'], ': ') . ' è obbligatorio.',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $errors;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Logical fixed_field_key - real datadb column (mirrors imported.php $fixedAliasMap)
|
||||||
|
$fixedAliasMap = [
|
||||||
|
'ClienteResponsabile' => 'cliente_responsabile_id',
|
||||||
|
'ClienteFornitore' => 'cliente_fornitore_id',
|
||||||
|
'ClienteAnalisi' => 'clienteAnalisi',
|
||||||
|
'MoltiplicatorePrezzo' => 'moltiplicatore_prezzo_id',
|
||||||
|
'AnagraficaCertestObject' => 'anagrafica_certest_object_id',
|
||||||
|
'AnagraficaCertestService' => 'anagrafica_certest_service_id',
|
||||||
|
'ConsegnaRichiesta' => 'consegna_richiesta',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Fixed keys NOT enforced by the generic mandatory check above:
|
||||||
|
// - ConsegnaRichiesta: handled by its dedicated validator (also checks the date)
|
||||||
|
// - ClienteFornitore / ClienteAnalisi: nullable placeholders, sent as null on
|
||||||
|
// export and accepted by LIMS.
|
||||||
|
$skipRequiredFixed = ['ConsegnaRichiesta', 'ClienteFornitore', 'ClienteAnalisi'];
|
||||||
|
|
||||||
// ── Main ────────────────────────────────────────────────────────────────────
|
// ── Main ────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -104,9 +156,12 @@ try {
|
|||||||
$iddatadbList = array_column($rows, 'iddatadb');
|
$iddatadbList = array_column($rows, 'iddatadb');
|
||||||
$placeholders = implode(',', array_fill(0, count($iddatadbList), '?'));
|
$placeholders = implode(',', array_fill(0, count($iddatadbList), '?'));
|
||||||
|
|
||||||
// Records (datadb) for fixed field validation
|
// Records (datadb) — templateid + fixed-field columns for mandatory validation
|
||||||
$stmt = $pdo->prepare("
|
$stmt = $pdo->prepare("
|
||||||
SELECT iddatadb, consegna_richiesta
|
SELECT iddatadb, templateid, consegna_richiesta,
|
||||||
|
cliente_responsabile_id, moltiplicatore_prezzo_id,
|
||||||
|
anagrafica_certest_object_id, anagrafica_certest_service_id,
|
||||||
|
cliente_fornitore_id, clienteAnalisi
|
||||||
FROM datadb
|
FROM datadb
|
||||||
WHERE iddatadb IN ($placeholders)
|
WHERE iddatadb IN ($placeholders)
|
||||||
");
|
");
|
||||||
@@ -128,6 +183,62 @@ try {
|
|||||||
$partsInfo[(int)$r['iddatadb']][] = $r;
|
$partsInfo[(int)$r['iddatadb']][] = $r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mandatory-field config per template
|
||||||
|
$templateIds = array_values(array_unique(array_filter(array_map(
|
||||||
|
fn ($r) => (int)($r['templateid'] ?? 0),
|
||||||
|
$recordsInfo
|
||||||
|
))));
|
||||||
|
|
||||||
|
$requiredFixedByTemplate = []; // template_id => [ fixed_field_key => label ]
|
||||||
|
$requiredCustomByTemplate = []; // template_id => [ { mapping_id, field_label }, ... ]
|
||||||
|
|
||||||
|
if (!empty($templateIds)) {
|
||||||
|
$tplPlaceholders = implode(',', array_fill(0, count($templateIds), '?'));
|
||||||
|
|
||||||
|
// Required fixed fields (is_required synced from LIMS ObbligatorioWeb)
|
||||||
|
$stmt = $pdo->prepare("
|
||||||
|
SELECT template_id, fixed_field_key
|
||||||
|
FROM template_fixed_mapping
|
||||||
|
WHERE template_id IN ($tplPlaceholders) AND is_required = 1
|
||||||
|
");
|
||||||
|
$stmt->execute($templateIds);
|
||||||
|
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $r) {
|
||||||
|
$key = $r['fixed_field_key'];
|
||||||
|
if (in_array($key, $skipRequiredFixed, true)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$requiredFixedByTemplate[(int)$r['template_id']][$key] = $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required custom fields that are visible in the import grid
|
||||||
|
$stmt = $pdo->prepare("
|
||||||
|
SELECT id AS mapping_id, template_id, field_label
|
||||||
|
FROM template_mapping
|
||||||
|
WHERE template_id IN ($tplPlaceholders)
|
||||||
|
AND is_required = 1
|
||||||
|
AND is_visible_import = 1
|
||||||
|
");
|
||||||
|
$stmt->execute($templateIds);
|
||||||
|
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $r) {
|
||||||
|
$requiredCustomByTemplate[(int)$r['template_id']][] = [
|
||||||
|
'mapping_id' => (int)$r['mapping_id'],
|
||||||
|
'field_label' => $r['field_label'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom field values per record (import_data_details.id is the FK to datadb)
|
||||||
|
$stmt = $pdo->prepare("
|
||||||
|
SELECT id AS iddatadb, mapping_id, field_value
|
||||||
|
FROM import_data_details
|
||||||
|
WHERE id IN ($placeholders)
|
||||||
|
");
|
||||||
|
$stmt->execute($iddatadbList);
|
||||||
|
$customValuesByRecord = []; // iddatadb => [ mapping_id => field_value ]
|
||||||
|
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $r) {
|
||||||
|
$customValuesByRecord[(int)$r['iddatadb']][(int)$r['mapping_id']] = $r['field_value'];
|
||||||
|
}
|
||||||
|
|
||||||
// ── Run validators per row ──────────────────────────────────────────────
|
// ── Run validators per row ──────────────────────────────────────────────
|
||||||
|
|
||||||
$results = [];
|
$results = [];
|
||||||
@@ -137,9 +248,15 @@ try {
|
|||||||
$index = $rowInfo['index'];
|
$index = $rowInfo['index'];
|
||||||
|
|
||||||
// Build context for validators
|
// Build context for validators
|
||||||
|
$record = $recordsInfo[$iddatadb] ?? null;
|
||||||
|
$templateId = (int)($record['templateid'] ?? 0);
|
||||||
$ctx = [
|
$ctx = [
|
||||||
'record' => $recordsInfo[$iddatadb] ?? null,
|
'record' => $record,
|
||||||
'parts' => $partsInfo[$iddatadb] ?? [],
|
'parts' => $partsInfo[$iddatadb] ?? [],
|
||||||
|
'fixedAliasMap' => $fixedAliasMap,
|
||||||
|
'requiredFixed' => $requiredFixedByTemplate[$templateId] ?? [],
|
||||||
|
'requiredCustom' => $requiredCustomByTemplate[$templateId] ?? [],
|
||||||
|
'customValues' => $customValuesByRecord[$iddatadb] ?? [],
|
||||||
];
|
];
|
||||||
|
|
||||||
$errors = [];
|
$errors = [];
|
||||||
|
|||||||
Reference in New Issue
Block a user