/** 
 * <feature scope="SanteDB.Persistence.Data.ADO" id="00010000-00" name="Initialize:001-01" invariantName="npgsql">
 *	<summary>Installs the core schema for SanteDB</summary>
 *	<remarks>This script installs the necessary core schema files for SanteDB</remarks>
 *  <isInstalled mustSucceed="true">SELECT to_regclass('public.sec_usr_tbl') IS NOT NULL;</isInstalled>
 * </feature>
 */
-- CREATE EXTENSIONS
CREATE EXTENSION IF NOT EXISTS PGCRYPTO;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";


-- SECURITY USER CLASS CODES. THESE ARE USED TO IDENTIFY THE USER CLASSES AND ARE USED
-- TO DIFFERENTIATE THE CLASSES OF USERS
CREATE TABLE SEC_USR_CLS_CDTBL (
    CLS_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
    MNEMONIC VARCHAR(32) NOT NULL,
    CONSTRAINT PK_SEC_USR_CLS_CDTBL PRIMARY KEY (CLS_ID)
);

INSERT INTO SEC_USR_CLS_CDTBL (CLS_ID, MNEMONIC) VALUES ('33932B42-6F4B-4659-8849-6ACA54139D8E','HumanUser');
INSERT INTO SEC_USR_CLS_CDTBL (CLS_ID, MNEMONIC) VALUES ('E9CD4DAD-2759-4022-AB07-92FCFB236A98','ApplicationUser');
INSERT INTO SEC_USR_CLS_CDTBL (CLS_ID, MNEMONIC) VALUES ('9F71BB34-9691-440F-8249-9C831EA16D58','SystemUser');


-- SECURITY PROVENANCE TABLE
-- THIS TABLE IS USED TO RECORD THE PROVENANCE OF AN OBJECT AT THE TIME OF CREATION / UPDATION / ETC.
CREATE TABLE SEC_PROV_TBL (
	PROV_ID UUID NOT NULL DEFAULT uuid_generate_v1(), -- THE ID OF THE PROVENANCE EVENT
	USR_ID UUID, -- THE USER IDENTITY OF THE EVENT
	DEV_ID UUID, -- THE DEVICE ID OF THE EVENT
	APP_ID UUID NOT NULL, -- THE APPLICATION THE USER OR DEVICE WAS USING
	SES_ID UUID, -- THE SESSION OF THE EVENT IF APPLICABLE - NB THE SESSION MECHANISM MAY NOT BE IN THIS DATABASE SO THERE IS NO FK TO THE SESSION IDENTIFIER
	EST_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE TIMESTAMP WHEN THE TRANSACTION BEGAN ON THE SERVER (REGARDLESS OF WHEN THE DEVICE SAID THE CREATION TIME WAS)
	EXT_ID UUID,
	EXT_TYP CHAR(1) CHECK (EXT_TYP IN ('U','P')),
	CONSTRAINT PK_SEC_PROV_TBL PRIMARY KEY (PROV_ID),
	CONSTRAINT CK_SEC_PROV_ORGN CHECK (USR_ID IS NOT NULL OR DEV_ID IS NOT NULL OR SES_ID IS NOT NULL)
);

INSERT INTO SEC_PROV_TBL (PROV_ID, USR_ID, APP_ID) VALUES ('fadca076-3690-4a6e-af9e-f1cd68e8c7e8', 'FADCA076-3690-4A6E-AF9E-F1CD68E8C7E8', '4c5b9f8d-49f4-4101-9662-4270895224b2');

-- SECURITY USER TABLE IS USED BY THE SECURITY SUBSYSTEM AND IS OFTEN
-- LINKED TO A USER ENTITY, DEVICE, OR OTHER ENTITY IN THE CLINICAL 
-- DATA MODEL
CREATE TABLE SEC_USR_TBL (
    USR_ID UUID NOT NULL DEFAULT uuid_generate_v1(), -- THE UNIQUE IDENTIFIER FOR THE USER
    CLS_ID UUID NOT NULL DEFAULT '33932B42-6F4B-4659-8849-6ACA54139D8E', -- THE USER CLASSIFICATION
    USR_NAME VARCHAR(64) NOT NULL, -- THE USERNAME OF THE USER
    EMAIL VARCHAR(256), -- THE EMAIL ADDRESS OF THE USER
    EMAIL_CNF BOOLEAN NOT NULL DEFAULT FALSE, -- WHETHER THE USERS EMAIL ADDRESS HAS BEEN CONFIRMED
    PHN_NUM VARCHAR(128), -- THE PRIMARY CONTACT NUMBER FOR SECURITY PURPOSES
    PHN_CNF BOOLEAN NOT NULL DEFAULT FALSE, -- INDICATES WHETHER THE SECURITY PHONE NUMBER HAS BEEN CONFIRMED
    TFA_ENABLED BOOLEAN NOT NULL DEFAULT FALSE, -- INDICATES WHETHER TWO FACTOR AUTHENTICATION IS REQUIRED FOR THIS ACCOUNT
    LOCKED TIMESTAMPTZ, -- TRUE IF THE ACCOUNT HAS BEEN LOCKED
    PASSWD VARCHAR(128) NOT NULL, -- THE PASSWORD OF THE USER
    SEC_STMP VARCHAR(128) NOT NULL, -- THE SECURITY STAMP WHICH IS USED AS A VERIFICATION THAT THE USER INFORMATION HAS CHANGED
    FAIL_LOGIN INT NOT NULL DEFAULT 0, -- THE NUMBER OF TIMES THAT THE USER HAS FAILED TO LOGIN
    LAST_LOGIN_UTC TIMESTAMPTZ, -- THE LAST TIME THAT THE USER SUCCESSFULLY LOGGED IN
    CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE TIME THAT THE USER ACCOUNT WAS CREATED
    CRT_PROV_ID UUID, -- THE USER WHICH CREATED THIS USER ACCOUNT
    OBSLT_UTC TIMESTAMPTZ, -- THE TIME THAT THE USER RECORD WAS OBSOLETED
    OBSLT_PROV_ID UUID, -- THE USER WHICH OBSOLETED THIS USER ACCOUNT
    UPD_UTC TIMESTAMPTZ, -- THE TIME WHEN THIS USER RECORD WAS LAST UPDATED
    UPD_PROV_ID UUID, -- THE USER ID WHICH WAS RESPONSIBLE FOR THE UPDATE
    CONSTRAINT PK_SEC_USR PRIMARY KEY (USR_ID),
    CONSTRAINT FK_SEC_USR_OBSLT_PROV_ID FOREIGN KEY(OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
    CONSTRAINT FK_SEC_USR_UPD_PROV_ID FOREIGN KEY (UPD_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
    CONSTRAINT FK_SEC_USR_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
    CONSTRAINT CK_SEC_USR_OBSLT_USR CHECK (OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL OR OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL),
    CONSTRAINT CK_SEC_USR_UPD_USR CHECK (UPD_PROV_ID IS NOT NULL AND UPD_UTC IS NOT NULL OR UPD_PROV_ID IS NULL AND UPD_UTC IS NULL),
    CONSTRAINT FK_SEC_USR_USR_CLS_ID FOREIGN KEY (CLS_ID) REFERENCES SEC_USR_CLS_CDTBL(CLS_ID)
);
   
-- Create a system user
INSERT INTO SEC_USR_TBL (USR_ID, USR_NAME, PASSWD, SEC_STMP, CLS_ID) VALUES ('FADCA076-3690-4A6E-AF9E-F1CD68E8C7E8', 'SYSTEM','XXXX','XXXX', '9F71BB34-9691-440F-8249-9C831EA16D58');
-- Create the anonymous user
INSERT INTO SEC_USR_TBL (USR_ID, USR_NAME, PASSWD, SEC_STMP, CLS_ID) VALUES ('C96859F0-043C-4480-8DAB-F69D6E86696C', 'ANONYMOUS','XXXX','XXXX', '9F71BB34-9691-440F-8249-9C831EA16D58');    

ALTER TABLE SEC_PROV_TBL ADD CONSTRAINT FK_SEC_PROV_USR FOREIGN KEY (USR_ID) REFERENCES SEC_USR_TBL(USR_ID);

-- Enforce SecurityUser
UPDATE SEC_USR_TBL SET CRT_PROV_ID = 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8';
ALTER TABLE SEC_USR_TBL ALTER COLUMN CRT_PROV_ID SET NOT NULL;

CREATE UNIQUE INDEX SEC_USR_NAME_IDX ON SEC_USR_TBL(LOWER(USR_NAME));
CREATE INDEX SEC_USR_NAME_PWD_IDX ON SEC_USR_TBL(USR_NAME, PASSWD);

-- SECURITY USER CLAIMS
CREATE TABLE SEC_USR_CLM_TBL (
    CLM_ID UUID NOT NULL DEFAULT uuid_generate_v1(), -- UNIQUE ID FOR THE CLAIM
    USR_ID UUID NOT NULL, -- THE USER TO WHICH THE CLAIM BELONGS
    CLM_TYP VARCHAR(128) NOT NULL, -- THE TYPE OF CLAIM
    CLM_VAL VARCHAR(128) NOT NULL, -- THE VALUE OF THE CLAIM
    CONSTRAINT PK_SEC_USR_CLM_TBL PRIMARY KEY (CLM_ID),
    CONSTRAINT FK_SEC_USR_CLM_SEC_USR_TBL FOREIGN KEY (USR_ID) REFERENCES SEC_USR_TBL(USR_ID)
);

CREATE INDEX SEC_USR_CLM_USR_ID_IDX ON SEC_USR_CLM_TBL(USR_ID);

-- LINK TO EXTERNAL IDENTIFIER TOKENS
CREATE TABLE SEC_USR_EXTRN_LGN_TBL (
    LGN_PVDR VARCHAR(128) NOT NULL, -- THE PROVIDER (GMAIL, LIVE, ETC.)
    PVD_KEY VARCHAR(128) NOT NULL, -- THE PROVIDER KEY
    USR_ID UUID NOT NULL, -- THE USER TO WHICH THE LOGIN PROVIDES
    CONSTRAINT PK_SEC_USR_EXTRN_LGN PRIMARY KEY (LGN_PVDR, PVD_KEY, USR_ID),
    CONSTRAINT FK_SEC_USR_EXTRN_LGN_USR_ID FOREIGN KEY (USR_ID) REFERENCES SEC_USR_TBL(USR_ID)
);

-- SECURITY ROLES ARE USED TO GROU POLICIES AND ACTIONS AS WELL AS ACCESS TO 
-- PARTICULAR POS APPLICATIONS BASED ON POLICY
CREATE TABLE SEC_ROL_TBL (
    ROL_ID UUID NOT NULL DEFAULT uuid_generate_v1(), -- UNIQUE ID OF THE ROLE
    ROL_NAME VARCHAR(256) NOT NULL, -- THE NAME OF THE ROLE
    DESCR VARCHAR(256), -- THE DESCRIPTION OF THE ROLE
    CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE CREATION TIME OF THE ROLE
    CRT_PROV_ID UUID NOT NULL, -- THE USER WHICH CREATE THE ROLE
    OBSLT_UTC TIMESTAMPTZ, -- THE TIME THAT THE ROLE WAS OBSOLETED
    OBSLT_PROV_ID UUID, -- THE USER WHICH OBSOLETED THE ROLE
    UPD_UTC TIMESTAMPTZ, -- THE TIME WHEN THE ROLE WAS UPDATED
    UPD_PROV_ID UUID, -- THE USER WHICH UPDATED THE ROLE
    CONSTRAINT PK_SEC_ROL_TBL PRIMARY KEY (ROL_ID),
    CONSTRAINT FK_SEC_ROL_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
    CONSTRAINT FK_SEC_ROL_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
    CONSTRAINT FK_SEC_ROL_UPD_PROV_ID FOREIGN KEY (UPD_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
    CONSTRAINT CK_SEC_ROL_OBSLT_USR CHECK (OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL OR OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL),
    CONSTRAINT CK_SEC_ROL_UPD_USR CHECK (UPD_PROV_ID IS NOT NULL AND UPD_UTC IS NOT NULL OR UPD_PROV_ID IS NULL AND UPD_UTC IS NULL)
);

-- UNIQUE INDEX ON NAME
CREATE UNIQUE INDEX SEC_ROL_ROL_NAME_IDX ON SEC_ROL_TBL(LOWER(ROL_NAME));

-- SECURITY USER TO ROLE ASSOCIATION
CREATE TABLE SEC_USR_ROL_ASSOC_TBL (
    USR_ID UUID NOT NULL, -- THE IDENTIFIER OF THE USER
    ROL_ID UUID NOT NULL, -- THE IDENTIFIER OF THE ROLE
    CONSTRAINT PK_SEC_ROL_ASSOC_TBL PRIMARY KEY (USR_ID, ROL_ID),
    CONSTRAINT FK_SEC_ROL_ASSOC_USR_ID FOREIGN KEY (USR_ID) REFERENCES SEC_USR_TBL(USR_ID),
    CONSTRAINT FK_SEC_ROL_ASSOC_ROL_ID FOREIGN KEY (ROL_ID) REFERENCES SEC_ROL_TBL(ROL_ID)
);

CREATE INDEX SEC_USR_ROL_ASSOC_USR_ID_IDX ON SEC_USR_ROL_ASSOC_TBL(USR_ID);
CREATE INDEX SEC_USR_ROL_ASSOC_ROL_ID_IDX ON SEC_USR_ROL_ASSOC_TBL(ROL_ID);

-- POLICY TABLE (SEE OIZ DESIGN DOCUMENTATION)
CREATE TABLE SEC_POL_TBL (
    POL_ID UUID NOT NULL DEFAULT uuid_generate_v1(), -- THE UNIQUE IDENTIFIER OF THE POLICY
    OID VARCHAR(128) NOT NULL, -- THE OID FOR THE POLICY
    POL_NAME VARCHAR(64) NOT NULL, -- THE NAME OF THE POLICY
    HDLR_CLS VARCHAR(256), -- THE HANDLER CLASS
    IS_PUB BOOLEAN NOT NULL DEFAULT FALSE, -- WHETHER THE POLICY IS INTERNAL OR SHOULD BE DISCLOSED
    IS_ELEV BOOLEAN NOT NULL DEFAULT FALSE, -- WHETHER THE POLICY CAN BE ELEVATED OVER
    CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE DATE THE POLICY WAS CREATED
    CRT_PROV_ID UUID NOT NULL, -- THE USER THAT CREATED THE ROLE
    OBSLT_UTC TIMESTAMPTZ, -- THE DATE THE POLICY WAS OBSOLETED
    OBSLT_PROV_ID UUID, -- THE OBSOLTION USER
    CONSTRAINT PK_SEC_POL_TBL PRIMARY KEY (POL_ID),
    CONSTRAINT FK_SEC_POL_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
    CONSTRAINT FK_SEC_POL_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID)
);

CREATE UNIQUE INDEX SEC_OID_IDX ON SEC_POL_TBL(OID);

-- BUILT IN OPENIZ POLICIES
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('da73c05a-3159-48c8-bbcb-741911d91cd2', '1.3.6.1.4.1.33349.3.1.5.9.2', 'Unrestricted All', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('ea73c05a-3159-48c8-bbcb-741911d91cd2', '1.3.6.1.4.1.33349.3.1.5.9.2.0', 'Unrestricted Administrative Function', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('d80ac1cf-3d6e-429f-a4a0-88c0bbbc839d', '1.3.6.1.4.1.33349.3.1.5.9.2.0.1', 'Change Password', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('9c0d65ac-613e-4a67-8bc6-5ce2c0b42160', '1.3.6.1.4.1.33349.3.1.5.9.2.0.2', 'Create Role', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('79bcc227-0d13-4fbf-a83e-f2b9fce34151', '1.3.6.1.4.1.33349.3.1.5.9.2.0.3', 'Alter Role', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('ab8642cb-28e4-4e9e-bd7b-d6dc72b729b2', '1.3.6.1.4.1.33349.3.1.5.9.2.0.4', 'Create Identity', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('bb8642cb-28e4-4e9e-bd7b-d6dc72b729b2', '1.3.6.1.4.1.33349.3.1.5.9.2.0.5', 'Create Device', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('cb8642cb-28e4-4e9e-bd7b-d6dc72b729b2', '1.3.6.1.4.1.33349.3.1.5.9.2.0.6', 'Create Application', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('db8642cb-28e4-4e9e-bd7b-d6dc72b729b2', '1.3.6.1.4.1.33349.3.1.5.9.2.0.7', 'Administer Concept Dictionary', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('eb8642cb-28e4-4e9e-bd7b-d6dc72b729b2', '1.3.6.1.4.1.33349.3.1.5.9.2.0.8', 'Alter Identity', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('fb8642cb-28e4-4e9e-bd7b-d6dc72b729b2', '1.3.6.1.4.1.33349.3.1.5.9.2.0.9', 'Alter Policy', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('fa8642cb-28e4-4e9e-bd7b-d6dc72b729b2', '1.3.6.1.4.1.33349.3.1.5.9.2.0.10', 'Administer Data Warehouse', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');

INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('d15b96ab-646c-4c00-9a58-ea09eee67d7c', '1.3.6.1.4.1.33349.3.1.5.9.2.1', 'Login', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('e15b96ab-646c-4c00-9a58-ea09eee67d7c', '1.3.6.1.4.1.33349.3.1.5.9.2.1.0', 'Login as a Service', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');

INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('f6840336-4e20-4bc0-b965-baa6d7c80be3', '1.3.6.1.4.1.33349.3.1.5.9.2.2', 'Unrestricted Clinical Data', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('b81daf47-17a5-465e-a5fd-706b168b0265', '1.3.6.1.4.1.33349.3.1.5.9.2.2.0', 'Query Clinical Data', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('d7276921-a078-4348-95f2-ed3cde83e607', '1.3.6.1.4.1.33349.3.1.5.9.2.2.1', 'Write Clinical Data', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('2e027dee-ede4-4731-b7fa-cb67ae0586be', '1.3.6.1.4.1.33349.3.1.5.9.2.2.2', 'Delete Clinical Data', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('5fb731bf-4e59-4863-80bd-51757d58ea3b', '1.3.6.1.4.1.33349.3.1.5.9.2.2.3', 'Read Clinical Data', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('5fb731bf-4e59-4863-80bd-51757d58ea9a', '1.3.6.1.4.1.33349.3.1.5.9.2.2.4', 'Export Clinical Data', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('dea891aa-224d-4859-81b3-c1eb2750067e', '1.3.6.1.4.1.33349.3.1.5.9.2.999', 'Override Disclosure', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('eea891aa-224d-4859-81b3-c1eb2750067e', '1.3.6.1.4.1.33349.3.1.5.9.2.4', 'Unrestricted Metadata', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('fea891aa-224d-4859-81b3-c1eb2750067e', '1.3.6.1.4.1.33349.3.1.5.9.2.4.0', 'Read Metadata', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');

INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('0ea891aa-224d-4859-81b3-c1eb2750067e', '1.3.6.1.4.1.33349.3.1.5.9.2.10', 'Access Client Administrative Function', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');

INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('0a8642cb-28e4-4e9e-bd7b-d6df72b729b2', '1.3.6.1.4.1.33349.3.1.5.9.2.5', 'Unrestricted Data Warehouse', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('1a8642cb-28e4-4e9e-bd7b-d6df72b729b2', '1.3.6.1.4.1.33349.3.1.5.9.2.5.0', 'Write Warehouse Data', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('2a8642cb-28e4-4e9e-bd7b-d6df72b729b2', '1.3.6.1.4.1.33349.3.1.5.9.2.5.1', 'Delete Warehouse Data', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('3a8642cb-28e4-4e9e-bd7b-d6df72b729b2', '1.3.6.1.4.1.33349.3.1.5.9.2.5.2', 'Read Warehouse Data', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES ('4a8642cb-28e4-4e9e-bd7b-d6df72b729b2', '1.3.6.1.4.1.33349.3.1.5.9.2.5.3', 'Query Warehouse Data', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');

INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID, IS_ELEV) VALUES ('36f1ed35-552e-421a-8f59-629561ab9eb6', '1.3.6.1.4.1.33349.3.1.5.9.3', 'Restricted Information', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8', TRUE);

INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES (('baa124aa-224d-4859-81b3-c1eb2750067e'), '1.3.6.1.4.1.33349.3.1.5.9.2.4.1.0', 'Write Materials', ('fadca076-3690-4a6e-af9e-f1cd68e8c7e8'));
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES (('baa125aa-224d-4859-81b3-c1eb2750067e'), '1.3.6.1.4.1.33349.3.1.5.9.2.4.1.1', 'Delete Materials', ('fadca076-3690-4a6e-af9e-f1cd68e8c7e8'));
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES (('baa126aa-224d-4859-81b3-c1eb2750067e'), '1.3.6.1.4.1.33349.3.1.5.9.2.4.0.1.2', 'Read Materials', ('fadca076-3690-4a6e-af9e-f1cd68e8c7e8'));
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES (('baa127aa-224d-4859-81b3-c1eb2750067e'), '1.3.6.1.4.1.33349.3.1.5.9.2.4.0.1.3', 'Query Materials', ('fadca076-3690-4a6e-af9e-f1cd68e8c7e8'));
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES (('baa224aa-224d-4859-81b3-c1eb2750067e'), '1.3.6.1.4.1.33349.3.1.5.9.2.4.2.0', 'Write Places & Orgs', ('fadca076-3690-4a6e-af9e-f1cd68e8c7e8'));
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES (('baa225aa-224d-4859-81b3-c1eb2750067e'), '1.3.6.1.4.1.33349.3.1.5.9.2.4.2.1', 'Delete Places & Orgs', ('fadca076-3690-4a6e-af9e-f1cd68e8c7e8'));
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES (('baa226aa-224d-4859-81b3-c1eb2750067e'), '1.3.6.1.4.1.33349.3.1.5.9.2.4.0.2.2', 'Read Places & Orgs', ('fadca076-3690-4a6e-af9e-f1cd68e8c7e8'));
INSERT INTO SEC_POL_TBL (POL_ID, OID, POL_NAME, CRT_PROV_ID) VALUES (('baa227aa-224d-4859-81b3-c1eb2750067e'), '1.3.6.1.4.1.33349.3.1.5.9.2.4.0.2.3', 'Query Places & Orgs', ('fadca076-3690-4a6e-af9e-f1cd68e8c7e8'));

-- SECURITY ROLE TO POLICY ASSOCIATIVE ENTITY
CREATE TABLE SEC_ROL_POL_ASSOC_TBL (
	SEC_POL_INST_ID UUID NOT NULL DEFAULT uuid_generate_v1(), -- UNIQUE IDENTIFIER
	ROL_ID UUID NOT NULL, -- THE ROLE TO WHICH THE POLICY APPLIES
	POL_ID UUID NOT NULL, -- POLICY IDENTIFIER
	POL_ACT INT NOT NULL DEFAULT 0 CHECK (POL_ACT < 3), -- POLICY ACTIONS
	CONSTRAINT PK_SEC_POL_ROL_ASSOC PRIMARY KEY (SEC_POL_INST_ID),
	CONSTRAINT FK_SEC_POL_ROL_ASSOC_ROL_ID FOREIGN KEY (ROL_ID) REFERENCES SEC_ROL_TBL(ROL_ID),
	CONSTRAINT FK_SEC_POL_ROL_ASSOC_POL_ID FOREIGN KEY (POL_ID) REFERENCES SEC_POL_TBL(POL_ID)
);

CREATE INDEX SEC_POL_ROL_ASSOC_ROL_ID_IDX ON SEC_ROL_POL_ASSOC_TBL(ROL_ID);
CREATE UNIQUE INDEX SEC_POL_ROL_ASSOC_POL_ROL_IDX ON SEC_ROL_POL_ASSOC_TBL(ROL_ID, POL_ID);

-- INSERT THE DEFAULT ASSOCIATIONS
-- CREATE USERS ROLE
INSERT INTO SEC_ROL_TBL (ROL_ID, ROL_NAME, DESCR, CRT_PROV_ID) VALUES ('f4e58ae8-8bbd-4635-a6d4-8a195b143436', 'USERS', 'Group for users who have login access', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('d15b96ab-646c-4c00-9a58-ea09eee67d7c', 'f4e58ae8-8bbd-4635-a6d4-8a195b143436', 2); -- GRANT Login

-- CREATE ADMINISTRATORS ROLE
INSERT INTO SEC_ROL_TBL (ROL_ID, ROL_NAME, DESCR, CRT_PROV_ID) VALUES ('f6d2ba1d-5bb5-41e3-b7fb-2ec32418b2e1', 'ADMINISTRATORS', 'Group for users who have administrative access', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('ea73c05a-3159-48c8-bbcb-741911d91cd2', 'f6d2ba1d-5bb5-41e3-b7fb-2ec32418b2e1', 2); -- GRANT Access Administrative Function
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('d15b96ab-646c-4c00-9a58-ea09eee67d7c', 'f6d2ba1d-5bb5-41e3-b7fb-2ec32418b2e1', 2); -- GRANT Login
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('f6840336-4e20-4bc0-b965-baa6d7c80be3', 'f6d2ba1d-5bb5-41e3-b7fb-2ec32418b2e1', 0); -- DENY Unrestricted Clinical Data
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('dea891aa-224d-4859-81b3-c1eb2750067e', 'f6d2ba1d-5bb5-41e3-b7fb-2ec32418b2e1', 0); -- DENY Override disclosure
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('0ea891aa-224d-4859-81b3-c1eb2750067e', 'f6d2ba1d-5bb5-41e3-b7fb-2ec32418b2e1', 2); -- GRANT Local Administrator
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('eea891aa-224d-4859-81b3-c1eb2750067e', 'f6d2ba1d-5bb5-41e3-b7fb-2ec32418b2e1', 2); -- GRANT Unrestricted Metadata


-- CLINICAL STAFF
INSERT INTO SEC_ROL_TBL (ROL_ID, ROL_NAME, DESCR, CRT_PROV_ID) VALUES ('43167DCB-6F77-4F37-8222-133E675B4434', 'CLINICAL_STAFF', 'Group for clinic staff', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('ea73c05a-3159-48c8-bbcb-741911d91cd2', '43167DCB-6F77-4F37-8222-133E675B4434', 0); -- GRANT Access Administrative Function
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('d15b96ab-646c-4c00-9a58-ea09eee67d7c', '43167DCB-6F77-4F37-8222-133E675B4434', 2); -- GRANT Login
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('f6840336-4e20-4bc0-b965-baa6d7c80be3', '43167DCB-6F77-4F37-8222-133E675B4434', 2); -- GRANT Unrestricted Clinical Data
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('dea891aa-224d-4859-81b3-c1eb2750067e', '43167DCB-6F77-4F37-8222-133E675B4434', 0); -- DENY Override disclosure
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('fea891aa-224d-4859-81b3-c1eb2750067e', '43167DCB-6F77-4F37-8222-133E675B4434', 2); -- GRANT Read Metadata Administrator

-- CREATE ROLE SYSTEM WHICH IS DENIED LOGIN
INSERT INTO SEC_ROL_TBL (ROL_ID, ROL_NAME, DESCR, CRT_PROV_ID) VALUES ('c3ae21d2-fc23-4133-ba42-b0e0a3b817d7', 'SYSTEM', 'Group for user SYSTEM. Identifies the functions that internal system functions have access to. EDITING THIS ROLE MAY CAUSE SYSTEM FAILURE', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_USR_ROL_ASSOC_TBL (ROL_ID, USR_ID) VALUES ('c3ae21d2-fc23-4133-ba42-b0e0a3b817d7', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');

-- GRANT ALL
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT) VALUES ('da73c05a-3159-48c8-bbcb-741911d91cd2',  'c3ae21d2-fc23-4133-ba42-b0e0a3b817d7', 2);
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('d15b96ab-646c-4c00-9a58-ea09eee67d7c', 'c3ae21d2-fc23-4133-ba42-b0e0a3b817d7', 0); -- DENY Login
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('dea891aa-224d-4859-81b3-c1eb2750067e', 'c3ae21d2-fc23-4133-ba42-b0e0a3b817d7', 0); -- DENY Override disclosure

-- CREATE ROLE ANONYMOUS WHICH IS DENIED ALL CLINICAL 
INSERT INTO SEC_ROL_TBL (ROL_ID, ROL_NAME, DESCR, CRT_PROV_ID) VALUES ('dadbd858-13c5-44a3-ad7d-1c44cecaa4b6', 'ANONYMOUS', 'Group for user ANONYMOUS. Identifies the functions that non-logged in users have access to. EDITING THIS ROLE MAY INTRODUCE SECURITY BREACHES', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_USR_ROL_ASSOC_TBL (ROL_ID, USR_ID) VALUES ('dadbd858-13c5-44a3-ad7d-1c44cecaa4b6', 'C96859F0-043C-4480-8DAB-F69D6E86696C');
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('ea73c05a-3159-48c8-bbcb-741911d91cd2', 'dadbd858-13c5-44a3-ad7d-1c44cecaa4b6', 0); -- DENY Access Administrative Function
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('d15b96ab-646c-4c00-9a58-ea09eee67d7c', 'dadbd858-13c5-44a3-ad7d-1c44cecaa4b6', 0); -- DENY Login
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('f6840336-4e20-4bc0-b965-baa6d7c80be3', 'dadbd858-13c5-44a3-ad7d-1c44cecaa4b6', 0); -- DENY Unrestricted Clinical Data
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('dea891aa-224d-4859-81b3-c1eb2750067e', 'dadbd858-13c5-44a3-ad7d-1c44cecaa4b6', 0); -- DENY Override disclosure
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('fea891aa-224d-4859-81b3-c1eb2750067e', 'dadbd858-13c5-44a3-ad7d-1c44cecaa4b6', 0); -- GRANT Read Metadata

-- CREATE SYNCHRONIZERS ROLE
INSERT INTO SEC_ROL_TBL (ROL_ID, ROL_NAME, DESCR, CRT_PROV_ID) VALUES ('54B7677C-682B-425F-A937-3AA03D5951F1', 'SYNCHRONIZERS', 'Group for user SYNCHRONIZERS. Identifies the functions that are used for synchronization. EDITING THIS ROLE MAY INTRODUCE SECURITY BREACHES', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('e15b96ab-646c-4c00-9a58-ea09eee67d7c', '54B7677C-682B-425F-A937-3AA03D5951F1', 2); -- GRANT AS Service Login
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('f6840336-4e20-4bc0-b965-baa6d7c80be3', '54B7677C-682B-425F-A937-3AA03D5951F1', 2); -- GRANT Unrestricted Clinical Data
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('fea891aa-224d-4859-81b3-c1eb2750067e', '54B7677C-682B-425F-A937-3AA03D5951F1', 2); -- GRANT Read Metadata
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('eea891aa-224d-4859-81b3-c1eb2750067e', '54B7677C-682B-425F-A937-3AA03D5951F1', 2); -- GRANT Unrestricted metadata
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('dea891aa-224d-4859-81b3-c1eb2750067e', '54B7677C-682B-425F-A937-3AA03D5951F1', 0); -- DENY Override disclosure

-- CREATE DEVICE ROLE
INSERT INTO SEC_ROL_TBL (ROL_ID, ROL_NAME, DESCR, CRT_PROV_ID) VALUES ('613d05a0-dd0d-4516-a30c-e733741885f0', 'DEVICE', 'Represents a device in the system. Identifies the functions that are used for devices. EDITING THIS ROLE MAY INTRODUCE SECURITY BREACHES', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('0ea891aa-224d-4859-81b3-c1eb2750067e', '613d05a0-dd0d-4516-a30c-e733741885f0', 2); -- GRANT Access Client Administrative Function
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('d80ac1cf-3d6e-429f-a4a0-88c0bbbc839d', '613d05a0-dd0d-4516-a30c-e733741885f0', 0); -- DENY Change Any Password
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('eb8642cb-28e4-4e9e-bd7b-d6dc72b729b2', '613d05a0-dd0d-4516-a30c-e733741885f0', 2); -- GRANT Alter Identity
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('ab8642cb-28e4-4e9e-bd7b-d6dc72b729b2', '613d05a0-dd0d-4516-a30c-e733741885f0', 2); -- GRANT Create Identity
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('d15b96ab-646c-4c00-9a58-ea09eee67d7c', '613d05a0-dd0d-4516-a30c-e733741885f0', 2); -- GRANT Login
INSERT INTO SEC_ROL_POL_ASSOC_TBL (POL_ID, ROL_ID, POL_ACT)  VALUES ('fea891aa-224d-4859-81b3-c1eb2750067e', '613d05a0-dd0d-4516-a30c-e733741885f0', 2); -- GRANT Read Metadata

-- SECURITY DEVICE WHICH IS HOW DEVICES AUTHENTICATE THEMSELVES
CREATE TABLE SEC_DEV_TBL (
	DEV_ID UUID NOT NULL DEFAULT uuid_generate_v1(), -- UNIQUE IDENTIFIER FOR THE DEVICE
	DEV_SCRT VARCHAR(64) NOT NULL, -- THE SECRET OF THE DEVICE (EX: X509 THUMB)
	DEV_PUB_ID VARCHAR(64) NOT NULL, -- THE PUBLIC IDENTIIFER OF THE DEVICE
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE DATE THE DEVICE WAS CREATED
	CRT_PROV_ID UUID NOT NULL, -- THE USER WHICH CREATED THE DEVICE
	OBSLT_UTC TIMESTAMPTZ, -- THE TIME THAT THE DEVICE WAS OBSOLETED
	OBSLT_PROV_ID UUID, -- THE USER WHICH OBSOLETD THE DEVICE
	RPLC_DEV_ID UUID, -- THE DEVICE THAT THIS DEVICE REPLACES.
	CONSTRAINT PK_SEC_DEV_TBL PRIMARY KEY (DEV_ID),
	CONSTRAINT FK_SEC_DEV_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_SEC_DEV_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_SEC_DEV_RPLC_DEV_ID FOREIGN KEY (RPLC_DEV_ID) REFERENCES SEC_DEV_TBL(DEV_ID),
    CONSTRAINT CK_SEC_DEV_OBSLT_USR CHECK (OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL OR OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL)
);

CREATE UNIQUE INDEX SEC_DEV_PUB_ID_IDX ON SEC_DEV_TBL(DEV_PUB_ID);
CREATE UNIQUE INDEX SEC_DEV_SCRT_IDX ON SEC_DEV_TBL(DEV_SCRT);
ALTER TABLE SEC_PROV_TBL ADD CONSTRAINT FK_SEC_PROV_DEV FOREIGN KEY (DEV_ID) REFERENCES SEC_DEV_TBL(DEV_ID);

-- SECURITY APPLICATION WHICH IS HOW APPLICATIONS AUTHENTICATE THEMSELVES
CREATE TABLE SEC_APP_TBL (
	APP_ID UUID NOT NULL DEFAULT uuid_generate_v1(), -- UNIQUE IDENTIIFER FOR THE DEV
	APP_PUB_ID VARCHAR(64) NOT NULL, -- THE PUBLIC IDENTIFIER FOR THE APP
	APP_SCRT VARCHAR(64) NOT NULL, -- THE APPLICATION SECRET
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE CREATION TIME OF THE APP
	CRT_PROV_ID UUID NOT NULL, -- THE USER WHICH IS RESPONSIBLE FOR THE CREATION OF THE APP
	OBSLT_UTC TIMESTAMPTZ, -- OBSOLETION TIME
	OBSLT_PROV_ID UUID, -- THE OBSOLETION USER
	RPLC_APP_ID UUID, -- THE APPLICATION WICH THIS APPLICATION REPLACES
	CONSTRAINT PK_SEC_APP_TBL PRIMARY KEY (APP_ID),
	CONSTRAINT FK_SEC_APP_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_SEC_APP_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_SEC_APP_RPLC_APP_ID FOREIGN KEY (RPLC_APP_ID) REFERENCES SEC_APP_TBL(APP_ID),
	CONSTRAINT CK_SEC_APP_OBSLT_PROV_ID CHECK (OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL OR OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL)
);

CREATE UNIQUE INDEX SEC_APP_APP_PUB_ID_IDX ON SEC_APP_TBL(APP_PUB_ID);
CREATE INDEX SEC_APP_APP_SCRT_IDX ON SEC_APP_TBL(APP_SCRT);

INSERT INTO SEC_APP_TBL (APP_ID, APP_PUB_ID, APP_SCRT, CRT_PROV_ID) VALUES ('4c5b9f8d-49f4-4101-9662-4270895224b2', 'SYSTEM', 'XXXXX', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
ALTER TABLE SEC_PROV_TBL ADD CONSTRAINT FK_SEC_PROV_APP FOREIGN KEY (APP_ID) REFERENCES SEC_APP_TBL(APP_ID);

-- SECURITY DEVICE TO POLICY ASSOC
CREATE TABLE SEC_DEV_POL_ASSOC_TBL (
	SEC_POL_INST_ID UUID NOT NULL DEFAULT uuid_generate_v1(), -- UUID FOR THE INSTANCES
	DEV_ID UUID NOT NULL, -- DEVICE IDENTIFIER TO WHICH THE POLICY APPLIES
	POL_ID UUID NOT NULL, -- POLICY IDENTIIFER TO WHICH THE POLICY APPLIES
	POL_ACT INT NOT NULL CHECK (POL_ACT < 3), -- POLICY ACTION EITHER GRANT, DENY OR ELEVATE
	CONSTRAINT PK_SEC_DEV_POL_ASSOC_TBL PRIMARY KEY (SEC_POL_INST_ID), 
	CONSTRAINT FK_SEC_DEV_POL_ASSOC_DEV_ID FOREIGN KEY (DEV_ID) REFERENCES SEC_DEV_TBL(DEV_ID),
	CONSTRAINT FK_SEC_DEV_POL_ASSOC_POL_ID FOREIGN KEY (POL_ID) REFERENCES SEC_POL_TBL(POL_ID)
);

CREATE INDEX SEC_DEV_POL_ASSOC_DEV_ID_IDX ON SEC_DEV_POL_ASSOC_TBL(DEV_ID);

-- SECURITY APPLICATION TO POLICY INSTANCE ASSOCIATION
CREATE TABLE SEC_APP_POL_ASSOC_TBL (
	SEC_POL_INST_ID UUID NOT NULL DEFAULT uuid_generate_v1(), -- UUID FOR THE INSTANCE
	APP_ID UUID NOT NULL, -- APPLICATION IDENTIFIER TO WHICH THE POLICY APPLIES
	POL_ID UUID NOT NULL, -- THE POLICY TO WHICH THE POLICY INSTANCE APPLIES
	POL_ACT INT NOT NULL CHECK (POL_ACT < 3), -- POLICY ACTION
	CONSTRAINT PK_SEC_APP_POL_ASSOC_TBL PRIMARY KEY (SEC_POL_INST_ID),
	CONSTRAINT FK_SEC_APP_POL_ASSOC_APP_ID FOREIGN KEY (APP_ID) REFERENCES SEC_APP_TBL(APP_ID),
	CONSTRAINT FK_SEC_APP_POL_ASSOC_POL_ID FOREIGN KEY (POL_ID) REFERENCES SEC_POL_TBL(POL_ID)
);

CREATE INDEX SEC_APP_POL_ASSOC_APP_ID_IDX ON SEC_APP_POL_ASSOC_TBL(APP_ID);

ALTER TABLE SEC_PROV_TBL ADD CONSTRAINT FK_SEC_PROV_USR_TBL FOREIGN KEY (USR_ID) REFERENCES SEC_USR_TBL(USR_ID);
ALTER TABLE SEC_PROV_TBL ADD CONSTRAINT FK_SEC_PROV_DEV_TBL FOREIGN KEY (DEV_ID) REFERENCES SEC_DEV_TBL(DEV_ID);
ALTER TABLE SEC_PROV_TBL ADD CONSTRAINT FK_SEC_PROV_APP_TBL FOREIGN KEY (APP_ID) REFERENCES SEC_APP_TBL(APP_ID);

-- PHONETIC ALGORITHMS TABLE
CREATE TABLE PHON_ALG_TBL (
	ALG_ID UUID NOT NULL DEFAULT uuid_generate_v1(), -- UNIQUE IDENTIFIER FOR THE ALGORITHM
	ALG_NAME VARCHAR(32) NOT NULL, -- NAME OF THE ALGORITHM
	HDLR_CLS VARCHAR(256), -- THE HANDLER CLASS WHICH CAN GENERATE THE ALGORITHM CODES
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE CREATION TIME
	CRT_PROV_ID UUID NOT NULL, -- THE USER WHICH CREATED THE ALGORITHM
	UPD_UTC TIMESTAMPTZ, -- THE UPDATED TIME FOR THE ALGORITHM
	UPD_PROV_ID UUID, -- THE USER WHICH UPDATED THE ALGORITHM
	OBSLT_UTC TIMESTAMPTZ, -- THE TIMESTAMP OF THE OBSOLETION
	OBSLT_PROV_ID UUID, -- THE USER WHICH OBSOLETED THE ALGORITHM
	CONSTRAINT PK_PHON_ALG_TBL PRIMARY KEY (ALG_ID),
	CONSTRAINT FK_PHON_ALG_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_PHON_ALG_UPD_PROV_ID FOREIGN KEY (UPD_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_PHON_ALG_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT CK_PHON_ALG_OBSLT_PROV_ID CHECK (OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL OR OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL),
	CONSTRAINT CK_PHON_ALG_UPD_USR CHECK (UPD_PROV_ID IS NOT NULL AND UPD_UTC IS NOT NULL OR UPD_PROV_ID IS NULL AND UPD_UTC IS NULL)
);

CREATE INDEX PHON_ALG_NAME_IDX ON PHON_ALG_TBL(ALG_NAME);

INSERT INTO PHON_ALG_TBL (ALG_ID, ALG_NAME, HDLR_CLS, CRT_PROV_ID)  VALUES ('402cd339-d0e4-46ce-8fc2-12a4b0e17226', 'NONE', NULL, 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO PHON_ALG_TBL (ALG_ID, ALG_NAME, HDLR_CLS, CRT_PROV_ID)  VALUES ('3352a79a-d2e0-4e0c-9b48-6fd2a202c681', 'SOUNDEX', 'SanteDB.Core.Services.Impl.PhoneticAlgorithms.SoundexPhoneticAlgorithmHandler, SanteDB.Core, Version=0.6.0.0', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO PHON_ALG_TBL (ALG_ID, ALG_NAME, HDLR_CLS, CRT_PROV_ID)  VALUES ('d79a4dc6-66a6-4602-8fcb-7dc09a895793', 'METAPHONE', 'SanteDB.Core.Services.Impl.PhoneticAlgorithms.MetaphonePhoneticAlgorithmHandler, SanteDB.Core, Version=0.6.0.0', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');

-- PHONETIC VALUES TABLE ASSOCIATES STRINGS WITH VALUES
CREATE TABLE PHON_VAL_TBL (
	VAL_ID UUID NOT NULL DEFAULT uuid_generate_v1(), -- UNIQUE IDENTIFIER FORHTE VALUE
	VAL VARCHAR(64) NOT NULL, -- THE VALUE OF THE CODE IN HUMAN READABLE FORM
	PHON_CS VARCHAR(32), -- THE PHONETIC CODE OF THE VALUE
	ALG_ID UUID NOT NULL, -- THE PHONETIC ALGORITHM USED TO GENERATE THE CODE
	CONSTRAINT PK_PHON_VAL_TBL PRIMARY KEY (VAL_ID),
	CONSTRAINT FK_PHON_VAL_ALG_ID FOREIGN KEY (ALG_ID) REFERENCES PHON_ALG_TBL(ALG_ID)
);

CREATE INDEX PHON_VAL_PHON_CS_IDX ON PHON_VAL_TBL(PHON_CS);
CREATE INDEX PHON_VAL_PHON_VAL_IDX ON PHON_VAL_TBL(VAL);

-- GENERIC CONCEPTS TABLE
CREATE TABLE CD_TBL (
	CD_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	IS_SYS BOOLEAN NOT NULL DEFAULT FALSE, -- WHETHER THE CONCEPT IS A SYSTEM CONCEPT
	CONSTRAINT PK_CD_TBL PRIMARY KEY (CD_ID)
);

-- CONCEPT CLASSIFICATIONS TABLE
CREATE TABLE CD_CLS_TBL (
	CLS_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	CLS_NAME VARCHAR(50) NOT NULL, -- THE NAME OF THE CLASS
	MNEMONIC VARCHAR(16) NOT NULL, -- THE MNEMONIC USED BY THE SYSTEM TO LOCATE CONCEPTS
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE TIME THAT HTE CONCEPT CLASS WAS CREATED
	CRT_PROV_ID UUID NOT NULL, -- THE USER WHICH CREATED THE CONCEPT CLASS
	UPD_UTC TIMESTAMPTZ, -- THE TIME WHEN THE CONCEPT CLASS WAS CREATE
	UPD_PROV_ID UUID, -- THE USER ID THAT UPDATED THE CONCEPT CLASS
	OBSLT_UTC TIMESTAMPTZ, -- THE OBSOLETION TIME OF THE CONCEPT
	OBSLT_PROV_ID UUID, -- THE USER WHICH OBSOLETED THE CONCEPT
	CONSTRAINT PK_CD_CLS_TBL PRIMARY KEY (CLS_ID),
	CONSTRAINT FK_CD_CLS_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_CD_CLS_UPD_PROV_ID FOREIGN KEY (UPD_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_CD_CLS_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT CK_CD_CLS_OBSLT_PROV_ID CHECK (OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL OR OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL),
	CONSTRAINT CK_CD_CLS_UPD_PROV_ID CHECK (UPD_PROV_ID IS NOT NULL AND UPD_UTC IS NOT NULL OR UPD_PROV_ID IS NULL AND UPD_UTC IS NULL)
);

CREATE UNIQUE INDEX CD_CLS_MNEMONIC_IDX ON CD_CLS_TBL(MNEMONIC);

-- CONCEPT SETS REPRESENT A SET OF CONCEPTS LOGICALLY GROUPED TOGEHTHER
CREATE TABLE CD_SET_TBL (
	SET_ID UUID NOT NULL DEFAULT uuid_generate_v1(), 
	SET_NAME VARCHAR(50) NOT NULL, -- THE NAME OF THE SET
	MNEMONIC VARCHAR(64) NOT NULL, -- THE MNEMONIC (SYSTEM NAME) OF THE SET
	OID VARCHAR(64) NOT NULL, -- THE OID (EXTERNAL ID) OF THE CONCEPT SET
	URL VARCHAR(256) NOT NULL, -- THE DEFINITION URL OF THE CONCEPT SET
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE CREATION TIME OF THE CONCEPT SET
	CRT_PROV_ID UUID NOT NULL, -- THE USER WHICH CREATED THE CONCEPT SET
	OBSLT_UTC TIMESTAMPTZ, -- THE TIME THAT THE SET WAS OBSOLETED
	OBSLT_RSN TEXT, -- THE REASON THE SET WAS OBSOLETED
	OBSLT_PROV_ID UUID, -- THE OBSOLETION USER IDENTIFIER
	UPD_UTC TIMESTAMPTZ, -- THE UPDATED TIME OF THE CONCEPT SET
	UPD_PROV_ID UUID, -- THE UUID OF THE USER WHICH UPDATED THE CONCEPT SET
	CONSTRAINT PK_CD_SET_TBL PRIMARY KEY (SET_ID), 
	CONSTRAINT FK_CD_SET_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_CD_SET_UPD_PROV_ID FOREIGN KEY (UPD_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_CD_SET_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT CK_CD_SET_OBSLT_PROV_ID CHECK (OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL OR OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL),
	CONSTRAINT CK_CD_SET_UPD_PROV_ID CHECK (UPD_PROV_ID IS NOT NULL AND UPD_UTC IS NOT NULL OR UPD_PROV_ID IS NULL AND UPD_UTC IS NULL)
);

CREATE UNIQUE INDEX CD_SET_OID_IDX ON CD_SET_TBL(OID);
CREATE UNIQUE INDEX CD_SET_URL_IDX ON CD_SET_TBL(URL);
CREATE UNIQUE INDEX CD_SET_MNEMONIC_IDX ON CD_SET_TBL(MNEMONIC);

-- CONCEPT SET MEMBERS ASSOCIATION
CREATE TABLE CD_SET_MEM_ASSOC_TBL (
	SET_ID UUID NOT NULL, -- THE CONCEPT SET TO WHICH THE CONCEPT BELONGS
	CD_ID UUID NOT NULL, -- THE CONCEPT WHICH BELONGS TO THE SET.,
	CONSTRAINT PK_CD_SET_MEM_ASSOC_TBL PRIMARY KEY (SET_ID, CD_ID),
	CONSTRAINT FK_CD_SET_MEM_ASSOC_CD_SET FOREIGN KEY (SET_ID) REFERENCES CD_SET_TBL(SET_ID),
	CONSTRAINT FK_CD_SET_MEM_ASSOC_CD_ID FOREIGN KEY (CD_ID) REFERENCES CD_TBL(CD_ID)
);

CREATE INDEX CD_SET_MEM_ASSOC_CD_SET_ID_IDX ON CD_SET_MEM_ASSOC_TBL(SET_ID);
CREATE INDEX CD_SET_MEM_ASSOC_CD_ID_IDX ON CD_SET_MEM_ASSOC_TBL(CD_ID);

-- VERSION SEQUENCING
CREATE SEQUENCE CD_VRSN_SEQ START WITH 1 INCREMENT BY 1;

-- CONCEPT VERSIONS
CREATE TABLE CD_VRSN_TBL (
	CD_VRSN_ID UUID NOT NULL DEFAULT uuid_generate_v1(), 
	VRSN_SEQ_ID NUMERIC(20) NOT NULL DEFAULT (nextval('CD_VRSN_SEQ')),-- VERSION SEQUENCE
	CD_ID UUID NOT NULL, -- THE CONCEPT TO WHICH THE VERSION APPLIES
	STS_CD_ID UUID NOT NULL, -- THE STATUS OF THE CONCEPT AT THE CURRENT STATE
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE TIME THE VERSION WAS CREATED
	CRT_PROV_ID UUID NOT NULL, -- THE USER WHICH WAS RESPONSIBLE FOR THE CREATION OF THE CONCEPT VERSION
	OBSLT_UTC TIMESTAMPTZ, -- THE TIME THAT OBSOLETED THIS VERSION
	OBSLT_PROV_ID UUID, -- THE USER WHICH OBSOLETED THIS VERSION
	RPLC_VRSN_ID UUID, -- THE VERSION THAT THIS VERSION REPLACES
	CLS_ID UUID NOT NULL, -- THE CONCEPT CLASSIFICATION OF THE CONCEPT AT THE CURRENT VERSION
	MNEMONIC VARCHAR(64) NOT NULL, -- THE MNEMONIC OF THE CONCEPT AT THE CURRENT VERSION
	CONSTRAINT PK_CD_VRSN_TBL PRIMARY KEY (CD_VRSN_ID),
	CONSTRAINT FK_CD_VRSN_STAT_CD_ID FOREIGN KEY (STS_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_CD_VRSN_CD_ID FOREIGN KEY (CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_CD_VRSN_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_CD_VRSN_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_CD_VRSN_CLS_ID FOREIGN KEY (CLS_ID) REFERENCES CD_CLS_TBL(CLS_ID),
	CONSTRAINT FK_CD_VRSN_RPLC_VRSN_ID FOREIGN KEY (RPLC_VRSN_ID) REFERENCES CD_VRSN_TBL(CD_VRSN_ID),
	CONSTRAINT CK_CD_VRSN_OBSLT_PROV_ID CHECK (OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL OR OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL)
);

CREATE INDEX CD_VRSN_CD_ID_IDX ON CD_VRSN_TBL(CD_ID);
CREATE INDEX CD_VRSN_MNEMONIC_IDX ON CD_VRSN_TBL(MNEMONIC);
--DROP INDEX CD_VRSN_MNEMONIC_UQ_IDX ON CD_VRSN_TBL(MNEMONIC) WHERE OBSLT_UTC IS NULL;
CREATE UNIQUE INDEX CD_VRSN_VRSN_SEQ_IDX ON CD_VRSN_TBL(VRSN_SEQ_ID);

-- CONCEPT NAME LOCALIZATION TABLE
CREATE TABLE CD_NAME_TBL (
	NAME_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	CD_ID UUID NOT NULL, -- THE CONCEPT THAT THE NAME APPLIES TO
	EFFT_VRSN_SEQ_ID NUMERIC(20) NOT NULL, -- THE VERSION SEQUENCE WHERE THIS BECOMES EFFECTIVE
	OBSLT_VRSN_SEQ_ID NUMERIC(20), -- THE VERSION SEQUENCE WHERE THIS IS NO LONGER EFFECTIVE
	LANG_CS CHAR(2) NOT NULL, -- THE LANGUAGE CODE
	VAL VARCHAR(256) NOT NULL, -- NAME OF THE CODE
	PHON_CS VARCHAR(32), -- THE PHONETIC CODE
	PHON_ALG_ID UUID NOT NULL, -- THE PHONETIC ALGORITHM USED TO GENERATE THE CODE
	CONSTRAINT PK_CD_NAME_TBL PRIMARY KEY (NAME_ID),
	CONSTRAINT FK_CD_NAME_CD_ID FOREIGN KEY (CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_CD_NAME_EFFT_VRSN_SEQ FOREIGN KEY (EFFT_VRSN_SEQ_ID) REFERENCES CD_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_CD_NAME_OBSLT_VRSN_SEQ FOREIGN KEY (OBSLT_VRSN_SEQ_ID) REFERENCES CD_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_CD_NAME_PHON_ALG_ID FOREIGN KEY (PHON_ALG_ID) REFERENCES PHON_ALG_TBL(ALG_ID)
);

CREATE INDEX CD_NAME_VRSN_IDX ON CD_NAME_TBL(EFFT_VRSN_SEQ_ID, OBSLT_VRSN_SEQ_ID);
CREATE INDEX CD_NAME_VAL_IDX ON CD_NAME_TBL(VAL);
CREATE INDEX CD_NAME_PHON_CS_IDX ON CD_NAME_TBL(PHON_CS);
CREATE INDEX CD_NAME_CD_ID_IDX ON CD_NAME_TBL(CD_ID);

-- CODE SYSTEMS TABLE
CREATE TABLE CD_SYS_TBL (
	CS_ID UUID NOT NULL DEFAULT uuid_generate_v1(), 
	CS_NAME VARCHAR(256), -- HUMAN READABLE NAME FOR THE CODESYSTEM
	OID VARCHAR(64) NOT NULL, -- THE OID OF THE CODE SYSTEM
	DOMAIN VARCHAR(50), -- THE ASSIGNING AUTHORITY OF THE COE SYSTEM
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE TIME THAT THE CODE SYSTEM WAS CREATED
	CRT_PROV_ID UUID NOT NULL, -- THE USER IDENTIFIER THAT CREATED THE CODE SYSTEM
	OBSLT_UTC TIMESTAMPTZ, -- THE TIMESTAMP OF OBSOLETION
	OBSLT_PROV_ID UUID, -- THE USER WHO OBSOLETED
	UPD_UTC TIMESTAMPTZ, -- THE TIMESTAMP OFUPDATING
	UPD_PROV_ID UUID, -- THE USER IDENTIIFER WHO UPDATED
	URL VARCHAR(256) NOT NULL, -- THE DEFINITION URL FOR THE CODE SYSTEM
	VRSN_TXT VARCHAR(10), -- THE VERSION OF THE CODE SYSTEM AS DEFINED BY THE AUTHORITY
	DESCR TEXT, -- THE HUMAN DESCRIPTION OF THE CODE SYSTEM
	CONSTRAINT PK_CD_SYS_TBL PRIMARY KEY (CS_ID),
	CONSTRAINT FK_CD_SYS_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_CD_SYS_UPD_PROV_ID FOREIGN KEY (UPD_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_CD_SYS_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT CK_CD_SYS_OBSLT_PROV_ID CHECK (OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL OR OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL),
	CONSTRAINT CK_CD_SYS_UPD_PROV_ID CHECK (UPD_PROV_ID IS NOT NULL AND UPD_UTC IS NOT NULL OR UPD_PROV_ID IS NULL AND UPD_UTC IS NULL)

);


-- INDEX ON CODE SYSTEM
CREATE UNIQUE INDEX CD_SYS_OID_IDX ON CD_SYS_TBL(OID);
CREATE UNIQUE INDEX CD_SYS_URL_IDX ON CD_SYS_TBL(URL);

-- CONCEPT RELATIONSHIP TYPES
CREATE TABLE CD_REL_TYP_CDTBL (
	REL_TYP_ID UUID NOT NULL DEFAULT uuid_generate_v1(), 
	REL_NAME VARCHAR(50) NOT NULL, -- NAME OF THE RELATIONSHIP TYPE
	MNEMONIC VARCHAR(20) NOT NULL, -- THE UNCHANGING MNEMONIC OF THE RELATIONSHIP
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE TIME THAT THE RELATION WAS CREATED
	CRT_PROV_ID UUID NOT NULL, -- THE USER IDENTIFIER THAT CREATED THE RELATION
	OBSLT_UTC TIMESTAMPTZ, -- THE TIMESTAMP OF OBSOLETION
	OBSLT_PROV_ID UUID, -- THE USER WHO OBSOLETED
	UPD_UTC TIMESTAMPTZ, -- THE TIMESTAMP OFUPDATING
	UPD_PROV_ID UUID, -- THE USER IDENTIIFER WHO UPDATED
	CONSTRAINT PK_CD_REL_TYP_CDTBL PRIMARY KEY (REL_TYP_ID),
	CONSTRAINT FK_CD_REL_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_CD_REL_UPD_PROV_ID FOREIGN KEY (UPD_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_CD_REL_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT CK_CD_REL_OBSLT_PROV_ID CHECK (OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL OR OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL),
	CONSTRAINT CK_CD_REL_UPD_PROV_ID CHECK (UPD_PROV_ID IS NOT NULL AND UPD_UTC IS NOT NULL OR UPD_PROV_ID IS NULL AND UPD_UTC IS NULL)
	
);

CREATE INDEX CD_REL_TYP_MNEMONIC_IDX ON CD_REL_TYP_CDTBL(MNEMONIC);

INSERT INTO CD_REL_TYP_CDTBL (REL_TYP_ID, REL_NAME, MNEMONIC, CRT_PROV_ID) VALUES ('2c4dafc2-566a-41ae-9ebc-3097d7d22f4a', 'Same as', 'SameAs', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO CD_REL_TYP_CDTBL (REL_TYP_ID, REL_NAME, MNEMONIC, CRT_PROV_ID) VALUES ('ad27293d-433c-4b75-88d2-b5360cd95450', 'Inverse of', 'InverseOf', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO CD_REL_TYP_CDTBL (REL_TYP_ID, REL_NAME, MNEMONIC, CRT_PROV_ID) VALUES ('a159d45b-3c34-4e1b-9b75-9193a7528ced', 'Member of', 'MemberOf', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO CD_REL_TYP_CDTBL (REL_TYP_ID, REL_NAME, MNEMONIC, CRT_PROV_ID) VALUES ('ae8b4f2f-009f-4e0d-b35e-5a89555c5947', 'Negation of', 'NegationOf', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO CD_REL_TYP_CDTBL (REL_TYP_ID, REL_NAME, MNEMONIC, CRT_PROV_ID) VALUES ('ae8b4f2f-009f-4e0d-b35e-5a89555c5980', 'Wider-Than', 'WiderThan', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');
INSERT INTO CD_REL_TYP_CDTBL (REL_TYP_ID, REL_NAME, MNEMONIC, CRT_PROV_ID) VALUES ('ae8b4f2f-009f-4e0d-b35e-5a89555c5990', 'Narrower-Than', 'NarrowerThan', 'fadca076-3690-4a6e-af9e-f1cd68e8c7e8');

-- REFERENCE TERMS
CREATE TABLE REF_TERM_TBL (
	REF_TERM_ID UUID NOT NULL DEFAULT uuid_generate_v1(), 
	CS_ID UUID NOT NULL, -- CODE SYSTEM UUID
	MNEMONIC VARCHAR(50) NOT NULL, -- MNEMONIC OF THE REF TERM
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE TIME THAT THE REF WAS CREATED
	CRT_PROV_ID UUID NOT NULL, -- THE USER IDENTIFIER THAT CREATED THE REF
	OBSLT_UTC TIMESTAMPTZ, -- THE TIMESTAMP OF OBSOLETION
	OBSLT_PROV_ID UUID, -- THE USER WHO OBSOLETED
	UPD_UTC TIMESTAMPTZ, -- THE TIMESTAMP OFUPDATING
	UPD_PROV_ID UUID, -- THE USER IDENTIIFER WHO UPDATED
	CONSTRAINT PK_REF_TERM_TBL PRIMARY KEY (REF_TERM_ID),
	CONSTRAINT FK_REF_TERM_CS_ID FOREIGN KEY (CS_ID) REFERENCES CD_SYS_TBL(CS_ID),
	CONSTRAINT FK_REF_TERM_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_REF_TERM_UPD_PROV_ID FOREIGN KEY (UPD_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_REF_TERM_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT CK_REF_TERM_OBSLT_PROV_ID CHECK (OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL OR OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL),
	CONSTRAINT CK_REF_TERM_UPD_PROV_ID CHECK (UPD_PROV_ID IS NOT NULL AND UPD_UTC IS NOT NULL OR UPD_PROV_ID IS NULL AND UPD_UTC IS NULL)
);

CREATE INDEX CD_REF_TERM_MNEMONIC_IDX ON REF_TERM_TBL(MNEMONIC);
CREATE UNIQUE INDEX CD_REF_TERM_CS_MNEMONIC_UQ_IDX ON REF_TERM_TBL(CS_ID, MNEMONIC);

-- CONCEPT REFERENCE TERM ASSOCIATION
CREATE TABLE CD_REF_TERM_ASSOC_TBL (
	CD_REF_TERM_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	REF_TERM_ID UUID NOT NULL, -- THE REFERENCE TERM PART OF THIS RELATIONSHIP
	CD_ID UUID NOT NULL, -- THE CONCEPT DEFINITION IDENTIFIER
	EFFT_VRSN_SEQ_ID NUMERIC(20) NOT NULL, -- THE VERSION AT WHICH THE REFERENCE TERM RELATIONSHIP BECAME ACTIVE
	OBSLT_VRSN_SEQ_ID NUMERIC(20), -- THE VERSION AT WHICH THE REFERENCE TERM IS NO LONGER ACTIVE
	REL_TYP_ID UUID NOT NULL, -- THE RELATIONSHIP TYPE IDENTIFIER
	CONSTRAINT PK_CD_REF_TERM_ASSOC_TBL PRIMARY KEY (CD_REF_TERM_ID),
	CONSTRAINT FK_CD_REF_TERM_ASSOC_REF_TERM_ID FOREIGN KEY (REF_TERM_ID) REFERENCES REF_TERM_TBL(REF_TERM_ID),
	CONSTRAINT FK_CD_REF_TERM_ASSOC_CD_ID FOREIGN KEY (CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_CD_REF_TERM_ASSOC_EFFT_VRSN_SEQ_ID FOREIGN KEY (EFFT_VRSN_SEQ_ID) REFERENCES CD_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_CD_REF_TERM_ASSOC_OBSLT_VRSN_SEQ_ID FOREIGN KEY (OBSLT_VRSN_SEQ_ID) REFERENCES CD_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_CD_REF_TERM_ASSOC_REL_TYP_ID FOREIGN KEY (REL_TYP_ID) REFERENCES CD_REL_TYP_CdTBL(REL_TYP_ID)
);

CREATE INDEX CD_REF_TERM_ASSOC_CD_ID_IDX ON CD_REF_TERM_ASSOC_TBL(CD_ID);
CREATE INDEX CD_REF_TERM_ASSOC_VRSN_IDX ON CD_REF_TERM_ASSOC_TBL(EFFT_VRSN_SEQ_ID, OBSLT_VRSN_SEQ_ID);

-- REFERENCE TERM DISPLAY NAMES 
CREATE TABLE REF_TERM_NAME_TBL (
	REF_TERM_NAME_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	REF_TERM_ID UUID NOT NULL, -- THE REFERENCE TERM ID TO WHICH THE NAME APPLIES
	LANG_CS CHAR(2) NOT NULL, -- THE ISO LANGUAGE CODE FOR WHICH THE NAME APPLIES
	TERM_NAME VARCHAR(256) NOT NULL, -- THE NAME TO BE USED
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE TIME THE NAME WAS CREATED
	CRT_PROV_ID UUID NOT NULL, -- THE USER WHICH WAS RESPONSIBLE FOR THE CREATION OF THE NAME
	OBSLT_UTC TIMESTAMPTZ, -- THE TIME THAT OBSOLETED THIS NAME
	OBSLT_PROV_ID UUID, -- THE USER WHICH OBSOLETED THIS NAME
	OBSLT_RSN TEXT, -- THE REASON THAT THE TERM NAME WAS OBSOLETED
	PHON_CS VARCHAR(20), -- THE PHONETIC CODE FOR THE NAME
	PHON_ALG_ID UUID NOT NULL, -- THE PHONETIC ALGORITHM FOR THE NAME
	CONSTRAINT PK_REF_TERM_NAME_TBL PRIMARY KEY (REF_TERM_NAME_ID),
	CONSTRAINT FK_REF_TERM_NAME_REF_TERM_ID FOREIGN KEY (REF_TERM_ID) REFERENCES REF_TERM_TBL(REF_TERM_ID),
	CONSTRAINT FK_REF_TERM_NAME_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_REF_TERM_NAME_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT CK_REF_TERM_NAME_OBSLT_PROV_ID CHECK (OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL OR OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL)
);

-- INDEX OF REF TERM NAMES
CREATE INDEX REF_TERM_NAME_PHON_CS_IDX ON REF_TERM_NAME_TBL(PHON_CS);
CREATE INDEX REF_TERM_NAME_TERM_NAME_IDX ON REF_TERM_NAME_TBL(TERM_NAME);

-- REFERENCE TERM RELATIONSHIP TABLE
CREATE TABLE CD_REL_ASSOC_TBL (
	CD_REL_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	SRC_CD_ID UUID NOT NULL, -- THE SOURCE OF THE RELATIONSHIP
	TRG_CD_ID UUID NOT NULL, -- THE TARGET OF THE RELATIONSHIP
	REL_TYP_ID UUID NOT NULL, -- THE TYPE OF RELATIONSHIP
	EFFT_VRSN_SEQ_ID NUMERIC(20) NOT NULL, -- THE VERSION AT WHICH THE RELATIONSHIP BECOMES ACTIVE
	OBSLT_VRSN_SEQ_ID NUMERIC(20), -- THE VERSION AT WHICH THE RELATIONSHIP IS NO LONGER ACTIVE
	CONSTRAINT PK_CD_REL_ASSOC_TBL PRIMARY KEY (CD_REL_ID),
	CONSTRAINT FK_CD_REL_ASSOC_SRC_CD_ID FOREIGN KEY (SRC_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_CD_REL_ASSOC_TRG_CD_ID FOREIGN KEY (TRG_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_CD_REL_ASSOC_REL_TYP_ID FOREIGN KEY (REL_TYP_ID) REFERENCES CD_REL_TYP_CDTBL(REL_TYP_ID),
	CONSTRAINT FK_CD_REL_ASSOC_EFFT_VRSN_SEQ_ID FOREIGN KEY (EFFT_VRSN_SEQ_ID) REFERENCES CD_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_CD_REL_ASSOC_OBSLT_VRSN_SEQ_ID FOREIGN KEY (OBSLT_VRSN_SEQ_ID) REFERENCES CD_VRSN_TBL(VRSN_SEQ_ID)
);

-- INDEX FOR RELATIONSHIP
CREATE INDEX CD_REL_ASSOC_VRSN_IDX ON CD_REL_ASSOC_TBL(EFFT_VRSN_SEQ_ID, OBSLT_VRSN_SEQ_ID);
CREATE INDEX CD_REL_ASSOC_SRC_ID_IDX ON CD_REL_ASSOC_TBL(SRC_CD_ID);
CREATE INDEX CD_REL_ASSOC_TRG_ID_IDX ON CD_REL_ASSOC_TBL(TRG_CD_ID);

-- CURRENT CONCEPT VERSION VIEW
CREATE VIEW CD_CUR_VRSN_VW AS
	SELECT CD_VRSN_TBL.*, CD_TBL.IS_SYS, CD_CLS_TBL.MNEMONIC AS CLS_MNEMONIC 
	FROM CD_VRSN_TBL INNER JOIN CD_TBL USING (CD_ID)
		INNER JOIN CD_CLS_TBL USING (CLS_ID)
		WHERE CD_VRSN_TBL.OBSLT_UTC IS NULL;

-- CONCEPT SET MEMBERS VIEW
CREATE VIEW CD_SET_MEM_VW AS
	SELECT CD_SET_TBL.SET_ID, CD_SET_TBL.MNEMONIC AS SET_MNEMONIC, CD_CUR_VRSN_VW.CD_ID, CD_CUR_VRSN_VW.CD_VRSN_ID, CD_CUR_VRSN_VW.MNEMONIC AS CD_MNEMONIC, CD_CUR_VRSN_VW.CLS_MNEMONIC
	FROM CD_SET_MEM_ASSOC_TBL INNER JOIN CD_SET_TBL USING (SET_ID) 
	INNER JOIN CD_CUR_VRSN_VW USING(CD_ID);

-- ASSERT A CONCEPT HAS A PARTICULAR CLASSIFIER
-- @RETURN : TRUE IF THE CLASS CARRIES THE SPECIIFED CLASSIFICATION
-- @PARAM CD_ID_IN : THE UUID OF THE CONCEPT 
-- @PARAM CLS_MNEMONIC_IN : THE CLASS TO ASSERT
CREATE OR REPLACE FUNCTION ASSRT_CD_CLS(
	CD_ID_IN IN UUID,
	CLS_MNEMONIC_IN IN VARCHAR(32)
) RETURNS BOOLEAN AS
$$
BEGIN
	RETURN (SELECT COUNT(*) FROM CD_VRSN_TBL INNER JOIN CD_CLS_TBL USING (CLS_ID) WHERE CD_ID = CD_ID_IN AND (CD_CLS_TBL.MNEMONIC = CLS_MNEMONIC_IN OR
	-- CAN ALSO BE A NuLL REASON
	 CD_CLS_TBL.CLS_ID = '05ac7b93-1b1e-47dd-87dd-e56e353ecb94')) > 0;
END;
$$ LANGUAGE PLPGSQL;

-- ASSERT THAT A CONCEPT HAS A SET MEMBER
-- @RETURN : TRUE IF THE CONCEPT SET CONTAINS THE CONCEPT
-- @PARAM CD_ID_IN : THE UUID FO THE CONCEPT
-- @PARAM SET_MNEMONIC_IN : THE NAME OF THE CONCEPT SET TO TEST
CREATE OR REPLACE FUNCTION IS_CD_SET_MEM(
	CD_ID_IN IN UUID,
	SET_MNEMONIC_IN IN VARCHAR(32)
) RETURNS BOOLEAN AS 
$$
BEGIN
	RETURN (SELECT COUNT(*) FROM CD_SET_MEM_ASSOC_TBL INNER JOIN CD_SET_TBL USING(SET_ID) WHERE CD_ID = CD_ID_IN AND (MNEMONIC = SET_MNEMONIC_IN OR SET_ID = '51925f69-14a3-4516-bb2c-e2280a4f3065')) > 0;
END;
$$ LANGUAGE PLPGSQL;

-- CONSTRAINT CHECK FOR CONCEPT SETS
ALTER TABLE CD_VRSN_TBL ADD CONSTRAINT CK_CD_VRSN_STS_CD_ID CHECK (IS_CD_SET_MEM(STS_CD_ID, 'ConceptStatus'));

-- EXTENSION TYPE REGISTRY
CREATE TABLE EXT_TYP_TBL (
	EXT_TYP_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	HDLR_CLS VARCHAR(256) NOT NULL, -- THE EXTENSION HANDLER WHICH HANDLES (SERIALIZES) THIS TYPE OF EXTENSION
	EXT_NAME VARCHAR(128) NOT NULL, -- THE HUMAN NAME OF THE EXTENSION
	IS_ACTIVE BOOLEAN NOT NULL DEFAULT TRUE, -- TRUE IF THE EXTENSION REGISTRATION IS ACTIVE
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE CREATION TIME OF THE EXTENSION TYPE
	CRT_PROV_ID UUID NOT NULL, -- THE USER WHO CREATED THE EXTENSION REGISTRATION
	UPD_UTC TIMESTAMPTZ, -- THE TIME THAT THE EXTENSION TYPE WAS UPDATED
	UPD_PROV_ID UUID, -- THE USER WHICH UPDATED THE EXTENSION TYPE
	OBSLT_UTC TIMESTAMPTZ, -- THE TIME WHEN THE EXTENSION WAS OBSOLETED
	OBSLT_PROV_ID UUID, -- THE USER WHICH OBSOLETED THE EXTENSION TYPE
	CONSTRAINT PK_EXT_TYP_TBL PRIMARY KEY (EXT_TYP_ID),
	CONSTRAINT FK_EXT_TYP_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_EXT_TYP_UPD_PROV_ID FOREIGN KEY (UPD_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_EXT_TYP_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT CK_EXT_TYP_OBSLT_PROV_ID CHECK (OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL OR OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL),
	CONSTRAINT CK_EXT_TYP_UPD_PROV_ID CHECK (UPD_PROV_ID IS NOT NULL AND UPD_UTC IS NOT NULL OR UPD_PROV_ID IS NULL AND UPD_UTC IS NULL)
);

-- INDEX ON EXTENSION TYPE
CREATE UNIQUE INDEX EXT_TYP_NAME_IDX ON EXT_TYP_TBL(EXT_NAME);

-- ASSIGNING AUTHORITY
CREATE TABLE ASGN_AUT_TBL (
	AUT_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	AUT_NAME VARCHAR(50) NOT NULL, -- THE NAME OF THE ASSIGNING AUTHORITY
	OID VARCHAR(256) NOT NULL, -- THE OID OF THE ASSIGNING AUTHORTIY
	NSID VARCHAR(32) NOT NULL, -- THE HL7 V2 CX.4 ASSIGNING AUTHORITY DOMAIN
	URL VARCHAR(250), -- THE URL OF THE ASSINGING AUTHORITY DEFINITION
	APP_ID UUID, -- APPLICATION IDENTIFIER OF A DEVICE THAT IS PERMITTED TO ASSIGN IDS
	DESCR TEXT, -- THE DESCRIPTION OF THE AUTHORITY
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE TIME THAT THE AA WAS CREATED
	CRT_PROV_ID UUID NOT NULL, -- THE USER WHICH CREATED THE AA
	OBSLT_UTC TIMESTAMPTZ, -- THE TIME THAT THE AA WAS OBSOLETED
	OBSLT_PROV_ID UUID, -- THE USER WHICH OBSOLETED THE AA
	VAL_RGX VARCHAR(64), -- REGULAR EXPRESSION FOR VALIDATION
	IS_UNQ BOOLEAN NOT NULL DEFAULT FALSE, -- TRUE IF THE ASSIGNING AUTHORITY IS UNIQUE
	CONSTRAINT PK_ASGN_AUT_TBL PRIMARY KEY (AUT_ID),
	CONSTRAINT FK_ASGN_AUT_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_ASGN_AUT_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT CK_ASGN_AUT_OBSLT_PROV_ID CHECK (OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL OR OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL),
	CONSTRAINT FK_ASGN_AUT_APP_ID FOREIGN KEY (APP_ID) REFERENCES SEC_APP_TBL(APP_ID)
);

CREATE UNIQUE INDEX ASGN_AUT_NAME_IDX ON ASGN_AUT_TBL(NSID);
CREATE UNIQUE INDEX ASGN_AUT_OID_IDX ON ASGN_AUT_TBL(OID);

-- IDENTIFIES SCOPES TO WHICH AN AA APPLIES
CREATE TABLE ASGN_AUT_SCP_TBL (
	AUT_ID UUID NOT NULL, -- THE AA TO WHICH THE SCOPE APPLIES
	CD_ID UUID NOT NULL, -- THE UUID FOR THE CLASS WHICH DESCRIBES THE SCOPE
	CONSTRAINT PK_ASGN_AUT_SCP_TBL PRIMARY KEY (AUT_ID, CD_ID),
	CONSTRAINT FK_ASGN_AUT_SCP_AUT_ID FOREIGN KEY (AUT_ID) REFERENCES ASGN_AUT_TBL(AUT_ID),
	CONSTRAINT FK_ASGN_AUT_SCP_CD_ID FOREIGN KEY (CD_ID) REFERENCES CD_TBL(CD_ID)
);

-- IDENTIFIER TYPES
CREATE TABLE ID_TYP_TBL (
	ID_TYP_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	TYP_CD_ID UUID NOT NULL, -- THE TYPE OF IDENTIFIER
	ENT_SCP_CD_ID UUID NOT NULL, -- THE SCOPE IN WHICH THE IDENTIFIER TYPE CAN BE USED
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE TIME THAT THE AA WAS CREATED
	CRT_PROV_ID UUID NOT NULL, -- THE USER WHICH CREATED THE AA
	OBSLT_UTC TIMESTAMPTZ, -- THE TIME THAT THE AA WAS OBSOLETED
	OBSLT_PROV_ID UUID, -- THE USER WHICH OBSOLETED THE AA
	CONSTRAINT PK_ID_TYP_TBL PRIMARY KEY (ID_TYP_ID),
	CONSTRAINT FK_ID_TYP_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_ID_TYP_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT CK_ID_TYP_OBSLT_PROV_ID CHECK (OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL OR OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL),
	CONSTRAINT FK_ID_TYP_TYP_CD_ID FOREIGN KEY (TYP_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_ID_TYP_ENT_SCP_CD_ID FOREIGN KEY (ENT_SCP_CD_ID) REFERENCES CD_TBL(CD_ID)
);

-- TEMPLATE DEFINITION TABLE
CREATE TABLE TPL_DEF_TBL (
	TPL_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	OID VARCHAR(64), -- THE OID OF THE TEMPLATE DEFINITION
	MNEMONIC VARCHAR(64) NOT NULL, -- THE MNEMONIC FOR THE TEMPLATE DEFINITION
	TPL_NAME VARCHAR(128), -- THE HUMAN READABLE NAME FOR THE TEMPLATE DEFINITION
	DESCR TEXT, -- A DESCRIPTION OF THE TEMPLATE
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE CREATION TIME OF THE EXTENSION TYPE
	CRT_PROV_ID UUID NOT NULL, -- THE USER WHO CREATED THE EXTENSION REGISTRATION
	UPD_UTC TIMESTAMPTZ, -- THE TIME THAT THE EXTENSION TYPE WAS UPDATED
	UPD_PROV_ID UUID, -- THE USER WHICH UPDATED THE EXTENSION TYPE
	OBSLT_UTC TIMESTAMPTZ, -- THE TIME WHEN THE EXTENSION WAS OBSOLETED
	OBSLT_PROV_ID UUID, -- THE USER WHICH OBSOLETED THE EXTENSION TYPE
	CONSTRAINT PK_TPL_DEF_TBL PRIMARY KEY (TPL_ID),
	CONSTRAINT FK_TPL_DEF_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_TPL_DEF_UPD_PROV_ID FOREIGN KEY (UPD_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_TPL_DEF_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT CK_TPL_DEF_OBSLT_PROV_ID CHECK (OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL OR OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL),
	CONSTRAINT CK_TPL_DEF_UPD_PROV_ID CHECK (UPD_PROV_ID IS NOT NULL AND UPD_UTC IS NOT NULL OR UPD_PROV_ID IS NULL AND UPD_UTC IS NULL)
);

CREATE UNIQUE INDEX TPL_DEF_OID_IDX ON TPL_DEF_TBL(OID);
CREATE UNIQUE INDEX TPL_DEF_MNEMONIC_IDX ON TPL_DEF_TBL(MNEMONIC);

-- CREATE ACT TABLE
CREATE TABLE ACT_TBL (
	ACT_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	TPL_ID UUID, -- IDENTIFIES THE TEMPLATE WHICH THIS ACT FOLLOWS
	CLS_CD_ID UUID NOT NULL, -- CLASSIFIES THE TYPE OF ACT
	MOD_CD_ID UUID NOT NULL, -- IDENTIIFES THE MOOD OF THE ACT
	CONSTRAINT PK_ACT PRIMARY KEY (ACT_ID),
	CONSTRAINT FK_ACT_CLS_CD_ID FOREIGN KEY (CLS_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_ACT_MOD_CD_ID FOREIGN KEY (MOD_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT CK_ACT_CLS_CD CHECK (IS_CD_SET_MEM(CLS_CD_ID, 'ActClass')),
	CONSTRAINT CK_ACT_MOD_CD CHECK (IS_CD_SET_MEM(MOD_CD_ID, 'ActMood')),
	CONSTRAINT FK_ACT_TPL_ID FOREIGN KEY (TPL_ID) REFERENCES TPL_DEF_TBL(TPL_ID)
);

-- INDEXING
CREATE INDEX ACT_CLS_CD_IDX ON ACT_TBL(CLS_CD_ID);

-- ACT VERSION SEQUENCE
CREATE SEQUENCE ACT_VRSN_SEQ START WITH 1 INCREMENT BY 1;

-- ACT VERSION TABLE
CREATE TABLE ACT_VRSN_TBL (
	ACT_VRSN_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	VRSN_SEQ_ID NUMERIC(20) NOT NULL DEFAULT nextval('ACT_VRSN_SEQ'), -- THE VERSION SEQUENCE
	ACT_ID UUID NOT NULL, -- THE ACT IDENTIFIER TO WHICH THIS VERSION APPLIES
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE TIME THAT HTE VERSION WAS CREATED
	CRT_PROV_ID UUID NOT NULL, -- THE USER WHICH WAS RESPONSIBLE FOR THE CREATION OF THE VERSION
	OBSLT_UTC TIMESTAMPTZ, -- THE TIME WHEN THE ACT VERSION BECOMES OBSOLETE
	OBSLT_PROV_ID UUID, -- THE USER WHICH OBSOLETED THE ACT VERSION
	OBSLT_RSN TEXT, -- THE REASON WHY THE VERSION WSA OBSOLETED
	RPLC_VRSN_ID UUID, -- THE UUID OF THE VERSION THAT THIS VERISON REPLACE
	NEG_IND BOOLEAN NOT NULL DEFAULT FALSE, -- TRUE IF THE ACT NEVER OCCURRED
	TYP_CD_ID UUID, -- THE TYPE CONCEPT OF THE ACT AT THIS VERSION
	STS_CD_ID UUID NOT NULL, -- THE STATUS OF THE ACT AS OF THIS VERSION
	RSN_CD_ID UUID, -- THE REASON OF THE ACT TO OCCUR
	ACT_UTC TIMESTAMPTZ, -- THE TIME THE ACT OCCURRED
	ACT_START_UTC TIMESTAMPTZ, -- THE TIME THE ACT STARTED OR WAS TO START
	ACT_STOP_UTC TIMESTAMPTZ, -- THE TIME THAT THE ACT STOPPED TO WAS TO STOP
	CONSTRAINT PK_ACT_VRSN_TBL PRIMARY KEY (ACT_VRSN_ID),
	CONSTRAINT FK_ACT_VRSN_ACT FOREIGN KEY (ACT_ID) REFERENCES ACT_TBL(ACT_ID),
	CONSTRAINT FK_ACT_VRSN_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_ACT_VRSN_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_ACT_VRSN_RPLC_VRSN_ID FOREIGN KEY (RPLC_VRSN_ID) REFERENCES ACT_VRSN_TBL(ACT_VRSN_ID),
	CONSTRAINT FK_ACT_VRSN_TYP_CD_ID FOREIGN KEY (TYP_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_ACT_VRSN_RSN_CD_ID FOREIGN KEY (RSN_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_ACT_VRSN_STS_CD_ID FOREIGN KEY (STS_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT CK_ACT_VRSN_STS_CD CHECK (IS_CD_SET_MEM(STS_CD_ID, 'ActStatus')),
	CONSTRAINT CK_ACT_VRSN_RSN_CD CHECK (RSN_CD_ID IS NULL OR IS_CD_SET_MEM(RSN_CD_ID, 'ActReason') OR IS_CD_SET_MEM(RSN_CD_ID, 'NullReason')),
	CONSTRAINT CK_ACT_VRSN_OBSLT_PROV_ID CHECK(OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL OR OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL),
	CONSTRAINT CK_ACT_VRSN_ACT_UTC CHECK(ACT_UTC IS NOT NULL OR ACT_START_UTC IS NOT NULL OR ACT_STOP_UTC IS NOT NULL) -- CHECK: ONE OF ACT TIME, START, OR END MUST BE PROVIDED
);

-- INDEXING FOR ACTS
CREATE UNIQUE INDEX ACT_VRSN_VRSN_SEQ_ID_IDX ON ACT_VRSN_TBL(VRSN_SEQ_ID);
CREATE INDEX ACT_VRSN_ACT_ID_IDX ON ACT_VRSN_TBL(ACT_ID);
CREATE INDEX ACT_VRSN_TYP_CD_ID_IDX ON ACT_VRSN_TBL(TYP_CD_ID);

-- IDENTIFIERS FOR ACTS
CREATE TABLE ACT_ID_TBL (
	ACT_ID_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	ID_TYP_ID UUID, -- THE TYPE OF IDENTIFIER 
	ACT_ID UUID NOT NULL, -- THE IDENTIFIER OF THE ACT
	EFFT_VRSN_SEQ_ID NUMERIC(20) NOT NULL, -- THE VERSION AT WHICH TIME THIS IDENTIIFER BECAME ACTIVE
	OBSLT_VRSN_SEQ_ID NUMERIC(20), -- THE VERSION SEQUENCE AT WHICH THE IDENTIFIER WAS NO LONGER ACTIVE
	AUT_ID UUID NOT NULL, -- THE ASSIGNING AUTHORITY OF THE IDENTIFIER
	ID_VAL VARCHAR(64) NOT NULL, -- THE VALUE OF THE IDENTIFIER
	CONSTRAINT PK_ACT_ID_TBL PRIMARY KEY(ACT_ID_ID),
	CONSTRAINT FK_ACT_ID_ACT_ID FOREIGN KEY (ACT_ID) REFERENCES ACT_TBL(ACT_ID),
	CONSTRAINT FK_ACT_ID_ID_TYP_ID FOREIGN KEY (ID_TYP_ID) REFERENCES ID_TYP_TBL(ID_TYP_ID),
	CONSTRAINT FK_ACT_ID_EFFT_VRSN_SEQ_ID FOREIGN KEY (EFFT_VRSN_SEQ_ID) REFERENCES ACT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ACT_ID_OBSLT_VRSN_SEQ_ID FOREIGN KEY (OBSLT_VRSN_SEQ_ID) REFERENCES ACT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ACT_ID_AUT_ID FOREIGN KEY (AUT_ID) REFERENCES ASGN_AUT_TBL(AUT_ID)
);

-- INDEXING FO RTHE ID TABLE
CREATE INDEX ACT_ID_ACT_ID_IDX ON ACT_ID_TBL(ACT_ID);
CREATE INDEX ACT_ID_VRSN_IDX ON ACT_ID_TBL(EFFT_VRSN_SEQ_ID, OBSLT_VRSN_SEQ_ID);

-- ACT RELATIONSHIPS
CREATE TABLE ACT_REL_TBL (
	REL_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	SRC_ACT_ID UUID NOT NULL, -- THE SOURCE ACT
	TRG_ACT_ID UUID NOT NULL, -- THE TARGET ACT
	EFFT_VRSN_SEQ_ID NUMERIC(20) NOT NULL, -- EFFECTIVE VERSION OF THE RELATIONSHIP
	OBSLT_VRSN_SEQ_ID NUMERIC(20), -- THE OBSOLETION VERSION OF THE RELATIONSHIP
	REL_TYP_CD_ID UUID NOT NULL, -- THE RELATIONSHIP TYPE CONCEPT
	CONSTRAINT PK_ACT_REL_TBL PRIMARY KEY (REL_ID),
	CONSTRAINT FK_ACT_REL_SRC_ACT_ID FOREIGN KEY (SRC_ACT_ID) REFERENCES ACT_TBL(ACT_ID),
	CONSTRAINT FK_ACT_REL_TRG_ACT_ID FOREIGN KEY (TRG_ACT_ID) REFERENCES ACT_TBL(ACT_ID),
	CONSTRAINT FK_ACT_REL_EFFT_VRSN_SEQ_ID FOREIGN KEY (EFFT_VRSN_SEQ_ID) REFERENCES ACT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ACT_REL_OBSLT_VRSN_SEQ_ID FOREIGN KEY (OBSLT_VRSN_SEQ_ID) REFERENCES ACT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ACT_REL_REL_TYP_CD_ID FOREIGN KEY (REL_TYP_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_ACT_REL_REL_TYP_CD CHECK (IS_CD_SET_MEM(REL_TYP_CD_ID, 'ActRelationshipType'))
);

CREATE INDEX ACT_REL_SRC_ACT_ID_IDX ON ACT_REL_TBL(SRC_ACT_ID);
CREATE INDEX ACT_REL_TRG_ACT_ID_IDX ON ACT_REL_TBL(TRG_ACT_ID);
CREATE INDEX ACT_REL_VRSN_IDX ON ACT_REL_TBL(EFFT_VRSN_SEQ_ID, OBSLT_VRSN_SEQ_ID);

-- ACT EXTENSIONS TABLE
CREATE TABLE ACT_EXT_TBL (
	ACT_EXT_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	ACT_ID UUID NOT NULL, -- THE ACT TO WHICH THE EXTENSION APPLIES
	EXT_TYP_ID UUID NOT NULL, -- THE TYPE OF EXTENSION
	EXT_VAL BYTEA, -- THE SERIALIZED EXTENSION VALUE
	EXT_DISP VARCHAR(64), -- THE DISPLAY (HUMAN) VERSION OF THE EXTENSION
	EFFT_VRSN_SEQ_ID NUMERIC(20) NOT NULL, -- THE VERSION AT WHICH THE EXTENSION IS ACTIVE
	OBSLT_VRSN_SEQ_ID NUMERIC(20), -- THE VERSION AT WHICH THE EXTENSION IS NOT ACTIVE
	CONSTRAINT PK_ACT_EXT_TBL PRIMARY KEY (ACT_EXT_ID), 
	CONSTRAINT FK_ACT_EXT_ACT_ID FOREIGN KEY (ACT_ID) REFERENCES ACT_TBL(ACT_ID),
	CONSTRAINT FK_ACT_EXT_EFFT_VRSN_SEQ_ID FOREIGN KEY (EFFT_VRSN_SEQ_ID) REFERENCES ACT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ACT_EXT_OBSLT_VRSN_SEQ_ID FOREIGN KEY (OBSLT_VRSN_SEQ_ID) REFERENCES ACT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ACT_EXT_EXT_TYP_ID FOREIGN KEY (EXT_TYP_ID) REFERENCES EXT_TYP_TBL(EXT_TYP_ID)
);

CREATE INDEX ACT_EXT_VRSN_IDX ON ACT_EXT_TBL(EFFT_VRSN_SEQ_ID, OBSLT_VRSN_SEQ_ID);
CREATE INDEX ACT_EXT_ACT_ID ON ACT_EXT_TBL(ACT_ID);

-- CONTROL ACT TABLE
CREATE TABLE CNTRL_ACT_TBL (
	ACT_VRSN_ID UUID NOT NULL, -- THE LINK TO THE ACT WHICH IS A CONTROL ACT
	CONSTRAINT PK_CNTRL_ACT_TBL PRIMARY KEY (ACT_VRSN_ID),
	CONSTRAINT FK_CNTRL_ACT_ACT_VRSN_ID FOREIGN KEY (ACT_VRSN_ID) REFERENCES ACT_VRSN_TBL(ACT_VRSN_ID)
);

-- OBSERVATION TABLE
CREATE TABLE OBS_TBL (
	ACT_VRSN_ID UUID NOT NULL, -- THE VERSION TO WHICH THIS OBSERVATION DATA APPLIES
	INT_CD_ID UUID, -- THE INTERPRETATION CODE OF THE OBSERVATION
	VAL_TYP VARCHAR(2) NOT NULL CHECK (VAL_TYP IN ('PQ','ST','CD')), -- THE TYPE OF VALUE
	CONSTRAINT PK_OBS_TBL PRIMARY KEY (ACT_VRSN_ID),
	CONSTRAINT FK_OBS_ACT_VRSN_ID FOREIGN KEY (ACT_VRSN_ID) REFERENCES ACT_VRSN_TBL(ACT_VRSN_ID),
	CONSTRAINT FK_OBS_INT_CD_ID FOREIGN KEY (INT_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT CK_OBS_INT_CD CHECK (INT_CD_ID IS NULL OR IS_CD_SET_MEM(INT_CD_ID, 'ActInterpretation'))
);

-- OBSERVATION VALUE TYPE INDEx
CREATE INDEX OBS_VAL_TYP_IDX ON OBS_TBL(VAL_TYP);

-- QUANTITY OBSERVATION TABLE
CREATE TABLE QTY_OBS_TBL (
	ACT_VRSN_ID UUID NOT NULL, -- THE VERSION TO WHICH THE OBSERVATION DATA APLIES
	QTY DECIMAL NOT NULL, -- THE QUANTITY ITSELF
	QTY_PRC NUMERIC(2), -- THE PRECISION OF THE OBSERVED VALUES
	UOM_CD_ID UUID NOT NULL, -- THE UNIT OF MEASURE OF THE QUANTITY
	CONSTRAINT PK_QTY_OBS_TBL PRIMARY KEY (ACT_VRSN_ID),
	CONSTRAINT FK_QTY_OBS_ACT_VRSN_ID FOREIGN KEY (ACT_VRSN_ID) REFERENCES OBS_TBL(ACT_VRSN_ID),
	CONSTRAINT FK_QTY_OBS_UOM_CD_ID FOREIGN KEY (UOM_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT CK_QTY_OBS_UOM_CD CHECK (ASSRT_CD_CLS(UOM_CD_ID, 'UnitOfMeasure'))
);

-- CODIFIED OBSERVATION TABLE
CREATE TABLE CD_OBS_TBL (
	ACT_VRSN_ID UUID NOT NULL, -- THE VERSION TO WHICH THE OBSERVATION DTA APPLIES
	VAL_CD_ID UUID NOT NULL, -- THE CONCEPT WHICH REPRESENTS THE VALUE
	CONSTRAINT PK_CD_OBS_TBL PRIMARY KEY (ACT_VRSN_ID),
	CONSTRAINT FK_CD_OBS_ACT_VRSN_ID FOREIGN KEY (ACT_VRSN_ID) REFERENCES OBS_TBL(ACT_VRSN_ID),
	CONSTRAINT FK_CD_OBS_VAL_CD_ID FOREIGN KEY (VAL_CD_ID) REFERENCES CD_TBL(CD_ID)
);

-- TEXT OBSERVATION
CREATE TABLE TXT_OBS_TBL (
	ACT_VRSN_ID UUID NOT NULL, -- THE VERSION TO WHICH THE TEXT DATA APPLIES
	OBS_VAL TEXT NOT NULL, -- THE OBSERVATION VALUE 
	CONSTRAINT PK_TXT_OBS_TBL PRIMARY KEY (ACT_VRSN_ID),
	CONSTRAINT FK_TXT_OBS_ACT_VRSN_ID FOREIGN KEY (ACT_VRSN_ID) REFERENCES OBS_TBL(ACT_VRSN_ID)
);

-- PATIENT ENCOUNTER
CREATE TABLE PAT_ENC_TBL (
	ACT_VRSN_ID UUID NOT NULL, -- THE VERSION TO WHICH THE ENCOUNTER DATA APPLIES
	DSCH_DSP_CD_ID UUID, -- THE DISCHARGE DISPOSITION IF KNOWN
	CONSTRAINT PK_PAT_ENC_TBL PRIMARY KEY (ACT_VRSN_ID),
	CONSTRAINT FK_PAT_ENC_ACT_VRSN_ID FOREIGN KEY (ACT_VRSN_ID) REFERENCES ACT_VRSN_TBL(ACT_VRSN_ID),
	CONSTRAINT FK_PAT_ENC_DSCH_DSP_CD_ID FOREIGN KEY (DSCH_DSP_CD_ID) REFERENCES CD_TBL(CD_ID)
);

-- SUBBSTANCE ADMINISTRATION
CREATE TABLE SUB_ADM_TBL (
	ACT_VRSN_ID UUID NOT NULL, -- THE VERSION TO WHICH THE SUBSTANCE ADMINISTRATION DATA APPLIES
	STE_CD_ID UUID, -- THE SITE OF ADMINISTRATION
	RTE_CD_ID UUID NOT NULL DEFAULT '8ba48d37-6c86-4a54-9a2f-e3a1dad2e6a2', -- THE ROUTE OF ADMINISTRATION
	DOS_QTY DECIMAL NOT NULL, -- THE AMOUNT ADMINISTERED
	DOS_UNT_CD_ID UUID NOT NULL, -- THE DOSE UOM CODE
	SEQ_ID INT, -- THE SEQUENCE CODE OF THE DOSE IF GIVEN AS PART OF A DOSE
	CONSTRAINT PK_SUB_ADM_TBL PRIMARY KEY (ACT_VRSN_ID),
	CONSTRAINT FK_SUB_ADM_ACT_VRSN_ID FOREIGN KEY (ACT_VRSN_ID) REFERENCES ACT_VRSN_TBL(ACT_VRSN_ID),
	CONSTRAINT FK_SUB_ADM_STE_CD_ID FOREIGN KEY (STE_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_SUB_ADM_RTE_CD_ID FOREIGN KEY (RTE_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT CK_SUB_ADM_RTE_CD CHECK (ASSRT_CD_CLS(RTE_CD_ID, 'Route')),
	CONSTRAINT FK_SUB_ADM_DOS_UNT_CD_ID FOREIGN KEY (DOS_UNT_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT CK_SUB_ADM_DOS_UNT_CD CHECK (ASSRT_CD_CLS(DOS_UNT_CD_ID, 'UnitOfMeasure'))
);

-- ACT TAG
CREATE TABLE ACT_TAG_TBL (
	TAG_ID UUID NOT NULL DEFAULT uuid_generate_v1(), 
	ACT_ID UUID NOT NULL, -- THE ACT TO WHICH THE TAG APPLIES
	TAG_NAME VARCHAR(64) NOT NULL, -- THE NAME OF THE TAG
	TAG_VALUE TEXT, -- THE VALUE OF THE TAG
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE TIME THE TAG WAS ATTACHED TO THE ACT
	CRT_PROV_ID UUID NOT NULL, -- THE USER WHICH IS RESPONSIBLE FOR THE CREATION OF THE ACT TAG
	OBSLT_UTC TIMESTAMPTZ, -- THE TIME THAT THE TAG NO LONGER APPLIES TO THE OBJECT
	OBSLT_PROV_ID UUID, -- THE USER THAT OBSOLETED THE TAG
	CONSTRAINT PK_ACT_TAG_TBL PRIMARY KEY (TAG_ID),
	CONSTRAINT FK_ACT_TAG_ACT_ID FOREIGN KEY (ACT_ID) REFERENCES ACT_TBL(ACT_ID),
	CONSTRAINT FK_ACT_TAG_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_ACT_TAG_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT CK_ACT_TAG_OBSLT_USR CHECK (OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL OR OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL)
);

CREATE INDEX ACT_TAG_TAG_NAME_IDX ON ACT_TAG_TBL(TAG_NAME);
CREATE INDEX ACT_TAG_ACT_ID_IDX ON ACT_TAG_TBL(ACT_ID);

-- ACT POLICY ASSOCIATION
CREATE TABLE ACT_POL_ASSOC_TBL (
	SEC_POL_INST_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	ACT_ID UUID NOT NULL, -- THE ACT TO WHICH THE POLICY APPLIES
	EFFT_VRSN_SEQ_ID NUMERIC(20) NOT NULL, -- THE VERSION OF THE ACT WHERE THE POLICY ASSOCIATION DID BECOME ACTIVE
	OBSLT_VRSN_SEQ_ID NUMERIC(20), -- THE VERSION OF THE ACT WHERE THE POLICY ASSOCIATION IS OBSOLETE,
	POL_ID UUID NOT NULL, -- THE IDENTIFIER OF THE POLICY WHICH IS ATTACHED TO THE ACT
	CONSTRAINT PK_ACT_POL_ASSOC_TBL PRIMARY KEY(SEC_POL_INST_ID),
	CONSTRAINT FK_ACT_POL_ACT_ID FOREIGN KEY (ACT_ID) REFERENCES ACT_TBL(ACT_ID),
	CONSTRAINT FK_ACT_POL_EFFT_VRSN_SEQ_ID FOREIGN KEY (EFFT_VRSN_SEQ_ID) REFERENCES ACT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ACT_POL_OBSLT_VRSN_SEQ_ID FOREIGN KEY (OBSLT_VRSN_SEQ_ID) REFERENCES ACT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ACT_POL_POL_ID FOREIGN KEY (POL_ID) REFERENCES SEC_POL_TBL(POL_ID)
);

CREATE INDEX ACT_POL_ASSOC_POL_ID_IDX ON ACT_POL_ASSOC_TBL(POL_ID);
CREATE INDEX ACT_POL_ASSOC_VRSN_IDX ON ACT_POL_ASSOC_TBL(EFFT_VRSN_SEQ_ID, OBSLT_VRSN_SEQ_ID);

-- ENTITY TABLE
CREATE TABLE ENT_TBL (
	ENT_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	TPL_ID UUID, -- THE TEMPLATE WHICH THIS ENTITY FOLLOWS
	CLS_CD_ID UUID NOT NULL, -- IDENTIIFES THE CLASS CONCEPT
	DTR_CD_ID UUID NOT NULL, -- IDENTIFIES THE ENTITY DETERMINER
	CONSTRAINT PK_ENT_TBL PRIMARY KEY (ENT_ID),
	CONSTRAINT FK_ENT_TPL_ID FOREIGN KEY (TPL_ID) REFERENCES TPL_DEF_TBL(TPL_ID),
	CONSTRAINT FK_ENT_CLS_CD_ID FOREIGN KEY (CLS_CD_ID) REFERENCES CD_TBL (CD_ID),
	CONSTRAINT FK_ENT_DTR_CD_ID FOREIGN KEY (DTR_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT CK_ENT_CLS_CD CHECK (IS_CD_SET_MEM(CLS_CD_ID, 'EntityClass')),
	CONSTRAINT FK_ENT_DTR_CD CHECK (IS_CD_SET_MEM(DTR_CD_ID, 'EntityDeterminer'))
);

CREATE INDEX ENT_TBL_CLS_CD_ID_IDX ON ENT_TBL(CLS_CD_ID);

-- ASSRERT ENTITY IS A PARTICULAR CLASS
CREATE OR REPLACE FUNCTION IS_ENT_CLS(
	ENT_ID_IN IN UUID,
	CLS_MNEMONIC_IN IN VARCHAR(32)
) RETURNS BOOLEAN AS 
$$
BEGIN
	RETURN (SELECT COUNT(*) FROM ENT_TBL INNER JOIN CD_CUR_VRSN ON (ENT_TBL.CLS_CD_ID = CD_CUR_VRSN.CD_ID) WHERE ENT_ID = ENT_ID_IN AND CD_CUR_VRSN.MNEMONIC = CLS_MNEMONIC_IN) > 0;
END
$$ LANGUAGE PLPGSQL;

-- ENTITY TAGS
CREATE TABLE ENT_TAG_TBL (
	TAG_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	ENT_ID UUID NOT NULL, -- THE ENTITY TO WHICH THE TAG APPLIES
	TAG_NAME VARCHAR(64) NOT NULL, -- THE NAME OF THE TAG
	TAG_VALUE TEXT, -- THE VALUE OF THE TAG
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE TIME WHEN THE TAG WAS ADDED TO THE ENTITY
	CRT_PROV_ID UUID NOT NULL, -- THE USER WHICH CREATED OR ATTACHED THE TAG TO THE ENTITY
	OBSLT_UTC TIMESTAMPTZ, -- THE TIME WHEN THE TAG WAS OBSOLETED,
	OBSLT_PROV_ID UUID, -- THE USER WHICH OBSOLETED THE TAG
	CONSTRAINT PK_ENT_TAG_TBL PRIMARY KEY (TAG_ID),
	CONSTRAINT FK_ENT_TAG_ENT_ID FOREIGN KEY (ENT_ID) REFERENCES ENT_TBL(ENT_ID),
	CONSTRAINT FK_ENT_TAG_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_ENT_TAG_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT CK_ENT_TAG_OBSLT_USR CHECK (OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL OR OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL)
);

-- INDEX ON ENTITY TAG
CREATE INDEX ENT_TAG_ENT_ID_IDX ON ENT_TAG_TBL(ENT_ID);

-- ENTITY VERSION
CREATE SEQUENCE ENT_VRSN_SEQ START WITH 1 INCREMENT BY 1;

-- ENTITY VERSION TABLE
CREATE TABLE ENT_VRSN_TBL (
	ENT_VRSN_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	VRSN_SEQ_ID NUMERIC(20) NOT NULL DEFAULT nextval('ENT_VRSN_SEQ'), -- UNIQUE VERSION SEQUENCE FOR THE ENTITY VERSION
	ENT_ID UUID NOT NULL, -- THE ENTITY TO WHICH THE VERSION APPLIES
	RPLC_VRSN_ID UUID, -- THE VERSION THAT THIS ENTITY VERSION REPLACES
	STS_CD_ID UUID NOT NULL, -- THE STATUS OF THE ENTITY AT THIS VERSION
	TYP_CD_ID UUID, -- THE SUBCLASS OR TYPE WITHIN THE CLASS OF THE ENTITY
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE TIME WHEN THE VERSION WAS CREATED
	CRT_PROV_ID UUID NOT NULL, -- THE USER WHICH CREATED THIS VERSION OF THE ENTITY
	OBSLT_UTC TIMESTAMPTZ, -- THE TIME WHEN THE VERSION WAS OBSOLETED
	OBSLT_PROV_ID UUID, -- THEUSER WHICH OBSOLETED THE VERSION
	CONSTRAINT PK_ENT_VRSN_TBL PRIMARY KEY (ENT_VRSN_ID),
	CONSTRAINT FK_ENT_VRSN_ENT_ID FOREIGN KEY (ENT_ID) REFERENCES ENT_TBL(ENT_ID),
	CONSTRAINT FK_ENT_VRSN_RPLC_VRSN_SEQ_ID FOREIGN KEY (RPLC_VRSN_ID) REFERENCES ENT_VRSN_TBL(ENT_VRSN_ID),
	CONSTRAINT FK_ENT_VRSN_STS_CD_ID FOREIGN KEY (STS_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_ENT_VRSN_TYP_CD_ID FOREIGN KEY (TYP_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_ENT_VRSN_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_ENT_VRSN_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT CK_ENT_VRSN_STS_CD CHECK (IS_CD_SET_MEM(STS_CD_ID, 'EntityStatus')),
	CONSTRAINT CK_ENT_VRSN_OBSLT_USR CHECK (OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL OR OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL)
);

CREATE INDEX ENT_VRSN_STS_CD_ID_IDX ON ENT_VRSN_TBL(STS_CD_ID);
CREATE INDEX ENT_VRSN_ENT_ID_IDX ON ENT_VRSN_TBL(ENT_ID);
CREATE UNIQUE INDEX ENT_VRSN_VRSN_SEQ_ID_IDX ON ENT_VRSN_TBL(VRSN_SEQ_ID);

-- ENTITY POLICY ASSOCIATION
CREATE TABLE ENT_POL_ASSOC_TBL (
	SEC_POL_INST_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	ENT_ID UUID NOT NULL, -- THE ACT TO WHICH THE POLICY APPLIES
	EFFT_VRSN_SEQ_ID NUMERIC(20) NOT NULL, -- THE VERSION OF THE ACT WHERE THE POLICY ASSOCIATION DID BECOME ACTIVE
	OBSLT_VRSN_SEQ_ID NUMERIC(20), -- THE VERSION OF THE ACT WHERE THE POLICY ASSOCIATION IS OBSOLETE,
	POL_ID UUID NOT NULL, -- THE IDENTIFIER OF THE POLICY WHICH IS ATTACHED TO THE ACT
	CONSTRAINT PK_ENT_POL_ASSOC_TBL PRIMARY KEY(SEC_POL_INST_ID),
	CONSTRAINT FK_ENT_POL_ENT_ID FOREIGN KEY (ENT_ID) REFERENCES ENT_TBL(ENT_ID),
	CONSTRAINT FK_ENT_POL_EFFT_VRSN_SEQ_ID FOREIGN KEY (EFFT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ENT_POL_OBSLT_VRSN_SEQ_ID FOREIGN KEY (OBSLT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ENT_POL_POL_ID FOREIGN KEY (POL_ID) REFERENCES SEC_POL_TBL(POL_ID)
);

CREATE INDEX ENT_POL_ASSOC_POL_ID_IDX ON ENT_POL_ASSOC_TBL(POL_ID);
CREATE INDEX ENT_POL_ASSOC_VRSN_IDX ON ENT_POL_ASSOC_TBL(EFFT_VRSN_SEQ_ID, OBSLT_VRSN_SEQ_ID);


-- ENTITY RELATIONSHIP TABLE
CREATE TABLE ENT_REL_TBL (
	ENT_REL_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	SRC_ENT_ID UUID NOT NULL, -- THE SOURCE ENTITY OF THE RELATIONSHIP
	TRG_ENT_ID UUID NOT NULL, -- THE TARGET ENTITY OF THE RELATIONSHIP
	EFFT_VRSN_SEQ_ID NUMERIC(20) NOT NULL, -- THE SOURCE VERSION SEQUENCE WHERE THE RELATIONSHIP BECAME ACTIVE
	OBSLT_VRSN_SEQ_ID NUMERIC(20), -- THE SOURCE VERSION SEQUENCE WHERE THE RELATIONSHIP BECAME OBSOLETE
	REL_TYP_CD_ID UUID NOT NULL, -- THE TYPE OF RELATIONSHIP BETWEEN THE ENTITIES
	QTY INT DEFAULT 1, -- THE NUMER OF THE TARGET ENTITY RELATED TO THE SOURCE ENTIYT
	CONSTRAINT PK_ENT_REL_TBL PRIMARY KEY (ENT_REL_ID),
	CONSTRAINT FK_ENT_REL_SRC_ENT_ID FOREIGN KEY (SRC_ENT_ID) REFERENCES ENT_TBL(ENT_ID),
	CONSTRAINT FK_ENT_REL_TRG_ENT_ID FOREIGN KEY (TRG_ENT_ID) REFERENCES ENT_TBL(ENT_ID),
	CONSTRAINT FK_ENT_REL_EFFT_VRSN_SEQ_ID FOREIGN KEY (EFFT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ENT_REL_OBSLT_VRSN_SEQ_ID FOREIGN KEY (OBSLT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ENT_REL_REL_TYP_CD_ID FOREIGN KEY (REL_TYP_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT CK_ENT_REL_REL_TYPE_CD CHECK (IS_CD_SET_MEM(REL_TYP_CD_ID, 'EntityRelationshipType'))
);

CREATE INDEX ENT_REL_SRC_ENT_ID_IDX ON ENT_REL_TBL(SRC_ENT_ID);
CREATE INDEX ENT_REL_TRG_ENT_ID_IDX ON ENT_REL_TBL(TRG_ENT_ID);
CREATE INDEX ENT_REL_VRSN_IDX ON ENT_REL_TBL(EFFT_VRSN_SEQ_ID, OBSLT_VRSN_SEQ_ID);
CREATE INDEX ent_rel_tbl_rel_typ_idx ON ent_rel_tbl (rel_typ_cd_id);
-- ENTITY ADDRESS TABLE
CREATE TABLE ENT_ADDR_TBL (
	ADDR_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	ENT_ID UUID NOT NULL, -- THE ENTITY TO WHICH THE ADDRESS IS ATTACHED
	EFFT_VRSN_SEQ_ID NUMERIC(20) NOT NULL, -- THE VERSION WHEN THE ADDRESS RELATIONSHIP BECAME ACTIVE
	OBSLT_VRSN_SEQ_ID NUMERIC(20), -- THE VERSION WHEN THE ADDRESS RELATIOSHIP IS NOT ACTIVE
	USE_CD_ID UUID NOT NULL, -- INDICATES THE USE OF THE ADDRESS
	CONSTRAINT PK_ENT_ADDR_TBL PRIMARY KEY (ADDR_ID),
	CONSTRAINT FK_ENT_ADDR_ENT_ID FOREIGN KEY (ENT_ID) REFERENCES ENT_TBL(ENT_ID),
	CONSTRAINT FK_ENT_ADDR_EFFT_VRSN_SEQ_ID FOREIGN KEY (EFFT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ENT_ADDR_OBSLT_VRSN_SEQ_ID FOREIGN KEY (OBSLT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ENT_ADDR_ADDR_USE_CD_ID FOREIGN KEY (USE_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT CK_ENT_ADDR_USE_CD CHECK (IS_CD_SET_MEM(USE_CD_ID, 'AddressUse'))
);

-- INDEX FO ADDRESS
CREATE INDEX ENT_ADDR_ENT_ID_IDX ON ENT_ADDR_TBL(ENT_ID);
CREATE INDEX ENT_ADDR_VRSN_IDX ON ENT_ADDR_TBL(EFFT_VRSN_SEQ_ID, OBSLT_VRSN_SEQ_ID);

-- ENTITY ADDRESS VALUES TABLE
CREATE TABLE ENT_ADDR_CMP_VAL_TBL (
	VAL_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	VAL VARCHAR(256) NOT NULL, -- THE VALUE OF THE COMPONENT
	CONSTRAINT PK_ENT_ADDR_CMP_VAL_TBL PRIMARY KEY (VAL_ID)
);
CREATE INDEX EN_ADDR_CMP_VAL_VAL_IDX ON ENT_ADDR_CMP_VAL_TBL(VAL);

-- ENTITY ADDRESS COMPONENT TABLE
CREATE TABLE ENT_ADDR_CMP_TBL (
	CMP_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	TYP_CD_ID UUID, -- THE TYPE OF THE COMPONENT (STREET, CITY, ETC.)
	VAL_ID UUID NOT NULL, -- THE UUID FOR THE ADDRESS VALUE
	ADDR_ID UUID NOT NULL, -- THE UUID FOR THE ADDRESS TO WHICH THE COMPONENT APPLIES
	CONSTRAINT PK_ENT_ADDR_CMP_TBL PRIMARY KEY(CMP_ID),
	CONSTRAINT FK_ENT_ADDR_CMP_TYP_CD_ID FOREIGN KEY (TYP_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_ENT_ADDR_CMP_VAL_ID FOREIGN KEY (VAL_ID) REFERENCES ENT_ADDR_CMP_VAL_TBL(VAL_ID),
	CONSTRAINT FK_ENT_ADDR_CMP_ADDR_ID FOREIGN KEY (ADDR_ID) REFERENCES ENT_ADDR_TBL(ADDR_ID),
	CONSTRAINT CK_ENT_ADDR_CMP_TYP_CD CHECK (TYP_CD_ID IS NULL OR IS_CD_SET_MEM(TYP_CD_ID, 'AddressComponentType'))
);

CREATE INDEX ENT_ADDR_CMP_ADDR_ID_IDX ON ENT_ADDR_CMP_TBL(ADDR_ID);
CREATE INDEX ENT_ADDR_CMP_VAL_ID_IDX ON ENT_ADDR_CMP_TBL(VAL_ID);

-- ENTITY NAME TABLE
CREATE TABLE ENT_NAME_TBL (
	NAME_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	ENT_ID UUID NOT NULL, -- THE ENTITY TO WHICH THE NAME APPLIES
	EFFT_VRSN_SEQ_ID NUMERIC(20) NOT NULL, -- THE ENTITY SEQUENCE AT WHICH THE NAME BECOMES ACTIVE
	OBSLT_VRSN_SEQ_ID NUMERIC(20), -- THE ENTITY SEQUENCE WHERE THE NAME IS NO LONGER ACTIVE
	USE_CD_ID UUID NOT NULL, -- THE USE OF THE NAME (LEGAL, ETC.)
	CONSTRAINT PK_ENT_NAME_TBL PRIMARY KEY (NAME_ID),
	CONSTRAINT FK_ENT_NAME_ENT_ID FOREIGN KEY (ENT_ID) REFERENCES ENT_TBL(ENT_ID),
	CONSTRAINT FK_ENT_NAME_EFFT_VRSN_SEQ_ID FOREIGN KEY (EFFT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ENT_NAME_OBSLT_VRSN_SEQ_ID FOREIGN KEY (OBSLT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ENT_NAME_USE_CD_ID FOREIGN KEY (USE_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT CK_ENT_NAME_USE_CD CHECK (IS_CD_SET_MEM(USE_CD_ID, 'NameUse'))
);

CREATE INDEX ENT_NAME_ENT_ID_IDX ON ENT_NAME_TBL(ENT_ID);
CREATE INDEX ENT_NAME_VRSN_IDX ON ENT_NAME_TBL(EFFT_VRSN_SEQ_ID, OBSLT_VRSN_SEQ_ID);

CREATE SEQUENCE NAME_VAL_SEQ START WITH 1 INCREMENT BY 1;

-- ENTITY NAME COMPONENT
CREATE TABLE ENT_NAME_CMP_TBL (
	CMP_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	TYP_CD_ID UUID, -- THE TYPE OF COMPONENT (FAMILY, GIVEN, ETC);
	VAL_ID UUID NOT NULL, -- THE PHONETIC CODE FOR THE NAME
	NAME_ID UUID NOT NULL, -- THE NAME TO WHICH THE COMPONENT APPLIES
	VAL_SEQ NUMERIC(20,0) NOT NULL DEFAULT nextval('NAME_VAL_SEQ'),
	CONSTRAINT PK_ENT_NAME_CMP_TBL PRIMARY KEY (CMP_ID),
	CONSTRAINT FK_ENT_NAME_CMP_TYP_CD_ID FOREIGN KEY (TYP_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_ENT_NAME_CMP_PHON_VAL_ID FOREIGN KEY (VAL_ID) REFERENCES PHON_VAL_TBL(VAL_ID),
	CONSTRAINT FK_ENT_NAME_CMP_NAME_ID FOREIGN KEY (NAME_ID) REFERENCES ENT_NAME_TBL(NAME_ID),
	CONSTRAINT CK_ENT_NAME_CMP_TYP_CD CHECK (TYP_CD_ID IS NULL OR IS_CD_SET_MEM(TYP_CD_ID, 'NameComponentType'))
);

CREATE INDEX ENT_NAME_CMP_NAME_ID_IDX ON ENT_NAME_CMP_TBL(NAME_ID);
CREATE INDEX ENT_NAME_CMP_PHON_VAL_ID_IDX ON ENT_NAME_CMP_TBL(VAL_ID);

-- ENTITY EXTENSIONS TABLE
CREATE TABLE ENT_EXT_TBL (
	ENT_EXT_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	ENT_ID UUID NOT NULL, -- THE ENTITY TO WHICH THE EXTENSION APPLIES
	EXT_TYP_ID UUID NOT NULL, -- THE TYPE OF ENTITY EXTENSION
	EXT_VAL BYTEA, -- THE VALUE OF THE EXTENSION
	EXT_DISP VARCHAR(64), -- A DISPLAY OF THE ENTITY EXTENSION
	EFFT_VRSN_SEQ_ID NUMERIC(20) NOT NULL, -- EFFECTIVE VERSION IDENTIFIER
	OBSLT_VRSN_SEQ_ID NUMERIC(20), -- OBSOLETIONS VERSION SEQ
	CONSTRAINT PK_ENT_EXT_TBL PRIMARY KEY (ENT_EXT_ID),
	CONSTRAINT FK_ENT_EXT_ENT_ID FOREIGN KEY (ENT_ID) REFERENCES ENT_TBL(ENT_ID),
	CONSTRAINT FK_ENT_EXT_EFFT_VRSN_SEQ_ID FOREIGN KEY (EFFT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ENT_EXT_OBSLT_VRSN_SEQ_ID FOREIGN KEY (OBSLT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ENT_EXT_TYP_ID FOREIGN KEY (EXT_TYP_ID) REFERENCES EXT_TYP_TBL(EXT_TYP_ID)
);

CREATE INDEX ENT_EXT_ENT_ID_IDX ON ENT_EXT_TBL(ENT_ID);
CREATE INDEX ENT_EXT_VRSN_IDX ON ENT_EXT_TBL(EFFT_VRSN_SEQ_ID, OBSLT_VRSN_SEQ_ID);

-- TODO: MAYBE IS TO BE CHANGED 
CREATE OR REPLACE FUNCTION IS_ENT_ID_UNQ (
	AUT_ID_IN IN UUID,
	ID_VAL_IN VARCHAR(64)
) RETURNS BOOLEAN AS
$$
BEGIN

	IF EXISTS (SELECT ENT_ID_ID FROM ENT_ID_TBL NATURAL JOIN ASGN_AUT_TBL WHERE IS_UNQ = TRUE AND AUT_ID = AUT_ID_IN AND ID_VAL = ID_VAL_IN AND OBSLT_VRSN_SEQ_ID IS NULL LIMIT 1) THEN
		RETURN TRUE;
	ELSE
		RETURN FALSE;
	END IF;
	
END;
$$ LANGUAGE PLPGSQL;

-- ENTITY IDENTIFIER TABLE
CREATE TABLE ENT_ID_TBL (
	ENT_ID_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	ENT_ID UUID NOT NULL, -- THE ENTITY TO WHICH THE IDENTIFIER IS ATTACHED
	ID_TYP_ID UUID, -- THE TYPE OF IDENTIIFER
	EFFT_VRSN_SEQ_ID NUMERIC(20) NOT NULL, -- THE VERSION WHEN THE IDENTIFIER WAS ACTIVE
	OBSLT_VRSN_SEQ_ID NUMERIC(20), -- OBSOLETE VERSION SEQUENCE ID
	AUT_ID UUID NOT NULL, -- THE ASSIGNING AUTHORITY OF THE IDENTIFIER
	ID_VAL VARCHAR(64) NOT NULL, -- THE VALUE OF THE IDENTIFIER
	CONSTRAINT PK_ENT_ID_TBL PRIMARY KEY (ENT_ID_ID),
	CONSTRAINT FK_ENT_ID_ENT_ID FOREIGN KEY (ENT_ID) REFERENCES ENT_TBL(ENT_ID),
	CONSTRAINT FK_ENT_ID_EFFT_VRSN_SEQ_ID FOREIGN KEY (EFFT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ENT_ID_OBSLT_VRSN_SEQ_ID FOREIGN KEY (OBSLT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ENT_ID_AUT_ID FOREIGN KEY (AUT_ID) REFERENCES ASGN_AUT_TBL(AUT_ID)
);

CREATE INDEX ENT_ID_VRSN_IDX ON ENT_ID_TBL(EFFT_VRSN_SEQ_ID, OBSLT_VRSN_SEQ_ID);
CREATE INDEX ENT_ID_ENT_ID_IDX ON ENT_ID_TBL(ENT_ID);
CREATE UNIQUE INDEX ENT_ID_ENT_VAL_UQ_IDX ON ENT_ID_TBL(EFFT_VRSN_SEQ_ID, AUT_ID, ID_VAL);

-- TELECOM ADDRESS
CREATE TABLE ENT_TEL_TBL (
	TEL_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	ENT_ID UUID NOT NULL, -- THE ENTITY TO WHICH THE TELECOM ADDRESS APPLIES
	TYP_CD_ID UUID, -- THE TYPE OF ADDRESS (FAX, TEL, EMAIL, PAGER, ETC.)
	USE_CD_ID UUID NOT NULL, -- IDENTIIFES THE USE OF THE ADDRESS (HOME, WORK, ETC.)
	TEL_VAL VARCHAR(256) NOT NULL, -- THE VALUE OF THE ADDRESS
	EFFT_VRSN_SEQ_ID NUMERIC(20) NOT NULL, -- THE VERSION SEQUENCE WHEN THE ADDRESS IS ACTIVE
	OBSLT_VRSN_SEQ_ID NUMERIC(20), -- THE VERSION SEQUENCE WHEN TH ADDRESS IS OBSOLETE
	CONSTRAINT PK_ENT_TEL_TBL PRIMARY KEY (TEL_ID),
	CONSTRAINT FK_ENT_TEL_ENT_ID FOREIGN KEY (ENT_ID) REFERENCES ENT_TBL(ENT_ID),
	CONSTRAINT FK_ENT_TEL_TYP_CD_ID FOREIGN KEY (TYP_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_ENT_TEL_USE_CD_ID FOREIGN KEY (USE_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_ENT_TEL_EFFT_VRSN_SEQ_ID FOREIGN KEY (EFFT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ENT_TEL_OBSLT_VRSN_SEQ_ID FOREIGN KEY (OBSLT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT CK_ENT_TEL_TYP_CD CHECK (TYP_CD_ID IS NULL OR IS_CD_SET_MEM(TYP_CD_ID, 'TelecomAddressType')),
	CONSTRAINT CK_ENT_TEL_USE_CD CHECK (IS_CD_SET_MEM(USE_CD_ID, 'TelecomAddressUse'))
);

CREATE INDEX ENT_TEL_VRSN_IDX ON ENT_TEL_TBL(EFFT_VRSN_SEQ_ID, OBSLT_VRSN_SEQ_ID);
CREATE INDEX ENT_TEL_ENT_ID_IDX ON ENT_TEL_TBL(ENT_ID);
CREATE INDEX ENT_TEL_VAL_IDX ON ENT_TEL_TBL(TEL_VAL);

-- PLACE TABLE
CREATE TABLE PLC_TBL (
	ENT_VRSN_ID UUID NOT NULL, -- THE ENTITY VERSION THIS PLACE REPRESENTS
	MOB_IND BOOLEAN NOT NULL DEFAULT FALSE, -- TRUE IF THE PLACE HAS NO FIXED ADDRESS
	LAT FLOAT, -- THE LATITUDE OF THE PLACE 
	LNG FLOAT, -- THE LONGITUDE OF THE PLACE
	CONSTRAINT PK_PLC_TBL PRIMARY KEY (ENT_VRSN_ID),
	CONSTRAINT FK_PLC_ENT_VRSN_TBL FOREIGN KEY (ENT_VRSN_ID) REFERENCES ENT_VRSN_TBL(ENT_VRSN_ID)
);

-- PLACE SERVICE TABLE
CREATE TABLE PLC_SVC_TBL (
	SVC_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	ENT_ID UUID NOT NULL, -- THE ENTITY TO WHICH THE SERVICE APPLIES
	EFFT_VRSN_SEQ_ID NUMERIC(20) NOT NULL, -- EFFECTIVE VERSION SEQUENCE
	OBSLT_VRSN_SEQ_ID NUMERIC(20), -- THE VERSION WHEERE THE SERVICE WAS REMOVED
	SVC_CD_ID UUID NOT NULL, -- THE CONCEPT WHICH DEFINES THE SERVICE
	SCHDL TEXT NOT NULL, -- THE SERVICE SCHEDULE
	CONSTRAINT PK_PLC_SVC_TBL PRIMARY KEY (SVC_ID),
	CONSTRAINT FK_PLC_SVC_ENT_ID FOREIGN KEY (ENT_ID) REFERENCES ENT_TBL(ENT_ID),
	CONSTRAINT CK_PLC_SVC_ENT CHECK (IS_ENT_CLS(ENT_ID, 'ServiceDeliveryLocation')),
	CONSTRAINT FK_PLC_SVC_EFFT_VRSN_SEQ_ID FOREIGN KEY (EFFT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_PLC_SVC_OBSLT_VRSN_SEQ_ID FOREIGN KEY (OBSLT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_PLC_SVC_CD_ID FOREIGN KEY (SVC_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT CK_PLC_SVC_CD CHECK (IS_CD_SET_MEM(SVC_CD_ID, 'ServiceCode'))
);

-- ORGANIZATION TABLE
CREATE TABLE ORG_TBL (
	ENT_VRSN_ID UUID NOT NULL, -- THE ENTITY VERSION TO WHICH THIS ORG APPLIES
	IND_CD_ID UUID, -- THE INDUSTRY CONCEPT OF THE ORGANIZATION
	CONSTRAINT PK_ORG_TBL PRIMARY KEY (ENT_VRSN_ID),
	CONSTRAINT FK_ORG_ENT_VRSN_ID FOREIGN KEY (ENT_VRSN_ID) REFERENCES ENT_VRSN_TBL(ENT_VRSN_ID), 
	CONSTRAINT FK_ORG_IND_CD_ID FOREIGN KEY (IND_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT CK_ORG_IND_CD CHECK (IND_CD_ID IS NULL OR IS_CD_SET_MEM(IND_CD_ID, 'IndustryCode'))
);

-- APPLICATION ENTITY
CREATE TABLE APP_ENT_TBL (
	ENT_VRSN_ID UUID NOT NULL, -- THE ENTITY TO WHICH THE VERISON APPLIES
	SEC_APP_ID UUID, -- THE SECURITY APPLICATION ASSOCIATION EDITH THE ENTITY
	SOFT_NAME VARCHAR(64) NOT NULL, -- THE NAME OF THE SOFTWARE PRODUCT THIS APPLICATION ENTITY REPRESENTS
	VER_NAME VARCHAR(64), -- THE VERSION NAME OF THE ENTITY 
	VND_NAME VARCHAR(64), -- THE VENDOR NAME
	CONSTRAINT PK_APP_ENT_TBL PRIMARY KEY (ENT_VRSN_ID),
	CONSTRAINT FK_APP_ENT_ENT_VRSN_ID FOREIGN KEY (ENT_VRSN_ID) REFERENCES ENT_VRSN_TBL(ENT_VRSN_ID),
	CONSTRAINT FK_APP_ENT_SEC_APP_ID FOREIGN KEY (SEC_APP_ID) REFERENCES SEC_APP_TBL(APP_ID)
);

CREATE INDEX APP_ENT_SEC_APP_ID_IDX ON APP_ENT_TBL(SEC_APP_ID);

-- DEVICE ENTITY 
CREATE TABLE DEV_ENT_TBL (
	ENT_VRSN_ID UUID NOT NULL, -- THE ENTITY VERSION TO WHICH THE DEVICE INFORMATION APPLIES
	SEC_DEV_ID UUID, -- THE SECURITY DEVICE TO WHICH THE DEVICE INFORMATION APPLIES
	MNF_NAME VARCHAR(64) NOT NULL, -- THE NAME THE MANUFACTURER GAVE TO THE DEVICE
	OS_NAME VARCHAR(64), -- THE NAME OF THE OPERATING SYSTEM ON THE DEVICE
	CONSTRAINT PK_DEV_ENT_TBL PRIMARY KEY (ENT_VRSN_ID),
	CONSTRAINT FK_DEV_ENT_ENT_VRSN_ID FOREIGN KEY (ENT_VRSN_ID) REFERENCES ENT_VRSN_TBL(ENT_VRSN_ID),
	CONSTRAINT FK_DEV_SEC_DEV_ID FOREIGN KEY (SEC_DEV_ID) REFERENCES SEC_DEV_TBL(DEV_ID)
);

CREATE INDEX DEV_ENT_SEC_APP_ID_IDX ON DEV_ENT_TBL(SEC_DEV_ID);

-- MATERIALS TABLE
CREATE TABLE MAT_TBL (
	ENT_VRSN_ID UUID NOT NULL, -- THE ENTITY VERSION TO WHICH TH EMATERIAL DATA APPLIES
	EXP_UTC DATE, -- THE DATE WHEN THE MATERIAL EXPIRES
	FRM_CD_ID UUID, -- THE FORM OF THE MATERIAL (CAPSULES, INJECTION, ETC),
	QTY DECIMAL(20,10), -- THE QUANTITY OF THIS OBJECT IN THE PARENT OBJECT
	QTY_CD_ID UUID, -- IDENTIFIES THE QUANTITY UNITS OF MATERIAL 
	IS_ADM BOOLEAN NOT NULL DEFAULT FALSE, -- TRUE IF THE MATERIAL ISN'T A REAL MATERIAL, RATHER EXISTS FOR ADMINISTRATIVE TRACKING PURPOSES
	CONSTRAINT PK_MAT_TBL PRIMARY KEY (ENT_VRSN_ID),
	CONSTRAINT FK_MAT_ENT_VRSN_ID FOREIGN KEY (ENT_VRSN_ID) REFERENCES ENT_VRSN_TBL(ENT_VRSN_ID),
	CONSTRAINT FK_MAT_FRM_CD_ID FOREIGN KEY (FRM_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_MAT_QTY_CD_ID FOREIGN KEY (QTY_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT CK_MAT_FRM_CD CHECK (FRM_CD_ID IS NULL OR ASSRT_CD_CLS(FRM_CD_ID, 'Form')),
	CONSTRAINT CK_MAT_QTY_CD CHECK (QTY_CD_ID IS NULL OR ASSRT_CD_CLS(QTY_CD_ID, 'UnitOfMeasure'))
);

-- MANUFACTURED MATERIALS TABLE
CREATE TABLE MMAT_TBL (
	ENT_VRSN_ID UUID NOT NULL, -- THE MATERIAL VERSION ID
	LOT_NO VARCHAR(32), -- THE LOT NUMBER OF THE MMAT
	CONSTRAINT PK_MMAT_TBL PRIMARY KEY (ENT_VRSN_ID),
	CONSTRAINT FK_MMAT_ENT_VRSN_ID FOREIGN KEY (ENT_VRSN_ID) REFERENCES MAT_TBL(ENT_VRSN_ID)
);

CREATE INDEX MMAT_LOT_NO_IDX ON MMAT_TBL (LOT_NO);

-- PERSON TABLE
CREATE TABLE PSN_TBL (
	ENT_VRSN_ID UUID NOT NULL, -- THE ENTITY VERSION ID TO WHICH TH EPERSON INFO 
	DOB DATE, -- DATE OF BIRTH OF THE PERSON
	DOB_PREC CHAR(1) CHECK (DOB_PREC IN ('Y','M','D')), -- THE PRECISION OF TH EDATE
	CONSTRAINT PK_PSN_TBL PRIMARY KEY (ENT_VRSN_ID),
	CONSTRAINT FK_PSN_ENT_VRSN_ID FOREIGN KEY (ENT_VRSN_ID) REFERENCES ENT_VRSN_TBL(ENT_VRSN_ID)
);

-- PERSON LANGUAGE COMMUNICATION TABLE
CREATE TABLE PSN_LNG_TBL (
	LNG_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	ENT_ID UUID NOT NULL, -- THE PERSON TO WHICH THE LANGUAGE APPLIES
	EFFT_VRSN_SEQ_ID NUMERIC(20) NOT NULL, -- THE VERSION OF THE PERSON ENTITY WHERE THIS BECOMES ACTIVE
	OBSLT_VRSN_SEQ_ID NUMERIC(20), -- THE OBSOLETION VERISON OF THE PERSON LANGUAGE
	LNG_CS CHAR(2) NOT NULL, -- THE LANGUAGE CODE REPRESENTING THE COMMUNICATION
	PREF_IND BOOLEAN NOT NULL DEFAULT FALSE, -- PREFERENCE INDICATOR
	CONSTRAINT PK_PSN_LNG_TBL PRIMARY KEY (LNG_ID),
	CONSTRAINT FK_PSN_LNG_ENT_ID FOREIGN KEY (ENT_ID) REFERENCES ENT_TBL(ENT_ID),
	CONSTRAINT FK_PSN_LNG_EFFT_VRSN_SEQ_ID FOREIGN KEY (EFFT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_PSN_LNG_OBSLT_VRSN_SEQ_ID FOREIGN KEY (OBSLT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID)
);

CREATE INDEX PSN_LNG_ENT_ID_IDX ON PSN_LNG_TBL(ENT_ID);
CREATE INDEX PSN_LNG_VRSN_IDX ON PSN_LNG_TBL(EFFT_VRSN_SEQ_ID, OBSLT_VRSN_SEQ_ID);

-- PATIENT TABLE
CREATE TABLE PAT_TBL (
	ENT_VRSN_ID UUID NOT NULL, -- THE VERSION ID OF THE ENTITY VERSION TO WHICH THE PATIENT INFO APPLIES
	GNDR_CD_ID UUID NOT NULL, -- THE GENDER OF THE PATIENT
	DCSD_UTC DATE, -- THE DATE THE PATIENT DIED
	DCSD_PREC CHAR(1) CHECK (DCSD_PREC IN ('Y','M','D')),
	MB_ORD NUMERIC(2), -- THE ORDER IN WHICH THE PATIENT WAS BORN
	MRTL_STS_CD_ID UUID, -- MARITAL STATUS KEY
	EDU_LVL_CD_ID UUID, -- EDUCATION LEVEL KEY
	LVN_ARG_CD_ID UUID, -- LIVING ARRANGEMENT
	RLGN_CD_ID UUID, -- RELIGION CODE
	ETH_GRP_CD_ID UUID, -- ETHNIC GROUP KEY
	CONSTRAINT PK_PAT_TBL PRIMARY KEY (ENT_VRSN_ID),
	CONSTRAINT FK_PAT_ENT_VRSN_ID FOREIGN KEY (ENT_VRSN_ID) REFERENCES PSN_TBL(ENT_VRSN_ID),
	CONSTRAINT FK_PAT_GNDR_CD_ID FOREIGN KEY (GNDR_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT CK_PAT_GNDR_CD CHECK (IS_CD_SET_MEM(GNDR_CD_ID, 'AdministrativeGenderCode')),
	CONSTRAINT FK_PSN_MRTL_STS_CD_ID FOREIGN KEY (MRTL_STS_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_PAT_EDU_LVL_CD_ID FOREIGN KEY (EDU_LVL_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_PAT_LVN_ARG_CD_ID FOREIGN KEY (LVN_ARG_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT FK_PAT_RLGN_CD_ID FOREIGN KEY (RLGN_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT CK_PAT_MRTL_STS_CD CHECK (MRTL_STS_CD_ID IS NULL OR IS_CD_SET_MEM(MRTL_STS_CD_ID, 'MaritalStatus')),
	CONSTRAINT CK_PAT_EDU_LVL_CD CHECK (EDU_LVL_CD_ID IS NULL OR IS_CD_SET_MEM(EDU_LVL_CD_ID, 'EducationLevel')),
	CONSTRAINT CK_PAT_LVN_ARG_CD CHECK (LVN_ARG_CD_ID IS NULL OR IS_CD_SET_MEM(LVN_ARG_CD_ID, 'LivingArrangement')),
	CONSTRAINT CK_PAT_RLGN_CD CHECK (RLGN_CD_ID IS NULL OR IS_CD_SET_MEM(RLGN_CD_ID, 'Religion')),
	CONSTRAINT CK_PAT_ETH_GRP_CD CHECK (ETH_GRP_CD_ID IS NULL OR IS_CD_SET_MEM(ETH_GRP_CD_ID, 'Ethnicity'))
);

-- PROVIDER TABLE
CREATE TABLE PVDR_TBL (
	ENT_VRSN_ID UUID NOT NULL, -- THE VERSION OF THE PERSON TO WHICH THE PROVIDER INFO APPLIES
	SPEC_CD_ID UUID, -- THE PROVIDER'S SPECIALTY
	CONSTRAINT PK_PVDR_TBL PRIMARY KEY (ENT_VRSN_ID),
	CONSTRAINT FK_PVDR_ENT_VRSN_ID FOREIGN KEY (ENT_VRSN_ID) REFERENCES PSN_TBL(ENT_VRSN_ID),
	CONSTRAINT FK_PVDR_SPEC_CD_ID FOREIGN KEY (SPEC_CD_ID) REFERENCES CD_TBL(CD_ID)
);

-- USER ENTITY TABLE
CREATE TABLE USR_ENT_TBL (
	ENT_VRSN_ID UUID NOT NULL, -- THE ENTITY VERSION OF THE PERSON THE ENTITY APPLIES TO
	SEC_USR_ID UUID NOT NULL, -- THE SECURITY USER IDENTIFIER OF THE USER ENTITY
	CONSTRAINT PK_USR_ENT_TBL PRIMARY KEY (ENT_VRSN_ID),
	CONSTRAINT FK_USR_ENT_VRSN_ID FOREIGN KEY (ENT_VRSN_ID) REFERENCES PSN_TBL(ENT_VRSN_ID),
	CONSTRAINT FK_USR_ENT_SEC_USR_ID FOREIGN KEY (SEC_USR_ID) REFERENCES SEC_USR_TBL(USR_ID)
);

CREATE INDEX USR_ENT_SEC_USR_ID_IDX ON USR_ENT_TBL(SEC_USR_ID);

-- CLINICAL PROTOCOL HANDLER
CREATE TABLE PROTO_HDLR_TBL (
	HDLR_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	HDLR_NAME VARCHAR(64) NOT NULL, -- THE NAME OF THE HANDLER (HUMAN READABLE)
	HDLR_CLS VARCHAR(256) NOT NULL, -- THE CLASS WHICH IS RESPONSIBLE FOR THE PROTOCOL EXECUTION
	IS_ACTIVE BOOLEAN NOT NULL DEFAULT TRUE, -- INDICATES WHETHER THE PROTOCOL IS ACTIVE
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE TIME WHEN THE HANDLER WAS CREATED
	CRT_PROV_ID UUID NOT NULL , -- THE IDENTIFIER OF THE USER WHICH CREATED THE HANDLER
	OBSLT_UTC TIMESTAMPTZ, -- THE TIME THE HANDLER WAS OBSOLETED
	OBSLT_PROV_ID UUID, -- THE USER WHICH OBSOLETED THE HANDLER
	CONSTRAINT PK_PROTO_HDLR_TBL PRIMARY KEY (HDLR_ID),
	CONSTRAINT FK_PROTO_HDLR_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_PROTO_HDLR_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT CK_PROTO_HDLR_OBSLT_USR CHECK (OBSLT_UTC IS NULL AND OBSLT_PROV_ID IS NULL OR OBSLT_UTC IS NOT NULL AND OBSLT_PROV_ID IS NOT NULL)
);

-- CLINICAL PROTOCOL DEFINITION TABLE
CREATE TABLE PROTO_TBL (
	PROTO_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	PROTO_NAME VARCHAR(64) NOT NULL, -- NAME FO THE PROTOCOL (EX: CHILDHOOD VACCINATIONS)
	HDLR_ID UUID NOT NULL, -- THE HANDLER CLASS WHICH EXECUTES THE PROTOCOL
	OID VARCHAR(64), -- THE OID OF THE PROTOCOL
	DEFN BYTEA, -- THE DEFINITION FILE WHICH DEFINES THE PROTOCOL IN A FORMAT THAT THE HANDLER CAN USE
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE TIME THE PROTOCOL DEFINITION WAS CREATE
	CRT_PROV_ID UUID NOT NULL, -- THE USER WHICH CREATE THE PROTOCOL
	OBSLT_UTC TIMESTAMPTZ, -- THE TIME WHEN THE PROTOCOL DEFINITION WAS OBSOLETED
	OBSLT_PROV_ID UUID, -- THE USER WHICH OBSOLETED THE PROTOCL DEFINITION
	RPLC_PROTO_ID UUID, -- IF THE PROTOCOL REPLACES A PREVIOUS PROTOCOL
	CONSTRAINT PK_PROTO_TBL PRIMARY KEY (PROTO_ID),
	CONSTRAINT FK_PROTO_HDLR_ID FOREIGN KEY (HDLR_ID) REFERENCES PROTO_HDLR_TBL(HDLR_ID),
	CONSTRAINT FK_PROTO_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_PROTO_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_PROTO_RPLC_PROTO_ID FOREIGN KEY (RPLC_PROTO_ID) REFERENCES PROTO_TBL(PROTO_ID),
	CONSTRAINT CK_PROTO_OBSLT_USR CHECK (OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL OR OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL)
);

-- INDEX FOR PROTOCOL BY OID
CREATE UNIQUE INDEX PROTO_NAME_UQ_IDX ON PROTO_TBL(PROTO_NAME);

-- PROTOCOL TO ACT TABLE
CREATE TABLE ACT_PROTO_ASSOC_TBL (
	PROTO_ID UUID NOT NULL, 
	ACT_ID UUID NOT NULL, -- THE ACT TO WHICH THE PROTOCOL APPLIES
	SEQ INT NOT NULL, -- INDICATES THE SEQUENCE IN THE CARE PROTOCOL
	IS_COMPL BOOLEAN NOT NULL DEFAULT FALSE, -- INDICATES THAT THE ACT IS A TERMINAL STATE OF THE PROTOCOL
	STATE_DAT BYTEA, -- ANY STATE DATA THE PROTOCOL HANDLER WISHES TO ATTACH
	CONSTRAINT PK_ACT_PROTO_ASSOC_TBL PRIMARY KEY (PROTO_ID, ACT_ID),
	CONSTRAINT FK_ACT_PROTO_ASSOC_PROTO_ID FOREIGN KEY (PROTO_ID) REFERENCES PROTO_TBL(PROTO_ID),
	CONSTRAINT FK_ACT_PROTO_ASSOC_ACT_ID FOREIGN KEY (ACT_ID) REFERENCES ACT_TBL(ACT_ID)
);

CREATE INDEX ACT_PROTO_ASSOC_ACT_ID_IDX ON ACT_PROTO_ASSOC_TBL(ACT_ID);

-- ACT NOTES TABLE
CREATE TABLE ACT_NOTE_TBL (
	NOTE_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	ACT_ID UUID NOT NULL, -- THE ACT TO WHICH THE NOTE APPLIES
	EFFT_VRSN_SEQ_ID NUMERIC(20) NOT NULL, -- THE VERSION OF HTE ACT WHERE THE NOTE WAS ADDED
	OBSLT_VRSN_SEQ_ID NUMERIC(20), -- THE VERSION OF THE ACT WHERE THE NOTE WAS REMOVED
	AUTH_ENT_ID UUID NOT NULL, -- THE UAHTOR WHO CREATED THE NOTE (SINCE A NOTE CAN BE ATTACHED WITHOUT CREATING A NEW VERSION)
	NOTE_TXT TEXT NOT NULL, -- THE NOTE TEXT
	CONSTRAINT PK_ACT_NOTE_TBL PRIMARY KEY (NOTE_ID),
	CONSTRAINT FK_ACT_NOTE_ACT_ID FOREIGN KEY (ACT_ID) REFERENCES ACT_TBL(ACT_ID),
	CONSTRAINT FK_ACT_NOTE_EFFT_VRSN_SEQ_ID FOREIGN KEY (EFFT_VRSN_SEQ_ID) REFERENCES ACT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ACT_NOTE_OBSLT_VRSN_SEQ_ID FOREIGN KEY (OBSLT_VRSN_SEQ_ID) REFERENCES ACT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ACT_NOTE_AUTH_ENT_ID FOREIGN KEY (AUTH_ENT_ID) REFERENCES ENT_TBL(ENT_ID)
);

CREATE INDEX ACT_NOTE_VRSN_IDX ON ACT_NOTE_TBL (EFFT_VRSN_SEQ_ID, OBSLT_VRSN_SEQ_ID);
CREATE INDEX ACT_NOTE_ACT_ID_IDX ON ACT_NOTE_TBL(ACT_ID);

-- ENTITY NOTE TABLE
CREATE TABLE ENT_NOTE_TBL (
	NOTE_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	ENT_ID UUID NOT NULL, -- THE ENTITY TO WHICH THE NOTE APPLIES
	EFFT_VRSN_SEQ_ID NUMERIC(20) NOT NULL, -- THE VERSION OF HTE ENTITY WHERE THE NOTE WAS ADDED
	OBSLT_VRSN_SEQ_ID NUMERIC(20), -- THE VERSION OF THE ENTITY WHERE THE NOTE WAS REMOVED
	AUTH_ENT_ID UUID NOT NULL, -- THE UAHTOR WHO CREATED THE NOTE (SINCE A NOTE CAN BE ATTACHED WITHOUT CREATING A NEW VERSION)
	NOTE_TXT TEXT NOT NULL, -- THE NOTE TEXT
	CONSTRAINT PK_ENT_NOTE_TBL PRIMARY KEY (NOTE_ID),
	CONSTRAINT FK_ENT_NOTE_ENT_ID FOREIGN KEY (ENT_ID) REFERENCES ENT_TBL(ENT_ID),
	CONSTRAINT FK_ENT_NOTE_EFFT_VRSN_SEQ_ID FOREIGN KEY (EFFT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ENT_NOTE_OBSLT_VRSN_SEQ_ID FOREIGN KEY (OBSLT_VRSN_SEQ_ID) REFERENCES ENT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ENT_NOTE_AUTH_ENT_ID FOREIGN KEY (AUTH_ENT_ID) REFERENCES ENT_TBL(ENT_ID)
);

CREATE INDEX ENT_NOTE_VRSN_IDX ON ENT_NOTE_TBL (EFFT_VRSN_SEQ_ID, OBSLT_VRSN_SEQ_ID);
CREATE INDEX ENT_NOTE_ENT_ID_IDX ON ENT_NOTE_TBL(ENT_ID);

-- ACT PARTICIPATION TABLE
CREATE TABLE ACT_PTCPT_TBL (
	ACT_PTCPT_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	ENT_ID UUID NOT NULL, -- THE ENTITY TO WHICH THE PARTICIPATION APPLIES
	ACT_ID UUID NOT NULL, -- THE ACT TO WHICH THE PARTICIPATION APPLIES
	EFFT_VRSN_SEQ_ID NUMERIC(20) NOT NULL, -- THE VERSION OF THE ACT WHERE THE PARTICIPATION IS ACTIVATED
	OBSLT_VRSN_SEQ_ID NUMERIC(20), -- THE VERISON OF THE ACT WHERE THE PARTICIPATION IS NO LONGER ACTIVE
	QTY INT DEFAULT 1, -- THE QUANTITY OF ENTITY PARTICIPATING IN ACT
	ROL_CD_ID UUID NOT NULL, -- THE ROLE THAT THE ENTITY PLAYS IN ACT
	CONSTRAINT PK_ACT_PTCPT_TBL PRIMARY KEY (ACT_PTCPT_ID),
	CONSTRAINT FK_ACT_PTCPT_ENT_ID FOREIGN KEY (ENT_ID) REFERENCES ENT_TBL(ENT_ID),
	CONSTRAINT FK_ACT_PTCPT_ACT_ID FOREIGN KEY (ACT_ID) REFERENCES ACT_TBL(ACT_ID),
	CONSTRAINT FK_ACT_PTCPT_EFFT_VRSN_SEQ_ID FOREIGN KEY (EFFT_VRSN_SEQ_ID) REFERENCES ACT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ACT_PTCPT_OBSLT_VRSN_SEQ_ID FOREIGN KEY (OBSLT_VRSN_SEQ_ID) REFERENCES ACT_VRSN_TBL(VRSN_SEQ_ID),
	CONSTRAINT FK_ACT_PTCPT_ROL_CD_ID FOREIGN KEY (ROL_CD_ID) REFERENCES CD_TBL(CD_ID),
	CONSTRAINT CK_ACT_PTCPT_ROL_CD CHECK (IS_CD_SET_MEM(ROL_CD_ID, 'ActParticipationType'))
);

CREATE INDEX ACT_PTCPT_ENT_ID_IDX ON ACT_PTCPT_TBL(ENT_ID);
CREATE INDEX ACT_PTCPT_ACT_ID_IDX ON ACT_PTCPT_TBL(ACT_ID);
CREATE INDEX ACT_PTCPT_VRSN_ID_IDX ON ACT_PTCPT_TBL(EFFT_VRSN_SEQ_ID, OBSLT_VRSN_SEQ_ID);
CREATE INDEX ACT_PTCPT_ACT_ROL_IDX ON ACT_PTCPT_TBL(ACT_ID, ROL_CD_ID);
CREATE INDEX ACT_PTCPT_ENT_ROL_IDX ON ACT_PTCPT_TBL(ENT_ID, ROL_CD_ID);

-- ALERT MESSAGES
CREATE TABLE ALRT_TBL (
	ALRT_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- TIME THE ALERT WAS CREATED
	CRT_PROV_ID UUID NOT NULL, -- THE USER WHO CREATED THE ALERT
	OBSLT_UTC TIMESTAMPTZ, -- THE TIME THE ALERT WAS REMOVED
	OBSLT_PROV_ID UUID, -- THE USER WHICH OBSOLETED THE ALERT
	UPD_UTC TIMESTAMPTZ, -- THE TIME THE ALERT WAS UPDATED
	UPD_PROV_ID UUID, -- THE USER WHICH UPDATED THE ALERT
	FROM_INFO VARCHAR(128) NOT NULL, -- THE INFORMATION WHICH APPEARS IN THE FROM HEADER (EXAMPLE: THE FROM MIME HEADER)
	TO_INFO VARCHAR(128) NOT NULL, -- THE INFORMATION WHICH APPEARS IN THE TO HEADER (EXAMPLE: FROM MIME)
	MSG_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE TIMESTAMP OF THE MESSAGE
	SUBJ VARCHAR(256), -- THE SUBJECT OF THE MESSAGE
	BODY TEXT NOT NULL, -- THE BODY OF THE MESSAGE
	FLAGS INT NOT NULL DEFAULT 0, -- FLAGS OF THE MESSAGE
	CONSTRAINT PK_ALRT_TBL PRIMARY KEY (ALRT_ID),
	CONSTRAINT FK_ALRT_CRT_PROV_ID FOREIGN KEY (CRT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_ALRT_UPD_PROV_ID FOREIGN KEY (UPD_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT FK_ALRT_OBSLT_PROV_ID FOREIGN KEY (OBSLT_PROV_ID) REFERENCES SEC_PROV_TBL(PROV_ID),
	CONSTRAINT CK_ALRT_UPD_USR CHECK (UPD_PROV_ID IS NULL AND UPD_UTC IS NULL OR UPD_PROV_ID IS NOT NULL AND UPD_UTC IS NOT NULL),
	CONSTRAINT CK_ALRT_OBSLT_USR CHECK (OBSLT_PROV_ID IS NULL AND OBSLT_UTC IS NULL OR OBSLT_PROV_ID IS NOT NULL AND OBSLT_UTC IS NOT NULL)
);

-- INDEX
CREATE INDEX ALRT_TO_INFO_IDX ON ALRT_TBL(TO_INFO);

-- ALERT RECIPIENT (RCPT TO) TABLE
CREATE TABLE ALRT_RCPT_TO_TBL (
	ALRT_ID UUID NOT NULL, -- THE ALERT TO WHICH THE RCPT TO APPLIES
	USR_ID UUID NOT NULL, -- THE RCPT TO USER 
	CONSTRAINT PK_ALRT_RCPT_TO_TBL PRIMARY KEY (ALRT_ID, USR_ID),
	CONSTRAINT FK_ALRT_RCPT_TO_ALRT_ID FOREIGN KEY (ALRT_ID) REFERENCES ALRT_TBL(ALRT_ID),
	CONSTRAINT FK_ALRT_RCPT_TO_USR_ID FOREIGN KEY (USR_ID) REFERENCES SEC_USR_TBL(USR_ID)
);

-- SECURITY SESSIONS TABLE
CREATE TABLE SEC_SES_TBL (
	SES_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	CRT_UTC TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, -- THE TIME WHEN THE SESSION WAS ESTABLISHED
	EXP_UTC TIMESTAMPTZ NOT NULL, -- THE TIME WHEN THE SESSION WILL EXPIRE
	APP_ID UUID NOT NULL, -- THE SECURITY APPLICATION WHICH THE SESSION IS ESTABLISHED FOR
	USR_ID UUID, -- THE USER IDENTIFIER (APPLICATION USER IF APPLICATION GRANT)
	DEV_ID UUID,
	RFRSH_TKN VARCHAR(128) UNIQUE NOT NULL, -- THE REFRESH TOKEN FOR THE OBJECT 
	RFRSH_EXP_UTC TIMESTAMPTZ NOT NULL, -- THE TIME THAT THE REFRESH TOKEN EXPIRES
	AUD VARCHAR(32) NOT NULL, -- THE REMOTE IP ADDRESS THAT ESTABLISHED THE SESSION
	CONSTRAINT PK_SEC_SES_TBL PRIMARY KEY (SES_ID),
	CONSTRAINT FK_SEC_SES_APP_ID FOREIGN KEY (APP_ID) REFERENCES SEC_APP_TBL(APP_ID),
	CONSTRAINT FK_SEC_SES_USR_ID FOREIGN KEY (USR_ID) REFERENCES SEC_USR_TBL(USR_ID),
	CONSTRAINT FK_SEC_SES_DEV_ID FOREIGN KEY (DEV_ID) REFERENCES SEC_DEV_TBL(DEV_ID),
	CONSTRAINT CK_SEC_SES_EXP CHECK (EXP_UTC > CRT_UTC),
	CONSTRAINT CK_SEC_SES_RFRSH_EXP CHECK (RFRSH_EXP_UTC > EXP_UTC)
);

-- SECURITY SESSION CLAIMS TABLE
CREATE TABLE SEC_SES_CLM_TBL ( 
	CLM_ID UUID NOT NULL DEFAULT uuid_generate_v1(),
	SES_ID UUID NOT NULL, -- THE SESSION TO WHICH THE CLAIM BELONGS
    CLM_TYP VARCHAR(128) NOT NULL, -- THE TYPE OF CLAIM
    CLM_VAL VARCHAR(128) NOT NULL, -- THE VALUE OF THE CLAIM
	CONSTRAINT PK_SEC_SES_CLM_TBL PRIMARY KEY (CLM_ID),
	CONSTRAINT FK_SEC_SES_CLM_SES_ID FOREIGN KEY (SES_ID) REFERENCES SEC_SES_TBL(SES_ID)
);

CREATE INDEX ALRT_RCPT_TO_USR_ID_IDX ON ALRT_RCPT_TO_TBL(USR_ID);
CREATE INDEX ALRT_RCPT_TO_ALRT_ID_IDX ON ALRT_RCPT_TO_TBL(ALRT_ID);

CREATE UNIQUE INDEX ACT_PTCPT_UNQ_ENF ON ACT_PTCPT_TBL(ACT_ID, ENT_ID, ROL_CD_ID) WHERE OBSLT_VRSN_SEQ_ID IS NULL;
CREATE UNIQUE INDEX ENT_REL_UNQ_ENF ON ENT_REL_TBL(SRC_ENT_ID, TRG_ENT_ID, REL_TYP_CD_ID) WHERE OBSLT_VRSN_SEQ_ID IS NULL;
CREATE UNIQUE INDEX ACT_REL_UNQ_ENF ON ACT_REL_TBL(SRC_ACT_ID, TRG_ACT_ID, REL_TYP_CD_ID) WHERE OBSLT_VRSN_SEQ_ID IS NULL;

ALTER TABLE ENT_VRSN_TBL ADD CRT_ACT_ID UUID;
ALTER TABLE ENT_VRSN_TBL ADD CONSTRAINT FK_ENT_VRSN_CRT_ACT FOREIGN KEY (CRT_ACT_ID) REFERENCES ACT_TBL(ACT_ID);