B2B-86: add function to save order response (#11)
* fix import * B2B-86: add function to save order response * fix private message parsing * generate new types * clean up * remove comment --------- Co-authored-by: Helena <helena@Helenas-MacBook-Pro.local>
This commit is contained in:
@@ -1,15 +1,12 @@
|
|||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
|
||||||
|
import { MedReportTitle } from '@/components/med-report-title';
|
||||||
import { ArrowRightIcon } from 'lucide-react';
|
import { ArrowRightIcon } from 'lucide-react';
|
||||||
|
|
||||||
import {
|
import { CtaButton, Hero } from '@kit/ui/marketing';
|
||||||
CtaButton,
|
|
||||||
Hero,
|
|
||||||
} from '@kit/ui/marketing';
|
|
||||||
import { Trans } from '@kit/ui/trans';
|
import { Trans } from '@kit/ui/trans';
|
||||||
|
|
||||||
import { withI18n } from '~/lib/i18n/with-i18n';
|
import { withI18n } from '~/lib/i18n/with-i18n';
|
||||||
import { MedReportTitle } from '@/components/MedReportTitle';
|
|
||||||
|
|
||||||
function Home() {
|
function Home() {
|
||||||
return (
|
return (
|
||||||
@@ -25,7 +22,6 @@ function Home() {
|
|||||||
cta={<MainCallToActionButton />}
|
cta={<MainCallToActionButton />}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,10 @@ import {
|
|||||||
GetMessageListResponse,
|
GetMessageListResponse,
|
||||||
MaterjalideGrupp,
|
MaterjalideGrupp,
|
||||||
MedipostAction,
|
MedipostAction,
|
||||||
|
MedipostOrderResponse,
|
||||||
MedipostPublicMessageResponse,
|
MedipostPublicMessageResponse,
|
||||||
Message,
|
Message,
|
||||||
|
ResponseUuringuGrupp,
|
||||||
UuringuGrupp,
|
UuringuGrupp,
|
||||||
} from '@/lib/types/medipost';
|
} from '@/lib/types/medipost';
|
||||||
import { toArray } from '@/lib/utils';
|
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})`);
|
throw new Error(`Failed to get private message (id: ${messageId})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const parser = new XMLParser({ ignoreAttributes: false });
|
return parsed;
|
||||||
return parser.parse(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deletePrivateMessage(messageId: string) {
|
export async function deletePrivateMessage(messageId: string) {
|
||||||
@@ -175,8 +179,9 @@ export async function readPrivateMessageResponse() {
|
|||||||
privateMessage.messageId,
|
privateMessage.messageId,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (privateMessageContent) {
|
const status = await syncPrivateMessage(privateMessageContent);
|
||||||
// to be implemented: map and save, only delete if successful
|
|
||||||
|
if (status === 'COMPLETED') {
|
||||||
await deletePrivateMessage(privateMessage.messageId);
|
await deletePrivateMessage(privateMessage.messageId);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -307,7 +312,6 @@ async function saveAnalysisGroup(
|
|||||||
.upsert(codes, { ignoreDuplicates: false });
|
.upsert(codes, { ignoreDuplicates: false });
|
||||||
|
|
||||||
if (codesError?.code) {
|
if (codesError?.code) {
|
||||||
console.error(codesError); // TODO remove this
|
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Failed to insert codes (analysis group id: ${analysisGroup.UuringuGruppId})`,
|
`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,
|
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 {
|
export enum MedipostAction {
|
||||||
GetPublicMessageList = "GetPublicMessageList",
|
GetPublicMessageList = 'GetPublicMessageList',
|
||||||
GetPublicMessage = "GetPublicMessage",
|
GetPublicMessage = 'GetPublicMessage',
|
||||||
SendPrivateMessage = "SendPrivateMessage",
|
SendPrivateMessage = 'SendPrivateMessage',
|
||||||
GetPrivateMessageList = "GetPrivateMessageList",
|
GetPrivateMessageList = 'GetPrivateMessageList',
|
||||||
GetPrivateMessage = "GetPrivateMessage",
|
GetPrivateMessage = 'GetPrivateMessage',
|
||||||
DeletePrivateMessage = "DeletePrivateMessage",
|
DeletePrivateMessage = 'DeletePrivateMessage',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type VoimalikVaartus = {
|
export type VoimalikVaartus = {
|
||||||
VaartusId: string;
|
VaartusId: string;
|
||||||
Vaartus: "jah" | "ei";
|
Vaartus: 'jah' | 'ei';
|
||||||
VaartusJarjekord: number;
|
VaartusJarjekord: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Sisendparameeter = {
|
export type Sisendparameeter = {
|
||||||
"@_VastuseTyyp"?: "ARV" | "VABATEKST" | "KODEERITUD" | "AJAHETK";
|
'@_VastuseTyyp'?: 'ARV' | 'VABATEKST' | 'KODEERITUD' | 'AJAHETK';
|
||||||
"@_VastuseKoodistikuOID"?: string;
|
'@_VastuseKoodistikuOID'?: string;
|
||||||
"@_VastuseKoodistikuNimi"?: string;
|
'@_VastuseKoodistikuNimi'?: string;
|
||||||
"@_URL"?: string;
|
'@_URL'?: string;
|
||||||
|
|
||||||
UuringIdOID: string;
|
UuringIdOID: string;
|
||||||
UuringId: string;
|
UuringId: string;
|
||||||
@@ -72,7 +72,7 @@ export type UuringuElement = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type Uuring = {
|
export type Uuring = {
|
||||||
tellitav: "JAH" | "EI";
|
tellitav: 'JAH' | 'EI';
|
||||||
UuringuElement: UuringuElement; //1..1
|
UuringuElement: UuringuElement; //1..1
|
||||||
MaterjalideGrupp?: MaterjalideGrupp | MaterjalideGrupp[]; //0..n If this is not present, then the analysis can't be ordered.
|
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;
|
MaterjaliTyyp: string;
|
||||||
MaterjaliNimi: string;
|
MaterjaliNimi: string;
|
||||||
KonteineriOmadus: string;
|
KonteineriOmadus: string;
|
||||||
MaterjaliPaige: { Kohustuslik: "JAH" | "EI" }; //0..1
|
MaterjaliPaige: { Kohustuslik: 'JAH' | 'EI' }; //0..1
|
||||||
MaterjalJarjekord?: number; //0..1
|
MaterjalJarjekord?: number; //0..1
|
||||||
Konteiner?: Konteiner | Konteiner[]; //0..n
|
Konteiner?: Konteiner | Konteiner[]; //0..n
|
||||||
};
|
};
|
||||||
|
|
||||||
export type MaterjalideGrupp = {
|
export type MaterjalideGrupp = {
|
||||||
vaikimisi: "JAH" | "EI";
|
vaikimisi: 'JAH' | 'EI';
|
||||||
Materjal: Materjal | Materjal[]; //1..n
|
Materjal: Materjal | Materjal[]; //1..n
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,22 +114,22 @@ export type Teostaja = {
|
|||||||
AsutuseNimi: string;
|
AsutuseNimi: string;
|
||||||
AsutuseKood: string;
|
AsutuseKood: string;
|
||||||
AllyksuseNimi: string;
|
AllyksuseNimi: string;
|
||||||
Telefon: string;
|
Telefon: number;
|
||||||
Aadress: string;
|
Aadress: string;
|
||||||
};
|
};
|
||||||
Sisendparameeter?: Sisendparameeter | Sisendparameeter[]; //0...n
|
Sisendparameeter?: Sisendparameeter | Sisendparameeter[]; //0...n
|
||||||
};
|
};
|
||||||
|
|
||||||
export type MedipostPublicMessageResponse = {
|
export type MedipostPublicMessageResponse = {
|
||||||
"?xml": {
|
'?xml': {
|
||||||
"@_version": string;
|
'@_version': string;
|
||||||
"@_encoding": "UTF-8";
|
'@_encoding': string;
|
||||||
"@_standalone"?: "yes" | "no";
|
'@_standalone'?: 'yes' | 'no';
|
||||||
};
|
};
|
||||||
ANSWER?: { CODE: number };
|
ANSWER?: { CODE: number };
|
||||||
Saadetis?: {
|
Saadetis?: {
|
||||||
Pais: {
|
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;
|
Saatja: string;
|
||||||
Saaja: string;
|
Saaja: string;
|
||||||
Aeg: string;
|
Aeg: string;
|
||||||
@@ -141,11 +141,127 @@ export type MedipostPublicMessageResponse = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AnalysisOrderStatus = {
|
export type UuringuVastus = {
|
||||||
1: "QUEUED",
|
VastuseVaartus: number; // text according to docs, but based on examples and logically, float
|
||||||
2: "ON_HOLD",
|
VastuseAeg: string;
|
||||||
3: "PROCESSING",
|
NormYlem?: {
|
||||||
4: "COMPLETED",
|
'#text': number;
|
||||||
5: "REJECTED",
|
'@_kaasaarvatud': string;
|
||||||
6: "CANCELLED",
|
}; // 0..1
|
||||||
} as const;
|
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',
|
||||||
|
};
|
||||||
|
|||||||
@@ -346,28 +346,128 @@ export type Database = {
|
|||||||
}
|
}
|
||||||
analysis_orders: {
|
analysis_orders: {
|
||||||
Row: {
|
Row: {
|
||||||
analysis_group_ids: number[] | null
|
analysis_element_ids: number[] | null
|
||||||
|
analysis_ids: number[] | null
|
||||||
created_at: string
|
created_at: string
|
||||||
id: string
|
id: number
|
||||||
status: Database["public"]["Enums"]["analysis_order_status"]
|
status: Database["public"]["Enums"]["analysis_order_status"]
|
||||||
user_id: string
|
user_id: string
|
||||||
}
|
}
|
||||||
Insert: {
|
Insert: {
|
||||||
analysis_group_ids?: number[] | null
|
analysis_element_ids?: number[] | null
|
||||||
|
analysis_ids?: number[] | null
|
||||||
created_at?: string
|
created_at?: string
|
||||||
id: string
|
id?: number
|
||||||
status: Database["public"]["Enums"]["analysis_order_status"]
|
status: Database["public"]["Enums"]["analysis_order_status"]
|
||||||
user_id: string
|
user_id: string
|
||||||
}
|
}
|
||||||
Update: {
|
Update: {
|
||||||
analysis_group_ids?: number[] | null
|
analysis_element_ids?: number[] | null
|
||||||
|
analysis_ids?: number[] | null
|
||||||
created_at?: string
|
created_at?: string
|
||||||
id?: string
|
id?: number
|
||||||
status?: Database["public"]["Enums"]["analysis_order_status"]
|
status?: Database["public"]["Enums"]["analysis_order_status"]
|
||||||
user_id?: string
|
user_id?: string
|
||||||
}
|
}
|
||||||
Relationships: []
|
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: {
|
billing_customers: {
|
||||||
Row: {
|
Row: {
|
||||||
account_id: string
|
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