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