201 lines
7.6 KiB
PHP
201 lines
7.6 KiB
PHP
<?php
|
|
header('Content-Type: application/json');
|
|
include('include/headscript.php');
|
|
|
|
$dbHandler = DBHandlerSelect::getInstance();
|
|
$pdo = $dbHandler->getConnection();
|
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|
|
|
$data = json_decode(file_get_contents('php://input'), true);
|
|
|
|
$sourceIddatadb = isset($data['source_iddatadb']) ? (int)$data['source_iddatadb'] : 0;
|
|
$targetList = $data['target_iddatadb_list'] ?? [];
|
|
// Default true: se il client non manda il parametro, cloniamo comunque le note
|
|
// (comportamento di default richiesto, coerente con la checkbox pre-spuntata)
|
|
$cloneNotes = array_key_exists('clone_notes', $data) ? !empty($data['clone_notes']) : true;
|
|
$cloneAnalyses = !empty($data['clone_analyses']);
|
|
$overwrite = !empty($data['overwrite']);
|
|
|
|
$targetIds = array_values(array_unique(array_filter(array_map('intval', (array)$targetList), function ($v) use ($sourceIddatadb) {
|
|
return $v > 0 && $v !== $sourceIddatadb;
|
|
})));
|
|
|
|
if ($sourceIddatadb <= 0 || empty($targetIds)) {
|
|
echo json_encode([
|
|
'success' => false,
|
|
'message' => 'Missing source or target records'
|
|
]);
|
|
exit;
|
|
}
|
|
|
|
try {
|
|
$pdo->beginTransaction();
|
|
|
|
// 1. Load source parts
|
|
$stmtParts = $pdo->prepare("
|
|
SELECT id, part_number, part_description, mix, idmatrice, note, dateexpiry
|
|
FROM identification_parts
|
|
WHERE iddatadb = ?
|
|
AND part_description IS NOT NULL
|
|
AND TRIM(part_description) <> ''
|
|
ORDER BY part_number ASC, id ASC
|
|
");
|
|
$stmtParts->execute([$sourceIddatadb]);
|
|
$sourceParts = $stmtParts->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
if (empty($sourceParts)) {
|
|
$pdo->rollBack();
|
|
echo json_encode([
|
|
'success' => false,
|
|
'message' => 'No parts found for source record'
|
|
]);
|
|
exit;
|
|
}
|
|
|
|
// 2. Prepare statements
|
|
$stmtInsertPart = $pdo->prepare("
|
|
INSERT INTO identification_parts
|
|
(iddatadb, part_number, part_description, mix, idmatrice, note, dateexpiry, created_at, updated_at)
|
|
VALUES
|
|
(:iddatadb, :part_number, :part_description, :mix, :idmatrice, :note, :dateexpiry, NOW(), NOW())
|
|
");
|
|
|
|
$stmtLoadCF = $pdo->prepare("
|
|
SELECT field_id, value_id, value_text
|
|
FROM identification_parts_customfields
|
|
WHERE part_id = ?
|
|
ORDER BY id ASC
|
|
");
|
|
|
|
$stmtLoadAnalyses = $pdo->prepare("
|
|
SELECT idmatrice, analysis_recordkey, analysis_name, analysis_method,
|
|
analysis_level, is_web_selectable, is_accredited
|
|
FROM identification_parts_analyses
|
|
WHERE part_id = ?
|
|
ORDER BY id ASC
|
|
");
|
|
|
|
$stmtInsertAnalysis = $pdo->prepare("
|
|
INSERT INTO identification_parts_analyses
|
|
(part_id, iddatadb, idmatrice, analysis_recordkey, analysis_name, analysis_method,
|
|
analysis_level, is_web_selectable, is_accredited, created_at, updated_at)
|
|
VALUES
|
|
(:part_id, :iddatadb, :idmatrice, :analysis_recordkey, :analysis_name, :analysis_method,
|
|
:analysis_level, :is_web_selectable, :is_accredited, NOW(), NOW())
|
|
");
|
|
|
|
$stmtInsertCF = $pdo->prepare("
|
|
INSERT INTO identification_parts_customfields
|
|
(part_id, field_id, value_id, value_text, created_at, updated_at)
|
|
VALUES
|
|
(:part_id, :field_id, :value_id, :value_text, NOW(), NOW())
|
|
");
|
|
|
|
$details = [];
|
|
$totalClonedParts = 0;
|
|
$totalClonedAnalyses = 0;
|
|
$totalDeletedParts = 0;
|
|
|
|
// 2b. Se overwrite: elimina le parti esistenti dei target (e i loro figli)
|
|
if ($overwrite) {
|
|
$stmtSelectExisting = $pdo->prepare("SELECT id FROM identification_parts WHERE iddatadb = ?");
|
|
$stmtDeleteCFByPart = $pdo->prepare("DELETE FROM identification_parts_customfields WHERE part_id = ?");
|
|
$stmtDeleteAnByPart = $pdo->prepare("DELETE FROM identification_parts_analyses WHERE part_id = ?");
|
|
$stmtDeletePart = $pdo->prepare("DELETE FROM identification_parts WHERE id = ?");
|
|
|
|
foreach ($targetIds as $targetIddatadb) {
|
|
$stmtSelectExisting->execute([$targetIddatadb]);
|
|
$existingIds = $stmtSelectExisting->fetchAll(PDO::FETCH_COLUMN);
|
|
|
|
foreach ($existingIds as $existingPartId) {
|
|
$existingPartId = (int)$existingPartId;
|
|
$stmtDeleteCFByPart->execute([$existingPartId]);
|
|
$stmtDeleteAnByPart->execute([$existingPartId]);
|
|
$stmtDeletePart->execute([$existingPartId]);
|
|
$totalDeletedParts++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 3. Clone source parts to each target record
|
|
foreach ($targetIds as $targetIddatadb) {
|
|
$clonedCountForTarget = 0;
|
|
|
|
foreach ($sourceParts as $part) {
|
|
$stmtInsertPart->execute([
|
|
':iddatadb' => $targetIddatadb,
|
|
':part_number' => $part['part_number'],
|
|
':part_description' => $part['part_description'],
|
|
':mix' => $part['mix'] ?? 'N',
|
|
':idmatrice' => $part['idmatrice'] !== '' ? $part['idmatrice'] : null,
|
|
':note' => $cloneNotes ? ($part['note'] ?? null) : null,
|
|
':dateexpiry' => $part['dateexpiry'] ?? null,
|
|
]);
|
|
|
|
$newPartId = (int)$pdo->lastInsertId();
|
|
|
|
// Load source custom fields for this part
|
|
$stmtLoadCF->execute([(int)$part['id']]);
|
|
$customFields = $stmtLoadCF->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
foreach ($customFields as $cf) {
|
|
$stmtInsertCF->execute([
|
|
':part_id' => $newPartId,
|
|
':field_id' => (int)$cf['field_id'],
|
|
':value_id' => ($cf['value_id'] !== null && $cf['value_id'] !== '') ? (int)$cf['value_id'] : null,
|
|
':value_text' => $cf['value_text'] !== '' ? $cf['value_text'] : null,
|
|
]);
|
|
}
|
|
|
|
// Clone linked analyses, if requested
|
|
if ($cloneAnalyses) {
|
|
$stmtLoadAnalyses->execute([(int)$part['id']]);
|
|
$analyses = $stmtLoadAnalyses->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
foreach ($analyses as $an) {
|
|
$stmtInsertAnalysis->execute([
|
|
':part_id' => $newPartId,
|
|
':iddatadb' => $targetIddatadb,
|
|
':idmatrice' => ($an['idmatrice'] !== null && $an['idmatrice'] !== '') ? (int)$an['idmatrice'] : null,
|
|
':analysis_recordkey' => $an['analysis_recordkey'],
|
|
':analysis_name' => $an['analysis_name'] ?? null,
|
|
':analysis_method' => $an['analysis_method'] ?? null,
|
|
':analysis_level' => ($an['analysis_level'] !== null && $an['analysis_level'] !== '') ? (int)$an['analysis_level'] : null,
|
|
':is_web_selectable' => (int)($an['is_web_selectable'] ?? 0),
|
|
':is_accredited' => (int)($an['is_accredited'] ?? 0),
|
|
]);
|
|
$totalClonedAnalyses++;
|
|
}
|
|
}
|
|
|
|
$clonedCountForTarget++;
|
|
$totalClonedParts++;
|
|
}
|
|
|
|
$details[] = [
|
|
'target_iddatadb' => $targetIddatadb,
|
|
'cloned_parts' => $clonedCountForTarget
|
|
];
|
|
}
|
|
|
|
$pdo->commit();
|
|
|
|
echo json_encode([
|
|
'success' => true,
|
|
'source_iddatadb' => $sourceIddatadb,
|
|
'cloned_targets' => count($targetIds),
|
|
'total_cloned_parts' => $totalClonedParts,
|
|
'total_cloned_analyses' => $totalClonedAnalyses,
|
|
'details' => $details
|
|
]);
|
|
} catch (Throwable $e) {
|
|
if ($pdo->inTransaction()) {
|
|
$pdo->rollBack();
|
|
}
|
|
|
|
echo json_encode([
|
|
'success' => false,
|
|
'message' => 'Clone failed: ' . $e->getMessage()
|
|
]);
|
|
}
|