'use server'; import { getAnalysisGroup, getClientInstitution, getClientPerson, getConfidentiality, getOrderEnteredPerson, getPais, getPatient, getProviderInstitution, getSpecimen, } from '@/lib/templates/medipost-order'; import { MaterjalideGrupp } from '@/lib/types/medipost'; import { uniqBy } from 'lodash'; import { toArray } from '@kit/shared/utils'; import { Tables } from '@kit/supabase/database'; import { AnalysesWithGroupsAndElements } from '../analyses.service'; import { AnalysisElement } from '../analysis-element.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, comment, }: { analyses: AnalysesWithGroupsAndElements; analysisElements: AnalysisElement[]; person: { idCode: string; firstName: string; lastName: string; phone: string; }; orderId: number; 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< string, { 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) { let relatedAnalysisElements = analysisElements?.filter( ({ analysis_groups }) => analysis_groups.id === currentGroup.id, ); if (!relatedAnalysisElements || relatedAnalysisElements.length === 0) { relatedAnalysisElements = analyses .filter( ({ analysis_elements }) => analysis_elements.analysis_groups.id === currentGroup.id, ) .flatMap(({ analysis_elements }) => analysis_elements); } if (!relatedAnalysisElements || relatedAnalysisElements.length === 0) { throw new Error( `Failed to find related analysis elements for group ${currentGroup.name} (id: ${currentGroup.id})`, ); } for (const analysisElement of relatedAnalysisElements) { for (const { Materjal, } of analysisElement.material_groups as MaterjalideGrupp[]) { for (const material of toArray(Materjal)) { const { MaterjaliTyyp } = material; for (const container of toArray(material.Konteiner)) { if (uniqueMaterials.has(MaterjaliTyyp)) { continue; } uniqueMaterials.set(MaterjaliTyyp, { MaterjaliTyypOID: material.MaterjaliTyypOID, MaterjaliTyyp: material.MaterjaliTyyp, MaterjaliNimi: material.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 relatedAnalysisElements = analysisElements?.filter( (element) => element.analysis_groups.id === currentGroup.id, ); if (!relatedAnalysisElements) { relatedAnalysisElements = analyses .filter( ({ analysis_elements }) => analysis_elements.analysis_groups.id === currentGroup.id, ) .flatMap(({ analysis_elements }) => analysis_elements); } if (!relatedAnalysisElements || relatedAnalysisElements.length === 0) { throw new Error( `Failed to find related analysis element for group ${currentGroup.name} (id: ${currentGroup.id})`, ); } const uuringElementInputs: { analysisElement: Tables<{ schema: 'medreport' }, 'analysis_elements'>; specimenOrderNr: number; }[] = []; for (const analysisElement of relatedAnalysisElements) { for (const group of analysisElement.material_groups as MaterjalideGrupp[]) { const materials = toArray(group.Materjal); for (const material of materials) { const uniqueMaterial = uniqueMaterials.get(material.MaterjaliTyyp); if (!uniqueMaterial) { console.info( `Unique material not found for material: ${material.MaterjaliTyyp}, analysis element: ${analysisElement.id} ${analysisElement.analysis_id_original} ${analysisElement.analysis_name_lab}`, ); continue; } uuringElementInputs.push({ analysisElement, specimenOrderNr: uniqueMaterial.order, }); break; } } } const groupXml = getAnalysisGroup( currentGroup.original_id, currentGroup.name, uuringElementInputs, ); analysisSection.push(groupXml); } return ` ${getPais(USER, RECIPIENT, orderId, 'OL')} ${orderId} ${getClientInstitution()} ${getProviderInstitution()} ${getClientPerson()} ${getOrderEnteredPerson()} ${comment ?? ''} ${getPatient(person)} ${getConfidentiality()} ${specimenSection.join('')} ${analysisSection?.join('')} `; }