1 Custom Best-Hold Selection
2 ==========================
7 In the Evergreen ILS, during opportunistic capture (which occurs at copy
8 checkin time), the copy being checked in is evaluated by the system for its
9 fitness to fulfill outstanding holds. When the copy might fulfill more than
10 one hold, a set of 'determinants' are used to rank the possible holds that
11 might be fulfilled, so that the best hold may be chosen.
13 Evergreen currently uses one of two possible sets of 'determinants' to rank
14 the holds that a given copy might fulfill. An org-unit setting determines
15 which set of 'determinants' is used.
17 We will call these sets the "best-hold selection sort orders". The best-hold
18 selection sort orders available for use at hold capture time are:
22 . 'pprox' - Proximity of capturing location to pickup library
23 . 'priority' - Group hold priority
24 . 'cut' - Hold cut-in-line
25 . 'depth' - Hold selection depth (deeper/narrower first)
26 . 'rtime' - Hold request time
30 . 'priority' - Group hold priority
31 . 'cut' - Hold cut-in-line
32 . 'rtime' - Hold request time
33 . 'depth' - Hold selection depth (deeper/narrower first)
34 . 'pprox' - Proximity of capturing location to pickup library
36 In either of these scenarios, a case could be made for changing the order of
37 several fields. However, the use of these is currently controlled only by a
38 single org-unit setting to turn on or off FIFO (if FIFO is "off," the
39 Traditional set is used).
41 Adding more org-unit settings to control yet more hard-coded orderings is a
42 path to madness, and therefore we should support custom field ordering for
48 To that end, we propose a new table to define field importance, and a new org-
49 unit setting to replace "FIFO Holds" and select the appropriate definition for
50 the capturing location. The UI for creating or editing hold order definitions
51 should consist of a list for ordering the options, controlled by up-and-down
52 buttons both clickable and accessible by keyboard. There will also be a field
53 for naming the definition and a save button.
55 This org-unit setting will be retrieved at capture time, instead of the FIFO
56 setting, and inspected by open-ils.storage.action.hold_request.nearest_hold.
57 If no value is set, the equivalent of the "traditional" order will be used.
59 An upgrade script will change all FIFO settings to version of the new setting
60 which points to the system-supplied definition that implements FIFO as it
61 stands today, thus avoiding functional changes and configuration problems.
69 The 'config.best_hold_order' database table will have two metadata columns
70 and eight data columns.
72 Each of the eight data columns corresponds to a similarly named column used for
73 ranking in the best-hold selection process (i.e., the 'determinants'). In a
74 given row, the value of each of these columns corresponds to its relative
75 priority in the ranking decision (lowest value representing the highest
78 Data columns with a null value have the effect of omitting the corresponding
79 determinant in the ORDER BY clause for best-hold selection when the given
80 best-hold selector order set is in play.
82 One of the 'determinants', *aprox*, depends on the Calculated Proximity
83 Adjustment enhancement (documented elsewhere).
85 The 'determinant' *rtime*, which in practice is virtually unique among the
86 set of all holds at a site, will always terminate the list of determinants
87 used in constructing the ORDER BY clause whenever it appears. In other words,
88 because *rtime* will never tie anyway, no more comparisons after rtime have
91 The default best-hold order sets sketched here are subject to refinement and
92 are not guaranteed to represent the final product.
95 ------------------------------------------------------------------------------
97 CREATE TABLE config.best_hold_order(
98 id SERIAL PRIMARY KEY, -- (metadata)
99 name TEXT UNIQUE, -- i18n (metadata)
100 pprox INT, -- copy capture <-> pickup lib prox
101 hprox INT, -- copy circ lib <-> request lib prox
102 aprox INT, -- copy circ lib <-> pickup lib ADJUSTED prox on ahcm
103 priority INT, -- group hold priority
104 cut INT, -- cut-in-line
105 depth INT, -- selection depth
106 htime INT, -- time since last home-lib circ exceeds org-unit setting
107 rtime INT -- request time
110 -- At least one of these columns must contain a non-null value
111 ALTER TABLE config.best_hold_order ADD CHECK ((
115 priority IS NOT NULL OR
122 INSERT INTO config.best_hold_order (
124 pprox, aprox, priority, cut, depth, rtime, htime, hprox
127 1, 2, 3, 4, 5, 6, 7, 8
130 INSERT INTO config.best_hold_order (
132 hprox, pprox, aprox, priority, cut, depth, rtime, htime
134 'Traditional with Holds-always-go-to-home-patrons',
135 1, 2, 3, 4, 5, 6, 7, 8
138 INSERT INTO config.best_hold_order (
140 htime, hprox, pprox, aprox, priority, cut, depth, rtime
142 'Traditional with Holds-go-home',
143 1, 2, 3, 4, 5, 6, 7, 8
146 INSERT INTO config.best_hold_order (
148 priority, cut, rtime, depth, pprox, hprox, aprox, htime
151 1, 2, 3, 4, 5, 6, 7, 8
154 INSERT INTO config.best_hold_order (
156 hprox, priority, cut, rtime, depth, pprox, aprox, htime
158 'FIFO with Holds-always-go-to-home-patrons',
159 1, 2, 3, 4, 5, 6, 7, 8
162 INSERT INTO config.best_hold_order (
164 htime, priority, cut, rtime, depth, pprox, aprox, hprox
166 'FIFO with Holds-go-home',
167 1, 2, 3, 4, 5, 6, 7, 8
170 INSERT INTO config.org_unit_setting_type (
171 name, label, description, datatype, fm_class, update_perm
173 'circ.hold_capture_order',
174 'Best-hold selection precedence',
175 'Defines the sort order of holds when selecting a hold to fill using a given copy at capture time',
178 'ADMIN_HOLD_CAPTURE_SORT'
181 INSERT INTO config.org_unit_setting_type (
182 name, label, description, datatype, update_perm
184 'circ.hold_go_home_interval',
185 'Max foreign-circulation time',
186 'Time a copy can spend circulating away from its circ lib before returning there to fill a hold (if one exists there)',
188 'ADMIN_HOLD_CAPTURE_SORT'
191 INSERT INTO actor.org_unit_setting (
192 org_unit, name, value
195 'circ.hold_go_home_interval',
199 UPDATE actor.org_unit_setting SET
200 name = 'circ.hold_capture_order',
201 value = (SELECT id FROM config.hold_capture_sort WHERE name = 'FIFO')
203 name = 'circ.holds_fifo';
204 ------------------------------------------------------------------------------
207 When constructing ORDER BY clauses, the *htime* determinant will be
208 represented by a more complex expression than the other determinants. The
209 likely form of this will be as follows:
212 -----------------------------------------------
214 ['value of org setting circ.hold_go_home_interval'] <
215 NOW() - ['timestamp of last circulation at copy circ lib']
220 -----------------------------------------------
225 The 'open-ils.storage.action.hold_request.nearest_hold' method issues a query
226 with an ORDER BY clause.
228 This clause, previously selected from two hard-coded choices based on a
229 boolean value indicating use- or don't-use-FIFO, will now be
230 dynamically prepared based on the order specified in the
231 'circ.hold_capture_order' org-unit setting.
236 A user interface will allow the creation of new best-hold orders and the
237 editing of existing ones, given sufficient user permission.
239 The name field (metadata) will be editable with a free-form text widget, and
240 the remaining (data) fields will be represented by objects that the user
241 manipulates via clickable buttons (also keyboard accessible) to indicate order.