Merge branch 'main' into B2B-95
This commit is contained in:
@@ -2,10 +2,7 @@ import Link from 'next/link';
|
||||
|
||||
import { ArrowRightIcon } from 'lucide-react';
|
||||
|
||||
import {
|
||||
CtaButton,
|
||||
Hero,
|
||||
} from '@kit/ui/marketing';
|
||||
import { CtaButton, Hero } from '@kit/ui/marketing';
|
||||
import { Trans } from '@kit/ui/trans';
|
||||
|
||||
import { withI18n } from '~/lib/i18n/with-i18n';
|
||||
@@ -25,7 +22,6 @@ function Home() {
|
||||
cta={<MainCallToActionButton />}
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
273
jobs/sync-analysis-groups.ts
Normal file
273
jobs/sync-analysis-groups.ts
Normal file
@@ -0,0 +1,273 @@
|
||||
import { createClient as createCustomClient } from '@supabase/supabase-js';
|
||||
import axios from 'axios';
|
||||
import { format } from 'date-fns';
|
||||
import { config } from 'dotenv';
|
||||
import { XMLParser } from 'fast-xml-parser';
|
||||
|
||||
function getLatestMessage(messages) {
|
||||
if (!messages?.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return messages.reduce((prev, current) =>
|
||||
Number(prev.messageId) > Number(current.messageId) ? prev : current,
|
||||
);
|
||||
}
|
||||
|
||||
export function toArray<T>(input?: T | T[] | null): T[] {
|
||||
if (!input) return [];
|
||||
return Array.isArray(input) ? input : [input];
|
||||
}
|
||||
|
||||
async function syncData() {
|
||||
if (process.env.NODE_ENV === 'local') {
|
||||
config({ path: `.env.${process.env.NODE_ENV}` });
|
||||
}
|
||||
|
||||
const baseUrl = process.env.MEDIPOST_URL!;
|
||||
const user = process.env.MEDIPOST_USER!;
|
||||
const password = process.env.MEDIPOST_PASSWORD!;
|
||||
const sender = process.env.MEDIPOST_MESSAGE_SENDER!;
|
||||
|
||||
if (!baseUrl || !user || !password || !sender) {
|
||||
throw new Error('Could not access all necessary environment variables');
|
||||
}
|
||||
|
||||
const supabase = createCustomClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY!,
|
||||
{
|
||||
auth: {
|
||||
persistSession: false,
|
||||
autoRefreshToken: false,
|
||||
detectSessionInUrl: false,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
try {
|
||||
// GET LATEST PUBLIC MESSAGE ID
|
||||
const { data: lastChecked } = await supabase
|
||||
.schema('audit')
|
||||
.from('sync_entries')
|
||||
.select('created_at')
|
||||
.eq('status', 'SUCCESS')
|
||||
.order('created_at')
|
||||
.limit(1);
|
||||
|
||||
const lastCheckedDate = lastChecked?.length
|
||||
? {
|
||||
LastChecked: format(lastChecked[0].created_at, 'yyyy-MM-dd HH:mm:ss'),
|
||||
}
|
||||
: {};
|
||||
|
||||
const { data } = await axios.get(baseUrl, {
|
||||
params: {
|
||||
Action: 'GetPublicMessageList',
|
||||
User: user,
|
||||
Password: password,
|
||||
Sender: sender,
|
||||
...lastCheckedDate,
|
||||
MessageType: 'Teenus',
|
||||
},
|
||||
});
|
||||
|
||||
if (data.code && data.code !== 0) {
|
||||
throw new Error('Failed to get public message list');
|
||||
}
|
||||
|
||||
if (!data.messages.length) {
|
||||
return supabase.schema('audit').from('sync_entries').insert({
|
||||
operation: 'ANALYSES_SYNC',
|
||||
comment: 'No new data received',
|
||||
status: 'SUCCESS',
|
||||
changed_by_role: 'service_role',
|
||||
});
|
||||
}
|
||||
|
||||
const latestMessage = getLatestMessage(data?.messages);
|
||||
|
||||
// GET PUBLIC MESSAGE WITH GIVEN ID
|
||||
|
||||
const { data: publicMessageData } = await axios.get(baseUrl, {
|
||||
params: {
|
||||
Action: 'GetPublicMessage',
|
||||
User: user,
|
||||
Password: password,
|
||||
MessageId: latestMessage.messageId,
|
||||
},
|
||||
headers: {
|
||||
Accept: 'application/xml',
|
||||
},
|
||||
});
|
||||
|
||||
const parser = new XMLParser({ ignoreAttributes: false });
|
||||
const parsed = parser.parse(publicMessageData);
|
||||
|
||||
if (parsed.ANSWER?.CODE && parsed.ANSWER?.CODE !== 0) {
|
||||
throw new Error(
|
||||
`Failed to get public message (id: ${latestMessage.messageId})`,
|
||||
);
|
||||
}
|
||||
|
||||
// SAVE PUBLIC MESSAGE DATA
|
||||
|
||||
const providers = toArray(parsed?.Saadetis?.Teenused.Teostaja);
|
||||
const analysisGroups = providers.flatMap((provider) =>
|
||||
toArray(provider.UuringuGrupp),
|
||||
);
|
||||
|
||||
if (!parsed || !analysisGroups.length) {
|
||||
return supabase.schema('audit').from('sync_entries').insert({
|
||||
operation: 'ANALYSES_SYNC',
|
||||
comment: 'No data received',
|
||||
status: 'FAIL',
|
||||
changed_by_role: 'service_role',
|
||||
});
|
||||
}
|
||||
|
||||
for (const analysisGroup of analysisGroups) {
|
||||
// SAVE ANALYSIS GROUP
|
||||
const { data: insertedAnalysisGroup, error } = await supabase
|
||||
.from('analysis_groups')
|
||||
.upsert(
|
||||
{
|
||||
original_id: analysisGroup.UuringuGruppId,
|
||||
name: analysisGroup.UuringuGruppNimi,
|
||||
order: analysisGroup.UuringuGruppJarjekord,
|
||||
},
|
||||
{ onConflict: 'original_id', ignoreDuplicates: false },
|
||||
)
|
||||
.select('id');
|
||||
|
||||
if (error || !insertedAnalysisGroup[0]?.id) {
|
||||
throw new Error(
|
||||
`Failed to insert analysis group (id: ${analysisGroup.UuringuGruppId}), error: ${error?.message}`,
|
||||
);
|
||||
}
|
||||
const analysisGroupId = insertedAnalysisGroup[0].id;
|
||||
|
||||
const analysisGroupCodes = toArray(analysisGroup.Kood);
|
||||
const codes = analysisGroupCodes.map((kood) => ({
|
||||
hk_code: kood.HkKood,
|
||||
hk_code_multiplier: kood.HkKoodiKordaja,
|
||||
coefficient: kood.Koefitsient,
|
||||
price: kood.Hind,
|
||||
analysis_group_id: analysisGroupId,
|
||||
analysis_element_id: null,
|
||||
analysis_id: null,
|
||||
}));
|
||||
|
||||
const analysisGroupItems = toArray(analysisGroup.Uuring);
|
||||
|
||||
for (const item of analysisGroupItems) {
|
||||
const analysisElement = item.UuringuElement;
|
||||
|
||||
const { data: insertedAnalysisElement, error } = await supabase
|
||||
.from('analysis_elements')
|
||||
.upsert(
|
||||
{
|
||||
analysis_id_oid: analysisElement.UuringIdOID,
|
||||
analysis_id_original: analysisElement.UuringId,
|
||||
tehik_short_loinc: analysisElement.TLyhend,
|
||||
tehik_loinc_name: analysisElement.KNimetus,
|
||||
analysis_name_lab: analysisElement.UuringNimi,
|
||||
order: analysisElement.Jarjekord,
|
||||
parent_analysis_group_id: analysisGroupId,
|
||||
material_groups: toArray(item.MaterjalideGrupp),
|
||||
},
|
||||
{ onConflict: 'analysis_id_original', ignoreDuplicates: false },
|
||||
)
|
||||
.select('id');
|
||||
|
||||
if (error || !insertedAnalysisElement[0]?.id) {
|
||||
throw new Error(
|
||||
`Failed to insert analysis element (id: ${analysisElement.UuringId}), error: ${error?.message}`,
|
||||
);
|
||||
}
|
||||
|
||||
const insertedAnalysisElementId = insertedAnalysisElement[0].id;
|
||||
|
||||
if (analysisElement.Kood) {
|
||||
const analysisElementCodes = toArray(analysisElement.Kood);
|
||||
codes.push(
|
||||
...analysisElementCodes.map((kood) => ({
|
||||
hk_code: kood.HkKood,
|
||||
hk_code_multiplier: kood.HkKoodiKordaja,
|
||||
coefficient: kood.Koefitsient,
|
||||
price: kood.Hind,
|
||||
analysis_group_id: null,
|
||||
analysis_element_id: insertedAnalysisElementId,
|
||||
analysis_id: null,
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
const analyses = analysisElement.UuringuElement;
|
||||
if (analyses?.length) {
|
||||
for (const analysis of analyses) {
|
||||
const { data: insertedAnalysis, error } = await supabase
|
||||
.from('analyses')
|
||||
.upsert(
|
||||
{
|
||||
analysis_id_oid: analysis.UuringIdOID,
|
||||
analysis_id_original: analysis.UuringId,
|
||||
tehik_short_loinc: analysis.TLyhend,
|
||||
tehik_loinc_name: analysis.KNimetus,
|
||||
analysis_name_lab: analysis.UuringNimi,
|
||||
order: analysis.Jarjekord,
|
||||
parent_analysis_element_id: insertedAnalysisElementId,
|
||||
},
|
||||
{ onConflict: 'analysis_id_original', ignoreDuplicates: false },
|
||||
)
|
||||
.select('id');
|
||||
|
||||
if (error || !insertedAnalysis[0]?.id) {
|
||||
throw new Error(
|
||||
`Failed to insert analysis (id: ${analysis.UuringId}) error: ${error?.message}`,
|
||||
);
|
||||
}
|
||||
|
||||
const insertedAnalysisId = insertedAnalysis[0].id;
|
||||
if (analysisElement.Kood) {
|
||||
const analysisCodes = toArray(analysis.Kood);
|
||||
|
||||
codes.push(
|
||||
...analysisCodes.map((kood) => ({
|
||||
hk_code: kood.HkKood,
|
||||
hk_code_multiplier: kood.HkKoodiKordaja,
|
||||
coefficient: kood.Koefitsient,
|
||||
price: kood.Hind,
|
||||
analysis_group_id: null,
|
||||
analysis_element_id: null,
|
||||
analysis_id: insertedAnalysisId,
|
||||
})),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await supabase.schema('audit').from('sync_entries').insert({
|
||||
operation: 'ANALYSES_SYNC',
|
||||
status: 'SUCCESS',
|
||||
changed_by_role: 'service_role',
|
||||
});
|
||||
} catch (e) {
|
||||
await supabase
|
||||
.schema('audit')
|
||||
.from('sync_entries')
|
||||
.insert({
|
||||
operation: 'ANALYSES_SYNC',
|
||||
status: 'FAIL',
|
||||
comment: JSON.stringify(e),
|
||||
changed_by_role: 'service_role',
|
||||
});
|
||||
throw new Error(
|
||||
`Failed to sync public message data, error: ${JSON.stringify(e)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
syncData();
|
||||
@@ -20,8 +20,10 @@ import {
|
||||
GetMessageListResponse,
|
||||
MaterjalideGrupp,
|
||||
MedipostAction,
|
||||
MedipostOrderResponse,
|
||||
MedipostPublicMessageResponse,
|
||||
Message,
|
||||
ResponseUuringuGrupp,
|
||||
UuringuGrupp,
|
||||
} from '@/lib/types/medipost';
|
||||
import { toArray } from '@/lib/utils';
|
||||
@@ -140,12 +142,14 @@ export async function getPrivateMessage(messageId: string) {
|
||||
},
|
||||
});
|
||||
|
||||
if (data.code && data.code !== 0) {
|
||||
const parser = new XMLParser({ ignoreAttributes: false });
|
||||
const parsed = parser.parse(data);
|
||||
|
||||
if (parsed.ANSWER?.CODE && parsed.ANSWER?.CODE !== 0) {
|
||||
throw new Error(`Failed to get private message (id: ${messageId})`);
|
||||
}
|
||||
|
||||
const parser = new XMLParser({ ignoreAttributes: false });
|
||||
return parser.parse(data);
|
||||
return parsed;
|
||||
}
|
||||
|
||||
export async function deletePrivateMessage(messageId: string) {
|
||||
@@ -175,8 +179,9 @@ export async function readPrivateMessageResponse() {
|
||||
privateMessage.messageId,
|
||||
);
|
||||
|
||||
if (privateMessageContent) {
|
||||
// to be implemented: map and save, only delete if successful
|
||||
const status = await syncPrivateMessage(privateMessageContent);
|
||||
|
||||
if (status === 'COMPLETED') {
|
||||
await deletePrivateMessage(privateMessage.messageId);
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -307,7 +312,6 @@ async function saveAnalysisGroup(
|
||||
.upsert(codes, { ignoreDuplicates: false });
|
||||
|
||||
if (codesError?.code) {
|
||||
console.error(codesError); // TODO remove this
|
||||
throw new Error(
|
||||
`Failed to insert codes (analysis group id: ${analysisGroup.UuringuGruppId})`,
|
||||
);
|
||||
@@ -514,3 +518,113 @@ function getLatestMessage(messages?: Message[]) {
|
||||
Number(prev.messageId) > Number(current.messageId) ? prev : current,
|
||||
);
|
||||
}
|
||||
|
||||
export async function syncPrivateMessage(
|
||||
parsedMessage?: MedipostOrderResponse,
|
||||
) {
|
||||
const supabase = createCustomClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY!,
|
||||
{
|
||||
auth: {
|
||||
persistSession: false,
|
||||
autoRefreshToken: false,
|
||||
detectSessionInUrl: false,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const response = parsedMessage?.Saadetis?.Vastus;
|
||||
|
||||
if (!response) {
|
||||
throw new Error(`Invalid data in private message response`);
|
||||
}
|
||||
|
||||
const status = response.TellimuseOlek;
|
||||
|
||||
const { data: analysisOrder, error: analysisOrderError } = await supabase
|
||||
.from('analysis_orders')
|
||||
.select('user_id')
|
||||
.eq('id', response.ValisTellimuseId);
|
||||
|
||||
if (analysisOrderError || !analysisOrder?.[0]?.user_id) {
|
||||
throw new Error(
|
||||
`Could not find analysis order with id ${response.ValisTellimuseId}`,
|
||||
);
|
||||
}
|
||||
|
||||
const { data: analysisResponse, error } = await supabase
|
||||
.from('analysis_responses')
|
||||
.upsert(
|
||||
{
|
||||
analysis_order_id: response.ValisTellimuseId,
|
||||
order_number: response.TellimuseNumber,
|
||||
order_status: AnalysisOrderStatus[status],
|
||||
user_id: analysisOrder[0].user_id,
|
||||
},
|
||||
{ onConflict: 'order_number', ignoreDuplicates: false },
|
||||
)
|
||||
.select('id');
|
||||
|
||||
if (error || !analysisResponse?.[0]?.id) {
|
||||
throw new Error(
|
||||
`Failed to insert or update analysis order response (external id: ${response?.TellimuseNumber})`,
|
||||
);
|
||||
}
|
||||
const analysisGroups = toArray(response.UuringuGrupp);
|
||||
|
||||
const responses: Omit<
|
||||
Tables<'analysis_response_elements'>,
|
||||
'id' | 'created_at' | 'updated_at'
|
||||
>[] = [];
|
||||
for (const analysisGroup of analysisGroups) {
|
||||
const groupItems = toArray(
|
||||
analysisGroup.Uuring as ResponseUuringuGrupp['Uuring'],
|
||||
);
|
||||
for (const item of groupItems) {
|
||||
const element = item.UuringuElement;
|
||||
const elementAnalysisResponses = toArray(element.UuringuVastus);
|
||||
|
||||
responses.push(
|
||||
...elementAnalysisResponses.map((response) => ({
|
||||
analysis_element_original_id: element.UuringId,
|
||||
analysis_response_id: analysisResponse[0]!.id,
|
||||
norm_lower: response.NormAlum?.['#text'] ?? null,
|
||||
norm_lower_included:
|
||||
response.NormAlum?.['@_kaasaarvatud'].toLowerCase() === 'jah',
|
||||
norm_status: response.NormiStaatus,
|
||||
norm_upper: response.NormYlem?.['#text'] ?? null,
|
||||
norm_upper_included:
|
||||
response.NormYlem?.['@_kaasaarvatud'].toLowerCase() === 'jah',
|
||||
response_time: response.VastuseAeg ?? null,
|
||||
response_value: response.VastuseVaartus,
|
||||
unit: element.Mootyhik ?? null,
|
||||
original_response_element: element,
|
||||
})),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const { error: deleteError } = await supabase
|
||||
.from('analysis_response_elements')
|
||||
.delete()
|
||||
.eq('analysis_response_id', analysisResponse[0].id);
|
||||
|
||||
if (deleteError) {
|
||||
throw new Error(
|
||||
`Failed to clean up response elements for response id ${analysisResponse[0].id}`,
|
||||
);
|
||||
}
|
||||
|
||||
const { error: elementInsertError } = await supabase
|
||||
.from('analysis_response_elements')
|
||||
.insert(responses);
|
||||
|
||||
if (elementInsertError) {
|
||||
throw new Error(
|
||||
`Failed to insert order response elements for response id ${analysisResponse[0].id}`,
|
||||
);
|
||||
}
|
||||
|
||||
return AnalysisOrderStatus[status];
|
||||
}
|
||||
|
||||
@@ -13,25 +13,25 @@ export type GetMessageListResponse = {
|
||||
};
|
||||
|
||||
export enum MedipostAction {
|
||||
GetPublicMessageList = "GetPublicMessageList",
|
||||
GetPublicMessage = "GetPublicMessage",
|
||||
SendPrivateMessage = "SendPrivateMessage",
|
||||
GetPrivateMessageList = "GetPrivateMessageList",
|
||||
GetPrivateMessage = "GetPrivateMessage",
|
||||
DeletePrivateMessage = "DeletePrivateMessage",
|
||||
GetPublicMessageList = 'GetPublicMessageList',
|
||||
GetPublicMessage = 'GetPublicMessage',
|
||||
SendPrivateMessage = 'SendPrivateMessage',
|
||||
GetPrivateMessageList = 'GetPrivateMessageList',
|
||||
GetPrivateMessage = 'GetPrivateMessage',
|
||||
DeletePrivateMessage = 'DeletePrivateMessage',
|
||||
}
|
||||
|
||||
export type VoimalikVaartus = {
|
||||
VaartusId: string;
|
||||
Vaartus: "jah" | "ei";
|
||||
Vaartus: 'jah' | 'ei';
|
||||
VaartusJarjekord: number;
|
||||
};
|
||||
|
||||
export type Sisendparameeter = {
|
||||
"@_VastuseTyyp"?: "ARV" | "VABATEKST" | "KODEERITUD" | "AJAHETK";
|
||||
"@_VastuseKoodistikuOID"?: string;
|
||||
"@_VastuseKoodistikuNimi"?: string;
|
||||
"@_URL"?: string;
|
||||
'@_VastuseTyyp'?: 'ARV' | 'VABATEKST' | 'KODEERITUD' | 'AJAHETK';
|
||||
'@_VastuseKoodistikuOID'?: string;
|
||||
'@_VastuseKoodistikuNimi'?: string;
|
||||
'@_URL'?: string;
|
||||
|
||||
UuringIdOID: string;
|
||||
UuringId: string;
|
||||
@@ -72,7 +72,7 @@ export type UuringuElement = {
|
||||
};
|
||||
|
||||
export type Uuring = {
|
||||
tellitav: "JAH" | "EI";
|
||||
tellitav: 'JAH' | 'EI';
|
||||
UuringuElement: UuringuElement; //1..1
|
||||
MaterjalideGrupp?: MaterjalideGrupp | MaterjalideGrupp[]; //0..n If this is not present, then the analysis can't be ordered.
|
||||
};
|
||||
@@ -97,13 +97,13 @@ export type Materjal = {
|
||||
MaterjaliTyyp: string;
|
||||
MaterjaliNimi: string;
|
||||
KonteineriOmadus: string;
|
||||
MaterjaliPaige: { Kohustuslik: "JAH" | "EI" }; //0..1
|
||||
MaterjaliPaige: { Kohustuslik: 'JAH' | 'EI' }; //0..1
|
||||
MaterjalJarjekord?: number; //0..1
|
||||
Konteiner?: Konteiner | Konteiner[]; //0..n
|
||||
};
|
||||
|
||||
export type MaterjalideGrupp = {
|
||||
vaikimisi: "JAH" | "EI";
|
||||
vaikimisi: 'JAH' | 'EI';
|
||||
Materjal: Materjal | Materjal[]; //1..n
|
||||
};
|
||||
|
||||
@@ -114,22 +114,22 @@ export type Teostaja = {
|
||||
AsutuseNimi: string;
|
||||
AsutuseKood: string;
|
||||
AllyksuseNimi: string;
|
||||
Telefon: string;
|
||||
Telefon: number;
|
||||
Aadress: string;
|
||||
};
|
||||
Sisendparameeter?: Sisendparameeter | Sisendparameeter[]; //0...n
|
||||
};
|
||||
|
||||
export type MedipostPublicMessageResponse = {
|
||||
"?xml": {
|
||||
"@_version": string;
|
||||
"@_encoding": "UTF-8";
|
||||
"@_standalone"?: "yes" | "no";
|
||||
'?xml': {
|
||||
'@_version': string;
|
||||
'@_encoding': string;
|
||||
'@_standalone'?: 'yes' | 'no';
|
||||
};
|
||||
ANSWER?: { CODE: number };
|
||||
Saadetis?: {
|
||||
Pais: {
|
||||
Pakett: { "#text": "SL" | "OL" | "AL" | "ME" }; // SL - Teenused, OL - Tellimus (meie poolt saadetav saatekiri), AL - Vastus (saatekirja vastus), ME - Teade
|
||||
Pakett: { '#text': 'SL' | 'OL' | 'AL' | 'ME' }; // SL - Teenused, OL - Tellimus (meie poolt saadetav saatekiri), AL - Vastus (saatekirja vastus), ME - Teade
|
||||
Saatja: string;
|
||||
Saaja: string;
|
||||
Aeg: string;
|
||||
@@ -141,11 +141,127 @@ export type MedipostPublicMessageResponse = {
|
||||
};
|
||||
};
|
||||
|
||||
export const AnalysisOrderStatus = {
|
||||
1: "QUEUED",
|
||||
2: "ON_HOLD",
|
||||
3: "PROCESSING",
|
||||
4: "COMPLETED",
|
||||
5: "REJECTED",
|
||||
6: "CANCELLED",
|
||||
} as const;
|
||||
export type UuringuVastus = {
|
||||
VastuseVaartus: number; // text according to docs, but based on examples and logically, float
|
||||
VastuseAeg: string;
|
||||
NormYlem?: {
|
||||
'#text': number;
|
||||
'@_kaasaarvatud': string;
|
||||
}; // 0..1
|
||||
NormAlum?: {
|
||||
'#text': number;
|
||||
'@_kaasaarvatud': string;
|
||||
};
|
||||
NormiStaatus: keyof typeof NormStatus;
|
||||
ProoviJarjenumber: number;
|
||||
};
|
||||
|
||||
export type ResponseUuring = {
|
||||
UuringuElement: {
|
||||
UuringIdOID: string;
|
||||
UuringId: string;
|
||||
TLyhend: string;
|
||||
KNimetus: string;
|
||||
UuringNimi: string;
|
||||
TellijaUuringId: number;
|
||||
TeostajaUuringId: string;
|
||||
UuringOlek: keyof typeof AnalysisOrderStatus;
|
||||
Mootyhik?: string; // 0..1
|
||||
Kood: {
|
||||
HkKood: number;
|
||||
HkKoodiKordaja: number;
|
||||
Koefitsient: number;
|
||||
Hind: number;
|
||||
};
|
||||
UuringuVastus?: UuringuVastus | UuringuVastus[]; // 0..n
|
||||
UuringuKommentaar?: string;
|
||||
}; // 1..1
|
||||
UuringuTaitjaAsutuseJnr: number;
|
||||
};
|
||||
|
||||
export type ResponseUuringuGrupp = {
|
||||
UuringuGruppId: string;
|
||||
UuringuGruppNimi: string;
|
||||
Uuring: ResponseUuring | ResponseUuring[]; // 1..n
|
||||
};
|
||||
|
||||
// type for UuringuGrupp is correct, but some of this is generated by an LLM and should be checked if data in use
|
||||
export type MedipostOrderResponse = {
|
||||
'?xml': {
|
||||
'@_version': string;
|
||||
'@_encoding': string;
|
||||
'@_standalone': 'yes' | 'no';
|
||||
};
|
||||
ANSWER?: { CODE: number };
|
||||
Saadetis: {
|
||||
Pais: {
|
||||
Pakett: {
|
||||
'#text': string;
|
||||
'@_versioon': string;
|
||||
};
|
||||
Saatja: string;
|
||||
Saaja: string;
|
||||
Aeg: string;
|
||||
SaadetisId: string;
|
||||
Email: string;
|
||||
};
|
||||
Vastus: {
|
||||
ValisTellimuseId: number;
|
||||
Asutus: {
|
||||
'@_tyyp': string; // TEOSTAJA
|
||||
'@_jarjenumber': string;
|
||||
AsutuseId: number;
|
||||
AsutuseNimi: string;
|
||||
AsutuseKood: string;
|
||||
AllyksuseNimi?: string;
|
||||
Telefon: number;
|
||||
}[]; //@_tyyp = TELLIJA 1..1, @_tyyp = TEOSTAJA 1..n
|
||||
Personal: {
|
||||
'@_tyyp': string;
|
||||
'@_jarjenumber': string;
|
||||
PersonalOID: string;
|
||||
PersonalKood: string;
|
||||
PersonalPerekonnaNimi: string;
|
||||
PersonalEesNimi: string;
|
||||
Telefon: number;
|
||||
};
|
||||
Patsient: {
|
||||
IsikukoodiOID: string;
|
||||
Isikukood: string;
|
||||
PerekonnaNimi: string;
|
||||
EesNimi: string;
|
||||
SynniAeg: string;
|
||||
SuguOID: string;
|
||||
Sugu: string;
|
||||
};
|
||||
Proov: Array<{
|
||||
ProovinouIdOID: string;
|
||||
ProovinouId: string;
|
||||
MaterjaliTyypOID: string;
|
||||
MaterjaliTyyp: number;
|
||||
MaterjaliNimi: string;
|
||||
Ribakood: string;
|
||||
Jarjenumber: number;
|
||||
VotmisAeg: string;
|
||||
SaabumisAeg: string;
|
||||
}>;
|
||||
TellimuseNumber: string;
|
||||
TellimuseOlek: keyof typeof AnalysisOrderStatus;
|
||||
UuringuGrupp?: ResponseUuringuGrupp | ResponseUuringuGrupp[];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export const AnalysisOrderStatus: Record<number, string> = {
|
||||
1: 'QUEUED',
|
||||
2: 'ON_HOLD',
|
||||
3: 'PROCESSING',
|
||||
4: 'COMPLETED',
|
||||
5: 'REJECTED',
|
||||
6: 'CANCELLED',
|
||||
};
|
||||
export const NormStatus: Record<number, string> = {
|
||||
1: 'NORMAL',
|
||||
2: 'WARNING',
|
||||
3: 'REQUIRES_ATTENTION',
|
||||
};
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
"supabase:typegen": "pnpm run supabase:typegen:packages && pnpm run supabase:typegen:app",
|
||||
"supabase:typegen:packages": "supabase gen types typescript --local > ../../packages/supabase/src/database.types.ts",
|
||||
"supabase:typegen:app": "supabase gen types typescript --local > ./lib/database.types.ts",
|
||||
"supabase:db:dump:local": "supabase db dump --local --data-only"
|
||||
"supabase:db:dump:local": "supabase db dump --local --data-only",
|
||||
"sync-data:dev": "NODE_ENV=local ts-node jobs/sync-analysis-groups.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@edge-csrf/nextjs": "2.5.3-cloudflare-rc1",
|
||||
@@ -76,6 +77,7 @@
|
||||
"recharts": "2.15.3",
|
||||
"sonner": "^2.0.3",
|
||||
"tailwind-merge": "^3.3.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"zod": "^3.24.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -85,10 +87,10 @@
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@next/bundle-analyzer": "15.3.2",
|
||||
"@tailwindcss/postcss": "^4.1.7",
|
||||
"@types/lodash": "^4.17.17",
|
||||
"@types/node": "^22.15.18",
|
||||
"@types/react": "19.1.4",
|
||||
"@types/react-dom": "19.1.5",
|
||||
"@types/lodash": "^4.17.17",
|
||||
"babel-plugin-react-compiler": "19.1.0-rc.2",
|
||||
"cssnano": "^7.0.7",
|
||||
"pino-pretty": "^13.0.0",
|
||||
@@ -98,7 +100,8 @@
|
||||
"tailwindcss": "4.1.7",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"typescript": "^5.8.3",
|
||||
"yup": "^1.6.1"
|
||||
"yup": "^1.6.1",
|
||||
"dotenv": "^16.5.0"
|
||||
},
|
||||
"prettier": "@kit/prettier-config",
|
||||
"browserslist": [
|
||||
|
||||
106
pnpm-lock.yaml
generated
106
pnpm-lock.yaml
generated
@@ -143,6 +143,9 @@ importers:
|
||||
tailwind-merge:
|
||||
specifier: ^3.3.0
|
||||
version: 3.3.0
|
||||
ts-node:
|
||||
specifier: ^10.9.2
|
||||
version: 10.9.2(@types/node@22.15.30)(typescript@5.8.3)
|
||||
zod:
|
||||
specifier: ^3.24.4
|
||||
version: 3.25.56
|
||||
@@ -180,6 +183,9 @@ importers:
|
||||
cssnano:
|
||||
specifier: ^7.0.7
|
||||
version: 7.0.7(postcss@8.5.4)
|
||||
dotenv:
|
||||
specifier: ^16.5.0
|
||||
version: 16.5.0
|
||||
pino-pretty:
|
||||
specifier: ^13.0.0
|
||||
version: 13.0.0
|
||||
@@ -1581,6 +1587,10 @@ packages:
|
||||
'@corex/deepmerge@4.0.43':
|
||||
resolution: {integrity: sha512-N8uEMrMPL0cu/bdboEWpQYb/0i2K5Qn8eCsxzOmxSggJbbQte7ljMRoXm917AbntqTGOzdTu+vP3KOOzoC70HQ==}
|
||||
|
||||
'@cspotcode/source-map-support@0.8.1':
|
||||
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
'@discoveryjs/json-ext@0.5.7':
|
||||
resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
@@ -1899,6 +1909,9 @@ packages:
|
||||
'@jridgewell/trace-mapping@0.3.25':
|
||||
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
|
||||
|
||||
'@jridgewell/trace-mapping@0.3.9':
|
||||
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
|
||||
|
||||
'@js-sdsl/ordered-map@4.4.2':
|
||||
resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==}
|
||||
|
||||
@@ -4168,6 +4181,18 @@ packages:
|
||||
peerDependencies:
|
||||
graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || 14 || 15 || 16
|
||||
|
||||
'@tsconfig/node10@1.0.11':
|
||||
resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==}
|
||||
|
||||
'@tsconfig/node12@1.0.11':
|
||||
resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==}
|
||||
|
||||
'@tsconfig/node14@1.0.3':
|
||||
resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==}
|
||||
|
||||
'@tsconfig/node16@1.0.4':
|
||||
resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
|
||||
|
||||
'@tybys/wasm-util@0.9.0':
|
||||
resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==}
|
||||
|
||||
@@ -4620,6 +4645,9 @@ packages:
|
||||
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
arg@4.1.3:
|
||||
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
|
||||
|
||||
argparse@2.0.1:
|
||||
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
||||
|
||||
@@ -4876,6 +4904,9 @@ packages:
|
||||
resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
create-require@1.1.1:
|
||||
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
|
||||
|
||||
cross-spawn@7.0.6:
|
||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||
engines: {node: '>= 8'}
|
||||
@@ -5062,6 +5093,10 @@ packages:
|
||||
devlop@1.1.0:
|
||||
resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
|
||||
|
||||
diff@4.0.2:
|
||||
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
|
||||
engines: {node: '>=0.3.1'}
|
||||
|
||||
direction@1.0.4:
|
||||
resolution: {integrity: sha512-GYqKi1aH7PJXxdhTeZBFrg8vUBeKXi+cNprXsC1kpJcbcVnV9wBsrOu1cQEdG0WeQwlfHiy3XvnKfIrJ2R0NzQ==}
|
||||
hasBin: true
|
||||
@@ -6017,6 +6052,9 @@ packages:
|
||||
resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
make-error@1.3.6:
|
||||
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
|
||||
|
||||
markdown-table@3.0.4:
|
||||
resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}
|
||||
|
||||
@@ -7331,6 +7369,20 @@ packages:
|
||||
ts-case-convert@2.1.0:
|
||||
resolution: {integrity: sha512-Ye79el/pHYXfoew6kqhMwCoxp4NWjKNcm2kBzpmEMIU9dd9aBmHNNFtZ+WTm0rz1ngyDmfqDXDlyUnBXayiD0w==}
|
||||
|
||||
ts-node@10.9.2:
|
||||
resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@swc/core': '>=1.2.50'
|
||||
'@swc/wasm': '>=1.2.50'
|
||||
'@types/node': '*'
|
||||
typescript: '>=2.7'
|
||||
peerDependenciesMeta:
|
||||
'@swc/core':
|
||||
optional: true
|
||||
'@swc/wasm':
|
||||
optional: true
|
||||
|
||||
tsconfig-paths@3.15.0:
|
||||
resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
|
||||
|
||||
@@ -7490,6 +7542,9 @@ packages:
|
||||
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
|
||||
hasBin: true
|
||||
|
||||
v8-compile-cache-lib@3.0.1:
|
||||
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
|
||||
|
||||
vfile-message@4.0.2:
|
||||
resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==}
|
||||
|
||||
@@ -7660,6 +7715,10 @@ packages:
|
||||
resolution: {integrity: sha512-OIDwaflOaq4wC6YlPBy2L6ceKeKuF7DeTxx+jPzv1FHn9tCZ0ZwSRnUBxD05E3yed46fv/FWJbvR+Ud7x0L7zw==}
|
||||
engines: {node: '>=16.0.0', npm: '>=8.0.0'}
|
||||
|
||||
yn@3.1.1:
|
||||
resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
yocto-queue@0.1.0:
|
||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -7816,6 +7875,10 @@ snapshots:
|
||||
|
||||
'@corex/deepmerge@4.0.43': {}
|
||||
|
||||
'@cspotcode/source-map-support@0.8.1':
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.9
|
||||
|
||||
'@discoveryjs/json-ext@0.5.7': {}
|
||||
|
||||
'@edge-csrf/nextjs@2.5.3-cloudflare-rc1(next@15.3.2(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))':
|
||||
@@ -8147,6 +8210,11 @@ snapshots:
|
||||
'@jridgewell/resolve-uri': 3.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
|
||||
'@jridgewell/trace-mapping@0.3.9':
|
||||
dependencies:
|
||||
'@jridgewell/resolve-uri': 3.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
|
||||
'@js-sdsl/ordered-map@4.4.2': {}
|
||||
|
||||
'@juggle/resize-observer@3.4.0': {}
|
||||
@@ -11071,6 +11139,14 @@ snapshots:
|
||||
graphql: 16.11.0
|
||||
graphql-tag: 2.12.6(graphql@16.11.0)
|
||||
|
||||
'@tsconfig/node10@1.0.11': {}
|
||||
|
||||
'@tsconfig/node12@1.0.11': {}
|
||||
|
||||
'@tsconfig/node14@1.0.3': {}
|
||||
|
||||
'@tsconfig/node16@1.0.4': {}
|
||||
|
||||
'@tybys/wasm-util@0.9.0':
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
@@ -11593,6 +11669,8 @@ snapshots:
|
||||
normalize-path: 3.0.0
|
||||
picomatch: 2.3.1
|
||||
|
||||
arg@4.1.3: {}
|
||||
|
||||
argparse@2.0.1: {}
|
||||
|
||||
aria-hidden@1.2.6:
|
||||
@@ -11888,6 +11966,8 @@ snapshots:
|
||||
path-type: 4.0.0
|
||||
yaml: 1.10.2
|
||||
|
||||
create-require@1.1.1: {}
|
||||
|
||||
cross-spawn@7.0.6:
|
||||
dependencies:
|
||||
path-key: 3.1.1
|
||||
@@ -12080,6 +12160,8 @@ snapshots:
|
||||
dependencies:
|
||||
dequal: 2.0.3
|
||||
|
||||
diff@4.0.2: {}
|
||||
|
||||
direction@1.0.4: {}
|
||||
|
||||
doctrine@2.1.0:
|
||||
@@ -13123,6 +13205,8 @@ snapshots:
|
||||
dependencies:
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
|
||||
make-error@1.3.6: {}
|
||||
|
||||
markdown-table@3.0.4: {}
|
||||
|
||||
marked@7.0.4: {}
|
||||
@@ -14689,6 +14773,24 @@ snapshots:
|
||||
|
||||
ts-case-convert@2.1.0: {}
|
||||
|
||||
ts-node@10.9.2(@types/node@22.15.30)(typescript@5.8.3):
|
||||
dependencies:
|
||||
'@cspotcode/source-map-support': 0.8.1
|
||||
'@tsconfig/node10': 1.0.11
|
||||
'@tsconfig/node12': 1.0.11
|
||||
'@tsconfig/node14': 1.0.3
|
||||
'@tsconfig/node16': 1.0.4
|
||||
'@types/node': 22.15.30
|
||||
acorn: 8.14.1
|
||||
acorn-walk: 8.3.4
|
||||
arg: 4.1.3
|
||||
create-require: 1.1.1
|
||||
diff: 4.0.2
|
||||
make-error: 1.3.6
|
||||
typescript: 5.8.3
|
||||
v8-compile-cache-lib: 3.0.1
|
||||
yn: 3.1.1
|
||||
|
||||
tsconfig-paths@3.15.0:
|
||||
dependencies:
|
||||
'@types/json5': 0.0.29
|
||||
@@ -14880,6 +14982,8 @@ snapshots:
|
||||
|
||||
uuid@9.0.1: {}
|
||||
|
||||
v8-compile-cache-lib@3.0.1: {}
|
||||
|
||||
vfile-message@4.0.2:
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
@@ -15090,6 +15194,8 @@ snapshots:
|
||||
dependencies:
|
||||
lib0: 0.2.108
|
||||
|
||||
yn@3.1.1: {}
|
||||
|
||||
yocto-queue@0.1.0: {}
|
||||
|
||||
yup@1.6.1:
|
||||
|
||||
@@ -346,28 +346,128 @@ export type Database = {
|
||||
}
|
||||
analysis_orders: {
|
||||
Row: {
|
||||
analysis_group_ids: number[] | null
|
||||
analysis_element_ids: number[] | null
|
||||
analysis_ids: number[] | null
|
||||
created_at: string
|
||||
id: string
|
||||
id: number
|
||||
status: Database["public"]["Enums"]["analysis_order_status"]
|
||||
user_id: string
|
||||
}
|
||||
Insert: {
|
||||
analysis_group_ids?: number[] | null
|
||||
analysis_element_ids?: number[] | null
|
||||
analysis_ids?: number[] | null
|
||||
created_at?: string
|
||||
id: string
|
||||
id?: number
|
||||
status: Database["public"]["Enums"]["analysis_order_status"]
|
||||
user_id: string
|
||||
}
|
||||
Update: {
|
||||
analysis_group_ids?: number[] | null
|
||||
analysis_element_ids?: number[] | null
|
||||
analysis_ids?: number[] | null
|
||||
created_at?: string
|
||||
id?: string
|
||||
id?: number
|
||||
status?: Database["public"]["Enums"]["analysis_order_status"]
|
||||
user_id?: string
|
||||
}
|
||||
Relationships: []
|
||||
}
|
||||
analysis_response_elements: {
|
||||
Row: {
|
||||
analysis_element_original_id: string
|
||||
analysis_response_id: number
|
||||
created_at: string
|
||||
id: number
|
||||
norm_lower: number | null
|
||||
norm_lower_included: boolean | null
|
||||
norm_status: number | null
|
||||
norm_upper: number | null
|
||||
norm_upper_included: boolean | null
|
||||
original_response_element: Json
|
||||
response_time: string
|
||||
response_value: Json
|
||||
unit: string | null
|
||||
updated_at: string | null
|
||||
}
|
||||
Insert: {
|
||||
analysis_element_original_id: string
|
||||
analysis_response_id: number
|
||||
created_at?: string
|
||||
id?: number
|
||||
norm_lower?: number | null
|
||||
norm_lower_included?: boolean | null
|
||||
norm_status?: number | null
|
||||
norm_upper?: number | null
|
||||
norm_upper_included?: boolean | null
|
||||
original_response_element: Json
|
||||
response_time: string
|
||||
response_value: Json
|
||||
unit?: string | null
|
||||
updated_at?: string | null
|
||||
}
|
||||
Update: {
|
||||
analysis_element_original_id?: string
|
||||
analysis_response_id?: number
|
||||
created_at?: string
|
||||
id?: number
|
||||
norm_lower?: number | null
|
||||
norm_lower_included?: boolean | null
|
||||
norm_status?: number | null
|
||||
norm_upper?: number | null
|
||||
norm_upper_included?: boolean | null
|
||||
original_response_element?: Json
|
||||
response_time?: string
|
||||
response_value?: Json
|
||||
unit?: string | null
|
||||
updated_at?: string | null
|
||||
}
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "analysis_response_element_analysis_response_id_fkey"
|
||||
columns: ["analysis_response_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "analysis_responses"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
]
|
||||
}
|
||||
analysis_responses: {
|
||||
Row: {
|
||||
analysis_order_id: number
|
||||
created_at: string
|
||||
id: number
|
||||
order_number: string
|
||||
order_status: Database["public"]["Enums"]["analysis_order_status"]
|
||||
updated_at: string | null
|
||||
user_id: string
|
||||
}
|
||||
Insert: {
|
||||
analysis_order_id: number
|
||||
created_at?: string
|
||||
id?: number
|
||||
order_number: string
|
||||
order_status: Database["public"]["Enums"]["analysis_order_status"]
|
||||
updated_at?: string | null
|
||||
user_id: string
|
||||
}
|
||||
Update: {
|
||||
analysis_order_id?: number
|
||||
created_at?: string
|
||||
id?: number
|
||||
order_number?: string
|
||||
order_status?: Database["public"]["Enums"]["analysis_order_status"]
|
||||
updated_at?: string | null
|
||||
user_id?: string
|
||||
}
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "analysis_responses_analysis_order_id_fkey"
|
||||
columns: ["analysis_order_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "analysis_orders"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
]
|
||||
}
|
||||
billing_customers: {
|
||||
Row: {
|
||||
account_id: string
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
create table "public"."analysis_response_elements" (
|
||||
"id" bigint generated by default as identity not null,
|
||||
"analysis_response_id" bigint not null,
|
||||
"analysis_element_original_id" text not null,
|
||||
"unit" text,
|
||||
"response_value" jsonb not null,
|
||||
"response_time" timestamp with time zone not null,
|
||||
"norm_upper" double precision,
|
||||
"norm_upper_included" boolean,
|
||||
"norm_lower" double precision,
|
||||
"norm_lower_included" boolean,
|
||||
"norm_status" smallint,
|
||||
"original_response_element" jsonb not null,
|
||||
"created_at" timestamp with time zone not null default now(),
|
||||
"updated_at" timestamp with time zone default now()
|
||||
);
|
||||
|
||||
|
||||
alter table "public"."analysis_response_elements" enable row level security;
|
||||
|
||||
create table "public"."analysis_responses" (
|
||||
"id" bigint generated by default as identity not null,
|
||||
"analysis_order_id" bigint not null,
|
||||
"order_number" text not null,
|
||||
"order_status" analysis_order_status not null,
|
||||
"user_id" uuid not null,
|
||||
"created_at" timestamp with time zone not null default now(),
|
||||
"updated_at" timestamp with time zone default now()
|
||||
);
|
||||
|
||||
alter table "public"."analysis_responses" enable row level security;
|
||||
|
||||
CREATE UNIQUE INDEX analysis_response_element_pkey ON public.analysis_response_elements USING btree (id);
|
||||
|
||||
CREATE UNIQUE INDEX analysis_response_pkey ON public.analysis_responses USING btree (id);
|
||||
|
||||
CREATE UNIQUE INDEX analysis_responses_order_number_key ON public.analysis_responses USING btree (order_number);
|
||||
|
||||
alter table "public"."analysis_response_elements" add constraint "analysis_response_element_pkey" PRIMARY KEY using index "analysis_response_element_pkey";
|
||||
|
||||
alter table "public"."analysis_responses" add constraint "analysis_response_pkey" PRIMARY KEY using index "analysis_response_pkey";
|
||||
|
||||
alter table "public"."analysis_response_elements" add constraint "analysis_response_element_analysis_response_id_fkey" FOREIGN KEY (analysis_response_id) REFERENCES analysis_responses(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
|
||||
|
||||
alter table "public"."analysis_response_elements" validate constraint "analysis_response_element_analysis_response_id_fkey";
|
||||
|
||||
alter table "public"."analysis_responses" add constraint "analysis_response_user_id_fkey" FOREIGN KEY (user_id) REFERENCES auth.users(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
|
||||
|
||||
alter table "public"."analysis_responses" validate constraint "analysis_response_user_id_fkey";
|
||||
|
||||
alter table "public"."analysis_responses" add constraint "analysis_responses_order_number_key" UNIQUE using index "analysis_responses_order_number_key";
|
||||
|
||||
grant delete on table "public"."analysis_response_elements" to "service_role";
|
||||
|
||||
grant insert on table "public"."analysis_response_elements" to "service_role";
|
||||
|
||||
grant references on table "public"."analysis_response_elements" to "service_role";
|
||||
|
||||
grant select on table "public"."analysis_response_elements" to "service_role";
|
||||
|
||||
grant trigger on table "public"."analysis_response_elements" to "service_role";
|
||||
|
||||
grant truncate on table "public"."analysis_response_elements" to "service_role";
|
||||
|
||||
grant update on table "public"."analysis_response_elements" to "service_role";
|
||||
|
||||
grant delete on table "public"."analysis_responses" to "service_role";
|
||||
|
||||
grant insert on table "public"."analysis_responses" to "service_role";
|
||||
|
||||
grant references on table "public"."analysis_responses" to "service_role";
|
||||
|
||||
grant select on table "public"."analysis_responses" to "service_role";
|
||||
|
||||
grant trigger on table "public"."analysis_responses" to "service_role";
|
||||
|
||||
grant truncate on table "public"."analysis_responses" to "service_role";
|
||||
|
||||
grant update on table "public"."analysis_responses" to "service_role";
|
||||
|
||||
create policy "select_own"
|
||||
on "public"."analysis_response_elements"
|
||||
as permissive
|
||||
for select
|
||||
to authenticated
|
||||
using ((( SELECT auth.uid() AS uid) IN ( SELECT analysis_responses.user_id
|
||||
FROM analysis_responses
|
||||
WHERE (analysis_responses.id = analysis_response_elements.analysis_response_id))));
|
||||
|
||||
|
||||
create policy "service_role_all"
|
||||
on "public"."analysis_response_elements"
|
||||
as permissive
|
||||
for all
|
||||
to service_role
|
||||
using (true);
|
||||
|
||||
|
||||
create policy "select_own"
|
||||
on "public"."analysis_responses"
|
||||
as permissive
|
||||
for select
|
||||
to authenticated
|
||||
using ((( SELECT auth.uid() AS uid) = user_id));
|
||||
|
||||
|
||||
create policy "service_role_all"
|
||||
on "public"."analysis_responses"
|
||||
as permissive
|
||||
for all
|
||||
to service_role
|
||||
using (true);
|
||||
|
||||
create policy "service_role_all"
|
||||
on "public"."analysis_orders"
|
||||
as permissive
|
||||
for all
|
||||
to service_role
|
||||
using (true);
|
||||
|
||||
|
||||
alter table "public"."analysis_orders" add constraint "analysis_orders_user_id_fkey" FOREIGN KEY (user_id) REFERENCES auth.users(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
|
||||
alter table "public"."analysis_orders" drop constraint "analysis_orders_id_fkey";
|
||||
alter table "public"."analysis_orders" drop column "id";
|
||||
alter table "public"."analysis_orders" add "id" bigint generated by default as identity not null;
|
||||
CREATE UNIQUE INDEX analysis_orders_pkey ON public.analysis_orders USING btree (id);
|
||||
alter table "public"."analysis_orders" add constraint "analysis_orders_pkey" PRIMARY KEY using index "analysis_orders_pkey";
|
||||
alter table "public"."analysis_responses" add constraint "analysis_responses_analysis_order_id_fkey" FOREIGN KEY (analysis_order_id) REFERENCES analysis_orders(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
|
||||
alter table "public"."analysis_responses" validate constraint "analysis_responses_analysis_order_id_fkey";
|
||||
Reference in New Issue
Block a user