From a37c4cad9c263297ecdef921fc3938cae13f9660 Mon Sep 17 00:00:00 2001 From: Karli Date: Thu, 28 Aug 2025 11:56:07 +0300 Subject: [PATCH] feat(MED-85): add logging for medipost actions with xml and related order id --- .../route.ts | 57 -------------- app/api/order/medipost-test-response/route.ts | 7 +- lib/services/medipost.service.ts | 77 +++++++++++++------ packages/supabase/src/database.types.ts | 24 +++++- ...827090152_bo_run_dev_fake_results_sync.sql | 6 +- .../20250828105844_medipost_actions.sql | 16 ++++ 6 files changed, 100 insertions(+), 87 deletions(-) delete mode 100644 app/api/job/send-medipost-test-response-for-order/route.ts create mode 100644 supabase/migrations/20250828105844_medipost_actions.sql diff --git a/app/api/job/send-medipost-test-response-for-order/route.ts b/app/api/job/send-medipost-test-response-for-order/route.ts deleted file mode 100644 index a4ad457..0000000 --- a/app/api/job/send-medipost-test-response-for-order/route.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { NextRequest, NextResponse } from "next/server"; -import { getAnalysisOrdersAdmin } from "~/lib/services/order.service"; -import { composeOrderTestResponseXML, sendPrivateMessageTestResponse } from "~/lib/services/medipostTest.service"; -import { retrieveOrder } from "@lib/data"; -import { getAccountAdmin } from "~/lib/services/account.service"; -import { getOrderedAnalysisElementsIds } from "~/lib/services/medipost.service"; -import loadEnv from "../handler/load-env"; -import validateApiKey from "../handler/validate-api-key"; - -export async function POST(request: NextRequest) { - loadEnv(); - - try { - validateApiKey(request); - } catch (e) { - return NextResponse.json({}, { status: 401, statusText: 'Unauthorized' }); - } - - const { order_id: medusaOrderId } = await request.json(); - if (!medusaOrderId) { - return NextResponse.json({ error: 'order_id is required' }, { status: 400 }); - } - - const analysisOrders = await getAnalysisOrdersAdmin({ medusaOrderId }); - - console.error(`Sending test responses for ${analysisOrders.length} analysis orders`); - for (const medreportOrder of analysisOrders) { - const medusaOrderId = medreportOrder.medusa_order_id; - const medusaOrder = await retrieveOrder(medusaOrderId) - - const account = await getAccountAdmin({ primaryOwnerUserId: medreportOrder.user_id }); - const orderedAnalysisElementsIds = await getOrderedAnalysisElementsIds({ medusaOrder }); - - console.info(`Sending test response for order=${medusaOrderId} with ${orderedAnalysisElementsIds.length} ordered analysis elements`); - const idsToSend = orderedAnalysisElementsIds; - const messageXml = await composeOrderTestResponseXML({ - person: { - idCode: account.personal_code!, - firstName: account.name ?? '', - lastName: account.last_name ?? '', - phone: account.phone ?? '', - }, - orderedAnalysisElementsIds: idsToSend.map(({ analysisElementId }) => analysisElementId), - orderedAnalysesIds: [], - orderId: medusaOrderId, - orderCreatedAt: new Date(medreportOrder.created_at), - }); - - try { - await sendPrivateMessageTestResponse({ messageXml }); - } catch (error) { - console.error("Error sending private message test response: ", error); - } - } - - return NextResponse.json({ success: true }); -} diff --git a/app/api/order/medipost-test-response/route.ts b/app/api/order/medipost-test-response/route.ts index 40cf4b2..a54e1fe 100644 --- a/app/api/order/medipost-test-response/route.ts +++ b/app/api/order/medipost-test-response/route.ts @@ -3,7 +3,7 @@ import { getOrder } from "~/lib/services/order.service"; import { composeOrderTestResponseXML, sendPrivateMessageTestResponse } from "~/lib/services/medipostTest.service"; import { retrieveOrder } from "@lib/data"; import { getAccountAdmin } from "~/lib/services/account.service"; -import { getOrderedAnalysisElementsIds } from "~/lib/services/medipost.service"; +import { createMedipostActionLog, getOrderedAnalysisElementsIds } from "~/lib/services/medipost.service"; export async function POST(request: Request) { // const isDev = process.env.NODE_ENV === 'development'; @@ -35,6 +35,11 @@ export async function POST(request: Request) { }); try { + await createMedipostActionLog({ + action: 'send_fake_analysis_results_to_medipost', + xml: messageXml, + medusaOrderId, + }); await sendPrivateMessageTestResponse({ messageXml }); } catch (error) { console.error("Error sending private message test response: ", error); diff --git a/lib/services/medipost.service.ts b/lib/services/medipost.service.ts index 542f275..c19970e 100644 --- a/lib/services/medipost.service.ts +++ b/lib/services/medipost.service.ts @@ -180,7 +180,10 @@ export async function getPrivateMessage(messageId: string) { await validateMedipostResponse(data, { canHaveEmptyCode: true }); - return parseXML(data) as MedipostOrderResponse; + return { + message: parseXML(data) as MedipostOrderResponse, + xml: data as string, + }; } export async function deletePrivateMessage(messageId: string) { @@ -211,7 +214,9 @@ export async function readPrivateMessageResponse({ try { const privateMessage = await getLatestPrivateMessageListItem({ excludedMessageIds }); - if (!privateMessage) { + messageId = privateMessage?.messageId ?? null; + + if (!privateMessage || !messageId) { return { messageId: null, hasAnalysisResponse: false, @@ -221,40 +226,28 @@ export async function readPrivateMessageResponse({ }; } - messageId = privateMessage.messageId; - if (!messageId) { - return { - messageId: null, - hasAnalysisResponse: false, - hasPartialAnalysisResponse: false, - hasFullAnalysisResponse: false, - medusaOrderId: undefined, - }; - } - - const privateMessageContent = await getPrivateMessage( + const { message: privateMessageContent, xml: privateMessageXml } = await getPrivateMessage( privateMessage.messageId, ); + const messageResponse = privateMessageContent?.Saadetis?.Vastus; medusaOrderId = privateMessageContent?.Saadetis?.Tellimus?.ValisTellimuseId || messageResponse?.ValisTellimuseId; - if (!medusaOrderId || !medusaOrderId.toString().startsWith('order_')) { - return { - messageId, - hasAnalysisResponse: false, - hasPartialAnalysisResponse: false, - hasFullAnalysisResponse: false, - medusaOrderId: undefined, - }; - } + const hasInvalidOrderId = !medusaOrderId || !medusaOrderId.toString().startsWith('order_'); - if (!messageResponse) { + if (hasInvalidOrderId || !messageResponse) { + await createMedipostActionLog({ + action: 'sync_analysis_results_from_medipost', + xml: privateMessageXml, + hasAnalysisResults: false, + medusaOrderId: hasInvalidOrderId ? undefined : medusaOrderId, + }); return { messageId, hasAnalysisResponse: false, hasPartialAnalysisResponse: false, hasFullAnalysisResponse: false, - medusaOrderId, + medusaOrderId: hasInvalidOrderId ? undefined : medusaOrderId, }; } @@ -743,6 +736,12 @@ export async function sendOrderToMedipost({ try { await sendPrivateMessage(orderXml); + await createMedipostActionLog({ + action: 'send_order_to_medipost', + xml: orderXml, + hasAnalysisResults: false, + medusaOrderId, + }); } catch (e) { const isMedipostError = e instanceof MedipostValidationError; await logMedipostDispatch({ @@ -825,3 +824,31 @@ export async function getOrderedAnalysisElementsIds({ return [...analysisPackageElements, ...orderedAnalysisElements]; } + +export async function createMedipostActionLog({ + action, + xml, + hasAnalysisResults = false, + medusaOrderId, +}: { + action: + | 'send_order_to_medipost' + | 'sync_analysis_results_from_medipost' + | 'send_fake_analysis_results_to_medipost' + | 'send_analysis_results_to_medipost'; + xml: string; + hasAnalysisResults?: boolean; + medusaOrderId?: string | null; +}) { + await getSupabaseServerAdminClient() + .schema('medreport') + .from('medipost_actions') + .insert({ + action, + xml, + has_analysis_results: hasAnalysisResults, + medusa_order_id: medusaOrderId, + }) + .select('id') + .throwOnError(); +} diff --git a/packages/supabase/src/database.types.ts b/packages/supabase/src/database.types.ts index 9e80564..df517ea 100644 --- a/packages/supabase/src/database.types.ts +++ b/packages/supabase/src/database.types.ts @@ -1188,6 +1188,28 @@ export type Database = { }, ] } + medipost_actions: { + Row: { + id: string + action: string + xml: string + has_analysis_results: boolean + created_at: string + medusa_order_id: string + } + Insert: { + action: string + xml: string + has_analysis_results: boolean + medusa_order_id: string + } + Update: { + action?: string + xml?: string + has_analysis_results?: boolean + medusa_order_id?: string + } + } medreport_product_groups: { Row: { created_at: string @@ -2076,7 +2098,7 @@ export type Database = { } send_medipost_test_response_for_order: { Args: { - order_id: string + medusa_order_id: string } } } diff --git a/supabase/migrations-env-specific/20250827090152_bo_run_dev_fake_results_sync.sql b/supabase/migrations-env-specific/20250827090152_bo_run_dev_fake_results_sync.sql index bf04187..0bc697f 100644 --- a/supabase/migrations-env-specific/20250827090152_bo_run_dev_fake_results_sync.sql +++ b/supabase/migrations-env-specific/20250827090152_bo_run_dev_fake_results_sync.sql @@ -1,17 +1,17 @@ -- Parameters order_id -CREATE OR REPLACE FUNCTION medreport.send_medipost_test_response_for_order(order_id text) +CREATE OR REPLACE FUNCTION medreport.send_medipost_test_response_for_order(medusa_order_id text) RETURNS void LANGUAGE plpgsql AS $$ BEGIN select net.http_post( - url := 'https://test.medreport.ee/api/job/send-medipost-test-response-for-order', + url := 'https://test.medreport.ee/api/order/medipost-test-response', headers := jsonb_build_object( 'Content-Type', 'application/json', 'x-jobs-api-key', 'fd26ec26-70ed-11f0-9e95-431ac3b15a84' ), body := jsonb_build_object( - 'order_id', order_id + 'medusaOrderId', medusa_order_id ) ) as request_id; END; diff --git a/supabase/migrations/20250828105844_medipost_actions.sql b/supabase/migrations/20250828105844_medipost_actions.sql new file mode 100644 index 0000000..3eea037 --- /dev/null +++ b/supabase/migrations/20250828105844_medipost_actions.sql @@ -0,0 +1,16 @@ +CREATE TABLE medreport.medipost_actions ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + action VARCHAR(255) NOT NULL, + xml VARCHAR(131072), + has_analysis_results BOOLEAN NOT NULL DEFAULT FALSE, + medusa_order_id VARCHAR(255), + created_at TIMESTAMP WITH TIME ZONE DEFAULT now() +); + +ALTER TABLE medreport.medipost_actions ENABLE ROW LEVEL SECURITY; + +CREATE POLICY "service_role_select" ON medreport.medipost_actions FOR SELECT TO service_role USING (true); +CREATE POLICY "service_role_insert" ON medreport.medipost_actions FOR INSERT TO service_role WITH CHECK (true); +CREATE POLICY "service_role_update" ON medreport.medipost_actions FOR UPDATE TO service_role USING (true); +CREATE POLICY "service_role_delete" ON medreport.medipost_actions FOR DELETE TO service_role USING (true); +grant select, insert, update, delete on table medreport.medipost_actions to service_role;