From 7c3aa45ec708c0ee50345446cdbfcec3ecb7ac0e Mon Sep 17 00:00:00 2001 From: k4rli Date: Mon, 4 Aug 2025 11:55:23 +0300 Subject: [PATCH] feat(MED-131): update analyses on package logic --- app/api/job/handler/sync-analysis-groups.ts | 10 +++- .../_components/compare-packages-modal.tsx | 50 ++++++++++--------- .../_lib/server/load-analysis-packages.ts | 5 +- components/select-analysis-package.tsx | 7 +-- lib/services/analysis-element.service.ts | 28 +++++++++-- lib/services/medipost.service.ts | 4 +- lib/services/medipostTest.service.ts | 4 +- .../src/lib/data/products.ts | 14 ------ utils/medusa-product.ts | 17 +++++++ 9 files changed, 88 insertions(+), 51 deletions(-) create mode 100644 utils/medusa-product.ts diff --git a/app/api/job/handler/sync-analysis-groups.ts b/app/api/job/handler/sync-analysis-groups.ts index fa4dc3e..fe76f2d 100644 --- a/app/api/job/handler/sync-analysis-groups.ts +++ b/app/api/job/handler/sync-analysis-groups.ts @@ -1,7 +1,7 @@ import axios from 'axios'; import { XMLParser } from 'fast-xml-parser'; import fs from 'fs'; -import { createAnalysisGroup } from '~/lib/services/analysis-group.service'; +import { createAnalysisGroup, getAnalysisGroups } from '~/lib/services/analysis-group.service'; import { IMedipostPublicMessageDataParsed } from '~/lib/services/medipost.types'; import { createAnalysis, createNoDataReceivedEntry, createNoNewDataReceivedEntry, createSyncFailEntry, createSyncSuccessEntry } from '~/lib/services/analyses.service'; import { getLastCheckedDate } from '~/lib/services/sync-entries.service'; @@ -64,6 +64,8 @@ export default async function syncAnalysisGroups() { ); } + const existingAnalysisGroups = await getAnalysisGroups(); + // SAVE PUBLIC MESSAGE DATA const providers = toArray(parsed?.Saadetis?.Teenused.Teostaja); @@ -79,6 +81,12 @@ export default async function syncAnalysisGroups() { const codes: ICode[] = []; for (const analysisGroup of analysisGroups) { + const existingAnalysisGroup = existingAnalysisGroups?.find(({ original_id }) => original_id === analysisGroup.UuringuGruppId); + if (existingAnalysisGroup) { + console.info(`Analysis group '${analysisGroup.UuringuGruppNimi}' already exists`); + continue; + } + // SAVE ANALYSIS GROUP const analysisGroupId = await createAnalysisGroup({ id: analysisGroup.UuringuGruppId, diff --git a/app/home/(user)/_components/compare-packages-modal.tsx b/app/home/(user)/_components/compare-packages-modal.tsx index 247c6ca..545edf4 100644 --- a/app/home/(user)/_components/compare-packages-modal.tsx +++ b/app/home/(user)/_components/compare-packages-modal.tsx @@ -24,7 +24,7 @@ import { PackageHeader } from '@/components/package-header'; import { InfoTooltip } from '@/components/ui/info-tooltip'; import { StoreProduct } from '@medusajs/types'; import type { AnalysisElement } from '~/lib/services/analysis-element.service'; -import { getAnalysisElementOriginalIds } from '@lib/data/products'; +import { getAnalysisElementOriginalIds } from '@/utils/medusa-product'; const CheckWithBackground = () => { return ( @@ -34,6 +34,24 @@ const CheckWithBackground = () => { ); }; +const PackageTableHead = async ({ product, nrOfAnalyses }: { product: StoreProduct, nrOfAnalyses: number }) => { + const { t, language } = await createI18nServerInstance(); + const variant = product.variants?.[0]; + const titleKey = product.title; + const price = variant?.calculated_price?.calculated_amount ?? 0; + return ( + + + + ) +} + const ComparePackagesModal = async ({ analysisElements, analysisPackages, @@ -43,7 +61,7 @@ const ComparePackagesModal = async ({ analysisPackages: StoreProduct[]; triggerElement: JSX.Element; }) => { - const { t, language } = await createI18nServerInstance(); + const { t } = await createI18nServerInstance(); const standardPackage = analysisPackages.find(({ metadata }) => metadata?.analysisPackageTier === 'standard')!; const standardPlusPackage = analysisPackages.find(({ metadata }) => metadata?.analysisPackageTier === 'standard-plus')!; @@ -53,9 +71,9 @@ const ComparePackagesModal = async ({ return null; } - const standardPackageAnalyses = await getAnalysisElementOriginalIds([standardPackage]); - const standardPlusPackageAnalyses = await getAnalysisElementOriginalIds([standardPlusPackage]); - const premiumPackageAnalyses = await getAnalysisElementOriginalIds([premiumPackage]); + const standardPackageAnalyses = getAnalysisElementOriginalIds([standardPackage]); + const standardPlusPackageAnalyses = getAnalysisElementOriginalIds([standardPlusPackage]); + const premiumPackageAnalyses = getAnalysisElementOriginalIds([premiumPackage]); return ( @@ -86,25 +104,9 @@ const ComparePackagesModal = async ({ - {analysisPackages.map( - (product) => { - const variant = product.variants?.[0]; - const titleKey = product.title; - const price = variant?.calculated_price?.calculated_amount ?? 0; - return ( - - - - ) - })} + + + diff --git a/app/home/(user)/_lib/server/load-analysis-packages.ts b/app/home/(user)/_lib/server/load-analysis-packages.ts index d46e8d1..68075e7 100644 --- a/app/home/(user)/_lib/server/load-analysis-packages.ts +++ b/app/home/(user)/_lib/server/load-analysis-packages.ts @@ -1,8 +1,9 @@ import { cache } from 'react'; -import { getAnalysisElementOriginalIds, listProductTypes, listProducts } from "@lib/data/products"; +import { listProductTypes, listProducts } from "@lib/data/products"; import { listRegions } from '@lib/data/regions'; import { AnalysisElement, getAnalysisElements } from '~/lib/services/analysis-element.service'; +import { getAnalysisElementOriginalIds } from '@/utils/medusa-product'; async function countryCodesLoader() { const countryCodes = await listRegions().then((regions) => @@ -33,7 +34,7 @@ async function analysisPackagesLoader() { }); const analysisPackages = response.products; let analysisElements: AnalysisElement[] = []; - const analysisElementOriginalIds = await getAnalysisElementOriginalIds(analysisPackages); + const analysisElementOriginalIds = getAnalysisElementOriginalIds(analysisPackages); if (analysisElementOriginalIds.length) { analysisElements = await getAnalysisElements({ originalIds: analysisElementOriginalIds }); diff --git a/components/select-analysis-package.tsx b/components/select-analysis-package.tsx index 950da9b..5dd3846 100644 --- a/components/select-analysis-package.tsx +++ b/components/select-analysis-package.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState } from 'react'; +import { use, useState } from 'react'; import { useTranslation } from 'react-i18next'; import Image from 'next/image'; import { useRouter } from 'next/navigation'; @@ -19,11 +19,11 @@ import { handleAddToCart } from '@/lib/services/medusaCart.service'; import { PackageHeader } from './package-header'; import { ButtonTooltip } from './ui/button-tooltip'; +import { getAnalysisElementOriginalIds } from '@/utils/medusa-product'; export interface IAnalysisPackage { titleKey: string; price: number; - nrOfAnalyses: number | string; tagColor: string; descriptionKey: string; } @@ -52,7 +52,8 @@ export default function SelectAnalysisPackage({ } const titleKey = analysisPackage.title; - const nrOfAnalyses = analysisPackage?.metadata?.nrOfAnalyses ?? 0; + const analysisElementOriginalIds = getAnalysisElementOriginalIds([analysisPackage]); + const nrOfAnalyses = analysisElementOriginalIds.length; const description = analysisPackage.description ?? ''; const subtitle = analysisPackage.subtitle ?? ''; const variant = analysisPackage.variants?.[0]; diff --git a/lib/services/analysis-element.service.ts b/lib/services/analysis-element.service.ts index a92f27d..2777a77 100644 --- a/lib/services/analysis-element.service.ts +++ b/lib/services/analysis-element.service.ts @@ -9,10 +9,8 @@ export type AnalysisElement = Tables<{ schema: 'medreport' }, 'analysis_elements export async function getAnalysisElements({ originalIds, - ids, }: { originalIds?: string[]; - ids?: number[]; }): Promise { const query = getSupabaseServerClient() .schema('medreport') @@ -24,11 +22,35 @@ export async function getAnalysisElements({ query.in('analysis_id_original', [...new Set(originalIds)]); } + const { data: analysisElements, error } = await query; + + if (error) { + throw new Error(`Failed to get analysis elements: ${error.message}`); + } + + return analysisElements ?? []; +} + +export async function getAnalysisElementsAdmin({ + ids, +}: { + ids?: number[]; +} = {}): Promise { + const query = getSupabaseServerAdminClient() + .schema('medreport') + .from('analysis_elements') + .select(`*, analysis_groups(*)`) + .order('order', { ascending: true }); + if (Array.isArray(ids)) { query.in('id', ids); } - const { data: analysisElements } = await query; + const { data: analysisElements, error } = await query; + + if (error) { + throw new Error(`Failed to get analysis elements: ${error.message}`); + } return analysisElements ?? []; } diff --git a/lib/services/medipost.service.ts b/lib/services/medipost.service.ts index 1a2dfee..1ec637c 100644 --- a/lib/services/medipost.service.ts +++ b/lib/services/medipost.service.ts @@ -37,7 +37,7 @@ 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 { getAnalysisElements } from './analysis-element.service'; +import { getAnalysisElementsAdmin } from './analysis-element.service'; import { getAnalyses } from './analyses.service'; const BASE_URL = process.env.MEDIPOST_URL!; @@ -407,7 +407,7 @@ export async function composeOrderXML({ orderCreatedAt: Date; comment?: string; }) { - const analysisElements = await getAnalysisElements({ ids: orderedAnalysisElementsIds }); + const analysisElements = await getAnalysisElementsAdmin({ ids: orderedAnalysisElementsIds }); const analyses = await getAnalyses({ ids: orderedAnalysesIds }); const analysisGroups: Tables<{ schema: 'medreport' }, 'analysis_groups'>[] = diff --git a/lib/services/medipostTest.service.ts b/lib/services/medipostTest.service.ts index ad2ad39..ee5a294 100644 --- a/lib/services/medipostTest.service.ts +++ b/lib/services/medipostTest.service.ts @@ -16,7 +16,7 @@ import { uniqBy } from 'lodash'; import { Tables } from '@kit/supabase/database'; import { formatDate } from 'date-fns'; import { getAnalyses } from './analyses.service'; -import { getAnalysisElements } from './analysis-element.service'; +import { getAnalysisElementsAdmin } from './analysis-element.service'; import { validateMedipostResponse } from './medipost.service'; const BASE_URL = process.env.MEDIPOST_URL!; @@ -70,7 +70,7 @@ export async function composeOrderTestResponseXML({ orderId: string; orderCreatedAt: Date; }) { - const analysisElements = await getAnalysisElements({ ids: orderedAnalysisElementsIds }); + const analysisElements = await getAnalysisElementsAdmin({ ids: orderedAnalysisElementsIds }); const analyses = await getAnalyses({ ids: orderedAnalysesIds }); const analysisGroups: Tables<{ schema: 'medreport' }, 'analysis_groups'>[] = diff --git a/packages/features/medusa-storefront/src/lib/data/products.ts b/packages/features/medusa-storefront/src/lib/data/products.ts index 3608d2d..1997706 100644 --- a/packages/features/medusa-storefront/src/lib/data/products.ts +++ b/packages/features/medusa-storefront/src/lib/data/products.ts @@ -85,20 +85,6 @@ export const listProducts = async ({ }) } -export const getAnalysisElementOriginalIds = async (products: HttpTypes.StoreProduct[]) => { - return products - .flatMap(({ metadata }) => { - const value = metadata?.analysisElementOriginalIds; - try { - return JSON.parse(value as string); - } catch (e) { - console.error("Failed to parse analysisElementOriginalIds from analysis package, possibly invalid format", e); - return []; - } - }) - .filter(Boolean) as string[]; -} - /** * This will fetch 100 products to the Next.js cache and sort them based on the sortBy parameter. * It will then return the paginated products based on the page and limit parameters. diff --git a/utils/medusa-product.ts b/utils/medusa-product.ts new file mode 100644 index 0000000..dc9cd32 --- /dev/null +++ b/utils/medusa-product.ts @@ -0,0 +1,17 @@ +export const getAnalysisElementOriginalIds = (products: ({ metadata?: { analysisElementOriginalIds?: string } | null } | null)[]) => { + if (!products) { + return []; + } + + return products + .flatMap((product) => { + const value = product?.metadata?.analysisElementOriginalIds; + try { + return JSON.parse(value as string); + } catch (e) { + console.error("Failed to parse analysisElementOriginalIds from analysis package, possibly invalid format", e); + return []; + } + }) + .filter(Boolean) as string[]; +}