Bug 6906: Follow coding guidelines in terminology.
[srvgit] / t / db_dependent / Patron / Borrower_PrevCheckout.t
1 #!/usr/bin/perl
2 use Modern::Perl;
3
4 use C4::Members;
5 use C4::Circulation;
6 use Koha::Database;
7 use Koha::Patrons;
8 use Koha::Patron;
9
10 use Test::More tests => 59;
11
12 use_ok('Koha::Patron');
13
14 use t::lib::TestBuilder;
15 use t::lib::Mocks;
16
17 my $schema = Koha::Database->new->schema;
18 $schema->storage->txn_begin;
19
20 my $builder = t::lib::TestBuilder->new;
21 my $yesCatCode = $builder->build({
22     source => 'Category',
23     value => {
24         categorycode => 'yesCat',
25         checkprevcheckout => 'yes',
26     },
27 });
28
29 my $noCatCode = $builder->build({
30     source => 'Category',
31     value => {
32         categorycode => 'noCat',
33         checkprevcheckout => 'no',
34     },
35 });
36
37 my $inheritCatCode = $builder->build({
38     source => 'Category',
39     value => {
40         categorycode => 'inheritCat',
41         checkprevcheckout => 'inherit',
42     },
43 });
44
45 # Create context for some tests late on in the file.
46 my $library = $builder->build({ source => 'Branch' });
47 my $staff = $builder->build({source => 'Borrower'});
48 my @USERENV = (
49     $staff->{borrowernumber}, 'test', 'MASTERTEST', 'firstname', $library->{branchcode},
50     $library->{branchcode}, 'email@example.org'
51 );
52 C4::Context->_new_userenv('DUMMY_SESSION_ID');
53 C4::Context->set_userenv(@USERENV);
54 BAIL_OUT("No userenv") unless C4::Context->userenv;
55
56
57 # wants_check_for_previous_checkout
58
59 # We expect the following result matrix:
60 #
61 # (1/0 indicates the return value of WantsCheckPrevCheckout; i.e. 1 says we
62 # should check whether the item was previously issued)
63 #
64 # | System Preference | hardyes                           | softyes                           | softno                            | hardno                            |
65 # |-------------------+-----------------------------------+-----------------------------------+-----------------------------------+-----------------------------------|
66 # | Category Setting  | yes       | no        | inherit   | yes       | no        | inherit   | yes       | no        | inherit   | yes       | no        | inherit   |
67 # |-------------------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------|
68 # | Patron Setting    | y | n | i | y | n | i | y | n | i | y | n | i | y | n | i | y | n | i | y | n | i | y | n | i | y | n | i | y | n | i | y | n | i | y | n | i |
69 # |-------------------+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
70 # | Expected Result   | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
71
72 my $mappings = [
73     {
74         syspref    => 'hardyes',
75         categories => [
76             {
77                 setting => 'yes',
78                 patrons => [
79                     {setting => 'yes',     result => 1},
80                     {setting => 'no',      result => 1},
81                     {setting => 'inherit', result => 1},
82                 ],
83             },
84             {
85                 setting => 'no',
86                 patrons => [
87                     {setting => 'yes',     result => 1},
88                     {setting => 'no',      result => 1},
89                     {setting => 'inherit', result => 1},
90                 ],
91             },
92             {
93                 setting => 'inherit',
94                 patrons => [
95                     {setting => 'yes',     result => 1},
96                     {setting => 'no',      result => 1},
97                     {setting => 'inherit', result => 1},
98                 ],
99             },
100         ],
101     },
102     {
103         syspref    => 'softyes',
104         categories => [
105             {
106                 setting => 'yes',
107                 patrons => [
108                     {setting => 'yes',     result => 1},
109                     {setting => 'no',      result => 0},
110                     {setting => 'inherit', result => 1},
111                 ],
112             },
113             {
114                 setting => 'no',
115                 patrons => [
116                     {setting => 'yes',     result => 1},
117                     {setting => 'no',      result => 0},
118                     {setting => 'inherit', result => 0},
119                 ],
120             },
121             {
122                 setting => 'inherit',
123                 patrons => [
124                     {setting => 'yes',     result => 1},
125                     {setting => 'no',      result => 0},
126                     {setting => 'inherit', result => 1},
127                 ],
128             },
129         ],
130     },
131     {
132         syspref    => 'softno',
133         categories => [
134             {
135                 setting => 'yes',
136                 patrons => [
137                     {setting => 'yes',     result => 1},
138                     {setting => 'no',      result => 0},
139                     {setting => 'inherit', result => 1},
140                 ],
141             },
142             {
143                 setting => 'no',
144                 patrons => [
145                     {setting => 'yes',     result => 1},
146                     {setting => 'no',      result => 0},
147                     {setting => 'inherit', result => 0},
148                 ],
149             },
150             {
151                 setting => 'inherit',
152                 patrons => [
153                     {setting => 'yes',     result => 1},
154                     {setting => 'no',      result => 0},
155                     {setting => 'inherit', result => 0},
156                 ],
157             },
158         ],
159     },
160     {
161         syspref    => 'hardno',
162         categories => [
163             {
164                 setting => 'yes',
165                 patrons => [
166                     {setting => 'yes',     result => 0},
167                     {setting => 'no',      result => 0},
168                     {setting => 'inherit', result => 0},
169                 ],
170             },
171             {
172                 setting => 'no',
173                 patrons => [
174                     {setting => 'yes',     result => 0},
175                     {setting => 'no',      result => 0},
176                     {setting => 'inherit', result => 0},
177                 ],
178             },
179             {
180                 setting => 'inherit',
181                 patrons => [
182                     {setting => 'yes',     result => 0},
183                     {setting => 'no',      result => 0},
184                     {setting => 'inherit', result => 0},
185                 ],
186             },
187         ],
188     },
189 ];
190
191 map {
192     my $syspref = $_->{syspref};
193     t::lib::Mocks::mock_preference('checkprevcheckout', $syspref);
194     map {
195         my $code = $_->{setting} . 'Cat';
196         map {
197             my $kpatron = $builder->build({
198                 source => 'Borrower',
199                 value  => {
200                     checkprevcheckout => $_->{setting},
201                     categorycode => $code,
202                 },
203             });
204             my $patron = Koha::Patrons->find($kpatron->{borrowernumber});
205             is(
206                 $patron->wants_check_for_previous_checkout, $_->{result},
207                 "Predicate with syspref " . $syspref . ", cat " . $code
208                     . ", patron " . $_->{setting}
209               );
210         } @{$_->{patrons}};
211     } @{$_->{categories}};
212 } @{$mappings};
213
214 # do_check_for_previous_checkout
215
216 # We want to test:
217 # - DESCRIPTION [RETURNVALUE (0/1)]
218 ## PreIssue (sanity checks)
219 # - Item, patron [0]
220 # - Diff item, same bib, same patron [0]
221 # - Diff item, diff bib, same patron [0]
222 # - Same item, diff patron [0]
223 # - Diff item, same bib, diff patron [0]
224 # - Diff item, diff bib, diff patron [0]
225 ## PostIssue
226 # - Same item, same patron [1]
227 # - Diff item, same bib, same patron [1]
228 # - Diff item, diff bib, same patron [0]
229 # - Same item, diff patron [0]
230 # - Diff item, same bib, diff patron [0]
231 # - Diff item, diff bib, diff patron [0]
232 ## PostReturn
233 # - Same item, same patron [1]
234 # - Diff item, same bib, same patron [1]
235 # - Diff item, diff bib, same patron [0]
236 # - Same item, diff patron [0]
237 # - Diff item, same bib, diff patron [0]
238 # - Diff item, diff bib, diff patron [0]
239
240 # Requirements:
241 # $patron, $different_patron, $items (same bib number), $different_item
242 my $patron = $builder->build({source => 'Borrower'});
243 my $patron_d = $builder->build({source => 'Borrower'});
244 my $item_1 = $builder->build({source => 'Item'});
245 my $item_2 = $builder->build({
246     source => 'Item',
247     value => { biblionumber => $item_1->{biblionumber} },
248 });
249 my $item_d = $builder->build({source => 'Item'});
250
251 ## Testing Sub
252 sub test_it {
253     my ($mapping, $stage) = @_;
254     map {
255         my $patron = Koha::Patrons->find($_->{patron}->{borrowernumber});
256         is(
257             $patron->do_check_for_previous_checkout($_->{item}),
258             $_->{result}, $stage . ": " . $_->{msg}
259         );
260     } @{$mapping};
261 };
262
263 ## Initial Mappings
264 my $cpvmappings = [
265     {
266         msg => "Item, patron [0]",
267         item => $item_1,
268         patron => $patron,
269         result => 0,
270     },
271     {
272         msg => "Diff item, same bib, same patron [0]",
273         item => $item_2,
274         patron => $patron,
275         result => 0,
276     },
277     {
278         msg => "Diff item, diff bib, same patron [0]",
279         item => $item_d,
280         patron => $patron,
281         result => 0,
282     },
283     {
284         msg => "Same item, diff patron [0]",
285         item => $item_1,
286         patron => $patron_d,
287         result => 0,
288     },
289     {
290         msg => "Diff item, same bib, diff patron [0]",
291         item => $item_2,
292         patron => $patron_d,
293         result => 0,
294     },
295     {
296         msg => "Diff item, diff bib, diff patron [0]",
297         item => $item_d,
298         patron => $patron_d,
299         result => 0,
300     },
301 ];
302
303 test_it($cpvmappings, "PreIssue");
304
305 # Issue item_1 to $patron:
306 my $patron_get_mem =
307     GetMember(%{{borrowernumber => $patron->{borrowernumber}}});
308 BAIL_OUT("Issue failed")
309     unless AddIssue($patron_get_mem, $item_1->{barcode});
310
311 # Then test:
312 my $cpvPmappings = [
313     {
314         msg => "Same item, same patron [1]",
315         item => $item_1,
316         patron => $patron,
317         result => 1,
318     },
319     {
320         msg => "Diff item, same bib, same patron [1]",
321         item => $item_2,
322         patron => $patron,
323         result => 1,
324     },
325     {
326         msg => "Diff item, diff bib, same patron [0]",
327         item => $item_d,
328         patron => $patron,
329         result => 0,
330     },
331     {
332         msg => "Same item, diff patron [0]",
333         item => $item_1,
334         patron => $patron_d,
335         result => 0,
336     },
337     {
338         msg => "Diff item, same bib, diff patron [0]",
339         item => $item_2,
340         patron => $patron_d,
341         result => 0,
342     },
343     {
344         msg => "Diff item, diff bib, diff patron [0]",
345         item => $item_d,
346         patron => $patron_d,
347         result => 0,
348     },
349 ];
350
351 test_it($cpvPmappings, "PostIssue");
352
353 # Return item_1 from patron:
354 BAIL_OUT("Return Failed") unless AddReturn($item_1->{barcode}, $patron->{branchcode});
355
356 # Then:
357 test_it($cpvPmappings, "PostReturn");
358
359 # Finally test C4::Circulation::CanBookBeIssued
360
361 # We have already tested ->wants_check_for_previous_checkout and
362 # ->do_check_for_previous_checkout, so all that remains to be tested is
363 # whetherthe different combinational outcomes of the above return values in
364 # CanBookBeIssued result in the approriate $needsconfirmation.
365
366 # We want to test:
367 # - DESCRIPTION [RETURNVALUE (0/1)]
368 # - patron, !wants_check_for_previous_checkout, !do_check_for_previous_checkout
369 #   [!$issuingimpossible,!$needsconfirmation->{PREVISSUE}]
370 # - patron, wants_check_for_previous_checkout, !do_check_for_previous_checkout
371 #   [!$issuingimpossible,!$needsconfirmation->{PREVISSUE}]
372 # - patron, !wants_check_for_previous_checkout, do_check_for_previous_checkout
373 #   [!$issuingimpossible,!$needsconfirmation->{PREVISSUE}]
374 # - patron, wants_check_for_previous_checkout, do_check_for_previous_checkout
375 #   [!$issuingimpossible,$needsconfirmation->{PREVISSUE}]
376
377 # Needs:
378 # - $patron_from_GetMember
379 # - $item objects (one not issued, another prevIssued)
380 # - $checkprevcheckout pref (first hardno, then hardyes)
381
382 # Our Patron
383 my $CBBI_patron = $builder->build({source => 'Borrower'});
384 my $p_from_GetMember =
385     GetMember(%{{borrowernumber => $CBBI_patron->{borrowernumber}}});
386 # Our Items
387 my $new_item = $builder->build({
388     source => 'Item',
389     value => {
390         notforloan => 0,
391         withdrawn  => 0,
392         itemlost   => 0,
393     },
394 });
395 my $prev_item = $builder->build({
396     source => 'Item',
397     value => {
398         notforloan => 0,
399         withdrawn  => 0,
400         itemlost   => 0,
401     },
402 });
403 # Second is Checked Out
404 BAIL_OUT("CanBookBeIssued Issue failed")
405     unless AddIssue($p_from_GetMember, $prev_item->{barcode});
406
407 # Mappings
408 my $CBBI_mappings = [
409     {
410         syspref => 'hardno',
411         item    => $new_item,
412         result  => undef,
413         msg     => "patron, !wants_check_for_previous_checkout, !do_check_for_previous_checkout"
414
415     },
416     {
417         syspref => 'hardyes',
418         item    => $new_item,
419         result  => undef,
420         msg     => "patron, wants_check_for_previous_checkout, !do_check_for_previous_checkout"
421     },
422     {
423         syspref => 'hardno',
424         item    => $prev_item,
425         result  => undef,
426         msg     => "patron, !wants_check_for_previous_checkout, do_check_for_previous_checkout"
427     },
428     {
429         syspref => 'hardyes',
430         item    => $prev_item,
431         result  => 1,
432         msg     => "patron, wants_check_for_previous_checkout, do_check_for_previous_checkout"
433     },
434 ];
435
436 # Tests
437 map {
438     t::lib::Mocks::mock_preference('checkprevcheckout', $_->{syspref});
439     my ( $issuingimpossible, $needsconfirmation ) =
440         C4::Circulation::CanBookBeIssued(
441             $p_from_GetMember, $_->{item}->{barcode}
442         );
443     is($needsconfirmation->{PREVISSUE}, $_->{result}, $_->{msg});
444 } @{$CBBI_mappings};
445
446 $schema->storage->txn_rollback;
447
448 1;