Part 2: Advanced topics in the in-database approach for the configuration of circulation and hold policies. This talk picks up where Part 1 ends and provides greater detail on the database interactions with copy locations, copy flags, matchpoints, and rules, including fall-thru. Tips for using SQL to directly configure new matchpoints will also be discussed.
The focus of this presentation is on the features available in Evergreen 2.2, the upcoming release. In some cases, notably those of circulation limits, we will discuss the differences between Evergreen 2.0/2.1 and what is available in Evergreen 2.2 as significant changes have been made in that area.
We begin with a run-through of the database tables involved in circulation and holds.
Main Tables
The tables config.circ_matrix_matchpoint and config.hold_matrix_matchpoint are central to the configuration of in-database parameters. They collect the main set of data used to determine what rules apply to any given circulation or hold repsectively. It is useful for us to think of their columns in terms of “match” columns, those that are used to match the particulars of a given circulation or hold transaction, and “result” columns, those that return the various parameters that are applied to the matching transaction.
config.circ_matrix_matchpoint
-
“match” columns
-
org_unit
-
integer: ID of the actor.org_unit where the circulation takes place
-
-
grp
-
integer: ID of the user group to which the matchpoint applies.
-
-
circ_modifier
-
text: circulation modifier code (if any) to which the matchpoint applies
-
-
marc_type
-
text: marc_type from the bib record
-
-
marc_form
-
text: marc_form from the bib record
-
-
marc_bib_level
-
text: bib_level from the bib record
-
-
marc_vr_format
-
text: video recording format from the bib record
-
-
copy_circ_lib
-
integer: circ_lib from the asset.copy
-
-
copy_owning_lib
-
integer: owning_lib from the asset.call_number
-
-
user_home_ou
-
integer: home_ou from actor.usr
-
-
ref_flag
-
boolean: if the matchpoint applies to reference copies
-
-
juvenile_flag
-
boolean: if the matchpoint applies to juvenile patrons
-
-
is_renewal
-
boolean: if the matchpoint applies to renewals
-
-
usr_age_lower_bound
-
interval: lower bound of ages of patrons to which the matchpoint applies
-
-
usr_age_upper_bound
-
interval: upper bound of ages of patrons to which the matchpoint applies
-
-
-
“result” columns
-
circulate
-
boolean: whether or not the copy will circulate, a false means the checkout is denied
-
-
duration_rule
-
integer: ID of the duration rule to apply
-
-
recurring_fine_rule
-
integer: ID of the recurring fine rule to apply
-
-
max_fine_rule
-
integer: the maximum fine rule to apply
-
-
renewals
-
integer: number of renewals allowed, overrides renewals from duration rule
-
-
grace_period
-
interval: number of days of grace when copy is returned late, overrides grace period in the recurring fine rule
-
-
config.hold_matrix_matchpoint
-
“match” columns
-
strict_ou_match
-
boolean: if matches on organizational units are “strict” or not
-
-
user_home_ou
-
integer: home_ou from actor.usr
-
-
request_ou
-
integer: organizational unit where the request is placed
-
-
pickup_ou
-
integer: organizational unit where the hold will be picked up
-
-
item_owning_ou
-
integer: owning_lib from asset.call_number
-
-
item_circ_ou
-
integer: circ_lib from asset.copy
-
-
usr_grp
-
integer: group of the user for whom the request is placed
-
-
requestor_grp
-
integer: group of the user placing the request
-
-
circ_modifier
-
text: code of the circulation modifier (if any)
-
-
marc_type
-
text: MARC item type from the bib record
-
-
marc_form
-
text: MARC form from the bib record
-
-
marc_bib_level
-
text: MARC bib level from the bib record
-
-
marc_vr_format
-
text: video recording format from the bib record
-
-
juvenile_flag
-
boolean: if the matchpoint applies to juvenile patrons or not
-
-
ref_flag
-
boolean: if the matchpoint applies to reference copies or not
-
-
item_age
-
interval: the age of items to which the matchpoint applies
-
-
-
“result” columns
-
holdable
-
boolean: if the matchpoint allows a hold
-
-
distance_is_from_owner
-
boolean: whether or not transit range is from the owner of the copy
-
-
transit_range
-
integer: distance in the organizational tree which matches are allowed to travel
-
-
max_holds
-
integer: maximum number of holds the patron is allowed to have
-
-
include_frozen_holds
-
boolean: whether or not to include frozen or suspended holds in that count
-
-
stop_blocked_user
-
boolean: stop a user who is blocked from circulation from placing holds
-
-
Weighting of Matchpoints
-
NEW! as of 2.1
-
Allows you to specify the “weight” of each “match” column
-
The weight can vary by organizational unit
Higher numbers imply a higher weight, so columns with a higher value in their weights table will have precedence over columns with a lower value. This is a useful way to break ties, if all other considerations between two potential matchpoints are equal.
Weighting Tables
-
config.circ_matrix_weights
-
name
-
text: name of the weighting “rule”
-
-
org_unit
-
numeric: weight for the org_unit column
-
-
grp
-
numeric: weight for the grp column
-
-
circ_modifier
-
numeric: weight for the circ_modifier column
-
-
marc_type
-
numeric: weight for the marc_type column
-
-
marc_form
-
numeric: weight for the marc_form column
-
-
marc_bib_level
-
numeric: weight for the marc_bib_level column
-
-
marc_vr_format
-
numeric: weight for the marc_vr_format column
-
-
copy_circ_lib
-
numeric: weight for the copy_circ_lib column
-
-
copy_owning_lib
-
numeric: weight for the copy_owning_lib column
-
-
user_home_ou
-
numeric: weight for the user_home_ou column
-
-
ref_flag
-
numeric: weight for the ref_flag column
-
-
juvenile_flag
-
numeric: weight for the juvenile_flag column
-
-
is_renewal
-
numeric: weight for the is_renewal column
-
-
usr_age_lower_bound
-
numeric: weight for the usr_age_lower_bound column
-
-
usr_age_upper_bound
-
numeric: weight for the usr_age_upper_bound column
-
-
item_age
-
numeric: weight for the item_age column
-
-
-
config.hold_matrix_weights
-
name
-
text: a name for the weight association
-
-
user_home_ou
-
numeric: weight for the user_home_ou column
-
-
request_ou
-
numeric: weight for the request_ou column
-
-
pickup_ou
-
numeric: weight for the pickup_ou column
-
-
item_owning_ou
-
numeric: weight for the item_owning_ou column
-
-
item_circ_ou
-
numeric: weight for the item_circ_ou column
-
-
usr_grp
-
numeric: weight for the usr_grp column
-
-
requestor_grp
-
numeric: weight for the requestor_grp column
-
-
circ_modifier
-
numeric: weight for the circ_modifier column
-
-
marc_type
-
numeric: weight for the marc_type column
-
-
marc_form
-
numeric: weight for the marc_form column
-
-
marc_bib_level
-
numeric: weight for the marc_bib_level column
-
-
marc_vr_format
-
numeric: weight for the marc_vr_format column
-
-
juvenile_flag
-
numeric: weight for the juvenile_flag column
-
-
ref_flag
-
numeric: weight for the ref_flag column
-
-
item_age
-
numeric: weight for the item_age column
-
-
-
config.weight_assoc
-
active
-
boolean: whether or not the association is active
-
-
org_unit
-
integer: the organizational unit where the weighting applies
-
-
circ_weights
-
integer: the entry from config.circ_matrix_weights to use
-
-
hold_weights
-
integer: the entry from config.hold_matrix_weights to use
-
-
For circ_weights the org_unit in the weight_assoc table corresponds to the org_unit column in config.circ_matrix_matchpoint.
For hold weights, the org_unit corresponds to either the copy’s circ_lib or the call number’s owning_lib depending on the setting of the circ.holds.weight_owner_not_circ internal flag. If that flag is enabled, the call number owning_lib is used.
There is an interface in the gui for editing these, but it is broken as of this writing (20120419). There is a bug report with a potential fix available.
GUI
The GUIs can be found in the staff client on the Server Administration submenu of the Admin menu. The specific menu options are:
-
Circulation Matchpoint Weights
-
Hold Matchpoint Weights
-
Weight Associations
fallthrough
-
NEW! as of 2.1
-
Works on result fields
-
Any otherwise matching matchpoint is eligible
fallthrough example
Let’s say that the consortium has decided on a 21_day_2_renew loan rule for general materials, i.e. books, etc. Most members do not charge overdue fines. System 1 charges 25 cents per day to a maximum of $3.00, but otherwise uses the default circulation duration. This situation might look like this:
org_unit | duration_rule | recurring_fine_rule | max_fine_rule |
---|---|---|---|
CONS |
21_day_2_renew |
NONE |
NONE |
SYS1 |
NULL |
25_cents |
3_dollars |
Fall through is rather hard to explain, but it is a rather simple concept once you grasp it. It works a lot like cascading style sheets.
It is perhaps easiest to think of fall through as working the org unit level. Let’s assume that we have constructed a set of circulation matchpoints that apply at the consortium. We could consider these matchpoints as representing default circulation rules for our consortium. Let us also assume that our consortium has decided on some common policies regarding loan periods and number of renewals for most materials but that we don’t have uniformity on overdue fines for various political reasons. If most of our members actually don’t charge fines, then it makes sense to set up a matchpoint for regular books at the consortium org unit that has all of the basic parameters and an empty recurring fine rule. If one of our members uses all of the basic parameters for book circulation, but charges 25 cents a day to a maximum of $3.00 for fines, then fall through allows us to configure only those two field for that library’s book matchpoint. The rest of the rules will fall through to the consortium’s matchpoint.
Fall through works similarly for branches and systems as well. If all members of a system use the same circulation rules, then you need only configure the rules at the system level. If, however, 1 branch needs something special for some reason, you can configure only those fields that differ from the system or consortium for that one branch.
Rules Tables
-
config.rule_circ_duration
-
name
-
text: name of the rule, typically use something like “7_day_2_renew”
-
-
extended
-
interval: length of the extended loan period (3 in asset.copy.loan_duration)
-
-
normal
-
interval: length of the normal loan period (2 in asset.copy.loan_duration)
-
-
shrt
-
interval: length of the short loan period (1 in asset.copy.loan_duration)
-
-
max_renewals
-
integer: maximum number of times a circulation can be renewed
-
-
-
config.rule_recurring_fine
-
name
-
text: name of the rule
-
-
high
-
numeric: amount of the high fine level (3 in asset.copy.fine_level)
-
-
normal
-
numeric: amount of the normal fine level (2 in asset.copy.fine_level)
-
-
low
-
numeric: amount of the low fine level (1 in asset.copy.fine_level)
-
-
recurrence_interval
-
interval: how often the fine charge recurs
-
-
grace_period
-
interval: how long to wait after something is due before fines accumulate
-
-
-
config.rule_max_fine
-
name
-
text: name of the maximum fine rule
-
-
amount
-
numeric: the amount of maximum fine
-
-
is_percent
-
boolean: whether or not the amount is to be considered a percentage of the material’s price
-
-
-
config.rule_age_hold_protect
-
name
-
text: name for the rule
-
-
age
-
interval: how long to protect copies with this rule
-
-
prox
-
integer: distance in the organizational tree where the protection starts
-
-
The default rules for recurring fines and circulation durations that ship with Evergreen have different values for the 3 “levels.” For instance, the intervals for circulation duration are 7 days, 14 days and 21 days respectively. Our members' staff seemed to find this idea confusing, so we created additional rules to cover our particular use cases where all three values were the same. If you look at the pre-existing rules in the editor, you’ll see that the first 10 entries follow this pattern and the “default” entry is the only one with 3 different values. I suggest making all three values the same for your circulation duration rules as well as your recurring fine rules. This helps avoid confusion with library cataloging and circulation staff.
Age hold protection has caused (and continues to cause) some confusion in our consortium. Part of the blame with that lies in the fact that its operation was explained to us at it functions when using scripted circulation parameters and not how it works with in database rules. With in-database rules, only the age hold protection rule applied to the copy (or in the future, the matchpoint applies). This means that if you set a 3-month age hold protection at the system level on a copy, then the copy will only have age hold protection at the system leve for those three months. There is no cascade effect with age hold protection when using the in-database circulation.
Other Tables
-
asset.copy_location
-
holdable
-
boolean: if copies from that location can be held
-
-
circulate
-
boolean: if copies from that location can circulate
-
-
-
asset.copy
-
circ_lib
-
integer: ID of the actor.org_unit that owns the copy
-
-
create_date
-
timestamp: date the copy was created in the database
-
-
status
-
integer: ID of the copy’s status
-
-
location
-
integer: ID of the copy’s location
-
-
loan_duration
-
integer: 1, 2, or 3, for short, normal or extended loan period
-
-
fine_level
-
integer: 1, 2, or 3, for low, normal, or high fine level
-
-
age_protect
-
integer: ID of the age protection rule to use
-
-
circulate
-
boolean: if this copy can circulate or not
-
-
ref
-
boolean: if the copy is reference or not
-
-
holdable
-
boolean: if the copy can be held or not
-
-
circ_modifier
-
text: code for the circulation modifier, if any
-
-
circ_as_type
-
text: MARC type to use instead of the type from bibliographic record
-
-
active_date
-
timestamp: date that the copy became active
-
-
-
config.copy_status
-
holdable
-
boolean: if copies with this status are holdable
-
-
copy_active
-
boolean: if copies with this status can circulate
-
-
-
config.circ_modifier
-
code
-
text: identifier for the circ_modifier
-
-
Limits
-
The “old” way (2.0/2.1)
-
circ modifier only
-
-
The “new” way (2.2+)
-
Not limited to circ modifiers
-
Associated with matchpoints
-
The “old” way
-
config.circ_matrix_mod_test
-
matchpoint
-
integer: ID of the circ_matrix_matchpoint to which the limit applies
-
-
items_out
-
integer: number of items out
-
-
-
config.circ_matrix_mod_test_map
-
circ_mod_test
-
integer: ID of the circ_matrix_mod_test
-
-
circ_mod
-
text: circ modifier code
-
-
The “old” way is fairly simple. It requires that you base all of your circulation limits on circulation modifiers, so you’re encouraged by this method to use circulation modifiers as “circulation types.”
You can add multiple circ_matrix_mod_test_map entries with different circ_mod values and the total of the copies with those circ_mod values will be counted. Thus, if you were using circulation modifiers to track different types of DVDs (DVD, HOTDVD, RENTALDVD, for instance), you could have a limit of 10 DVDs that included the counts from all three types, and two separate limits that allow say 3 RENTALDVD and 1 HOTDVD.
The “new” way
-
config.circ_limit_group
-
name
-
text: name for the group
-
-
description
-
text: description for the group
-
-
-
config.circ_limit_set
-
name
-
text: name for the set
-
-
owning_lib
-
integer: organizational unit that owns the set
-
-
depth
-
integer: depth at which the limit set applies
-
-
items_out
-
integer: number of items circulated to a patron at the same time
-
-
global
-
boolean: whether or not the limit set applies to all organizational units below the depth or only to direct descendants of the circulation library
-
-
description
-
text: a description for the limit set
-
-
-
config.circ_limit_set_group_map
-
limit_set
-
integer: id from config.circ_limit_set
-
-
limit_group
-
integer: id from config.circ_limit_group
-
-
check_only
-
boolean: count but not tag circulations
-
-
-
config.circ_limit_set_circ_mod_map
-
limit_set
-
integer: id of the limit set
-
-
circ_mod
-
text: code of the circulation modifier
-
-
-
config.circ_matrix_limit_set_map
-
matchpoint
-
integer: id of the matchpoint
-
-
limit_set
-
integer: id of the limit set
-
-
fallthrough
-
boolean: whether or not fallthrough applies to the limit set
-
-
The new way still can do everything that the old way does. In fact, the upgrade script for 2.1 to 2.2 will convert your circ_matrix_mod_test_map entries to the new way of doing things.
This new method of configuring limits offers much more flexibility over the old way. You can now configure limits without requiring a circulation modifier to set the the limits. You can enable fallthrough on the limits so that the limit will apply to any matching circulation. You can set organizational unit depths at which the limits apply, so it is easier to set up limits that apply consortium-wide or at just a single system or branch. If your limit set does not require a circulation modifier it is also possible to set a tag only rule so that circulations are tagged for future use. (This is, in fact, the recommendation of the developer who added the new way of handling limits.)
Penalties
-
permission.grp_penalty_threshold
-
grp
-
integer: id of the group to which the penalty applies
-
-
org_unit
-
integer: organizational unit where the penalty applies
-
-
penalty
-
integer: id of the penalty
-
-
threshold
-
numeric: the threshold
-
-
SQL Helper Functions
-
config.create_circ_matrix_matchpoint
-
config.create_hold_matrix_matchpoint
-
permission.create_grp_penalty_threshold
-
available online: http://git.mvlcstaff.org/?p=jason/helperfuncs.git;a=summary
-
git clone git://git.mvlcstaff.org/jason/helperfuncs.git
-
Click the “snapshot” link by the top entry under the “shortlog” list.
-
-
Install with psql:
-
psql -f config.create_circ_matrix_matchpoint.sql
-
psql -f config.create_hold_matrix_machtpoint.sql
-
psql -f permission.create_grp_penalty_threshold.sql
-
And so on, if any new ones get added later.
-
Helper functions make creating certain complicated rules easier. Typically, you’d write them such that they provide default arguments for most parameters, and so you can use shortnames or names instead of database ids.
Using Helper functions
-
To create a circ_matrix_matchpoint:
SELECT config.create_circ_matrix_matchpoint ( org := 'SYS1', grp := 'Users', circ_modifer := 'BESTSELLER', duration_rule := '7_day_0_renew', recurring_fine_rule := '1_dollar_per_day', max_fine_rule := '5_dollars' )
-
To create a hold_matrix_matchpoint
SELECT config.create_circ_matrix_matchpoint ( item_circ_ou := 'SYS1', usr_grp := 'Users', circ_modifer := 'BESTSELLER', holdable := FALSE )
-
To create a grp_penalty_threshold
SELECT permission.create_grp_penalty_threshold ( grp := 'Users', org := 'SYS1', penalty := 'PATRON_EXCEEDS_FINES', threshold := 10.00 )
Creating Limits with SQL
-
The old way (2.0/2.1)
-
The new way (2.2 and beyond)
The “old” way
BEGIN; INSERT INTO config.circ_matrix_circ_mod_test (matchpoint, items_out) SELECT id, 1 FROM config.circ_matrix_matchpoint WHERE org_unit = (SELECT id FROM actor.org_unit WHERE shortname = 'SYS1') AND circ_modifier = 'BESTSELLER'; INSERT INTO config.circ_matrix_circ_mod_test_map (circ_mod_test, circ_mod) SELECT ccmcmt.id, 'BESTSELLER' FROM config.circ_matrix_circ_mod_test ccmcmt join config.circ_matrix_matchpoint ccmm on ccmcmt.matchpoint = ccmm.id WHERE ccmm.org_unit = (SELECT id FROM actor.org_unit WHERE shortname = 'SYS1') AND ccmm.circ_modifier = 'BESTSELLER'; COMMIT;
The “new” way
BEGIN; INSERT INTO config.circ_limit_group (name, description) VALUES ('BESTSELLER', 'Limit on BESTSELLER'); INSERT INTO config.circ_limit_set (name, owning_lib, items_out, depth, global, description) VALUES ('One BESTSELLER Limit', 1, 1, 1, TRUE, 'Limit to 1 BESTSELLER at system'); INSERT INTO config.circ_limit_set_group_map (limit_set, limit_group, check_only) SELECT ccls.id, cclg.id, FALSE FROM config.circ_limit_set ccls, config.circ_limit_group cclg WHERE ccls.name like 'One BESTSELLER Limit' AND cclg.name = 'BESTSELLER'; INSERT INTO config.circ_limit_set_circ_mod_map (limit_set, circ_mod) SELECT ccls.id, 'BESTSELLER' FROM config.circ_limit_set ccls WHERE ccls.name = 'One BESTSELLER Limit'; INSERT INTO config.circ_matrix_limit_set_map (matchpoint, limit_set, fallthrough) SELECT ccmm.id, ccls.id, TRUE FROM config.circ_limit_set ccls, config.circ_matrix_matchpoint WHERE ccls.name = 'One BESTSELLER Limit' AND ccmm.org_unit = (SELECT id FROM actor.orgunit WHERE shortname = 'SYS1') AND ccmm.circ_modifier = 'BESTSELLER'; COMMIT;
TODO Create helper functions for the “new” way.
Upcoming Development
-
Updated Editors
-
Custom Failure Codes
-
Split “Grouped” Failure Codes
-
Failure Scopes
-
Importance/Manual Ordering
-
Comments/Notes Field
-
Relative Organizational Units
-
Exact Match
-
In Ancestor Tree of
-
In Descendant Tree of
-
In Full Tree of
-
Negations of the above
-
Notes plagiarized from the developer who plans to do the work.
Updated Editors
At this point I plan on replacing the existing editor interfaces with more “TPac-like” editors, that is generated server side. This will allow a lot more flexibility in overall display, will permit more complicated sorting, and will make it easier to implement things like filtering.
My overall goal is to always sort the way they will be used, but allow filtering on anything that affects what rules are in use.
Custom Failure Codes
Not much to say here. Instead of the generic failure code of “we said no” I plan on having custom failure codes that permit things like “This is a Local Use Only patron” and such. As a side benefit, these custom failure codes will also be able to get custom override permissions, allowing much more granular override options.
Split “grouped” failure reasons into individual codes
It is very hard to provide granular control over overrides when a half dozen failure reasons all get the same code, and thus the same override permission. Splitting them up will help with that. Dealing with upgrade scripts (as in, what to do about who gets the new override permissions, mainly) is a different matter.
Failure Scopes
At the moment all overrides for circulation are “do you have permission at the circ desk you are standing at” when they are checked. I want to change this so that, for example, you can say “do you have permission at the item’s owning library” and similar, to give greater control over who can override what.
Importance/Manual Ordering
Some people want a lot of control over the ordering of the matrix, and weighting doesn’t give them enough control. This field would allow for all else to be considered equal and an explicit numerical order to be applied. Or, in the case of normal configurations, it would allow for fine adjustment of otherwise equal rules.
Comments/Notes Field
I mainly want to put this in for when you go to edit a rule, so you can see what someone else who edited it might have been thinking when they did so. Or put a warning not to mess with the rule for whatever reason, etc.
Relative Org Units
Similar to the current strict org unit checks, I see it as being potentially useful to be able to say things like “The User’s Home Library is the same as the Item’s Circ Library” and similar, possibly with the following variants:
-
Exact match
-
In Ancestor tree of
-
In Descendant tree of
-
In Full tree of
-
Negations of all of the above
Circulation
-
Add Context Field to the circulation matrix
Adding copy locations to the limit sets means that you would be able to limit the number of copies that a patron can have checked out from a given copy location. This way you could put your new books or bestsellers in a copy location and limit that way, rather than having a circulation modifier or having to configure all of the MARC specifics.
Context Field in the circulation matrix
Sometimes you want the rules for a circulation to differ depending on where the circulation is being triggered from. Allow renewals, but not OPAC renewals, or allow checkout but not at the self check, that kind of thing. This field would allow for those differences by allowing filtering based on which interface the circulation is happening at.
Holds
-
Add fallthrough to the hold matrix
-
Capture holds at circulation library only
-
Change when hold exists check is done
-
Hold Stalling Flag
-
Improved Overrides & Messages
Capture holds at circulation library only
This flag would cause the hold matchpoint to only capture the hold if the copy being considered is presently at its home library (‘asset.copy.circ_lib`). One example where this would be useful is how the Merrimack Valley Library Consortium handles statewide virtual catalog requests. Our policy is for members to transit other libraries’ materials home rather than sending them in transit to the statewide VC when these holds trigger. This additional transit often results in the hold expiring before the copy gets home. Setting this flag would prevent the hold from taking place until the copy gets home, thus improving that situation.
At the moment HOLD_EXISTS is only checked at the final place hold step. This means that if any other override has been requested we may silently override the HOLD_EXISTS failure as well.
By checking for it at “can this be placed” time we get a better picture of why placement might fail overall.
Stalling Start
Currently stalling starts at hold placement, which means that patrons who place suspended holds bypass stalling when they re-activate the holds. This would allow for holds to flag when they were placed or unfrozen and use that as the start of the stalling period instead, possibly with a global flag to turn it on and off.
Overrides
At this point I have too many issues with storing overrides, but I feel that the full list of reasons a hold could not be placed, in groups by the copy that generated them, should be returned to the UI layer. Otherwise you don’t get enough information to make a decision about overriding.
Parts
-
Designation of a Default Part
-
Subparts
Parts
Parts can cause a lot of issues, and don’t seem to be as useful/powerful as they could be. The easy solution is to add optional fields to the parts themselves. Without the fields filled in the system will act identically, but once supplied the system will act upon the information.
Default Part
By adding a “default” flag to parts, with a limit of one per bib, we can support older and/or on order title holds (by assuming the default part flagged copies can fill them) and allow for partless copies to fill holds on the default part (by assuming no part is the default part). In addition, this could be used to auto-select the default part when placing a hold, and disallow title holds when there is a default part.
Subparts
Adding subpart designators to the system will allow part holds to be filled by copies that contain the part in question. Interface wise it may be possible to provide “auto-subpart” routines where ranges are involved to automatically build and populate subpart information for new and existing bibs.
Age Protection
-
Match age protection rule on the copy
-
Supply the age protection in the hold matrix
Age protection is a hot topic, where different groups want different things where age protection is concerned. Some want to match on the user’s home library, others on the circ library, some want cascading rules and others don’t. By adding two new fields to the hold matrix we can permit a lot of these configurations.
The first is a “Match the Age Protect rule on the copy” field, where you select the age protect rule to match. This allows your rules to take into account what the cataloger has put on the copy for age protection.
The second is a “Bypass Copy Age Protection” result field that tells the system to not do the normal copy level age protect checks, allowing the matrix itself to provide that. This also allows for staff (or any other group) to not be subject to age protection for any reasons desired.