diff --git a/lib/services/medipostXML.service.ts b/lib/services/medipostXML.service.ts index ad6fb04..3b55506 100644 --- a/lib/services/medipostXML.service.ts +++ b/lib/services/medipostXML.service.ts @@ -62,9 +62,19 @@ export async function composeOrderXML({ 'id', ); - const specimenSection = []; - const analysisSection = []; - let order = 1; + // First, collect all unique materials across all analysis groups + const uniqueMaterials = new Map(); + + let specimenOrder = 1; + + // Collect all materials from all analysis groups for (const currentGroup of analysisGroups) { let relatedAnalysisElement = analysisElements?.find( (element) => element.analysis_groups.id === currentGroup.id, @@ -89,31 +99,86 @@ export async function composeOrderXML({ for (const group of relatedAnalysisElement?.material_groups as MaterjalideGrupp[]) { const materials = toArray(group.Materjal); - const specimenXml = materials.flatMap( - ({ MaterjaliNimi, MaterjaliTyyp, MaterjaliTyypOID, Konteiner }) => { - return toArray(Konteiner).map((container) => - getSpecimen( + for (const material of materials) { + const { MaterjaliNimi, MaterjaliTyyp, MaterjaliTyypOID, Konteiner } = material; + const containers = toArray(Konteiner); + + for (const container of containers) { + // Use MaterialTyyp as the key for deduplication + const materialKey = MaterjaliTyyp; + + if (!uniqueMaterials.has(materialKey)) { + uniqueMaterials.set(materialKey, { MaterjaliTyypOID, MaterjaliTyyp, MaterjaliNimi, - order, - container.ProovinouKoodOID, - container.ProovinouKood, - ), - ); - }, - ); + ProovinouKoodOID: container.ProovinouKoodOID, + ProovinouKood: container.ProovinouKood, + order: specimenOrder++, + }); + } + } + } + } + } - specimenSection.push(...specimenXml); + // 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, + ) + ); + + // 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( currentGroup.original_id, currentGroup.name, - order, + specimenOrderNumber, relatedAnalysisElement, ); - order++; analysisSection.push(groupXml); }