import type { PostgrestError } from "@supabase/supabase-js"; import { toArray } from '@kit/shared/utils'; import type { AnalysisOrder } from "~/lib/types/order"; import type { AnalysisResponseElement } from '~/lib/types/analysis-response-element'; import { AnalysisOrderStatus } from '@/packages/shared/src/types/medipost-analysis'; import type { MedipostAnalysisResult, ResponseUuringuGrupp, } from '@/packages/shared/src/types/medipost-analysis'; import { getAnalysisResponseElementsForGroup } from "./medipostPrivateMessage.service"; import { getExistingAnalysisResponseElements, upsertAnalysisResponse, upsertAnalysisResponseElement, } from "../analysis-order.service"; import type { Logger } from './types'; type AnalysisResponseElementMapped = Omit< AnalysisResponseElement, 'created_at' | 'updated_at' | 'id' | 'analysis_response_id' >; export type SyncResult = | { isCompleted: boolean; isPartial?: undefined; } | { isPartial: boolean; isCompleted?: undefined; }; export default class MedipostAnalysisResultService { public async storeAnalysisResult({ messageResponse: { TellimuseNumber: orderNumber, TellimuseOlek, UuringuGrupp, }, analysisOrder, log, }: { messageResponse: Pick< NonNullable, 'TellimuseNumber' | 'TellimuseOlek' | 'UuringuGrupp' >; analysisOrder: AnalysisOrder; log: Logger; }): Promise { const orderStatus = AnalysisOrderStatus[TellimuseOlek]; const { analysisResponseId } = await upsertAnalysisResponse({ analysisOrderId: analysisOrder.id, orderNumber, orderStatus, userId: analysisOrder.user_id, }); const existingElements = await getExistingAnalysisResponseElements({ analysisResponseId, }); const analysisGroups = toArray(UuringuGrupp); log(`Order has results for ${analysisGroups.length} analysis groups`); const newElements = await this.getNewAnalysisResponseElements({ analysisGroups, existingElements, log, }); for (const element of newElements) { try { await upsertAnalysisResponseElement({ element: { ...element, analysis_response_id: analysisResponseId, }, }); } catch (e) { log( `Failed to create order response element for response id ${analysisResponseId}, element id '${element.analysis_element_original_id}'`, "error", e as PostgrestError, ); } } const hasAllResults = await this.hasAllAnalysisResponseElements({ analysisResponseId, analysisOrder, }); log(`Order has ${hasAllResults ? 'all' : 'some'} results, status is ${orderStatus}`); return hasAllResults ? { isCompleted: orderStatus === 'COMPLETED' } : { isPartial: true }; } private async getNewAnalysisResponseElements({ analysisGroups, existingElements, log, }: { analysisGroups: ResponseUuringuGrupp[]; existingElements: AnalysisResponseElement[]; log: Logger; }): Promise { const newElements: AnalysisResponseElementMapped[] = []; for (const analysisGroup of analysisGroups) { log( `[${analysisGroups.indexOf(analysisGroup) + 1}/${analysisGroups.length}] Syncing analysis group '${analysisGroup.UuringuGruppNimi}'`, ); const elements = await getAnalysisResponseElementsForGroup({ analysisGroup, existingElements, log, }); newElements.push(...elements); } return newElements; } private async hasAllAnalysisResponseElements({ analysisResponseId, analysisOrder, }: { analysisResponseId: number; analysisOrder: Pick; }): Promise { const allOrderResponseElements = await getExistingAnalysisResponseElements({ analysisResponseId, }); const expectedOrderResponseElements = analysisOrder.analysis_element_ids?.length ?? 0; return allOrderResponseElements.length >= expectedOrderResponseElements; } }