286 lines
9.2 KiB
TypeScript
286 lines
9.2 KiB
TypeScript
import { createClient as createCustomClient } from '@supabase/supabase-js';
|
|
|
|
import axios from 'axios';
|
|
import { format } from 'date-fns';
|
|
import { XMLParser } from 'fast-xml-parser';
|
|
import { IMedipostResponse_GetPublicMessageList } from './types';
|
|
|
|
function getLatestMessage(messages: IMedipostResponse_GetPublicMessageList['messages']): IMedipostResponse_GetPublicMessageList['messages'][number] | null {
|
|
if (!messages?.length) {
|
|
return null;
|
|
}
|
|
|
|
return messages.reduce((prev, current) =>
|
|
Number(prev.messageId) > Number(current.messageId) ? prev : current,
|
|
);
|
|
}
|
|
|
|
function toArray<T>(input?: T | T[] | null): T[] {
|
|
if (!input) return [];
|
|
return Array.isArray(input) ? input : [input];
|
|
}
|
|
|
|
export default async function syncAnalysisGroups() {
|
|
const baseUrl = process.env.MEDIPOST_URL;
|
|
const user = process.env.MEDIPOST_USER;
|
|
const password = process.env.MEDIPOST_PASSWORD;
|
|
const sender = process.env.MEDIPOST_MESSAGE_SENDER;
|
|
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
|
|
const supabaseServiceRoleKey = process.env.SUPABASE_SERVICE_ROLE_KEY;
|
|
|
|
if (
|
|
!baseUrl ||
|
|
!supabaseUrl ||
|
|
!supabaseServiceRoleKey ||
|
|
!user ||
|
|
!password ||
|
|
!sender
|
|
) {
|
|
throw new Error('Could not access all necessary environment variables');
|
|
}
|
|
|
|
const supabase = createCustomClient(supabaseUrl, supabaseServiceRoleKey, {
|
|
auth: {
|
|
persistSession: false,
|
|
autoRefreshToken: false,
|
|
detectSessionInUrl: false,
|
|
},
|
|
});
|
|
|
|
try {
|
|
console.info('Getting latest public message id');
|
|
const { data: lastChecked } = await supabase
|
|
.schema('audit')
|
|
.from('sync_entries')
|
|
.select('created_at')
|
|
.eq('status', 'SUCCESS')
|
|
.order('created_at')
|
|
.limit(1);
|
|
const lastEntry = lastChecked?.[0];
|
|
const lastCheckedDate = lastEntry
|
|
? format(lastEntry.created_at, 'yyyy-MM-dd HH:mm:ss')
|
|
: null;
|
|
|
|
console.info('Getting public message list');
|
|
const { data, status } = await axios.get<IMedipostResponse_GetPublicMessageList>(baseUrl, {
|
|
params: {
|
|
Action: 'GetPublicMessageList',
|
|
User: user,
|
|
Password: password,
|
|
//Sender: sender,
|
|
// ...(lastCheckedDate && { LastChecked: lastCheckedDate }),
|
|
MessageType: 'Teenus',
|
|
},
|
|
});
|
|
|
|
if (!data || status !== 200 || data.code !== 0) {
|
|
console.error("Failed to get public message list, status: ", status, data);
|
|
throw new Error('Failed to get public message list');
|
|
}
|
|
|
|
if (!data.messages?.length) {
|
|
console.info('No new data received');
|
|
return supabase.schema('audit').from('sync_entries').insert({
|
|
operation: 'ANALYSES_SYNC',
|
|
comment: 'No new data received',
|
|
status: 'SUCCESS',
|
|
changed_by_role: 'service_role',
|
|
});
|
|
}
|
|
|
|
// GET PUBLIC MESSAGE WITH GIVEN ID
|
|
const latestMessage = getLatestMessage(data?.messages)!;
|
|
console.info('Getting public message with id: ', latestMessage.messageId);
|
|
|
|
const { data: publicMessageData } = await axios.get(baseUrl, {
|
|
params: {
|
|
Action: 'GetPublicMessage',
|
|
User: user,
|
|
Password: password,
|
|
MessageId: latestMessage.messageId,
|
|
},
|
|
headers: {
|
|
Accept: 'application/xml',
|
|
},
|
|
});
|
|
|
|
const parser = new XMLParser({ ignoreAttributes: false });
|
|
const parsed = parser.parse(publicMessageData);
|
|
|
|
if (parsed.ANSWER?.CODE && parsed.ANSWER?.CODE !== 0) {
|
|
throw new Error(
|
|
`Failed to get public message (id: ${latestMessage.messageId})`,
|
|
);
|
|
}
|
|
|
|
// SAVE PUBLIC MESSAGE DATA
|
|
|
|
const providers = toArray(parsed?.Saadetis?.Teenused.Teostaja);
|
|
const analysisGroups = providers.flatMap((provider) =>
|
|
toArray(provider.UuringuGrupp),
|
|
);
|
|
|
|
if (!parsed || !analysisGroups.length) {
|
|
return supabase.schema('audit').from('sync_entries').insert({
|
|
operation: 'ANALYSES_SYNC',
|
|
comment: 'No data received',
|
|
status: 'FAIL',
|
|
changed_by_role: 'service_role',
|
|
});
|
|
}
|
|
|
|
const codes: any[] = [];
|
|
for (const analysisGroup of analysisGroups) {
|
|
// SAVE ANALYSIS GROUP
|
|
const { data: insertedAnalysisGroup, error } = await supabase
|
|
.schema('medreport')
|
|
.from('analysis_groups')
|
|
.upsert(
|
|
{
|
|
original_id: analysisGroup.UuringuGruppId,
|
|
name: analysisGroup.UuringuGruppNimi,
|
|
order: analysisGroup.UuringuGruppJarjekord,
|
|
},
|
|
{ onConflict: 'original_id', ignoreDuplicates: false },
|
|
)
|
|
.select('id');
|
|
|
|
if (error || !insertedAnalysisGroup[0]?.id) {
|
|
throw new Error(
|
|
`Failed to insert analysis group (id: ${analysisGroup.UuringuGruppId}), error: ${error?.message}`,
|
|
);
|
|
}
|
|
const analysisGroupId = insertedAnalysisGroup[0].id;
|
|
|
|
const analysisGroupCodes = toArray(analysisGroup.Kood);
|
|
codes.push(
|
|
...analysisGroupCodes.map((kood) => ({
|
|
hk_code: kood.HkKood,
|
|
hk_code_multiplier: kood.HkKoodiKordaja,
|
|
coefficient: kood.Koefitsient,
|
|
price: kood.Hind,
|
|
analysis_group_id: analysisGroupId,
|
|
analysis_element_id: null,
|
|
analysis_id: null,
|
|
})),
|
|
);
|
|
|
|
const analysisGroupItems = toArray(analysisGroup.Uuring);
|
|
|
|
for (const item of analysisGroupItems) {
|
|
const analysisElement = item.UuringuElement;
|
|
|
|
const { data: insertedAnalysisElement, error } = await supabase
|
|
.schema('medreport')
|
|
.from('analysis_elements')
|
|
.upsert(
|
|
{
|
|
analysis_id_oid: analysisElement.UuringIdOID,
|
|
analysis_id_original: analysisElement.UuringId,
|
|
tehik_short_loinc: analysisElement.TLyhend,
|
|
tehik_loinc_name: analysisElement.KNimetus,
|
|
analysis_name_lab: analysisElement.UuringNimi,
|
|
order: analysisElement.Jarjekord,
|
|
parent_analysis_group_id: analysisGroupId,
|
|
material_groups: toArray(item.MaterjalideGrupp),
|
|
},
|
|
{ onConflict: 'analysis_id_original', ignoreDuplicates: false },
|
|
)
|
|
.select('id');
|
|
|
|
if (error || !insertedAnalysisElement[0]?.id) {
|
|
throw new Error(
|
|
`Failed to insert analysis element (id: ${analysisElement.UuringId}), error: ${error?.message}`,
|
|
);
|
|
}
|
|
|
|
const insertedAnalysisElementId = insertedAnalysisElement[0].id;
|
|
|
|
if (analysisElement.Kood) {
|
|
const analysisElementCodes = toArray(analysisElement.Kood);
|
|
codes.push(
|
|
...analysisElementCodes.map((kood) => ({
|
|
hk_code: kood.HkKood,
|
|
hk_code_multiplier: kood.HkKoodiKordaja,
|
|
coefficient: kood.Koefitsient,
|
|
price: kood.Hind,
|
|
analysis_group_id: null,
|
|
analysis_element_id: insertedAnalysisElementId,
|
|
analysis_id: null,
|
|
})),
|
|
);
|
|
}
|
|
|
|
const analyses = analysisElement.UuringuElement;
|
|
if (analyses?.length) {
|
|
for (const analysis of analyses) {
|
|
const { data: insertedAnalysis, error } = await supabase
|
|
.schema('medreport')
|
|
.from('analyses')
|
|
.upsert(
|
|
{
|
|
analysis_id_oid: analysis.UuringIdOID,
|
|
analysis_id_original: analysis.UuringId,
|
|
tehik_short_loinc: analysis.TLyhend,
|
|
tehik_loinc_name: analysis.KNimetus,
|
|
analysis_name_lab: analysis.UuringNimi,
|
|
order: analysis.Jarjekord,
|
|
parent_analysis_element_id: insertedAnalysisElementId,
|
|
},
|
|
{ onConflict: 'analysis_id_original', ignoreDuplicates: false },
|
|
)
|
|
.select('id');
|
|
|
|
if (error || !insertedAnalysis[0]?.id) {
|
|
throw new Error(
|
|
`Failed to insert analysis (id: ${analysis.UuringId}) error: ${error?.message}`,
|
|
);
|
|
}
|
|
|
|
const insertedAnalysisId = insertedAnalysis[0].id;
|
|
if (analysis.Kood) {
|
|
const analysisCodes = toArray(analysis.Kood);
|
|
|
|
codes.push(
|
|
...analysisCodes.map((kood) => ({
|
|
hk_code: kood.HkKood,
|
|
hk_code_multiplier: kood.HkKoodiKordaja,
|
|
coefficient: kood.Koefitsient,
|
|
price: kood.Hind,
|
|
analysis_group_id: null,
|
|
analysis_element_id: null,
|
|
analysis_id: insertedAnalysisId,
|
|
})),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
console.info('Inserting codes');
|
|
await supabase.schema('medreport').from('codes').upsert(codes);
|
|
|
|
console.info('Inserting sync entry');
|
|
await supabase.schema('audit').from('sync_entries').insert({
|
|
operation: 'ANALYSES_SYNC',
|
|
status: 'SUCCESS',
|
|
changed_by_role: 'service_role',
|
|
});
|
|
} catch (e) {
|
|
await supabase
|
|
.schema('audit')
|
|
.from('sync_entries')
|
|
.insert({
|
|
operation: 'ANALYSES_SYNC',
|
|
status: 'FAIL',
|
|
comment: JSON.stringify(e),
|
|
changed_by_role: 'service_role',
|
|
});
|
|
console.error(e);
|
|
throw new Error(
|
|
`Failed to sync public message data, error: ${JSON.stringify(e)}`,
|
|
);
|
|
}
|
|
}
|