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 owning_lib_to_home_lib_prox INT, -- copy owning lib <-> user home lib prox
103 aprox INT, -- copy circ lib <-> pickup lib ADJUSTED prox on ahcm
104 priority INT, -- group hold priority
105 cut INT, -- cut-in-line
106 depth INT, -- selection depth
107 htime INT, -- time since last home-lib circ exceeds org-unit setting
108 rtime INT -- request time
111 -- At least one of these columns must contain a non-null value
112 ALTER TABLE config.best_hold_order ADD CHECK ((
115 owning_lib_to_home_lib_prox IS NOT NULL OR
117 priority IS NOT NULL OR
124 INSERT INTO config.best_hold_order (
126 pprox, aprox, priority, cut, depth, rtime, htime, hprox
129 1, 2, 3, 4, 5, 6, 7, 8
132 INSERT INTO config.best_hold_order (
134 hprox, pprox, aprox, priority, cut, depth, rtime, htime
136 'Traditional with Holds-always-go-to-home-patrons',
137 1, 2, 3, 4, 5, 6, 7, 8
140 INSERT INTO config.best_hold_order (
142 htime, hprox, pprox, aprox, priority, cut, depth, rtime
144 'Traditional with Holds-go-home',
145 1, 2, 3, 4, 5, 6, 7, 8
148 INSERT INTO config.best_hold_order (
150 priority, cut, rtime, depth, pprox, hprox, aprox, htime
153 1, 2, 3, 4, 5, 6, 7, 8
156 INSERT INTO config.best_hold_order (
158 hprox, priority, cut, rtime, depth, pprox, aprox, htime
160 'FIFO with Holds-always-go-to-home-patrons',
161 1, 2, 3, 4, 5, 6, 7, 8
164 INSERT INTO config.best_hold_order (
166 htime, priority, cut, rtime, depth, pprox, aprox, hprox
168 'FIFO with Holds-go-home',
169 1, 2, 3, 4, 5, 6, 7, 8
172 INSERT INTO config.best_hold_order (
174 owning_lib_to_home_lib_prox, hprox, approx, pprox, aprox, priority, cut, depth, rtime
176 'Traditional with Holds-chase-home-lib-patrons',
177 1, 2, 3, 4, 5, 6, 7, 8, 9
180 INSERT INTO config.org_unit_setting_type (
181 name, label, description, datatype, fm_class, update_perm
183 'circ.hold_capture_order',
184 'Best-hold selection precedence',
185 'Defines the sort order of holds when selecting a hold to fill using a given copy at capture time',
188 'ADMIN_HOLD_CAPTURE_SORT'
191 INSERT INTO config.org_unit_setting_type (
192 name, label, description, datatype, update_perm
194 'circ.hold_go_home_interval',
195 'Max foreign-circulation time',
196 'Time a copy can spend circulating away from its circ lib before returning there to fill a hold (if one exists there)',
198 'ADMIN_HOLD_CAPTURE_SORT'
201 INSERT INTO actor.org_unit_setting (
202 org_unit, name, value
205 'circ.hold_go_home_interval',
209 UPDATE actor.org_unit_setting SET
210 name = 'circ.hold_capture_order',
211 value = (SELECT id FROM config.hold_capture_sort WHERE name = 'FIFO')
213 name = 'circ.holds_fifo';
214 ------------------------------------------------------------------------------
217 When constructing ORDER BY clauses, the *htime* determinant will be
218 represented by a more complex expression than the other determinants. The
219 likely form of this will be as follows:
222 -----------------------------------------------
224 ['value of org setting circ.hold_go_home_interval'] <
225 NOW() - ['timestamp of last circulation at copy circ lib']
230 -----------------------------------------------
235 The 'open-ils.storage.action.hold_request.nearest_hold' method issues a query
236 with an ORDER BY clause.
238 This clause, previously selected from two hard-coded choices based on a
239 boolean value indicating use- or don't-use-FIFO, will now be
240 dynamically prepared based on the order specified in the
241 'circ.hold_capture_order' org-unit setting.
246 A user interface will allow the creation of new best-hold orders and the
247 editing of existing ones, given sufficient user permission.
249 The name field (metadata) will be editable with a free-form text widget, and
250 the remaining (data) fields will be represented by objects that the user
251 manipulates via clickable buttons (also keyboard accessible) to indicate order.