# ------------------------------------------------------------------------------
# If the circ.checkout_fill_related_hold setting is turned on and no hold for
# the patron directly targets the checked out item, see if there is another hold
-# (with hold_type T or V) for the patron that could be fulfilled by the checked
-# out item. Fulfill the oldest hold and only fulfill 1 of them.
+# for the patron that could be fulfilled by the checked out item. Fulfill the
+# oldest hold and only fulfill 1 of them.
+#
+# For "another hold":
+#
+# First, check for one that the copy matches via hold_copy_map, ensuring that
+# *any* hold type that this copy could fill may end up filled.
+#
+# Then, if circ.checkout_fill_related_hold_exact_match_only is not enabled, look
+# for a Title (T) or Volume (V) hold that matches the item. This allows items
+# that are non-requestable to count as capturing those hold types.
# ------------------------------------------------------------------------------
sub find_related_user_hold {
my($self, $copy, $patron) = @_;
select => {ahr => ['id']},
from => {
ahr => {
+ ahcm => {
+ field => 'hold',
+ fkey => 'id'
+ }
+ }
+ },
+ where => {
+ '+ahr' => {
+ usr => $patron->id,
+ fulfillment_time => undef,
+ cancel_time => undef,
+ '-or' => [
+ {expire_time => undef},
+ {expire_time => {'>' => 'now'}}
+ ]
+ },
+ '+ahcm' => {
+ target_copy => $self->copy->id
+ },
+ },
+ order_by => {ahr => {request_time => {direction => 'asc'}}},
+ limit => 1
+ };
+
+ my $hold_info = $e->json_query($args)->[0];
+ return $e->retrieve_action_hold_request($hold_info->{id}) if $hold_info;
+ return undef if $U->ou_ancestor_setting_value(
+ $self->circ_lib, 'circ.checkout_fills_related_hold_exact_match_only', $e);
+
+ # find the oldest unfulfilled hold that has not yet hit the holds shelf.
+ $args = {
+ select => {ahr => ['id']},
+ from => {
+ ahr => {
acp => {
field => 'id',
fkey => 'current_copy',
limit => 1
};
- my $hold_info = $e->json_query($args)->[0];
+ $hold_info = $e->json_query($args)->[0];
return $e->retrieve_action_hold_request($hold_info->{id}) if $hold_info;
return undef;
}
oils_i18n_gettext('circ.checkout_fills_related_hold', 'When a patron checks out an item and they have no holds that directly target the item, the system will attempt to find a hold for the patron that could be fulfilled by the checked out item and fulfills it', 'coust', 'description'),
'bool'),
+( 'circ.checkout_fills_related_hold_exact_match_only',
+ oils_i18n_gettext('circ.checkout_fills_related_hold_exact_match_only', 'Checkout Fills Related Hold On Valid Copy Only', 'coust', 'label'),
+ oils_i18n_gettext('circ.checkout_fills_related_hold_exact_match_only', 'When filling related holds on checkout only match on items that are valid for opportunistic capture for the hold. Without this set a Title or Volume hold could match when the item is not holdable. With this set only holdable items will match.', 'coust', 'description'),
+ 'bool'),
+
( 'circ.selfcheck.auto_override_checkout_events',
oils_i18n_gettext('circ.selfcheck.auto_override_checkout_events', 'Selfcheck override events list', 'coust', 'label'),
oils_i18n_gettext('circ.selfcheck.auto_override_checkout_events', 'List of checkout/renewal events that the selfcheck interface should automatically override instead instead of alerting and stopping the transaction', 'coust', 'description'),