2 -- Functions used by collectionHQ reporting. This only needs to be run once.
5 -- Copyright (C) 2011-2012 Equinox Software Inc.
6 -- Ben Ostrowsky <ben@esilibrary.com>
7 -- Galen Charlton <gmc@esilibrary.com>
9 -- Original version sponsored by the King County Library System
11 -- This program is free software; you can redistribute it and/or modify
12 -- it under the terms of the GNU General Public License as published by
13 -- the Free Software Foundation; either version 2 of the License, or
14 -- (at your option) any later version.
16 -- This program is distributed in the hope that it will be useful,
17 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
18 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 -- GNU General Public License for more details.
21 -- You should have received a copy of the GNU General Public License
22 -- along with this program; if not, write to the Free Software
23 -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 CREATE SCHEMA collectionHQ;
27 CREATE OR REPLACE FUNCTION collectionHQ.attempt_year (TEXT) RETURNS TEXT AS $$
29 attempt_value ALIAS FOR $1;
33 EXECUTE 'SELECT SUBSTRING(REGEXP_REPLACE(' || quote_literal(attempt_value) || E', E\'[^0-9]\', \'\', \'g\') FROM 1 FOR 4) AS a;'
40 EXECUTE E'SELECT \'\' AS a;'
45 $$ LANGUAGE PLPGSQL STRICT STABLE;
48 CREATE OR REPLACE FUNCTION collectionHQ.attempt_price (TEXT) RETURNS TEXT AS $$
50 attempt_value ALIAS FOR $1;
54 EXECUTE 'SELECT (REGEXP_REPLACE(' || quote_literal(attempt_value) || E', E\'[^0-9\.]\', \'\', \'g\')::NUMERIC(8,2) * 100)::INTEGER AS a;'
61 EXECUTE E'SELECT \'\' AS a;'
66 $$ LANGUAGE PLPGSQL STRICT STABLE;
69 CREATE OR REPLACE FUNCTION collectionHQ.attempt_isbn (BIGINT) RETURNS TEXT AS $$
72 output TEXT[]; -- Coding this now in case we ever can send more than one isbn
76 -- mine metabib.real_full_rec
78 SELECT regexp_replace(value,'^\s*([^\s\(\)\:\.]*)[\s\(\)\:\.]*.*$','\1','g')
79 FROM metabib.real_full_rec where
81 subfield in('a','z') AND
82 length(regexp_replace(value,'^\s*([^\s\(\)\:\.]*)[\s\(\)\:\.]*.*$','\1','g')) < 14 AND
84 ORDER BY length(regexp_replace(value,'^\s*([^\s\(\)\:\.]*)[\s\(\)\:\.]*.*$','\1','g')) DESC, regexp_replace(value,'^\s*([^\s\(\)\:\.]*)[\s\(\)\:\.]*.*$','\1','g')
86 output = array_append(output, loopvar);
89 -- Fail over to reporter.materialized_simple_record
90 IF array_length(output, 1) = 0
93 SELECT regexp_replace(isbn,'^\s*([^\s\(\)\:\.]*)[\s\(\)\:\.]*.*$','\1','g'),* FROM
95 SELECT unnest(isbn) AS "isbn" FROM
96 reporter.materialized_simple_record
101 length(regexp_replace(isbn,'^\s*([^\s\(\)\:\.]*)[\s\(\)\:\.]*.*$','\1','g')) < 14
102 ORDER BY length(regexp_replace(isbn,'^\s*([^\s\(\)\:\.]*)[\s\(\)\:\.]*.*$','\1','g')) DESC, regexp_replace(isbn,'^\s*([^\s\(\)\:\.]*)[\s\(\)\:\.]*.*$','\1','g')
104 output = array_append(output, loopvar);
107 IF array_length(output, 1) = 0
110 EXECUTE E'SELECT \'\' AS a;'
112 output = array_append(output, loopvar);
121 EXECUTE E'SELECT \'\' AS a;'
123 output = array_append(output, loopvar);
127 $$ LANGUAGE plpgsql STRICT STABLE;
130 CREATE OR REPLACE FUNCTION collectionHQ.quote (TEXT) RETURNS TEXT AS $$
135 IF value IS NOT NULL AND value <> '' THEN
136 RETURN '##' || value || '##';
141 $$ LANGUAGE PLPGSQL STRICT STABLE;
143 DROP FUNCTION IF EXISTS collectionHQ.write_item_rows_to_stdout (TEXT, INT);
144 CREATE OR REPLACE FUNCTION collectionHQ.write_item_rows_to_stdout (TEXT, INT) RETURNS VOID AS $$
145 -- Usage: SELECT collectionHQ.write_item_rows_to_stdout ('LIBRARYCODE',org_unit_id);
149 authority_code ALIAS FOR $1;
150 org_unit_id ALIAS for $2;
156 cumulative_use_total TEXT;
157 cumulative_use_current TEXT;
167 collection_code TEXT;
168 collection_code_level_2 TEXT;
176 num_rows INTEGER := 0;
181 SELECT id FROM asset.copy WHERE NOT deleted AND circ_lib IN (SELECT id FROM actor.org_unit_descendants(org_unit_id)) ORDER BY id
184 SELECT cn.record, cn.label, collectionHQ.attempt_isbn(cn.record::BIGINT)
185 INTO lms_bib_id, filter_level_1, isbn
186 FROM asset.call_number cn, asset.copy c
187 WHERE c.call_number = cn.id AND c.id = item;
188 SELECT collectionHQ.attempt_price(ac.price::TEXT), barcode, ac.status,
189 REPLACE(create_date::DATE::TEXT, '-', ''),
190 CASE WHEN floating::INT > 0 THEN 'Y' ELSE NULL END
191 INTO price, bar_code, status, date_added, rotating_stock
194 IF price IS NULL OR price = '' THEN
195 SELECT collectionHQ.attempt_price((XPATH('//marc:datafield[@tag="020"][1]/marc:subfield[@code="c"]/text()', marc::XML, ARRAY[ARRAY['marc', 'http://www.loc.gov/MARC21/slim']]))[1]::TEXT)
197 FROM biblio.record_entry
198 WHERE id = lms_bib_id;
200 SELECT REPLACE(NOW()::DATE::TEXT, '-', '') INTO extract_date;
201 SELECT ou.shortname INTO library_code FROM actor.org_unit ou, asset.copy c WHERE ou.id = c.circ_lib AND c.id = item;
202 SELECT aou.shortname, REPLACE(circ.xact_start::DATE::TEXT, '-', '') INTO last_circ_lib, last_use_date FROM actor.org_unit aou INNER JOIN action.all_circulation circ ON (circ.circ_lib = aou.id)
203 WHERE circ.target_copy = item ORDER BY circ.xact_start DESC LIMIT 1;
204 SELECT REPLACE(xact_start::DATE::TEXT, '-', '') INTO last_use_date FROM action.circulation WHERE target_copy = item ORDER BY xact_start DESC LIMIT 1;
205 SELECT circ_count INTO cumulative_use_total FROM extend_reporter.full_circ_count WHERE id = item;
206 IF cumulative_use_total IS NULL THEN
207 cumulative_use_total := '0';
209 SELECT MAX(dest_recv_time) INTO arrived
210 FROM action.transit_copy atc
211 JOIN asset.copy ac ON (ac.id = atc.target_copy AND ac.circ_lib = atc.dest)
213 IF arrived IS NOT NULL THEN
214 SELECT COUNT(*) INTO cumulative_use_current FROM action.circulation WHERE target_copy = item AND xact_start > arrived;
216 cumulative_use_current := '0';
218 SELECT SUBSTRING(value FROM 1 FOR 100) INTO notes FROM asset.copy_note WHERE owning_copy = item AND title ILIKE '%collectionHQ%' ORDER BY id LIMIT 1;
219 SELECT l.name INTO collection_code FROM asset.copy c, asset.copy_location l WHERE c.location = l.id AND c.id = item;
221 purchase_code := ''; -- FIXME do we want something else here?
222 lib_supsel_tag := ''; -- FIXME do we want something else here?
223 gen_supsel_tag := ''; -- FIXME do we want something else here?
224 collection_code_level_2 := ''; -- FIXME do we want something else here?
225 filter_level_2 := ''; -- FIXME do we want something else here?
226 filter_level_3 := ''; -- FIXME do we want something else here?
227 filter_level_4 := ''; -- FIXME do we want something else here?
229 output := '##HOLD##,'
231 || COALESCE(collectionHQ.quote(authority_code), '') || ','
232 || COALESCE(collectionHQ.quote(library_code), '') || ','
233 || COALESCE(collectionHQ.quote(last_circ_lib), '') || ','
234 || COALESCE(collectionHQ.quote(bar_code), '') || ','
235 || COALESCE(collectionHQ.quote(last_use_date), '') || ','
236 || COALESCE(cumulative_use_total, '') || ','
237 --|| COALESCE(cumulative_use_current, '') || ','
239 || COALESCE(collectionHQ.quote(status), '') || ','
240 || COALESCE(collectionHQ.quote(date_added), '') || ','
241 || COALESCE(price, '') || ','
242 || COALESCE(collectionHQ.quote(purchase_code), '') || ','
243 || COALESCE(collectionHQ.quote(rotating_stock), '') || ','
244 || COALESCE(collectionHQ.quote(lib_supsel_tag), '') || ','
245 || COALESCE(collectionHQ.quote(gen_supsel_tag), '') || ','
246 || COALESCE(collectionHQ.quote(notes), '') || ','
247 || COALESCE(collectionHQ.quote(extract_date), '') || ','
248 || COALESCE(collectionHQ.quote(collection_code), '') || ','
249 || COALESCE(collectionHQ.quote(collection_code_level_2), '') || ','
250 || COALESCE(collectionHQ.quote(filter_level_1), '') || ','
251 || COALESCE(collectionHQ.quote(filter_level_2), '') || ','
252 || COALESCE(collectionHQ.quote(filter_level_3), '') || ','
253 || COALESCE(collectionHQ.quote(filter_level_4), '') || ','
254 || COALESCE(collectionHQ.quote(isbn), '');
256 RAISE INFO '%', output;
258 num_rows := num_rows + 1;
259 IF (num_rows::numeric % 1000.0 = 0.0) THEN RAISE INFO '% rows written', num_rows; END IF;
263 RAISE INFO '% rows written in total.', num_rows;
269 DROP FUNCTION IF EXISTS collectionHQ.write_bib_rows_to_stdout(TEXT, INT);
270 CREATE OR REPLACE FUNCTION collectionHQ.write_bib_rows_to_stdout (TEXT, INT) RETURNS VOID AS $$
271 -- Usage: SELECT collectionHQ.write_bib_rows_to_stdout('LIBRARYCODE', org_unit_id);
274 library_service_code ALIAS FOR $1;
275 org_unit_id ALIAS FOR $2;
279 edition_num TEXT := '';
280 publication_date TEXT := '';
281 publisher TEXT := '';
283 lms_item_type TEXT := '';
284 class_num TEXT := '';
287 extract_date TEXT := '';
290 num_rows INTEGER := 0;
295 SELECT DISTINCT bre.id FROM biblio.record_entry bre JOIN asset.call_number acn ON (acn.record = bre.id) WHERE acn.owning_lib IN (SELECT id FROM actor.org_unit_descendants(org_unit_id)) AND NOT acn.deleted AND NOT bre.deleted
298 SELECT collectionHQ.attempt_isbn(r.id::BIGINT),
299 SUBSTRING(r.title FROM 1 FOR 100),
300 SUBSTRING(r.author FROM 1 FOR 50)
301 INTO isbn, title, author
302 FROM reporter.materialized_simple_record r
303 WHERE id = lms_bib_id;
305 SUBSTRING(naco_normalize((XPATH('//marc:datafield[@tag="250"][1]/marc:subfield[@code="a"]/text()', marc::XML, ARRAY[ARRAY['marc', 'http://www.loc.gov/MARC21/slim']]))[1]::TEXT, 'a') FROM 1 FOR 20),
306 collectionHQ.attempt_year((XPATH('//marc:datafield[@tag="260"][1]/marc:subfield[@code="c"]/text()', marc::XML, ARRAY[ARRAY['marc', 'http://www.loc.gov/MARC21/slim']]))[1]::TEXT),
307 SUBSTRING(naco_normalize((XPATH('//marc:datafield[@tag="260"][1]/marc:subfield[@code="b"]/text()', marc::XML, ARRAY[ARRAY['marc', 'http://www.loc.gov/MARC21/slim']]))[1]::TEXT, 'b') FROM 1 FOR 100),
308 collectionHQ.attempt_price((XPATH('//marc:datafield[@tag="020"][1]/marc:subfield[@code="c"]/text()', marc::XML, ARRAY[ARRAY['marc', 'http://www.loc.gov/MARC21/slim']]))[1]::TEXT),
309 SUBSTRING(naco_normalize((XPATH('//marc:datafield[@tag="082"][1]/marc:subfield[@code="a"][1]/text()', marc::XML, ARRAY[ARRAY['marc', 'http://www.loc.gov/MARC21/slim']]))[1]::TEXT, 'a') FROM 1 FOR 20),
310 (SELECT '!!!' || SUBSTRING(STRING_AGG("six50",'!!!') FROM 1 FOR 200) || '!!!' FROM
311 (SELECT naco_normalize( unnest(XPATH('//marc:datafield[@tag="650"]/marc:subfield[@code="a"]/text()', marc::XML, ARRAY[ARRAY['marc', 'http://www.loc.gov/MARC21/slim']]))::TEXT) AS "six50"
312 FROM BIBLIO.RECORD_ENTRY WHERE ID=A.ID ) AS B
314 (SELECT '!!!' || SUBSTRING(STRING_AGG("six55",'!!!') FROM 1 FOR 200) || '!!!' FROM
315 (SELECT naco_normalize( unnest(XPATH('//marc:datafield[@tag="655"]/marc:subfield[@code="a"]/text()', marc::XML, ARRAY[ARRAY['marc', 'http://www.loc.gov/MARC21/slim']]))::TEXT) AS "six55"
316 FROM BIBLIO.RECORD_ENTRY WHERE ID=A.ID ) AS C
319 INTO edition_num, publication_date, publisher, price, class_num, subject, genre
320 FROM biblio.record_entry A
321 WHERE id = lms_bib_id;
323 SELECT circ_modifier INTO lms_item_type FROM asset.copy c, asset.call_number cn WHERE cn.record = lms_bib_id AND c.circ_lib IN (SELECT id FROM actor.org_unit_descendants(org_unit_id)) AND cn.id = c.call_number AND NOT cn.deleted AND NOT c.deleted LIMIT 1;
324 SELECT REPLACE(NOW()::DATE::TEXT, '-', '') INTO extract_date;
329 || COALESCE(collectionHQ.quote(library_service_code), '') || ','
330 || COALESCE(collectionHQ.quote(isbn), '') || ','
331 || COALESCE(collectionHQ.quote(title), '') || ','
332 || COALESCE(collectionHQ.quote(author), '') || ','
333 || COALESCE(collectionHQ.quote(edition_num), '') || ','
334 || COALESCE(collectionHQ.quote(publication_date), '') || ','
335 || COALESCE(collectionHQ.quote(publisher), '') || ','
336 || COALESCE(price, '') || ','
337 || COALESCE(collectionHQ.quote(lms_item_type), '') || ','
338 || COALESCE(collectionHQ.quote(class_num), '') || ','
339 || COALESCE(collectionHQ.quote(extract_date), '') || ','
340 || COALESCE(collectionHQ.quote(subject), '') || ','
341 || COALESCE(collectionHQ.quote(genre), '');
343 RAISE INFO '%', output;
345 num_rows := num_rows + 1;
346 IF (num_rows::numeric % 1000.0 = 0.0) THEN RAISE INFO '% rows written', num_rows; END IF;
350 RAISE INFO '% rows written in total.', num_rows;