prettier fix

This commit is contained in:
Danel Kungla
2025-09-19 17:22:36 +03:00
parent efa94b3322
commit 0c2cfe6d18
509 changed files with 17988 additions and 9920 deletions

View File

@@ -1,36 +1,42 @@
'use server';
import type { PostgrestError } from '@supabase/supabase-js';
import axios from 'axios';
import {
GetMessageListResponse,
MedipostAction,
} from '@/lib/types/medipost';
import { GetMessageListResponse, MedipostAction } from '@/lib/types/medipost';
import { createUserAnalysesApi } from '@/packages/features/user-analyses/src/server/api';
import { AnalysisOrderStatus } from '@/packages/shared/src/types/medipost-analysis';
import type {
ResponseUuringuGrupp,
MedipostOrderResponse,
ResponseUuringuGrupp,
UuringElement,
} from '@/packages/shared/src/types/medipost-analysis';
import { getSupabaseServerAdminClient } from '@/packages/supabase/src/clients/server-admin-client';
import axios from 'axios';
import { toArray } from '@kit/shared/utils';
import { Tables } from '@kit/supabase/database';
import type { AnalysisOrder } from '~/lib/types/analysis-order';
import type { AnalysisResponseElement } from '~/lib/types/analysis-response-element';
import { createUserAnalysesApi } from '@/packages/features/user-analyses/src/server/api';
import { Tables } from '@kit/supabase/database';
import { getSupabaseServerAdminClient } from '@/packages/supabase/src/clients/server-admin-client';
import { getAnalysisElementsAdmin } from '../analysis-element.service';
import { getAccountAdmin } from '../account.service';
import { getAnalyses } from '../analyses.service';
import { upsertMedipostActionLog, getLatestMessage } from './medipostMessageBase.service';
import { validateMedipostResponse } from './medipostValidate.service';
import { getAnalysisElementsAdmin } from '../analysis-element.service';
import {
getExistingAnalysisResponseElements,
upsertAnalysisResponse,
upsertAnalysisResponseElement,
} from '../analysis-order.service';
import { logMedipostDispatch } from '../audit.service';
import { getAnalysisOrder, updateAnalysisOrderStatus } from '../order.service';
import { parseXML } from '../util/xml.service';
import { composeOrderXML, OrderedAnalysisElement } from './medipostXML.service';
import { getAccountAdmin } from '../account.service';
import { logMedipostDispatch } from '../audit.service';
import { MedipostValidationError } from './MedipostValidationError';
import { upsertAnalysisResponseElement, getExistingAnalysisResponseElements, upsertAnalysisResponse } from '../analysis-order.service';
import {
getLatestMessage,
upsertMedipostActionLog,
} from './medipostMessageBase.service';
import { validateMedipostResponse } from './medipostValidate.service';
import { OrderedAnalysisElement, composeOrderXML } from './medipostXML.service';
const BASE_URL = process.env.MEDIPOST_URL!;
const USER = process.env.MEDIPOST_USER!;
@@ -56,73 +62,102 @@ export async function getLatestPrivateMessageListItem({
throw new Error('Failed to get private message list');
}
return await getLatestMessage({ messages: data?.messages, excludedMessageIds });
return await getLatestMessage({
messages: data?.messages,
excludedMessageIds,
});
}
const logger = (analysisOrder: AnalysisOrder, externalId: string, analysisResponseId: string) => (message: string, error?: PostgrestError | null) => {
const messageFormatted = `[${analysisOrder.id}] [${externalId}] [${analysisResponseId}] ${message}`;
if (error) {
console.info(messageFormatted, error);
} else {
console.info(messageFormatted);
}
};
const logger =
(
analysisOrder: AnalysisOrder,
externalId: string,
analysisResponseId: string,
) =>
(message: string, error?: PostgrestError | null) => {
const messageFormatted = `[${analysisOrder.id}] [${externalId}] [${analysisResponseId}] ${message}`;
if (error) {
console.info(messageFormatted, error);
} else {
console.info(messageFormatted);
}
};
export async function canCreateAnalysisResponseElement({
existingElements,
groupUuring: {
UuringuElement: {
UuringOlek: status,
UuringId: analysisElementOriginalId,
},
UuringuElement: { UuringOlek: status, UuringId: analysisElementOriginalId },
},
responseValue,
log,
}: {
existingElements: Pick<AnalysisResponseElement, 'analysis_element_original_id' | 'status' | 'response_value'>[];
groupUuring: { UuringuElement: Pick<UuringElement, 'UuringOlek' | 'UuringId'> };
existingElements: Pick<
AnalysisResponseElement,
'analysis_element_original_id' | 'status' | 'response_value'
>[];
groupUuring: {
UuringuElement: Pick<UuringElement, 'UuringOlek' | 'UuringId'>;
};
responseValue: number | null;
log: ReturnType<typeof logger>;
}) {
const existingAnalysisResponseElement = existingElements.find(({ analysis_element_original_id }) => analysis_element_original_id === analysisElementOriginalId);
const existingAnalysisResponseElement = existingElements.find(
({ analysis_element_original_id }) =>
analysis_element_original_id === analysisElementOriginalId,
);
if (!existingAnalysisResponseElement) {
return true;
}
if (Number(existingAnalysisResponseElement.status) > status) {
log(`Analysis response element id=${analysisElementOriginalId} already exists for order in higher status ${existingAnalysisResponseElement.status} than ${status}`);
log(
`Analysis response element id=${analysisElementOriginalId} already exists for order in higher status ${existingAnalysisResponseElement.status} than ${status}`,
);
return false;
}
if (existingAnalysisResponseElement.response_value && !responseValue) {
log(`Analysis response element id=${analysisElementOriginalId} already exists for order with response value ${existingAnalysisResponseElement.response_value} but new response has no value`);
log(
`Analysis response element id=${analysisElementOriginalId} already exists for order with response value ${existingAnalysisResponseElement.response_value} but new response has no value`,
);
return false;
}
return true;
}
export async function getAnalysisResponseElementsForGroup({
analysisGroup,
existingElements,
log,
}: {
analysisGroup: Pick<ResponseUuringuGrupp, 'UuringuGruppNimi' | 'Uuring'>;
existingElements: Pick<AnalysisResponseElement, 'analysis_element_original_id' | 'status' | 'response_value'>[];
existingElements: Pick<
AnalysisResponseElement,
'analysis_element_original_id' | 'status' | 'response_value'
>[];
log: ReturnType<typeof logger>;
}) {
const groupUuringItems = toArray(analysisGroup.Uuring as ResponseUuringuGrupp['Uuring']);
log(`Order has results in group '${analysisGroup.UuringuGruppNimi}' for ${groupUuringItems.length} analysis elements`);
const groupUuringItems = toArray(
analysisGroup.Uuring as ResponseUuringuGrupp['Uuring'],
);
log(
`Order has results in group '${analysisGroup.UuringuGruppNimi}' for ${groupUuringItems.length} analysis elements`,
);
const results: Omit<AnalysisResponseElement, 'created_at' | 'updated_at' | 'id' | 'analysis_response_id'>[] = [];
const results: Omit<
AnalysisResponseElement,
'created_at' | 'updated_at' | 'id' | 'analysis_response_id'
>[] = [];
for (const groupUuring of groupUuringItems) {
const groupUuringElement = groupUuring.UuringuElement;
const elementAnalysisResponses = toArray(groupUuringElement.UuringuVastus);
const status = groupUuringElement.UuringOlek;
log(`Group uuring '${analysisGroup.UuringuGruppNimi}' has status ${status}`);
log(
`Group uuring '${analysisGroup.UuringuGruppNimi}' has status ${status}`,
);
for (const response of elementAnalysisResponses) {
const analysisElementOriginalId = groupUuringElement.UuringId;
@@ -135,12 +170,20 @@ export async function getAnalysisResponseElementsForGroup({
return valueAsNumber;
})();
if (!await canCreateAnalysisResponseElement({ existingElements, groupUuring, responseValue, log })) {
if (
!(await canCreateAnalysisResponseElement({
existingElements,
groupUuring,
responseValue,
log,
}))
) {
continue;
}
const mappedResponse = createUserAnalysesApi(getSupabaseServerAdminClient())
.mapUuringVastus({ uuringVastus: response });
const mappedResponse = createUserAnalysesApi(
getSupabaseServerAdminClient(),
).mapUuringVastus({ uuringVastus: response });
results.push({
analysis_element_original_id: analysisElementOriginalId,
@@ -153,7 +196,8 @@ export async function getAnalysisResponseElementsForGroup({
response_value: mappedResponse.responseValue,
unit: groupUuringElement.Mootyhik ?? null,
original_response_element: groupUuringElement,
analysis_name: groupUuringElement.UuringNimi || groupUuringElement.KNimetus,
analysis_name:
groupUuringElement.UuringNimi || groupUuringElement.KNimetus,
comment: groupUuringElement.UuringuKommentaar ?? null,
status: status.toString(),
response_value_is_within_norm: mappedResponse.responseValueIsWithinNorm,
@@ -174,9 +218,14 @@ async function getNewAnalysisResponseElements({
existingElements: AnalysisResponseElement[];
log: ReturnType<typeof logger>;
}) {
const newElements: Omit<AnalysisResponseElement, 'created_at' | 'updated_at' | 'id' | 'analysis_response_id'>[] = [];
const newElements: Omit<
AnalysisResponseElement,
'created_at' | 'updated_at' | 'id' | 'analysis_response_id'
>[] = [];
for (const analysisGroup of analysisGroups) {
log(`[${analysisGroups.indexOf(analysisGroup) + 1}/${analysisGroups.length}] Syncing analysis group '${analysisGroup.UuringuGruppNimi}'`);
log(
`[${analysisGroups.indexOf(analysisGroup) + 1}/${analysisGroups.length}] Syncing analysis group '${analysisGroup.UuringuGruppNimi}'`,
);
const elements = await getAnalysisResponseElementsForGroup({
analysisGroup,
existingElements,
@@ -194,7 +243,9 @@ async function hasAllAnalysisResponseElements({
analysisResponseId: number;
order: Pick<AnalysisOrder, 'analysis_element_ids'>;
}) {
const allOrderResponseElements = await getExistingAnalysisResponseElements({ analysisResponseId });
const allOrderResponseElements = await getExistingAnalysisResponseElements({
analysisResponseId,
});
const expectedOrderResponseElements = order.analysis_element_ids?.length ?? 0;
return allOrderResponseElements.length >= expectedOrderResponseElements;
}
@@ -208,7 +259,10 @@ export async function syncPrivateMessage({
},
order,
}: {
messageResponse: Pick<NonNullable<MedipostOrderResponse['Saadetis']['Vastus']>, 'ValisTellimuseId' | 'TellimuseNumber' | 'TellimuseOlek' | 'UuringuGrupp'>;
messageResponse: Pick<
NonNullable<MedipostOrderResponse['Saadetis']['Vastus']>,
'ValisTellimuseId' | 'TellimuseNumber' | 'TellimuseOlek' | 'UuringuGrupp'
>;
order: Tables<{ schema: 'medreport' }, 'analysis_orders'>;
}) {
const supabase = getSupabaseServerAdminClient();
@@ -232,11 +286,17 @@ export async function syncPrivateMessage({
userId: analysisOrder.user_id,
});
const existingElements = await getExistingAnalysisResponseElements({ analysisResponseId });
const existingElements = await getExistingAnalysisResponseElements({
analysisResponseId,
});
const analysisGroups = toArray(UuringuGrupp);
log(`Order has results for ${analysisGroups.length} analysis groups`);
const newElements = await getNewAnalysisResponseElements({ analysisGroups, existingElements, log });
const newElements = await getNewAnalysisResponseElements({
analysisGroups,
existingElements,
log,
});
for (const element of newElements) {
try {
@@ -247,11 +307,14 @@ export async function syncPrivateMessage({
},
});
} catch (e) {
log(`Failed to create order response element for response id ${analysisResponseId}, element id '${element.analysis_element_original_id}' (order id: ${order.id})`, e as PostgrestError);
log(
`Failed to create order response element for response id ${analysisResponseId}, element id '${element.analysis_element_original_id}' (order id: ${order.id})`,
e as PostgrestError,
);
}
}
return await hasAllAnalysisResponseElements({ analysisResponseId, order })
return (await hasAllAnalysisResponseElements({ analysisResponseId, order }))
? { isCompleted: orderStatus === 'COMPLETED' }
: { isPartial: true };
}
@@ -276,7 +339,9 @@ export async function readPrivateMessageResponse({
let analysisOrderId: number | undefined = undefined;
try {
const privateMessage = await getLatestPrivateMessageListItem({ excludedMessageIds });
const privateMessage = await getLatestPrivateMessageListItem({
excludedMessageIds,
});
messageId = privateMessage?.messageId ?? null;
if (!privateMessage || !messageId) {
@@ -286,17 +351,18 @@ export async function readPrivateMessageResponse({
hasPartialAnalysisResponse: false,
hasFullAnalysisResponse: false,
medusaOrderId: undefined,
analysisOrderId: undefined
analysisOrderId: undefined,
};
}
const { messageId: privateMessageId } = privateMessage;
const { message: privateMessageContent, xml: privateMessageXml } = await getPrivateMessage(
privateMessageId,
);
const { message: privateMessageContent, xml: privateMessageXml } =
await getPrivateMessage(privateMessageId);
const messageResponse = privateMessageContent?.Saadetis?.Vastus;
const medipostExternalOrderId = privateMessageContent?.Saadetis?.Tellimus?.ValisTellimuseId || messageResponse?.ValisTellimuseId;
const medipostExternalOrderId =
privateMessageContent?.Saadetis?.Tellimus?.ValisTellimuseId ||
messageResponse?.ValisTellimuseId;
const patientPersonalCode = messageResponse?.Patsient.Isikukood?.toString();
analysisOrderId = Number(medipostExternalOrderId);
@@ -318,27 +384,36 @@ export async function readPrivateMessageResponse({
hasPartialAnalysisResponse: false,
hasFullAnalysisResponse: false,
medusaOrderId: hasInvalidOrderId ? undefined : medusaOrderId,
analysisOrderId: hasInvalidOrderId ? undefined : analysisOrderId
analysisOrderId: hasInvalidOrderId ? undefined : analysisOrderId,
};
}
let analysisOrder: AnalysisOrder;
try {
analysisOrder = await getAnalysisOrder({ analysisOrderId })
analysisOrder = await getAnalysisOrder({ analysisOrderId });
medusaOrderId = analysisOrder.medusa_order_id;
} catch (e) {
if (IS_ENABLED_DELETE_PRIVATE_MESSAGE) {
await deletePrivateMessage(privateMessageId);
}
throw new Error(`No analysis order found for Medipost message ValisTellimuseId=${medipostExternalOrderId}`);
throw new Error(
`No analysis order found for Medipost message ValisTellimuseId=${medipostExternalOrderId}`,
);
}
const orderPerson = await getAccountAdmin({ primaryOwnerUserId: analysisOrder.user_id });
const orderPerson = await getAccountAdmin({
primaryOwnerUserId: analysisOrder.user_id,
});
if (orderPerson.personal_code !== patientPersonalCode) {
throw new Error(`Order person personal code does not match Medipost message Patsient.Isikukood=${patientPersonalCode}, orderPerson.personal_code=${orderPerson.personal_code}`);
throw new Error(
`Order person personal code does not match Medipost message Patsient.Isikukood=${patientPersonalCode}, orderPerson.personal_code=${orderPerson.personal_code}`,
);
}
const status = await syncPrivateMessage({ messageResponse, order: analysisOrder });
const status = await syncPrivateMessage({
messageResponse,
order: analysisOrder,
});
await upsertMedipostActionLog({
action: 'sync_analysis_results_from_medipost',
@@ -349,11 +424,17 @@ export async function readPrivateMessageResponse({
medipostExternalOrderId,
});
if (status.isPartial) {
await updateAnalysisOrderStatus({ medusaOrderId, orderStatus: 'PARTIAL_ANALYSIS_RESPONSE' });
await updateAnalysisOrderStatus({
medusaOrderId,
orderStatus: 'PARTIAL_ANALYSIS_RESPONSE',
});
hasAnalysisResponse = true;
hasPartialAnalysisResponse = true;
} else if (status.isCompleted) {
await updateAnalysisOrderStatus({ medusaOrderId, orderStatus: 'FULL_ANALYSIS_RESPONSE' });
await updateAnalysisOrderStatus({
medusaOrderId,
orderStatus: 'FULL_ANALYSIS_RESPONSE',
});
if (IS_ENABLED_DELETE_PRIVATE_MESSAGE) {
await deletePrivateMessage(privateMessageId);
}
@@ -361,10 +442,19 @@ export async function readPrivateMessageResponse({
hasFullAnalysisResponse = true;
}
} catch (e) {
console.warn(`Failed to process private message id=${messageId}, message=${(e as Error).message}`);
console.warn(
`Failed to process private message id=${messageId}, message=${(e as Error).message}`,
);
}
return { messageId, hasAnalysisResponse, hasPartialAnalysisResponse, hasFullAnalysisResponse, medusaOrderId, analysisOrderId };
return {
messageId,
hasAnalysisResponse,
hasPartialAnalysisResponse,
hasFullAnalysisResponse,
medusaOrderId,
analysisOrderId,
};
}
export async function deletePrivateMessage(messageId: string) {
@@ -430,7 +520,9 @@ export async function sendOrderToMedipost({
orderedAnalysisElements: OrderedAnalysisElement[];
}) {
const medreportOrder = await getAnalysisOrder({ medusaOrderId });
const account = await getAccountAdmin({ primaryOwnerUserId: medreportOrder.user_id });
const account = await getAccountAdmin({
primaryOwnerUserId: medreportOrder.user_id,
});
const orderedAnalysesIds = orderedAnalysisElements
.map(({ analysisId }) => analysisId)
@@ -441,11 +533,17 @@ export async function sendOrderToMedipost({
const analyses = await getAnalyses({ ids: orderedAnalysesIds });
if (analyses.length !== orderedAnalysesIds.length) {
throw new Error(`Got ${analyses.length} analyses, expected ${orderedAnalysesIds.length}`);
throw new Error(
`Got ${analyses.length} analyses, expected ${orderedAnalysesIds.length}`,
);
}
const analysisElements = await getAnalysisElementsAdmin({ ids: orderedAnalysisElementsIds });
const analysisElements = await getAnalysisElementsAdmin({
ids: orderedAnalysisElementsIds,
});
if (analysisElements.length !== orderedAnalysisElementsIds.length) {
throw new Error(`Got ${analysisElements.length} analysis elements, expected ${orderedAnalysisElementsIds.length}`);
throw new Error(
`Got ${analysisElements.length} analysis elements, expected ${orderedAnalysisElementsIds.length}`,
);
}
const orderXml = await composeOrderXML({