circ corner case support; container "public" flag
[Evergreen.git] / Open-ILS / src / sql / Pg / 090.schema.action.sql
1 DROP SCHEMA action CASCADE;
2
3 BEGIN;
4
5 CREATE SCHEMA action;
6
7 CREATE TABLE action.in_house_use (
8         id              SERIAL                          PRIMARY KEY,
9         item            BIGINT                          NOT NULL REFERENCES asset.copy (id),
10         staff           INT                             NOT NULL REFERENCES actor.usr (id),
11         org_unit        INT                             NOT NULL REFERENCES actor.org_unit (id),
12         use_time        TIMESTAMP WITH TIME ZONE        NOT NULL DEFAULT NOW()
13 );
14
15 CREATE TABLE action.non_cataloged_circulation (
16         id              SERIAL                          PRIMARY KEY,
17         patron          INT                             NOT NULL REFERENCES actor.usr (id),
18         staff           INT                             NOT NULL REFERENCES actor.usr (id),
19         circ_lib        INT                             NOT NULL REFERENCES actor.org_unit (id),
20         item_type       INT                             NOT NULL REFERENCES config.non_cataloged_type (id),
21         circ_time       TIMESTAMP WITH TIME ZONE        NOT NULL DEFAULT NOW()
22 );
23
24 CREATE TABLE action.survey (
25         id              SERIAL  PRIMARY KEY,
26         owner           INT     NOT NULL REFERENCES actor.org_unit (id),
27         start_date      DATE    NOT NULL DEFAULT NOW(),
28         end_date        DATE    NOT NULL DEFAULT NOW() + '10 years'::INTERVAL,
29         usr_summary     BOOL    NOT NULL DEFAULT FALSE,
30         opac            BOOL    NOT NULL DEFAULT FALSE,
31         poll            BOOL    NOT NULL DEFAULT FALSE,
32         required        BOOL    NOT NULL DEFAULT FALSE,
33         name            TEXT    NOT NULL,
34         description     TEXT    NOT NULL
35 );
36 CREATE UNIQUE INDEX asv_once_per_owner_idx ON action.survey (owner,name);
37
38 CREATE TABLE action.survey_question (
39         id              SERIAL  PRIMARY KEY,
40         survey          INT     NOT NULL REFERENCES action.survey,
41         question        TEXT    NOT NULL
42 );
43
44 CREATE TABLE action.survey_answer (
45         id              SERIAL  PRIMARY KEY,
46         question        INT     NOT NULL REFERENCES action.survey_question,
47         answer          TEXT    NOT NULL
48 );
49
50 CREATE SEQUENCE action.survey_response_group_id_seq;
51
52 CREATE TABLE action.survey_response (
53         id                      BIGSERIAL                       PRIMARY KEY,
54         response_group_id       INT,
55         usr                     INT, -- REFERENCES actor.usr
56         survey                  INT                             NOT NULL REFERENCES action.survey,
57         question                INT                             NOT NULL REFERENCES action.survey_question,
58         answer                  INT                             NOT NULL REFERENCES action.survey_answer,
59         answer_date             TIMESTAMP WITH TIME ZONE,
60         effective_date          TIMESTAMP WITH TIME ZONE        NOT NULL DEFAULT NOW()
61 );
62 CREATE OR REPLACE FUNCTION action.survey_response_answer_date_fixup () RETURNS TRIGGER AS '
63 BEGIN
64         NEW.answer_date := NOW();
65         RETURN NEW;
66 END;
67 ' LANGUAGE 'plpgsql';
68 CREATE TRIGGER action_survey_response_answer_date_fixup_tgr
69         BEFORE INSERT ON action.survey_response
70         FOR EACH ROW
71         EXECUTE PROCEDURE action.survey_response_answer_date_fixup ();
72
73
74 CREATE TABLE action.circulation (
75         target_copy             BIGINT                          NOT NULL, -- asset.copy.id
76         circ_lib                INT                             NOT NULL, -- actor.org_unit.id
77         circ_staff              INT                             NOT NULL, -- actor.usr.id
78         checkin_staff           INT,                                      -- actor.usr.id
79         checkin_lib             INT,                                      -- actor.org_unit.id
80         renewal_remaining       INT                             NOT NULL, -- derived from "circ duration" rule
81         due_date                TIMESTAMP WITH TIME ZONE        NOT NULL,
82         stop_fines_time         TIMESTAMP WITH TIME ZONE,
83         checkin_time            TIMESTAMP WITH TIME ZONE,
84         duration                INTERVAL                        NOT NULL, -- derived from "circ duration" rule
85         fine_interval           INTERVAL                        NOT NULL DEFAULT '1 day'::INTERVAL, -- derived from "circ fine" rule
86         recuring_fine           NUMERIC(6,2)                    NOT NULL, -- derived from "circ fine" rule
87         max_fine                NUMERIC(6,2)                    NOT NULL, -- derived from "max fine" rule
88         phone_renewal           BOOL                            NOT NULL DEFAULT FALSE,
89         desk_renewal            BOOL                            NOT NULL DEFAULT FALSE,
90         opac_renewal            BOOL                            NOT NULL DEFAULT FALSE,
91         duration_rule           TEXT                            NOT NULL, -- name of "circ duration" rule
92         recuring_fine_rule      TEXT                            NOT NULL, -- name of "circ fine" rule
93         max_fine_rule           TEXT                            NOT NULL, -- name of "max fine" rule
94         stop_fines              TEXT                            CHECK (stop_fines IN ('CHECKIN','CLAIMSRETURNED','LOST','MAXFINES','RENEW','LONGOVERDUE'))
95 ) INHERITS (money.billable_xact);
96 CREATE INDEX circ_open_xacts_idx ON action.circulation (usr) WHERE xact_finish IS NULL;
97
98 CREATE OR REPLACE VIEW action.open_circulation AS
99         SELECT  *
100           FROM  action.circulation
101           WHERE checkin_time IS NULL
102           ORDER BY due_date;
103                 
104
105 CREATE OR REPLACE VIEW action.billable_cirulations AS
106         SELECT  *
107           FROM  action.circulation
108           WHERE xact_finish IS NULL;
109
110 CREATE VIEW stats.fleshed_circulation AS
111         SELECT  c.*,
112                 CAST(c.xact_start AS DATE) AS start_date_day,
113                 CAST(c.xact_finish AS DATE) AS finish_date_day,
114                 DATE_TRUNC('hour', c.xact_start) AS start_date_hour,
115                 DATE_TRUNC('hour', c.xact_finish) AS finish_date_hour,
116                 cp.call_number_label,
117                 cp.owning_lib,
118                 cp.item_lang,
119                 cp.item_type,
120                 cp.item_form
121         FROM    "action".circulation c
122                 JOIN stats.fleshed_copy cp ON (cp.id = c.target_copy);
123
124
125 CREATE OR REPLACE FUNCTION action.circulation_claims_returned () RETURNS TRIGGER AS $$
126 BEGIN
127         IF OLD.stop_fines IS NULL OR OLD.stop_fines <> NEW.stop_fines THEN
128                 IF NEW.stop_fines = 'CLAIMSRETURNED' THEN
129                         UPDATE actor.usr SET claims_returned_count = claims_returned_count + 1 WHERE id = NEW.usr;
130                 END IF;
131                 IF NEW.stop_fines = 'LOST' THEN
132                         UPDATE asset.copy SET status = 3 WHERE id = NEW.target_copy;
133                 END IF;
134         END IF;
135         RETURN NEW;
136 END;
137 $$ LANGUAGE 'plpgsql';
138 CREATE TRIGGER action_circulation_stop_fines_tgr
139         BEFORE UPDATE ON action.circulation
140         FOR EACH ROW
141         EXECUTE PROCEDURE action.circulation_claims_returned ();
142
143
144 CREATE TABLE action.hold_request (
145         id                      SERIAL                          PRIMARY KEY,
146         request_time            TIMESTAMP WITH TIME ZONE        NOT NULL DEFAULT NOW(),
147         capture_time            TIMESTAMP WITH TIME ZONE,
148         fulfillment_time        TIMESTAMP WITH TIME ZONE,
149         checkin_time            TIMESTAMP WITH TIME ZONE,
150         return_time             TIMESTAMP WITH TIME ZONE,
151         prev_check_time         TIMESTAMP WITH TIME ZONE,
152         expire_time             TIMESTAMP WITH TIME ZONE,
153         target                  BIGINT                          NOT NULL, -- see hold_type
154         current_copy            BIGINT                          REFERENCES asset.copy (id) ON DELETE SET NULL,
155         fulfillment_staff       INT                             REFERENCES actor.usr (id),
156         fulfillment_lib         INT                             REFERENCES actor.org_unit (id),
157         request_lib             INT                             NOT NULL REFERENCES actor.org_unit (id),
158         requestor               INT                             NOT NULL REFERENCES actor.usr (id),
159         usr                     INT                             NOT NULL REFERENCES actor.usr (id),
160         selection_depth         INT                             NOT NULL DEFAULT 0,
161         pickup_lib              INT                             NOT NULL REFERENCES actor.org_unit,
162         hold_type               "char"                          NOT NULL CHECK (hold_type IN ('M','T','V','C')),
163         holdable_formats        TEXT,
164         phone_notify            TEXT,
165         email_notify            TEXT
166 );
167
168
169 CREATE TABLE action.hold_notification (
170         id              SERIAL                          PRIMARY KEY,
171         hold            INT                             NOT NULL REFERENCES action.hold_request (id),
172         notify_time     TIMESTAMP WITH TIME ZONE        NOT NULL DEFAULT NOW(),
173         method          TEXT                            NOT NULL, -- eh...
174         note            TEXT
175 );
176
177 CREATE TABLE action.hold_copy_map (
178         id              SERIAL  PRIMARY KEY,
179         hold            INT     NOT NULL REFERENCES action.hold_request (id) ON DELETE CASCADE,
180         target_copy     BIGINT  NOT NULL REFERENCES asset.copy (id) ON DELETE CASCADE,
181         CONSTRAINT copy_once_per_hold UNIQUE (hold,target_copy)
182 );
183
184 CREATE TABLE action.transit_copy (
185         id                      SERIAL                          PRIMARY KEY,
186         source_send_time        TIMESTAMP WITH TIME ZONE,
187         dest_recv_time          TIMESTAMP WITH TIME ZONE,
188         target_copy             BIGINT                          NOT NULL REFERENCES asset.copy (id) ON DELETE CASCADE,
189         source                  INT                             NOT NULL REFERENCES actor.org_unit (id),
190         dest                    INT                             NOT NULL REFERENCES actor.org_unit (id),
191         prev_hop                INT                             REFERENCES action.transit_copy (id),
192         copy_status             INT                             NOT NULL REFERENCES config.copy_status (id),
193         persistant_transfer     BOOL                            NOT NULL DEFAULT FALSE
194 );
195
196 CREATE TABLE action.hold_transit_copy (
197         hold    INT     REFERENCES action.hold_request (id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED
198 ) INHERITS (action.transit_copy);
199
200 CREATE TABLE action.unfulfilled_hold_list (
201         id              BIGSERIAL                       PRIMARY KEY,
202         current_copy    BIGINT                          NOT NULL,
203         hold            INT                             NOT NULL,
204         circ_lib        INT                             NOT NULL,
205         fail_time       TIMESTAMP WITH TIME ZONE        NOT NULL DEFAULT NOW()
206 );
207
208 COMMIT;
209