feat(MED-87): update status on results

This commit is contained in:
2025-08-11 10:41:01 +03:00
parent d582e222ce
commit 63b86c0abb
8 changed files with 87 additions and 17 deletions

View File

@@ -119,7 +119,6 @@ export async function processMontonioCallback(orderToken: string) {
console.error("Missing email or analysisPackageName", orderResult);
}
// Send order to Medipost (no await to avoid blocking)
sendOrderToMedipost({ medusaOrderId, orderedAnalysisElements });
return { success: true, orderId };

View File

@@ -4,6 +4,8 @@
*/
import { type Instrumentation } from 'next';
const isEnabledInDev = process.env.ENABLE_LOCAL_JOBS === 'true';
export async function register() {
const { registerMonitoringInstrumentation } = await import(
'@kit/monitoring/instrumentation'
@@ -12,6 +14,9 @@ export async function register() {
// Register monitoring instrumentation
// based on the MONITORING_PROVIDER environment variable.
await registerMonitoringInstrumentation();
// Register lightweight in-process job scheduler
await registerJobScheduler();
}
/**
@@ -28,3 +33,53 @@ export const onRequestError: Instrumentation.onRequestError = async (err) => {
await service.ready();
await service.captureException(err as Error);
};
async function registerJobScheduler() {
const isProd = process.env.NODE_ENV === 'production';
if (!isProd && !isEnabledInDev) {
console.info('Job scheduler disabled');
return;
}
// Prevent duplicate intervals on hot reloads/dev
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const globalAny = globalThis as any;
if (globalAny.__mrJobSchedulerInitialized) {
console.info('Job scheduler already initialized');
return;
}
globalAny.__mrJobSchedulerInitialized = true;
let isRunning = false;
const runSyncAnalysisResults = async () => {
if (isRunning) {
console.info('Scheduled job syncAnalysisResults skipped: previous run still in progress');
return;
}
isRunning = true;
try {
// Ensure env variables are loaded for the handler
try {
const { default: loadEnv } = await import('./app/api/job/handler/load-env');
loadEnv();
} catch {
// ignore if not available or already loaded
}
const { default: syncAnalysisResults } = await import(
'./app/api/job/handler/sync-analysis-results'
);
await syncAnalysisResults();
} catch (error) {
// Log and continue; do not crash the process
console.error('Scheduled job syncAnalysisResults failed:', error);
} finally {
isRunning = false;
}
};
// Run every 10 minutes
setTimeout(runSyncAnalysisResults, 15_000);
setInterval(runSyncAnalysisResults, 10 * 60 * 1000);
}

View File

@@ -36,7 +36,7 @@ import { uniqBy } from 'lodash';
import { Tables } from '@kit/supabase/database';
import { createAnalysisGroup } from './analysis-group.service';
import { getSupabaseServerAdminClient } from '@/packages/supabase/src/clients/server-admin-client';
import { getOrder } from './order.service';
import { getOrder, updateOrder } from './order.service';
import { getAnalysisElements, getAnalysisElementsAdmin } from './analysis-element.service';
import { getAnalyses } from './analyses.service';
import { getAccountAdmin } from './account.service';
@@ -235,6 +235,7 @@ export async function readPrivateMessageResponse({
const status = await syncPrivateMessage({ messageResponse, order });
if (status === 'COMPLETED') {
await updateOrder({ orderId: order.id, orderStatus: 'FULL_ANALYSIS_RESPONSE' });
await deletePrivateMessage(privateMessage.messageId);
messageIdProcessed = privateMessage.messageId;
}
@@ -658,6 +659,7 @@ export async function syncPrivateMessage({
);
}
console.info("status", AnalysisOrderStatus[messageResponse.TellimuseOlek], messageResponse.TellimuseOlek);
return AnalysisOrderStatus[messageResponse.TellimuseOlek];
}
@@ -686,6 +688,7 @@ export async function sendOrderToMedipost({
});
await sendPrivateMessage(orderXml);
await updateOrder({ orderId: medreportOrder.id, orderStatus: 'PROCESSING' });
}
export async function getOrderedAnalysisElementsIds({

View File

@@ -45,7 +45,8 @@ export async function updateOrder({
orderId: number;
orderStatus: Tables<{ schema: 'medreport' }, 'analysis_orders'>['status'];
}) {
const { error } = await getSupabaseServerClient()
console.info(`Updating order id=${orderId} status=${orderStatus}`);
await getSupabaseServerAdminClient()
.schema('medreport')
.from('analysis_orders')
.update({
@@ -53,9 +54,6 @@ export async function updateOrder({
})
.eq('id', orderId)
.throwOnError();
if (error) {
throw new Error(`Failed to update order, message=${error}, data=${JSON.stringify(error)}`);
}
}
export async function getOrder({

View File

@@ -1883,6 +1883,9 @@ export type Database = {
| "QUEUED"
| "ON_HOLD"
| "PROCESSING"
| "PARTIAL_ANALYSIS_RESPONSE"
| "FULL_ANALYSIS_RESPONSE"
| "WAITING_FOR_DOCTOR_RESPONSE"
| "COMPLETED"
| "REJECTED"
| "CANCELLED"
@@ -7769,12 +7772,15 @@ export const Constants = {
medreport: {
Enums: {
analysis_order_status: [
"QUEUED",
"ON_HOLD",
"PROCESSING",
"COMPLETED",
"REJECTED",
"CANCELLED",
"QUEUED", // makstud, ootab Synlabi saatmist
"ON_HOLD", //
"PROCESSING", // ootab proovide tulemusi
"PARTIAL_ANALYSIS_RESPONSE", // osalised tulemused
"FULL_ANALYSIS_RESPONSE", // kõik tulemused käes
"WAITING_FOR_DOCTOR_RESPONSE", // ootab arsti kokkuvõtet
"COMPLETED", // kinnitatud, lõplik
"REJECTED", // tagastatud
"CANCELLED", // tühistatud
],
app_permissions: [
"roles.manage",

View File

@@ -11,6 +11,9 @@
"QUEUED": "Waiting to send to lab",
"ON_HOLD": "Waiting for analysis results",
"PROCESSING": "In progress",
"PARTIAL_ANALYSIS_RESPONSE": "Partial analysis response",
"FULL_ANALYSIS_RESPONSE": "All analysis responses",
"WAITING_FOR_DOCTOR_RESPONSE": "Waiting for doctor response",
"COMPLETED": "Completed",
"REJECTED": "Rejected",
"CANCELLED": "Cancelled"

View File

@@ -8,11 +8,14 @@
"status": "Olek"
},
"status": {
"QUEUED": "Ootab saatekirja saatmist",
"ON_HOLD": "Ootab analüüsi tulemusi",
"PROCESSING": "Töötlemisel",
"COMPLETED": "Valmis",
"REJECTED": "Tühistatud",
"QUEUED": "Esitatud",
"ON_HOLD": "Makstud",
"PROCESSING": "Synlabile edastatud",
"PARTIAL_ANALYSIS_RESPONSE": "Osalised tulemused",
"FULL_ANALYSIS_RESPONSE": "Kõik tulemused käes",
"WAITING_FOR_DOCTOR_RESPONSE": "Ootab arsti kokkuvõtet",
"COMPLETED": "Lõplikud tulemused",
"REJECTED": "Tagastatud",
"CANCELLED": "Tühistatud"
}
}

View File

@@ -0,0 +1,3 @@
alter type medreport.analysis_order_status add value 'PARTIAL_ANALYSIS_RESPONSE';
alter type medreport.analysis_order_status add value 'FULL_ANALYSIS_RESPONSE';
alter type medreport.analysis_order_status add value 'WAITING_FOR_DOCTOR_RESPONSE';