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;
my $MESSAGE_MAP = {
'09' => \&handle_checkin,
'11' => \&handle_checkout,
+ '15' => \&handle_hold,
'17' => \&handle_item_info,
'23' => \&handle_patron_status,
'29' => \&handle_renew,
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 {
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
{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,
&& $circ->renewal_remaining > 0;
}
- return ({
+ return {
code => $code,
fixed_fields => [
$circ ? 1 : 0, # checkout ok
$circ ? {BK => $circ->id} : (),
$deposit ? {BV => $deposit} : (),
]
- }, $circ_details);
+ };
}
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
{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
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
{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,
};
}
+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;
--- /dev/null
+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']);
+}
+