From c4fc645612335e9f0a631f58bb263c9082597e1f Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Wed, 4 Nov 2020 15:36:01 -0500 Subject: [PATCH] LP1901930 Hold cancel support Signed-off-by: Bill Erickson --- .../src/perlmods/lib/OpenILS/Application/SIP2.pm | 134 +++++++++++++++------ .../lib/OpenILS/Application/SIP2/Checkout.pm | 6 +- .../perlmods/lib/OpenILS/Application/SIP2/Hold.pm | 78 ++++++++++++ .../perlmods/lib/OpenILS/Application/SIP2/Item.pm | 1 - .../lib/OpenILS/Application/SIP2/Patron.pm | 3 +- 5 files changed, 180 insertions(+), 42 deletions(-) create mode 100644 Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Hold.pm diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2.pm index 38cc2f83c2..240ea7c0e3 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2.pm @@ -13,6 +13,7 @@ use OpenILS::Utils::DateTime qw/:datetime/; use OpenILS::Application::SIP2::Common; use OpenILS::Application::SIP2::Session; use OpenILS::Application::SIP2::Item; +use OpenILS::Application::SIP2::Hold; use OpenILS::Application::SIP2::Patron; use OpenILS::Application::SIP2::Checkout; use OpenILS::Application::SIP2::Checkin; @@ -69,6 +70,7 @@ sub dispatch_sip2_request { my $MESSAGE_MAP = { '09' => \&handle_checkin, '11' => \&handle_checkout, + '15' => \&handle_hold, '17' => \&handle_item_info, '23' => \&handle_patron_status, '29' => \&handle_renew, @@ -391,20 +393,12 @@ sub patron_response_common_data { sub handle_checkout { my ($session, $message) = @_; - - my ($msg, $details) = checkout_renew_common($session, $message); - - # No modifications required - return $msg; + return checkout_renew_common($session, $message); } sub handle_renew { my ($session, $message) = @_; - - my ($msg, $details) = checkout_renew_common($session, $message, 1); - - # No modifications required - return $msg; + return checkout_renew_common($session, $message, 1); } sub checkout_renew_common { @@ -415,17 +409,8 @@ sub checkout_renew_common { my $item_barcode = $SC->get_field_value($message, 'AB'); my $fee_ack = $SC->get_field_value($message, 'BO'); - my $item_details = OpenILS::Application::SIP2::Item->get_item_details( - $session, barcode => $item_barcode - ); - - my $patron_details = OpenILS::Application::SIP2::Patron->get_patron_details( - $session, barcode => $patron_barcode - ); - my $code = $is_renewal ? '30' : '12'; - - return ({ + my $stub = { code => $code, fixed_fields => [ 0, # checkout ok @@ -438,7 +423,17 @@ sub checkout_renew_common { {AA => $patron_barcode}, {AB => $item_barcode} ] - }) unless ($item_details && $patron_details); + }; + + my $item_details = OpenILS::Application::SIP2::Item->get_item_details( + $session, barcode => $item_barcode); + + return $stub unless $item_details; + + my $patron_details = OpenILS::Application::SIP2::Patron->get_patron_details( + $session, barcode => $patron_barcode); + + return $stub unless $patron_details; my $circ_details = OpenILS::Application::SIP2::Checkout->checkout( $session, @@ -460,7 +455,7 @@ sub checkout_renew_common { && $circ->renewal_remaining > 0; } - return ({ + return { code => $code, fixed_fields => [ $circ ? 1 : 0, # checkout ok @@ -482,7 +477,7 @@ sub checkout_renew_common { $circ ? {BK => $circ->id} : (), $deposit ? {BV => $deposit} : (), ] - }, $circ_details); + }; } sub handle_renew_all { @@ -492,11 +487,7 @@ sub handle_renew_all { my $patron_barcode = $SC->get_field_value($message, 'AA'); my $fee_ack = $SC->get_field_value($message, 'BO'); - my $patron_details = OpenILS::Application::SIP2::Patron->get_patron_details( - $session, barcode => $patron_barcode - ); - - return { + my $stub = { code => '66', fixed_fields => [ 0, # ok @@ -508,7 +499,12 @@ sub handle_renew_all { {AA => $patron_barcode}, {AO => $config->{institution}}, ] - } unless $patron_details; + }; + + my $patron_details = OpenILS::Application::SIP2::Patron->get_patron_details( + $session, barcode => $patron_barcode); + + return $stub unless $patron_details; my $circ_details = OpenILS::Application::SIP2::Checkout->renew_all( $session, $patron_details, fee_ack => $fee_ack @@ -547,11 +543,7 @@ sub handle_checkin { my $current_loc = $SC->get_field_value($message, 'AP'); my $return_date = $fixed_fields[2]; - my $item_details = OpenILS::Application::SIP2::Item->get_item_details( - $session, barcode => $item_barcode - ); - - return { + my $stub = { code => '10', fixed_fields => [ 0, # checkin ok @@ -565,7 +557,12 @@ sub handle_checkin { {AO => $config->{institution}}, {CV => '00'} # unkown alert type ] - } unless $item_details; + }; + + my $item_details = OpenILS::Application::SIP2::Item->get_item_details( + $session, barcode => $item_barcode); + + return $stub unless $item_details; my $checkin_details = OpenILS::Application::SIP2::Checkin->checkin( $session, @@ -610,6 +607,73 @@ sub handle_checkin { }; } +sub handle_hold { + my ($session, $message) = @_; + my $config = $session->config; + + my @fixed_fields = @{$message->{fixed_fields} || []}; + my $hold_mode = $fixed_fields[0]; + + my $patron_barcode = $SC->get_field_value($message, 'AA'); + my $item_barcode = $SC->get_field_value($message, 'AB'); + + my $stub = { + code => '16', + fixed_fields => [ + 0, # ok + 0, # available + $SC->sipdate + ], + fields => [ + {AA => $patron_barcode}, + {AB => $item_barcode}, + {AO => $config->{institution}} + ] + }; + + # Hold Cancel is the only supported action. + return $stub unless $hold_mode eq '-'; + + my $patron_details = + OpenILS::Application::SIP2::Patron->get_patron_details( + $session, barcode => $patron_barcode); + + return $stub unless $patron_details; + + my $item_details = OpenILS::Application::SIP2::Item->get_item_details( + $session, barcode => $item_barcode); + + return $stub unless $item_details; + + my $hold = OpenILS::Application::SIP2::Hold->hold_from_copy( + $session, $patron_details, $item_details); + + return $stub unless $hold; + + my $details = OpenILS::Application::SIP2::Hold->cancel($session, $hold); + + return $stub unless $details->{ok}; + + # report info on the targeted copy if one is set. + my $copy = $hold->current_copy || $item_details->{item}; + my $title_id = $item_details->{item}->call_number->record->id; + + return { + code => '16', + fixed_fields => [ + 1, # ok + 0, # available + $SC->sipdate + ], + fields => [ + {AA => $patron_barcode}, + {AB => $copy->barcode}, + {AJ => $title_id}, + {AO => $config->{institution}} + ] + }; +} + sub handle_payment { my ($session, $message) = @_; my $config = $session->config; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Checkout.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Checkout.pm index 2c6f33ab44..a739d0d22d 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Checkout.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Checkout.pm @@ -2,14 +2,10 @@ package OpenILS::Application::SIP2::Checkout; use strict; use warnings; use DateTime; use DateTime::Format::ISO8601; -use OpenSRF::System; -use OpenILS::Utils::CStoreEditor q/:funcs/; +use OpenILS::Utils::DateTime qw/:datetime/; use OpenSRF::Utils::Logger q/$logger/; use OpenILS::Application::AppUtils; -use OpenILS::Utils::DateTime qw/:datetime/; -use OpenILS::Const qw/:const/; use OpenILS::Application::SIP2::Common; -use OpenILS::Application::SIP2::Session; my $U = 'OpenILS::Application::AppUtils'; my $SC = 'OpenILS::Application::SIP2::Common'; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Hold.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Hold.pm new file mode 100644 index 0000000000..3cb3edda34 --- /dev/null +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Hold.pm @@ -0,0 +1,78 @@ +package OpenILS::Application::SIP2::Hold; +use strict; use warnings; +use OpenSRF::Utils::Logger q/$logger/; +use OpenILS::Application::AppUtils; +use OpenILS::Application::SIP2::Common; +my $U = 'OpenILS::Application::AppUtils'; +my $SC = 'OpenILS::Application::SIP2::Common'; + + +sub cancel { + my ($class, $session, $hold) = @_; + + my $details = {ok => 0}; + + my $resp = $U->simplereq( + 'open-ils.circ', + 'open-ils.circ.hold.cancel', + $session->editor->authtoken, $hold->id, 7 # cancel via SIP + ); + + return $details unless $resp && !$U->event_code($resp); + + $details->{ok} = 1; + + return $details; +} + +# Given a "representative" copy, finds a matching hold +sub hold_from_copy { + my ($class, $session, $patron_details, $item_details) = @_; + my $e = $session->editor; + my $hold; + + my $copy = $item_details->{item}; + + my $run_hold_query = sub { + my %filter = @_; + return $e->search_action_hold_request([ + { usr => $patron_details->{patron}->id, + cancel_time => undef, + fulfillment_time => undef, + %filter + }, { + flesh => 2, + flesh_fields => { + ahr => ['current_copy'], + acp => ['call_number'] + }, + order_by => {ahr => 'request_time DESC'}, + limit => 1 + } + ])->[0]; + }; + + # first see if there is a match on current_copy + return $hold if $hold = + $run_hold_query->(current_copy => $copy->id); + + # next, assume bib-level holds are the most common + return $hold if $hold = $run_hold_query->( + target => $copy->call_number->record->id, hold_type => 'T'); + + # next try metarecord holds + my $map = $e->search_metabib_metarecord_source_map( + {source => $copy->call_number->record->id})->[0]; + + return $hold if $hold = $run_hold_query->( + target => $map->metarecord, hold_type => 'M'); + + # volume holds + return $hold if $hold = $run_hold_query->( + target => $copy->call_number->id, hold_type => 'V'); + + # copy holds + return $run_hold_query->( + target => $copy->id, hold_type => ['C', 'F', 'R']); +} + diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Item.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Item.pm index 5ab25ff745..f697382b31 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Item.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Item.pm @@ -9,7 +9,6 @@ use OpenILS::Application::AppUtils; use OpenILS::Utils::DateTime qw/:datetime/; use OpenILS::Const qw/:const/; use OpenILS::Application::SIP2::Common; -use OpenILS::Application::SIP2::Session; my $U = 'OpenILS::Application::AppUtils'; my $SC = 'OpenILS::Application::SIP2::Common'; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Patron.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Patron.pm index b9d3ea3fd9..40a6a2f74e 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Patron.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Patron.pm @@ -9,7 +9,6 @@ use OpenILS::Const qw/:const/; use OpenILS::Application::AppUtils; use OpenILS::Utils::DateTime qw/:datetime/; use OpenILS::Application::SIP2::Common; -use OpenILS::Application::SIP2::Session; my $U = 'OpenILS::Application::AppUtils'; my $SC = 'OpenILS::Application::SIP2::Common'; @@ -38,6 +37,8 @@ sub get_patron_details { } }])->[0]; + return undef unless $card; + my $patron = $details->{patron} = $card->usr; $patron->card($card); -- 2.11.0