3 DROP SCHEMA IF EXISTS serial CASCADE;
9 CREATE TABLE serial.record_entry (
10 id BIGSERIAL PRIMARY KEY,
11 record BIGINT REFERENCES biblio.record_entry (id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED,
12 owning_lib INT NOT NULL DEFAULT 1 REFERENCES actor.org_unit (id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED,
13 creator INT NOT NULL DEFAULT 1,
14 editor INT NOT NULL DEFAULT 1,
16 create_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
17 edit_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
18 active BOOL NOT NULL DEFAULT TRUE,
19 deleted BOOL NOT NULL DEFAULT FALSE,
21 last_xact_id TEXT NOT NULL
23 CREATE INDEX serial_record_entry_record_idx ON serial.record_entry ( record );
24 CREATE INDEX serial_record_entry_creator_idx ON serial.record_entry ( creator );
25 CREATE INDEX serial_record_entry_editor_idx ON serial.record_entry ( editor );
26 CREATE INDEX serial_record_entry_owning_lib_idx ON serial.record_entry ( owning_lib, deleted );
27 CREATE TRIGGER b_maintain_901 BEFORE INSERT OR UPDATE ON serial.record_entry FOR EACH ROW EXECUTE PROCEDURE evergreen.maintain_901();
28 CREATE TRIGGER c_maintain_control_numbers BEFORE INSERT OR UPDATE ON serial.record_entry FOR EACH ROW EXECUTE PROCEDURE evergreen.maintain_control_numbers();
30 CREATE RULE protect_mfhd_delete AS ON DELETE TO serial.record_entry DO INSTEAD UPDATE serial.record_entry SET deleted = true WHERE old.id = serial.record_entry.id;
32 CREATE TABLE serial.subscription (
33 id SERIAL PRIMARY KEY,
34 owning_lib INT NOT NULL DEFAULT 1 REFERENCES actor.org_unit (id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED,
35 start_date TIMESTAMP WITH TIME ZONE NOT NULL,
36 end_date TIMESTAMP WITH TIME ZONE, -- interpret NULL as current subscription
37 record_entry BIGINT REFERENCES biblio.record_entry (id)
39 DEFERRABLE INITIALLY DEFERRED,
40 expected_date_offset INTERVAL
41 -- acquisitions/business-side tables link to here
43 CREATE INDEX serial_subscription_record_idx ON serial.subscription (record_entry);
44 CREATE INDEX serial_subscription_owner_idx ON serial.subscription (owning_lib);
46 CREATE TABLE serial.subscription_note (
47 id SERIAL PRIMARY KEY,
48 subscription INT NOT NULL
49 REFERENCES serial.subscription (id)
51 DEFERRABLE INITIALLY DEFERRED,
53 REFERENCES actor.usr (id)
54 DEFERRABLE INITIALLY DEFERRED,
55 create_date TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
56 pub BOOL NOT NULL DEFAULT FALSE,
57 alert BOOL NOT NULL DEFAULT FALSE,
61 CREATE INDEX serial_subscription_note_sub_idx ON serial.subscription_note (subscription);
63 CREATE TABLE serial.caption_and_pattern (
64 id SERIAL PRIMARY KEY,
65 subscription INT NOT NULL
66 REFERENCES serial.subscription (id)
68 DEFERRABLE INITIALLY DEFERRED,
70 CONSTRAINT cap_type CHECK ( type in
71 ( 'basic', 'supplement', 'index' )),
72 create_date TIMESTAMPTZ NOT NULL DEFAULT now(),
73 start_date TIMESTAMPTZ NOT NULL DEFAULT now(),
75 active BOOL NOT NULL DEFAULT FALSE,
76 pattern_code TEXT NOT NULL, -- must contain JSON
89 CREATE INDEX serial_caption_and_pattern_sub_idx ON serial.caption_and_pattern (subscription);
91 --at least one distribution per org_unit holding issues
92 CREATE TABLE serial.distribution (
93 id SERIAL PRIMARY KEY,
94 record_entry BIGINT REFERENCES serial.record_entry (id)
96 DEFERRABLE INITIALLY DEFERRED,
97 summary_method TEXT CONSTRAINT sdist_summary_method_check
98 CHECK (summary_method IS NULL
99 OR summary_method IN ( 'add_to_sre',
100 'merge_with_sre', 'use_sre_only',
102 subscription INT NOT NULL
103 REFERENCES serial.subscription (id)
105 DEFERRABLE INITIALLY DEFERRED,
106 holding_lib INT NOT NULL
107 REFERENCES actor.org_unit (id)
108 DEFERRABLE INITIALLY DEFERRED,
110 display_grouping TEXT NOT NULL DEFAULT 'chron'
111 CHECK (display_grouping IN ('enum', 'chron')),
112 receive_call_number BIGINT REFERENCES asset.call_number (id)
113 DEFERRABLE INITIALLY DEFERRED,
114 receive_unit_template INT REFERENCES asset.copy_template (id)
115 DEFERRABLE INITIALLY DEFERRED,
116 bind_call_number BIGINT REFERENCES asset.call_number (id)
117 DEFERRABLE INITIALLY DEFERRED,
118 bind_unit_template INT REFERENCES asset.copy_template (id)
119 DEFERRABLE INITIALLY DEFERRED,
120 unit_label_prefix TEXT,
121 unit_label_suffix TEXT
123 CREATE UNIQUE INDEX one_dist_per_sre_idx ON serial.distribution (record_entry);
124 CREATE INDEX serial_distribution_sub_idx ON serial.distribution (subscription);
125 CREATE INDEX serial_distribution_holding_lib_idx ON serial.distribution (holding_lib);
127 CREATE TABLE serial.distribution_note (
128 id SERIAL PRIMARY KEY,
129 distribution INT NOT NULL
130 REFERENCES serial.distribution (id)
132 DEFERRABLE INITIALLY DEFERRED,
134 REFERENCES actor.usr (id)
135 DEFERRABLE INITIALLY DEFERRED,
136 create_date TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
137 pub BOOL NOT NULL DEFAULT FALSE,
138 alert BOOL NOT NULL DEFAULT FALSE,
142 CREATE INDEX serial_distribution_note_dist_idx ON serial.distribution_note (distribution);
144 CREATE TABLE serial.stream (
145 id SERIAL PRIMARY KEY,
146 distribution INT NOT NULL
147 REFERENCES serial.distribution (id)
149 DEFERRABLE INITIALLY DEFERRED,
152 CREATE INDEX serial_stream_dist_idx ON serial.stream (distribution);
154 CREATE UNIQUE INDEX label_once_per_dist
155 ON serial.stream (distribution, routing_label)
156 WHERE routing_label IS NOT NULL;
158 CREATE TABLE serial.routing_list_user (
159 id SERIAL PRIMARY KEY,
161 REFERENCES serial.stream
163 DEFERRABLE INITIALLY DEFERRED,
164 pos INT NOT NULL DEFAULT 1,
165 reader INT REFERENCES actor.usr
167 DEFERRABLE INITIALLY DEFERRED,
170 CONSTRAINT one_pos_per_routing_list UNIQUE ( stream, pos ),
171 CONSTRAINT reader_or_dept CHECK
173 -- Recipient is a person or a department, but not both
174 (reader IS NOT NULL AND department IS NULL) OR
175 (reader IS NULL AND department IS NOT NULL)
178 CREATE INDEX serial_routing_list_user_stream_idx ON serial.routing_list_user (stream);
179 CREATE INDEX serial_routing_list_user_reader_idx ON serial.routing_list_user (reader);
181 CREATE TABLE serial.issuance (
182 id SERIAL PRIMARY KEY,
184 REFERENCES actor.usr (id)
185 DEFERRABLE INITIALLY DEFERRED,
187 REFERENCES actor.usr (id)
188 DEFERRABLE INITIALLY DEFERRED,
189 create_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
190 edit_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
191 subscription INT NOT NULL
192 REFERENCES serial.subscription (id)
194 DEFERRABLE INITIALLY DEFERRED,
196 date_published TIMESTAMP WITH TIME ZONE,
197 caption_and_pattern INT REFERENCES serial.caption_and_pattern (id)
199 DEFERRABLE INITIALLY DEFERRED,
200 holding_code TEXT CONSTRAINT issuance_holding_code_check CHECK (
201 holding_code IS NULL OR could_be_serial_holding_code(holding_code)
203 holding_type TEXT CONSTRAINT valid_holding_type CHECK
206 OR holding_type IN ('basic','supplement','index')
208 holding_link_id INT -- probably defunct
209 -- TODO: add columns for separate enumeration/chronology values
211 ALTER TABLE serial.issuance ADD CHECK (holding_code IS NULL OR evergreen.is_json(holding_code));
212 CREATE INDEX serial_issuance_sub_idx ON serial.issuance (subscription);
213 CREATE INDEX serial_issuance_caption_and_pattern_idx ON serial.issuance (caption_and_pattern);
214 CREATE INDEX serial_issuance_date_published_idx ON serial.issuance (date_published);
216 CREATE TABLE serial.unit (
218 detailed_contents TEXT NOT NULL,
219 summary_contents TEXT NOT NULL
220 ) INHERITS (asset.copy);
221 ALTER TABLE serial.unit ADD PRIMARY KEY (id);
222 CREATE UNIQUE INDEX unit_barcode_key ON serial.unit (barcode) WHERE deleted = FALSE OR deleted IS FALSE;
223 CREATE INDEX unit_cn_idx ON serial.unit (call_number);
224 CREATE INDEX unit_avail_cn_idx ON serial.unit (call_number);
225 CREATE INDEX unit_creator_idx ON serial.unit ( creator );
226 CREATE INDEX unit_editor_idx ON serial.unit ( editor );
227 CREATE INDEX unit_extant_by_circ_lib_idx ON serial.unit(circ_lib) WHERE deleted = FALSE OR deleted IS FALSE;
229 -- must create this rule explicitly; it is not inherited from asset.copy
230 CREATE RULE protect_serial_unit_delete AS ON DELETE TO serial.unit DO INSTEAD UPDATE serial.unit SET deleted = TRUE WHERE OLD.id = serial.unit.id;
232 -- must create this trigger explicitly; it is not inherited from asset.copy
233 CREATE TRIGGER autogenerate_placeholder_barcode
234 BEFORE INSERT OR UPDATE ON serial.unit
235 FOR EACH ROW EXECUTE PROCEDURE asset.autogenerate_placeholder_barcode()
238 -- must create this trigger explicitly; it is not inherited from asset.copy
239 CREATE TRIGGER sunit_status_changed_trig
240 BEFORE UPDATE ON serial.unit
241 FOR EACH ROW EXECUTE PROCEDURE asset.acp_status_changed();
244 CREATE TRIGGER sunit_created_trig
245 BEFORE INSERT ON serial.unit
246 FOR EACH ROW EXECUTE PROCEDURE asset.acp_created();
248 CREATE TABLE serial.item (
249 id SERIAL PRIMARY KEY,
251 REFERENCES actor.usr (id)
252 DEFERRABLE INITIALLY DEFERRED,
254 REFERENCES actor.usr (id)
255 DEFERRABLE INITIALLY DEFERRED,
256 create_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
257 edit_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
258 issuance INT NOT NULL
259 REFERENCES serial.issuance (id)
261 DEFERRABLE INITIALLY DEFERRED,
263 REFERENCES serial.stream (id)
265 DEFERRABLE INITIALLY DEFERRED,
266 unit INT REFERENCES serial.unit (id)
268 DEFERRABLE INITIALLY DEFERRED,
269 uri INT REFERENCES asset.uri (id)
271 DEFERRABLE INITIALLY DEFERRED,
272 date_expected TIMESTAMP WITH TIME ZONE,
273 date_received TIMESTAMP WITH TIME ZONE,
274 status TEXT CONSTRAINT valid_status CHECK
276 status IN ('Bindery', 'Bound', 'Claimed', 'Discarded', 'Expected', 'Not Held', 'Not Published', 'Received')
277 ) DEFAULT 'Expected',
278 shadowed BOOL NOT NULL DEFAULT FALSE -- ignore when generating summaries/labels
280 CREATE INDEX serial_item_stream_idx ON serial.item (stream);
281 CREATE INDEX serial_item_issuance_idx ON serial.item (issuance);
282 CREATE INDEX serial_item_unit_idx ON serial.item (unit);
283 CREATE INDEX serial_item_uri_idx ON serial.item (uri);
284 CREATE INDEX serial_item_date_received_idx ON serial.item (date_received);
285 CREATE INDEX serial_item_status_idx ON serial.item (status);
287 CREATE TABLE serial.item_note (
288 id SERIAL PRIMARY KEY,
290 REFERENCES serial.item (id)
292 DEFERRABLE INITIALLY DEFERRED,
294 REFERENCES actor.usr (id)
295 DEFERRABLE INITIALLY DEFERRED,
296 create_date TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
297 pub BOOL NOT NULL DEFAULT FALSE,
298 alert BOOL NOT NULL DEFAULT FALSE,
302 CREATE INDEX serial_item_note_item_idx ON serial.item_note (item);
304 CREATE TABLE serial.basic_summary (
305 id SERIAL PRIMARY KEY,
306 distribution INT NOT NULL
307 REFERENCES serial.distribution (id)
309 DEFERRABLE INITIALLY DEFERRED,
310 generated_coverage TEXT NOT NULL,
311 textual_holdings TEXT,
312 show_generated BOOL NOT NULL DEFAULT TRUE
314 CREATE INDEX serial_basic_summary_dist_idx ON serial.basic_summary (distribution);
316 CREATE TABLE serial.supplement_summary (
317 id SERIAL PRIMARY KEY,
318 distribution INT NOT NULL
319 REFERENCES serial.distribution (id)
321 DEFERRABLE INITIALLY DEFERRED,
322 generated_coverage TEXT NOT NULL,
323 textual_holdings TEXT,
324 show_generated BOOL NOT NULL DEFAULT TRUE
326 CREATE INDEX serial_supplement_summary_dist_idx ON serial.supplement_summary (distribution);
328 CREATE TABLE serial.index_summary (
329 id SERIAL PRIMARY KEY,
330 distribution INT NOT NULL
331 REFERENCES serial.distribution (id)
333 DEFERRABLE INITIALLY DEFERRED,
334 generated_coverage TEXT NOT NULL,
335 textual_holdings TEXT,
336 show_generated BOOL NOT NULL DEFAULT TRUE
338 CREATE INDEX serial_index_summary_dist_idx ON serial.index_summary (distribution);
340 CREATE VIEW serial.any_summary AS
342 'basic' AS summary_type, id, distribution,
343 generated_coverage, textual_holdings, show_generated
344 FROM serial.basic_summary
347 'index' AS summary_type, id, distribution,
348 generated_coverage, textual_holdings, show_generated
349 FROM serial.index_summary
352 'supplement' AS summary_type, id, distribution,
353 generated_coverage, textual_holdings, show_generated
354 FROM serial.supplement_summary ;
357 CREATE TABLE serial.materialized_holding_code (
358 id BIGSERIAL PRIMARY KEY,
359 issuance INTEGER NOT NULL REFERENCES serial.issuance (id) ON DELETE CASCADE,
364 CREATE OR REPLACE FUNCTION serial.materialize_holding_code() RETURNS TRIGGER
371 if (not defined $_TD->{new}{holding_code}) {
372 elog(WARNING, 'NULL in "holding_code" column of serial.issuance allowed for now, but may not be useful');
376 # Do nothing if holding_code has not changed...
378 if ($_TD->{new}{holding_code} eq $_TD->{old}{holding_code}) {
379 # ... unless the following internal flag is set.
381 my $flag_rv = spi_exec_query(q{
382 SELECT * FROM config.internal_flag
383 WHERE name = 'serial.rematerialize_on_same_holding_code' AND enabled
385 return unless $flag_rv->{processed};
389 my $holding_code = (new JSON::XS)->decode($_TD->{new}{holding_code});
391 my $field = new MARC::Field('999', @$holding_code); # tag doesnt matter
393 my $dstmt = spi_prepare(
394 'DELETE FROM serial.materialized_holding_code WHERE issuance = $1',
397 spi_exec_prepared($dstmt, $_TD->{new}{id});
399 my $istmt = spi_prepare(
401 INSERT INTO serial.materialized_holding_code (
402 issuance, subfield, value
403 ) VALUES ($1, $2, $3)
407 foreach ($field->subfields) {
418 $func$ LANGUAGE 'plperlu';
420 CREATE INDEX assist_holdings_display
421 ON serial.materialized_holding_code (issuance, subfield);
423 CREATE TRIGGER materialize_holding_code
424 AFTER INSERT OR UPDATE ON serial.issuance
425 FOR EACH ROW EXECUTE PROCEDURE serial.materialize_holding_code() ;
427 CREATE TABLE serial.pattern_template (
428 id SERIAL PRIMARY KEY,
430 pattern_code TEXT NOT NULL,
431 owning_lib INTEGER REFERENCES actor.org_unit(id) DEFERRABLE INITIALLY DEFERRED,
432 share_depth INTEGER NOT NULL DEFAULT 0
434 CREATE INDEX serial_pattern_template_name_idx ON serial.pattern_template (evergreen.lowercase(name));
436 CREATE OR REPLACE FUNCTION serial.pattern_templates_visible_to(org_unit INT) RETURNS SETOF serial.pattern_template AS $func$
438 RETURN QUERY SELECT *
439 FROM serial.pattern_template spt
442 FROM actor.org_unit_descendants(spt.owning_lib, spt.share_depth)
443 ) @@ org_unit::TEXT::QUERY_INT;
445 $func$ LANGUAGE PLPGSQL;