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); console.error("Missing email or analysisPackageName", orderResult);
} }
// Send order to Medipost (no await to avoid blocking)
sendOrderToMedipost({ medusaOrderId, orderedAnalysisElements }); sendOrderToMedipost({ medusaOrderId, orderedAnalysisElements });
return { success: true, orderId }; return { success: true, orderId };

View File

@@ -4,6 +4,8 @@
*/ */
import { type Instrumentation } from 'next'; import { type Instrumentation } from 'next';
const isEnabledInDev = process.env.ENABLE_LOCAL_JOBS === 'true';
export async function register() { export async function register() {
const { registerMonitoringInstrumentation } = await import( const { registerMonitoringInstrumentation } = await import(
'@kit/monitoring/instrumentation' '@kit/monitoring/instrumentation'
@@ -12,6 +14,9 @@ export async function register() {
// Register monitoring instrumentation // Register monitoring instrumentation
// based on the MONITORING_PROVIDER environment variable. // based on the MONITORING_PROVIDER environment variable.
await registerMonitoringInstrumentation(); 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.ready();
await service.captureException(err as Error); 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 { Tables } from '@kit/supabase/database';
import { createAnalysisGroup } from './analysis-group.service'; import { createAnalysisGroup } from './analysis-group.service';
import { getSupabaseServerAdminClient } from '@/packages/supabase/src/clients/server-admin-client'; 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 { getAnalysisElements, getAnalysisElementsAdmin } from './analysis-element.service';
import { getAnalyses } from './analyses.service'; import { getAnalyses } from './analyses.service';
import { getAccountAdmin } from './account.service'; import { getAccountAdmin } from './account.service';
@@ -235,6 +235,7 @@ export async function readPrivateMessageResponse({
const status = await syncPrivateMessage({ messageResponse, order }); const status = await syncPrivateMessage({ messageResponse, order });
if (status === 'COMPLETED') { if (status === 'COMPLETED') {
await updateOrder({ orderId: order.id, orderStatus: 'FULL_ANALYSIS_RESPONSE' });
await deletePrivateMessage(privateMessage.messageId); await deletePrivateMessage(privateMessage.messageId);
messageIdProcessed = 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]; return AnalysisOrderStatus[messageResponse.TellimuseOlek];
} }
@@ -686,6 +688,7 @@ export async function sendOrderToMedipost({
}); });
await sendPrivateMessage(orderXml); await sendPrivateMessage(orderXml);
await updateOrder({ orderId: medreportOrder.id, orderStatus: 'PROCESSING' });
} }
export async function getOrderedAnalysisElementsIds({ export async function getOrderedAnalysisElementsIds({

View File

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

View File

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

View File

@@ -11,6 +11,9 @@
"QUEUED": "Waiting to send to lab", "QUEUED": "Waiting to send to lab",
"ON_HOLD": "Waiting for analysis results", "ON_HOLD": "Waiting for analysis results",
"PROCESSING": "In progress", "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", "COMPLETED": "Completed",
"REJECTED": "Rejected", "REJECTED": "Rejected",
"CANCELLED": "Cancelled" "CANCELLED": "Cancelled"

View File

@@ -8,11 +8,14 @@
"status": "Olek" "status": "Olek"
}, },
"status": { "status": {
"QUEUED": "Ootab saatekirja saatmist", "QUEUED": "Esitatud",
"ON_HOLD": "Ootab analüüsi tulemusi", "ON_HOLD": "Makstud",
"PROCESSING": "Töötlemisel", "PROCESSING": "Synlabile edastatud",
"COMPLETED": "Valmis", "PARTIAL_ANALYSIS_RESPONSE": "Osalised tulemused",
"REJECTED": "Tühistatud", "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" "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';