]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/sql/Pg/040.schema.asset.sql
Add label_prefix and label_suffix columns to asset.copy_location
[Evergreen.git] / Open-ILS / src / sql / Pg / 040.schema.asset.sql
1 /*
2  * Copyright (C) 2004-2008  Georgia Public Library Service
3  * Copyright (C) 2007-2008  Equinox Software, Inc.
4  * Mike Rylander <miker@esilibrary.com> 
5  *
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.
10  *
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.
15  *
16  */
17
18 DROP SCHEMA IF EXISTS asset CASCADE;
19
20 BEGIN;
21
22 CREATE SCHEMA asset;
23
24 CREATE TABLE asset.copy_location (
25         id              SERIAL  PRIMARY KEY,
26         name            TEXT    NOT NULL,
27         owning_lib      INT     NOT NULL REFERENCES actor.org_unit (id) DEFERRABLE INITIALLY DEFERRED,
28         holdable        BOOL    NOT NULL DEFAULT TRUE,
29         hold_verify     BOOL    NOT NULL DEFAULT FALSE,
30         opac_visible    BOOL    NOT NULL DEFAULT TRUE,
31         circulate       BOOL    NOT NULL DEFAULT TRUE,
32         label_prefix    TEXT,
33         label_suffix    TEXT,
34         CONSTRAINT acl_name_once_per_lib UNIQUE (name, owning_lib)
35 );
36
37 CREATE TABLE asset.copy_location_order
38 (
39         id              SERIAL           PRIMARY KEY,
40         location        INT              NOT NULL
41                                              REFERENCES asset.copy_location
42                                              ON DELETE CASCADE
43                                              DEFERRABLE INITIALLY DEFERRED,
44         org             INT              NOT NULL
45                                              REFERENCES actor.org_unit
46                                              ON DELETE CASCADE
47                                              DEFERRABLE INITIALLY DEFERRED,
48         position        INT              NOT NULL DEFAULT 0,
49         CONSTRAINT acplo_once_per_org UNIQUE ( location, org )
50 );
51
52 CREATE TABLE asset.copy (
53         id              BIGSERIAL                       PRIMARY KEY,
54         circ_lib        INT                             NOT NULL REFERENCES actor.org_unit (id) DEFERRABLE INITIALLY DEFERRED,
55         creator         BIGINT                          NOT NULL,
56         call_number     BIGINT                          NOT NULL,
57         editor          BIGINT                          NOT NULL,
58         create_date     TIMESTAMP WITH TIME ZONE        DEFAULT NOW(),
59         edit_date       TIMESTAMP WITH TIME ZONE        DEFAULT NOW(),
60         copy_number     INT,
61         status          INT                             NOT NULL DEFAULT 0 REFERENCES config.copy_status (id) DEFERRABLE INITIALLY DEFERRED,
62         location        INT                             NOT NULL DEFAULT 1 REFERENCES asset.copy_location (id) DEFERRABLE INITIALLY DEFERRED,
63         loan_duration   INT                             NOT NULL CHECK ( loan_duration IN (1,2,3) ),
64         fine_level      INT                             NOT NULL CHECK ( fine_level IN (1,2,3) ),
65         age_protect     INT,
66         circulate       BOOL                            NOT NULL DEFAULT TRUE,
67         deposit         BOOL                            NOT NULL DEFAULT FALSE,
68         ref             BOOL                            NOT NULL DEFAULT FALSE,
69         holdable        BOOL                            NOT NULL DEFAULT TRUE,
70         deposit_amount  NUMERIC(6,2)                    NOT NULL DEFAULT 0.00,
71         price           NUMERIC(8,2),
72         barcode         TEXT                            NOT NULL,
73         circ_modifier   TEXT,
74         circ_as_type    TEXT,
75         dummy_title     TEXT,
76         dummy_author    TEXT,
77         alert_message   TEXT,
78         opac_visible    BOOL                            NOT NULL DEFAULT TRUE,
79         deleted         BOOL                            NOT NULL DEFAULT FALSE,
80         floating                BOOL                            NOT NULL DEFAULT FALSE,
81         dummy_isbn      TEXT,
82         status_changed_time TIMESTAMP WITH TIME ZONE,
83         mint_condition      BOOL        NOT NULL DEFAULT TRUE,
84     cost    NUMERIC(8,2)
85 );
86 CREATE UNIQUE INDEX copy_barcode_key ON asset.copy (barcode) WHERE deleted = FALSE OR deleted IS FALSE;
87 CREATE INDEX cp_cn_idx ON asset.copy (call_number);
88 CREATE INDEX cp_avail_cn_idx ON asset.copy (call_number);
89 CREATE INDEX cp_creator_idx  ON asset.copy ( creator );
90 CREATE INDEX cp_editor_idx   ON asset.copy ( editor );
91 CREATE RULE protect_copy_delete AS ON DELETE TO asset.copy DO INSTEAD UPDATE asset.copy SET deleted = TRUE WHERE OLD.id = asset.copy.id;
92
93 CREATE TABLE asset.opac_visible_copies (
94   id        BIGINT primary key, -- copy id
95   record    BIGINT,
96   circ_lib  INTEGER
97 );
98 COMMENT ON TABLE asset.opac_visible_copies IS $$
99 Materialized view of copies that are visible in the OPAC, used by
100 search.query_parser_fts() to speed up OPAC visibility checks on large
101 databases.  Contents are maintained by a set of triggers.
102 $$;
103 CREATE INDEX opac_visible_copies_idx1 on asset.opac_visible_copies (record, circ_lib);
104
105 CREATE OR REPLACE FUNCTION asset.acp_status_changed()
106 RETURNS TRIGGER AS $$
107 BEGIN
108     IF NEW.status <> OLD.status THEN
109         NEW.status_changed_time := now();
110     END IF;
111     RETURN NEW;
112 END;
113 $$ LANGUAGE plpgsql;
114
115 CREATE TRIGGER acp_status_changed_trig
116     BEFORE UPDATE ON asset.copy
117     FOR EACH ROW EXECUTE PROCEDURE asset.acp_status_changed();
118
119 CREATE TABLE asset.stat_cat_entry_transparency_map (
120         id                      BIGSERIAL       PRIMARY KEY,
121         stat_cat                INT             NOT NULL, -- needs ON DELETE CASCADE
122         stat_cat_entry          INT             NOT NULL, -- needs ON DELETE CASCADE
123         owning_transparency     INT             NOT NULL, -- needs ON DELETE CASCADE
124         CONSTRAINT scte_once_per_trans UNIQUE (owning_transparency,stat_cat)
125 );
126
127 CREATE TABLE asset.stat_cat (
128         id              SERIAL  PRIMARY KEY,
129         owner           INT     NOT NULL,
130         opac_visible    BOOL    NOT NULL DEFAULT FALSE,
131         name            TEXT    NOT NULL,
132         required        BOOL    NOT NULL DEFAULT FALSE,
133         CONSTRAINT sc_once_per_owner UNIQUE (owner,name)
134 );
135
136 CREATE TABLE asset.stat_cat_entry (
137         id              SERIAL  PRIMARY KEY,
138         stat_cat        INT     NOT NULL,
139         owner           INT     NOT NULL,
140         value           TEXT    NOT NULL,
141         CONSTRAINT sce_once_per_owner UNIQUE (stat_cat,owner,value)
142 );
143
144 CREATE TABLE asset.stat_cat_entry_copy_map (
145         id              BIGSERIAL       PRIMARY KEY,
146         stat_cat        INT             NOT NULL,
147         stat_cat_entry  INT             NOT NULL,
148         owning_copy     BIGINT          NOT NULL,
149         CONSTRAINT sce_once_per_copy UNIQUE (owning_copy,stat_cat)
150 );
151 CREATE INDEX scecm_owning_copy_idx ON asset.stat_cat_entry_copy_map(owning_copy);
152
153 CREATE TABLE asset.copy_note (
154         id              BIGSERIAL                       PRIMARY KEY,
155         owning_copy     BIGINT                          NOT NULL,
156         creator         BIGINT                          NOT NULL,
157         create_date     TIMESTAMP WITH TIME ZONE        DEFAULT NOW(),
158         pub             BOOL                            NOT NULL DEFAULT FALSE,
159         title           TEXT                            NOT NULL,
160         value           TEXT                            NOT NULL
161 );
162 CREATE INDEX asset_copy_note_creator_idx ON asset.copy_note ( creator );
163
164 CREATE TABLE asset.uri (
165     id  SERIAL  PRIMARY KEY,
166     href    TEXT    NOT NULL,
167     label   TEXT,
168     use_restriction TEXT,
169     active  BOOL    NOT NULL DEFAULT TRUE
170 );
171
172 CREATE TABLE asset.call_number_class (
173     id             bigserial     PRIMARY KEY,
174     name           TEXT          NOT NULL,
175     normalizer     TEXT          NOT NULL DEFAULT 'asset.normalize_generic',
176     field          TEXT          NOT NULL DEFAULT '050ab,055ab,060ab,070ab,080ab,082ab,086ab,088ab,090,092,096,098,099'
177 );
178 COMMENT ON TABLE asset.call_number_class IS $$
179 Defines the call number normalization database functions in the "normalizer"
180 column and the tag/subfield combinations to use to lookup the call number in
181 the "field" column for a given classification scheme. Tag/subfield combinations
182 are delimited by commas.
183 $$;
184
185 CREATE OR REPLACE FUNCTION asset.label_normalizer() RETURNS TRIGGER AS $func$
186 DECLARE
187     sortkey        TEXT := '';
188 BEGIN
189     sortkey := NEW.label_sortkey;
190
191     EXECUTE 'SELECT ' || acnc.normalizer || '(' || 
192        quote_literal( NEW.label ) || ')'
193        FROM asset.call_number_class acnc
194        WHERE acnc.id = NEW.label_class
195        INTO sortkey;
196
197     NEW.label_sortkey = sortkey;
198
199     RETURN NEW;
200 END;
201 $func$ LANGUAGE PLPGSQL;
202
203 CREATE OR REPLACE FUNCTION asset.label_normalizer_generic(TEXT) RETURNS TEXT AS $func$
204     # Created after looking at the Koha C4::ClassSortRoutine::Generic module,
205     # thus could probably be considered a derived work, although nothing was
206     # directly copied - but to err on the safe side of providing attribution:
207     # Copyright (C) 2007 LibLime
208     # Licensed under the GPL v2 or later
209
210     use strict;
211     use warnings;
212
213     # Converts the callnumber to uppercase
214     # Strips spaces from start and end of the call number
215     # Converts anything other than letters, digits, and periods into underscores
216     # Collapses multiple underscores into a single underscore
217     my $callnum = uc(shift);
218     $callnum =~ s/^\s//g;
219     $callnum =~ s/\s$//g;
220     $callnum =~ s/[^A-Z0-9_.]/_/g;
221     $callnum =~ s/_{2,}/_/g;
222
223     return $callnum;
224 $func$ LANGUAGE PLPERLU;
225
226 CREATE OR REPLACE FUNCTION asset.label_normalizer_dewey(TEXT) RETURNS TEXT AS $func$
227     # Derived from the Koha C4::ClassSortRoutine::Dewey module
228     # Copyright (C) 2007 LibLime
229     # Licensed under the GPL v2 or later
230
231     use strict;
232     use warnings;
233
234     my $init = uc(shift);
235     $init =~ s/^\s+//;
236     $init =~ s/\s+$//;
237     $init =~ s!/!!g;
238     $init =~ s/^([\p{IsAlpha}]+)/$1 /;
239     my @tokens = split /\.|\s+/, $init;
240     my $digit_group_count = 0;
241     for (my $i = 0; $i <= $#tokens; $i++) {
242         if ($tokens[$i] =~ /^\d+$/) {
243             $digit_group_count++;
244             if (2 == $digit_group_count) {
245                 $tokens[$i] = sprintf("%-15.15s", $tokens[$i]);
246                 $tokens[$i] =~ tr/ /0/;
247             }
248         }
249     }
250     my $key = join("_", @tokens);
251     $key =~ s/[^\p{IsAlnum}_]//g;
252
253     return $key;
254
255 $func$ LANGUAGE PLPERLU;
256
257 CREATE OR REPLACE FUNCTION asset.label_normalizer_lc(TEXT) RETURNS TEXT AS $func$
258     use strict;
259     use warnings;
260
261     # Library::CallNumber::LC is currently hosted at http://code.google.com/p/library-callnumber-lc/
262     # The author hopes to upload it to CPAN some day, which would make our lives easier
263     use Library::CallNumber::LC;
264
265     my $callnum = Library::CallNumber::LC->new(shift);
266     return $callnum->normalize();
267
268 $func$ LANGUAGE PLPERLU;
269
270 INSERT INTO asset.call_number_class (name, normalizer, field) VALUES 
271     ('Generic', 'asset.label_normalizer_generic', '050ab,055ab,060ab,070ab,080ab,082ab,086ab,088ab,090,092,096,098,099'),
272     ('Dewey (DDC)', 'asset.label_normalizer_dewey', '080ab,082ab'),
273     ('Library of Congress (LC)', 'asset.label_normalizer_lc', '050ab,055ab')
274 ;
275
276 CREATE TABLE asset.call_number (
277         id              bigserial PRIMARY KEY,
278         creator         BIGINT                          NOT NULL,
279         create_date     TIMESTAMP WITH TIME ZONE        DEFAULT NOW(),
280         editor          BIGINT                          NOT NULL,
281         edit_date       TIMESTAMP WITH TIME ZONE        DEFAULT NOW(),
282         record          bigint                          NOT NULL,
283         owning_lib      INT                             NOT NULL,
284         label           TEXT                            NOT NULL,
285         deleted         BOOL                            NOT NULL DEFAULT FALSE,
286         label_class     BIGINT                          DEFAULT 1 NOT NULL
287                                                         REFERENCES asset.call_number_class(id)
288                                                         DEFERRABLE INITIALLY DEFERRED,
289         label_sortkey   TEXT
290 );
291 CREATE INDEX asset_call_number_record_idx ON asset.call_number (record);
292 CREATE INDEX asset_call_number_creator_idx ON asset.call_number (creator);
293 CREATE INDEX asset_call_number_editor_idx ON asset.call_number (editor);
294 CREATE INDEX asset_call_number_dewey_idx ON asset.call_number (public.call_number_dewey(label));
295 CREATE INDEX asset_call_number_upper_label_id_owning_lib_idx ON asset.call_number (upper(label),id,owning_lib);
296 CREATE INDEX asset_call_number_label_sortkey ON asset.call_number(label_sortkey);
297 CREATE UNIQUE INDEX asset_call_number_label_once_per_lib ON asset.call_number (record, owning_lib, label) WHERE deleted = FALSE OR deleted IS FALSE;
298 CREATE RULE protect_cn_delete AS ON DELETE TO asset.call_number DO INSTEAD UPDATE asset.call_number SET deleted = TRUE WHERE OLD.id = asset.call_number.id;
299 CREATE TRIGGER asset_label_sortkey_trigger
300     BEFORE UPDATE OR INSERT ON asset.call_number
301     FOR EACH ROW EXECUTE PROCEDURE asset.label_normalizer();
302
303 CREATE TABLE asset.uri_call_number_map (
304     id          BIGSERIAL   PRIMARY KEY,
305     uri         INT         NOT NULL REFERENCES asset.uri (id),
306     call_number INT         NOT NULL REFERENCES asset.call_number (id),
307     CONSTRAINT uri_cn_once UNIQUE (uri,call_number)
308 );
309 CREATE INDEX asset_uri_call_number_map_cn_idx ON asset.uri_call_number_map (call_number);
310
311 CREATE TABLE asset.call_number_note (
312         id              BIGSERIAL                       PRIMARY KEY,
313         call_number     BIGINT                          NOT NULL,
314         creator         BIGINT                          NOT NULL,
315         create_date     TIMESTAMP WITH TIME ZONE        DEFAULT NOW(),
316         pub             BOOL                            NOT NULL DEFAULT FALSE,
317         title           TEXT                            NOT NULL,
318         value           TEXT                            NOT NULL
319 );
320 CREATE INDEX asset_call_number_note_creator_idx ON asset.call_number_note ( creator );
321
322 CREATE TABLE asset.copy_template (
323         id             SERIAL   PRIMARY KEY,
324         owning_lib     INT      NOT NULL
325                                 REFERENCES actor.org_unit (id)
326                                 DEFERRABLE INITIALLY DEFERRED,
327         creator        BIGINT   NOT NULL
328                                 REFERENCES actor.usr (id)
329                                 DEFERRABLE INITIALLY DEFERRED,
330         editor         BIGINT   NOT NULL
331                                 REFERENCES actor.usr (id)
332                                 DEFERRABLE INITIALLY DEFERRED,
333         create_date    TIMESTAMP WITH TIME ZONE    DEFAULT NOW(),
334         edit_date      TIMESTAMP WITH TIME ZONE    DEFAULT NOW(),
335         name           TEXT     NOT NULL,
336         -- columns above this point are attributes of the template itself
337         -- columns after this point are attributes of the copy this template modifies/creates
338         circ_lib       INT      REFERENCES actor.org_unit (id)
339                                 DEFERRABLE INITIALLY DEFERRED,
340         status         INT      REFERENCES config.copy_status (id)
341                                 DEFERRABLE INITIALLY DEFERRED,
342         location       INT      REFERENCES asset.copy_location (id)
343                                 DEFERRABLE INITIALLY DEFERRED,
344         loan_duration  INT      CONSTRAINT valid_loan_duration CHECK (
345                                     loan_duration IS NULL OR loan_duration IN (1,2,3)),
346         fine_level     INT      CONSTRAINT valid_fine_level CHECK (
347                                     fine_level IS NULL OR loan_duration IN (1,2,3)),
348         age_protect    INT,
349         circulate      BOOL,
350         deposit        BOOL,
351         ref            BOOL,
352         holdable       BOOL,
353         deposit_amount NUMERIC(6,2),
354         price          NUMERIC(8,2),
355         circ_modifier  TEXT,
356         circ_as_type   TEXT,
357         alert_message  TEXT,
358         opac_visible   BOOL,
359         floating       BOOL,
360         mint_condition BOOL
361 );
362
363 CREATE VIEW stats.fleshed_copy AS 
364         SELECT  cp.*,
365                 CAST(cp.create_date AS DATE) AS create_date_day,
366                 CAST(cp.edit_date AS DATE) AS edit_date_day,
367                 DATE_TRUNC('hour', cp.create_date) AS create_date_hour,
368                 DATE_TRUNC('hour', cp.edit_date) AS edit_date_hour,
369                 cn.label AS call_number_label,
370                 cn.owning_lib,
371                 rd.item_lang,
372                 rd.item_type,
373                 rd.item_form
374         FROM    asset.copy cp
375                 JOIN asset.call_number cn ON (cp.call_number = cn.id)
376                 JOIN metabib.rec_descriptor rd ON (rd.record = cn.record);
377
378 CREATE VIEW stats.fleshed_call_number AS 
379         SELECT  cn.*,
380                 CAST(cn.create_date AS DATE) AS create_date_day,
381                 CAST(cn.edit_date AS DATE) AS edit_date_day,
382                 DATE_TRUNC('hour', cn.create_date) AS create_date_hour,
383                 DATE_TRUNC('hour', cn.edit_date) AS edit_date_hour,
384                 rd.item_lang,
385                 rd.item_type,
386                 rd.item_form
387         FROM    asset.call_number cn
388                 JOIN metabib.rec_descriptor rd ON (rd.record = cn.record);
389
390 CREATE OR REPLACE FUNCTION asset.opac_ou_record_copy_count (org INT, record BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
391 DECLARE
392     ans RECORD;
393     trans INT;
394 BEGIN
395     SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = record;
396
397     FOR ans IN SELECT u.id, t.depth FROM actor.org_unit_ancestors(org) AS u JOIN actor.org_unit_type t ON (u.ou_type = t.id) LOOP
398         RETURN QUERY
399         SELECT  ans.depth,
400                 ans.id,
401                 COUNT( av.id ),
402                 SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
403                 COUNT( av.id ),
404                 trans
405           FROM  
406                 actor.org_unit_descendants(ans.id) d
407                 JOIN asset.opac_visible_copies av ON (av.record = record AND av.circ_lib = d.id)
408                 JOIN asset.copy cp ON (cp.id = av.id)
409           GROUP BY 1,2,6;
410
411         IF NOT FOUND THEN
412             RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
413         END IF;
414
415     END LOOP;
416
417     RETURN;
418 END;
419 $f$ LANGUAGE PLPGSQL;
420
421 CREATE OR REPLACE FUNCTION asset.opac_lasso_record_copy_count (i_lasso INT, record BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
422 DECLARE
423     ans RECORD;
424     trans INT;
425 BEGIN
426     SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = record;
427
428     FOR ans IN SELECT u.org_unit AS id FROM actor.org_lasso_map AS u WHERE lasso = i_lasso LOOP
429         RETURN QUERY
430         SELECT  -1,
431                 ans.id,
432                 COUNT( av.id ),
433                 SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
434                 COUNT( av.id ),
435                 trans
436           FROM
437                 actor.org_unit_descendants(ans.id) d
438                 JOIN asset.opac_visible_copies av ON (av.record = record AND av.circ_lib = d.id)
439                 JOIN asset.copy cp ON (cp.id = av.id)
440           GROUP BY 1,2,6;
441
442         IF NOT FOUND THEN
443             RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
444         END IF;
445
446     END LOOP;   
447                 
448     RETURN;     
449 END;            
450 $f$ LANGUAGE PLPGSQL;
451
452 CREATE OR REPLACE FUNCTION asset.staff_ou_record_copy_count (org INT, record BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
453 DECLARE         
454     ans RECORD; 
455     trans INT;
456 BEGIN           
457     SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = record;
458
459     FOR ans IN SELECT u.id, t.depth FROM actor.org_unit_ancestors(org) AS u JOIN actor.org_unit_type t ON (u.ou_type = t.id) LOOP
460         RETURN QUERY
461         SELECT  ans.depth,
462                 ans.id,
463                 COUNT( cp.id ),
464                 SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
465                 COUNT( cp.id ),
466                 trans
467           FROM
468                 actor.org_unit_descendants(ans.id) d
469                 JOIN asset.copy cp ON (cp.circ_lib = d.id)
470                 JOIN asset.call_number cn ON (cn.record = record AND cn.id = cp.call_number)
471           GROUP BY 1,2,6;
472
473         IF NOT FOUND THEN
474             RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
475         END IF;
476
477     END LOOP;
478
479     RETURN;
480 END;
481 $f$ LANGUAGE PLPGSQL;
482
483 CREATE OR REPLACE FUNCTION asset.staff_lasso_record_copy_count (i_lasso INT, record BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
484 DECLARE
485     ans RECORD;
486     trans INT;
487 BEGIN
488     SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = record;
489
490     FOR ans IN SELECT u.org_unit AS id FROM actor.org_lasso_map AS u WHERE lasso = i_lasso LOOP
491         RETURN QUERY
492         SELECT  -1,
493                 ans.id,
494                 COUNT( cp.id ),
495                 SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
496                 COUNT( cp.id ),
497                 trans
498           FROM
499                 actor.org_unit_descendants(ans.id) d
500                 JOIN asset.copy cp ON (cp.circ_lib = d.id)
501                 JOIN asset.call_number cn ON (cn.record = record AND cn.id = cp.call_number)
502           GROUP BY 1,2,6;
503
504         IF NOT FOUND THEN
505             RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
506         END IF;
507
508     END LOOP;
509
510     RETURN;
511 END;
512 $f$ LANGUAGE PLPGSQL;
513
514 CREATE OR REPLACE FUNCTION asset.record_copy_count ( place INT, record BIGINT, staff BOOL) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
515 BEGIN
516     IF staff IS TRUE THEN
517         IF place > 0 THEN
518             RETURN QUERY SELECT * FROM asset.staff_ou_record_copy_count( place, record );
519         ELSE
520             RETURN QUERY SELECT * FROM asset.staff_lasso_record_copy_count( -place, record );
521         END IF;
522     ELSE
523         IF place > 0 THEN
524             RETURN QUERY SELECT * FROM asset.opac_ou_record_copy_count( place, record );
525         ELSE
526             RETURN QUERY SELECT * FROM asset.opac_lasso_record_copy_count( -place, record );
527         END IF;
528     END IF;
529
530     RETURN;
531 END;
532 $f$ LANGUAGE PLPGSQL;
533
534 CREATE OR REPLACE FUNCTION asset.opac_ou_metarecord_copy_count (org INT, record BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
535 DECLARE
536     ans RECORD;
537     trans INT;
538 BEGIN
539     SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = record;
540
541     FOR ans IN SELECT u.id, t.depth FROM actor.org_unit_ancestors(org) AS u JOIN actor.org_unit_type t ON (u.ou_type = t.id) LOOP
542         RETURN QUERY
543         SELECT  ans.depth,
544                 ans.id,
545                 COUNT( av.id ),
546                 SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
547                 COUNT( av.id ),
548                 trans
549           FROM  
550                 actor.org_unit_descendants(ans.id) d
551                 JOIN asset.opac_visible_copies av ON (av.record = record AND av.circ_lib = d.id)
552                 JOIN asset.copy cp ON (cp.id = av.id)
553                 JOIN metabib.metarecord_source_map m ON (m.source = av.record)
554           GROUP BY 1,2,6;
555
556         IF NOT FOUND THEN
557             RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
558         END IF;
559
560     END LOOP;
561
562     RETURN;
563 END;
564 $f$ LANGUAGE PLPGSQL;
565
566 CREATE OR REPLACE FUNCTION asset.opac_lasso_metarecord_copy_count (i_lasso INT, record BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
567 DECLARE
568     ans RECORD;
569     trans INT;
570 BEGIN
571     SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = record;
572
573     FOR ans IN SELECT u.org_unit AS id FROM actor.org_lasso_map AS u WHERE lasso = i_lasso LOOP
574         RETURN QUERY
575         SELECT  -1,
576                 ans.id,
577                 COUNT( av.id ),
578                 SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
579                 COUNT( av.id ),
580                 trans
581           FROM
582                 actor.org_unit_descendants(ans.id) d
583                 JOIN asset.opac_visible_copies av ON (av.record = record AND av.circ_lib = d.id)
584                 JOIN asset.copy cp ON (cp.id = av.id)
585                 JOIN metabib.metarecord_source_map m ON (m.source = av.record)
586           GROUP BY 1,2,6;
587
588         IF NOT FOUND THEN
589             RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
590         END IF;
591
592     END LOOP;   
593                 
594     RETURN;     
595 END;            
596 $f$ LANGUAGE PLPGSQL;
597
598 CREATE OR REPLACE FUNCTION asset.staff_ou_metarecord_copy_count (org INT, record BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
599 DECLARE         
600     ans RECORD; 
601     trans INT;
602 BEGIN
603     SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = record;
604
605     FOR ans IN SELECT u.id, t.depth FROM actor.org_unit_ancestors(org) AS u JOIN actor.org_unit_type t ON (u.ou_type = t.id) LOOP
606         RETURN QUERY
607         SELECT  ans.depth,
608                 ans.id,
609                 COUNT( cp.id ),
610                 SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
611                 COUNT( cp.id ),
612                 trans
613           FROM
614                 actor.org_unit_descendants(ans.id) d
615                 JOIN asset.copy cp ON (cp.circ_lib = d.id)
616                 JOIN asset.call_number cn ON (cn.record = record AND cn.id = cp.call_number)
617                 JOIN metabib.metarecord_source_map m ON (m.source = cn.record)
618           GROUP BY 1,2,6;
619
620         IF NOT FOUND THEN
621             RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
622         END IF;
623
624     END LOOP;
625
626     RETURN;
627 END;
628 $f$ LANGUAGE PLPGSQL;
629
630 CREATE OR REPLACE FUNCTION asset.staff_lasso_metarecord_copy_count (i_lasso INT, record BIGINT) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
631 DECLARE
632     ans RECORD;
633     trans INT;
634 BEGIN
635     SELECT 1 INTO trans FROM biblio.record_entry b JOIN config.bib_source src ON (b.source = src.id) WHERE src.transcendant AND b.id = record;
636
637     FOR ans IN SELECT u.org_unit AS id FROM actor.org_lasso_map AS u WHERE lasso = i_lasso LOOP
638         RETURN QUERY
639         SELECT  -1,
640                 ans.id,
641                 COUNT( cp.id ),
642                 SUM( CASE WHEN cp.status IN (0,7,12) THEN 1 ELSE 0 END ),
643                 COUNT( cp.id ),
644                 trans
645           FROM
646                 actor.org_unit_descendants(ans.id) d
647                 JOIN asset.copy cp ON (cp.circ_lib = d.id)
648                 JOIN asset.call_number cn ON (cn.record = record AND cn.id = cp.call_number)
649                 JOIN metabib.metarecord_source_map m ON (m.source = cn.record)
650           GROUP BY 1,2,6;
651
652         IF NOT FOUND THEN
653             RETURN QUERY SELECT ans.depth, ans.id, 0::BIGINT, 0::BIGINT, 0::BIGINT, trans;
654         END IF;
655
656     END LOOP;
657
658     RETURN;
659 END;
660 $f$ LANGUAGE PLPGSQL;
661
662 CREATE OR REPLACE FUNCTION asset.metarecord_copy_count ( place INT, record BIGINT, staff BOOL) RETURNS TABLE (depth INT, org_unit INT, visible BIGINT, available BIGINT, unshadow BIGINT, transcendant INT) AS $f$
663 BEGIN
664     IF staff IS TRUE THEN
665         IF place > 0 THEN
666             RETURN QUERY SELECT * FROM asset.staff_ou_metarecord_copy_count( place, record );
667         ELSE
668             RETURN QUERY SELECT * FROM asset.staff_lasso_metarecord_copy_count( -place, record );
669         END IF;
670     ELSE
671         IF place > 0 THEN
672             RETURN QUERY SELECT * FROM asset.opac_ou_metarecord_copy_count( place, record );
673         ELSE
674             RETURN QUERY SELECT * FROM asset.opac_lasso_metarecord_copy_count( -place, record );
675         END IF;
676     END IF;
677
678     RETURN;
679 END;
680 $f$ LANGUAGE PLPGSQL;
681
682 COMMIT;
683