Avoid referencing nonexistent AgencyId vars
[sitka/iNCIPit.git] / iNCIPit.cgi
CommitLineData
4cdc4f67
JS
1#! /usr/bin/perl
2
1ac548f2 3# This file is part of iNCIPit
4cdc4f67
JS
4#
5# iNCIPit is free software: you can redistribute it and/or modify it
6# under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 2 of the License, or
8# (at your option) any later version.
9#
10# iNCIPit is distributed in the hope that it will be useful, but WITHOUT
11# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
13# License for more details.
14#
15# You should have received a copy of the GNU General Public License
7a94033c 16# along with iNCIPit. If not, see <http://www.gnu.org/licenses/>.
4cdc4f67 17
4cdc4f67
JS
18use warnings;
19use XML::LibXML;
20use CGI::XMLPost;
21use HTML::Entities;
22use CGI::Carp;
23use XML::XPath;
24use OpenSRF::System;
25use OpenSRF::Utils::SettingsClient;
26use Digest::MD5 qw/md5_hex/;
27use OpenILS::Utils::Fieldmapper;
28use OpenILS::Utils::CStoreEditor qw/:funcs/;
29use OpenILS::Const qw/:const/;
30use Scalar::Util qw(reftype blessed);
31use MARC::Record;
32use MARC::Field;
33use MARC::File::XML;
34use POSIX qw/strftime/;
35use DateTime;
a30f6f9e 36my $U = "OpenILS::Application::AppUtils";
4cdc4f67
JS
37
38my $xmlpost = CGI::XMLPost->new();
5f517e0a 39my $xml = $xmlpost->data();
4cdc4f67 40
1ac548f2
JS
41# log posted data
42# XXX: posted ncip message log filename should be in config.
4cdc4f67
JS
43open POST_DATA, ">>post_data.txt";
44print POST_DATA $xml;
45close POST_DATA;
46
47# initialize the parser
48my $parser = new XML::LibXML;
49my $doc = $parser->load_xml( string => $xml );
50
51my %session = login();
52
53# Setup our SIGALRM handler.
54$SIG{'ALRM'} = \&logout;
55
1ac548f2 56if ( defined( $session{authtoken} ) ) {
5f517e0a
DW
57 $doc->exists('/NCIPMessage/LookupUser') ? lookupUser() : (
58 $doc->exists('/NCIPMessage/ItemRequested') ? item_request() : (
59 $doc->exists('/NCIPMessage/ItemShipped') ? item_shipped() : (
60 $doc->exists('/NCIPMessage/ItemCheckedOut') ? item_checked_out() : (
61 $doc->exists('/NCIPMessage/CheckOutItem') ? check_out_item() : (
62 $doc->exists('/NCIPMessage/ItemCheckedIn') ? item_checked_in() : (
63 $doc->exists('/NCIPMessage/CheckInItem') ? check_in_item() : (
64 $doc->exists('/NCIPMessage/ItemReceived') ? item_received() : (
65 $doc->exists('/NCIPMessage/AcceptItem') ? accept_item() : (
66 $doc->exists('/NCIPMessage/ItemRequestCancelled') ? item_cancelled() : (
67 $doc->exists('/NCIPMessage/ItemRenewed') ? item_renew() : (
68 $doc->exists('/NCIPMessage/RenewItem') ? renew_item() :
69 fail("UNKNOWN NCIPMessage")
70 )))))))))));
71
72 # Clear any SIGALRM timers.
73 alarm(0);
74 logout();
4cdc4f67 75} else {
5f517e0a 76 fail("Unable to perform action : Unknown Service Request");
4cdc4f67
JS
77}
78
79sub logit {
5f517e0a
DW
80 my ( $msg, $func, $more_info ) = @_;
81 open RESP_DATA, ">>resp_data.txt";
82 print RESP_DATA $msg;
83 print RESP_DATA $more_info unless !$more_info;
84 close RESP_DATA;
85 print $msg || fail($func);
4cdc4f67
JS
86}
87
6e6bdfe9 88sub staff_log {
5f517e0a
DW
89 my ( $taiv, $faiv, $more_info ) = @_;
90 my $now = localtime();
91 open STAFF_LOG, ">>staff_data.csv";
92 print STAFF_LOG "$now, $faiv, $taiv, $more_info\n";
93 close STAFF_LOG;
6e6bdfe9
JS
94}
95
4cdc4f67 96sub item_renew {
5f517e0a
DW
97 my $faidSchemeX = $doc->findvalue('/NCIPMessage/ItemRenewed/InitiationHeader/FromAgencyId/UniqueAgencyId/Scheme');
98 my $faidScheme = HTML::Entities::encode($faidSchemeX);
99 my $faidValue = $doc->find('/NCIPMessage/ItemRenewed/InitiationHeader/FromAgencyId/UniqueAgencyId/Value');
100 my $taidSchemeX = $doc->findvalue('/NCIPMessage/ItemRenewed/InitiationHeader/ToAgencyId/UniqueAgencyId/Scheme');
101 my $taidScheme = HTML::Entities::encode($taidSchemeX);
102 my $taidValue = $doc->find('/NCIPMessage/ItemRenewed/InitiationHeader/ToAgencyId/UniqueAgencyId/Value');
103
104 my $pid = $doc->findvalue('/NCIPMessage/ItemRenewed/UniqueUserId/UserIdentifierValue');
105 my $visid = $doc->findvalue('/NCIPMessage/ItemRenewed/ItemOptionalFields/ItemDescription/VisibleItemId/VisibleItemIdentifier') . $faidValue;
106 my $due_date = $doc->findvalue('/NCIPMessage/ItemRenewed/DateDue');
107
108 my $r = renewal( $visid, $due_date );
109
110 my $hd = <<ITEMRENEWAL;
4cdc4f67
JS
111Content-type: text/xml
112
113
114<!DOCTYPE NCIPMessage PUBLIC "-//NISO//NCIP DTD Version 1.0//EN" "http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
115<NCIPMessage version="http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
5f517e0a
DW
116 <ItemRenewedResponse>
117 <ResponseHeader>
118 <FromAgencyId>
119 <UniqueAgencyId>
120 <Scheme>$faidScheme</Scheme>
121 <Value>$faidValue</Value>
122 </UniqueAgencyId>
123 </FromAgencyId>
124 <ToAgencyId>
125 <UniqueAgencyId>
126 <Scheme>$taidScheme</Scheme>
127 <Value>$taidValue</Value>
128 </UniqueAgencyId>
129 </ToAgencyId>
130 </ResponseHeader>
131 <UniqueItemId>
132 <ItemIdentifierValue datatype="string">$visid</ItemIdentifierValue>
133 </UniqueItemId>
134 </ItemRenewedResponse>
4cdc4f67
JS
135</NCIPMessage>
136
137ITEMRENEWAL
138
5f517e0a 139 my $more_info = <<MOREINFO;
4cdc4f67 140
5f517e0a
DW
141VISID = $visid
142Desired Due Date = $due_date
4cdc4f67
JS
143
144MOREINFO
145
5f517e0a
DW
146 logit( $hd, ( caller(0) )[3], $more_info );
147 staff_log( $taidValue, $faidValue,
148 "ItemRenewal -> Patronid : "
149 . $pid
150 . " | Visid : "
151 . $visid
152 . " | Due Date : "
153 . $due_date );
6e6bdfe9 154}
4cdc4f67 155
6e6bdfe9 156sub renew_item {
5f517e0a
DW
157 my $faidSchemeX = $doc->findvalue('/NCIPMessage/RenewItem/InitiationHeader/FromAgencyId/UniqueAgencyId/Scheme');
158 my $faidScheme = HTML::Entities::encode($faidSchemeX);
159 my $faidValue = $doc->find('/NCIPMessage/RenewItem/InitiationHeader/FromAgencyId/UniqueAgencyId/Value');
160 my $taidSchemeX = $doc->findvalue('/NCIPMessage/RenewItem/InitiationHeader/ToAgencyId/UniqueAgencyId/Scheme');
161 my $taidScheme = HTML::Entities::encode($taidSchemeX);
162 my $taidValue = $doc->find('/NCIPMessage/RenewItem/InitiationHeader/ToAgencyId/UniqueAgencyId/Value');
163
164 my $pid = $doc->findvalue('/NCIPMessage/RenewItem/UniqueUserId/UserIdentifierValue');
165 my $barcode = $doc->findvalue('/NCIPMessage/RenewItem/UniqueItemId/ItemIdentifierValue');
166 my $due_date = $doc->findvalue('/NCIPMessage/RenewItem/DateDue');
167
168 my $r = renewal( $barcode, $due_date );
169
170 my $hd = <<ITEMRENEWAL;
6e6bdfe9
JS
171Content-type: text/xml
172
173
174<!DOCTYPE NCIPMessage PUBLIC "-//NISO//NCIP DTD Version 1.0//EN" "http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
175<NCIPMessage version="http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
5f517e0a
DW
176 <RenewItemResponse>
177 <ResponseHeader>
178 <FromAgencyId>
179 <UniqueAgencyId>
180 <Scheme>$faidScheme</Scheme>
181 <Value>$faidValue</Value>
182 </UniqueAgencyId>
183 </FromAgencyId>
184 <ToAgencyId>
185 <UniqueAgencyId>
186 <Scheme>$taidScheme</Scheme>
187 <Value>$taidValue</Value>
188 </UniqueAgencyId>
189 </ToAgencyId>
190 </ResponseHeader>
191 <UniqueItemId>
192 <ItemIdentifierValue datatype="string">$visid</ItemIdentifierValue>
193 </UniqueItemId>
194 </RenewItemResponse>
6e6bdfe9
JS
195</NCIPMessage>
196
197ITEMRENEWAL
198
5f517e0a 199 my $more_info = <<MOREINFO;
6e6bdfe9 200
5f517e0a
DW
201VISID = $visid
202Desired Due Date = $due_date
6e6bdfe9
JS
203
204MOREINFO
205
5f517e0a
DW
206 logit( $hd, ( caller(0) )[3], $more_info );
207 staff_log( $taidValue, $faidValue,
208 "RenewItem -> Patronid : "
209 . $pid
210 . " | Visid : "
211 . $visid
212 . " | Due Date : "
213 . $due_date );
4cdc4f67
JS
214}
215
216sub accept_item {
5f517e0a
DW
217 my $faidSchemeX = $doc->findvalue('/NCIPMessage/AcceptItem/InitiationHeader/FromAgencyId/UniqueAgencyId/Scheme');
218 my $faidScheme = HTML::Entities::encode($faidSchemeX);
219 my $faidValue = $doc->find('/NCIPMessage/AcceptItem/InitiationHeader/FromAgencyId/UniqueAgencyId/Value');
220 my $taidSchemeX = $doc->findvalue('/NCIPMessage/AcceptItem/InitiationHeader/ToAgencyId/UniqueAgencyId/Scheme');
221 my $taidScheme = HTML::Entities::encode($taidSchemeX);
222 my $taidValue = $doc->find('/NCIPMessage/AcceptItem/InitiationHeader/ToAgencyId/UniqueAgencyId/Value');
5f517e0a
DW
223 my $visid = $doc->findvalue('/NCIPMessage/AcceptItem/ItemOptionalFields/ItemDescription/VisibleItemId/VisibleItemIdentifier') . $faidValue;
224 my $request_id = $doc->findvalue('/NCIPMessage/AcceptItem/UniqueRequestId/RequestIdentifierValue') || "unknown";
225 my $patron = $doc->findvalue('/NCIPMessage/AcceptItem/UserOptionalFields/VisibleUserId/VisibleUserIdentifier');
226 my $copy = copy_from_barcode($visid);
0b0c5299
DW
227 my $r2 = update_copy( $copy, 111 ); # XXX CUSTOMIZATION NEEDED XXX # put into INN-Reach Hold status
228
229# TODO: this should probably fulfill the original hold, not just change the status. Eventually we should split the hold type, as holds arriving are not the same as holds needing to be sent
5f517e0a
DW
230
231 my $hd = <<ACCEPTITEM;
4cdc4f67
JS
232Content-type: text/xml
233
234
235<!DOCTYPE NCIPMessage PUBLIC "-//NISO//NCIP DTD Version 1.0//EN" "http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
236<NCIPMessage version="http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
5f517e0a
DW
237 <AcceptItemResponse>
238 <ResponseHeader>
239 <FromAgencyId>
240 <UniqueAgencyId>
241 <Scheme>$faidScheme</Scheme>
242 <Value>$faidValue</Value>
243 </UniqueAgencyId>
244 </FromAgencyId>
245 <ToAgencyId>
246 <UniqueAgencyId>
247 <Scheme>$taidScheme</Scheme>
248 <Value>$taidValue</Value>
249 </UniqueAgencyId>
250 </ToAgencyId>
251 </ResponseHeader>
252 <UniqueRequestId>
253 <ItemIdentifierValue datatype="string">$request_id</ItemIdentifierValue>
254 </UniqueRequestId>
255 <UniqueItemId>
256 <ItemIdentifierValue datatype="string">$visid</ItemIdentifierValue>
257 </UniqueItemId>
258 </AcceptItemResponse>
4cdc4f67
JS
259</NCIPMessage>
260
261ACCEPTITEM
262
5f517e0a
DW
263 logit( $hd, ( caller(0) )[3] );
264 staff_log( $taidValue, $faidValue,
0b0c5299 265 "AcceptItem -> Request Id : " . $request_id . " | Patron Id : " . $patron . " | Visible Id :" . $visid );
4cdc4f67
JS
266}
267
268sub item_received {
5f517e0a 269 my $faidValue = $doc->find('/NCIPMessage/ItemReceived/InitiationHeader/FromAgencyId/UniqueAgencyId/Value');
0b0c5299
DW
270 my $visid = $doc->findvalue('/NCIPMessage/ItemReceived/ItemOptionalFields/ItemDescription/VisibleItemId/VisibleItemIdentifier') . $faidValue;
271 my $copy = copy_from_barcode($visid);
272 fail( $copy->{textcode} . " $visid" ) unless ( blessed $copy);
273 my $r1 = checkin($visid) if ( $copy->status == OILS_COPY_STATUS_CHECKED_OUT ); # checkin the item before delete if ItemCheckedIn step was skipped
5f517e0a
DW
274 my $r2 = delete_copy($copy);
275
276 my $hd = <<ITEMRECEIVED;
4cdc4f67
JS
277Content-type: text/xml
278
279
280<!DOCTYPE NCIPMessage PUBLIC "-//NISO//NCIP DTD Version 1.0//EN" "http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
281<NCIPMessage version="http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
5f517e0a
DW
282 <ItemReceivedResponse>
283 <ResponseHeader>
284 <FromAgencyId>
285 <UniqueAgencyId>
286 <Scheme>$faidScheme</Scheme>
287 <Value>$faidValue</Value>
288 </UniqueAgencyId>
289 </FromAgencyId>
290 <ToAgencyId>
291 <UniqueAgencyId>
292 <Scheme>$taidScheme</Scheme>
293 <Value>$taidValue</Value>
294 </UniqueAgencyId>
295 </ToAgencyId>
296 </ResponseHeader>
297 <UniqueItemId>
0b0c5299 298 <ItemIdentifierValue datatype="string">$visid</ItemIdentifierValue>
5f517e0a
DW
299 </UniqueItemId>
300 </ItemReceivedResponse>
4cdc4f67
JS
301</NCIPMessage>
302
303ITEMRECEIVED
304
5f517e0a 305 logit( $hd, ( caller(0) )[3] );
0b0c5299 306 staff_log( $taidValue, $faidValue, "ItemReceived -> Visible ID : " . $visid );
4cdc4f67
JS
307}
308
309sub item_cancelled {
5f517e0a
DW
310 my $faidSchemeX = $doc->findvalue('/NCIPMessage/ItemRequestCancelled/InitiationHeader/FromAgencyId/UniqueAgencyId/Scheme');
311 my $faidScheme = HTML::Entities::encode($faidSchemeX);
312 my $faidValue = $doc->find('/NCIPMessage/ItemRequestCancelled/InitiationHeader/FromAgencyId/UniqueAgencyId/Value');
313
314 my $taidSchemeX = $doc->findvalue('/NCIPMessage/ItemRequestCancelled/InitiationHeader/ToAgencyId/UniqueAgencyId/Scheme');
315 my $taidScheme = HTML::Entities::encode($taidSchemeX);
316 my $taidValue = $doc->find('/NCIPMessage/ItemRequestCancelled/InitiationHeader/ToAgencyId/UniqueAgencyId/Value');
317 my $UniqueItemIdAgencyIdValue = $doc->findvalue('/NCIPMessage/ItemRequestCancelled/UniqueItemId/UniqueAgencyId/Value');
318
319 my $barcode = $doc->findvalue('/NCIPMessage/ItemRequestCancelled/UniqueItemId/ItemIdentifierValue');
320
321 if ( $barcode =~ /^i/ ) { # delete copy only if barcode is an iNUMBER
322 $barcode .= $faidValue;
323 my $copy = copy_from_barcode($barcode);
324 fail( $copy->{textcode} . " $barcode" ) unless ( blessed $copy);
325 my $r = delete_copy($copy);
326 } else {
327
328 # remove hold!
329 my $copy = copy_from_barcode($barcode);
330 fail( $copy->{textcode} . " $barcode" ) unless ( blessed $copy);
0b0c5299 331 my $r = update_copy( $copy, 0 ); # TODO: we need to actually remove the hold, not just reset to available
5f517e0a
DW
332 }
333
334 my $hd = <<ITEMREQUESTCANCELLED;
4cdc4f67
JS
335Content-type: text/xml
336
337
338<!DOCTYPE NCIPMessage PUBLIC "-//NISO//NCIP DTD Version 1.0//EN" "http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
339<NCIPMessage version="http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
5f517e0a
DW
340 <ItemRequestCancelledResponse>
341 <ResponseHeader>
342 <FromAgencyId>
343 <UniqueAgencyId>
344 <Scheme>$faidScheme</Scheme>
345 <Value>$faidValue</Value>
346 </UniqueAgencyId>
347 </FromAgencyId>
348 <ToAgencyId>
349 <UniqueAgencyId>
350 <Scheme>$taidScheme</Scheme>
351 <Value>$taidValue</Value>
352 </UniqueAgencyId>
353 </ToAgencyId>
354 </ResponseHeader>
355 <UniqueItemId>
356 <ItemIdentifierValue datatype="string">$barcode</ItemIdentifierValue>
357 </UniqueItemId>
358 </ItemRequestCancelledResponse>
4cdc4f67
JS
359</NCIPMessage>
360
361ITEMREQUESTCANCELLED
362
5f517e0a
DW
363 logit( $hd, ( caller(0) )[3] );
364 staff_log( $taidValue, $faidValue,
365 "ItemRequestCancelled -> Barcode : " . $barcode );
4cdc4f67
JS
366}
367
368sub item_checked_in {
5f517e0a
DW
369 my $faidSchemeX = $doc->findvalue('/NCIPMessage/ItemCheckedIn/InitiationHeader/FromAgencyId/UniqueAgencyId/Scheme');
370 my $faidScheme = HTML::Entities::encode($faidSchemeX);
371 my $faidValue = $doc->find('/NCIPMessage/ItemCheckedIn/InitiationHeader/FromAgencyId/UniqueAgencyId/Value');
372 my $taidSchemeX = $doc->findvalue('/NCIPMessage/ItemCheckedIn/InitiationHeader/ToAgencyId/UniqueAgencyId/Scheme');
373 my $taidScheme = HTML::Entities::encode($taidSchemeX);
374 my $taidValue = $doc->find('/NCIPMessage/ItemCheckedIn/InitiationHeader/ToAgencyId/UniqueAgencyId/Value');
375
0b0c5299
DW
376 my $visid = $doc->findvalue('/NCIPMessage/ItemCheckedIn/ItemOptionalFields/ItemDescription/VisibleItemId/VisibleItemIdentifier') . $faidValue;
377 my $r = checkin($visid);
378 my $copy = copy_from_barcode($visid);
379 fail( $copy->{textcode} . " $visid" ) unless ( blessed $copy);
380 my $r2 = update_copy( $copy, 113 ); # XXX CUSTOMIZATION NEEDED XXX # "INN-Reach Transit Return" status
5f517e0a
DW
381
382 my $hd = <<ITEMCHECKEDIN;
4cdc4f67
JS
383Content-type: text/xml
384
385
386<!DOCTYPE NCIPMessage PUBLIC "-//NISO//NCIP DTD Version 1.0//EN" "http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
387<NCIPMessage version="http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
5f517e0a
DW
388 <ItemCheckedInResponse>
389 <ResponseHeader>
390 <FromAgencyId>
391 <UniqueAgencyId>
392 <Scheme>$faidScheme</Scheme>
393 <Value>$faidValue</Value>
394 </UniqueAgencyId>
395 </FromAgencyId>
396 <ToAgencyId>
397 <UniqueAgencyId>
398 <Scheme>$taidScheme</Scheme>
399 <Value>$taidValue</Value>
400 </UniqueAgencyId>
401 </ToAgencyId>
402 </ResponseHeader>
403 <UniqueItemId>
0b0c5299 404 <ItemIdentifierValue datatype="string">$visid</ItemIdentifierValue>
5f517e0a
DW
405 </UniqueItemId>
406 </ItemCheckedInResponse>
4cdc4f67
JS
407</NCIPMessage>
408
409ITEMCHECKEDIN
410
5f517e0a 411 logit( $hd, ( caller(0) )[3] );
0b0c5299 412 staff_log( $taidValue, $faidValue, "ItemCheckedIn -> Visible ID : " . $visid );
4cdc4f67
JS
413}
414
415sub item_checked_out {
5f517e0a
DW
416 my $faidSchemeX = $doc->findvalue('/NCIPMessage/ItemCheckedOut/InitiationHeader/FromAgencyId/UniqueAgencyId/Scheme');
417 my $faidScheme = HTML::Entities::encode($faidSchemeX);
418 my $faidValue = $doc->find('/NCIPMessage/ItemCheckedOut/InitiationHeader/FromAgencyId/UniqueAgencyId/Value');
419 my $taidSchemeX = $doc->findvalue('/NCIPMessage/ItemCheckedOut/InitiationHeader/ToAgencyId/UniqueAgencyId/Scheme');
420 my $taidScheme = HTML::Entities::encode($taidSchemeX);
421 my $taidValue = $doc->find('/NCIPMessage/ItemCheckedOut/InitiationHeader/ToAgencyId/UniqueAgencyId/Value');
422
0b0c5299 423 my $patron_barcode = $doc->findvalue('/NCIPMessage/ItemCheckedOut/UserOptionalFields/VisibleUserId/VisibleUserIdentifier');
5f517e0a 424 my $due_date = $doc->findvalue('/NCIPMessage/ItemCheckedOut/DateDue');
0b0c5299 425 my $visid = $doc->findvalue('/NCIPMessage/ItemCheckedOut/ItemOptionalFields/ItemDescription/VisibleItemId/VisibleItemIdentifier') . $faidValue;
5f517e0a
DW
426
427 my $copy = copy_from_barcode($visid);
428 fail( $copy->{textcode} . " $visid" ) unless ( blessed $copy);
0b0c5299
DW
429 my $r = update_copy( $copy, 0 ); # seemed like copy had to be available before it could be checked out, so ...
430 my $r1 = checkin($visid) if ( $copy->status == OILS_COPY_STATUS_CHECKED_OUT ); # double posted itemcheckedout messages cause error ... trying to simplify
431 my $r2 = checkout( $visid, $patron_barcode, $due_date );
5f517e0a
DW
432
433 my $hd = <<ITEMCHECKEDOUT;
4cdc4f67
JS
434Content-type: text/xml
435
436
437<!DOCTYPE NCIPMessage PUBLIC "-//NISO//NCIP DTD Version 1.0//EN" "http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
438<NCIPMessage version="http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
5f517e0a
DW
439 <ItemCheckedOutResponse>
440 <ResponseHeader>
441 <FromAgencyId>
442 <UniqueAgencyId>
443 <Scheme>$faidScheme</Scheme>
444 <Value>$faidValue</Value>
445 </UniqueAgencyId>
446 </FromAgencyId>
447 <ToAgencyId>
448 <UniqueAgencyId>
449 <Scheme>$taidScheme</Scheme>
450 <Value>$taidValue</Value>
451 </UniqueAgencyId>
452 </ToAgencyId>
453 </ResponseHeader>
454 <UniqueItemId>
455 <ItemIdentifierValue datatype="string">$visid</ItemIdentifierValue>
456 </UniqueItemId>
457 </ItemCheckedOutResponse>
4cdc4f67
JS
458</NCIPMessage>
459
460ITEMCHECKEDOUT
461
5f517e0a
DW
462 logit( $hd, ( caller(0) )[3] );
463 staff_log( $taidValue, $faidValue,
0b0c5299 464 "ItemCheckedOut -> Visible Id : " . $visid . " | Patron Barcode : " . $patron_barcode . " | Due Date : " . $due_date );
4cdc4f67
JS
465}
466
467sub check_out_item {
5f517e0a
DW
468 my $faidSchemeX = $doc->findvalue('/NCIPMessage/CheckOutItem/InitiationHeader/FromAgencyId/UniqueAgencyId/Scheme');
469 my $faidScheme = HTML::Entities::encode($faidSchemeX);
470 my $faidValue = $doc->find('/NCIPMessage/CheckOutItem/InitiationHeader/FromAgencyId/UniqueAgencyId/Value');
471 my $taidSchemeX = $doc->findvalue('/NCIPMessage/CheckOutItem/InitiationHeader/ToAgencyId/UniqueAgencyId/Scheme');
472 my $taidScheme = HTML::Entities::encode($taidSchemeX);
473 my $taidValue = $doc->find('/NCIPMessage/CheckOutItem/InitiationHeader/ToAgencyId/UniqueAgencyId/Value');
474
475 my $mdate = $doc->findvalue('/NCIPMessage/CheckOutItem/MandatedAction/DateEventOccurred');
0b0c5299 476 my $patron_barcode = "zyyyy"; # XXX: CUSTOMIZATION NEEDED XXX institution/eg_as_item_agency user lookup here
5f517e0a
DW
477
478 my $barcode = $doc->findvalue('/NCIPMessage/CheckOutItem/UniqueItemId/ItemIdentifierValue');
0b0c5299
DW
479
480 # TODO: watch for possible real ids here?
5f517e0a
DW
481 my $due_date = $doc->findvalue('/NCIPMessage/CheckOutItem/DateDue');
482
483 my $copy = copy_from_barcode($barcode);
484 fail( $copy->{textcode} . " $barcode" ) unless ( blessed $copy);
485
0b0c5299
DW
486 my $r2 = checkout( $barcode, $patron_barcode, $due_date );
487
488 # TODO: check for checkout exception (like OPEN_CIRCULATION_EXISTS)
5f517e0a
DW
489
490 my $hd = <<CHECKOUTITEM;
4cdc4f67
JS
491Content-type: text/xml
492
493
494<!DOCTYPE NCIPMessage PUBLIC "-//NISO//NCIP DTD Version 1.0//EN" "http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
495<NCIPMessage version="http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
5f517e0a
DW
496 <CheckOutItemResponse>
497 <ResponseHeader>
498 <FromAgencyId>
499 <UniqueAgencyId>
500 <Scheme>$faidScheme</Scheme>
501 <Value>$faidValue</Value>
502 </UniqueAgencyId>
503 </FromAgencyId>
504 <ToAgencyId>
505 <UniqueAgencyId>
506 <Scheme>$taidScheme</Scheme>
507 <Value>$taidValue</Value>
508 </UniqueAgencyId>
509 </ToAgencyId>
510 </ResponseHeader>
511 <UniqueItemId>
512 <ItemIdentifierValue datatype="string">$barcode</ItemIdentifierValue>
513 </UniqueItemId>
514 </CheckOutItemResponse>
4cdc4f67
JS
515</NCIPMessage>
516
517CHECKOUTITEM
518
5f517e0a
DW
519 logit( $hd, ( caller(0) )[3] );
520 staff_log( $taidValue, $faidValue,
0b0c5299 521 "CheckOutItem -> Barcode : " . $barcode . " | Patron Barcode : " . $patron_barcode . " | Due Date : " . $due_date );
4cdc4f67
JS
522}
523
524sub check_in_item {
5f517e0a
DW
525 my $faidSchemeX = $doc->findvalue('/NCIPMessage/CheckInItem/InitiationHeader/FromAgencyId/UniqueAgencyId/Scheme');
526 my $faidScheme = HTML::Entities::encode($faidSchemeX);
527 my $faidValue = $doc->find('/NCIPMessage/CheckInItem/InitiationHeader/FromAgencyId/UniqueAgencyId/Value');
528 my $taidSchemeX = $doc->findvalue('/NCIPMessage/CheckInItem/InitiationHeader/ToAgencyId/UniqueAgencyId/Scheme');
529 my $taidScheme = HTML::Entities::encode($taidSchemeX);
530 my $taidValue = $doc->find('/NCIPMessage/CheckInItem/InitiationHeader/ToAgencyId/UniqueAgencyId/Value');
531
532 my $barcode = $doc->findvalue('/NCIPMessage/CheckInItem/UniqueItemId/ItemIdentifierValue');
2606eada
DW
533 my $r = checkin($barcode);
534 fail($r) if $r =~ /^COPY_NOT_CHECKED_OUT/;
535 # TODO: do we need to do these next steps? checkin() should handle everything, and we want this to end up in 'reshelving'. If we are worried about transits, we should handle (abort) them, not just change the status
536 ##my $copy = copy_from_barcode($barcode);
537 ##fail($copy->{textcode}." $barcode") unless (blessed $copy);
538 ## my $r2 = update_copy($copy,0); # Available now
5f517e0a
DW
539
540 my $hd = <<CHECKINITEM;
4cdc4f67
JS
541Content-type: text/xml
542
543
544<!DOCTYPE NCIPMessage PUBLIC "-//NISO//NCIP DTD Version 1.0//EN" "http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
545<NCIPMessage version="http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
5f517e0a
DW
546 <CheckInItemResponse>
547 <ResponseHeader>
548 <FromAgencyId>
549 <UniqueAgencyId>
550 <Scheme>$faidScheme</Scheme>
551 <Value>$faidValue</Value>
552 </UniqueAgencyId>
553 </FromAgencyId>
554 <ToAgencyId>
555 <UniqueAgencyId>
556 <Scheme>$taidScheme</Scheme>
557 <Value>$taidValue</Value>
558 </UniqueAgencyId>
559 </ToAgencyId>
560 </ResponseHeader>
561 <UniqueItemId>
562 <ItemIdentifierValue datatype="string">$barcode</ItemIdentifierValue>
563 </UniqueItemId>
564 </CheckInItemResponse>
4cdc4f67
JS
565</NCIPMessage>
566
567CHECKINITEM
568
5f517e0a
DW
569 logit( $hd, ( caller(0) )[3] );
570 staff_log( $taidValue, $faidValue, "CheckInItem -> Barcode : " . $barcode );
4cdc4f67
JS
571}
572
573sub item_shipped {
5f517e0a
DW
574 my $faidSchemeX = $doc->findvalue('/NCIPMessage/ItemShipped/InitiationHeader/FromAgencyId/UniqueAgencyId/Scheme');
575 my $faidScheme = HTML::Entities::encode($faidSchemeX);
576 my $faidValue = $doc->find('/NCIPMessage/ItemShipped/InitiationHeader/FromAgencyId/UniqueAgencyId/Value');
577 my $taidSchemeX = $doc->findvalue('/NCIPMessage/ItemShipped/InitiationHeader/ToAgencyId/UniqueAgencyId/Scheme');
578 my $taidScheme = HTML::Entities::encode($taidSchemeX);
579 my $taidValue = $doc->find('/NCIPMessage/ItemShipped/InitiationHeader/ToAgencyId/UniqueAgencyId/Value');
580
581 my $visid = $doc->findvalue('/NCIPMessage/ItemShipped/ItemOptionalFields/ItemDescription/VisibleItemId/VisibleItemIdentifier') . $faidValue;
582 my $barcode = $doc->findvalue('/NCIPMessage/ItemShipped/UniqueItemId/ItemIdentifierValue') . $faidValue;
583 my $title = $doc->findvalue('/NCIPMessage/ItemShipped/ItemOptionalFields/BibliographicDescription/Title');
584 my $callnumber = $doc->findvalue('/NCIPMessage/ItemShipped/ItemOptionalFields/ItemDescription/CallNumber');
585
586 my $copy = copy_from_barcode($barcode);
587 fail( $copy->{textcode} . " $barcode" ) unless ( blessed $copy);
0b0c5299 588 my $r = update_copy_shipped( $copy, 112, $visid ); # XXX CUSTOMIZATION NEEDED XXX # put copy into INN-Reach Transit status & modify barcode = Visid != tempIIIiNumber
5f517e0a
DW
589
590 my $hd = <<ITEMSHIPPED;
4cdc4f67
JS
591Content-type: text/xml
592
593
594<!DOCTYPE NCIPMessage PUBLIC "-//NISO//NCIP DTD Version 1.0//EN" "http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
595<NCIPMessage version="http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
5f517e0a
DW
596 <ItemShippedResponse>
597 <ResponseHeader>
598 <FromAgencyId>
599 <UniqueAgencyId>
600 <Scheme>$faidScheme</Scheme>
601 <Value>$faidValue</Value>
602 </UniqueAgencyId>
603 </FromAgencyId>
604 <ToAgencyId>
605 <UniqueAgencyId>
606 <Scheme>$taidScheme</Scheme>
607 <Value>$taidValue</Value>
608 </UniqueAgencyId>
609 </ToAgencyId>
610 </ResponseHeader>
611 <UniqueItemId>
612 <ItemIdentifierValue datatype="string">$visid</ItemIdentifierValue>
613 </UniqueItemId>
614 </ItemShippedResponse>
4cdc4f67
JS
615</NCIPMessage>
616
617ITEMSHIPPED
618
5f517e0a
DW
619 logit( $hd, ( caller(0) )[3] );
620 staff_log( $taidValue, $faidValue,
0b0c5299 621 "ItemShipped -> Visible Id : " . $visid . " | Barcode : " . $barcode . " | Title : " . $title . " | Call Number : " . $callnumber );
4cdc4f67
JS
622}
623
624sub item_request {
5f517e0a
DW
625 my $faidSchemeX = $doc->findvalue('/NCIPMessage/ItemRequested/InitiationHeader/FromAgencyId/UniqueAgencyId/Scheme');
626 my $faidScheme = HTML::Entities::encode($faidSchemeX);
627 my $faidValue = $doc->find('/NCIPMessage/ItemRequested/InitiationHeader/FromAgencyId/UniqueAgencyId/Value');
628
629 my $taidSchemeX = $doc->findvalue('/NCIPMessage/ItemRequested/InitiationHeader/ToAgencyId/UniqueAgencyId/Scheme');
630 my $taidScheme = HTML::Entities::encode($taidSchemeX);
631 my $taidValue = $doc->find('/NCIPMessage/ItemRequested/InitiationHeader/ToAgencyId/UniqueAgencyId/Value');
632 my $UniqueItemIdAgencyIdValue = $doc->findvalue('/NCIPMessage/ItemRequested/UniqueItemId/UniqueAgencyId/Value');
633
0b0c5299
DW
634 # TODO: should we use the VisibleID for item agency variation of this method call
635
636 my $pid = $doc->findvalue('/NCIPMessage/ItemRequested/UniqueUserId/UserIdentifierValue');
5f517e0a
DW
637 my $barcode = $doc->findvalue('/NCIPMessage/ItemRequested/UniqueItemId/ItemIdentifierValue');
638 my $author = $doc->findvalue('/NCIPMessage/ItemRequested/ItemOptionalFields/BibliographicDescription/Author');
639 my $title = $doc->findvalue('/NCIPMessage/ItemRequested/ItemOptionalFields/BibliographicDescription/Title');
640 my $callnumber = $doc->findvalue('/NCIPMessage/ItemRequested/ItemOptionalFields/ItemDescription/CallNumber');
641 my $medium_type = $doc->find('/NCIPMessage/ItemRequested/ItemOptionalFields/BibliographicDescription/MediumType/Value');
642
643 my $r = "default error checking response";
644
a30f6f9e
DW
645 if ( $barcode =~ /^i/ ) { # XXX EG is User Agency # create copy only if barcode is an iNUMBER
646 my $copy_status_id = 110; # XXX CUSTOMIZATION NEEDED XXX # INN-Reach Loan Requested - local configured status
5f517e0a 647 $barcode .= $faidValue;
a30f6f9e
DW
648 # we want our custom status to be then end result, so create the copy with status of "Available, then hold it, then update the status
649 $r = create_copy( $title, $callnumber, $barcode, 0, $medium_type );
650 my $copy = copy_from_barcode($barcode);
651 my $r2 = place_simple_hold( $copy->id, $pid );
652 my $r3 = update_copy( $copy, $copy_status_id );
653 } else { # XXX EG is Item Agency
654 # place hold for user UniqueUserId/UniqueAgencyId/Value = institution account
5f517e0a 655 my $copy = copy_from_barcode($barcode);
a30f6f9e
DW
656 my $pid2 = 1013459; # XXX CUSTOMIZATION NEEDED XXX # this is the id of a user representing your DCB system, TODO: use agency information to create and link to individual accounts per agency, if needed
657 $r = place_simple_hold( $copy->id, $pid2 );
658 my $r2 = update_copy( $copy, 111 ); # XXX CUSTOMIZATION NEEDED XXX # put into INN-Reach Hold status
5f517e0a
DW
659 }
660
661 my $hd = <<ITEMREQ;
4cdc4f67
JS
662Content-type: text/xml
663
664
665<!DOCTYPE NCIPMessage PUBLIC "-//NISO//NCIP DTD Version 1.0//EN" "http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
666<NCIPMessage version="http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
5f517e0a
DW
667 <ItemRequestedResponse>
668 <ResponseHeader>
669 <FromAgencyId>
670 <UniqueAgencyId>
671 <Scheme>$faidScheme</Scheme>
672 <Value>$faidValue</Value>
673 </UniqueAgencyId>
674 </FromAgencyId>
675 <ToAgencyId>
676 <UniqueAgencyId>
677 <Scheme>$taidScheme</Scheme>
678 <Value>$taidValue</Value>
679 </UniqueAgencyId>
680 </ToAgencyId>
681 </ResponseHeader>
682 <UniqueUserId>
683 <UniqueAgencyId>
684 <Scheme datatype="string">$taidScheme</Scheme>
685 <Value datatype="string">$taidValue</Value>
686 </UniqueAgencyId>
0b0c5299 687 <UserIdentifierValue datatype="string">$pid</UserIdentifierValue>
5f517e0a
DW
688 </UniqueUserId>
689 <UniqueItemId>
690 <ItemIdentifierValue datatype="string">$barcode</ItemIdentifierValue>
691 </UniqueItemId>
692 <ItemOptionalFields>
693 <BibliographicDescription>
694 <Author datatype="string">$author</Author>
695 <Title datatype="string">$title</Title>
696 </BibliographicDescription>
697 <ItemDescription>
698 <CallNumber datatype="string">$callnumber</CallNumber>
699 </ItemDescription>
700 </ItemOptionalFields>
701 </ItemRequestedResponse>
4cdc4f67
JS
702</NCIPMessage>
703
704ITEMREQ
705
5f517e0a
DW
706 logit( $hd, ( caller(0) )[3] );
707 staff_log( $taidValue, $faidValue,
0b0c5299 708 "ItemRequested -> Barcode : " . $barcode . " | Title : " . $title . " | Call Number : " . $callnumber . " | Patronid :" . $pid );
4cdc4f67
JS
709}
710
1ac548f2
JS
711sub lookupUser {
712
5f517e0a
DW
713 my $faidScheme = $doc->findvalue('/NCIPMessage/LookupUser/InitiationHeader/FromAgencyId/UniqueAgencyId/Scheme');
714 $faidScheme = HTML::Entities::encode($faidScheme);
715 my $faidValue = $doc->find('/NCIPMessage/LookupUser/InitiationHeader/FromAgencyId/UniqueAgencyId/Value');
716 my $taidScheme = $doc->findvalue('/NCIPMessage/LookupUser/InitiationHeader/ToAgencyId/UniqueAgencyId/Scheme');
717 $taidScheme = HTML::Entities::encode($taidScheme);
718
719 my $taidValue = $doc->find('/NCIPMessage/LookupUser/InitiationHeader/ToAgencyId/UniqueAgencyId/Value');
720 my $id = $doc->findvalue('/NCIPMessage/LookupUser/VisibleUserId/VisibleUserIdentifier');
721 my $uidValue = user_id_from_barcode($id);
722
723 if ( !defined($uidValue)
724 || ( ref($uidValue) && reftype($uidValue) eq 'HASH' ) )
725 {
726 do_lookup_user_error_stanza("PATRON_NOT_FOUND : $id");
727 die;
728 }
729
730 my ( $propername, $email, $good_until, $userprivid, $block_stanza ) =
731 ( "name here", "", "good until", "0", "" ); # defaults
732
733 my $patron = flesh_user($uidValue);
734
735 #if (blessed($patron)) {
736 my $patron_ok = 1;
737 my @penalties = @{ $patron->standing_penalties };
738
739 if ( $patron->deleted eq 't' ) {
740 do_lookup_user_error_stanza("PATRON_DELETED : $uidValue");
741 die;
742 } elsif ( $patron->barred eq 't' ) {
743 do_lookup_user_error_stanza("PATRON_BARRED : $uidValue");
744 die;
745 } elsif ( $patron->active eq 'f' ) {
746 do_lookup_user_error_stanza("PATRON_INACTIVE : $uidValue");
747 die;
748 }
749
750 elsif ( $#penalties > -1 ) {
751
752# my $penalty;
753# foreach $penalty (@penalties) {
754# if (defined($penalty->standing_penalty->block_list)) {
755# my @block_list = split(/\|/, $penalty->standing_penalty->block_list);
756# foreach my $block (@block_list) {
757# foreach my $block_on (@$block_types) {
758# if ($block eq $block_on) {
759# $block_stanza .= "\n".$penalty->standing_penalty->name;
760# $patron_ok = 0;
761# }
762# last unless ($patron_ok);
763# }
764# last unless ($patron_ok);
765# }
766# }
767# }
768 $block_stanza = qq(
769 <BlockOrTrap>
770 <UniqueAgencyId>
771 <Scheme datatype="string">http://just.testing.now</Scheme>
772 <Value datatype="string">$faidValue</Value>
773 </UniqueAgencyId>
774 <BlockOrTrapType>
775 <Scheme datatype="string">http://just.testing.now</Scheme>
776 <Value datatype="string">Block Hold</Value>
777 </BlockOrTrapType>
778 </BlockOrTrap>);
779 }
780
781 if ( defined( $patron->email ) ) {
782 $email = qq(
783 <UserAddressInformation>
784 <ElectronicAddress>
785 <ElectronicAddressType>
786 <Scheme datatype="string">http://testing.now</Scheme>
787 <Value datatype="string">mailto</Value>
788 </ElectronicAddressType>
789 <ElectronicAddressData datatype="string">)
790 . HTML::Entities::encode( $patron->email )
791 . qq(</ElectronicAddressData>
792 </ElectronicAddress>
793 </UserAddressInformation>);
794 }
795
796 $propername = $patron->first_given_name . " " . $patron->family_name;
797 $good_until = $patron->expire_date || "unknown";
798 $userprivid = $patron->profile;
799 my $userou = $patron->home_ou->name;
800 my $userpriv = $patron->profile->name;
801
802 #} else {
803 # do_lookup_user_error_stanza("PATRON_NOT_FOUND : $id");
804 # die;
805 #}
0b0c5299
DW
806 my $uniqid = $patron->id;
807 my $visid = $patron->card->barcode;
5f517e0a 808 my $hd = <<LOOKUPUSERRESPONSE;
4cdc4f67
JS
809Content-type: text/xml
810
811
812<!DOCTYPE NCIPMessage PUBLIC "-//NISO//NCIP DTD Version 1.0//EN" "http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
813<NCIPMessage version="http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
5f517e0a
DW
814 <LookupUserResponse>
815 <ResponseHeader>
816 <FromAgencyId>
817 <UniqueAgencyId>
818 <Scheme>$taidScheme</Scheme>
819 <Value>$taidValue</Value>
820 </UniqueAgencyId>
821 </FromAgencyId>
822 <ToAgencyId>
823 <UniqueAgencyId>
824 <Scheme>$faidScheme</Scheme>
825 <Value>$faidValue</Value>
826 </UniqueAgencyId>
827 </ToAgencyId>
828 </ResponseHeader>
829 <UniqueUserId>
830 <UniqueAgencyId>
831 <Scheme>$taidScheme</Scheme>
832 <Value>$taidValue</Value>
833 </UniqueAgencyId>
0b0c5299 834 <UserIdentifierValue>$uniqid</UserIdentifierValue>
5f517e0a
DW
835 </UniqueUserId>
836 <UserOptionalFields>
837 <VisibleUserId>
838 <VisibleUserIdentifierType>
839 <Scheme datatype="string">http://blah.com</Scheme>
840 <Value datatype="string">Barcode</Value>
841 </VisibleUserIdentifierType>
0b0c5299 842 <VisibleUserIdentifier datatype="string">$visid</VisibleUserIdentifier>
5f517e0a
DW
843 </VisibleUserId>
844 <NameInformation>
845 <PersonalNameInformation>
846 <UnstructuredPersonalUserName datatype="string">$propername</UnstructuredPersonalUserName>
847 </PersonalNameInformation>
848 </NameInformation>
849 <UserPrivilege>
850 <UniqueAgencyId>
851 <Scheme datatype="string">$faidScheme</Scheme>
852 <Value datatype="string">$faidValue</Value>
853 </UniqueAgencyId>
854 <AgencyUserPrivilegeType>
855 <Scheme datatype="string">http://testing.purposes.only</Scheme>
0b0c5299 856 <Value datatype="string">$userprivid</Value>
5f517e0a
DW
857 </AgencyUserPrivilegeType>
858 <ValidToDate datatype="string">$good_until</ValidToDate>
859 </UserPrivilege> $email $block_stanza
860 </UserOptionalFields>
4cdc4f67
JS
861 </LookupUserResponse>
862</NCIPMessage>
863
864LOOKUPUSERRESPONSE
865
5f517e0a
DW
866 logit( $hd, ( caller(0) )[3] );
867 staff_log( $taidValue, $faidValue,
868 "LookupUser -> Patron Barcode : "
869 . $id
870 . " | Patron Id : "
871 . $uidValue
872 . " | User Name : "
873 . $propername
874 . " | User Priv : "
875 . $userpriv );
4cdc4f67
JS
876}
877
4cdc4f67 878sub fail {
5f517e0a
DW
879 my $error_msg =
880 shift || "THIS IS THE DEFAULT / DO NOT HANG III NCIP RESP MSG";
881 print "Content-type: text/xml\n\n";
4cdc4f67 882
5f517e0a 883 print <<ITEMREQ;
4cdc4f67
JS
884<!DOCTYPE NCIPMessage PUBLIC "-//NISO//NCIP DTD Version 1.0//EN" "http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
885<NCIPMessage version="http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
5f517e0a
DW
886 <ItemRequestedResponse>
887 <ResponseHeader>
888 <FromAgencyId>
889 <UniqueAgencyId>
890 <Scheme>http://136.181.125.166:6601/IRCIRCD?target=get_scheme_values&amp;scheme=UniqueAgencyId</Scheme>
891 <Value></Value>
892 </UniqueAgencyId>
893 </FromAgencyId>
894 <ToAgencyId>
895 <UniqueAgencyId>
896 <Scheme>http://136.181.125.166:6601/IRCIRCD?target=get_scheme_values&amp;scheme=UniqueAgencyId</Scheme>
897 <Value>$error_msg</Value>
898 </UniqueAgencyId>
899 </ToAgencyId>
900 </ResponseHeader>
901 </ItemRequestedResponse>
4cdc4f67
JS
902</NCIPMessage>
903
904ITEMREQ
6e6bdfe9 905
601be0bb
JG
906 # XXX: we should log FromAgencyId and ToAgencyId values here, but they are not available to the code at this point
907 staff_log( '', '',
5f517e0a
DW
908 ( ( caller(0) )[3] . " -> " . $error_msg ) );
909 die;
4cdc4f67
JS
910}
911
912sub do_lookup_user_error_stanza {
913
601be0bb 914 # XXX: we should include FromAgencyId and ToAgencyId values, but they are not available to the code at this point
5f517e0a
DW
915 my $error = shift;
916 my $hd = <<LOOKUPPROB;
4cdc4f67
JS
917Content-type: text/xml
918
919
920<!DOCTYPE NCIPMessage PUBLIC "-//NISO//NCIP DTD Version 1.0//EN" "http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
921<NCIPMessage version="http://www.niso.org/ncip/v1_0/imp1/dtd/ncip_v1_0.dtd">
5f517e0a
DW
922 <LookupUserResponse>
923 <ResponseHeader>
924 <FromAgencyId>
925 <UniqueAgencyId>
601be0bb
JG
926 <Scheme></Scheme>
927 <Value></Value>
5f517e0a
DW
928 </UniqueAgencyId>
929 </FromAgencyId>
930 <ToAgencyId>
931 <UniqueAgencyId>
601be0bb
JG
932 <Scheme></Scheme>
933 <Value></Value>
5f517e0a
DW
934 </UniqueAgencyId>
935 </ToAgencyId>
936 </ResponseHeader>
937 <Problem>
938 <ProcessingError>
939 <ProcessingErrorType>
940 <Scheme>http://www.niso.org/ncip/v1_0/schemes/processingerrortype/lookupuserprocessingerror.scm</Scheme>
941 <Value>$error</Value>
942 </ProcessingErrorType>
943 <ProcessingErrorElement>
944 <ElementName>AuthenticationInput</ElementName>
945 </ProcessingErrorElement>
946 </ProcessingError>
947 </Problem>
948 </LookupUserResponse>
4cdc4f67
JS
949</NCIPMessage>
950
951LOOKUPPROB
952
5f517e0a 953 logit( $hd, ( caller(0) )[3] );
601be0bb
JG
954 # XXX: we should log FromAgencyId and ToAgencyId values here, but they are not available to the code at this point
955 staff_log( '', '', ( ( caller(0) )[3] . " -> " . $error ) );
5f517e0a 956 die;
4cdc4f67
JS
957}
958
959# Login to the OpenSRF system/Evergreen.
960#
961# Returns a hash with the authtoken, authtime, and expiration (time in
962# seconds since 1/1/1970).
963sub login {
1ac548f2
JS
964
965 # XXX: local opensrf core conf filename should be in config.
966 # XXX: STAFF account with ncip service related permissions should be in config.
5f517e0a
DW
967 my $bootstrap = '/openils/conf/opensrf_core.xml';
968 my $uname = "STAFF_EQUIVALENT_USERNAME_HERE";
969 my $password = "STAFF_EQUIVALENT_PASSWORD";
970
971 # Bootstrap the client
972 OpenSRF::System->bootstrap_client( config_file => $bootstrap );
973 my $idl = OpenSRF::Utils::SettingsClient->new->config_value("IDL");
974 Fieldmapper->import( IDL => $idl );
975
976 # Initialize CStoreEditor:
977 OpenILS::Utils::CStoreEditor->init;
978
979 my $seed = OpenSRF::AppSession->create('open-ils.auth')
980 ->request( 'open-ils.auth.authenticate.init', $uname )->gather(1);
981
982 return undef unless $seed;
983
984 my $response = OpenSRF::AppSession->create('open-ils.auth')->request(
985 'open-ils.auth.authenticate.complete',
986 {
987 username => $uname,
988 password => md5_hex( $seed . md5_hex($password) ),
989 type => 'staff'
990 }
991 )->gather(1);
992
993 return undef unless $response;
994
995 my %result;
996 $result{'authtoken'} = $response->{payload}->{authtoken};
997 $result{'authtime'} = $response->{payload}->{authtime};
998 $result{'expiration'} = time() + $result{'authtime'}
999 if ( defined( $result{'authtime'} ) );
1000 return %result;
4cdc4f67
JS
1001}
1002
1003# Check the time versus the session expiration time and login again if
1004# the session has expired, consequently resetting the session
1005# paramters. We want to run this before doing anything that requires
1006# us to have a current session in OpenSRF.
1007#
1008# Arguments
1009# none
1010#
1011# Returns
1012# Nothing
1013sub check_session_time {
5f517e0a
DW
1014 if ( time() > $session{'expiration'} ) {
1015 %session = login();
1016 if ( !%session ) {
1017 die("Failed to reinitialize the session after expiration.");
1018 }
1019 }
4cdc4f67
JS
1020}
1021
1022# Retrieve the logged in user.
1023#
1024sub get_session {
5f517e0a
DW
1025 my $response =
1026 OpenSRF::AppSession->create('open-ils.auth')
1027 ->request( 'open-ils.auth.session.retrieve', $session{authtoken} )
1028 ->gather(1);
1029 return $response;
4cdc4f67
JS
1030}
1031
1032# Logout/destroy the OpenSRF session
1033#
1034# Argument is
1035# none
1036#
1037# Returns
1038# Does not return anything
1039sub logout {
5f517e0a
DW
1040 if ( time() < $session{'expiration'} ) {
1041 my $response =
1042 OpenSRF::AppSession->create('open-ils.auth')
1043 ->request( 'open-ils.auth.session.delete', $session{authtoken} )
1044 ->gather(1);
1045 if ($response) {
1046
1047 # strong.silent.success
1048 exit(0);
1049 } else {
1050 fail("Logout unsuccessful. Good-bye, anyway.");
1051 }
1052 }
4cdc4f67
JS
1053}
1054
1055sub update_copy {
5f517e0a
DW
1056 check_session_time();
1057 my ( $copy, $status_id ) = @_;
1058 my $e = new_editor( authtoken => $session{authtoken} );
1059 return $e->event->{textcode} unless ( $e->checkauth );
1060 $e->xact_begin;
1061 $copy->status($status_id);
1062 return $e->event unless $e->update_asset_copy($copy);
1063 $e->commit;
1064 return 'SUCCESS';
4cdc4f67
JS
1065}
1066
1067# my paranoia re barcode on shipped items using visid for unique value
1068sub update_copy_shipped {
5f517e0a
DW
1069 check_session_time();
1070 my ( $copy, $status_id, $barcode ) = @_;
1071 my $e = new_editor( authtoken => $session{authtoken} );
1072 return $e->event->{textcode} unless ( $e->checkauth );
1073 $e->xact_begin;
1074 $copy->status($status_id);
1075 $copy->barcode($barcode);
1076 return $e->event unless $e->update_asset_copy($copy);
1077 $e->commit;
1078 return 'SUCCESS';
4cdc4f67
JS
1079}
1080
1081# Delete a copy
1082#
1083# Argument
1084# Fieldmapper asset.copy object
1085#
1086# Returns
1087# "SUCCESS" on success
1088# Event textcode if an error occurs
1089sub delete_copy {
5f517e0a
DW
1090 check_session_time();
1091 my ($copy) = @_;
1092
1093 my $e = new_editor( authtoken => $session{authtoken} );
1094 return $e->event->{textcode} unless ( $e->checkauth );
1095
1096 # Get the calnumber
1097 my $vol = $e->retrieve_asset_call_number( $copy->call_number );
1098 return $e->event->{textcode} unless ($vol);
1099
1100 # Get the biblio.record_entry
1101 my $bre = $e->retrieve_biblio_record_entry( $vol->record );
1102 return $e->event->{textcode} unless ($bre);
1103
1104 # Delete everything in a transaction and rollback if anything fails.
0b0c5299 1105 # TODO: I think there is a utility function which handles all this
5f517e0a
DW
1106 $e->xact_begin;
1107 my $r; # To hold results of editor calls
1108 $r = $e->delete_asset_copy($copy);
1109 unless ($r) {
1110 my $lval = $e->event->{textcode};
1111 $e->rollback;
1112 return $lval;
1113 }
1114 my $list =
1115 $e->search_asset_copy( { call_number => $vol->id, deleted => 'f' } );
1116 unless (@$list) {
1117 $r = $e->delete_asset_call_number($vol);
1118 unless ($r) {
1119 my $lval = $e->event->{textcode};
1120 $e->rollback;
1121 return $lval;
1122 }
0b0c5299 1123 $list = $e->search_asset_call_number( { record => $bre->id, deleted => 'f' } );
5f517e0a 1124 unless (@$list) {
0b0c5299 1125 $r = $e->delete_biblio_record_entry($bre);
5f517e0a
DW
1126 unless ($r) {
1127 my $lval = $e->event->{textcode};
1128 $e->rollback;
1129 return $lval;
1130 }
1131 }
1132 }
1133 $e->commit;
1134 return 'SUCCESS';
4cdc4f67
JS
1135}
1136
1137# Get asset.copy from asset.copy.barcode.
1138# Arguments
1139# copy barcode
1140#
1141# Returns
1142# asset.copy fieldmaper object
1143# or hash on error
1144sub copy_from_barcode {
5f517e0a
DW
1145 check_session_time();
1146 my ($barcode) = @_;
1147 my $response =
1148 OpenSRF::AppSession->create('open-ils.search')
1149 ->request( 'open-ils.search.asset.copy.find_by_barcode', $barcode )
1150 ->gather(1);
1151 return $response;
4cdc4f67
JS
1152}
1153
1154sub locid_from_barcode {
5f517e0a
DW
1155 my ($barcode) = @_;
1156 my $response =
1157 OpenSRF::AppSession->create('open-ils.search')
1158 ->request( 'open-ils.search.biblio.find_by_barcode', $barcode )
1159 ->gather(1);
1160 return $response->{ids}[0];
4cdc4f67
JS
1161}
1162
1163# Convert a MARC::Record to XML for Evergreen
1164#
6e6bdfe9 1165# Copied from Dyrcona's issa framework which copied
1ac548f2 1166# it from MVLC's Safari Load program which copied it
4cdc4f67
JS
1167# from some code in the Open-ILS example import scripts.
1168#
1169# Argument
1170# A MARC::Record object
1171#
1172# Returns
1173# String with XML for the MARC::Record as Evergreen likes it
1174sub convert2marcxml {
5f517e0a
DW
1175 my $input = shift;
1176 ( my $xml = $input->as_xml_record() ) =~ s/\n//sog;
1177 $xml =~ s/^<\?xml.+\?\s*>//go;
1178 $xml =~ s/>\s+</></go;
1179 $xml =~ s/\p{Cc}//go;
0b0c5299 1180 $xml = $U->entityize($xml);
5f517e0a
DW
1181 $xml =~ s/[\x00-\x1f]//go;
1182 return $xml;
4cdc4f67
JS
1183}
1184
1185# Create a copy and marc record
1186#
1187# Arguments
1188# title
1189# call number
1190# copy barcode
1191#
1192# Returns
1193# bib id on succes
1194# event textcode on failure
1195sub create_copy {
5f517e0a
DW
1196 check_session_time();
1197 my ( $title, $callnumber, $barcode, $copy_status_id, $medium_type ) = @_;
4cdc4f67 1198
5f517e0a
DW
1199 my $e = new_editor( authtoken => $session{authtoken} );
1200 return $e->event->{textcode} unless ( $e->checkauth );
1ac548f2 1201
5f517e0a
DW
1202 my $r = $e->allowed( [ 'CREATE_COPY', 'CREATE_MARC', 'CREATE_VOLUME' ] );
1203 if ( ref($r) eq 'HASH' ) {
1204 return $r->{textcode} . ' ' . $r->{ilsperm};
1205 }
4cdc4f67 1206
5f517e0a
DW
1207 # Check if the barcode exists in asset.copy and bail if it does.
1208 my $list = $e->search_asset_copy( { deleted => 'f', barcode => $barcode } );
1209 if (@$list) {
6e6bdfe9 1210# in the future, can we update it, if it exists and only if it is an INN-Reach status item ?
5f517e0a
DW
1211 $e->finish;
1212 fail( 'BARCODE_EXISTS ! Barcode : ' . $barcode );
1213 die;
1214 }
1215
1216 # Create MARC record
1217 my $record = MARC::Record->new();
1218 $record->encoding('UTF-8');
1219 $record->leader('00881nam a2200193 4500');
1220 my $datespec = strftime( "%Y%m%d%H%M%S.0", localtime );
1221 my @fields = ();
1222 push( @fields, MARC::Field->new( '005', $datespec ) );
1223 push( @fields, MARC::Field->new( '082', '0', '4', 'a' => $callnumber ) );
1224 push( @fields, MARC::Field->new( '245', '0', '0', 'a' => $title ) );
1225 $record->append_fields(@fields);
1226
1227 # Convert the record to XML
1228 my $xml = convert2marcxml($record);
1229
1230 my $bre =
1231 OpenSRF::AppSession->create('open-ils.cat')
1232 ->request( 'open-ils.cat.biblio.record.xml.import',
1233 $session{authtoken}, $xml, 'System Local', 1 )->gather(1);
1234 return $bre->{textcode} if ( ref($bre) eq 'HASH' );
1235
1236 # Create volume record
1237 my $vol =
1238 OpenSRF::AppSession->create('open-ils.cat')
0b0c5299
DW
1239 ->request( 'open-ils.cat.call_number.find_or_create', $session{authtoken}, $callnumber, $bre->id, 2 ) # XXX CUSTOMIZATION NEEDED XXX
1240 ->gather(1);
5f517e0a
DW
1241 return $vol->{textcode} if ( $vol->{textcode} );
1242
1243 # Retrieve the user
1244 my $user = get_session;
1245
1246 # Create copy record
1247 my $copy = Fieldmapper::asset::copy->new();
0b0c5299
DW
1248 # XXX CUSTOMIZATION NEEDED XXX
1249 # You will need to either create a circ mod for every expected medium type,
1250 # OR you should create a single circ mod for all requests from the external
1251 # system.
1252 # Adjust these lines as needed.
1253 # $copy->circ_modifier(qq($medium_type)); # XXX CUSTOMIZATION NEEDED XXX
1254 # OR
1255 $copy->circ_modifier('DCB'); # XXX CUSTOMIZATION NEEDED XXX
5f517e0a
DW
1256 $copy->barcode($barcode);
1257 $copy->call_number( $vol->{acn_id} );
0b0c5299 1258 $copy->circ_lib(2); # XXX CUSTOMIZATION NEEDED XXX
5f517e0a
DW
1259 $copy->circulate('t');
1260 $copy->holdable('t');
1261 $copy->opac_visible('t');
1262 $copy->deleted('f');
1263 $copy->fine_level(2);
1264 $copy->loan_duration(2);
0b0c5299 1265 $copy->location(156); # XXX CUSTOMIZATION NEEDED XXX
5f517e0a
DW
1266 $copy->status($copy_status_id);
1267 $copy->editor('1');
1268 $copy->creator('1');
1269
1270 # Add the configured stat cat entries.
1271 #my @stat_cats;
1272 #my $nodes = $xpath->find("/copy/stat_cat_entry");
1273 #foreach my $node ($nodes->get_nodelist) {
1274 # next unless ($node->isa('XML::XPath::Node::Element'));
1275 # my $stat_cat_id = $node->getAttribute('stat_cat');
1276 # my $value = $node->string_value();
1277 # # Need to search for an existing asset.stat_cat_entry
0b0c5299 1278 # my $asce = $e->search_asset_stat_cat_entry({'stat_cat' => $stat_cat_id, 'value' => $value})->[0];
5f517e0a
DW
1279 # unless ($asce) {
1280 # # if not, create a new one and use its id.
1281 # $asce = Fieldmapper::asset::stat_cat_entry->new();
1282 # $asce->stat_cat($stat_cat_id);
1283 # $asce->value($value);
1284 # $asce->owner($ou->id);
1285 # $e->xact_begin;
1286 # $asce = $e->create_asset_stat_cat_entry($asce);
1287 # $e->xact_commit;
1288 # }
1289 # push(@stat_cats, $asce);
1290 #}
1291
1292 $e->xact_begin;
1293 $copy = $e->create_asset_copy($copy);
1294
1295 #if (scalar @stat_cats) {
1296 # foreach my $asce (@stat_cats) {
1297 # my $ascecm = Fieldmapper::asset::stat_cat_entry_copy_map->new();
1298 # $ascecm->stat_cat($asce->stat_cat);
1299 # $ascecm->stat_cat_entry($asce->id);
1300 # $ascecm->owning_copy($copy->id);
1301 # $ascecm = $e->create_asset_stat_cat_entry_copy_map($ascecm);
1302 # }
1303 #}
1304 $e->commit;
1305 return $e->event->{textcode} unless ($r);
1306 return 'SUCCESS';
4cdc4f67
JS
1307}
1308
1309# Checkout a copy to a patron
1310#
1311# Arguments
1312# copy barcode
1313# patron barcode
1314#
1315# Returns
1316# textcode of the OSRF response.
1ac548f2 1317sub checkout {
5f517e0a
DW
1318 check_session_time();
1319 my ( $copy_barcode, $patron_barcode, $due_date ) = @_;
1320
1321 # Check for copy:
1322 my $copy = copy_from_barcode($copy_barcode);
1323 unless ( defined($copy) && blessed($copy) ) {
1324 return 'COPY_BARCODE_NOT_FOUND : ' . $copy_barcode;
1325 }
1326
1327 # Check for user
1328 my $uid = user_id_from_barcode($patron_barcode);
1329 return 'PATRON_BARCODE_NOT_FOUND : ' . $patron_barcode if ( ref($uid) );
1330
1331 my $response = OpenSRF::AppSession->create('open-ils.circ')->request(
1332 'open-ils.circ.checkout.full.override',
1333 $session{authtoken},
1334 {
1335 copy_barcode => $copy_barcode,
1336 patron_id => $uid,
1337 due_date => $due_date
1338 }
1339 )->gather(1);
1340 return $response->{textcode};
4cdc4f67
JS
1341}
1342
1ac548f2 1343sub renewal {
5f517e0a
DW
1344 check_session_time();
1345 my ( $copy_barcode, $due_date ) = @_;
1346
1347 # Check for copy:
1348 my $copy = copy_from_barcode($copy_barcode);
1349 unless ( defined($copy) && blessed($copy) ) {
1350 return 'COPY_BARCODE_NOT_FOUND : ' . $copy_barcode;
1351 }
1352
1353 my $response = OpenSRF::AppSession->create('open-ils.circ')->request(
1354 'open-ils.circ.renew.override',
1355 $session{authtoken},
1356 {
1357 copy_barcode => $copy_barcode,
1358 due_date => $due_date
1359 }
1360 )->gather(1);
1361 return $response->{textcode};
4cdc4f67
JS
1362}
1363
1ac548f2 1364# Check a copy in
4cdc4f67
JS
1365#
1366# Arguments
1367# copy barcode
4cdc4f67
JS
1368#
1369# Returns
1370# "SUCCESS" on success
1371# textcode of a failed OSRF request
0b0c5299 1372# 'COPY_NOT_CHECKED_OUT' when the copy is not checked out
6e6bdfe9 1373
1ac548f2 1374sub checkin {
5f517e0a
DW
1375 check_session_time();
1376 my ($barcode) = @_;
1377
1378 my $copy = copy_from_barcode($barcode);
1379 return $copy->{textcode} unless ( blessed $copy);
1380
1381 return ("COPY_NOT_CHECKED_OUT $barcode")
1382 unless ( $copy->status == OILS_COPY_STATUS_CHECKED_OUT );
1383
1384 my $e = new_editor( authtoken => $session{authtoken} );
1385 return $e->event->{textcode} unless ( $e->checkauth );
1386
1387 my $circ = $e->search_action_circulation(
1388 [ { target_copy => $copy->id, xact_finish => undef } ] )->[0];
1389 my $r =
1390 OpenSRF::AppSession->create('open-ils.circ')
1391 ->request( 'open-ils.circ.checkin.override',
1392 $session{authtoken}, { force => 1, copy_id => $copy->id } )->gather(1);
1393 return 'SUCCESS' if ( $r->{textcode} eq 'ROUTE_ITEM' );
1394 return $r->{textcode};
4cdc4f67
JS
1395}
1396
1397# Get actor.usr.id from barcode.
1398# Arguments
1399# patron barcode
1400#
1401# Returns
1402# actor.usr.id
1403# or hash on error
1404sub user_id_from_barcode {
5f517e0a
DW
1405 check_session_time();
1406 my ($barcode) = @_;
4cdc4f67 1407
5f517e0a 1408 my $response;
4cdc4f67 1409
5f517e0a
DW
1410 my $e = new_editor( authtoken => $session{authtoken} );
1411 return $response unless ( $e->checkauth );
4cdc4f67 1412
5f517e0a
DW
1413 my $card = $e->search_actor_card( { barcode => $barcode, active => 't' } );
1414 return $e->event unless ($card);
4cdc4f67 1415
5f517e0a 1416 $response = $card->[0]->usr if (@$card);
4cdc4f67 1417
5f517e0a 1418 $e->finish;
4cdc4f67 1419
5f517e0a 1420 return $response;
4cdc4f67
JS
1421}
1422
6e6bdfe9 1423# Place a simple hold for a patron.
4cdc4f67
JS
1424#
1425# Arguments
1426# Target object appropriate for type of hold
1427# Patron for whom the hold is place
1428#
1429# Returns
1430# "SUCCESS" on success
1431# textcode of a failed OSRF request
1432# "HOLD_TYPE_NOT_SUPPORTED" if the hold type is not supported
1433# (Currently only support 'T' and 'C')
1434
1ac548f2 1435# simple hold should be removed and full holds sub should be used instead - pragmatic solution only
5082b884 1436
4cdc4f67 1437sub place_simple_hold {
5f517e0a 1438 check_session_time();
1ac548f2 1439
5f517e0a 1440 #my ($type, $target, $patron, $pickup_ou) = @_;
7e2d6432 1441 my ( $target, $patron_id ) = @_;
1ac548f2 1442
5f517e0a 1443 # NOTE : switch "t" to an "f" to make inactive hold active
7e2d6432 1444 require '/openils/bin/oils_header.pl'; # XXX CUSTOMIZATION NEEDED XXX
5f517e0a 1445 use vars qw/ $apputils $memcache $user $authtoken $authtime /;
1ac548f2
JS
1446
1447 # XXX: local opensrf core conf filename should be in config.
1448 # XXX: STAFF account with ncip service related permissions should be in config.
5f517e0a
DW
1449 osrf_connect("/openils/conf/opensrf_core.xml");
1450 oils_login( "STAFF_EQUIVALENT_USERNAME", "STAFF_EQUIVALENT_PASSWORD" );
7e2d6432
DW
1451 my $ahr = Fieldmapper::action::hold_request->new();
1452 $ahr->hold_type('C');
1453 # The targeter doesn't like our special statuses, and changing the status after the targeter finishes is difficult because it runs asynchronously. Our workaround is to create the hold frozen, unfreeze it, then run the targeter manually.
1454 $ahr->target($target);
1455 $ahr->usr($patron_id);
1456 $ahr->requestor(1); # XXX CUSTOMIZATION NEEDED XXX admin user (?)
1457 $ahr->pickup_lib(2); # XXX CUSTOMIZATION NEEDED XXX script user OU
1458 $ahr->phone_notify('');
1459 $ahr->email_notify(1);
1460 $ahr->frozen('t');
1461 my $resp = simplereq( CIRC(), 'open-ils.circ.holds.create', $authtoken, $ahr );
1462 my $e = new_editor( xact => 1, authtoken => $session{authtoken} );
1463 $ahr = $e->retrieve_action_hold_request($resp); # refresh from db
1464 $ahr->frozen('f');
1465 $e->update_action_hold_request($ahr);
1466 $e->commit;
1467 $U->storagereq( 'open-ils.storage.action.hold_request.copy_targeter', undef, $ahr->id );
5f517e0a
DW
1468
1469 #oils_event_die($resp);
1470 my $errors = "";
1471 if ( ref($resp) eq 'ARRAY' ) {
1472 ( $errors .= "error : " . $_->{textcode} ) for @$resp;
1473 return $errors;
1474 } elsif ( ref($resp) ne 'HASH' ) {
1475 return "Hold placed! hold_id = " . $resp . "\n";
1476 }
4cdc4f67
JS
1477}
1478
1479# Place a hold for a patron.
1480#
1481# Arguments
1482# Type of hold
1483# Target object appropriate for type of hold
1484# Patron for whom the hold is place
1485# OU where hold is to be picked up
1486#
1487# Returns
1488# "SUCCESS" on success
1489# textcode of a failed OSRF request
1490# "HOLD_TYPE_NOT_SUPPORTED" if the hold type is not supported
1491# (Currently only support 'T' and 'C')
877ae895
DW
1492# XXX NOT USED OR WORKING, COMMENTING OUT FOR NOW
1493#sub place_hold {
1494# check_session_time();
1495# my ( $type, $target, $patron, $pickup_ou ) = @_;
1496#
1497# my $ou = org_unit_from_shortname($work_ou); # $work_ou is global
1498# my $ahr = Fieldmapper::action::hold_request->new;
1499# $ahr->hold_type($type);
1500# if ( $type eq 'C' ) {
1501#
1502# # Check if we own the copy.
1503# if ( $ou->id == $target->circ_lib ) {
1504#
1505# # We own it, so let's place a copy hold.
1506# $ahr->target( $target->id );
1507# $ahr->current_copy( $target->id );
1508# } else {
1509#
1510# # We don't own it, so let's place a title hold instead.
1511# my $bib = bre_from_barcode( $target->barcode );
1512# $ahr->target( $bib->id );
1513# $ahr->hold_type('T');
1514# }
1515# } elsif ( $type eq 'T' ) {
1516# $ahr->target($target);
1517# } else {
1518# return "HOLD_TYPE_NOT_SUPPORTED";
1519# }
1520# $ahr->usr( user_id_from_barcode($id) );
1521#
1522# #$ahr->pickup_lib($pickup_ou->id);
1523# $ahr->pickup_lib('3');
1524# if ( !$patron->email ) {
1525# $ahr->email_notify('f');
1526# $ahr->phone_notify( $patron->day_phone ) if ( $patron->day_phone );
1527# } else {
1528# $ahr->email_notify('t');
1529# }
1530#
1531# # We must have a title hold and we want to change the hold
1532# # expiration date if we're sending the copy to the VC.
1533# set_title_hold_expiration($ahr) if ( $ahr->pickup_lib == $ou->id );
1534#
1535# my $params = {
1536# pickup_lib => $ahr->pickup_lib,
1537# patronid => $ahr->usr,
1538# hold_type => $ahr->hold_type
1539# };
1540#
1541# if ( $ahr->hold_type eq 'C' ) {
1542# $params->{copy_id} = $ahr->target;
1543# } else {
1544# $params->{titleid} = $ahr->target;
1545# }
1546#
1547# my $r =
1548# OpenSRF::AppSession->create('open-ils.circ')
1549# ->request( 'open-ils.circ.title_hold.is_possible',
1550# $session{authtoken}, $params )->gather(1);
1551#
1552# if ( $r->{textcode} ) {
1553# return $r->{textcode};
1554# } elsif ( $r->{success} ) {
1555# $r =
1556# OpenSRF::AppSession->create('open-ils.circ')
1557# ->request( 'open-ils.circ.holds.create.override',
1558# $session{authtoken}, $ahr )->gather(1);
1559#
1560# my $returnValue = "SUCCESS";
1561# if ( ref($r) eq 'HASH' ) {
1562# $returnValue =
1563# ( $r->{textcode} eq 'PERM_FAILURE' )
1564# ? $r->{ilsperm}
1565# : $r->{textcode};
1566# $returnValue =~ s/\.override$//
1567# if ( $r->{textcode} eq 'PERM_FAILURE' );
1568# }
1569# return $returnValue;
1570# } else {
1571# return 'HOLD_NOT_POSSIBLE';
1572# }
1573#}
4cdc4f67
JS
1574
1575# Set the expiration date on title holds
1576#
1577# Argument
1578# Fieldmapper action.hold_request object
1579#
1580# Returns
1581# Nothing
877ae895
DW
1582# XXX NOT USED OR WORKING, COMMENTING OUT FOR NOW
1583#sub set_title_hold_expiration {
1584# my $hold = shift;
1585# if ( $title_holds->{unit} && $title_holds->{duration} ) {
1586# my $expiration = DateTime->now( time_zone => $tz );
1587# $expiration->add( $title_holds->{unit} => $title_holds->{duration} );
1588# $hold->expire_time( $expiration->iso8601() );
1589# }
1590#}
4cdc4f67
JS
1591
1592# Get actor.org_unit from the shortname
1593#
1594# Arguments
1595# org_unit shortname
1596#
1597# Returns
1598# Fieldmapper aou object
1599# or HASH on error
1600sub org_unit_from_shortname {
5f517e0a
DW
1601 check_session_time();
1602 my ($shortname) = @_;
1603 my $ou =
1604 OpenSRF::AppSession->create('open-ils.actor')
1605 ->request( 'open-ils.actor.org_unit.retrieve_by_shortname', $shortname )
1606 ->gather(1);
1607 return $ou;
4cdc4f67
JS
1608}
1609
1610# Flesh user information
1611# Arguments
1612# actor.usr.id
1613#
1614# Returns
1615# fieldmapped, fleshed user or
1616# event hash on error
1617sub flesh_user {
5f517e0a
DW
1618 check_session_time();
1619 my ($id) = @_;
1620 my $response =
1621 OpenSRF::AppSession->create('open-ils.actor')
1622 ->request( 'open-ils.actor.user.fleshed.retrieve',
1623 $session{'authtoken'}, $id,
1624 [ 'card', 'cards', 'standing_penalties', 'home_ou', 'profile' ] )
1625 ->gather(1);
1626 return $response;
4cdc4f67 1627}