1 package OpenILS::SIP::Transaction::Checkin;
2 use warnings; use strict;
4 use POSIX qw(strftime);
5 use Sys::Syslog qw(syslog);
7 use Time::HiRes q/time/;
10 use OpenILS::SIP::Transaction;
11 use OpenILS::Const qw/:const/;
12 use OpenILS::Application::AppUtils;
13 my $U = 'OpenILS::Application::AppUtils';
15 use base qw(OpenILS::SIP::Transaction);
22 # 3M extensions: (most of the data is stored under Item)
23 # collection_code => undef,
24 # call_number => undef,
25 destination_loc => undef,
26 alert_type => undef, # 00,01,02,03,04 or 99
27 # hold_patron_id => undef,
28 # hold_patron_name => "",
32 my $hold_as_transit = 0;
36 my $self = $class->SUPER::new(@_); # start with an Transaction object
38 foreach (keys %fields) {
39 $self->{_permitted}->{$_} = $fields{$_}; # overlaying _permitted
42 @{$self}{keys %fields} = values %fields; # copying defaults into object
44 $self->load_override_events;
46 $hold_as_transit = OpenILS::SIP->config->{implementation_config}->{checkin_hold_as_transit};
48 return bless $self, $class;
53 return 0 if !$self->{item};
54 return !$self->{item}->magnetic;
58 sub load_override_events {
59 return if %override_events;
60 my $override = OpenILS::SIP->config->{implementation_config}->{checkin_override};
61 return unless $override;
62 my $events = $override->{event};
63 $events = [$events] unless ref $events eq 'ARRAY';
64 $override_events{$_} = 1 for @$events;
70 my ($sip_handler, $inst_id, $trans_date, $return_date, $current_loc, $item_props) = @_; # most unused
72 unless($self->{item}) {
79 # physical location defaults to ws ou of the logged in sip user,
80 # which currently defaults to home_ou, since ws's aren't used.
81 my $phys_location = $sip_handler->{login_session}->ws_ou;
83 my $args = {barcode => $self->{item}->id};
84 $args->{hold_as_transit} = 1 if $hold_as_transit;
87 # SIP date format is YYYYMMDD. Translate to ISO8601
88 $return_date =~ s/(\d{4})(\d{2})(\d{2}).*/$1-$2-$3/;
89 syslog('LOG_INFO', "Checking in with backdate $return_date");
90 $args->{backdate} = $return_date;
93 if($current_loc) { # SIP client specified a physical location
95 my $org_id = (defined $org_sn_cache{$current_loc}) ?
96 $org_sn_cache{$current_loc} :
97 OpenILS::SIP->editor()->search_actor_org_unit({shortname => $current_loc}, {idlist => 1})->[0];
99 $org_sn_cache{$current_loc} = $org_id;
101 # if the caller specifies a physical location, use it as the checkin circ lib
102 $args->{circ_lib} = $phys_location = $org_id if defined $org_id;
106 my ($resp, $txt, $code);
110 my $method = 'open-ils.circ.checkin';
111 $method .= '.override' if $override;
113 my $start_time = time();
114 $resp = $U->simplereq('open-ils.circ', $method, $self->{authtoken}, $args);
115 syslog('LOG_INFO', "OILS: Checkin API call took %0.3f seconds", (time() - $start_time));
118 my $s = Dumper($resp);
120 syslog('LOG_INFO', "OILS: Checkin response: $s");
123 # In oddball cases, we can receive an array of events.
124 # The first event received should be treated as the main result.
125 $resp = $$resp[0] if ref($resp) eq 'ARRAY';
126 $code = $U->event_code($resp);
127 $txt = (defined $code) ? $resp->{textcode} : '';
131 if ( $override_events{$txt} ) {
138 syslog('LOG_INFO', "OILS: Checkin resulted in event: $txt, phys_location: $phys_location");
140 $resp->{org} &&= OpenILS::SIP::shortname_from_id($resp->{org}); # Convert id to shortname
142 $self->destination_loc($resp->{org}) if $resp->{org};
144 if ($txt eq 'ROUTE_ITEM') {
145 # Note, this alert_type will be overridden below if this is a hold transit
146 $self->alert_type('04'); # send to other branch
148 } elsif ($txt and $txt ne 'NO_CHANGE' and $txt ne 'SUCCESS') {
149 syslog('LOG_WARNING', "OILS: Checkin returned unexpected event $code : $txt");
150 $self->alert_type('00'); # unknown
153 my $payload = $resp->{payload} || {};
157 if(ref $payload eq 'HASH') {
159 # Two places to look for hold data. These are more important and more definitive than above.
160 if ($payload->{remote_hold}) {
161 # actually only used for checkin at non-owning branch w/ hold at same branch
162 $self->item->hold($payload->{remote_hold});
164 } elsif ($payload->{hold}) {
165 $self->item->hold($payload->{hold});
168 $circ = $resp->{payload}->{circ} || '';
169 $copy = $resp->{payload}->{copy} || '';
172 if ($self->item->hold) {
173 my ($pickup_lib_id, $pickup_lib_sn);
175 my $holder = OpenILS::SIP->editor()->retrieve_actor_user(
176 [$self->item->hold->usr, {flesh => 1, flesh_fields => {au => ['card']}}]);
178 my $holder_name = OpenILS::SIP::Patron::format_name($holder);
180 if (ref $self->item->hold->pickup_lib) {
181 $pickup_lib_id = $self->item->hold->pickup_lib->id;
182 $pickup_lib_sn = $self->item->hold->pickup_lib->shortname;
185 $pickup_lib_id = $self->item->hold->pickup_lib;
186 $pickup_lib_sn = OpenILS::SIP::shortname_from_id($pickup_lib_id);
189 $self->item->hold_patron_bcode( ($holder->card) ? $holder->card->barcode : '');
190 $self->item->hold_patron_name($holder_name);
191 $self->item->destination_loc($pickup_lib_sn);
193 my $atype = ($pickup_lib_id == $phys_location) ? '01' : '02';
194 $self->alert_type($atype);
197 $self->alert(1) if defined $self->alert_type; # alert_type could be "00", hypothetically
200 $self->{circ_user_id} = $circ->usr;
202 } elsif ($txt eq 'NO_CHANGE' or $txt eq 'SUCCESS' or $txt eq 'ROUTE_ITEM') {
203 $self->ok(1); # NO_CHANGE means it wasn't checked out anyway, no problem
206 $self->alert_type('00') unless $self->alert_type; # wasn't checked out, but *something* changed
207 # $self->ok(0); # maybe still ok?
214 Successful Checkin event payload includes:
215 $payload->{copy} (unfleshed)
219 $payload->{cancelled_hold_transit}
225 ASSET_COPY_NOT_FOUND => ,
228 CIRC_CLAIMS_RETURNED => ,
229 COPY_ALERT_MESSAGE => ,
230 COPY_STATUS_LOST => ,
231 COPY_STATUS_MISSING => ,
233 ITEM_DEPOSIT_PAID => ,
235 DATABASE_UPDATE_FAILED => ,
236 DATABASE_QUERY_FAILED => ,
240 # 01 - hold in local library
241 # 02 - hold for other branch
242 # 03 - hold for ILL (not used in EG)
243 # 04 - send to other branch (no hold)