fix: deduplicate specimen elements in medipost XML generation
- Fix duplicate <Proov> elements when multiple analysis elements use same material type - Ensure analysis elements reference correct specimen order numbers - Move XML composition logic to separate service for better separation of concerns
This commit is contained in:
@@ -62,9 +62,19 @@ export async function composeOrderXML({
|
|||||||
'id',
|
'id',
|
||||||
);
|
);
|
||||||
|
|
||||||
const specimenSection = [];
|
// First, collect all unique materials across all analysis groups
|
||||||
const analysisSection = [];
|
const uniqueMaterials = new Map<string, {
|
||||||
let order = 1;
|
MaterjaliTyypOID: string;
|
||||||
|
MaterjaliTyyp: string;
|
||||||
|
MaterjaliNimi: string;
|
||||||
|
ProovinouKoodOID?: string;
|
||||||
|
ProovinouKood?: string;
|
||||||
|
order: number;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
let specimenOrder = 1;
|
||||||
|
|
||||||
|
// Collect all materials from all analysis groups
|
||||||
for (const currentGroup of analysisGroups) {
|
for (const currentGroup of analysisGroups) {
|
||||||
let relatedAnalysisElement = analysisElements?.find(
|
let relatedAnalysisElement = analysisElements?.find(
|
||||||
(element) => element.analysis_groups.id === currentGroup.id,
|
(element) => element.analysis_groups.id === currentGroup.id,
|
||||||
@@ -89,31 +99,86 @@ export async function composeOrderXML({
|
|||||||
|
|
||||||
for (const group of relatedAnalysisElement?.material_groups as MaterjalideGrupp[]) {
|
for (const group of relatedAnalysisElement?.material_groups as MaterjalideGrupp[]) {
|
||||||
const materials = toArray(group.Materjal);
|
const materials = toArray(group.Materjal);
|
||||||
const specimenXml = materials.flatMap(
|
for (const material of materials) {
|
||||||
({ MaterjaliNimi, MaterjaliTyyp, MaterjaliTyypOID, Konteiner }) => {
|
const { MaterjaliNimi, MaterjaliTyyp, MaterjaliTyypOID, Konteiner } = material;
|
||||||
return toArray(Konteiner).map((container) =>
|
const containers = toArray(Konteiner);
|
||||||
getSpecimen(
|
|
||||||
|
for (const container of containers) {
|
||||||
|
// Use MaterialTyyp as the key for deduplication
|
||||||
|
const materialKey = MaterjaliTyyp;
|
||||||
|
|
||||||
|
if (!uniqueMaterials.has(materialKey)) {
|
||||||
|
uniqueMaterials.set(materialKey, {
|
||||||
MaterjaliTyypOID,
|
MaterjaliTyypOID,
|
||||||
MaterjaliTyyp,
|
MaterjaliTyyp,
|
||||||
MaterjaliNimi,
|
MaterjaliNimi,
|
||||||
order,
|
ProovinouKoodOID: container.ProovinouKoodOID,
|
||||||
container.ProovinouKoodOID,
|
ProovinouKood: container.ProovinouKood,
|
||||||
container.ProovinouKood,
|
order: specimenOrder++,
|
||||||
),
|
});
|
||||||
);
|
}
|
||||||
},
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate specimen section from unique materials
|
||||||
|
const specimenSection = Array.from(uniqueMaterials.values()).map(material =>
|
||||||
|
getSpecimen(
|
||||||
|
material.MaterjaliTyypOID,
|
||||||
|
material.MaterjaliTyyp,
|
||||||
|
material.MaterjaliNimi,
|
||||||
|
material.order,
|
||||||
|
material.ProovinouKoodOID,
|
||||||
|
material.ProovinouKood,
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
specimenSection.push(...specimenXml);
|
// Generate analysis section with correct specimen references
|
||||||
|
const analysisSection = [];
|
||||||
|
for (const currentGroup of analysisGroups) {
|
||||||
|
let relatedAnalysisElement = analysisElements?.find(
|
||||||
|
(element) => element.analysis_groups.id === currentGroup.id,
|
||||||
|
);
|
||||||
|
const relatedAnalyses = analyses?.filter((analysis) => {
|
||||||
|
return analysis.analysis_elements.analysis_groups.id === currentGroup.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!relatedAnalysisElement) {
|
||||||
|
relatedAnalysisElement = relatedAnalyses?.find(
|
||||||
|
(relatedAnalysis) =>
|
||||||
|
relatedAnalysis.analysis_elements.analysis_groups.id ===
|
||||||
|
currentGroup.id,
|
||||||
|
)?.analysis_elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!relatedAnalysisElement || !relatedAnalysisElement.material_groups) {
|
||||||
|
throw new Error(
|
||||||
|
`Failed to find related analysis element for group ${currentGroup.name} (id: ${currentGroup.id})`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the specimen order number for this analysis group
|
||||||
|
let specimenOrderNumber = 1;
|
||||||
|
for (const group of relatedAnalysisElement?.material_groups as MaterjalideGrupp[]) {
|
||||||
|
const materials = toArray(group.Materjal);
|
||||||
|
for (const material of materials) {
|
||||||
|
const materialKey = material.MaterjaliTyyp;
|
||||||
|
const uniqueMaterial = uniqueMaterials.get(materialKey);
|
||||||
|
if (uniqueMaterial) {
|
||||||
|
specimenOrderNumber = uniqueMaterial.order;
|
||||||
|
break; // Use the first material's order number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (specimenOrderNumber > 1) break; // Found a specimen, use it
|
||||||
}
|
}
|
||||||
|
|
||||||
const groupXml = getAnalysisGroup(
|
const groupXml = getAnalysisGroup(
|
||||||
currentGroup.original_id,
|
currentGroup.original_id,
|
||||||
currentGroup.name,
|
currentGroup.name,
|
||||||
order,
|
specimenOrderNumber,
|
||||||
relatedAnalysisElement,
|
relatedAnalysisElement,
|
||||||
);
|
);
|
||||||
order++;
|
|
||||||
analysisSection.push(groupXml);
|
analysisSection.push(groupXml);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user