LP 1694058: Perl tests for backend multiple hold placement changes.
[Evergreen.git] / Open-ILS / src / perlmods / live_t / 25-lp1694058-multiple-hold-placement.t
1 #!perl
2 use strict; use warnings;
3 use Test::More tests => 30;
4 use OpenILS::Utils::TestUtils;
5 use OpenILS::Const qw(:const);
6
7 diag("Test LP 1694058 multiple hold placement.");
8
9 my $script = OpenILS::Utils::TestUtils->new();
10 my $U = 'OpenILS::Application::AppUtils';
11
12 use constant {
13     BR1_WORKSTATION => 'BR1-test-lp1694058-multiple-hold-placement.t',
14     BR1_ID => 4,
15     BR2_ID => 5,
16     PATRON1_BARCODE => '99999376864',
17     PATRON2_BARCODE => '99999342948',
18     RECORD_ID => 3,
19     METARECORD_ID => 13,
20     COPY_ID => 2503,
21 };
22
23 # Because this may run multiple times, without a DB reload, we search
24 # for the workstation before registering it.  Takes an authtoken, the
25 # id of the workstation lib, and the name of the workstation.
26 sub find_or_register_workstation {
27     my ($authtoken, $lib, $workstation) = @_;
28     my $ws;
29     my $r = $U->simplereq(
30         'open-ils.actor',
31         'open-ils.actor.workstation.list',
32         $authtoken,
33         $lib
34     );
35     if ($r && $r->{$lib}) {
36         $ws = grep {$_->name() eq $workstation} @{$r->{$lib}};
37     }
38     unless ($ws) {
39         $ws = $script->register_workstation($workstation, $lib);
40     }
41     return $ws;
42 }
43
44
45 # Keep track of hold ids, so we can cancel them later.
46 my @holds = ();
47
48 # Login as admin at BR1.
49 my $authtoken = $script->authenticate({
50     username=>'admin',
51     password=>'demo123',
52     type=>'staff'
53 });
54 ok(
55     $script->authtoken,
56     'Have an authtoken'
57 );
58
59 # Register workstation.
60 my $ws = find_or_register_workstation($authtoken, BR1_ID, BR1_WORKSTATION);
61 ok(
62     ! ref $ws,
63     'Found or registered workstation'
64 );
65
66 # Logout.
67 $script->logout();
68 ok(
69     ! $script->authtoken,
70     'Successfully logged out'
71 );
72
73 # Login as admin at BR1 using the workstation.
74 $authtoken = $script->authenticate({
75     username=>'admin',
76     password=>'demo123',
77     type=>'staff',
78     workstation => BR1_WORKSTATION
79 });
80 ok(
81     $script->authtoken,
82     'Have an authtoken'
83 );
84
85 # Check that OILS_SETTING_MAX_DUPLICATE_HOLDS is not set at BR1 and ancestors.
86 my $setting_value = $U->ou_ancestor_setting_value(BR1_ID, OILS_SETTING_MAX_DUPLICATE_HOLDS);
87 ok(
88     ! $setting_value,
89     'circ.holds.max_duplicate_holds is not set for BR1'
90 );
91
92 # Check that OILS_SETTING_MAX_DUPLICATE_HOLDS is not set at BR2 and ancestors.
93 $setting_value = $U->ou_ancestor_setting_value(BR2_ID, OILS_SETTING_MAX_DUPLICATE_HOLDS);
94 ok(
95     ! $setting_value,
96     'circ.holds.max_duplicate_holds is not set for BR2'
97 );
98
99 # Set OILS_SETTING_MAX_DUPLICATE_HOLDS to 5 at BR1.
100 $setting_value = $U->simplereq(
101     'open-ils.actor',
102     'open-ils.actor.org_unit.settings.update',
103     $authtoken,
104     BR1_ID,
105     {OILS_SETTING_MAX_DUPLICATE_HOLDS, 5}
106 );
107 ok(
108     ! ref $setting_value,
109     'circ.holds.max_duplicate_holds set to 5 for BR1'
110 );
111
112 # Retrieve PATRON1.
113 my $patron1 = $U->simplereq(
114     'open-ils.actor',
115     'open-ils.actor.user.fleshed.retrieve_by_barcode',
116     $authtoken,
117     PATRON1_BARCODE
118 );
119 isa_ok(
120     ref $patron1,
121     'Fieldmapper::actor::user',
122     'Got patron 1'
123 ) or BAIL_OUT('Need Patron1');
124
125 # Create a circ session for holds placement.
126 my $circ_session = $script->session('open-ils.circ');
127
128 # Place 5 holds for RECORD_ID for PATRON1. Expect success.
129 my $request = $circ_session->request(
130     'open-ils.circ.holds.test_and_create.batch',
131     $authtoken,
132     {
133         hold_type => 'T',
134         patronid => $patron1->id(),
135         pickup_lib => $patron1->home_ou()
136     },
137     [RECORD_ID, RECORD_ID, RECORD_ID, RECORD_ID, RECORD_ID]
138 );
139 my $success = 0;
140 while (my $response = $request->recv()) {
141     my $result = $response->content();
142     if ($result->{result} && !ref $result->{result}) {
143         $success++;
144         push(@holds, $result->{result});
145     }
146 }
147 $request->finish();
148 is(
149     $success,
150     5,
151     'Placed 5 title holds for Patron 1'
152 );
153
154 # Place 1 hold for RECORD_ID for PATRON1. Expect HOLD_EXISTS.
155 $request = $circ_session->request(
156     'open-ils.circ.holds.test_and_create.batch',
157     $authtoken,
158     {
159         hold_type => 'T',
160         patronid => $patron1->id(),
161         pickup_lib => $patron1->home_ou()
162     },
163     [RECORD_ID]
164 );
165 my $textcode;
166 while (my $response = $request->recv()) {
167     my $result = $response->content();
168     if ($result->{result} && ref($result->{result}) eq 'ARRAY') {
169         if (grep {$_->{textcode} eq 'HOLD_EXISTS'} @{$result->{result}}) {
170             $textcode = 'HOLD_EXISTS';
171         }
172     }
173 }
174 $request->finish();
175 is(
176     $textcode,
177     'HOLD_EXISTS',
178     'Got HOLD_EXISTS placing 6th title hold for patron 1'
179 );
180
181 # Place 5 holds for METARECORD_ID for PATRON1. Expect success.
182 $request = $circ_session->request(
183     'open-ils.circ.holds.test_and_create.batch',
184     $authtoken,
185     {
186         hold_type => 'M',
187         patronid => $patron1->id(),
188         pickup_lib => $patron1->home_ou()
189     },
190     [METARECORD_ID, METARECORD_ID, METARECORD_ID, METARECORD_ID, METARECORD_ID]
191 );
192 $success = 0;
193 while (my $response = $request->recv()) {
194     my $result = $response->content();
195     if ($result->{result} && !ref $result->{result}) {
196         $success++;
197         push(@holds, $result->{result});
198     }
199 }
200 $request->finish();
201 is(
202     $success,
203     5,
204     'Placed 5 metarecord holds for Patron 1'
205 );
206
207 # Place 1 hold for METARECORD_ID for PATRON1. Expect HOLD_EXISTS.
208 $request = $circ_session->request(
209     'open-ils.circ.holds.test_and_create.batch',
210     $authtoken,
211     {
212         hold_type => 'M',
213         patronid => $patron1->id(),
214         pickup_lib => $patron1->home_ou()
215     },
216     [METARECORD_ID]
217 );
218 $textcode = '';
219 while (my $response = $request->recv()) {
220     my $result = $response->content();
221     if ($result->{result} && ref($result->{result}) eq 'ARRAY') {
222         if (grep {$_->{textcode} eq 'HOLD_EXISTS'} @{$result->{result}}) {
223             $textcode = 'HOLD_EXISTS';
224         }
225     }
226 }
227 $request->finish();
228 is(
229     $textcode,
230     'HOLD_EXISTS',
231     'Got HOLD_EXISTS placing 6th metarecord hold for patron 1'
232 );
233
234 # Place 5 holds for COPY_ID for PATRON1. Expect 1 success and 4 HOLD_EXISTS.
235 $request = $circ_session->request(
236     'open-ils.circ.holds.test_and_create.batch',
237     $authtoken,
238     {
239         hold_type => 'C',
240         patronid => $patron1->id(),
241         pickup_lib => $patron1->home_ou()
242     },
243     [COPY_ID, COPY_ID, COPY_ID, COPY_ID, COPY_ID]
244 );
245 $success = 0;
246 $textcode = 0; # Using textcode as int this time.
247 while (my $response = $request->recv()) {
248     my $result = $response->content();
249     if ($result->{result} && ref($result->{result}) eq 'ARRAY') {
250         if (grep {$_->{textcode} eq 'HOLD_EXISTS'} @{$result->{result}}) {
251             $textcode++;
252         }
253     } elsif ($result->{result}) {
254         $success++;
255         push(@holds, $result->{result});
256     }
257 }
258 $request->finish();
259 is(
260     $success,
261     1,
262     'Placed 1 copy hold for patron 1'
263 );
264 is(
265     $textcode,
266     4,
267     'Got 4 HOLD_EXISTS on copy holds for patron 1'
268 );
269
270 # Retrieve PATRON2.
271 my $patron2 = $U->simplereq(
272     'open-ils.actor',
273     'open-ils.actor.user.fleshed.retrieve_by_barcode',
274     $authtoken,
275     PATRON2_BARCODE
276 );
277 isa_ok(
278     ref $patron2,
279     'Fieldmapper::actor::user',
280     'Got patron 2'
281 ) or BAIL_OUT('Need Patron 2');
282
283 # Place 5 holds for RECORD_ID for PATRON2. Expect 1 success and 4 HOLD_EXISTS.
284 $request = $circ_session->request(
285     'open-ils.circ.holds.test_and_create.batch',
286     $authtoken,
287     {
288         hold_type => 'T',
289         patronid => $patron2->id(),
290         pickup_lib => $patron2->home_ou()
291     },
292     [RECORD_ID, RECORD_ID, RECORD_ID, RECORD_ID, RECORD_ID]
293 );
294 $success = 0;
295 $textcode = 0; # Using textcode as int this time.
296 while (my $response = $request->recv()) {
297     my $result = $response->content();
298     if ($result->{result} && ref($result->{result}) eq 'ARRAY') {
299         if (grep {$_->{textcode} eq 'HOLD_EXISTS'} @{$result->{result}}) {
300             $textcode++;
301         }
302     } elsif ($result->{result}) {
303         $success++;
304         push(@holds, $result->{result});
305     }
306 }
307 $request->finish();
308 is(
309     $success,
310     1,
311     'Placed 1 title hold for patron 2'
312 );
313 is(
314     $textcode,
315     4,
316     'Got 4 HOLD_EXISTS on title holds for patron 2'
317 );
318
319 # Place 5 holds for METARECORD_ID for PATRON2. Expect 1 success and 4 HOLD_EXISTS.
320 $request = $circ_session->request(
321     'open-ils.circ.holds.test_and_create.batch',
322     $authtoken,
323     {
324         hold_type => 'M',
325         patronid => $patron2->id(),
326         pickup_lib => $patron2->home_ou()
327     },
328     [METARECORD_ID, METARECORD_ID, METARECORD_ID, METARECORD_ID, METARECORD_ID]
329 );
330 $success = 0;
331 $textcode = 0; # Using textcode as int this time.
332 while (my $response = $request->recv()) {
333     my $result = $response->content();
334     if ($result->{result} && ref($result->{result}) eq 'ARRAY') {
335         if (grep {$_->{textcode} eq 'HOLD_EXISTS'} @{$result->{result}}) {
336             $textcode++;
337         }
338     } elsif ($result->{result}) {
339         $success++;
340         push(@holds, $result->{result});
341     }
342 }
343 $request->finish();
344 is(
345     $success,
346     1,
347     'Placed 1 metarecord hold for patron 2'
348 );
349 is(
350     $textcode,
351     4,
352     'Got 4 HOLD_EXISTS on metarecord holds for patron 2'
353 );
354
355 # Place 5 holds for COPY_ID for PATRON2. Expect 1 success and 4 HOLD_EXISTS.
356 $request = $circ_session->request(
357     'open-ils.circ.holds.test_and_create.batch',
358     $authtoken,
359     {
360         hold_type => 'C',
361         patronid => $patron2->id(),
362         pickup_lib => $patron2->home_ou()
363     },
364     [COPY_ID, COPY_ID, COPY_ID, COPY_ID, COPY_ID]
365 );
366 $success = 0;
367 $textcode = 0; # Using textcode as int this time.
368 while (my $response = $request->recv()) {
369     my $result = $response->content();
370     if ($result->{result} && ref($result->{result}) eq 'ARRAY') {
371         if (grep {$_->{textcode} eq 'HOLD_EXISTS'} @{$result->{result}}) {
372             $textcode++;
373         }
374     } elsif ($result->{result}) {
375         $success++;
376         push(@holds, $result->{result});
377     }
378 }
379 $request->finish();
380 is(
381     $success,
382     1,
383     'Placed 1 copy hold for patron 2'
384 );
385 is(
386     $textcode,
387     4,
388     'Got 4 HOLD_EXISTS on copy holds for patron 2'
389 );
390
391 # Cancel all of the holds placed.
392 # How many successes we expect.
393 my $expect = scalar(@holds);
394 $success = 0;
395 foreach my $hold (@holds) {
396     my $result = $circ_session->request(
397         'open-ils.circ.hold.cancel',
398         $authtoken,
399         $hold,
400         5,
401         'LP 1694058 perl test'
402     )->gather(1);
403     if ($result && ! ref $result) {
404         $success++;
405     }
406 }
407 is(
408     $success,
409     $expect,
410     "Cancelled $expect holds"
411 );
412
413 # Reset @holds
414 @holds = ();
415
416 # Test the permission by logging in as patron 1 and placing a title and metarecord hold.
417
418 # Login as patron1.
419 my $patron_auth = $script->authenticate({
420     username => $patron1->usrname(),
421     password => 'leona1234',
422     type => 'opac'
423 });
424 ok(
425     $patron_auth,
426     'Logged in as patron 1'
427 );
428
429 # Place 5 holds for RECORD_ID as PATRON1. Expect 1 success and 4 HOLD_EXISTS.
430 $request = $circ_session->request(
431     'open-ils.circ.holds.test_and_create.batch',
432     $patron_auth,
433     {
434         hold_type => 'T',
435         patronid => $patron1->id(),
436         pickup_lib => $patron1->home_ou()
437     },
438     [RECORD_ID, RECORD_ID, RECORD_ID, RECORD_ID, RECORD_ID]
439 );
440 $success = 0;
441 $textcode = 0; # Using textcode as int this time.
442 while (my $response = $request->recv()) {
443     my $result = $response->content();
444     if ($result->{result} && ref($result->{result}) eq 'ARRAY') {
445         if (grep {$_->{textcode} eq 'HOLD_EXISTS'} @{$result->{result}}) {
446             $textcode++;
447         }
448     } elsif ($result->{result}) {
449         $success++;
450         push(@holds, $result->{result});
451     }
452 }
453 $request->finish();
454 is(
455     $success,
456     1,
457     'Patron 1 placed 1 title hold'
458 );
459 is(
460     $textcode,
461     4,
462     'Patron 1 got 4 HOLD_EXISTS on title holds'
463 );
464
465 # Ditto for metarecord holds:
466 $request = $circ_session->request(
467     'open-ils.circ.holds.test_and_create.batch',
468     $patron_auth,
469     {
470         hold_type => 'T',
471         patronid => $patron1->id(),
472         pickup_lib => $patron1->home_ou()
473     },
474     [METARECORD_ID, METARECORD_ID, METARECORD_ID, METARECORD_ID, METARECORD_ID]
475 );
476 $success = 0;
477 $textcode = 0; # Using textcode as int this time.
478 while (my $response = $request->recv()) {
479     my $result = $response->content();
480     if ($result->{result} && ref($result->{result}) eq 'ARRAY') {
481         if (grep {$_->{textcode} eq 'HOLD_EXISTS'} @{$result->{result}}) {
482             $textcode++;
483         }
484     } elsif ($result->{result}) {
485         $success++;
486         push(@holds, $result->{result});
487     }
488 }
489 $request->finish();
490 is(
491     $success,
492     1,
493     'Patron 1 placed 1 metarecord hold'
494 );
495 is(
496     $textcode,
497     4,
498     'Patron 1 got 4 HOLD_EXISTS on metarecord holds'
499 );
500
501 # Cancel the patron-placed holds.
502 $expect = scalar(@holds);
503 $success = 0;
504 foreach my $hold (@holds) {
505     my $result = $circ_session->request(
506         'open-ils.circ.hold.cancel',
507         $patron_auth,
508         $hold,
509         6,
510         'LP 1694058 perl test'
511     )->gather(1);
512     if ($result && ! ref $result) {
513         $success++;
514     }
515 }
516 is(
517     $success,
518     $expect,
519     "Cancelled $expect patron holds"
520 );
521
522 # Reset @holds
523 @holds = ();
524
525 # Unset OILS_SETTING_MAX_DUPLICATE_HOLDS at BR1.
526 $setting_value = $U->simplereq(
527     'open-ils.actor',
528     'open-ils.actor.org_unit.settings.update',
529     $authtoken,
530     BR1_ID,
531     {OILS_SETTING_MAX_DUPLICATE_HOLDS, undef}
532 );
533 ok(
534     ! ref $setting_value,
535     'circ.holds.max_duplicate_holds unset for BR1'
536 );
537
538 # Logout. Because of a "bug" in Cronscript.pm, we need to log out in the order that we logged in.
539 $script->logout($authtoken);
540 $script->logout($patron_auth);
541 ok(
542     ! $script->authtoken,
543     'Successfully logged out'
544 );
545