Merge branch 'main' into MED-122

This commit is contained in:
2025-07-18 16:11:50 +03:00
28 changed files with 6608 additions and 391 deletions

5
.env
View File

@@ -51,7 +51,4 @@ LOGGER=pino
NEXT_PUBLIC_DEFAULT_LOCALE=et NEXT_PUBLIC_DEFAULT_LOCALE=et
NEXT_PUBLIC_TEAM_NAVIGATION_STYLE=custom NEXT_PUBLIC_TEAM_NAVIGATION_STYLE=custom
NEXT_PUBLIC_USER_NAVIGATION_STYLE=custom NEXT_PUBLIC_USER_NAVIGATION_STYLE=custom
# MEDUSA
NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY=

View File

@@ -1,10 +1,9 @@
# This file is used to define environment variables for the development environment. # This file is used to define environment variables for the development environment.
# These values are only used when running the app in development mode. # These values are only used when running the app in development mode.
# SUPABASE # SUPABASE DEVELOPMENT
NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321 NEXT_PUBLIC_SUPABASE_URL=https://oqsdacktkhmbylmzstjq.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0 NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im9xc2RhY2t0a2htYnlsbXpzdGpxIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDY1MjgxMjMsImV4cCI6MjA2MjEwNDEyM30.LdHCTWxijFmhXdnT9KVuLRAVbtSwY7OO-oLtpd8GmO0
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU
## THIS IS FOR DEVELOPMENT ONLY - DO NOT USE IN PRODUCTION ## THIS IS FOR DEVELOPMENT ONLY - DO NOT USE IN PRODUCTION
SUPABASE_DB_WEBHOOK_SECRET=WEBHOOKSECRET SUPABASE_DB_WEBHOOK_SECRET=WEBHOOKSECRET
@@ -14,8 +13,6 @@ SUPABASE_DB_WEBHOOK_SECRET=WEBHOOKSECRET
# CONTACT FORM # CONTACT FORM
CONTACT_EMAIL=test@makerkit.dev CONTACT_EMAIL=test@makerkit.dev
# STRIPE
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
# MAILER # MAILER
MAILER_PROVIDER=nodemailer MAILER_PROVIDER=nodemailer

View File

@@ -6,7 +6,7 @@
## PUBLIC KEYS OR CONFIGURATION ARE OKAY TO BE PLACED HERE. ## PUBLIC KEYS OR CONFIGURATION ARE OKAY TO BE PLACED HERE.
# SUPABASE # SUPABASE
NEXT_PUBLIC_SUPABASE_URL= NEXT_PUBLIC_SUPABASE_URL=https://oqsdacktkhmbylmzstjq.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im9xc2RhY2t0a2htYnlsbXpzdGpxIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDY1MjgxMjMsImV4cCI6MjA2MjEwNDEyM30.LdHCTWxijFmhXdnT9KVuLRAVbtSwY7OO-oLtpd8GmO0
# STRIPE
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=

View File

@@ -1,17 +1,50 @@
# --- Stage 1: Build ---
FROM node:20-alpine as builder FROM node:20-alpine as builder
WORKDIR /app WORKDIR /app
RUN npm install -g pnpm@9 RUN npm install -g pnpm@9
RUN npm install -g dotenv-cli
# Copy necessary files for workspace resolution
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY packages packages COPY packages packages
COPY tooling tooling COPY tooling tooling
COPY .env .env
COPY .env.production .env.production
# Install all dependencies # Load env file and echo a specific variable
# RUN dotenv -e .env -- printenv | grep 'SUPABASE' || true
RUN pnpm install --frozen-lockfile RUN pnpm install --frozen-lockfile
COPY . . COPY . .
RUN pnpm build ENV NODE_ENV=production
# 🔍 Optional: Log key envs for debug
RUN echo "📄 .env.production contents:" && cat .env.production \
&& echo "🔧 Current ENV available to Next.js build:" && printenv | grep -E 'SUPABASE|STRIPE|NEXT|NODE_ENV' || true
RUN node check-env.js
RUN pnpm build
# --- Stage 2: Runtime ---
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app ./
RUN npm install -g pnpm@9 \
&& pnpm install --prod --frozen-lockfile
ENV NODE_ENV=production
# 🔍 Optional: Log key envs for debug
RUN echo "📄 .env.production contents:" && cat .env.production \
&& echo "🔧 Current ENV available to Next.js build:" && printenv | grep -E 'SUPABASE|STRIPE|NEXT|NODE_ENV' || true
EXPOSE 3000
CMD ["pnpm", "start"]

View File

@@ -0,0 +1,89 @@
import React from 'react';
import { ArrowDown } from 'lucide-react';
import { cn } from '@kit/ui/utils';
export enum AnalysisResultLevel {
VERY_LOW = 0,
LOW = 1,
NORMAL = 2,
HIGH = 3,
VERY_HIGH = 4,
}
const Level = ({
isActive = false,
color,
isFirst = false,
isLast = false,
}: {
isActive?: boolean;
color: 'destructive' | 'success' | 'warning';
isFirst?: boolean;
isLast?: boolean;
}) => {
return (
<div
className={cn(`bg-${color} relative h-3 flex-1`, {
'opacity-20': !isActive,
'rounded-l-lg': isFirst,
'rounded-r-lg': isLast,
})}
>
{isActive && (
<div className="absolute top-[-14px] left-1/2 -translate-x-1/2 rounded-[10px] bg-white p-[2px]">
<ArrowDown strokeWidth={2} />
</div>
)}
</div>
);
};
const AnalysisLevelBar = ({
normLowerIncluded = true,
normUpperIncluded = true,
level,
}: {
normLowerIncluded?: boolean;
normUpperIncluded?: boolean;
level: AnalysisResultLevel;
}) => {
return (
<div className="flex h-3 w-full max-w-[360px] gap-1">
{normLowerIncluded && (
<>
<Level
isActive={level === AnalysisResultLevel.VERY_LOW}
color="destructive"
isFirst
/>
<Level isActive={level === AnalysisResultLevel.LOW} color="warning" />
</>
)}
<Level
isFirst={!normLowerIncluded}
isLast={!normUpperIncluded}
isActive={level === AnalysisResultLevel.NORMAL}
color="success"
/>
{normUpperIncluded && (
<>
<Level
isActive={level === AnalysisResultLevel.HIGH}
color="warning"
/>
<Level
isActive={level === AnalysisResultLevel.VERY_HIGH}
color="destructive"
isLast
/>
</>
)}
</div>
);
};
export default AnalysisLevelBar;

View File

@@ -0,0 +1,84 @@
import React from 'react';
import { Info } from 'lucide-react';
import AnalysisLevelBar, { AnalysisResultLevel } from './analysis-level-bar';
export enum AnalysisStatus {
NORMAL = 0,
MEDIUM = 1,
HIGH = 2,
}
const Analysis = ({
analysis: {
name,
status,
unit,
value,
normLowerIncluded,
normUpperIncluded,
normLower,
normUpper,
},
}: {
analysis: {
name: string;
status: AnalysisStatus;
unit: string;
value: number;
normLowerIncluded: boolean;
normUpperIncluded: boolean;
normLower: number;
normUpper: number;
};
}) => {
const isUnderNorm = value < normLower;
const getAnalysisResultLevel = () => {
if (isUnderNorm) {
switch (status) {
case AnalysisStatus.MEDIUM:
return AnalysisResultLevel.LOW;
default:
return AnalysisResultLevel.VERY_LOW;
}
}
switch (status) {
case AnalysisStatus.MEDIUM:
return AnalysisResultLevel.HIGH;
case AnalysisStatus.HIGH:
return AnalysisResultLevel.VERY_HIGH;
default:
return AnalysisResultLevel.NORMAL;
}
};
return (
<div className="border-border flex items-center justify-between rounded-lg border px-5 py-3">
<div className="flex items-center gap-2 font-semibold">
{name}
<div className="group/tooltip relative">
<Info className="hover" />{' '}
<div className="absolute bottom-full left-1/2 z-10 mb-2 hidden -translate-x-1/2 rounded bg-gray-800 px-2 py-1 text-sm whitespace-nowrap text-white group-hover/tooltip:block">
This text changes when you hover the box above.
</div>
</div>
</div>
<div className="flex items-center gap-3">
<div className="font-semibold">{value}</div>
<div className="text-muted-foreground text-sm">{unit}</div>
</div>
<div className="text-muted-foreground text-center text-sm">
{normLower} - {normUpper}
<div>Normaalne vahemik</div>
</div>
<AnalysisLevelBar
normLowerIncluded={normLowerIncluded}
normUpperIncluded={normUpperIncluded}
level={getAnalysisResultLevel()}
/>
</div>
);
};
export default Analysis;

View File

@@ -0,0 +1,59 @@
import { createI18nServerInstance } from '@/lib/i18n/i18n.server';
import { withI18n } from '@/lib/i18n/with-i18n';
import { Trans } from '@kit/ui/makerkit/trans';
import { PageBody } from '@kit/ui/page';
import { Button } from '@kit/ui/shadcn/button';
import { loadUserAnalysis } from '../../_lib/server/load-user-analysis';
import Analysis, { AnalysisStatus } from './_components/analysis';
export const generateMetadata = async () => {
const i18n = await createI18nServerInstance();
const title = i18n.t('account:analysisResults.pageTitle');
return {
title,
};
};
async function AnalysisResultsPage() {
const analysisList = await loadUserAnalysis();
return (
<PageBody>
<div className="mt-8 flex items-center justify-between">
<div>
<h4>
<Trans i18nKey="account:analysisResults.pageTitle" />
</h4>
<p className="text-muted-foreground text-sm">
<Trans i18nKey="account:analysisResults.description" />
</p>
</div>
<Button>
<Trans i18nKey="account:analysisResults.orderNewAnalysis" />
</Button>
</div>
<div className="flex flex-col gap-2">
{analysisList?.map((analysis, index) => (
<Analysis
key={index}
analysis={{
name: analysis.element.analysis_name || '',
status: analysis.element.norm_status as AnalysisStatus,
unit: analysis.element.unit || '',
value: analysis.element.response_value,
normLowerIncluded: !!analysis.element.norm_lower_included,
normUpperIncluded: !!analysis.element.norm_upper_included,
normLower: analysis.element.norm_lower || 0,
normUpper: analysis.element.norm_upper || 0,
}}
/>
))}
</div>
</PageBody>
);
}
export default withI18n(AnalysisResultsPage);

View File

@@ -0,0 +1,22 @@
import { cache } from 'react';
import { createAccountsApi } from '@kit/accounts/api';
import { UserAnalysis } from '@kit/accounts/types/accounts';
import { getSupabaseServerClient } from '@kit/supabase/server-client';
export type UserAccount = Awaited<ReturnType<typeof loadUserAnalysis>>;
/**
* @name loadUserAccount
* @description
* Load the user account. It's a cached per-request function that fetches the user workspace data.
* It can be used across the server components to load the user workspace data.
*/
export const loadUserAnalysis = cache(analysisLoader);
async function analysisLoader(): Promise<UserAnalysis | null> {
const client = getSupabaseServerClient();
const api = createAccountsApi(client);
return api.getUserAnalysis();
}

1
check-env.js Normal file
View File

@@ -0,0 +1 @@
console.log('ENV =', process.env.MEDUSA_BACKEND_URL);

View File

@@ -61,7 +61,7 @@ const pathsConfig = PathsSchema.parse({
orderAnalysisPackage: '/home/order-analysis-package', orderAnalysisPackage: '/home/order-analysis-package',
// these routes are added as placeholders and can be changed when the pages are added // these routes are added as placeholders and can be changed when the pages are added
myOrders: '/my-orders', myOrders: '/my-orders',
analysisResults: '/analysis-results', analysisResults: '/home/analysis-results',
orderAnalysis: '/order-analysis', orderAnalysis: '/order-analysis',
orderHealthAnalysis: '/order-health-analysis', orderHealthAnalysis: '/order-health-analysis',
}, },

View File

@@ -617,6 +617,7 @@ export async function syncPrivateMessage(
response_value: response.VastuseVaartus, response_value: response.VastuseVaartus,
unit: element.Mootyhik ?? null, unit: element.Mootyhik ?? null,
original_response_element: element, original_response_element: element,
analysis_name: element.UuringNimi || element.KNimetus,
})), })),
); );
} }

View File

@@ -23,7 +23,7 @@
"supabase:test": "supabase db test", "supabase:test": "supabase db test",
"supabase:db:reset": "supabase db reset", "supabase:db:reset": "supabase db reset",
"supabase:db:lint": "supabase db lint", "supabase:db:lint": "supabase db lint",
"supabase:db:diff": "supabase db diff", "supabase:db:diff": "supabase db diff --schema auth --schema audit --schema medreport",
"supabase:deploy": "supabase link --project-ref $SUPABASE_PROJECT_REF && supabase db push", "supabase:deploy": "supabase link --project-ref $SUPABASE_PROJECT_REF && supabase db push",
"supabase:typegen": "supabase gen types typescript --local > ./packages/supabase/src/database.types.ts", "supabase:typegen": "supabase gen types typescript --local > ./packages/supabase/src/database.types.ts",
"supabase:db:dump:local": "supabase db dump --local --data-only", "supabase:db:dump:local": "supabase db dump --local --data-only",

View File

@@ -14,7 +14,8 @@
"./personal-account-settings": "./src/components/personal-account-settings/index.ts", "./personal-account-settings": "./src/components/personal-account-settings/index.ts",
"./components": "./src/components/index.ts", "./components": "./src/components/index.ts",
"./hooks/*": "./src/hooks/*.ts", "./hooks/*": "./src/hooks/*.ts",
"./api": "./src/server/api.ts" "./api": "./src/server/api.ts",
"./types/*": "./src/types/*.ts"
}, },
"dependencies": { "dependencies": {
"nanoid": "^5.1.5" "nanoid": "^5.1.5"

View File

@@ -2,6 +2,8 @@ import { SupabaseClient } from '@supabase/supabase-js';
import { Database } from '@kit/supabase/database'; import { Database } from '@kit/supabase/database';
import { UserAnalysis } from '../types/accounts';
/** /**
* Class representing an API for interacting with user accounts. * Class representing an API for interacting with user accounts.
* @constructor * @constructor
@@ -169,6 +171,51 @@ class AccountsApi {
return response.data?.customer_id; return response.data?.customer_id;
} }
async getUserAnalysis(): Promise<UserAnalysis | null> {
const authUser = await this.client.auth.getUser();
const { data, error: userError } = authUser;
if (userError) {
console.error('Failed to get user', userError);
throw userError;
}
const { user } = data;
const { data: analysisResponses } = await this.client
.schema('medreport')
.from('analysis_responses')
.select('*')
.eq('user_id', user.id);
if (!analysisResponses) {
return null;
}
const analysisResponseIds = analysisResponses.map((r) => r.id);
const { data: analysisResponseElements } = await this.client
.schema('medreport')
.from('analysis_response_elements')
.select('*')
.in('analysis_response_id', analysisResponseIds);
if (!analysisResponseElements) {
return null;
}
const elementMap = new Map(
analysisResponseElements.map((e) => [e.analysis_response_id, e]),
);
return analysisResponses
.filter((r) => elementMap.has(r.id))
.map((r) => ({
...r,
element: elementMap.get(r.id)!,
}));
}
} }
export function createAccountsApi(client: SupabaseClient<Database>) { export function createAccountsApi(client: SupabaseClient<Database>) {

View File

@@ -0,0 +1,6 @@
import { Database } from '@kit/supabase/database';
export type UserAnalysis =
(Database['medreport']['Tables']['analysis_responses']['Row'] & {
element: Database['medreport']['Tables']['analysis_response_elements']['Row'];
})[];

View File

@@ -1,14 +1,16 @@
import Medusa from "@medusajs/js-sdk" import Medusa from "@medusajs/js-sdk";
// Defaults to standard port for Medusa server // Defaults to standard port for Medusa server
let MEDUSA_BACKEND_URL = "http://localhost:9000" let MEDUSA_BACKEND_URL = "http://localhost:9000";
if (process.env.MEDUSA_BACKEND_URL) { if (process.env.MEDUSA_BACKEND_URL) {
MEDUSA_BACKEND_URL = process.env.MEDUSA_BACKEND_URL MEDUSA_BACKEND_URL = process.env.MEDUSA_BACKEND_URL;
} }
export const sdk = new Medusa({ export const SDK_CONFIG = {
baseUrl: MEDUSA_BACKEND_URL, baseUrl: MEDUSA_BACKEND_URL,
debug: process.env.NODE_ENV === "development", debug: process.env.NODE_ENV === "development",
publishableKey: process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY, publishableKey: process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
}) };
export const sdk = new Medusa(SDK_CONFIG);

View File

@@ -1,13 +1,13 @@
"use server" "use server";
import { sdk } from "@lib/config" import { sdk, SDK_CONFIG } from "@lib/config";
import { HttpTypes } from "@medusajs/types" import { HttpTypes } from "@medusajs/types";
import { getCacheOptions } from "./cookies" import { getCacheOptions } from "./cookies";
export const retrieveCollection = async (id: string) => { export const retrieveCollection = async (id: string) => {
const next = { const next = {
...(await getCacheOptions("collections")), ...(await getCacheOptions("collections")),
} };
return sdk.client return sdk.client
.fetch<{ collection: HttpTypes.StoreCollection }>( .fetch<{ collection: HttpTypes.StoreCollection }>(
@@ -17,19 +17,19 @@ export const retrieveCollection = async (id: string) => {
cache: "force-cache", cache: "force-cache",
} }
) )
.then(({ collection }) => collection) .then(({ collection }) => collection);
} };
export const listCollections = async ( export const listCollections = async (
queryParams: Record<string, string> = {} queryParams: Record<string, string> = {}
): Promise<{ collections: HttpTypes.StoreCollection[]; count: number }> => { ): Promise<{ collections: HttpTypes.StoreCollection[]; count: number }> => {
const next = { const next = {
...(await getCacheOptions("collections")), ...(await getCacheOptions("collections")),
} };
queryParams.limit = queryParams.limit || "100"
queryParams.offset = queryParams.offset || "0"
queryParams.limit = queryParams.limit || "100";
queryParams.offset = queryParams.offset || "0";
console.log("SDK_CONFIG: ", SDK_CONFIG.baseUrl);
return sdk.client return sdk.client
.fetch<{ collections: HttpTypes.StoreCollection[]; count: number }>( .fetch<{ collections: HttpTypes.StoreCollection[]; count: number }>(
"/store/collections", "/store/collections",
@@ -39,15 +39,15 @@ export const listCollections = async (
cache: "force-cache", cache: "force-cache",
} }
) )
.then(({ collections }) => ({ collections, count: collections.length })) .then(({ collections }) => ({ collections, count: collections.length }));
} };
export const getCollectionByHandle = async ( export const getCollectionByHandle = async (
handle: string handle: string
): Promise<HttpTypes.StoreCollection> => { ): Promise<HttpTypes.StoreCollection> => {
const next = { const next = {
...(await getCacheOptions("collections")), ...(await getCacheOptions("collections")),
} };
return sdk.client return sdk.client
.fetch<HttpTypes.StoreCollectionListResponse>(`/store/collections`, { .fetch<HttpTypes.StoreCollectionListResponse>(`/store/collections`, {
@@ -55,5 +55,5 @@ export const getCollectionByHandle = async (
next, next,
cache: "force-cache", cache: "force-cache",
}) })
.then(({ collections }) => collections[0]) .then(({ collections }) => collections[0]);
} };

File diff suppressed because it is too large Load Diff

View File

@@ -37,16 +37,12 @@ function PageWithSidebar(props: PageProps) {
<div <div
className={ className={
props.contentContainerClassName ?? props.contentContainerClassName ??
'mx-auto flex h-screen w-full flex-col overflow-y-auto bg-inherit' 'mx-auto flex h-screen w-full flex-col bg-inherit'
} }
> >
{MobileNavigation} {MobileNavigation}
<div <div className={'bg-background flex flex-1 flex-col px-4 lg:px-0'}>
className={
'bg-background flex flex-1 flex-col overflow-y-auto px-4 lg:px-0'
}
>
{Children} {Children}
</div> </div>
</div> </div>
@@ -75,7 +71,7 @@ function PageWithHeader(props: PageProps) {
const { Navigation, Children, MobileNavigation } = getSlotsFromPage(props); const { Navigation, Children, MobileNavigation } = getSlotsFromPage(props);
return ( return (
<div className={cn('flex h-screen flex-1 flex-col z-900', props.className)}> <div className={cn('z-900 flex h-screen flex-1 flex-col', props.className)}>
<div <div
className={ className={
props.contentContainerClassName ?? 'flex flex-1 flex-col space-y-4' props.contentContainerClassName ?? 'flex flex-1 flex-col space-y-4'
@@ -83,7 +79,7 @@ function PageWithHeader(props: PageProps) {
> >
<div <div
className={cn( className={cn(
'bg-bg-background border-1 light:border-border dark:border-border dark:shadow-primary/10 flex h-15 items-center justify-between px-4 py-1 lg:justify-start lg:shadow-xs border-b', 'bg-bg-background light:border-border dark:border-border dark:shadow-primary/10 flex h-15 items-center justify-between border-1 border-b px-4 py-1 lg:justify-start lg:shadow-xs',
{ {
'sticky top-0 z-1000 backdrop-blur-md': props.sticky ?? true, 'sticky top-0 z-1000 backdrop-blur-md': props.sticky ?? true,
}, },

View File

@@ -122,5 +122,10 @@
"consentToAnonymizedCompanyData": { "consentToAnonymizedCompanyData": {
"label": "Consent to be included in employer statistics", "label": "Consent to be included in employer statistics",
"description": "Consent to be included in anonymized company statistics" "description": "Consent to be included in anonymized company statistics"
},
"analysisResults": {
"pageTitle": "My analysis results",
"description": "Super, oled käinud tervist kontrollimas. Siin on sinule olulised näitajad:",
"orderNewAnalysis": "Telli uued analüüsid"
} }
} }

View File

@@ -145,5 +145,10 @@
"successTitle": "Tere, {{firstName}} {{lastName}}", "successTitle": "Tere, {{firstName}} {{lastName}}",
"successDescription": "Teie tervisekonto on aktiveeritud ja kasutamiseks valmis!", "successDescription": "Teie tervisekonto on aktiveeritud ja kasutamiseks valmis!",
"successButton": "Jätka" "successButton": "Jätka"
},
"analysisResults": {
"pageTitle": "Minu analüüside vastused",
"description": "Super, oled käinud tervist kontrollimas. Siin on sinule olulised näitajad:",
"orderNewAnalysis": "Telli uued analüüsid"
} }
} }

View File

@@ -119,5 +119,8 @@
"consentToAnonymizedCompanyData": { "consentToAnonymizedCompanyData": {
"label": "Consent to be included in employer statistics", "label": "Consent to be included in employer statistics",
"description": "Consent to be included in anonymized company statistics" "description": "Consent to be included in anonymized company statistics"
},
"analysisResults": {
"pageTitle": "My analysis results"
} }
} }

View File

@@ -1,227 +1,227 @@
create table "public"."connected_online_providers" ( -- create table "public"."connected_online_providers" (
"id" bigint not null, -- "id" bigint not null,
"name" text not null, -- "name" text not null,
"email" text, -- "email" text,
"phone_number" text, -- "phone_number" text,
"can_select_worker" boolean not null, -- "can_select_worker" boolean not null,
"personal_code_required" boolean not null, -- "personal_code_required" boolean not null,
"created_at" timestamp with time zone not null default now(), -- "created_at" timestamp with time zone not null default now(),
"updated_at" timestamp without time zone default now() -- "updated_at" timestamp without time zone default now()
); -- );
alter table "public"."connected_online_providers" enable row level security; -- alter table "public"."connected_online_providers" enable row level security;
create table "public"."connected_online_services" ( -- create table "public"."connected_online_services" (
"id" bigint not null, -- "id" bigint not null,
"clinic_id" bigint not null, -- "clinic_id" bigint not null,
"sync_id" bigint not null, -- "sync_id" bigint not null,
"name" text not null, -- "name" text not null,
"description" text, -- "description" text,
"price" double precision not null, -- "price" double precision not null,
"requires_payment" boolean not null, -- "requires_payment" boolean not null,
"duration" bigint not null, -- "duration" bigint not null,
"neto_duration" bigint, -- "neto_duration" bigint,
"display" text, -- "display" text,
"price_periods" text, -- "price_periods" text,
"online_hide_duration" bigint, -- "online_hide_duration" bigint,
"online_hide_price" bigint, -- "online_hide_price" bigint,
"code" text not null, -- "code" text not null,
"has_free_codes" boolean not null, -- "has_free_codes" boolean not null,
"created_at" timestamp with time zone not null default now(), -- "created_at" timestamp with time zone not null default now(),
"updated_at" timestamp with time zone default now() -- "updated_at" timestamp with time zone default now()
); -- );
alter table "public"."connected_online_services" enable row level security; -- alter table "public"."connected_online_services" enable row level security;
CREATE UNIQUE INDEX connected_online_providers_id_key ON public.connected_online_providers USING btree (id); -- CREATE UNIQUE INDEX connected_online_providers_id_key ON public.connected_online_providers USING btree (id);
CREATE UNIQUE INDEX connected_online_providers_pkey ON public.connected_online_providers USING btree (id); -- CREATE UNIQUE INDEX connected_online_providers_pkey ON public.connected_online_providers USING btree (id);
CREATE UNIQUE INDEX connected_online_services_id_key ON public.connected_online_services USING btree (id); -- CREATE UNIQUE INDEX connected_online_services_id_key ON public.connected_online_services USING btree (id);
CREATE UNIQUE INDEX connected_online_services_pkey ON public.connected_online_services USING btree (id); -- CREATE UNIQUE INDEX connected_online_services_pkey ON public.connected_online_services USING btree (id);
alter table "public"."connected_online_providers" add constraint "connected_online_providers_pkey" PRIMARY KEY using index "connected_online_providers_pkey"; -- alter table "public"."connected_online_providers" add constraint "connected_online_providers_pkey" PRIMARY KEY using index "connected_online_providers_pkey";
alter table "public"."connected_online_services" add constraint "connected_online_services_pkey" PRIMARY KEY using index "connected_online_services_pkey"; -- alter table "public"."connected_online_services" add constraint "connected_online_services_pkey" PRIMARY KEY using index "connected_online_services_pkey";
alter table "public"."connected_online_providers" add constraint "connected_online_providers_id_key" UNIQUE using index "connected_online_providers_id_key"; -- alter table "public"."connected_online_providers" add constraint "connected_online_providers_id_key" UNIQUE using index "connected_online_providers_id_key";
alter table "public"."connected_online_services" add constraint "connected_online_services_clinic_id_fkey" FOREIGN KEY (clinic_id) REFERENCES connected_online_providers(id) ON UPDATE CASCADE ON DELETE CASCADE not valid; -- alter table "public"."connected_online_services" add constraint "connected_online_services_clinic_id_fkey" FOREIGN KEY (clinic_id) REFERENCES connected_online_providers(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
alter table "public"."connected_online_services" validate constraint "connected_online_services_clinic_id_fkey"; -- alter table "public"."connected_online_services" validate constraint "connected_online_services_clinic_id_fkey";
alter table "public"."connected_online_services" add constraint "connected_online_services_id_key" UNIQUE using index "connected_online_services_id_key"; -- alter table "public"."connected_online_services" add constraint "connected_online_services_id_key" UNIQUE using index "connected_online_services_id_key";
grant delete on table "public"."connected_online_providers" to "service_role"; -- grant delete on table "public"."connected_online_providers" to "service_role";
grant insert on table "public"."connected_online_providers" to "service_role"; -- grant insert on table "public"."connected_online_providers" to "service_role";
grant references on table "public"."connected_online_providers" to "service_role"; -- grant references on table "public"."connected_online_providers" to "service_role";
grant select on table "public"."connected_online_providers" to "service_role"; -- grant select on table "public"."connected_online_providers" to "service_role";
grant trigger on table "public"."connected_online_providers" to "service_role"; -- grant trigger on table "public"."connected_online_providers" to "service_role";
grant truncate on table "public"."connected_online_providers" to "service_role"; -- grant truncate on table "public"."connected_online_providers" to "service_role";
grant update on table "public"."connected_online_providers" to "service_role"; -- grant update on table "public"."connected_online_providers" to "service_role";
grant select on table "public"."connected_online_providers" to "authenticated"; -- grant select on table "public"."connected_online_providers" to "authenticated";
grant delete on table "public"."connected_online_services" to "service_role"; -- grant delete on table "public"."connected_online_services" to "service_role";
grant insert on table "public"."connected_online_services" to "service_role"; -- grant insert on table "public"."connected_online_services" to "service_role";
grant references on table "public"."connected_online_services" to "service_role"; -- grant references on table "public"."connected_online_services" to "service_role";
grant select on table "public"."connected_online_services" to "service_role"; -- grant select on table "public"."connected_online_services" to "service_role";
grant trigger on table "public"."connected_online_services" to "service_role"; -- grant trigger on table "public"."connected_online_services" to "service_role";
grant truncate on table "public"."connected_online_services" to "service_role"; -- grant truncate on table "public"."connected_online_services" to "service_role";
grant update on table "public"."connected_online_services" to "service_role"; -- grant update on table "public"."connected_online_services" to "service_role";
grant select on table "public"."connected_online_services" to "authenticated"; -- grant select on table "public"."connected_online_services" to "authenticated";
create type "audit"."request_status" as enum ('SUCCESS', 'FAIL'); -- create type "audit"."request_status" as enum ('SUCCESS', 'FAIL');
create table "audit"."request_entries" ( -- create table "audit"."request_entries" (
"id" bigint generated by default as identity not null, -- "id" bigint generated by default as identity not null,
"personal_code" bigint, -- "personal_code" bigint,
"request_api" text not null, -- "request_api" text not null,
"request_api_method" text not null, -- "request_api_method" text not null,
"status" audit.request_status not null, -- "status" audit.request_status not null,
"comment" text, -- "comment" text,
"service_provider_id" bigint, -- "service_provider_id" bigint,
"service_id" bigint, -- "service_id" bigint,
"requested_start_date" timestamp with time zone, -- "requested_start_date" timestamp with time zone,
"requested_end_date" timestamp with time zone, -- "requested_end_date" timestamp with time zone,
"created_at" timestamp with time zone not null default now() -- "created_at" timestamp with time zone not null default now()
); -- );
alter table "audit"."request_entries" enable row level security; -- alter table "audit"."request_entries" enable row level security;
CREATE UNIQUE INDEX request_entries_pkey ON audit.request_entries USING btree (id); -- CREATE UNIQUE INDEX request_entries_pkey ON audit.request_entries USING btree (id);
alter table "audit"."request_entries" add constraint "request_entries_pkey" PRIMARY KEY using index "request_entries_pkey"; -- alter table "audit"."request_entries" add constraint "request_entries_pkey" PRIMARY KEY using index "request_entries_pkey";
grant delete on table "audit"."request_entries" to "service_role"; -- grant delete on table "audit"."request_entries" to "service_role";
grant insert on table "audit"."request_entries" to "service_role"; -- grant insert on table "audit"."request_entries" to "service_role";
grant references on table "audit"."request_entries" to "service_role"; -- grant references on table "audit"."request_entries" to "service_role";
grant select on table "audit"."request_entries" to "service_role"; -- grant select on table "audit"."request_entries" to "service_role";
grant trigger on table "audit"."request_entries" to "service_role"; -- grant trigger on table "audit"."request_entries" to "service_role";
grant truncate on table "audit"."request_entries" to "service_role"; -- grant truncate on table "audit"."request_entries" to "service_role";
grant update on table "audit"."request_entries" to "service_role"; -- grant update on table "audit"."request_entries" to "service_role";
create policy "service_role_all" -- create policy "service_role_all"
on "audit"."request_entries" -- on "audit"."request_entries"
as permissive -- as permissive
for all -- for all
to service_role -- to service_role
using (true); -- using (true);
create table "public"."connected_online_reservation" ( -- create table "public"."connected_online_reservation" (
"id" bigint generated by default as identity not null, -- "id" bigint generated by default as identity not null,
"user_id" uuid not null, -- "user_id" uuid not null,
"booking_code" text not null, -- "booking_code" text not null,
"service_id" bigint not null, -- "service_id" bigint not null,
"clinic_id" bigint not null, -- "clinic_id" bigint not null,
"service_user_id" bigint, -- "service_user_id" bigint,
"sync_user_id" bigint not null, -- "sync_user_id" bigint not null,
"requires_payment" boolean not null, -- "requires_payment" boolean not null,
"comments" text, -- "comments" text,
"start_time" timestamp with time zone not null, -- "start_time" timestamp with time zone not null,
"lang" text not null, -- "lang" text not null,
"discount_code" text, -- "discount_code" text,
"created_at" timestamp with time zone not null default now(), -- "created_at" timestamp with time zone not null default now(),
"updated_at" timestamp with time zone default now() -- "updated_at" timestamp with time zone default now()
); -- );
alter table "public"."connected_online_reservation" enable row level security; -- alter table "public"."connected_online_reservation" enable row level security;
CREATE UNIQUE INDEX connected_online_reservation_booking_code_key ON public.connected_online_reservation USING btree (booking_code); -- CREATE UNIQUE INDEX connected_online_reservation_booking_code_key ON public.connected_online_reservation USING btree (booking_code);
CREATE UNIQUE INDEX connected_online_reservation_pkey ON public.connected_online_reservation USING btree (id); -- CREATE UNIQUE INDEX connected_online_reservation_pkey ON public.connected_online_reservation USING btree (id);
alter table "public"."connected_online_reservation" add constraint "connected_online_reservation_pkey" PRIMARY KEY using index "connected_online_reservation_pkey"; -- alter table "public"."connected_online_reservation" add constraint "connected_online_reservation_pkey" PRIMARY KEY using index "connected_online_reservation_pkey";
alter table "public"."connected_online_reservation" add constraint "connected_online_reservation_booking_code_key" UNIQUE using index "connected_online_reservation_booking_code_key"; -- alter table "public"."connected_online_reservation" add constraint "connected_online_reservation_booking_code_key" UNIQUE using index "connected_online_reservation_booking_code_key";
alter table "public"."connected_online_reservation" add constraint "connected_online_reservation_user_id_fkey" FOREIGN KEY (user_id) REFERENCES auth.users(id) ON UPDATE CASCADE ON DELETE CASCADE not valid; -- alter table "public"."connected_online_reservation" add constraint "connected_online_reservation_user_id_fkey" FOREIGN KEY (user_id) REFERENCES auth.users(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
alter table "public"."connected_online_reservation" validate constraint "connected_online_reservation_user_id_fkey"; -- alter table "public"."connected_online_reservation" validate constraint "connected_online_reservation_user_id_fkey";
grant delete on table "public"."connected_online_reservation" to "service_role"; -- grant delete on table "public"."connected_online_reservation" to "service_role";
grant insert on table "public"."connected_online_reservation" to "service_role"; -- grant insert on table "public"."connected_online_reservation" to "service_role";
grant references on table "public"."connected_online_reservation" to "service_role"; -- grant references on table "public"."connected_online_reservation" to "service_role";
grant select on table "public"."connected_online_reservation" to "service_role"; -- grant select on table "public"."connected_online_reservation" to "service_role";
grant trigger on table "public"."connected_online_reservation" to "service_role"; -- grant trigger on table "public"."connected_online_reservation" to "service_role";
grant truncate on table "public"."connected_online_reservation" to "service_role"; -- grant truncate on table "public"."connected_online_reservation" to "service_role";
grant update on table "public"."connected_online_reservation" to "service_role"; -- grant update on table "public"."connected_online_reservation" to "service_role";
create policy "service_role_all" -- create policy "service_role_all"
on "public"."connected_online_reservation" -- on "public"."connected_online_reservation"
as permissive -- as permissive
for all -- for all
to service_role -- to service_role
using (true); -- using (true);
CREATE TRIGGER connected_online_providers_change_record_timestamps AFTER INSERT OR UPDATE ON public.connected_online_providers FOR EACH ROW EXECUTE FUNCTION trigger_set_timestamps(); -- CREATE TRIGGER connected_online_providers_change_record_timestamps AFTER INSERT OR UPDATE ON public.connected_online_providers FOR EACH ROW EXECUTE FUNCTION trigger_set_timestamps();
CREATE TRIGGER connected_online_services_change_record_timestamps AFTER INSERT OR UPDATE ON public.connected_online_services FOR EACH ROW EXECUTE FUNCTION trigger_set_timestamps(); -- CREATE TRIGGER connected_online_services_change_record_timestamps AFTER INSERT OR UPDATE ON public.connected_online_services FOR EACH ROW EXECUTE FUNCTION trigger_set_timestamps();
create policy "service_role_all" -- create policy "service_role_all"
on "public"."connected_online_providers" -- on "public"."connected_online_providers"
as permissive -- as permissive
for all -- for all
to service_role -- to service_role
using (true); -- using (true);
create policy "service_role_all" -- create policy "service_role_all"
on "public"."connected_online_services" -- on "public"."connected_online_services"
as permissive -- as permissive
for all -- for all
to service_role -- to service_role
using (true); -- using (true);
create policy "authenticated_select" -- create policy "authenticated_select"
on "public"."connected_online_providers" -- on "public"."connected_online_providers"
as permissive -- as permissive
for select -- for select
to authenticated -- to authenticated
using (true); -- using (true);
create policy "authenticated_select" -- create policy "authenticated_select"
on "public"."connected_online_services" -- on "public"."connected_online_services"
as permissive -- as permissive
for select -- for select
to authenticated -- to authenticated
using (true); -- using (true);
create policy "own_all" -- create policy "own_all"
on "public"."connected_online_reservation" -- on "public"."connected_online_reservation"
as permissive -- as permissive
for all -- for all
to authenticated -- to authenticated
using ((( SELECT auth.uid() AS uid) = user_id)); -- using ((( SELECT auth.uid() AS uid) = user_id));

View File

@@ -1,225 +1,225 @@
create table "public"."medreport_product_groups" ( -- create table "public"."medreport_product_groups" (
"id" bigint generated by default as identity not null, -- "id" bigint generated by default as identity not null,
"name" text not null, -- "name" text not null,
"created_at" timestamp with time zone not null default now(), -- "created_at" timestamp with time zone not null default now(),
"updated_at" timestamp with time zone -- "updated_at" timestamp with time zone
); -- );
create table "public"."medreport_products" ( -- create table "public"."medreport_products" (
"id" bigint generated by default as identity not null, -- "id" bigint generated by default as identity not null,
"name" text not null, -- "name" text not null,
"product_group_id" bigint, -- "product_group_id" bigint,
"created_at" timestamp with time zone not null default now(), -- "created_at" timestamp with time zone not null default now(),
"updated_at" timestamp with time zone default now() -- "updated_at" timestamp with time zone default now()
); -- );
alter table "public"."medreport_products" enable row level security; -- alter table "public"."medreport_products" enable row level security;
create table "public"."medreport_products_analyses_relations" ( -- create table "public"."medreport_products_analyses_relations" (
"product_id" bigint not null, -- "product_id" bigint not null,
"analysis_element_id" bigint, -- "analysis_element_id" bigint,
"analysis_id" bigint -- "analysis_id" bigint
); -- );
alter table "public"."medreport_product_groups" enable row level security; -- alter table "public"."medreport_product_groups" enable row level security;
alter table "public"."medreport_products_analyses_relations" enable row level security; -- alter table "public"."medreport_products_analyses_relations" enable row level security;
CREATE UNIQUE INDEX medreport_product_groups_name_key ON public.medreport_product_groups USING btree (name); -- CREATE UNIQUE INDEX medreport_product_groups_name_key ON public.medreport_product_groups USING btree (name);
CREATE UNIQUE INDEX medreport_product_groups_pkey ON public.medreport_product_groups USING btree (id); -- CREATE UNIQUE INDEX medreport_product_groups_pkey ON public.medreport_product_groups USING btree (id);
alter table "public"."medreport_product_groups" add constraint "medreport_product_groups_pkey" PRIMARY KEY using index "medreport_product_groups_pkey"; -- alter table "public"."medreport_product_groups" add constraint "medreport_product_groups_pkey" PRIMARY KEY using index "medreport_product_groups_pkey";
alter table "public"."medreport_product_groups" add constraint "medreport_product_groups_name_key" UNIQUE using index "medreport_product_groups_name_key"; -- alter table "public"."medreport_product_groups" add constraint "medreport_product_groups_name_key" UNIQUE using index "medreport_product_groups_name_key";
alter table "public"."medreport_products" add constraint "medreport_products_product_groups_id_fkey" FOREIGN KEY (product_group_id) REFERENCES medreport_product_groups(id) ON UPDATE CASCADE ON DELETE CASCADE not valid; -- alter table "public"."medreport_products" add constraint "medreport_products_product_groups_id_fkey" FOREIGN KEY (product_group_id) REFERENCES medreport_product_groups(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
alter table "public"."medreport_products" validate constraint "medreport_products_product_groups_id_fkey"; -- alter table "public"."medreport_products" validate constraint "medreport_products_product_groups_id_fkey";
grant select on table "public"."medreport_product_groups" to "anon"; -- grant select on table "public"."medreport_product_groups" to "anon";
grant select on table "public"."medreport_product_groups" to "authenticated"; -- grant select on table "public"."medreport_product_groups" to "authenticated";
grant delete on table "public"."medreport_product_groups" to "service_role"; -- grant delete on table "public"."medreport_product_groups" to "service_role";
grant insert on table "public"."medreport_product_groups" to "service_role"; -- grant insert on table "public"."medreport_product_groups" to "service_role";
grant references on table "public"."medreport_product_groups" to "service_role"; -- grant references on table "public"."medreport_product_groups" to "service_role";
grant select on table "public"."medreport_product_groups" to "service_role"; -- grant select on table "public"."medreport_product_groups" to "service_role";
grant trigger on table "public"."medreport_product_groups" to "service_role"; -- grant trigger on table "public"."medreport_product_groups" to "service_role";
grant truncate on table "public"."medreport_product_groups" to "service_role"; -- grant truncate on table "public"."medreport_product_groups" to "service_role";
grant update on table "public"."medreport_product_groups" to "service_role"; -- grant update on table "public"."medreport_product_groups" to "service_role";
CREATE UNIQUE INDEX medreport_products_analyses_analysis_element_id_key ON public.medreport_products_analyses_relations USING btree (analysis_element_id); -- CREATE UNIQUE INDEX medreport_products_analyses_analysis_element_id_key ON public.medreport_products_analyses_relations USING btree (analysis_element_id);
CREATE UNIQUE INDEX medreport_products_analyses_analysis_id_key ON public.medreport_products_analyses_relations USING btree (analysis_id); -- CREATE UNIQUE INDEX medreport_products_analyses_analysis_id_key ON public.medreport_products_analyses_relations USING btree (analysis_id);
CREATE UNIQUE INDEX medreport_products_analyses_pkey ON public.medreport_products_analyses_relations USING btree (product_id); -- CREATE UNIQUE INDEX medreport_products_analyses_pkey ON public.medreport_products_analyses_relations USING btree (product_id);
CREATE UNIQUE INDEX medreport_products_name_key ON public.medreport_products USING btree (name); -- CREATE UNIQUE INDEX medreport_products_name_key ON public.medreport_products USING btree (name);
CREATE UNIQUE INDEX medreport_products_pkey ON public.medreport_products USING btree (id); -- CREATE UNIQUE INDEX medreport_products_pkey ON public.medreport_products USING btree (id);
alter table "public"."medreport_products" add constraint "medreport_products_pkey" PRIMARY KEY using index "medreport_products_pkey"; -- alter table "public"."medreport_products" add constraint "medreport_products_pkey" PRIMARY KEY using index "medreport_products_pkey";
alter table "public"."medreport_products_analyses_relations" add constraint "medreport_products_analyses_pkey" PRIMARY KEY using index "medreport_products_analyses_pkey"; -- alter table "public"."medreport_products_analyses_relations" add constraint "medreport_products_analyses_pkey" PRIMARY KEY using index "medreport_products_analyses_pkey";
alter table "public"."medreport_products" add constraint "medreport_products_name_key" UNIQUE using index "medreport_products_name_key"; -- alter table "public"."medreport_products" add constraint "medreport_products_name_key" UNIQUE using index "medreport_products_name_key";
alter table "public"."medreport_products_analyses_relations" add constraint "medreport_products_analyses_analysis_element_id_fkey" FOREIGN KEY (analysis_element_id) REFERENCES analysis_elements(id) ON UPDATE CASCADE ON DELETE CASCADE not valid; -- alter table "public"."medreport_products_analyses_relations" add constraint "medreport_products_analyses_analysis_element_id_fkey" FOREIGN KEY (analysis_element_id) REFERENCES analysis_elements(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
alter table "public"."medreport_products_analyses_relations" validate constraint "medreport_products_analyses_analysis_element_id_fkey"; -- alter table "public"."medreport_products_analyses_relations" validate constraint "medreport_products_analyses_analysis_element_id_fkey";
alter table "public"."medreport_products_analyses_relations" add constraint "medreport_products_analyses_analysis_element_id_key" UNIQUE using index "medreport_products_analyses_analysis_element_id_key"; -- alter table "public"."medreport_products_analyses_relations" add constraint "medreport_products_analyses_analysis_element_id_key" UNIQUE using index "medreport_products_analyses_analysis_element_id_key";
alter table "public"."medreport_products_analyses_relations" add constraint "medreport_products_analyses_analysis_id_fkey" FOREIGN KEY (analysis_id) REFERENCES analyses(id) ON UPDATE CASCADE ON DELETE CASCADE not valid; -- alter table "public"."medreport_products_analyses_relations" add constraint "medreport_products_analyses_analysis_id_fkey" FOREIGN KEY (analysis_id) REFERENCES analyses(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
alter table "public"."medreport_products_analyses_relations" validate constraint "medreport_products_analyses_analysis_id_fkey"; -- alter table "public"."medreport_products_analyses_relations" validate constraint "medreport_products_analyses_analysis_id_fkey";
alter table "public"."medreport_products_analyses_relations" add constraint "medreport_products_analyses_analysis_id_key" UNIQUE using index "medreport_products_analyses_analysis_id_key"; -- alter table "public"."medreport_products_analyses_relations" add constraint "medreport_products_analyses_analysis_id_key" UNIQUE using index "medreport_products_analyses_analysis_id_key";
alter table "public"."medreport_products_analyses_relations" add constraint "medreport_products_analyses_product_id_fkey" FOREIGN KEY (product_id) REFERENCES medreport_products(id) ON UPDATE CASCADE ON DELETE CASCADE not valid; -- alter table "public"."medreport_products_analyses_relations" add constraint "medreport_products_analyses_product_id_fkey" FOREIGN KEY (product_id) REFERENCES medreport_products(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
alter table "public"."medreport_products_analyses_relations" validate constraint "medreport_products_analyses_product_id_fkey"; -- alter table "public"."medreport_products_analyses_relations" validate constraint "medreport_products_analyses_product_id_fkey";
alter table "public"."medreport_products_analyses_relations" add constraint "product_can_be_tied_to_only_one_external_item" CHECK (((analysis_id IS NULL) OR (analysis_element_id IS NULL))) not valid; -- alter table "public"."medreport_products_analyses_relations" add constraint "product_can_be_tied_to_only_one_external_item" CHECK (((analysis_id IS NULL) OR (analysis_element_id IS NULL))) not valid;
alter table "public"."medreport_products_analyses_relations" validate constraint "product_can_be_tied_to_only_one_external_item"; -- alter table "public"."medreport_products_analyses_relations" validate constraint "product_can_be_tied_to_only_one_external_item";
grant select on table "public"."medreport_products" to "anon"; -- grant select on table "public"."medreport_products" to "anon";
grant select on table "public"."medreport_products" to "authenticated"; -- grant select on table "public"."medreport_products" to "authenticated";
grant delete on table "public"."medreport_products" to "service_role"; -- grant delete on table "public"."medreport_products" to "service_role";
grant insert on table "public"."medreport_products" to "service_role"; -- grant insert on table "public"."medreport_products" to "service_role";
grant references on table "public"."medreport_products" to "service_role"; -- grant references on table "public"."medreport_products" to "service_role";
grant select on table "public"."medreport_products" to "service_role"; -- grant select on table "public"."medreport_products" to "service_role";
grant trigger on table "public"."medreport_products" to "service_role"; -- grant trigger on table "public"."medreport_products" to "service_role";
grant truncate on table "public"."medreport_products" to "service_role"; -- grant truncate on table "public"."medreport_products" to "service_role";
grant update on table "public"."medreport_products" to "service_role"; -- grant update on table "public"."medreport_products" to "service_role";
grant select on table "public"."medreport_products_analyses_relations" to "anon"; -- grant select on table "public"."medreport_products_analyses_relations" to "anon";
grant select on table "public"."medreport_products_analyses_relations" to "authenticated"; -- grant select on table "public"."medreport_products_analyses_relations" to "authenticated";
grant delete on table "public"."medreport_products_analyses_relations" to "service_role"; -- grant delete on table "public"."medreport_products_analyses_relations" to "service_role";
grant insert on table "public"."medreport_products_analyses_relations" to "service_role"; -- grant insert on table "public"."medreport_products_analyses_relations" to "service_role";
grant references on table "public"."medreport_products_analyses_relations" to "service_role"; -- grant references on table "public"."medreport_products_analyses_relations" to "service_role";
grant select on table "public"."medreport_products_analyses_relations" to "service_role"; -- grant select on table "public"."medreport_products_analyses_relations" to "service_role";
grant trigger on table "public"."medreport_products_analyses_relations" to "service_role"; -- grant trigger on table "public"."medreport_products_analyses_relations" to "service_role";
grant truncate on table "public"."medreport_products_analyses_relations" to "service_role"; -- grant truncate on table "public"."medreport_products_analyses_relations" to "service_role";
grant update on table "public"."medreport_products_analyses_relations" to "service_role"; -- grant update on table "public"."medreport_products_analyses_relations" to "service_role";
create policy "Enable read access for all users" -- create policy "Enable read access for all users"
on "public"."medreport_products_analyses_relations" -- on "public"."medreport_products_analyses_relations"
as permissive -- as permissive
for select -- for select
to public -- to public
using (true); -- using (true);
ALTER TABLE medreport_products_analyses_relations -- ALTER TABLE medreport_products_analyses_relations
ADD CONSTRAINT product_can_be_tied_to_only_one_analysis_item -- ADD CONSTRAINT product_can_be_tied_to_only_one_analysis_item
CHECK (analysis_id IS NULL OR analysis_element_id IS NULL); -- CHECK (analysis_id IS NULL OR analysis_element_id IS NULL);
create table "public"."medreport_products_external_services_relations" ( -- create table "public"."medreport_products_external_services_relations" (
"product_id" bigint not null, -- "product_id" bigint not null,
"connected_online_service_id" bigint not null -- "connected_online_service_id" bigint not null
); -- );
alter table "public"."medreport_products_external_services_relations" enable row level security; -- alter table "public"."medreport_products_external_services_relations" enable row level security;
CREATE UNIQUE INDEX medreport_products_connected_online_services_id_key ON public.medreport_products_external_services_relations USING btree (connected_online_service_id); -- CREATE UNIQUE INDEX medreport_products_connected_online_services_id_key ON public.medreport_products_external_services_relations USING btree (connected_online_service_id);
CREATE UNIQUE INDEX medreport_products_connected_online_services_pkey ON public.medreport_products_external_services_relations USING btree (connected_online_service_id); -- CREATE UNIQUE INDEX medreport_products_connected_online_services_pkey ON public.medreport_products_external_services_relations USING btree (connected_online_service_id);
alter table "public"."medreport_products_external_services_relations" add constraint "medreport_products_connected_online_services_pkey" PRIMARY KEY using index "medreport_products_connected_online_services_pkey"; -- alter table "public"."medreport_products_external_services_relations" add constraint "medreport_products_connected_online_services_pkey" PRIMARY KEY using index "medreport_products_connected_online_services_pkey";
alter table "public"."medreport_products_external_services_relations" add constraint "medreport_products_connected_online_services_id_fkey" FOREIGN KEY (connected_online_service_id) REFERENCES connected_online_services(id) ON UPDATE CASCADE ON DELETE CASCADE not valid; -- alter table "public"."medreport_products_external_services_relations" add constraint "medreport_products_connected_online_services_id_fkey" FOREIGN KEY (connected_online_service_id) REFERENCES connected_online_services(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
alter table "public"."medreport_products_external_services_relations" validate constraint "medreport_products_connected_online_services_id_fkey"; -- alter table "public"."medreport_products_external_services_relations" validate constraint "medreport_products_connected_online_services_id_fkey";
alter table "public"."medreport_products_external_services_relations" add constraint "medreport_products_connected_online_services_id_key" UNIQUE using index "medreport_products_connected_online_services_id_key"; -- alter table "public"."medreport_products_external_services_relations" add constraint "medreport_products_connected_online_services_id_key" UNIQUE using index "medreport_products_connected_online_services_id_key";
alter table "public"."medreport_products_external_services_relations" add constraint "medreport_products_connected_online_services_product_id_fkey" FOREIGN KEY (product_id) REFERENCES medreport_products(id) ON UPDATE CASCADE ON DELETE CASCADE not valid; -- alter table "public"."medreport_products_external_services_relations" add constraint "medreport_products_connected_online_services_product_id_fkey" FOREIGN KEY (product_id) REFERENCES medreport_products(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
alter table "public"."medreport_products_external_services_relations" validate constraint "medreport_products_connected_online_services_product_id_fkey"; -- alter table "public"."medreport_products_external_services_relations" validate constraint "medreport_products_connected_online_services_product_id_fkey";
grant select on table "public"."medreport_products_external_services_relations" to "anon"; -- grant select on table "public"."medreport_products_external_services_relations" to "anon";
grant select on table "public"."medreport_products_external_services_relations" to "authenticated"; -- grant select on table "public"."medreport_products_external_services_relations" to "authenticated";
grant delete on table "public"."medreport_products_external_services_relations" to "service_role"; -- grant delete on table "public"."medreport_products_external_services_relations" to "service_role";
grant insert on table "public"."medreport_products_external_services_relations" to "service_role"; -- grant insert on table "public"."medreport_products_external_services_relations" to "service_role";
grant references on table "public"."medreport_products_external_services_relations" to "service_role"; -- grant references on table "public"."medreport_products_external_services_relations" to "service_role";
grant select on table "public"."medreport_products_external_services_relations" to "service_role"; -- grant select on table "public"."medreport_products_external_services_relations" to "service_role";
grant trigger on table "public"."medreport_products_external_services_relations" to "service_role"; -- grant trigger on table "public"."medreport_products_external_services_relations" to "service_role";
grant truncate on table "public"."medreport_products_external_services_relations" to "service_role"; -- grant truncate on table "public"."medreport_products_external_services_relations" to "service_role";
grant update on table "public"."medreport_products_external_services_relations" to "service_role"; -- grant update on table "public"."medreport_products_external_services_relations" to "service_role";
CREATE OR REPLACE FUNCTION check_tied_to_connected_online() -- CREATE OR REPLACE FUNCTION check_tied_to_connected_online()
RETURNS TRIGGER AS $$ -- RETURNS TRIGGER AS $$
BEGIN -- BEGIN
IF EXISTS ( -- IF EXISTS (
SELECT 1 -- SELECT 1
FROM medreport_products_external_services_relations -- FROM medreport_products_external_services_relations
WHERE product_id = NEW.product_id -- WHERE product_id = NEW.product_id
) THEN -- ) THEN
RAISE EXCEPTION 'Value "%" already exists in medreport_products_external_services_relations', NEW.product_id; -- RAISE EXCEPTION 'Value "%" already exists in medreport_products_external_services_relations', NEW.product_id;
END IF; -- END IF;
RETURN NEW; -- RETURN NEW;
END; -- END;
$$ LANGUAGE plpgsql; -- $$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION check_tied_to_analysis_item() -- CREATE OR REPLACE FUNCTION check_tied_to_analysis_item()
RETURNS TRIGGER AS $$ -- RETURNS TRIGGER AS $$
BEGIN -- BEGIN
IF EXISTS ( -- IF EXISTS (
SELECT 1 -- SELECT 1
FROM medreport_products_analyses_relations -- FROM medreport_products_analyses_relations
WHERE product_id = NEW.product_id -- WHERE product_id = NEW.product_id
) THEN -- ) THEN
RAISE EXCEPTION 'Value "%" already exists in medreport_products_analyses_relations', NEW.product_id; -- RAISE EXCEPTION 'Value "%" already exists in medreport_products_analyses_relations', NEW.product_id;
END IF; -- END IF;
RETURN NEW; -- RETURN NEW;
END; -- END;
$$ LANGUAGE plpgsql; -- $$ LANGUAGE plpgsql;
CREATE TRIGGER check_not_already_tied_to_connected_online BEFORE INSERT OR UPDATE ON public.medreport_products_analyses_relations FOR EACH ROW EXECUTE FUNCTION check_tied_to_connected_online(); -- CREATE TRIGGER check_not_already_tied_to_connected_online BEFORE INSERT OR UPDATE ON public.medreport_products_analyses_relations FOR EACH ROW EXECUTE FUNCTION check_tied_to_connected_online();
CREATE TRIGGER check_not_already_tied_to_analysis BEFORE INSERT OR UPDATE ON public.medreport_products_external_services_relations FOR EACH ROW EXECUTE FUNCTION check_tied_to_analysis_item(); -- CREATE TRIGGER check_not_already_tied_to_analysis BEFORE INSERT OR UPDATE ON public.medreport_products_external_services_relations FOR EACH ROW EXECUTE FUNCTION check_tied_to_analysis_item();
create policy "read_all" -- create policy "read_all"
on "public"."medreport_product_groups" -- on "public"."medreport_product_groups"
as permissive -- as permissive
for select -- for select
to public -- to public
using (true); -- using (true);

View File

@@ -680,17 +680,17 @@ drop policy "accounts_self_update" on "public"."accounts";
drop policy "create_org_account" on "public"."accounts"; drop policy "create_org_account" on "public"."accounts";
drop policy "restrict_mfa_accounts" on "public"."accounts"; -- drop policy "restrict_mfa_accounts" on "public"."accounts";
drop policy "super_admins_access_accounts" on "public"."accounts"; -- drop policy "super_admins_access_accounts" on "public"."accounts";
drop policy "accounts_memberships_delete" on "public"."accounts_memberships"; drop policy "accounts_memberships_delete" on "public"."accounts_memberships";
drop policy "accounts_memberships_read" on "public"."accounts_memberships"; drop policy "accounts_memberships_read" on "public"."accounts_memberships";
drop policy "restrict_mfa_accounts_memberships" on "public"."accounts_memberships"; -- drop policy "restrict_mfa_accounts_memberships" on "public"."accounts_memberships";
drop policy "super_admins_access_accounts_memberships" on "public"."accounts_memberships"; -- drop policy "super_admins_access_accounts_memberships" on "public"."accounts_memberships";
drop policy "analysis_all" on "public"."analyses"; drop policy "analysis_all" on "public"."analyses";
@@ -742,53 +742,53 @@ drop policy "invitations_read_self" on "public"."invitations";
drop policy "invitations_update" on "public"."invitations"; drop policy "invitations_update" on "public"."invitations";
drop policy "restrict_mfa_invitations" on "public"."invitations"; -- drop policy "restrict_mfa_invitations" on "public"."invitations";
drop policy "super_admins_access_invitations" on "public"."invitations"; -- drop policy "super_admins_access_invitations" on "public"."invitations";
drop policy "read_all" on "public"."medreport_product_groups"; drop policy "read_all" on "public"."medreport_product_groups";
drop policy "Enable read access for all users" on "public"."medreport_products_analyses_relations"; drop policy "Enable read access for all users" on "public"."medreport_products_analyses_relations";
drop policy "Users can read their own nonces" on "public"."nonces"; -- drop policy "Users can read their own nonces" on "public"."nonces";
drop policy "notifications_read_self" on "public"."notifications"; drop policy "notifications_read_self" on "public"."notifications";
drop policy "notifications_update_self" on "public"."notifications"; drop policy "notifications_update_self" on "public"."notifications";
drop policy "restrict_mfa_notifications" on "public"."notifications"; -- drop policy "restrict_mfa_notifications" on "public"."notifications";
drop policy "order_items_read_self" on "public"."order_items"; drop policy "order_items_read_self" on "public"."order_items";
drop policy "restrict_mfa_order_items" on "public"."order_items"; -- drop policy "restrict_mfa_order_items" on "public"."order_items";
drop policy "super_admins_access_order_items" on "public"."order_items"; -- drop policy "super_admins_access_order_items" on "public"."order_items";
drop policy "orders_read_self" on "public"."orders"; drop policy "orders_read_self" on "public"."orders";
drop policy "restrict_mfa_orders" on "public"."orders"; -- drop policy "restrict_mfa_orders" on "public"."orders";
drop policy "super_admins_access_orders" on "public"."orders"; -- drop policy "super_admins_access_orders" on "public"."orders";
drop policy "restrict_mfa_role_permissions" on "public"."role_permissions"; -- drop policy "restrict_mfa_role_permissions" on "public"."role_permissions";
drop policy "role_permissions_read" on "public"."role_permissions"; drop policy "role_permissions_read" on "public"."role_permissions";
drop policy "super_admins_access_role_permissions" on "public"."role_permissions"; -- drop policy "super_admins_access_role_permissions" on "public"."role_permissions";
drop policy "roles_read" on "public"."roles"; drop policy "roles_read" on "public"."roles";
drop policy "restrict_mfa_subscription_items" on "public"."subscription_items"; -- drop policy "restrict_mfa_subscription_items" on "public"."subscription_items";
drop policy "subscription_items_read_self" on "public"."subscription_items"; drop policy "subscription_items_read_self" on "public"."subscription_items";
drop policy "super_admins_access_subscription_items" on "public"."subscription_items"; -- drop policy "super_admins_access_subscription_items" on "public"."subscription_items";
drop policy "restrict_mfa_subscriptions" on "public"."subscriptions"; -- drop policy "restrict_mfa_subscriptions" on "public"."subscriptions";
drop policy "subscriptions_read_self" on "public"."subscriptions"; drop policy "subscriptions_read_self" on "public"."subscriptions";
drop policy "super_admins_access_subscriptions" on "public"."subscriptions"; -- drop policy "super_admins_access_subscriptions" on "public"."subscriptions";
alter table "public"."accounts" drop constraint "accounts_created_by_fkey"; alter table "public"."accounts" drop constraint "accounts_created_by_fkey";
@@ -888,7 +888,7 @@ alter table "public"."medreport_products_analyses_relations" drop constraint "pr
alter table "public"."medreport_products_analyses_relations" drop constraint "product_can_be_tied_to_only_one_external_item"; alter table "public"."medreport_products_analyses_relations" drop constraint "product_can_be_tied_to_only_one_external_item";
alter table "public"."nonces" drop constraint "nonces_user_id_fkey"; -- alter table "public"."nonces" drop constraint "nonces_user_id_fkey";
alter table "public"."notifications" drop constraint "notifications_account_id_fkey"; alter table "public"."notifications" drop constraint "notifications_account_id_fkey";
@@ -956,7 +956,7 @@ alter table "public"."medreport_products_analyses_relations" drop constraint "me
alter table "public"."medreport_products_external_services_relations" drop constraint "medreport_products_connected_online_services_pkey"; alter table "public"."medreport_products_external_services_relations" drop constraint "medreport_products_connected_online_services_pkey";
alter table "public"."nonces" drop constraint "nonces_pkey"; -- alter table "public"."nonces" drop constraint "nonces_pkey";
alter table "public"."notifications" drop constraint "notifications_pkey"; alter table "public"."notifications" drop constraint "notifications_pkey";
@@ -5160,47 +5160,47 @@ revoke truncate on table "public"."medreport_products_external_services_relation
revoke update on table "public"."medreport_products_external_services_relations" from "service_role"; revoke update on table "public"."medreport_products_external_services_relations" from "service_role";
revoke delete on table "public"."nonces" from "anon"; -- revoke delete on table "public"."nonces" from "anon";
revoke insert on table "public"."nonces" from "anon"; -- revoke insert on table "public"."nonces" from "anon";
revoke references on table "public"."nonces" from "anon"; -- revoke references on table "public"."nonces" from "anon";
revoke select on table "public"."nonces" from "anon"; -- revoke select on table "public"."nonces" from "anon";
revoke trigger on table "public"."nonces" from "anon"; -- revoke trigger on table "public"."nonces" from "anon";
revoke truncate on table "public"."nonces" from "anon"; -- revoke truncate on table "public"."nonces" from "anon";
revoke update on table "public"."nonces" from "anon"; -- revoke update on table "public"."nonces" from "anon";
revoke delete on table "public"."nonces" from "authenticated"; -- revoke delete on table "public"."nonces" from "authenticated";
revoke insert on table "public"."nonces" from "authenticated"; -- revoke insert on table "public"."nonces" from "authenticated";
revoke references on table "public"."nonces" from "authenticated"; -- revoke references on table "public"."nonces" from "authenticated";
revoke select on table "public"."nonces" from "authenticated"; -- revoke select on table "public"."nonces" from "authenticated";
revoke trigger on table "public"."nonces" from "authenticated"; -- revoke trigger on table "public"."nonces" from "authenticated";
revoke truncate on table "public"."nonces" from "authenticated"; -- revoke truncate on table "public"."nonces" from "authenticated";
revoke update on table "public"."nonces" from "authenticated"; -- revoke update on table "public"."nonces" from "authenticated";
revoke delete on table "public"."nonces" from "service_role"; -- revoke delete on table "public"."nonces" from "service_role";
revoke insert on table "public"."nonces" from "service_role"; -- revoke insert on table "public"."nonces" from "service_role";
revoke references on table "public"."nonces" from "service_role"; -- revoke references on table "public"."nonces" from "service_role";
revoke select on table "public"."nonces" from "service_role"; -- revoke select on table "public"."nonces" from "service_role";
revoke trigger on table "public"."nonces" from "service_role"; -- revoke trigger on table "public"."nonces" from "service_role";
revoke truncate on table "public"."nonces" from "service_role"; -- revoke truncate on table "public"."nonces" from "service_role";
revoke update on table "public"."nonces" from "service_role"; -- revoke update on table "public"."nonces" from "service_role";
revoke delete on table "public"."notifications" from "anon"; revoke delete on table "public"."notifications" from "anon";
@@ -5410,7 +5410,7 @@ drop table "public"."medreport_products_analyses_relations";
drop table "public"."medreport_products_external_services_relations"; drop table "public"."medreport_products_external_services_relations";
drop table "public"."nonces"; -- drop table "public"."nonces";
drop table "public"."notifications"; drop table "public"."notifications";

View File

@@ -0,0 +1,3 @@
alter table "medreport"."analysis_response_elements" add column "analysis_name" text;
alter table "medreport"."analysis_response_elements" alter column "response_value" set data type double precision using "response_value"::double precision;

146
supabase/sql/analysis.sql Normal file
View File

@@ -0,0 +1,146 @@
-- Create analysis for /home/analysis-results
INSERT INTO medreport.analysis_groups (
id,
original_id,
name,
"order",
created_at,
updated_at
)
VALUES (
1, -- id
'GROUP_ORIG_001', -- original_id
'Blood Tests', -- name
1, -- order
NOW(), -- created_at
NOW() -- updated_at
);
INSERT INTO medreport.analysis_elements (
id,
analysis_id_oid,
analysis_id_original,
tehik_short_loinc,
tehik_loinc_name,
analysis_name_lab,
"order",
created_at,
updated_at,
parent_analysis_group_id,
material_groups
)
VALUES (
1, -- id (must match the one used in analyses)
'OID12345', -- analysis_id_oid
'ORIG123', -- analysis_id_original
'LNC123-4', -- tehik_short_loinc
'Hemoglobiin', -- tehik_loinc_name
'Hemoglobiin (Lab)', -- analysis_name_lab
1, -- order
NOW(), -- created_at
NOW(), -- updated_at
1, -- parent_analysis_group_id
'{}'::jsonb[] -- material_groups (empty array for now)
);
INSERT INTO medreport.analyses (
id,
analysis_id_oid,
analysis_id_original,
tehik_short_loinc,
tehik_loinc_name,
analysis_name_lab,
"order",
created_at,
updated_at,
parent_analysis_element_id
)
VALUES (
101, -- id
'OID12345', -- analysis_id_oid
'ORIG123', -- analysis_id_original
'LNC123-4', -- tehik_short_loinc
'Hemoglobiin', -- tehik_loinc_name
'Hemoglobiin (Lab)', -- analysis_name_lab
1, -- order
NOW(), -- created_at
NOW(), -- updated_at
1 -- parent_analysis_element_id
);
INSERT INTO medreport.analysis_orders (
analysis_element_ids,
analysis_ids,
user_id,
status,
id
) VALUES (
ARRAY[1, 2, 3],
ARRAY[101, 102],
'8dcb4354-77be-4915-a2cd-8fc573e675d6',
'COMPLETED',
'10' -- unique id
);
INSERT INTO medreport.analysis_responses (
id,
analysis_order_id,
order_number,
order_status,
user_id
)
VALUES (
'1', -- unique id
'10', -- ID of medreport.analysis_orders
'123',
'COMPLETED',
'8dcb4354-77be-4915-a2cd-8fc573e675d6'
)
ON CONFLICT (order_number)
DO UPDATE SET
analysis_order_id = EXCLUDED.analysis_order_id,
order_status = EXCLUDED.order_status,
user_id = EXCLUDED.user_id
RETURNING id;
INSERT INTO medreport.analysis_response_elements (
id,
analysis_response_id,
analysis_element_original_id,
unit,
response_value,
response_time,
norm_upper,
norm_upper_included,
norm_lower,
norm_lower_included,
norm_status,
original_response_element,
created_at,
updated_at,
analysis_name
)
VALUES
-- Repeat this row for each element
(
'1000', -- unique id
'1', -- ID of medreport.analysis_responses
'2',
'g/L',
146,
NOW()::timestamptz,
5,
true,
1,
false,
3,
'{"original_name": "Hgb", "value": 13.5}'::jsonb,
NOW(),
NOW(),
'Hematokrit'
);

View File

@@ -3,16 +3,18 @@
"compilerOptions": { "compilerOptions": {
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"@kit/ui/*": ["packages/ui/src/*"],
"@kit/ui": ["packages/ui/src/index.ts"],
"@lib/*": ["packages/features/medusa-storefront/src/lib/*"], "@lib/*": ["packages/features/medusa-storefront/src/lib/*"],
"@modules/*": ["packages/features/medusa-storefront/src/modules/*"], "@modules/*": ["packages/features/medusa-storefront/src/modules/*"],
"@styles/*": ["packages/features/medusa-storefront/src/styles/*"], "@styles/*": ["packages/features/medusa-storefront/src/styles/*"],
"types/*": ["packages/features/medusa-storefront/src/types/*"], "types/*": ["packages/features/medusa-storefront/src/types/*"],
"@/*": ["./*"],
"~/*": ["./app/*"],
"~/config/*": ["./config/*"], "~/config/*": ["./config/*"],
"~/components/*": ["./components/*"], "~/components/*": ["./components/*"],
"~/lib/*": ["./lib/*"], "~/lib/*": ["./lib/*"],
"~/medusa/*": ["./packages/features/medusa-storefront/src/*"] "~/medusa/*": ["./packages/features/medusa-storefront/src/*"],
"@/*": ["./*"],
"~/*": ["./app/*"]
}, },
"plugins": [ "plugins": [
{ {