]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/sql/Pg/reporter-schema.sql
some new management functions for the materialized reporting view
[working/Evergreen.git] / Open-ILS / src / sql / Pg / reporter-schema.sql
1 DROP SCHEMA reporter CASCADE;
2
3 BEGIN;
4
5 CREATE SCHEMA reporter;
6
7 CREATE TABLE reporter.template_folder (
8         id              SERIAL                          PRIMARY KEY,
9         parent          INT                             REFERENCES reporter.template_folder (id) DEFERRABLE INITIALLY DEFERRED,
10         owner           INT                             NOT NULL REFERENCES actor.usr (id) DEFERRABLE INITIALLY DEFERRED,
11         create_time     TIMESTAMP WITH TIME ZONE        NOT NULL DEFAULT NOW(),
12         name            TEXT                            NOT NULL,
13         shared          BOOL                            NOT NULL DEFAULT FALSE,
14         share_with      INT                             REFERENCES actor.org_unit (id) DEFERRABLE INITIALLY DEFERRED
15 );
16 CREATE INDEX rpt_tmpl_fldr_owner_idx ON reporter.template_folder (owner);
17 CREATE UNIQUE INDEX rpt_template_folder_once_parent_idx ON reporter.template_folder (name,parent);
18 CREATE UNIQUE INDEX rpt_template_folder_once_idx ON reporter.template_folder (name,owner) WHERE parent IS NULL;
19
20 CREATE TABLE reporter.report_folder (
21         id              SERIAL                          PRIMARY KEY,
22         parent          INT                             REFERENCES reporter.report_folder (id) DEFERRABLE INITIALLY DEFERRED,
23         owner           INT                             NOT NULL REFERENCES actor.usr (id) DEFERRABLE INITIALLY DEFERRED,
24         create_time     TIMESTAMP WITH TIME ZONE        NOT NULL DEFAULT NOW(),
25         name            TEXT                            NOT NULL,
26         shared          BOOL                            NOT NULL DEFAULT FALSE,
27         share_with      INT                             REFERENCES actor.org_unit (id) DEFERRABLE INITIALLY DEFERRED
28 );
29 CREATE INDEX rpt_rpt_fldr_owner_idx ON reporter.report_folder (owner);
30 CREATE UNIQUE INDEX rpt_report_folder_once_parent_idx ON reporter.report_folder (name,parent);
31 CREATE UNIQUE INDEX rpt_report_folder_once_idx ON reporter.report_folder (name,owner) WHERE parent IS NULL;
32
33 CREATE TABLE reporter.output_folder (
34         id              SERIAL                          PRIMARY KEY,
35         parent          INT                             REFERENCES reporter.output_folder (id) DEFERRABLE INITIALLY DEFERRED,
36         owner           INT                             NOT NULL REFERENCES actor.usr (id) DEFERRABLE INITIALLY DEFERRED,
37         create_time     TIMESTAMP WITH TIME ZONE        NOT NULL DEFAULT NOW(),
38         name            TEXT                            NOT NULL,
39         shared          BOOL                            NOT NULL DEFAULT FALSE,
40         share_with      INT                             REFERENCES actor.org_unit (id) DEFERRABLE INITIALLY DEFERRED
41 );
42 CREATE INDEX rpt_output_fldr_owner_idx ON reporter.output_folder (owner);
43 CREATE UNIQUE INDEX rpt_output_folder_once_parent_idx ON reporter.output_folder (name,parent);
44 CREATE UNIQUE INDEX rpt_output_folder_once_idx ON reporter.output_folder (name,owner) WHERE parent IS NULL;
45
46
47 CREATE TABLE reporter.template (
48         id              SERIAL                          PRIMARY KEY,
49         owner           INT                             NOT NULL REFERENCES actor.usr (id) DEFERRABLE INITIALLY DEFERRED,
50         create_time     TIMESTAMP WITH TIME ZONE        NOT NULL DEFAULT NOW(),
51         name            TEXT                            NOT NULL,
52         description     TEXT                            NOT NULL,
53         data            TEXT                            NOT NULL,
54         folder          INT                             NOT NULL REFERENCES reporter.template_folder (id) DEFERRABLE INITIALLY DEFERRED
55 );
56 CREATE INDEX rpt_tmpl_owner_idx ON reporter.template (owner);
57 CREATE INDEX rpt_tmpl_fldr_idx ON reporter.template (folder);
58 CREATE UNIQUE INDEX rtp_template_folder_once_idx ON reporter.template (name,folder);
59
60 CREATE TABLE reporter.report (
61         id              SERIAL                          PRIMARY KEY,
62         owner           INT                             NOT NULL REFERENCES actor.usr (id) DEFERRABLE INITIALLY DEFERRED,
63         create_time     TIMESTAMP WITH TIME ZONE        NOT NULL DEFAULT NOW(),
64         name            TEXT                            NOT NULL DEFAULT '',
65         description     TEXT                            NOT NULL DEFAULT '',
66         template        INT                             NOT NULL REFERENCES reporter.template (id) DEFERRABLE INITIALLY DEFERRED,
67         data            TEXT                            NOT NULL,
68         folder          INT                             NOT NULL REFERENCES reporter.report_folder (id) DEFERRABLE INITIALLY DEFERRED,
69         recur           BOOL                            NOT NULL DEFAULT FALSE,
70         recurance       INTERVAL
71 );
72 CREATE INDEX rpt_rpt_owner_idx ON reporter.report (owner);
73 CREATE INDEX rpt_rpt_fldr_idx ON reporter.report (folder);
74 CREATE UNIQUE INDEX rtp_report_folder_once_idx ON reporter.report (name,folder);
75
76 CREATE TABLE reporter.schedule (
77         id              SERIAL                          PRIMARY KEY,
78         report          INT                             NOT NULL REFERENCES reporter.report (id) DEFERRABLE INITIALLY DEFERRED,
79         folder          INT                             NOT NULL REFERENCES reporter.output_folder (id) DEFERRABLE INITIALLY DEFERRED,
80         runner          INT                             NOT NULL REFERENCES actor.usr (id) DEFERRABLE INITIALLY DEFERRED,
81         run_time        TIMESTAMP WITH TIME ZONE        NOT NULL DEFAULT NOW(),
82         start_time      TIMESTAMP WITH TIME ZONE,
83         complete_time   TIMESTAMP WITH TIME ZONE,
84         email           TEXT,
85         excel_format    BOOL                            NOT NULL DEFAULT TRUE,
86         html_format     BOOL                            NOT NULL DEFAULT TRUE,
87         csv_format      BOOL                            NOT NULL DEFAULT TRUE,
88         chart_pie       BOOL                            NOT NULL DEFAULT FALSE,
89         chart_bar       BOOL                            NOT NULL DEFAULT FALSE,
90         chart_line      BOOL                            NOT NULL DEFAULT FALSE,
91         error_code      INT,
92         error_text      TEXT
93 );
94 CREATE INDEX rpt_sched_runner_idx ON reporter.schedule (runner);
95 CREATE INDEX rpt_sched_folder_idx ON reporter.schedule (folder);
96
97 CREATE OR REPLACE VIEW reporter.simple_record AS
98 SELECT  r.id,
99         s.metarecord,
100         r.fingerprint,
101         r.quality,
102         r.tcn_source,
103         r.tcn_value,
104         title.value AS title,
105         uniform_title.value AS uniform_title,
106         author.value AS author,
107         publisher.value AS publisher,
108         SUBSTRING(pubdate.value FROM $$\d+$$) AS pubdate,
109         series_title.value AS series_title,
110         series_statement.value AS series_statement,
111         summary.value AS summary,
112         ARRAY_ACCUM( SUBSTRING(isbn.value FROM $$^\S+$$) ) AS isbn,
113         ARRAY_ACCUM( SUBSTRING(issn.value FROM $$^\S+$$) ) AS issn,
114         ARRAY((SELECT DISTINCT value FROM metabib.full_rec WHERE tag = '650' AND subfield = 'a' AND record = r.id)) AS topic_subject,
115         ARRAY((SELECT DISTINCT value FROM metabib.full_rec WHERE tag = '651' AND subfield = 'a' AND record = r.id)) AS geographic_subject,
116         ARRAY((SELECT DISTINCT value FROM metabib.full_rec WHERE tag = '655' AND subfield = 'a' AND record = r.id)) AS genre,
117         ARRAY((SELECT DISTINCT value FROM metabib.full_rec WHERE tag = '600' AND subfield = 'a' AND record = r.id)) AS name_subject,
118         ARRAY((SELECT DISTINCT value FROM metabib.full_rec WHERE tag = '610' AND subfield = 'a' AND record = r.id)) AS corporate_subject,
119         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
120   FROM  biblio.record_entry r
121         JOIN metabib.metarecord_source_map s ON (s.source = r.id)
122         LEFT JOIN metabib.full_rec uniform_title ON (r.id = uniform_title.record AND uniform_title.tag = '240' AND uniform_title.subfield = 'a')
123         LEFT JOIN metabib.full_rec title ON (r.id = title.record AND title.tag = '245' AND title.subfield = 'a')
124         LEFT JOIN metabib.full_rec author ON (r.id = author.record AND author.tag = '100' AND author.subfield = 'a')
125         LEFT JOIN metabib.full_rec publisher ON (r.id = publisher.record AND publisher.tag = '260' AND publisher.subfield = 'b')
126         LEFT JOIN metabib.full_rec pubdate ON (r.id = pubdate.record AND pubdate.tag = '260' AND pubdate.subfield = 'c')
127         LEFT JOIN metabib.full_rec isbn ON (r.id = isbn.record AND isbn.tag IN ('024', '020') AND isbn.subfield IN ('a','z'))
128         LEFT JOIN metabib.full_rec issn ON (r.id = issn.record AND issn.tag = '022' AND issn.subfield = 'a')
129         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')
130         LEFT JOIN metabib.full_rec series_statement ON (r.id = series_statement.record AND series_statement.tag = '490' AND series_statement.subfield = 'a')
131         LEFT JOIN metabib.full_rec summary ON (r.id = summary.record AND summary.tag = '520' AND summary.subfield = 'a')
132   GROUP BY 1,2,3,4,5,6,7,8,9,10,11,12,13,14;
133
134 CREATE OR REPLACE VIEW reporter.old_super_simple_record AS
135 SELECT  r.id,
136         r.fingerprint,
137         r.quality,
138         r.tcn_source,
139         r.tcn_value,
140         title.value AS title,
141         FIRST(author.value) AS author,
142         publisher.value AS publisher,
143         SUBSTRING(pubdate.value FROM $$\d+$$) AS pubdate,
144         ARRAY_ACCUM( SUBSTRING(isbn.value FROM $$^\S+$$) ) AS isbn,
145         ARRAY_ACCUM( SUBSTRING(issn.value FROM $$^\S+$$) ) AS issn
146   FROM  biblio.record_entry r
147         LEFT JOIN metabib.full_rec title ON (r.id = title.record AND title.tag = '245' AND title.subfield = 'a')
148         LEFT JOIN metabib.full_rec author ON (r.id = author.record AND author.tag IN ('100','110','111') AND author.subfield = 'a')
149         LEFT JOIN metabib.full_rec publisher ON (r.id = publisher.record AND publisher.tag = '260' AND publisher.subfield = 'b')
150         LEFT JOIN metabib.full_rec pubdate ON (r.id = pubdate.record AND pubdate.tag = '260' AND pubdate.subfield = 'c')
151         LEFT JOIN metabib.full_rec isbn ON (r.id = isbn.record AND isbn.tag IN ('024', '020') AND isbn.subfield IN ('a','z'))
152         LEFT JOIN metabib.full_rec issn ON (r.id = issn.record AND issn.tag = '022' AND issn.subfield = 'a')
153   GROUP BY 1,2,3,4,5,6,8,9;
154
155 CREATE TABLE reporter.materialized_simple_record AS SELECT * FROM reporter.old_super_simple_record WHERE 1=0;
156 ALTER TABLE reporter.materialized_simple_record ADD PRIMARY KEY (id);
157 CREATE VIEW reporter.super_simple_record AS SELECT * FROM reporter.materialized_simple_record;
158
159 CREATE OR REPLACE FUNCTION reporter.simple_rec_sync () RETURNS TRIGGER AS $$
160 DECLARE
161     r_id        BIGINT;
162     new_data    RECORD;
163 BEGIN
164     IF TG_OP IN ('DELETE') THEN
165         r_id := OLD.record;
166     ELSE
167         r_id := NEW.record;
168     END IF;
169
170     SELECT * INTO new_data FROM reporter.materialized_simple_record WHERE id = r_id FOR UPDATE;
171     DELETE FROM reporter.materialized_simple_record WHERE id = r_id;
172
173     IF TG_OP IN ('DELETE') THEN
174         RETURN OLD;
175     ELSE
176         INSERT INTO reporter.materialized_simple_record SELECT DISTINCT ON (id) * FROM reporter.old_super_simple_record WHERE id = NEW.record;
177         RETURN NEW;
178     END IF;
179
180 END;
181 $$ LANGUAGE PLPGSQL;
182
183 CREATE TRIGGER zzz_update_materialized_simple_record_tgr
184     AFTER INSERT OR UPDATE OR DELETE ON metabib.full_rec
185     FOR EACH ROW EXECUTE PROCEDURE reporter.simple_rec_sync();
186
187 CREATE OR REPLACE FUNCTION reporter.disable_materialized_simple_record_trigger () RETURNS VOID AS $$
188     DROP TRIGGER zzz_update_materialized_simple_record_tgr ON metabib.full_rec;
189 $$ LANGUAGE SQL;
190
191 CREATE OR REPLACE FUNCTION reporter.enable_materialized_simple_record_trigger () RETURNS VOID AS $$
192
193     TRUNCATE TABLE reporter.materialized_simple_record;
194
195     INSERT INTO reporter.materialized_simple_record
196         (id,fingerprint,quality,tcn_source,tcn_value,title,author,publisher,pubdate,isbn,issn)
197         SELECT DISTINCT ON (id) * FROM reporter.old_super_simple_record;
198
199     CREATE TRIGGER zzz_update_materialized_simple_record_tgr
200         AFTER INSERT OR UPDATE OR DELETE ON metabib.full_rec
201         FOR EACH ROW EXECUTE PROCEDURE reporter.simple_rec_sync();
202
203 $$ LANGUAGE SQL;
204
205 CREATE OR REPLACE FUNCTION reporter.refresh_materialized_simple_record () RETURNS VOID AS $$
206     SELECT reporter.disable_materialized_simple_record_trigger();
207     SELECT reporter.enable_materialized_simple_record_trigger();
208 $$ LANGUAGE SQL;
209
210 CREATE OR REPLACE VIEW reporter.demographic AS
211 SELECT  u.id,
212         u.dob,
213         CASE
214                 WHEN u.dob IS NULL
215                         THEN 'Adult'
216                 WHEN AGE(u.dob) > '18 years'::INTERVAL
217                         THEN 'Adult'
218                 ELSE 'Juvenile'
219         END AS general_division
220   FROM  actor.usr u;
221
222 CREATE OR REPLACE VIEW reporter.circ_type AS
223 SELECT  id,
224         CASE WHEN opac_renewal OR phone_renewal OR desk_renewal
225                 THEN 'RENEWAL'
226                 ELSE 'CHECKOUT'
227         END AS "type"
228   FROM  action.circulation;
229
230 CREATE OR REPLACE VIEW reporter.hold_request_record AS
231 SELECT  id,
232         target,
233         hold_type,
234         CASE
235                 WHEN hold_type = 'T'
236                         THEN target
237                 WHEN hold_type = 'V'
238                         THEN (SELECT cn.record FROM asset.call_number cn WHERE cn.id = ahr.target)
239                 WHEN hold_type = 'C'
240                         THEN (SELECT cn.record FROM asset.call_number cn JOIN asset.copy cp ON (cn.id = cp.call_number) WHERE cp.id = ahr.target)
241                 WHEN hold_type = 'M'
242                         THEN (SELECT mr.master_record FROM metabib.metarecord mr WHERE mr.id = ahr.target)
243         END AS bib_record
244   FROM  action.hold_request ahr;
245
246 CREATE OR REPLACE VIEW reporter.xact_billing_totals AS
247 SELECT  b.xact,
248         SUM( CASE WHEN b.voided THEN 0 ELSE amount END ) as unvoided,
249         SUM( CASE WHEN b.voided THEN amount ELSE 0 END ) as voided,
250         SUM( amount ) as total
251   FROM  money.billing b
252   GROUP BY 1;
253
254 CREATE OR REPLACE VIEW reporter.xact_paid_totals AS
255 SELECT  b.xact,
256         SUM( CASE WHEN b.voided THEN 0 ELSE amount END ) as unvoided,
257         SUM( CASE WHEN b.voided THEN amount ELSE 0 END ) as voided,
258         SUM( amount ) as total
259   FROM  money.payment b
260   GROUP BY 1;
261
262 CREATE OR REPLACE VIEW reporter.overdue_circs AS
263 SELECT  *
264   FROM  "action".circulation
265   WHERE checkin_time is null
266         AND (stop_fines NOT IN ('LOST','CLAIMSRETURNED') OR stop_fines IS NULL)
267         AND due_date < now();
268
269 CREATE OR REPLACE VIEW reporter.overdue_reports AS
270  SELECT s.id, c.barcode AS runner_barcode, r.name, s.run_time, s.run_time - now() AS scheduled_wait_time
271    FROM reporter.schedule s
272    JOIN reporter.report r ON r.id = s.report
273    JOIN actor.usr u ON s.runner = u.id
274    JOIN actor.card c ON c.id = u.card
275   WHERE s.start_time IS NULL AND s.run_time < now();
276
277 CREATE OR REPLACE VIEW reporter.pending_reports AS
278  SELECT s.id, c.barcode AS runner_barcode, r.name, s.run_time, s.run_time - now() AS scheduled_wait_time
279    FROM reporter.schedule s
280    JOIN reporter.report r ON r.id = s.report
281    JOIN actor.usr u ON s.runner = u.id
282    JOIN actor.card c ON c.id = u.card
283   WHERE s.start_time IS NULL;
284
285 CREATE OR REPLACE VIEW reporter.currently_running AS
286  SELECT s.id, c.barcode AS runner_barcode, r.name, s.run_time, s.run_time - now() AS scheduled_wait_time
287    FROM reporter.schedule s
288    JOIN reporter.report r ON r.id = s.report
289    JOIN actor.usr u ON s.runner = u.id
290    JOIN actor.card c ON c.id = u.card
291   WHERE s.start_time IS NOT NULL AND s.complete_time IS NULL;
292
293 COMMIT;
294