CREATE LANGUAGE plpgsql;

ALTER TABLE sales_hashes_products ADD COLUMN business_date DATE;

CREATE OR REPLACE FUNCTION document_operations_value_field() RETURNS text
    LANGUAGE plpgsql
    AS $$
BEGIN

  IF NOT EXISTS (SELECT data_type FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'document_operations' AND COLUMN_NAME = 'value')
  THEN
    RAISE NOTICE '!! DOCUMENT_OPERATIONS ISNT CORRECT !!';
    DROP TABLE document_operations;
  ELSE
    RAISE NOTICE 'DOCUMENT_OPERATIONS IS CORRECT';
  END IF;

  RETURN NULL;
END;
$$;

CREATE OR REPLACE FUNCTION check_sales_details_aux_header_field() RETURNS text
    LANGUAGE plpgsql
    AS $$
BEGIN

  IF NOT EXISTS (SELECT data_type FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'sales_details_aux' AND COLUMN_NAME = 'header')
  THEN
    RAISE NOTICE '!! SALES_DETAILS_AUX ISNT CORRECT !!';
    DROP TABLE sales_details_aux;
  ELSE
    RAISE NOTICE 'SALES_DETAILS_AUX IS CORRECT';
  END IF;

  RETURN NULL;
END;
$$;

CREATE OR REPLACE FUNCTION check_sales_hashes_id_field() RETURNS text
    LANGUAGE plpgsql
    AS $$
BEGIN
  IF NOT EXISTS (SELECT data_type FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'sales_hashes' AND COLUMN_NAME = 'id' AND DATA_TYPE = 'character varying')
  THEN
    RAISE NOTICE '!! ID IN SALES HASHES ISNT CORRECT !!';

    DROP SEQUENCE sales_hashes_seq;
    DROP TABLE sales_hashes_products CASCADE;
    DROP TABLE sales_hashes CASCADE;

    CREATE TABLE sales_hashes (
      id VARCHAR(36),
      header INTEGER NOT NULL REFERENCES sales_headers(id),
      gb_identifier_header VARCHAR(30) NOT NULL,
      business_date DATE NOT NULL,
      system_entry_date VARCHAR(19) NOT NULL,
      fo_doc_number VARCHAR(50) NOT NULL,
      value NUMERIC DEFAULT 0 NOT NULL,
      hash VARCHAR(172) NOT NULL,
      hash_small VARCHAR(15) NOT NULL,
      doc_type INTEGER NOT NULL DEFAULT 1,
      PRIMARY KEY (id)
    );

    CREATE INDEX idx_sales_hashes_id ON sales_hashes (id);
    CREATE INDEX idx_sales_hashes_doc_type ON sales_hashes (doc_type);
    CREATE INDEX idx_sales_hashes_header ON sales_hashes (header);
    CREATE INDEX idx_sales_hashes_gb_identifier_header ON sales_hashes (gb_identifier_header);

    CREATE TABLE sales_hashes_products (
      hash_id VARCHAR(36) NOT NULL REFERENCES sales_hashes(id),
      gb_identifier_detail VARCHAR(30) NOT NULL,
      business_date DATE NOT NULL
    );

    CREATE INDEX idx_sales_hashes_products_hash_id ON sales_hashes_products (hash_id);
    CREATE INDEX idx_sales_hashes_products_gb_identifier_detail ON sales_hashes_products (gb_identifier_detail);
    CREATE INDEX idx_sales_hashes_products_business_date ON sales_hashes_products (business_date);
  ELSE
    RAISE NOTICE 'ID IN SALES HASHES IS ALREADY CORRECT';
  END IF;

  RETURN NULL;
END;
$$;

CREATE OR REPLACE FUNCTION check_sales_headers_date_fields() RETURNS text
    LANGUAGE plpgsql
    AS $$
BEGIN
  IF NOT EXISTS (SELECT data_type FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'sales_headers' AND COLUMN_NAME = 'date' AND DATA_TYPE = 'timestamp without time zone')
  THEN
    RAISE NOTICE '!! DATES IN SALES HEADERS ARENT CORRECT !!';

    EXECUTE 'ALTER TABLE sales_headers ALTER date TYPE TIMESTAMP';
    EXECUTE 'ALTER TABLE sales_headers ALTER date_closed TYPE TIMESTAMP';
  ELSE
    RAISE NOTICE 'DATES IN SALES_HEADERS ARE CORRECT ALREADY';
  END IF;

  RETURN NULL;
END;
$$;

CREATE OR REPLACE FUNCTION date_partitioned_insert_trigger() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
DECLARE
  start_date text;
  stop_date text;
  yyyymm text;
BEGIN
  yyyymm := to_char(NEW.business_date, 'yyyymm');

  EXECUTE 'INSERT INTO ' || TG_TABLE_NAME || '_' || yyyymm || ' SELECT (' || quote_literal(NEW) || '::' || TG_TABLE_NAME || ').*';
  RETURN NULL;
EXCEPTION
  WHEN undefined_table THEN
    start_date := to_char(NEW.business_date, 'yyyy-mm-01');
    stop_date := to_char(date(NEW.business_date + interval '1 month'), 'yyyy-mm-01');

    RAISE NOTICE 'Table Does Not Exist. Will Create % % %', start_date, stop_date, TG_TABLE_NAME;
    PERFORM date_partitioned_create_table(TG_TABLE_NAME, yyyymm, start_date, stop_date);

    EXECUTE 'INSERT INTO ' || TG_TABLE_NAME || '_' || yyyymm || ' SELECT (' || quote_literal(NEW) || '::' || TG_TABLE_NAME || ').*';
    RETURN NULL;
END;
$$;

CREATE OR REPLACE FUNCTION date_partitioned_create_table(ptable_name text, yyyymm text, start_date text, stop_date text) RETURNS text
    LANGUAGE plpgsql
    AS $$
BEGIN
    EXECUTE 'CREATE TABLE ' || ptable_name || '_' || yyyymm || ' (CHECK ( business_date >= DATE ''' || start_date || ''' AND business_date < DATE ''' || stop_date || ''')) INHERITS (' || ptable_name || ')';

    IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ptable_name AND COLUMN_NAME = 'id')
    THEN
      EXECUTE 'ALTER TABLE ' || ptable_name || '_' || yyyymm || ' ADD CONSTRAINT ' || ptable_name || '_' || yyyymm || '_pk PRIMARY KEY (id)';
    END IF;
    
    IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ptable_name AND COLUMN_NAME = 'business_date')
    THEN
      EXECUTE 'CREATE INDEX ' || ptable_name || '_' || yyyymm || '_idx_bdate ON ' || ptable_name || '_' || yyyymm || '(business_date)';
    END IF;

    IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ptable_name AND COLUMN_NAME = 'doc_type')
    THEN
      EXECUTE 'CREATE INDEX ' || ptable_name || '_' || yyyymm || '_idx_doctype ON ' || ptable_name || '_' || yyyymm || '(doc_type)';
    END IF;    
    
    IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ptable_name AND COLUMN_NAME = 'fo_doc_number')
    THEN
      EXECUTE 'CREATE INDEX ' || ptable_name || '_' || yyyymm || '_idx_fo_doc_number ON ' || ptable_name || '_' || yyyymm || '(fo_doc_number)';
    END IF; 
    
    IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ptable_name AND COLUMN_NAME = 'clerk_close')
    THEN
      EXECUTE 'CREATE INDEX ' || ptable_name || '_' || yyyymm || '_idx_clerk_close ON ' || ptable_name || '_' || yyyymm || '(clerk_close)';
    END IF;
    
--    IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ptable_name AND COLUMN_NAME = 'header')
--    THEN
--      EXECUTE 'CREATE INDEX ' || ptable_name || '_' || yyyymm || '_idx_header ON ' || ptable_name || '_' || yyyymm || '(header)';
--      EXECUTE 'ALTER TABLE ' || ptable_name || '_' || yyyymm || ' ADD CONSTRAINT ' || ptable_name || '_' || yyyymm || '_fk_header FOREIGN KEY (header) REFERENCES sales_headers_' || yyyymm || '(id)';
--    END IF;
 
    IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ptable_name AND COLUMN_NAME = 'operation_type')
    THEN
      EXECUTE 'CREATE INDEX ' || ptable_name || '_' || yyyymm || '_idx_operation_type ON ' || ptable_name || '_' || yyyymm || '(operation_type)';
    END IF; 

    IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ptable_name AND COLUMN_NAME = 'product')
    THEN
      EXECUTE 'CREATE INDEX ' || ptable_name || '_' || yyyymm || '_idx_product ON ' || ptable_name || '_' || yyyymm || '(product)';
      EXECUTE 'ALTER TABLE ' || ptable_name || '_' || yyyymm || ' ADD CONSTRAINT ' || ptable_name || '_' || yyyymm || '_fk_product FOREIGN KEY (product) REFERENCES products(id)';
    END IF;    

    IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ptable_name AND COLUMN_NAME = 'clerk')
    THEN
      EXECUTE 'CREATE INDEX ' || ptable_name || '_' || yyyymm || '_idx_clerk ON ' || ptable_name || '_' || yyyymm || '(clerk)';
      EXECUTE 'ALTER TABLE ' || ptable_name || '_' || yyyymm || ' ADD CONSTRAINT ' || ptable_name || '_' || yyyymm || '_fk_clerk FOREIGN KEY (clerk) REFERENCES clerks(id)';
    END IF;

    IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ptable_name AND COLUMN_NAME = 'clerk_open')
    THEN
      EXECUTE 'CREATE INDEX ' || ptable_name || '_' || yyyymm || '_idx_clerk_open ON ' || ptable_name || '_' || yyyymm || '(clerk_open)';
      EXECUTE 'ALTER TABLE ' || ptable_name || '_' || yyyymm || ' ADD CONSTRAINT ' || ptable_name || '_' || yyyymm || '_fk_clerk_open FOREIGN KEY (clerk_open) REFERENCES clerks(id)';
    END IF;
    
    IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ptable_name AND COLUMN_NAME = 'clerk_close')
    THEN
      EXECUTE 'CREATE INDEX ' || ptable_name || '_' || yyyymm || '_idx_clerk ON ' || ptable_name || '_' || yyyymm || '(clerk_close)';
      EXECUTE 'ALTER TABLE ' || ptable_name || '_' || yyyymm || ' ADD CONSTRAINT ' || ptable_name || '_' || yyyymm || '_fk_clerk_close FOREIGN KEY (clerk_close) REFERENCES clerks(id)';
    END IF;
    
    IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ptable_name AND COLUMN_NAME = 'hash_id')
    THEN
      EXECUTE 'CREATE INDEX ' || ptable_name || '_' || yyyymm || '_idx_clerk ON ' || ptable_name || '_' || yyyymm || '(hash_id)';
      EXECUTE 'ALTER TABLE ' || ptable_name || '_' || yyyymm || ' ADD CONSTRAINT ' || ptable_name || '_' || yyyymm || '_fk_header FOREIGN KEY (hash_id) REFERENCES sales_hashes_' || yyyymm || '(id)';
    END IF;
    
    RETURN NULL;
END;
$$;

CREATE OR REPLACE FUNCTION add2db_business_date() RETURNS void LANGUAGE plpgsql
AS $$
BEGIN
  IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'sales_details' AND COLUMN_NAME = 'business_date')
  THEN
    RAISE NOTICE 'Nothing to DO';
  ELSE 
    RAISE NOTICE 'Applying Changes';
    ALTER TABLE sales_details ADD COLUMN business_date DATE;
    CREATE INDEX idx_sales_details_business_date ON sales_details (business_date);
    
    UPDATE sales_details SET business_date = sh.business_date
    FROM sales_headers sh
    WHERE sales_details.header = sh.id
    AND sales_details.business_date IS NULL;
    
    ALTER TABLE sales_payments ADD COLUMN business_date DATE;
    CREATE INDEX idx_sales_payments_business_date ON sales_payments (business_date);
    
    UPDATE sales_payments SET business_date = sh.business_date
    FROM sales_headers sh
    WHERE sales_payments.header = sh.id
    AND sales_payments.business_date IS NULL;
    
    ALTER TABLE sales_details ALTER COLUMN business_date SET NOT NULL;
    ALTER TABLE sales_payments ALTER COLUMN business_date SET NOT NULL;
  END IF;

  IF EXISTS (SELECT * FROM pg_trigger WHERE tgname='insert_sales_headers_trigger') 
  THEN
    RAISE NOTICE 'Nothing to DO';
  ELSE 
    RAISE NOTICE 'Applying PARTITIONING';

    CREATE TRIGGER insert_sales_details_trigger
    BEFORE INSERT ON sales_details
    FOR EACH ROW
    EXECUTE PROCEDURE date_partitioned_insert_trigger();

    CREATE TRIGGER insert_sales_headers_trigger
    BEFORE INSERT ON sales_headers
    FOR EACH ROW
    EXECUTE PROCEDURE date_partitioned_insert_trigger();

    CREATE TRIGGER insert_sales_payments_trigger
    BEFORE INSERT ON sales_payments
    FOR EACH ROW
    EXECUTE PROCEDURE date_partitioned_insert_trigger();
    
    CREATE TABLE sales_headers_copy (LIKE sales_headers);
    CREATE TABLE sales_details_copy (LIKE sales_details);
    CREATE TABLE sales_payments_copy (LIKE sales_payments);
    
    INSERT INTO sales_headers_copy SELECT * FROM sales_headers;
    INSERT INTO sales_details_copy SELECT * FROM sales_details;
    INSERT INTO sales_payments_copy SELECT * FROM sales_payments; 
    
    DELETE FROM sales_payments;
    DELETE FROM sales_details;
    DELETE FROM sales_headers;

    INSERT INTO sales_headers SELECT * FROM sales_headers_copy;
    INSERT INTO sales_details SELECT * FROM sales_details_copy;
    INSERT INTO sales_payments SELECT * FROM sales_payments_copy; 
  END IF;

  IF EXISTS (SELECT * FROM pg_trigger WHERE tgname='insert_sales_hashes_trigger')
  THEN
    RAISE NOTICE 'Nothing to DO';
  ELSE 
    RAISE NOTICE 'Applying PARTITIONING HASHES';
    
    CREATE TRIGGER insert_sales_hashes_trigger
    BEFORE INSERT ON sales_hashes
    FOR EACH ROW
    EXECUTE PROCEDURE date_partitioned_insert_trigger();
    
    CREATE TRIGGER insert_sales_hashes_products_trigger
    BEFORE INSERT ON sales_hashes_products
    FOR EACH ROW
    EXECUTE PROCEDURE date_partitioned_insert_trigger();

    UPDATE sales_hashes_products SET business_date = sales_hashes.business_date FROM sales_hashes WHERE sales_hashes.id = sales_hashes_products.hash_id;

    DROP TABLE IF EXISTS sales_hashes_products_copy;
    DROP TABLE IF EXISTS sales_hashes_copy;
    CREATE TABLE sales_hashes_copy (LIKE sales_hashes);    
    CREATE TABLE sales_hashes_products_copy (LIKE sales_hashes_products); 
    
    INSERT INTO sales_hashes_copy SELECT * FROM sales_hashes;    
    INSERT INTO sales_hashes_products_copy SELECT * FROM sales_hashes_products;
    
    DELETE FROM sales_hashes_products;
    DELETE FROM sales_hashes;
   
    INSERT INTO sales_hashes SELECT * FROM sales_hashes_copy;
    INSERT INTO sales_hashes_products SELECT * FROM sales_hashes_products_copy;

    DELETE FROM sales_hashes_copy;
    DELETE FROM sales_hashes_products_copy;
  END IF;
END;
$$;

BEGIN;
SELECT add2db_business_date();
COMMIT;
DROP FUNCTION add2db_business_date();

SELECT check_sales_headers_date_fields();
DROP FUNCTION check_sales_headers_date_fields();

SELECT check_sales_details_aux_header_field();
DROP FUNCTION check_sales_details_aux_header_field();

SELECT document_operations_value_field();
DROP FUNCTION document_operations_value_field();

SELECT check_sales_hashes_id_field();
DROP FUNCTION check_sales_hashes_id_field();

ALTER TABLE clerks ADD can_login INTEGER DEFAULT 1;
ALTER TABLE products ADD require_extras INTEGER DEFAULT 0;
ALTER TABLE products ADD which_extras VARCHAR(255);
ALTER TABLE groups ADD button_bg_color VARCHAR(10);
ALTER TABLE products ADD button_bg_color VARCHAR(10);
ALTER TABLE lists ADD for_reporting INTEGER DEFAULT 0;
ALTER TABLE products_lists DROP CONSTRAINT products_lists_product_id_fkey;
ALTER TABLE products ADD qtty_factor NUMERIC DEFAULT 0;
ALTER TABLE sales_details ALTER gb_identifier TYPE VARCHAR(50);
ALTER TABLE sales_hashes ALTER gb_identifier_header TYPE VARCHAR(50);
ALTER TABLE sales_hashes_products ALTER gb_identifier_detail TYPE VARCHAR(50);
ALTER TABLE sales_hashes ADD COLUMN atcud VARCHAR(20);
ALTER TABLE sales_headers ALTER customer_nif TYPE VARCHAR(50);

CREATE SEQUENCE transfers_seq INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1;
CREATE TABLE transfers (
  id INT NOT NULL,
  date DATE NOT NULL,
  hour VARCHAR(8) NOT NULL DEFAULT '00:00:00',
  station INTEGER,
  clerk INTEGER,
  clerk_name VARCHAR,
  area_from INTEGER,
  area_to INTEGER,
  table_from VARCHAR(5),
  table_to VARCHAR(5),
  PRIMARY KEY (id)
);

CREATE TABLE transfer_products (
  transfer_id INTEGER NOT NULL REFERENCES transfers(id),
  product_id INTEGER NOT NULL REFERENCES products(id),
  product_name VARCHAR,
  quantity NUMERIC DEFAULT 0
);

CREATE TABLE product_names (
  product_id INTEGER NOT NULL REFERENCES products(id),
  language VARCHAR NOT NULL,
  value VARCHAR NOT NULL
);

ALTER TABLE products ADD handy_plu INTEGER DEFAULT 0;
ALTER TABLE products ADD require_extra_data INTEGER DEFAULT 0;
ALTER TABLE transfer_products ADD hour_registered VARCHAR(8);
ALTER TABLE customers ADD contact VARCHAR(50);
ALTER TABLE customers ADD aux VARCHAR(255);
ALTER TABLE customers ADD total_credit NUMERIC DEFAULT 0;
CREATE INDEX idx_sales_headers_customer ON sales_headers (customer);
CREATE INDEX idx_sales_headers_customer_nif ON sales_headers (customer_nif);
ALTER TABLE clerks ADD cant_suspend INTEGER DEFAULT 0;
ALTER TABLE clerks ADD cant_print_bill INTEGER DEFAULT 0;
ALTER TABLE clerks ADD cant_print_bill_internal INTEGER DEFAULT 0;
ALTER TABLE products ADD image VARCHAR(20);
ALTER TABLE groups ADD image VARCHAR(20);
ALTER TABLE clerks ADD consumption_discount NUMERIC DEFAULT 0;
CREATE INDEX idx_customers_nif ON customers (nif);
CREATE INDEX idx_customers_card_number ON customers (card_number);
CREATE INDEX idx_customers_app_sign_key ON customers (app_sign_key);
ALTER TABLE sales_hashes ALTER system_entry_date TYPE VARCHAR(19);
ALTER TABLE sales_hashes_products ADD COLUMN business_date DATE;
ALTER TABLE sales_headers ADD gb_identifier VARCHAR(40);
ALTER TABLE clerks ADD blocked_stations VARCHAR(30);
ALTER TABLE clerks ADD commission_group VARCHAR(100);
ALTER TABLE customers ADD discount_group VARCHAR(100);
ALTER TABLE products ADD product_group VARCHAR(100);
ALTER TABLE sales_hashes ALTER header DROP NOT NULL;
ALTER TABLE clerks ADD tables VARCHAR(50);

CREATE TABLE commissions (
  clerkgroup VARCHAR(100) NOT NULL,
  productgroup VARCHAR(100) NOT NULL,
  value NUMERIC DEFAULT 0
);

CREATE TABLE discounts (
  customergroup VARCHAR(100) NOT NULL,
  productgroup VARCHAR(100) NOT NULL,
  value NUMERIC DEFAULT 0
);

CREATE TABLE products_extra_data (
  product_id INTEGER NOT NULL REFERENCES products(id),
  field_name VARCHAR NOT NULL,
  field_value VARCHAR
);

CREATE TABLE document_operations (
  source_gb_identifier character varying(40),
  dest_gb_identifier character varying(40),
  value NUMERIC DEFAULT 0
);

CREATE TABLE sales_details_aux (
  header INTEGER NOT NULL,
  product_id INTEGER NOT NULL,
  gb_identifier VARCHAR(50) NOT NULL,
  key_name VARCHAR(100) NOT NULL,
  key_value VARCHAR(100)
);

ALTER TABLE sales_headers ADD serie VARCHAR(15);
CREATE INDEX idx_sales_headers_serie ON sales_headers(serie);

ALTER TABLE customers ADD days_to_pay INTEGER DEFAULT 0;
ALTER TABLE products ALTER handy_plu TYPE NUMERIC;
ALTER TABLE product_daily_specials ADD group_id INTEGER;
ALTER TABLE clerks ADD drawer VARCHAR(5);
ALTER TABLE sales_hashes DROP CONSTRAINT sales_hashes_header_fkey;
ALTER TABLE sales_headers_aux DROP CONSTRAINT sales_headers_aux_header_fkey;
ALTER TABLE products ALTER image TYPE VARCHAR(100);
ALTER TABLE groups ALTER image TYPE VARCHAR(100);
ALTER TABLE clerks ALTER can_edit_tables TYPE VARCHAR(50);
ALTER TABLE clerks ADD cant_close_others_tables INTEGER DEFAULT 0;
ALTER TABLE products ALTER handy_plu TYPE VARCHAR(100);
CREATE INDEX idx_products_handy_plu ON products (handy_plu);

CREATE TABLE contents_last_update (
  content_type VARCHAR(50) NOT NULL,
  content_id INTEGER NOT NULL,
  timestamp TIMESTAMP NOT NULL,
  UNIQUE (content_type, content_id)
);

CREATE TABLE suppliers (
  id INT NOT NULL,
  name VARCHAR(150),
  nif VARCHAR(100),
  discount NUMERIC DEFAULT 0,
  address VARCHAR(255),
  postal_code VARCHAR(20),
  city VARCHAR(100),
  days_to_pay INTEGER DEFAULT 0,
  deleted INTEGER DEFAULT 0,
  aux VARCHAR(255),
  contact VARCHAR(50),
  PRIMARY KEY (id)
);

CREATE INDEX idx_suppliers_nif ON suppliers (nif);
CREATE SEQUENCE suppliers_seq INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1;


-- product_id: id of the 'promotion' product
-- promotion_type: 0 - new price, 1 - % discount, 2 - product offer
--   0 > neste modo, o promotion_trigger terá o id do produto a que o novo preço será aplicado e o promotion_data terá o valor do novo preço.
--     este modo serve apenas para um produto ou para o exemplo "Fixed Price Promotion" que temos da Bleep.
--   1 > neste modo, o promotion_trigger terá o id do produto a que o desconto será aplicado e quando ele for registado, ficará com um desconto à linha do
--     que estiver no promotion trigger
--   2 > neste modo, quando se registar o produto que está no campo promotion_trigger, ele oferecerá o que está no promotion_data
--
-- Exemplos para o promotion_trigger: P123=2 D17=1  (dois produtos com o codigo 123 e um produto da familia 17)
--
CREATE TABLE product_promotions (
  id INT NOT NULL,
  product_id INTEGER NOT NULL REFERENCES products(id),
  date_from TIMESTAMP NOT NULL,
  date_to TIMESTAMP NOT NULL,
  priority INT DEFAULT 0,
  promotion_type INT DEFAULT 0,
  promotion_trigger VARCHAR(50),
  promotion_data VARCHAR(50),
  PRIMARY KEY (id)
);

CREATE SEQUENCE product_promotions_seq INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1;

CREATE TABLE stock_movements (
  id INT NOT NULL,
  product_id INTEGER NOT NULL REFERENCES products(id),
  date DATE NOT NULL,
  quantity NUMERIC NOT NULL DEFAULT 0,
  cost_price NUMERIC NOT NULL DEFAULT 0,
  justification VARCHAR(255),
  PRIMARY KEY (id)
);

CREATE SEQUENCE stock_movements_seq INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1;

ALTER TABLE products ADD stock_use INTEGER DEFAULT 0;
ALTER TABLE products ADD stock_min NUMERIC DEFAULT 0;
ALTER TABLE products ADD stock_current NUMERIC DEFAULT 0;

ALTER TABLE sales_headers_aux ALTER key_value TYPE TEXT;
ALTER TABLE clerks ADD cant_hold INTEGER DEFAULT 0;
ALTER TABLE clerks ADD cant_open_cashiers INTEGER DEFAULT 0;

CREATE TABLE document_history (
  id INT NOT NULL,
  header INTEGER NOT NULL,
  gbi VARCHAR(50) NOT NULL,
  nif VARCHAR(50) NOT NULL,
  doc_date DATE NOT NULL,
  doc_type INTEGER NOT NULL,
  fo_doc_number VARCHAR(50) NOT NULL,
  doc_value NUMERIC NOT NULL,
  amount_payed NUMERIC NOT NULL
);

CREATE INDEX idx_document_history_nif ON document_history (nif);
CREATE INDEX idx_document_history_gbi ON document_history (gbi);
CREATE INDEX idx_document_history_nif_and_date ON document_history (nif,doc_date);
CREATE SEQUENCE document_history_seq INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1;

ALTER TABLE products ADD glink INTEGER DEFAULT 0;
ALTER TABLE groups ADD plink INTEGER DEFAULT 0;

CREATE TABLE schedules (
  id INT NOT NULL,
  schedule INTEGER NOT NULL DEFAULT 0,
  schedule_date DATE NOT NULL,
  start_hour VARCHAR(5) NOT NULL DEFAULT '00:00',
  end_hour VARCHAR(5) NOT NULL DEFAULT '00:00',
  description TEXT,
  gb_identifier VARCHAR(40)
);

ALTER TABLE schedules ADD PRIMARY KEY (id);
CREATE INDEX idx_schedules_schedule ON schedules (schedule);
CREATE INDEX idx_schedules_schedule_date ON schedules (schedule_date);
CREATE INDEX idx_schedules_gb_identifier ON schedules (gb_identifier);
CREATE SEQUENCE schedules_seq INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1;

CREATE TABLE cashiers (
  id INT NOT NULL,
  clerk INTEGER NOT NULL,
  station INTEGER NOT NULL,
  business_date DATE NOT NULL,
  number INTEGER NOT NULL,
  date_opened TIMESTAMP NOT NULL,
  date_closed TIMESTAMP,
  from_previous NUMERIC NOT NULL,
  to_next NUMERIC NOT NULL,
  sales NUMERIC NOT NULL,
  counted NUMERIC NOT NULL,
  PRIMARY KEY (id)
);

CREATE INDEX idx_cashiers_number ON cashiers (number);
CREATE SEQUENCE cashiers_seq INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1;

CREATE TABLE cashier_operations (
  cashier INT NOT NULL REFERENCES cashiers(id),
  clerk INTEGER NOT NULL,
  station INTEGER NOT NULL,
  date TIMESTAMP NOT NULL,
  operation VARCHAR(3) NOT NULL,
  description VARCHAR(255) NOT NULL,
  amount NUMERIC NOT NULL DEFAULT 0
);

ALTER TABLE customers ADD max_credit NUMERIC DEFAULT 0;
ALTER TABLE products ADD is_service INTEGER DEFAULT 0;
ALTER TABLE cashdrawer_opens ADD business_date DATE;
ALTER TABLE sales_details ALTER product_name TYPE VARCHAR(150);
ALTER TABLE sales_hashes ADD value_net numeric DEFAULT 0;
ALTER TABLE sales_headers ADD customer_id INTEGER DEFAULT 0;

DROP TABLE payment_medias;
DROP SEQUENCE payment_medias_seq;

ALTER TABLE sales_hashes_products ADD product_id INTEGER DEFAULT 0;
ALTER TABLE sales_hashes_products ADD price NUMERIC DEFAULT 0;
ALTER TABLE sales_hashes_products ADD price_wo_vat NUMERIC DEFAULT 0;
ALTER TABLE sales_hashes_products ADD quantity NUMERIC DEFAULT 0;
ALTER TABLE sales_hashes_products ADD discount NUMERIC DEFAULT 0;

CREATE TABLE counters (
  name VARCHAR,
  key VARCHAR,
  value VARCHAR,
  updated TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_counters_name_and_key ON counters (name, key);

CREATE TABLE card_sets (
  set_definition VARCHAR(100),
  minimal_consumption NUMERIC DEFAULT 0,
  maximum_consumption NUMERIC DEFAULT 0,
  inactive_cards INTEGER DEFAULT 0,
  clerk_id_for_comissions INTEGER DEFAULT 0,
  is_blacklisted INTEGER DEFAULT 0,
  product_list_for_offer VARCHAR(255),
  number_products_to_offer INTEGER DEFAULT 0,
  UNIQUE (set_definition)
);

ALTER TABLE card_sets ADD activated TIMESTAMP DEFAULT NOW();
ALTER TABLE sales_hashes ADD clerk_close INTEGER DEFAULT 0;
ALTER TABLE sales_hashes ADD customer_id INTEGER DEFAULT 0;
ALTER TABLE sales_hashes_products ADD vat NUMERIC DEFAULT 0;

CREATE INDEX idx_sales_headers_aux_key_name ON sales_headers_aux(key_name);
CREATE INDEX idx_sales_headers_aux_header ON sales_headers_aux(header);
ANALYZE sales_headers_aux;

CREATE INDEX idx_counters_name ON counters (name);
ANALYZE counters;

CREATE INDEX idx_document_history_header ON document_history(header);
CREATE INDEX idx_document_history_doc_type ON document_history(doc_type);
ANALYZE document_history;

ALTER TABLE clerks ADD priority INTEGER DEFAULT 0;
ALTER TABLE groups ADD vat NUMERIC DEFAULT -1;
ALTER TABLE products ADD credit SMALLINT DEFAULT 0;
ALTER TABLE customers ADD points NUMERIC DEFAULT 0;
ALTER TABLE stock_movements ADD operation VARCHAR(10) DEFAULT 'in';
ALTER TABLE clerks ALTER skin SET DEFAULT '';
ALTER TABLE clerks ADD serie INTEGER DEFAULT 1;
ALTER TABLE sales_hashes ADD serie INTEGER DEFAULT 1;
ALTER TABLE sales_hashes ADD table_num INTEGER DEFAULT 0;

ALTER TABLE products ADD type VARCHAR(1);
ALTER TABLE products ADD unit VARCHAR(20);

ALTER TABLE sales_headers ADD doc_serie VARCHAR(10);
CREATE INDEX idx_sales_headers_doc_serie ON sales_headers(doc_serie);

CREATE TABLE split_docs_link (
  gbi_old VARCHAR(40) NOT NULL,
  gbi_new VARCHAR(40) NOT NULL,
  business_date DATE NOT NULL
);

ALTER TABLE sales_details ADD had_bill SMALLINT DEFAULT 0;

ALTER TABLE clerks RENAME cant_print_bill_internal TO can_connect_stations;
ALTER TABLE clerks RENAME can_connect_stations TO open_blocked_checks;

ALTER TABLE counters ADD locked SMALLINT DEFAULT 0;

ALTER TABLE product_menus ADD id SERIAL;

ALTER TABLE customers ADD birthdate DATE;

CREATE TABLE special_prices (
  id SERIAL,
  name VARCHAR(100),
  date_from DATE NOT NULL,
  date_to DATE NOT NULL,
  hour_from VARCHAR(8) NOT NULL,
  hour_to VARCHAR(8) NOT NULL,
  PRIMARY KEY (id)
);

CREATE TABLE special_prices_products (
  id SERIAL,
  special_price_id INTEGER NOT NULL REFERENCES special_prices(id),
  product_id INTEGER NOT NULL,
  price NUMERIC NOT NULL DEFAULT 0,
  discount NUMERIC NOT NULL DEFAULT 0,
  PRIMARY KEY (id)
);

ALTER TABLE products ALTER barcode TYPE TEXT;
ALTER TABLE sales_hashes DROP serie_str;

CREATE TABLE scale_tickets_read (
  id SERIAL,
  business_date DATE NOT NULL,
  inserted TIMESTAMP NOT NULL DEFAULT NOW(),
  clerk INTEGER NOT NULL,
  station INTEGER NOT NULL,
  ticket_num INTEGER NOT NULL,
  num_products INTEGER NOT NULL,
  amount NUMERIC DEFAULT 0,
  PRIMARY KEY (id)
);

CREATE INDEX idx_scale_tickets_read_business_date ON scale_tickets_read(business_date);

ALTER TABLE sales_details ADD idx INTEGER DEFAULT 0;

ALTER TABLE products ADD modified TIMESTAMP DEFAULT NOW();
ALTER TABLE product_menus ADD modified TIMESTAMP DEFAULT NOW();
ALTER TABLE groups ADD modified TIMESTAMP DEFAULT NOW();
ALTER TABLE clerks ADD modified TIMESTAMP DEFAULT NOW();
ALTER TABLE customers ADD modified TIMESTAMP DEFAULT NOW();

CREATE OR REPLACE FUNCTION update_modified_column() 
RETURNS TRIGGER AS $$
BEGIN
    NOTIFY online_api_feeder;
    EXECUTE 'NOTIFY ' || TG_TABLE_NAME;
    NEW.modified = now();
    RETURN NEW; 
END;
$$ language 'plpgsql';

CREATE OR REPLACE FUNCTION notify_products() 
RETURNS TRIGGER AS $$
BEGIN
    NOTIFY online_api_feeder;
    EXECUTE 'NOTIFY products';
    RETURN NEW; 
END;
$$ language 'plpgsql';

CREATE TRIGGER update_product_modtime BEFORE UPDATE ON products FOR EACH ROW EXECUTE PROCEDURE update_modified_column();
CREATE TRIGGER update_clerk_modtime BEFORE UPDATE ON clerks FOR EACH ROW EXECUTE PROCEDURE update_modified_column();
CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON customers FOR EACH ROW EXECUTE PROCEDURE update_modified_column();
CREATE TRIGGER update_group_modtime BEFORE UPDATE ON groups FOR EACH ROW EXECUTE PROCEDURE update_modified_column();

CREATE TRIGGER insert_product_modtime AFTER INSERT ON products FOR EACH ROW EXECUTE PROCEDURE update_modified_column();
CREATE TRIGGER insert_clerk_modtime AFTER INSERT ON clerks FOR EACH ROW EXECUTE PROCEDURE update_modified_column();
CREATE TRIGGER insert_customer_modtime AFTER INSERT ON customers FOR EACH ROW EXECUTE PROCEDURE update_modified_column();
CREATE TRIGGER insert_group_modtime AFTER INSERT ON groups FOR EACH ROW EXECUTE PROCEDURE update_modified_column();

CREATE TRIGGER update_product_menus AFTER INSERT ON product_menus FOR EACH ROW EXECUTE PROCEDURE notify_products();
CREATE TRIGGER insert_product_menus AFTER INSERT ON product_menus FOR EACH ROW EXECUTE PROCEDURE notify_products();

CREATE TRIGGER update_product_names AFTER INSERT ON product_names FOR EACH ROW EXECUTE PROCEDURE notify_products();
CREATE TRIGGER insert_product_names AFTER INSERT ON product_names FOR EACH ROW EXECUTE PROCEDURE notify_products();

ALTER TABLE cashier_operations ADD business_date DATE;

CREATE TABLE sales_details_extra_data (
  product INTEGER NOT NULL REFERENCES products(id),
  detail_gbi VARCHAR(50) NOT NULL,
  extra_data VARCHAR(255)
);

ALTER TABLE products ADD qty_to_offer SMALLINT DEFAULT 0;
ALTER TABLE products ADD no_points SMALLINT DEFAULT 0;
ALTER TABLE customers ADD use_points SMALLINT DEFAULT 0;
ALTER TABLE customers ADD email VARCHAR(255);
ALTER TABLE products ADD upsale SMALLINT DEFAULT 0;
ALTER TABLE products ADD no_service_charge SMALLINT DEFAULT 0;
ALTER TABLE products ADD soldout SMALLINT DEFAULT 0;
ALTER TABLE clerks ADD cant_remove_service_charge SMALLINT DEFAULT 0;
ALTER TABLE vouchers ADD synced SMALLINT DEFAULT 0;
ALTER TABLE vouchers ADD date_used_synced SMALLINT DEFAULT 0;
ALTER TABLE vouchers ADD customer_id INTEGER DEFAULT 0;
ALTER TABLE customers ADD app_sign_key VARCHAR(50);
ALTER TABLE products ADD margin NUMERIC DEFAULT 0;
ALTER TABLE products DROP pcu;

ALTER TABLE customers ADD keep_in_source SMALLINT DEFAULT 0;
ALTER TABLE customers ADD rgpd_authorized SMALLINT DEFAULT 0;

CREATE TABLE money_counts (
  id SERIAL,
  business_date DATE NOT NULL,
  date timestamp DEFAULT now(),
  clerk VARCHAR(50) NOT NULL,
  station INTEGER NOT NULL DEFAULT 0,
  txt TEXT,
  PRIMARY KEY (id)
);

CREATE TABLE money_counts_operations (
  id SERIAL,
  business_date DATE NOT NULL,
  date timestamp DEFAULT now(),
  clerk VARCHAR(50) NOT NULL,
  station INTEGER NOT NULL DEFAULT 0,
  operation VARCHAR(10),
  justification VARCHAR(255),
  amount NUMERIC DEFAULT 0,
  PRIMARY KEY (id)
);

CREATE TABLE customer_changes_logs (
  id SERIAL,
  date timestamp DEFAULT now(),
  clerk_id INTEGER NOT NULL,
  clerk_login VARCHAR(50) NOT NULL,
  query TEXT,
  PRIMARY KEY (id)
);

-- used to save records of external cashdrawers
CREATE TABLE cashdrawer_operations (
  id SERIAL,
  business_date DATE NOT NULL,
  date timestamp DEFAULT now(),
  clerk_id INTEGER NOT NULL,
  operation VARCHAR(25) NOT NULL,
  params TEXT,
  obs TEXT
);

ALTER TABLE cashdrawer_operations ADD amount NUMERIC DEFAULT 0;
ALTER TABLE cashdrawer_operations ADD station SMALLINT DEFAULT 0;

CREATE TABLE clerk_auto_clockins (
  id SERIAL,
  business_date DATE NOT NULL,
  date timestamp DEFAULT now(),
  clerk INTEGER NOT NULL,
  station INTEGER NOT NULL DEFAULT 0,
  PRIMARY KEY (id)
);

ALTER TABLE customers ADD settlement NUMERIC DEFAULT 0;
ALTER TABLE customers ADD settlement_date DATE;
ALTER TABLE customers ALTER settlement TYPE VARCHAR(100);
ALTER TABLE customers DROP settlement_date;
ALTER TABLE customers ADD vat_isention SMALLINT DEFAULT 0;
ALTER TABLE customers ALTER vat_isention TYPE VARCHAR(150);
ALTER TABLE customers ADD products TEXT;
ALTER TABLE customers ADD price_to_use INTEGER DEFAULT 0;

ALTER TABLE cashdrawer_operations RENAME COLUMN clerk_id TO clerk;

CREATE INDEX idx_sales_hashes_doc_num_doc_type ON sales_hashes(fo_doc_number, doc_type);

ALTER TABLE sales_details ADD id SERIAL;

ALTER TABLE special_prices_products ADD quantity NUMERIC DEFAULT 1;

CREATE TABLE promotional_packs (
  id SERIAL,
  name VARCHAR(100),
  date_from DATE NOT NULL,
  date_to DATE NOT NULL,
  hour_from VARCHAR(8) NOT NULL,
  hour_to VARCHAR(8) NOT NULL,
  PRIMARY KEY (id)
);

CREATE TABLE promotional_pack_product_to_trigger (
  id SERIAL,
  promotional_pack_id INTEGER NOT NULL REFERENCES promotional_packs(id),
  product_id INTEGER NOT NULL,
  quantity NUMERIC DEFAULT 1,
  PRIMARY KEY (id)
);

CREATE TABLE promotional_pack_product_to_apply (
  id SERIAL,
  promotional_pack_id INTEGER NOT NULL REFERENCES promotional_packs(id),
  product_id INTEGER NOT NULL,
  quantity NUMERIC DEFAULT 1,
  price NUMERIC NOT NULL DEFAULT 0,
  discount NUMERIC NOT NULL DEFAULT 0,
  PRIMARY KEY (id)
);

ALTER TABLE promotional_pack_product_to_apply DROP product_to_trigger_id;

ALTER TABLE customers ADD dont_apply_vat_isentions SMALLINT DEFAULT 0;

ALTER TABLE sales_details_extra_data ALTER extra_data TYPE TEXT;

ALTER TABLE products ADD md5 VARCHAR(50);

CREATE TABLE rfid_operations (
  id SERIAL NOT NULL,
  datetime TIMESTAMP DEFAULT NOW(),
  hardlock VARCHAR(50),
  business_date DATE,
  token_id VARCHAR(4),
  card_id VARCHAR(20),
  operation_type VARCHAR(6),
  amount NUMERIC DEFAULT 0,
  check_num VARCHAR(6),
  clerk VARCHAR(20),
  area SMALLINT DEFAULT -1,
  station SMALLINT DEFAULT -1,
  station_name VARCHAR(20),
  header INTEGER DEFAULT 0,
  fo_doc_number VARCHAR(50),
  PRIMARY KEY (id)
);

CREATE INDEX idx_rfid_operations_idx1 ON rfid_operations(card_id);
CREATE INDEX idx_rfid_operations_idx2 ON rfid_operations(card_id, token_id);
CREATE INDEX idx_rfid_operations_idx3 ON rfid_operations(synced, operation_type);

ALTER TABLE customers ADD missed_orders SMALLINT DEFAULT 0;

ALTER TABLE products ADD online SMALLINT DEFAULT 0;

ALTER TABLE rfid_operations ALTER operation_type TYPE VARCHAR(25);

ALTER TABLE rfid_operations ADD obs VARCHAR(150);

ALTER TABLE sales_hashes ADD date_inserted TIMESTAMP DEFAULT NOW();

CREATE INDEX idx_sales_headers_gb_identifier ON sales_headers (gb_identifier);
CREATE INDEX idx_sales_details_gb_identifier ON sales_details (gb_identifier);
CREATE INDEX idx_split_docs_link_gbi_old ON split_docs_link (gbi_old);
CREATE INDEX idx_split_docs_link_gbi_new ON split_docs_link (gbi_new);

ALTER TABLE customers ADD invoice_credit SMALLINT DEFAULT 0;
ALTER TABLE rfid_operations ADD synced SMALLINT DEFAULT 0;
ALTER TABLE rfid_operations ADD card_balance NUMERIC DEFAULT 0;
ALTER TABLE rfid_operations ALTER check_num TYPE VARCHAR(25);
ALTER TABLE rfid_operations ADD gbi VARCHAR(50);
CREATE INDEX idx_rfid_operations_idx4 ON rfid_operations(card_id, gbi);

ALTER TABLE card_sets ADD hour_from VARCHAR(5);
ALTER TABLE card_sets ADD hour_to VARCHAR(5);
ALTER TABLE card_sets ADD coat_product NUMERIC DEFAULT 0;
ALTER TABLE card_sets ADD coat_offer_qtty NUMERIC DEFAULT 0;
ALTER TABLE card_sets ADD dont_use_consumption SMALLINT DEFAULT 0;
ALTER TABLE card_sets ADD ignore_min_cons_limit SMALLINT DEFAULT 0;
ALTER TABLE card_sets ADD offer_consumption_value SMALLINT DEFAULT 0;
ALTER TABLE card_sets ADD affect_persons_count SMALLINT DEFAULT 1;

ALTER TABLE clerks ALTER blocked_stations TYPE VARCHAR(255);

ALTER TABLE time_clock ADD created TIMESTAMP DEFAULT NOW();

ALTER TABLE clerks ADD sap_operations VARCHAR(150);

CREATE TABLE sap_movs_headers (
  id INT NOT NULL,
  date_mov DATE NOT NULL,
  hour_mov VARCHAR(8) NOT NULL DEFAULT '00:00:00',
  clerk_mov INTEGER NOT NULL,
  value_mov NUMERIC DEFAULT 0 NOT NULL,
  PRIMARY KEY (id)
);


CREATE TABLE sap_movs_details (
  id INT NOT NULL,
  header INT NOT NULL,
  tipo_doc VARCHAR(5),
  fo_doc_number VARCHAR(50),
  date_doc DATE NOT NULL,
  value_doc NUMERIC DEFAULT 0 NOT NULL,
  obs_doc VARCHAR(100),
  PRIMARY KEY (id)
);

