-- CREATE SCHEMA
/*
-- DROP SCHEMA art CASCADE;

CREATE SCHEMA art AUTHORIZATION sherwinp;

*/

-- POSTGRESQL SQL SCHEMA DDL: art
SET search_path TO art;

-- art."document" definition

-- Drop table

-- DROP TABLE "document";

CREATE TABLE "document" (
	document_id int4 GENERATED ALWAYS AS IDENTITY NOT NULL,
	document_url varchar(254) NOT NULL,
	CONSTRAINT pk_document PRIMARY KEY (document_id)
);


-- art.zip definition

-- Drop table

-- DROP TABLE zip;

CREATE TABLE zip (
	zip varchar(5) NOT NULL,
	city varchar(16) NULL,
	state varchar(2) NULL,
	CONSTRAINT pk_zip PRIMARY KEY (zip),
	CONSTRAINT zip_check CHECK (regexp_like((zip)::text, '\d{5}'::text))
);


-- art.contact definition

-- Drop table

-- DROP TABLE contact;

CREATE TABLE contact (
	contact_id int4 GENERATED ALWAYS AS IDENTITY NOT NULL,
	first_name varchar(16) NOT NULL,
	last_name varchar(16) NOT NULL,
	phone_no varchar(12) NULL,
	email varchar(64) NOT NULL,
	modified_by int4 NULL,
	created_dt timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL,
	modified_dt timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL,
	CONSTRAINT pk_contact_id PRIMARY KEY (contact_id),
	CONSTRAINT contact_modified_by_fkey FOREIGN KEY (modified_by) REFERENCES contact(contact_id)
);


-- art."plan" definition

-- Drop table

-- DROP TABLE "plan";

CREATE TABLE "plan" (
	plan_id int4 GENERATED ALWAYS AS IDENTITY NOT NULL,
	description varchar(32) NULL,
	fk_document_id int4 NOT NULL,
	duration int4 NULL,
	price int4 NULL,
	modified_by int4 NULL,
	created_dt timestamp DEFAULT CURRENT_TIMESTAMP NULL,
	modified_dt timestamp DEFAULT CURRENT_TIMESTAMP NULL,
	CONSTRAINT pk_plan PRIMARY KEY (plan_id),
	CONSTRAINT plan_fk_document_id_fkey FOREIGN KEY (fk_document_id) REFERENCES "document"(document_id)
);


-- art.profile definition

-- Drop table

-- DROP TABLE profile;

CREATE TABLE profile (
	profile_id int4 GENERATED ALWAYS AS IDENTITY NOT NULL,
	fk_contact_id int4 NOT NULL,
	active bool DEFAULT false NULL,
	modified_by int4 NOT NULL,
	created_dt timestamp DEFAULT CURRENT_TIMESTAMP NULL,
	modified_dt timestamp DEFAULT CURRENT_TIMESTAMP NULL,
	CONSTRAINT pk_profile_id PRIMARY KEY (profile_id),
	CONSTRAINT profile_fk_contact_id_fkey FOREIGN KEY (fk_contact_id) REFERENCES contact(contact_id) ON DELETE CASCADE,
	CONSTRAINT profile_modified_by_fkey FOREIGN KEY (modified_by) REFERENCES profile(profile_id)
);


-- art.staff definition

-- Drop table

-- DROP TABLE staff;

CREATE TABLE staff (
	fk_profile_id int4 NOT NULL,
	"position" varchar(14) NOT NULL,
	CONSTRAINT check_position CHECK ((("position")::text = ANY ((ARRAY['Director'::character varying, 'Curator'::character varying, 'Art Handler'::character varying, 'Registrar'::character varying, 'Associate'::character varying])::text[]))),
	CONSTRAINT pk_staff PRIMARY KEY (fk_profile_id),
	CONSTRAINT staff_fk_profile_id_fkey FOREIGN KEY (fk_profile_id) REFERENCES profile(profile_id)
);


-- art."subscription" definition

-- Drop table

-- DROP TABLE "subscription";

CREATE TABLE "subscription" (
	fk_plan_id int4 NOT NULL,
	fk_contact_id int4 NOT NULL,
	modified_by int4 NULL,
	created_dt timestamp DEFAULT CURRENT_TIMESTAMP NULL,
	modified_dt timestamp DEFAULT CURRENT_TIMESTAMP NULL,
	CONSTRAINT pk_subscription PRIMARY KEY (fk_plan_id, fk_contact_id),
	CONSTRAINT subscription_fk_contact_id_fkey FOREIGN KEY (fk_contact_id) REFERENCES contact(contact_id),
	CONSTRAINT subscription_fk_plan_id_fkey FOREIGN KEY (fk_plan_id) REFERENCES "plan"(plan_id)
);


-- art.task_history definition

-- Drop table

-- DROP TABLE task_history;

CREATE TABLE task_history (
	task_id int4 GENERATED ALWAYS AS IDENTITY NOT NULL,
	assigned_to_profile_id int4 NOT NULL,
	created_by_profile_id int4 NOT NULL,
	related_entity_type varchar(32) NULL,
	related_entity_id int4 NULL,
	task_type varchar(32) NOT NULL,
	task_title varchar(64) NOT NULL,
	description varchar(128) NULL,
	fk_document_id int4 NULL,
	status varchar(16) DEFAULT 'pending'::character varying NULL,
	due_date timestamp NULL,
	completed_at timestamp NULL,
	created_at timestamp DEFAULT CURRENT_TIMESTAMP NULL,
	updated_at timestamp DEFAULT CURRENT_TIMESTAMP NULL,
	CONSTRAINT chk_status CHECK (((status)::text = ANY ((ARRAY['pending'::character varying, 'in_progress'::character varying, 'completed'::character varying, 'cancelled'::character varying])::text[]))),
	CONSTRAINT task_history_pkey PRIMARY KEY (task_id),
	CONSTRAINT task_history_fk_document_id_fkey FOREIGN KEY (fk_document_id) REFERENCES "document"(document_id)
);


-- art.userrole definition

-- Drop table

-- DROP TABLE userrole;

CREATE TABLE userrole (
	fk_profile_id int4 NOT NULL,
	rolename varchar(16) NULL,
	passwordhash varchar(256) DEFAULT NULL::character varying NULL,
	CONSTRAINT check_role CHECK (((rolename)::text = ANY ((ARRAY['SYSTEM'::character varying, 'CONTACT'::character varying, 'CUSTOMER'::character varying, 'STAFF'::character varying, 'SUPPLIER'::character varying])::text[]))),
	CONSTRAINT pk_userrole PRIMARY KEY (fk_profile_id),
	CONSTRAINT userrole_fk_profile_id_fkey FOREIGN KEY (fk_profile_id) REFERENCES profile(profile_id) ON DELETE CASCADE
);


-- art.address definition

-- Drop table

-- DROP TABLE address;

CREATE TABLE address (
	zip varchar(5) NOT NULL,
	fk_contact_id int4 NOT NULL,
	street varchar(32) NOT NULL,
	CONSTRAINT pk_address PRIMARY KEY (zip, fk_contact_id),
	CONSTRAINT address_fk_contact_id_fkey FOREIGN KEY (fk_contact_id) REFERENCES contact(contact_id) ON DELETE CASCADE,
	CONSTRAINT address_zip_fkey FOREIGN KEY (zip) REFERENCES zip(zip)
);


-- art.authorize definition

-- Drop table

-- DROP TABLE authorize;

CREATE TABLE authorize (
	authorization_id int4 GENERATED ALWAYS AS IDENTITY NOT NULL,
	fk_contact_id int4 NULL,
	authorization_status varchar(16) NOT NULL,
	authorization_date timestamp DEFAULT CURRENT_TIMESTAMP NULL,
	expiration_date timestamp DEFAULT CURRENT_TIMESTAMP NULL,
	fk_document_id int4 NULL,
	modified_by int4 NULL,
	created_dt timestamp DEFAULT CURRENT_TIMESTAMP NULL,
	modified_dt timestamp DEFAULT CURRENT_TIMESTAMP NULL,
	CONSTRAINT authorize_pkey PRIMARY KEY (authorization_id),
	CONSTRAINT check_authorization_status CHECK (((authorization_status)::text = ANY ((ARRAY['pending'::character varying, 'approved'::character varying, 'rejected'::character varying, 'expired'::character varying])::text[]))),
	CONSTRAINT authorize_fk_contact_id_fkey FOREIGN KEY (fk_contact_id) REFERENCES contact(contact_id),
	CONSTRAINT authorize_fk_document_id_fkey FOREIGN KEY (fk_document_id) REFERENCES "document"(document_id)
);


-- art.inventory definition

-- Drop table

-- DROP TABLE inventory;

CREATE TABLE inventory (
	inventory_id int4 GENERATED ALWAYS AS IDENTITY NOT NULL,
	fk_contact_id int4 NOT NULL,
	fk_authorization_id int4 NULL,
	sku varchar(100) NOT NULL,
	product_description varchar(100) NOT NULL,
	unit_cost numeric(10, 2) NOT NULL,
	lead_time_days int4 NOT NULL,
	product_name varchar(100) NOT NULL,
	unit_of_measure varchar(50) NOT NULL,
	base_price numeric(10, 2) NOT NULL,
	quantity_available int4 DEFAULT 0 NOT NULL,
	created_at timestamp DEFAULT CURRENT_TIMESTAMP NULL,
	updated_at timestamp DEFAULT CURRENT_TIMESTAMP NULL,
	fk_document_id int4 NULL,
	CONSTRAINT inventory_pkey PRIMARY KEY (inventory_id),
	CONSTRAINT supplier_unique_sku UNIQUE (fk_contact_id, sku),
	CONSTRAINT inventory_fk_authorization_id_fkey FOREIGN KEY (fk_authorization_id) REFERENCES authorize(authorization_id),
	CONSTRAINT inventory_fk_contact_id_fkey FOREIGN KEY (fk_contact_id) REFERENCES contact(contact_id),
	CONSTRAINT inventory_fk_document_id_fkey FOREIGN KEY (fk_document_id) REFERENCES "document"(document_id)
);


-- art.invoice definition

-- Drop table

-- DROP TABLE invoice;

CREATE TABLE invoice (
	invoice_id uuid DEFAULT gen_random_uuid() NOT NULL,
	fk_plan_id int4 NULL,
	fk_contact_id int4 NULL,
	invoicedate date NULL,
	amountpaid numeric(10, 2) DEFAULT 0 NULL,
	CONSTRAINT invoice_pkey PRIMARY KEY (invoice_id),
	CONSTRAINT invoice_fk_contact_id_fkey FOREIGN KEY (fk_contact_id) REFERENCES contact(contact_id),
	CONSTRAINT invoice_fk_plan_id_fkey FOREIGN KEY (fk_plan_id) REFERENCES "plan"(plan_id)
);


-- art.order_items definition

-- Drop table

-- DROP TABLE order_items;

CREATE TABLE order_items (
	order_item_id int4 GENERATED ALWAYS AS IDENTITY NOT NULL,
	fk_profile_id int4 NOT NULL,
	transaction_id varchar(32) NULL,
	created_at timestamp NOT NULL,
	quantity int4 DEFAULT 1 NOT NULL,
	unit_price numeric(10, 2) NOT NULL,
	line_total numeric(10, 2) NOT NULL,
	fk_inventory_id int4 NOT NULL,
	CONSTRAINT order_items_pkey PRIMARY KEY (order_item_id),
	CONSTRAINT order_items_fk_inventory_id_fkey FOREIGN KEY (fk_inventory_id) REFERENCES inventory(inventory_id),
	CONSTRAINT order_items_fk_profile_id_fkey FOREIGN KEY (fk_profile_id) REFERENCES profile(profile_id)
);


-- art.exhibit definition

-- Drop table

-- DROP TABLE exhibit;

CREATE TABLE exhibit (
	exhibit_id int4 GENERATED ALWAYS AS IDENTITY NOT NULL,
	fk_inventory_id int4 NOT NULL,
	fk_plan_id int4 NULL,
	CONSTRAINT exhibit_pkey PRIMARY KEY (exhibit_id),
	CONSTRAINT exhibit_fk_inventory_id_fkey FOREIGN KEY (fk_inventory_id) REFERENCES inventory(inventory_id),
	CONSTRAINT exhibit_fk_plan_id_fkey FOREIGN KEY (fk_plan_id) REFERENCES "plan"(plan_id)
);


/* VIEW of available exhibit inventory */
CREATE OR REPLACE VIEW view_available_inventory
AS SELECT inventory.inventory_id,
    inventory.fk_contact_id,
    inventory.fk_authorization_id,
    inventory.sku,
    inventory.product_description,
    inventory.unit_cost,
    inventory.lead_time_days,
    inventory.product_name,
    inventory.unit_of_measure,
    inventory.base_price,
    inventory.quantity_available,
    inventory.created_at,
    inventory.updated_at,
    inventory.fk_document_id
   FROM art.inventory
  WHERE inventory.quantity_available > 0
INTERSECT
 SELECT exhibit.fk_inventory_id AS inventory_id,
    NULL::integer AS fk_contact_id,
    NULL::integer AS fk_authorization_id,
    NULL::character varying AS sku,
    NULL::character varying AS product_description,
    NULL::numeric AS unit_cost,
    NULL::integer AS lead_time_days,
    NULL::character varying AS product_name,
    NULL::character varying AS unit_of_measure,
    NULL::numeric AS base_price,
    NULL::integer AS quantity_available,
    NULL::timestamp without time zone AS created_at,
    NULL::timestamp without time zone AS updated_at,
    NULL::integer AS fk_document_id
   FROM art.exhibit;

CREATE OR REPLACE VIEW VIEW_SYSTEMROLE AS
	SELECT u.FK_PROFILE_ID, p.FK_CONTACT_ID,  u.ROLENAME, p.ACTIVE  FROM
	USERROLE u
	JOIN PROFILE p ON p.PROFILE_ID=u.FK_PROFILE_ID AND u.ROLENAME = 'SYSTEM';

CREATE OR REPLACE VIEW VIEW_STAFF AS
	SELECT u.FK_PROFILE_ID, p.FK_CONTACT_ID,  u.ROLENAME, p.ACTIVE, c.FIRST_NAME, c.LAST_NAME, s.POSITION FROM
	USERROLE u
	JOIN PROFILE p ON p.PROFILE_ID=u.FK_PROFILE_ID AND u.ROLENAME = 'STAFF'
	JOIN CONTACT c ON c.CONTACT_ID = p.FK_CONTACT_ID
    JOIN STAFF s on s.FK_PROFILE_ID = p.PROFILE_ID;

CREATE OR REPLACE VIEW VIEW_SUPPLIER AS
	SELECT u.FK_PROFILE_ID, p.FK_CONTACT_ID,  u.ROLENAME, p.ACTIVE, c.FIRST_NAME, c.LAST_NAME FROM
	USERROLE u
	JOIN PROFILE p ON p.PROFILE_ID=u.FK_PROFILE_ID AND u.ROLENAME = 'SUPPLIER'
	JOIN CONTACT c ON c.CONTACT_ID = p.FK_CONTACT_ID;

CREATE OR REPLACE VIEW VIEW_CUSTOMER AS
	SELECT u.FK_PROFILE_ID, p.FK_CONTACT_ID,  u.ROLENAME, p.ACTIVE, c.FIRST_NAME, c.LAST_NAME FROM
	USERROLE u
	JOIN PROFILE p ON p.PROFILE_ID=u.FK_PROFILE_ID AND u.ROLENAME = 'CUSTOMER'
	JOIN CONTACT c ON c.CONTACT_ID = p.FK_CONTACT_ID;

-- Trigger Function Paid Invoice, generates subscription
CREATE OR REPLACE FUNCTION invoice_paid_subscription()
 RETURNS trigger
 LANGUAGE plpgsql
AS $function$
BEGIN
    INSERT INTO SUBSCRIPTION (FK_PLAN_ID, FK_CONTACT_ID) VALUES (NEW.FK_PLAN_ID, NEW.FK_CONTACT_ID);
    RETURN NEW;
END;
$function$
;
-- Trigger on invoice
create trigger paid_subscription after
insert
    on invoice for each row
    execute function invoice_paid_subscription();

CREATE OR REPLACE FUNCTION ORDER_ITEMS_reserved()
 RETURNS trigger
 LANGUAGE plpgsql
AS $function$
BEGIN
    UPDATE INVENTORY SET QUANTITY_AVAILABLE = QUANTITY_AVAILABLE - NEW.QUANTITY WHERE INVENTORY_ID= NEW.FK_INVENTORY_ID;
    RETURN NEW;
END;
$function$
;
-- Trigger on ORDER_ITEMS customer ordered items reservation
CREATE TRIGGER ORDER_ITEMS_reserved AFTER
INSERT
     ON ORDER_ITEMS FOR EACH ROW
     execute function ORDER_ITEMS_reserved();
