2 * Copyright (C) 2004-2008 Georgia Public Library Service
3 * Copyright (C) 2007-2008 Equinox Software, Inc.
4 * Mike Rylander <miker@esilibrary.com>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
18 DROP SCHEMA IF EXISTS reporter CASCADE;
22 CREATE SCHEMA reporter;
24 CREATE TABLE reporter.template_folder (
25 id SERIAL PRIMARY KEY,
26 parent INT REFERENCES reporter.template_folder (id) DEFERRABLE INITIALLY DEFERRED,
27 owner INT NOT NULL REFERENCES actor.usr (id) DEFERRABLE INITIALLY DEFERRED,
28 create_time TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
30 shared BOOL NOT NULL DEFAULT FALSE,
31 share_with INT REFERENCES actor.org_unit (id) DEFERRABLE INITIALLY DEFERRED
33 CREATE INDEX rpt_tmpl_fldr_owner_idx ON reporter.template_folder (owner);
34 CREATE UNIQUE INDEX rpt_template_folder_once_parent_idx ON reporter.template_folder (name,parent);
35 CREATE UNIQUE INDEX rpt_template_folder_once_idx ON reporter.template_folder (name,owner) WHERE parent IS NULL;
37 CREATE TABLE reporter.report_folder (
38 id SERIAL PRIMARY KEY,
39 parent INT REFERENCES reporter.report_folder (id) DEFERRABLE INITIALLY DEFERRED,
40 owner INT NOT NULL REFERENCES actor.usr (id) DEFERRABLE INITIALLY DEFERRED,
41 create_time TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
43 shared BOOL NOT NULL DEFAULT FALSE,
44 share_with INT REFERENCES actor.org_unit (id) DEFERRABLE INITIALLY DEFERRED
46 CREATE INDEX rpt_rpt_fldr_owner_idx ON reporter.report_folder (owner);
47 CREATE UNIQUE INDEX rpt_report_folder_once_parent_idx ON reporter.report_folder (name,parent);
48 CREATE UNIQUE INDEX rpt_report_folder_once_idx ON reporter.report_folder (name,owner) WHERE parent IS NULL;
50 CREATE TABLE reporter.output_folder (
51 id SERIAL PRIMARY KEY,
52 parent INT REFERENCES reporter.output_folder (id) DEFERRABLE INITIALLY DEFERRED,
53 owner INT NOT NULL REFERENCES actor.usr (id) DEFERRABLE INITIALLY DEFERRED,
54 create_time TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
56 shared BOOL NOT NULL DEFAULT FALSE,
57 share_with INT REFERENCES actor.org_unit (id) DEFERRABLE INITIALLY DEFERRED
59 CREATE INDEX rpt_output_fldr_owner_idx ON reporter.output_folder (owner);
60 CREATE UNIQUE INDEX rpt_output_folder_once_parent_idx ON reporter.output_folder (name,parent);
61 CREATE UNIQUE INDEX rpt_output_folder_once_idx ON reporter.output_folder (name,owner) WHERE parent IS NULL;
64 CREATE TABLE reporter.template (
65 id SERIAL PRIMARY KEY,
66 owner INT NOT NULL REFERENCES actor.usr (id) DEFERRABLE INITIALLY DEFERRED,
67 create_time TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
69 description TEXT NOT NULL,
71 folder INT NOT NULL REFERENCES reporter.template_folder (id) DEFERRABLE INITIALLY DEFERRED
73 CREATE INDEX rpt_tmpl_owner_idx ON reporter.template (owner);
74 CREATE INDEX rpt_tmpl_fldr_idx ON reporter.template (folder);
75 CREATE UNIQUE INDEX rtp_template_folder_once_idx ON reporter.template (name,folder);
77 CREATE TABLE reporter.report (
78 id SERIAL PRIMARY KEY,
79 owner INT NOT NULL REFERENCES actor.usr (id) DEFERRABLE INITIALLY DEFERRED,
80 create_time TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
81 name TEXT NOT NULL DEFAULT '',
82 description TEXT NOT NULL DEFAULT '',
83 template INT NOT NULL REFERENCES reporter.template (id) DEFERRABLE INITIALLY DEFERRED,
85 folder INT NOT NULL REFERENCES reporter.report_folder (id) DEFERRABLE INITIALLY DEFERRED,
86 recur BOOL NOT NULL DEFAULT FALSE,
89 CREATE INDEX rpt_rpt_owner_idx ON reporter.report (owner);
90 CREATE INDEX rpt_rpt_fldr_idx ON reporter.report (folder);
91 CREATE UNIQUE INDEX rtp_report_folder_once_idx ON reporter.report (name,folder);
93 CREATE TABLE reporter.schedule (
94 id SERIAL PRIMARY KEY,
95 report INT NOT NULL REFERENCES reporter.report (id) DEFERRABLE INITIALLY DEFERRED,
96 folder INT NOT NULL REFERENCES reporter.output_folder (id) DEFERRABLE INITIALLY DEFERRED,
97 runner INT NOT NULL REFERENCES actor.usr (id) DEFERRABLE INITIALLY DEFERRED,
98 run_time TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
99 start_time TIMESTAMP WITH TIME ZONE,
100 complete_time TIMESTAMP WITH TIME ZONE,
102 excel_format BOOL NOT NULL DEFAULT TRUE,
103 html_format BOOL NOT NULL DEFAULT TRUE,
104 csv_format BOOL NOT NULL DEFAULT TRUE,
105 chart_pie BOOL NOT NULL DEFAULT FALSE,
106 chart_bar BOOL NOT NULL DEFAULT FALSE,
107 chart_line BOOL NOT NULL DEFAULT FALSE,
111 CREATE INDEX rpt_sched_runner_idx ON reporter.schedule (runner);
112 CREATE INDEX rpt_sched_folder_idx ON reporter.schedule (folder);
114 CREATE OR REPLACE VIEW reporter.simple_record AS
121 title.value AS title,
122 uniform_title.value AS uniform_title,
123 author.value AS author,
124 publisher.value AS publisher,
125 SUBSTRING(pubdate.value FROM $$\d+$$) AS pubdate,
126 series_title.value AS series_title,
127 series_statement.value AS series_statement,
128 summary.value AS summary,
129 ARRAY_ACCUM( SUBSTRING(isbn.value FROM $$^\S+$$) ) AS isbn,
130 ARRAY_ACCUM( REGEXP_REPLACE(issn.value, E'^\\S*(\\d{4})[-\\s](\\d{3,4}x?)', E'\\1 \\2') ) AS issn,
131 ARRAY((SELECT DISTINCT value FROM metabib.full_rec WHERE tag = '650' AND subfield = 'a' AND record = r.id)) AS topic_subject,
132 ARRAY((SELECT DISTINCT value FROM metabib.full_rec WHERE tag = '651' AND subfield = 'a' AND record = r.id)) AS geographic_subject,
133 ARRAY((SELECT DISTINCT value FROM metabib.full_rec WHERE tag = '655' AND subfield = 'a' AND record = r.id)) AS genre,
134 ARRAY((SELECT DISTINCT value FROM metabib.full_rec WHERE tag = '600' AND subfield = 'a' AND record = r.id)) AS name_subject,
135 ARRAY((SELECT DISTINCT value FROM metabib.full_rec WHERE tag = '610' AND subfield = 'a' AND record = r.id)) AS corporate_subject,
136 ARRAY((SELECT value FROM metabib.full_rec WHERE tag = '856' AND subfield IN ('3','y','u') AND record = r.id ORDER BY CASE WHEN subfield IN ('3','y') THEN 0 ELSE 1 END)) AS external_uri
137 FROM biblio.record_entry r
138 JOIN metabib.metarecord_source_map s ON (s.source = r.id)
139 LEFT JOIN metabib.full_rec uniform_title ON (r.id = uniform_title.record AND uniform_title.tag = '240' AND uniform_title.subfield = 'a')
140 LEFT JOIN metabib.full_rec title ON (r.id = title.record AND title.tag = '245' AND title.subfield = 'a')
141 LEFT JOIN metabib.full_rec author ON (r.id = author.record AND author.tag = '100' AND author.subfield = 'a')
142 LEFT JOIN metabib.full_rec publisher ON (r.id = publisher.record AND publisher.tag = '260' AND publisher.subfield = 'b')
143 LEFT JOIN metabib.full_rec pubdate ON (r.id = pubdate.record AND pubdate.tag = '260' AND pubdate.subfield = 'c')
144 LEFT JOIN metabib.full_rec isbn ON (r.id = isbn.record AND isbn.tag IN ('024', '020') AND isbn.subfield IN ('a','z'))
145 LEFT JOIN metabib.full_rec issn ON (r.id = issn.record AND issn.tag = '022' AND issn.subfield = 'a')
146 LEFT JOIN metabib.full_rec series_title ON (r.id = series_title.record AND series_title.tag IN ('830','440') AND series_title.subfield = 'a')
147 LEFT JOIN metabib.full_rec series_statement ON (r.id = series_statement.record AND series_statement.tag = '490' AND series_statement.subfield = 'a')
148 LEFT JOIN metabib.full_rec summary ON (r.id = summary.record AND summary.tag = '520' AND summary.subfield = 'a')
149 GROUP BY 1,2,3,4,5,6,7,8,9,10,11,12,13,14;
151 CREATE OR REPLACE VIEW reporter.old_super_simple_record AS
157 FIRST(title.value) AS title,
158 FIRST(author.value) AS author,
159 ARRAY_TO_STRING(ARRAY_ACCUM( DISTINCT publisher.value), ', ') AS publisher,
160 ARRAY_TO_STRING(ARRAY_ACCUM( DISTINCT SUBSTRING(pubdate.value FROM $$\d+$$) ), ', ') AS pubdate,
161 ARRAY_ACCUM( DISTINCT SUBSTRING(isbn.value FROM $$^\S+$$) ) AS isbn,
162 ARRAY_ACCUM( DISTINCT SUBSTRING(issn.value FROM $$^\S+$$) ) AS issn
163 FROM biblio.record_entry r
164 LEFT JOIN metabib.full_rec title ON (r.id = title.record AND title.tag = '245' AND title.subfield = 'a')
165 LEFT JOIN metabib.full_rec author ON (r.id = author.record AND author.tag IN ('100','110','111') AND author.subfield = 'a')
166 LEFT JOIN metabib.full_rec publisher ON (r.id = publisher.record AND publisher.tag = '260' AND publisher.subfield = 'b')
167 LEFT JOIN metabib.full_rec pubdate ON (r.id = pubdate.record AND pubdate.tag = '260' AND pubdate.subfield = 'c')
168 LEFT JOIN metabib.full_rec isbn ON (r.id = isbn.record AND isbn.tag IN ('024', '020') AND isbn.subfield IN ('a','z'))
169 LEFT JOIN metabib.full_rec issn ON (r.id = issn.record AND issn.tag = '022' AND issn.subfield = 'a')
172 CREATE TABLE reporter.materialized_simple_record AS SELECT * FROM reporter.old_super_simple_record WHERE 1=0;
173 ALTER TABLE reporter.materialized_simple_record ADD PRIMARY KEY (id);
175 CREATE VIEW reporter.super_simple_record AS SELECT * FROM reporter.materialized_simple_record;
177 CREATE OR REPLACE FUNCTION reporter.simple_rec_update (r_id BIGINT, deleted BOOL) RETURNS BOOL AS $$
180 DELETE FROM reporter.materialized_simple_record WHERE id = r_id;
183 INSERT INTO reporter.materialized_simple_record SELECT DISTINCT ON (id) * FROM reporter.old_super_simple_record WHERE id = r_id;
191 CREATE OR REPLACE FUNCTION reporter.simple_rec_update (r_id BIGINT) RETURNS BOOL AS $$
192 SELECT reporter.simple_rec_update($1, FALSE);
195 CREATE OR REPLACE FUNCTION reporter.simple_rec_delete (r_id BIGINT) RETURNS BOOL AS $$
196 SELECT reporter.simple_rec_update($1, TRUE);
199 CREATE OR REPLACE FUNCTION reporter.simple_rec_trigger () RETURNS TRIGGER AS $func$
201 IF TG_OP = 'DELETE' THEN
202 PERFORM reporter.simple_rec_delete(NEW.id);
204 PERFORM reporter.simple_rec_update(NEW.id);
209 $func$ LANGUAGE PLPGSQL;
211 CREATE OR REPLACE FUNCTION reporter.simple_rec_sync () RETURNS TRIGGER AS $$
216 IF TG_OP IN ('DELETE') THEN
224 PERFORM reporter.simple_rec_update(r_id, deleted);
236 -- Disabling this by default for now, but we'll keep it around
238 --CREATE TRIGGER zzz_update_materialized_simple_record_tgr
239 -- AFTER INSERT OR UPDATE OR DELETE ON metabib.real_full_rec
240 -- FOR EACH ROW EXECUTE PROCEDURE reporter.simple_rec_sync();
242 CREATE OR REPLACE FUNCTION reporter.simple_rec_bib_sync () RETURNS TRIGGER AS $$
245 DELETE FROM reporter.materialized_simple_record WHERE id = NEW.id;
253 --CREATE TRIGGER zzz_update_materialized_simple_rec_delete_tgr
254 -- AFTER UPDATE ON biblio.record_entry
255 -- FOR EACH ROW EXECUTE PROCEDURE reporter.simple_rec_bib_sync();
258 CREATE OR REPLACE FUNCTION reporter.disable_materialized_simple_record_trigger () RETURNS VOID AS $$
259 DROP TRIGGER IF EXISTS zzz_update_materialized_simple_record_tgr ON metabib.real_full_rec;
262 CREATE OR REPLACE FUNCTION reporter.enable_materialized_simple_record_trigger () RETURNS VOID AS $$
264 TRUNCATE TABLE reporter.materialized_simple_record;
266 INSERT INTO reporter.materialized_simple_record
267 (id,fingerprint,quality,tcn_source,tcn_value,title,author,publisher,pubdate,isbn,issn)
268 SELECT DISTINCT ON (id) * FROM reporter.old_super_simple_record;
270 CREATE TRIGGER zzz_update_materialized_simple_record_tgr
271 AFTER INSERT OR UPDATE OR DELETE ON metabib.real_full_rec
272 FOR EACH ROW EXECUTE PROCEDURE reporter.simple_rec_sync();
276 CREATE OR REPLACE FUNCTION reporter.refresh_materialized_simple_record () RETURNS VOID AS $$
277 SELECT reporter.disable_materialized_simple_record_trigger();
278 SELECT reporter.enable_materialized_simple_record_trigger();
281 CREATE OR REPLACE VIEW reporter.demographic AS
287 WHEN AGE(u.dob) > '18 years'::INTERVAL
290 END AS general_division
293 CREATE OR REPLACE VIEW reporter.circ_type AS
295 CASE WHEN opac_renewal OR phone_renewal OR desk_renewal
299 FROM action.circulation;
301 CREATE OR REPLACE VIEW reporter.hold_request_record AS
309 THEN (SELECT ssub.record_entry FROM serial.subscription ssub JOIN serial.issuance si ON (si.subscription = ssub.id) WHERE si.id = ahr.target)
311 THEN (SELECT cn.record FROM asset.call_number cn WHERE cn.id = ahr.target)
312 WHEN hold_type IN ('C','R','F')
313 THEN (SELECT cn.record FROM asset.call_number cn JOIN asset.copy cp ON (cn.id = cp.call_number) WHERE cp.id = ahr.target)
315 THEN (SELECT mr.master_record FROM metabib.metarecord mr WHERE mr.id = ahr.target)
317 FROM action.hold_request ahr;
319 CREATE OR REPLACE VIEW reporter.xact_billing_totals AS
321 SUM( CASE WHEN b.voided THEN 0 ELSE amount END ) as unvoided,
322 SUM( CASE WHEN b.voided THEN amount ELSE 0 END ) as voided,
323 SUM( amount ) as total
327 CREATE OR REPLACE VIEW reporter.xact_paid_totals AS
329 SUM( CASE WHEN b.voided THEN 0 ELSE amount END ) as unvoided,
330 SUM( CASE WHEN b.voided THEN amount ELSE 0 END ) as voided,
331 SUM( amount ) as total
335 CREATE OR REPLACE VIEW reporter.overdue_circs AS
337 FROM "action".circulation
338 WHERE checkin_time is null
339 AND (stop_fines NOT IN ('LOST','CLAIMSRETURNED') OR stop_fines IS NULL)
340 AND due_date < now();
342 CREATE OR REPLACE VIEW reporter.overdue_reports AS
343 SELECT s.id, c.barcode AS runner_barcode, r.name, s.run_time, s.run_time - now() AS scheduled_wait_time
344 FROM reporter.schedule s
345 JOIN reporter.report r ON r.id = s.report
346 JOIN actor.usr u ON s.runner = u.id
347 JOIN actor.card c ON c.id = u.card
348 WHERE s.start_time IS NULL AND s.run_time < now();
350 CREATE OR REPLACE VIEW reporter.pending_reports AS
351 SELECT s.id, c.barcode AS runner_barcode, r.name, s.run_time, s.run_time - now() AS scheduled_wait_time
352 FROM reporter.schedule s
353 JOIN reporter.report r ON r.id = s.report
354 JOIN actor.usr u ON s.runner = u.id
355 JOIN actor.card c ON c.id = u.card
356 WHERE s.start_time IS NULL;
358 CREATE OR REPLACE VIEW reporter.currently_running AS
359 SELECT s.id, c.barcode AS runner_barcode, r.name, s.run_time, s.run_time - now() AS scheduled_wait_time
360 FROM reporter.schedule s
361 JOIN reporter.report r ON r.id = s.report
362 JOIN actor.usr u ON s.runner = u.id
363 JOIN actor.card c ON c.id = u.card
364 WHERE s.start_time IS NOT NULL AND s.complete_time IS NULL;