3 # Copyright 2015 Koha Development team
5 # This file is part of Koha
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
22 use Test::More tests => 11;
24 use C4::Circulation qw( MarkIssueReturned AddReturn );
25 use C4::Reserves qw( AddReserve );
28 use Koha::DateUtils qw( dt_from_string );
31 use t::lib::TestBuilder;
34 my $schema = Koha::Database->new->schema;
35 $schema->storage->txn_begin;
37 my $builder = t::lib::TestBuilder->new;
38 my $library = $builder->build( { source => 'Branch' } );
39 my $patron = $builder->build(
40 { source => 'Borrower', value => { branchcode => $library->{branchcode} } }
42 my $item_1 = $builder->build_sample_item;
43 my $item_2 = $builder->build_sample_item;
44 my $nb_of_checkouts = Koha::Checkouts->search->count;
45 my $new_checkout_1 = Koha::Checkout->new(
47 borrowernumber => $patron->{borrowernumber},
48 itemnumber => $item_1->itemnumber,
49 branchcode => $library->{branchcode},
52 my $new_checkout_2 = Koha::Checkout->new(
54 borrowernumber => $patron->{borrowernumber},
55 itemnumber => $item_2->itemnumber,
56 branchcode => $library->{branchcode},
60 like( $new_checkout_1->issue_id, qr|^\d+$|,
61 'Adding a new checkout should have set the issue_id' );
63 Koha::Checkouts->search->count,
65 'The 2 checkouts should have been added'
68 my $retrieved_checkout_1 = Koha::Checkouts->find( $new_checkout_1->issue_id );
70 $retrieved_checkout_1->itemnumber,
71 $new_checkout_1->itemnumber,
72 'Find a checkout by id should return the correct checkout'
75 subtest 'is_overdue' => sub {
77 my $ten_days_ago = dt_from_string->add( days => -10 );
78 my $ten_days_later = dt_from_string->add( days => 10 );
79 my $yesterday = dt_from_string->add( days => -1 );
80 my $tomorrow = dt_from_string->add( days => 1 );
82 $retrieved_checkout_1->date_due($ten_days_ago)->store;
83 is( $retrieved_checkout_1->is_overdue,
84 1, 'The item should have been returned 10 days ago' );
86 $retrieved_checkout_1->date_due($ten_days_later)->store;
87 is( $retrieved_checkout_1->is_overdue, 0, 'The item is due in 10 days' );
89 $retrieved_checkout_1->date_due($tomorrow)->store;
90 is( $retrieved_checkout_1->is_overdue($ten_days_later),
91 1, 'The item should have been returned yesterday' );
93 $retrieved_checkout_1->date_due($yesterday)->store;
94 is( $retrieved_checkout_1->is_overdue($ten_days_ago),
95 0, 'Ten days ago the item due yesterday was not late' );
97 $retrieved_checkout_1->date_due($tomorrow)->store;
98 is( $retrieved_checkout_1->is_overdue($ten_days_later),
99 1, 'In Ten days, the item due tomorrow will be late' );
101 $retrieved_checkout_1->date_due($yesterday)->store;
102 is( $retrieved_checkout_1->is_overdue($ten_days_ago),
103 0, 'In Ten days, the item due yesterday will still be late' );
106 subtest 'item' => sub {
108 my $item = $retrieved_checkout_1->item;
109 is( ref($item), 'Koha::Item',
110 'Koha::Checkout->item should return a Koha::Item' );
111 is( $item->itemnumber, $item_1->itemnumber,
112 'Koha::Checkout->item should return the correct item' );
115 subtest 'account_lines' => sub {
118 my $accountline = Koha::Account::Line->new(
120 issue_id => $retrieved_checkout_1->id,
121 borrowernumber => $retrieved_checkout_1->borrowernumber,
122 itemnumber => $retrieved_checkout_1->itemnumber,
123 branchcode => $retrieved_checkout_1->branchcode,
125 debit_type_code => 'OVERDUE',
126 status => 'UNRETURNED',
129 amountoutstanding => '1',
133 my $account_lines = $retrieved_checkout_1->account_lines;
134 is( ref($account_lines), 'Koha::Account::Lines',
135 'Koha::Checkout->account_lines should return a Koha::Account::Lines' );
137 my $line = $account_lines->next;
138 is( ref($line), 'Koha::Account::Line',
139 'next returns a Koha::Account::Line' );
144 'Koha::Checkout->account_lines should return the correct account_lines'
148 subtest 'patron' => sub {
150 my $patron = $builder->build_object(
152 class => 'Koha::Patrons',
153 value => { branchcode => $library->{branchcode} }
157 my $item = $builder->build_sample_item;
158 my $checkout = Koha::Checkout->new(
160 borrowernumber => $patron->borrowernumber,
161 itemnumber => $item->itemnumber,
162 branchcode => $library->{branchcode},
166 my $p = $checkout->patron;
167 is( ref($p), 'Koha::Patron',
168 'Koha::Checkout->patron should return a Koha::Patron' );
169 is( $p->borrowernumber, $patron->borrowernumber,
170 'Koha::Checkout->patron should return the correct patron' );
172 # Testing Koha::Old::Checkout->patron now
173 my $issue_id = $checkout->issue_id;
174 C4::Circulation::MarkIssueReturned( $p->borrowernumber,
175 $checkout->itemnumber );
177 my $old_issue = Koha::Old::Checkouts->find($issue_id);
178 is( $old_issue->patron, undef,
179 'Koha::Checkout->patron should return undef if the patron record has been deleted'
183 $retrieved_checkout_1->delete;
185 Koha::Checkouts->search->count,
186 $nb_of_checkouts + 1,
187 'Delete should have deleted the checkout'
190 subtest 'issuer' => sub {
192 my $patron = $builder->build_object(
194 class => 'Koha::Patrons',
195 value => { branchcode => $library->{branchcode} }
198 my $issuer = $builder->build_object(
200 class => 'Koha::Patrons',
201 value => { branchcode => $library->{branchcode} }
205 my $item = $builder->build_sample_item;
206 my $checkout = Koha::Checkout->new(
208 borrowernumber => $patron->borrowernumber,
209 issuer_id => $issuer->borrowernumber,
210 itemnumber => $item->itemnumber,
211 branchcode => $library->{branchcode},
215 my $i = $checkout->issuer;
216 is( ref($i), 'Koha::Patron',
217 'Koha::Checkout->issuer should return a Koha::Patron' );
218 is( $i->borrowernumber, $issuer->borrowernumber,
219 'Koha::Checkout->issuer should return the correct patron' );
221 # Testing Koha::Old::Checkout->patron now
222 my $issue_id = $checkout->issue_id;
223 C4::Circulation::MarkIssueReturned( $patron->borrowernumber,
224 $checkout->itemnumber );
226 my $old_issue = Koha::Old::Checkouts->find($issue_id);
227 is( $old_issue->issuer_id, undef,
228 'Koha::Checkout->issuer_id should return undef if the patron record has been deleted'
233 subtest 'Koha::Old::Checkouts->filter_by_todays_checkins' => sub {
237 # We will create 7 checkins for a given patron
238 # 3 checked in today - 2 days, and 4 checked in today
239 my $librarian = $builder->build_object(
241 class => 'Koha::Patrons',
242 value => { branchcode => $library->{branchcode} }
245 t::lib::Mocks::mock_userenv( { patron => $librarian } );
246 my $patron = $builder->build_object(
248 class => 'Koha::Patrons',
249 value => { branchcode => $library->{branchcode} }
256 my $item = $builder->build_sample_item;
260 borrowernumber => $patron->borrowernumber,
261 itemnumber => $item->itemnumber,
262 branchcode => $library->{branchcode},
267 # Checkin 3 today - 2 days
268 my $not_today = dt_from_string->add( days => -2 );
269 for my $i ( 0 .. 2 ) {
270 my $checkout = $checkouts[$i];
271 C4::Circulation::AddReturn(
272 $checkout->item->barcode, $library->{branchcode},
273 undef, $not_today->set_hour( int( rand(24) ) )
277 my $today = dt_from_string;
278 for my $i ( 3 .. 6 ) {
279 my $checkout = $checkouts[$i];
280 C4::Circulation::AddReturn(
281 $checkout->item->barcode, $library->{branchcode},
282 undef, $today->set_hour( int( rand(24) ) )
286 my $old_checkouts = $patron->old_checkouts;
287 is( $old_checkouts->count, 7, 'There should be 7 old checkouts' );
288 my $todays_checkins = $old_checkouts->filter_by_todays_checkins;
289 is( $todays_checkins->count, 4, 'There should be 4 checkins today' );
291 [ $todays_checkins->get_column('itemnumber') ],
292 [ map { $_->itemnumber } @checkouts[ 3 .. 6 ] ],
293 q{Correct list of today's checkins}
297 $schema->storage->txn_rollback;
299 subtest 'automatic_checkin' => sub {
303 $schema->storage->txn_begin;
305 my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
308 $builder->build_sample_item(
309 { homebranch => $patron->branchcode, itemlost => 0 } );
311 $builder->build_sample_item(
312 { homebranch => $patron->branchcode, itemlost => 0 } );
314 $builder->build_sample_item(
315 { homebranch => $patron->branchcode, itemlost => 0 } );
317 $builder->build_sample_item(
318 { homebranch => $patron->branchcode, itemlost => 0 } );
320 $due_ac_item->itemtype->automatic_checkin(1)->store;
321 $odue_ac_item->itemtype->automatic_checkin(1)->store;
322 $ac_item->itemtype->automatic_checkin(1)->store;
323 $normal_item->itemtype->automatic_checkin(0)->store;
325 my $today = dt_from_string;
326 my $tomorrow = dt_from_string->add( days => 1 );
327 my $yesterday = dt_from_string->subtract( days => 1 );
329 # Checkout do for automatic checkin
330 my $checkout_due_aci = Koha::Checkout->new(
332 borrowernumber => $patron->borrowernumber,
333 itemnumber => $due_ac_item->itemnumber,
334 branchcode => $patron->branchcode,
339 # Checkout not due for automatic checkin
340 my $checkout_odue_aci = Koha::Checkout->new(
342 borrowernumber => $patron->borrowernumber,
343 itemnumber => $odue_ac_item->itemnumber,
344 branchcode => $patron->branchcode,
345 date_due => $yesterday
349 # Checkout not due for automatic checkin
350 my $checkout_aci = Koha::Checkout->new(
352 borrowernumber => $patron->borrowernumber,
353 itemnumber => $ac_item->itemnumber,
354 branchcode => $patron->branchcode,
355 date_due => $tomorrow
359 # due checkout for nomal itemtype
360 my $checkout_ni = Koha::Checkout->new(
362 borrowernumber => $patron->borrowernumber,
363 itemnumber => $normal_item->itemnumber,
364 branchcode => $patron->branchcode,
369 my $searched = Koha::Checkouts->find( $checkout_ni->issue_id );
370 is( $searched->issue_id, $checkout_ni->issue_id,
371 'checkout for normal_item exists' );
373 $searched = Koha::Checkouts->find( $checkout_aci->issue_id );
374 is( $searched->issue_id, $checkout_aci->issue_id,
375 'checkout for ac_item exists' );
377 $searched = Koha::Checkouts->find( $checkout_due_aci->issue_id );
380 $checkout_due_aci->issue_id,
381 'checkout for due_ac_item exists'
384 $searched = Koha::Checkouts->find( $checkout_odue_aci->issue_id );
387 $checkout_odue_aci->issue_id,
388 'checkout for odue_ac_item exists'
391 Koha::Checkouts->automatic_checkin;
393 $searched = Koha::Checkouts->find( $checkout_ni->issue_id );
394 is( $searched->issue_id, $checkout_ni->issue_id,
395 'checkout for normal_item still exists' );
397 $searched = Koha::Checkouts->find( $checkout_aci->issue_id );
398 is( $searched->issue_id, $checkout_aci->issue_id,
399 'checkout for ac_item still exists' );
401 $searched = Koha::Checkouts->find( $checkout_due_aci->issue_id );
402 is( $searched, undef, 'checkout for due_ac_item doesn\'t exist anymore' );
404 $searched = Koha::Checkouts->find( $checkout_odue_aci->issue_id );
405 is( $searched, undef, 'checkout for odue_ac_item doesn\'t exist anymore' );
407 $searched = Koha::Old::Checkouts->find( $checkout_odue_aci->issue_id );
408 is( dt_from_string($searched->returndate), $yesterday, 'old checkout for odue_ac_item has the right return date' );
411 subtest 'automatic_checkin AutomaticCheckinAutoFill tests' => sub {
415 my $checkout_2_due_ac = Koha::Checkout->new(
417 borrowernumber => $patron->borrowernumber,
418 itemnumber => $due_ac_item->itemnumber,
419 branchcode => $patron->branchcode,
425 $builder->build_object( { class => 'Koha::Patrons', value => { branchcode => $patron->branchcode } } );
426 my $reserveid = AddReserve(
428 branchcode => $patron->branchcode,
429 borrowernumber => $patron_2->id,
430 biblionumber => $due_ac_item->biblionumber,
435 t::lib::Mocks::mock_preference( 'AutomaticCheckinAutoFill', '0' );
437 Koha::Checkouts->automatic_checkin;
438 my $reserve = Koha::Holds->find($reserveid);
440 is( $reserve->found, undef, "Hold was not filled when AutomaticCheckinAutoFill disabled" );
442 my $checkout_3_due_ac = Koha::Checkout->new(
444 borrowernumber => $patron->borrowernumber,
445 itemnumber => $due_ac_item->itemnumber,
446 branchcode => $patron->branchcode,
450 t::lib::Mocks::mock_preference( 'AutomaticCheckinAutoFill', '1' );
452 Koha::Checkouts->automatic_checkin;
453 $reserve->discard_changes;
455 is( $reserve->found, 'W', "Hold was filled when AutomaticCheckinAutoFill enabled" );
457 my $checkout_2_odue_ac = Koha::Checkout->new(
459 borrowernumber => $patron->borrowernumber,
460 itemnumber => $odue_ac_item->itemnumber,
461 branchcode => $patron->branchcode,
465 my $branch2 = $builder->build_object( { class => "Koha::Libraries" } );
466 my $reserve2id = AddReserve(
468 branchcode => $branch2->branchcode,
469 borrowernumber => $patron_2->id,
470 biblionumber => $odue_ac_item->biblionumber,
474 Koha::Checkouts->automatic_checkin;
476 my $reserve2 = Koha::Holds->find($reserve2id);
478 $reserve2->found, 'T',
479 "Hold was filled when AutomaticCheckinAutoFill enabled and transfer was initiated when branches didn't match"
483 $schema->storage->txn_rollback;