'use server'; import { getAnalysisGroup, getClientInstitution, getClientPerson, getConfidentiality, getOrderEnteredPerson, getPais, getPatient, getProviderInstitution, getSpecimen, } from '@/lib/templates/medipost-order'; import { MaterjalideGrupp, } from '@/lib/types/medipost'; import { toArray } from '@/lib/utils'; import { uniqBy } from 'lodash'; import { Tables } from '@kit/supabase/database'; import { AnalysisElement } from './analysis-element.service'; import { AnalysesWithGroupsAndElements } from './analyses.service'; const USER = process.env.MEDIPOST_USER!; const RECIPIENT = process.env.MEDIPOST_RECIPIENT!; export type OrderedAnalysisElement = { analysisElementId?: number; analysisId?: number; } export async function composeOrderXML({ analyses, analysisElements, person, orderId, orderCreatedAt, comment, }: { analyses: AnalysesWithGroupsAndElements; analysisElements: AnalysisElement[]; person: { idCode: string; firstName: string; lastName: string; phone: string; }; orderId: number; orderCreatedAt: Date; comment?: string; }) { const analysisGroups: Tables<{ schema: 'medreport' }, 'analysis_groups'>[] = uniqBy( ( analysisElements?.flatMap(({ analysis_groups }) => analysis_groups) ?? [] ).concat( analyses?.flatMap( ({ analysis_elements }) => analysis_elements.analysis_groups, ) ?? [], ), 'id', ); // 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, ); 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})`, ); } for (const group of relatedAnalysisElement?.material_groups as MaterjalideGrupp[]) { const materials = toArray(group.Materjal); 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, ProovinouKoodOID: container.ProovinouKoodOID, 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, ) ); // 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, specimenOrderNumber, relatedAnalysisElement, ); analysisSection.push(groupXml); } return ` ${getPais(USER, RECIPIENT, orderId)} ${orderId} ${getClientInstitution()} ${getProviderInstitution()} ${getClientPerson()} ${getOrderEnteredPerson()} ${comment ?? ''} ${getPatient(person)} ${getConfidentiality()} ${specimenSection.join('')} ${analysisSection?.join('')} `; }