|
|
|
|
162
|
confwindow.show();
|
162
|
confwindow.show();
|
163
|
});
|
163
|
});
|
164
|
<![CDATA[
|
164
|
<![CDATA[
|
165
|
- query = new QSqlQuery();
|
|
|
166
|
- query.exec("CREATE TABLE certifications (item bigint NOT NULL, certification text NOT NULL)");
|
|
|
167
|
- query.exec("CREATE TABLE cupping_samples (session bigint NOT NULL, sample text NOT NULL, position bigint NOT NULL, type text NOT NULL, \"time\" timestamp without time zone, machine bigint, point text, item bigint)");
|
|
|
168
|
- query.exec("CREATE TABLE cupping_sessions (id bigserial NOT NULL, event text, name text NOT NULL, \"time\" timestamp without time zone NOT NULL, blind boolean NOT NULL, open boolean NOT NULL, note text)");
|
|
|
169
|
- query.exec("CREATE TABLE cuppingforms (session bigint NOT NULL, sample text NOT NULL, position bigint NOT NULL, grader text, finalscore numeric, notes text, serialization text)");
|
|
|
170
|
- query.exec("CREATE TABLE cuppingform_t1 (aroma numeric, flavor numeric, aftertaste numeric, acidity numeric, body numeric, uniformity numeric, balance numeric, cleancup numeric, sweetness numeric, overall numeric, total numeric) INHERITS (cuppingforms)");
|
|
|
171
|
- query.exec("CREATE TABLE invoices (id bigserial PRIMARY KEY NOT NULL, invoice text, vendor text NOT NULL, \"time\" timestamp without time zone NOT NULL)");
|
|
|
172
|
- query.exec("CREATE TABLE invoice_items (invoice_id bigint NOT NULL, record_type text NOT NULL, item_id bigint, description text NOT NULL, cost numeric NOT NULL)");
|
|
|
173
|
- query.exec("CREATE TABLE transactions (\"time\" timestamp without time zone NOT NULL, item bigint NOT NULL)");
|
|
|
174
|
- query.exec("CREATE TABLE inventory (quantity numeric NOT NULL) INHERITS (transactions)");
|
|
|
175
|
- query.exec("CREATE TABLE loss (quantity numeric NOT NULL, reason text) INHERITS (transactions)");
|
|
|
176
|
- query.exec("CREATE TABLE make (quantity numeric NOT NULL) INHERITS (transactions)");
|
|
|
177
|
- query.exec("CREATE TABLE purchase (quantity numeric NOT NULL, cost numeric NOT NULL, vendor text NOT NULL) INHERITS (transactions)");
|
|
|
178
|
- query.exec("CREATE TABLE sale (quantity numeric NOT NULL, customer text) INHERITS (transactions)");
|
|
|
179
|
- query.exec("CREATE TABLE use (quantity numeric NOT NULL) INHERITS (transactions)");
|
|
|
180
|
- query.exec("CREATE VIEW all_transactions AS ((((SELECT purchase.\"time\", purchase.item, purchase.quantity, purchase.cost, purchase.vendor, NULL::unknown AS reason, NULL::unknown AS customer, 'PURCHASE' AS type FROM purchase UNION SELECT use.\"time\", use.item, use.quantity, NULL::unknown AS cost, NULL::unknown AS vendor, NULL::unknown AS reason, NULL::unknown AS customer, 'USE' AS type FROM use) UNION SELECT inventory.\"time\", inventory.item, inventory.quantity, NULL::unknown AS cost, NULL::unknown AS vendor, NULL::unknown AS reason, NULL::unknown AS customer, 'INVENTORY' AS type FROM inventory) UNION SELECT loss.\"time\", loss.item, loss.quantity, NULL::unknown AS cost, NULL::unknown AS vendor, loss.reason, NULL::unknown AS customer, 'LOSS' AS type FROM loss) UNION SELECT make.\"time\", make.item, make.quantity, NULL::unknown AS cost, NULL::unknown AS vendor, NULL::unknown AS reason, NULL::unknown AS customer, 'MAKE' AS type FROM make) UNION SELECT sale.\"time\", sale.item, sale.quantity, NULL::unknown AS cost, NULL::unknown AS vendor, NULL::unknown AS reason, sale.customer, 'SALE' AS type FROM sale");
|
|
|
181
|
- query.exec("CREATE FUNCTION time_range(bigint) RETURNS integer AS $$ BEGIN IF (SELECT quantity FROM items WHERE id = $1) > 0 THEN RETURN (SELECT current_date - min(time)::date + 1 FROM use WHERE item = $1); ELSE RETURN (SELECT max(time)::date - min(time)::date + 1 FROM use WHERE item = $1); END IF; END; $$ LANGUAGE plpgsql STRICT");
|
|
|
182
|
- query.exec("CREATE TABLE items(id bigint NOT NULL, name text NOT NULL, reference text, unit text NOT NULL, quantity numeric DEFAULT 0, category text)");
|
|
|
183
|
- query.exec("CREATE SEQUENCE items_id_seq INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1");
|
|
|
184
|
- query.exec("CREATE TABLE coffees(origin text NOT NULL, region text, producer text, grade text, milling text, drying text) INHERITS (items)");
|
|
|
185
|
- query.exec("CREATE VIEW coffee_history AS SELECT coffees.id, coffees.name, coffees.origin, coffees.quantity AS stock, (SELECT sum(use.quantity) AS sum FROM use WHERE (use.item = coffees.id)) AS used, time_range(coffees.id) AS \"interval\", ((SELECT (sum(use.quantity) / (time_range(use.item))::numeric) FROM use WHERE (use.item = coffees.id) GROUP BY use.item))::numeric(10,2) AS rate, (SELECT (('now'::text)::date + ((coffees.quantity / (SELECT (sum(use.quantity) / (time_range(use.item))::numeric) FROM use WHERE (use.item = coffees.id) GROUP BY use.item)))::integer)) AS \"out\" FROM coffees WHERE (coffees.id IN (SELECT use.item FROM use)) ORDER BY coffees.origin");
|
|
|
186
|
- query.exec("CREATE TABLE current_items (item bigint NOT NULL)");
|
|
|
187
|
- query.exec("CREATE TABLE decaf_coffees (decaf_method text NOT NULL) INHERITS (coffees)");
|
|
|
188
|
- query.exec("CREATE TABLE files (id bigint NOT NULL, name text NOT NULL, type text NOT NULL, note text, file bytea NOT NULL)");
|
|
|
189
|
- query.exec("CREATE TABLE item_files(\"time\" timestamp without time zone NOT NULL, item bigint NOT NULL, files bigint[] NOT NULL)");
|
|
|
190
|
- query.exec("CREATE TYPE item_transaction_with_balance AS (\"time\" timestamp without time zone, item bigint, quantity numeric, cost numeric, vendor text, reason text, customer text, type text, balance numeric)");
|
|
|
191
|
- query.exec("CREATE TABLE lb_bag_conversion (item bigint NOT NULL, conversion numeric NOT NULL)");
|
|
|
192
|
- query.exec("CREATE TABLE machine (id bigint NOT NULL, name text NOT NULL)");
|
|
|
193
|
- query.exec("CREATE VIEW regular_coffees AS SELECT coffees.id, coffees.name, coffees.reference, coffees.unit, coffees.quantity, coffees.category, coffees.origin, coffees.region, coffees.producer, coffees.grade, coffees.milling, coffees.drying FROM coffees WHERE (NOT (coffees.id IN (SELECT decaf_coffees.id FROM decaf_coffees)))");
|
|
|
194
|
- query.exec("CREATE TABLE roasting_log (\"time\" timestamp without time zone NOT NULL, unroasted_id bigint[], unroasted_quantity numeric[], unroasted_total_quantity numeric, roasted_id bigint, roasted_quantity numeric, transaction_type text NOT NULL, annotation text, machine bigint NOT NULL, duration interval, approval boolean, humidity numeric, barometric numeric, indoor_air numeric, outdoor_air numeric, files bigint[])");
|
|
|
195
|
- query.exec("CREATE VIEW short_log AS SELECT roasting_log.\"time\", (SELECT items.name FROM items WHERE (items.id = roasting_log.roasted_id)) AS name, roasting_log.unroasted_total_quantity, roasting_log.roasted_quantity, ((((roasting_log.unroasted_total_quantity - roasting_log.roasted_quantity) / roasting_log.unroasted_total_quantity) * (100)::numeric))::numeric(12,2) AS weight_loss, roasting_log.duration FROM roasting_log ORDER BY roasting_log.\"time\"");
|
|
|
196
|
- query.exec("CREATE FUNCTION add_inventory() RETURNS trigger AS $$ BEGIN UPDATE items SET quantity = quantity + NEW.quantity WHERE id = NEW.item; RETURN NEW; END; $$ LANGUAGE plpgsql");
|
|
|
197
|
- query.exec("CREATE FUNCTION bags_in_stock(bigint) RETURNS numeric AS $_$SELECT quantity / (SELECT conversion FROM lb_bag_conversion WHERE item = id) FROM items WHERE id = $1;$_$ LANGUAGE sql IMMUTABLE STRICT");
|
|
|
198
|
- query.exec("CREATE FUNCTION calculate_inventory_balance() RETURNS trigger AS $$ DECLARE old_quantity numeric; BEGIN old_quantity := (SELECT balance FROM working WHERE time = (SELECT max(time) FROM working)); IF old_quantity IS NULL THEN old_quantity := 0; END IF; IF NEW.type = 'PURCHASE' OR NEW.type = 'MAKE' THEN NEW.balance := old_quantity + NEW.quantity; ELSE IF NEW.type = 'INVENTORY' THEN NEW.balance := NEW.quantity; ELSE IF NEW.type = 'USE' OR NEW.type = 'SALE' OR NEW.type = 'LOSS' THEN NEW.balance := old_quantity - NEW.quantity; END IF; END IF; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql");
|
|
|
199
|
- query.exec("CREATE FUNCTION item_history(bigint) RETURNS SETOF item_transaction_with_balance AS $_$ DECLARE r item_transaction_with_balance; BEGIN CREATE TEMPORARY TABLE working(time timestamp without time zone, item bigint, quantity numeric, cost numeric, vendor text, reason text, customer text, type text, balance numeric) ON COMMIT DROP; CREATE TRIGGER quantity_update BEFORE INSERT ON working FOR EACH ROW EXECUTE PROCEDURE calculate_inventory_balance(); INSERT INTO working SELECT time, item, quantity, cost, vendor, reason, customer, type, NULL AS balance FROM all_transactions WHERE item = $1 ORDER BY time ASC; FOR r IN SELECT time, item, quantity, cost, vendor, reason, customer, type, balance FROM working LOOP RETURN NEXT r; END LOOP; DROP TABLE working; RETURN; END; $_$ LANGUAGE plpgsql");
|
|
|
200
|
- query.exec("CREATE FUNCTION log_make() RETURNS trigger AS $$ BEGIN IF NEW.roasted_quantity IS NOT NULL THEN INSERT INTO make VALUES(NEW.time, NEW.roasted_id, NEW.roasted_quantity); END IF; RETURN NEW; END; $$ LANGUAGE plpgsql");
|
|
|
201
|
- query.exec("CREATE FUNCTION log_make_update() RETURNS trigger AS $$ BEGIN IF NEW.roasted_quantity <> OLD.roasted_quantity AND NEW.roasted_quantity IS NOT NULL THEN INSERT INTO make VALUES(NEW.time, NEW.roasted_id, NEW.roasted_quantity); END IF; RETURN NEW; END; $$ LANGUAGE plpgsql");
|
|
|
202
|
- query.exec("CREATE FUNCTION log_use() RETURNS trigger AS $$ DECLARE i integer := array_lower(NEW.unroasted_id, 1); u integer := array_upper(NEW.unroasted_id, 1); BEGIN WHILE i <= u LOOP INSERT INTO use VALUES(NEW.time, NEW.unroasted_id[i], NEW.unroasted_quantity[i]); i := i + 1; END LOOP; RETURN NEW; END; $$ LANGUAGE plpgsql");
|
|
|
203
|
- query.exec("CREATE FUNCTION replace_inventory() RETURNS trigger AS $$ BEGIN UPDATE items SET quantity = NEW.quantity WHERE id = NEW.item; RETURN NEW; END; $$ LANGUAGE plpgsql");
|
|
|
204
|
- query.exec("CREATE FUNCTION subtract_inventory() RETURNS trigger AS $$ BEGIN UPDATE items SET quantity = quantity - NEW.quantity WHERE id = NEW.item; RETURN NEW; END; $$ LANGUAGE plpgsql");
|
|
|
205
|
- query.exec("CREATE SEQUENCE files_id_seq START WITH 1 INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1");
|
|
|
206
|
- query.exec("ALTER TABLE files ALTER COLUMN id SET DEFAULT nextval('files_id_seq'::regclass)");
|
|
|
207
|
- query.exec("ALTER TABLE items ALTER COLUMN id SET DEFAULT nextval('items_id_seq'::regclass)");
|
|
|
208
|
- query.exec("ALTER TABLE ONLY files ADD CONSTRAINT file_pkey PRIMARY KEY (id)");
|
|
|
209
|
- query.exec("ALTER TABLE ONLY items ADD CONSTRAINT items_pkey PRIMARY KEY (id)");
|
|
|
210
|
- query.exec("ALTER TABLE ONLY lb_bag_conversion ADD CONSTRAINT lb_bag_conversion_item_key UNIQUE (item)");
|
|
|
211
|
- query.exec("ALTER TABLE ONLY roasting_log ADD CONSTRAINT roasting_log_pkey PRIMARY KEY (\"time\", machine)");
|
|
|
212
|
- query.exec("CREATE INDEX itemcategories ON items USING btree (category)");
|
|
|
213
|
- query.exec("CREATE INDEX itemnames ON items USING btree (name)");
|
|
|
214
|
- query.exec("CREATE INDEX roasting_log_index ON roasting_log USING btree (\"time\")");
|
|
|
215
|
- query.exec("CREATE INDEX transactionitems ON transactions USING btree (item)");
|
|
|
216
|
- query.exec("CREATE INDEX transactiontimes ON transactions USING btree (\"time\")");
|
|
|
217
|
- query.exec("CREATE TRIGGER add_inventory_trigger AFTER INSERT ON purchase FOR EACH ROW EXECUTE PROCEDURE add_inventory()");
|
|
|
218
|
- query.exec("CREATE TRIGGER add_inventory_trigger AFTER INSERT ON make FOR EACH ROW EXECUTE PROCEDURE add_inventory()");
|
|
|
219
|
- query.exec("CREATE TRIGGER log_use_trigger AFTER INSERT ON roasting_log FOR EACH ROW EXECUTE PROCEDURE log_use()");
|
|
|
220
|
- query.exec("CREATE TRIGGER replace_inventory_trigger AFTER INSERT ON inventory FOR EACH ROW EXECUTE PROCEDURE replace_inventory()");
|
|
|
221
|
- query.exec("CREATE TRIGGER subtract_inventory_trigger AFTER INSERT ON loss FOR EACH ROW EXECUTE PROCEDURE subtract_inventory()");
|
|
|
222
|
- query.exec("CREATE TRIGGER subtract_inventory_trigger AFTER INSERT ON sale FOR EACH ROW EXECUTE PROCEDURE subtract_inventory()");
|
|
|
223
|
- query.exec("CREATE TRIGGER subtract_inventory_trigger AFTER INSERT ON use FOR EACH ROW EXECUTE PROCEDURE subtract_inventory()");
|
|
|
224
|
- query.exec("ALTER TABLE ONLY item_files ADD CONSTRAINT item_files_item_fkey FOREIGN KEY (item) REFERENCES items(id)");
|
|
|
225
|
- query.exec("ALTER TABLE ONLY transactions ADD CONSTRAINT transactions_item_fkey FOREIGN KEY (item) REFERENCES items(id)");
|
|
|
226
|
- query = query.invalidate();
|
|
|
|
|
165
|
+ var DBCreateBase = function() {
|
|
|
166
|
+ var query = new QSqlQuery();
|
|
|
167
|
+ query.exec("CREATE TABLE IF NOT EXISTS certifications (item bigint NOT NULL, certification text NOT NULL)");
|
|
|
168
|
+ query.exec("CREATE TABLE IF NOT EXISTS cupping_samples (session bigint NOT NULL, sample text NOT NULL, position bigint NOT NULL, type text NOT NULL, \"time\" timestamp without time zone, machine bigint, point text, item bigint)");
|
|
|
169
|
+ query.exec("CREATE TABLE cupping_sessions (id bigserial NOT NULL, event text, name text NOT NULL, \"time\" timestamp without time zone NOT NULL, blind boolean NOT NULL, open boolean NOT NULL, note text)");
|
|
|
170
|
+ query.exec("CREATE TABLE IF NOT EXISTS cuppingforms (session bigint NOT NULL, sample text NOT NULL, position bigint NOT NULL, grader text, finalscore numeric, notes text, serialization text)");
|
|
|
171
|
+ query.exec("CREATE TABLE IF NOT EXISTS cuppingform_t1 (aroma numeric, flavor numeric, aftertaste numeric, acidity numeric, body numeric, uniformity numeric, balance numeric, cleancup numeric, sweetness numeric, overall numeric, total numeric) INHERITS (cuppingforms)");
|
|
|
172
|
+ query.exec("CREATE TABLE IF NOT EXISTS invoices (id bigserial PRIMARY KEY NOT NULL, invoice text, vendor text NOT NULL, \"time\" timestamp without time zone NOT NULL)");
|
|
|
173
|
+ query.exec("CREATE TABLE IF NOT EXISTS invoice_items (invoice_id bigint NOT NULL, record_type text NOT NULL, item_id bigint, description text NOT NULL, cost numeric NOT NULL)");
|
|
|
174
|
+ query.exec("CREATE TABLE IF NOT EXISTS transactions (\"time\" timestamp without time zone NOT NULL, item bigint NOT NULL)");
|
|
|
175
|
+ query.exec("CREATE TABLE IF NOT EXISTS inventory (quantity numeric NOT NULL) INHERITS (transactions)");
|
|
|
176
|
+ query.exec("CREATE TABLE IF NOT EXISTS loss (quantity numeric NOT NULL, reason text) INHERITS (transactions)");
|
|
|
177
|
+ query.exec("CREATE TABLE IF NOT EXISTS make (quantity numeric NOT NULL) INHERITS (transactions)");
|
|
|
178
|
+ query.exec("CREATE TABLE IF NOT EXISTS purchase (quantity numeric NOT NULL, cost numeric NOT NULL, vendor text NOT NULL) INHERITS (transactions)");
|
|
|
179
|
+ query.exec("CREATE TABLE IF NOT EXISTS sale (quantity numeric NOT NULL, customer text) INHERITS (transactions)");
|
|
|
180
|
+ query.exec("CREATE TABLE IF NOT EXISTS use (quantity numeric NOT NULL) INHERITS (transactions)");
|
|
|
181
|
+ query.exec("CREATE VIEW all_transactions AS ((((SELECT purchase.\"time\", purchase.item, purchase.quantity, purchase.cost, purchase.vendor, NULL::unknown AS reason, NULL::unknown AS customer, 'PURCHASE' AS type FROM purchase UNION SELECT use.\"time\", use.item, use.quantity, NULL::unknown AS cost, NULL::unknown AS vendor, NULL::unknown AS reason, NULL::unknown AS customer, 'USE' AS type FROM use) UNION SELECT inventory.\"time\", inventory.item, inventory.quantity, NULL::unknown AS cost, NULL::unknown AS vendor, NULL::unknown AS reason, NULL::unknown AS customer, 'INVENTORY' AS type FROM inventory) UNION SELECT loss.\"time\", loss.item, loss.quantity, NULL::unknown AS cost, NULL::unknown AS vendor, loss.reason, NULL::unknown AS customer, 'LOSS' AS type FROM loss) UNION SELECT make.\"time\", make.item, make.quantity, NULL::unknown AS cost, NULL::unknown AS vendor, NULL::unknown AS reason, NULL::unknown AS customer, 'MAKE' AS type FROM make) UNION SELECT sale.\"time\", sale.item, sale.quantity, NULL::unknown AS cost, NULL::unknown AS vendor, NULL::unknown AS reason, sale.customer, 'SALE' AS type FROM sale");
|
|
|
182
|
+ query.exec("CREATE FUNCTION time_range(bigint) RETURNS integer AS $$ BEGIN IF (SELECT quantity FROM items WHERE id = $1) > 0 THEN RETURN (SELECT current_date - min(time)::date + 1 FROM use WHERE item = $1); ELSE RETURN (SELECT max(time)::date - min(time)::date + 1 FROM use WHERE item = $1); END IF; END; $$ LANGUAGE plpgsql STRICT");
|
|
|
183
|
+ query.exec("CREATE TABLE IF NOT EXISTS items(id bigint NOT NULL, name text NOT NULL, reference text, unit text NOT NULL, quantity numeric DEFAULT 0, category text)");
|
|
|
184
|
+ query.exec("CREATE SEQUENCE items_id_seq INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1");
|
|
|
185
|
+ query.exec("CREATE TABLE IF NOT EXISTS coffees(origin text NOT NULL, region text, producer text, grade text, milling text, drying text) INHERITS (items)");
|
|
|
186
|
+ query.exec("CREATE VIEW coffee_history AS SELECT coffees.id, coffees.name, coffees.origin, coffees.quantity AS stock, (SELECT sum(use.quantity) AS sum FROM use WHERE (use.item = coffees.id)) AS used, time_range(coffees.id) AS \"interval\", ((SELECT (sum(use.quantity) / (time_range(use.item))::numeric) FROM use WHERE (use.item = coffees.id) GROUP BY use.item))::numeric(10,2) AS rate, (SELECT (('now'::text)::date + ((coffees.quantity / (SELECT (sum(use.quantity) / (time_range(use.item))::numeric) FROM use WHERE (use.item = coffees.id) GROUP BY use.item)))::integer)) AS \"out\" FROM coffees WHERE (coffees.id IN (SELECT use.item FROM use)) ORDER BY coffees.origin");
|
|
|
187
|
+ query.exec("CREATE TABLE IF NOT EXISTS current_items (item bigint NOT NULL)");
|
|
|
188
|
+ query.exec("CREATE TABLE IF NOT EXISTS decaf_coffees (decaf_method text NOT NULL) INHERITS (coffees)");
|
|
|
189
|
+ query.exec("CREATE TABLE IF NOT EXISTS files (id bigint NOT NULL, name text NOT NULL, type text NOT NULL, note text, file bytea NOT NULL)");
|
|
|
190
|
+ query.exec("CREATE TABLE IF NOT EXISTS item_files(\"time\" timestamp without time zone NOT NULL, item bigint NOT NULL, files bigint[] NOT NULL)");
|
|
|
191
|
+ query.exec("CREATE TYPE item_transaction_with_balance AS (\"time\" timestamp without time zone, item bigint, quantity numeric, cost numeric, vendor text, reason text, customer text, type text, balance numeric)");
|
|
|
192
|
+ query.exec("CREATE TABLE IF NOT EXISTS lb_bag_conversion (item bigint NOT NULL, conversion numeric NOT NULL)");
|
|
|
193
|
+ query.exec("CREATE TABLE IF NOT EXISTS machine (id bigint NOT NULL, name text NOT NULL)");
|
|
|
194
|
+ query.exec("CREATE VIEW regular_coffees AS SELECT coffees.id, coffees.name, coffees.reference, coffees.unit, coffees.quantity, coffees.category, coffees.origin, coffees.region, coffees.producer, coffees.grade, coffees.milling, coffees.drying FROM coffees WHERE (NOT (coffees.id IN (SELECT decaf_coffees.id FROM decaf_coffees)))");
|
|
|
195
|
+ query.exec("CREATE TABLE IF NOT EXISTS roasting_log (\"time\" timestamp without time zone NOT NULL, unroasted_id bigint[], unroasted_quantity numeric[], unroasted_total_quantity numeric, roasted_id bigint, roasted_quantity numeric, transaction_type text NOT NULL, annotation text, machine bigint NOT NULL, duration interval, approval boolean, humidity numeric, barometric numeric, indoor_air numeric, outdoor_air numeric, files bigint[])");
|
|
|
196
|
+ query.exec("CREATE VIEW short_log AS SELECT roasting_log.\"time\", (SELECT items.name FROM items WHERE (items.id = roasting_log.roasted_id)) AS name, roasting_log.unroasted_total_quantity, roasting_log.roasted_quantity, ((((roasting_log.unroasted_total_quantity - roasting_log.roasted_quantity) / roasting_log.unroasted_total_quantity) * (100)::numeric))::numeric(12,2) AS weight_loss, roasting_log.duration FROM roasting_log ORDER BY roasting_log.\"time\"");
|
|
|
197
|
+ query.exec("CREATE FUNCTION add_inventory() RETURNS trigger AS $$ BEGIN UPDATE items SET quantity = quantity + NEW.quantity WHERE id = NEW.item; RETURN NEW; END; $$ LANGUAGE plpgsql");
|
|
|
198
|
+ query.exec("CREATE FUNCTION bags_in_stock(bigint) RETURNS numeric AS $_$SELECT quantity / (SELECT conversion FROM lb_bag_conversion WHERE item = id) FROM items WHERE id = $1;$_$ LANGUAGE sql IMMUTABLE STRICT");
|
|
|
199
|
+ query.exec("CREATE FUNCTION calculate_inventory_balance() RETURNS trigger AS $$ DECLARE old_quantity numeric; BEGIN old_quantity := (SELECT balance FROM working WHERE time = (SELECT max(time) FROM working)); IF old_quantity IS NULL THEN old_quantity := 0; END IF; IF NEW.type = 'PURCHASE' OR NEW.type = 'MAKE' THEN NEW.balance := old_quantity + NEW.quantity; ELSE IF NEW.type = 'INVENTORY' THEN NEW.balance := NEW.quantity; ELSE IF NEW.type = 'USE' OR NEW.type = 'SALE' OR NEW.type = 'LOSS' THEN NEW.balance := old_quantity - NEW.quantity; END IF; END IF; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql");
|
|
|
200
|
+ query.exec("CREATE FUNCTION item_history(bigint) RETURNS SETOF item_transaction_with_balance AS $_$ DECLARE r item_transaction_with_balance; BEGIN CREATE TEMPORARY TABLE working(time timestamp without time zone, item bigint, quantity numeric, cost numeric, vendor text, reason text, customer text, type text, balance numeric) ON COMMIT DROP; CREATE TRIGGER quantity_update BEFORE INSERT ON working FOR EACH ROW EXECUTE PROCEDURE calculate_inventory_balance(); INSERT INTO working SELECT time, item, quantity, cost, vendor, reason, customer, type, NULL AS balance FROM all_transactions WHERE item = $1 ORDER BY time ASC; FOR r IN SELECT time, item, quantity, cost, vendor, reason, customer, type, balance FROM working LOOP RETURN NEXT r; END LOOP; DROP TABLE working; RETURN; END; $_$ LANGUAGE plpgsql");
|
|
|
201
|
+ query.exec("CREATE FUNCTION log_make() RETURNS trigger AS $$ BEGIN IF NEW.roasted_quantity IS NOT NULL THEN INSERT INTO make VALUES(NEW.time, NEW.roasted_id, NEW.roasted_quantity); END IF; RETURN NEW; END; $$ LANGUAGE plpgsql");
|
|
|
202
|
+ query.exec("CREATE FUNCTION log_make_update() RETURNS trigger AS $$ BEGIN IF NEW.roasted_quantity <> OLD.roasted_quantity AND NEW.roasted_quantity IS NOT NULL THEN INSERT INTO make VALUES(NEW.time, NEW.roasted_id, NEW.roasted_quantity); END IF; RETURN NEW; END; $$ LANGUAGE plpgsql");
|
|
|
203
|
+ query.exec("CREATE FUNCTION log_use() RETURNS trigger AS $$ DECLARE i integer := array_lower(NEW.unroasted_id, 1); u integer := array_upper(NEW.unroasted_id, 1); BEGIN WHILE i <= u LOOP INSERT INTO use VALUES(NEW.time, NEW.unroasted_id[i], NEW.unroasted_quantity[i]); i := i + 1; END LOOP; RETURN NEW; END; $$ LANGUAGE plpgsql");
|
|
|
204
|
+ query.exec("CREATE FUNCTION replace_inventory() RETURNS trigger AS $$ BEGIN UPDATE items SET quantity = NEW.quantity WHERE id = NEW.item; RETURN NEW; END; $$ LANGUAGE plpgsql");
|
|
|
205
|
+ query.exec("CREATE FUNCTION subtract_inventory() RETURNS trigger AS $$ BEGIN UPDATE items SET quantity = quantity - NEW.quantity WHERE id = NEW.item; RETURN NEW; END; $$ LANGUAGE plpgsql");
|
|
|
206
|
+ query.exec("CREATE SEQUENCE files_id_seq START WITH 1 INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1");
|
|
|
207
|
+ query.exec("ALTER TABLE files ALTER COLUMN id SET DEFAULT nextval('files_id_seq'::regclass)");
|
|
|
208
|
+ query.exec("ALTER TABLE items ALTER COLUMN id SET DEFAULT nextval('items_id_seq'::regclass)");
|
|
|
209
|
+ query.exec("ALTER TABLE ONLY files ADD CONSTRAINT file_pkey PRIMARY KEY (id)");
|
|
|
210
|
+ query.exec("ALTER TABLE ONLY items ADD CONSTRAINT items_pkey PRIMARY KEY (id)");
|
|
|
211
|
+ query.exec("ALTER TABLE ONLY lb_bag_conversion ADD CONSTRAINT lb_bag_conversion_item_key UNIQUE (item)");
|
|
|
212
|
+ query.exec("ALTER TABLE ONLY roasting_log ADD CONSTRAINT roasting_log_pkey PRIMARY KEY (\"time\", machine)");
|
|
|
213
|
+ query.exec("CREATE INDEX itemcategories ON items USING btree (category)");
|
|
|
214
|
+ query.exec("CREATE INDEX itemnames ON items USING btree (name)");
|
|
|
215
|
+ query.exec("CREATE INDEX roasting_log_index ON roasting_log USING btree (\"time\")");
|
|
|
216
|
+ query.exec("CREATE INDEX transactionitems ON transactions USING btree (item)");
|
|
|
217
|
+ query.exec("CREATE INDEX transactiontimes ON transactions USING btree (\"time\")");
|
|
|
218
|
+ query.exec("CREATE TRIGGER add_inventory_trigger AFTER INSERT ON purchase FOR EACH ROW EXECUTE PROCEDURE add_inventory()");
|
|
|
219
|
+ query.exec("CREATE TRIGGER add_inventory_trigger AFTER INSERT ON make FOR EACH ROW EXECUTE PROCEDURE add_inventory()");
|
|
|
220
|
+ query.exec("CREATE TRIGGER log_use_trigger AFTER INSERT ON roasting_log FOR EACH ROW EXECUTE PROCEDURE log_use()");
|
|
|
221
|
+ query.exec("CREATE TRIGGER replace_inventory_trigger AFTER INSERT ON inventory FOR EACH ROW EXECUTE PROCEDURE replace_inventory()");
|
|
|
222
|
+ query.exec("CREATE TRIGGER subtract_inventory_trigger AFTER INSERT ON loss FOR EACH ROW EXECUTE PROCEDURE subtract_inventory()");
|
|
|
223
|
+ query.exec("CREATE TRIGGER subtract_inventory_trigger AFTER INSERT ON sale FOR EACH ROW EXECUTE PROCEDURE subtract_inventory()");
|
|
|
224
|
+ query.exec("CREATE TRIGGER subtract_inventory_trigger AFTER INSERT ON use FOR EACH ROW EXECUTE PROCEDURE subtract_inventory()");
|
|
|
225
|
+ query.exec("ALTER TABLE ONLY item_files ADD CONSTRAINT item_files_item_fkey FOREIGN KEY (item) REFERENCES items(id)");
|
|
|
226
|
+ query.exec("ALTER TABLE ONLY transactions ADD CONSTRAINT transactions_item_fkey FOREIGN KEY (item) REFERENCES items(id)");
|
|
|
227
|
+ query.exec("INSERT INTO TypicaFeatures VALUES('base-features', TRUE, 1)");
|
|
|
228
|
+ query = query.invalidate();
|
|
|
229
|
+ };
|
|
|
230
|
+ query = new QSqlQuery();
|
|
|
231
|
+ /* A table keeps track of database versioning information. This table is created
|
|
|
232
|
+ if required. */
|
|
|
233
|
+ query.exec("CREATE TABLE IF NOT EXISTS TypicaFeatures (feature TEXT PRIMARY KEY, enabled boolean, version bigint)");
|
|
|
234
|
+ /* At the moment everything we're interested in is covered in the base-features
|
|
|
235
|
+ row, but this can be extended later if needed. Each row encodes if certain
|
|
|
236
|
+ database structures exist and what version of those structures exist. */
|
|
|
237
|
+ query.exec("SELECT feature, enabled, version FROM TypicaFeatures WHERE feature = 'base-features'");
|
|
|
238
|
+ if(query.next())
|
|
|
239
|
+ {
|
|
|
240
|
+ if(query.value(2) < 1)
|
|
|
241
|
+ {
|
|
|
242
|
+ DBCreateBase();
|
|
|
243
|
+ }
|
|
|
244
|
+ }
|
|
|
245
|
+ else
|
|
|
246
|
+ {
|
|
|
247
|
+ DBCreateBase();
|
|
|
248
|
+ }
|
227
|
]]>
|
249
|
]]>
|
228
|
</program>
|
250
|
</program>
|
229
|
</window>
|
251
|
</window>
|