3 # Copyright 2024 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>.
23 use Test::More tests => 2;
27 use Koha::DateUtils qw( dt_from_string );
29 use t::lib::TestBuilder;
32 my $schema = Koha::Database->new->schema;
33 my $builder = t::lib::TestBuilder->new;
35 subtest 'Relation accessor tests' => sub {
38 subtest 'biblio relation tests' => sub {
40 $schema->storage->txn_begin;
42 my $biblio = $builder->build_sample_biblio;
44 $builder->build_object( { class => 'Koha::Bookings', value => { biblio_id => $biblio->biblionumber } } );
46 my $THE_biblio = $booking->biblio;
47 is( ref($THE_biblio), 'Koha::Biblio', "Koha::Booking->biblio returns a Koha::Biblio object" );
48 is( $THE_biblio->biblionumber, $biblio->biblionumber, "Koha::Booking->biblio returns the links biblio object" );
51 $booking = Koha::Bookings->find( $booking->booking_id );
52 is( $booking, undef, "The booking is deleted when the biblio it's attached to is deleted" );
54 $schema->storage->txn_rollback;
57 subtest 'patron relation tests' => sub {
59 $schema->storage->txn_begin;
61 my $patron = $builder->build_object( { class => "Koha::Patrons" } );
63 $builder->build_object( { class => 'Koha::Bookings', value => { patron_id => $patron->borrowernumber } } );
65 my $THE_patron = $booking->patron;
66 is( ref($THE_patron), 'Koha::Patron', "Koha::Booking->patron returns a Koha::Patron object" );
68 $THE_patron->borrowernumber, $patron->borrowernumber,
69 "Koha::Booking->patron returns the links patron object"
73 $booking = Koha::Bookings->find( $booking->booking_id );
74 is( $booking, undef, "The booking is deleted when the patron it's attached to is deleted" );
76 $schema->storage->txn_rollback;
79 subtest 'item relation tests' => sub {
81 $schema->storage->txn_begin;
83 my $item = $builder->build_sample_item( { bookable => 1 } );
85 $builder->build_object( { class => 'Koha::Bookings', value => { item_id => $item->itemnumber } } );
87 my $THE_item = $booking->item;
88 is( ref($THE_item), 'Koha::Item', "Koha::Booking->item returns a Koha::Item object" );
90 $THE_item->itemnumber, $item->itemnumber,
91 "Koha::Booking->item returns the links item object"
95 $booking = Koha::Bookings->find( $booking->booking_id );
96 is( $booking, undef, "The booking is deleted when the item it's attached to is deleted" );
98 $schema->storage->txn_rollback;
102 subtest 'store() tests' => sub {
104 $schema->storage->txn_begin;
106 my $patron = $builder->build_object( { class => "Koha::Patrons" } );
107 my $biblio = $builder->build_sample_biblio();
108 my $item_1 = $builder->build_sample_item( { biblionumber => $biblio->biblionumber } );
109 my $start_0 = dt_from_string->subtract( days => 2 )->truncate( to => 'day' );
110 my $end_0 = $start_0->clone()->add( days => 6 );
112 my $deleted_item = $builder->build_sample_item( { biblionumber => $biblio->biblionumber } );
113 $deleted_item->delete;
115 my $wrong_item = $builder->build_sample_item();
117 my $booking = Koha::Booking->new(
119 patron_id => $patron->borrowernumber,
120 biblio_id => $biblio->biblionumber,
121 item_id => $deleted_item->itemnumber,
122 start_date => $start_0,
127 throws_ok { $booking->store() } 'Koha::Exceptions::Object::FKConstraint',
128 'Throws exception if passed a deleted item';
130 $booking = Koha::Booking->new(
132 patron_id => $patron->borrowernumber,
133 biblio_id => $biblio->biblionumber,
134 item_id => $wrong_item->itemnumber,
135 start_date => $start_0,
140 throws_ok { $booking->store() } 'Koha::Exceptions::Object::FKConstraint',
141 "Throws exception if item passed doesn't match biblio passed";
143 $booking = Koha::Booking->new(
145 patron_id => $patron->borrowernumber,
146 biblio_id => $biblio->biblionumber,
147 item_id => $item_1->itemnumber,
148 start_date => $start_0,
153 # FIXME: Should this be allowed if an item is passed specifically?
154 throws_ok { $booking->store() } 'Koha::Exceptions::Booking::Clash',
155 'Throws exception when there are no items marked bookable for this biblio';
157 $item_1->bookable(1)->store();
159 ok( $booking->in_storage, 'First booking on item 1 stored OK' );
165 my $start_1 = dt_from_string->truncate( to => 'day' );
166 my $end_1 = $start_1->clone()->add( days => 6 );
167 $booking = Koha::Booking->new(
169 patron_id => $patron->borrowernumber,
170 biblio_id => $biblio->biblionumber,
171 item_id => $item_1->itemnumber,
172 start_date => $start_1,
176 throws_ok { $booking->store } 'Koha::Exceptions::Booking::Clash',
177 'Throws exception when passed booking start_date falls inside another booking for the item passed';
182 $start_1 = dt_from_string->subtract( days => 4 )->truncate( to => 'day' );
183 $end_1 = $start_1->clone()->add( days => 6 );
184 $booking = Koha::Booking->new(
186 patron_id => $patron->borrowernumber,
187 biblio_id => $biblio->biblionumber,
188 item_id => $item_1->itemnumber,
189 start_date => $start_1,
193 throws_ok { $booking->store } 'Koha::Exceptions::Booking::Clash',
194 'Throws exception when passed booking end_date falls inside another booking for the item passed';
198 # ✗ Item 1 |--------|
199 $start_1 = dt_from_string->subtract( days => 4 )->truncate( to => 'day' );
200 $end_1 = $start_1->clone()->add( days => 10 );
201 $booking = Koha::Booking->new(
203 patron_id => $patron->borrowernumber,
204 biblio_id => $biblio->biblionumber,
205 item_id => $item_1->itemnumber,
206 start_date => $start_1,
210 throws_ok { $booking->store } 'Koha::Exceptions::Booking::Clash',
211 'Throws exception when passed booking dates would envelope another booking for the item passed';
216 $start_1 = dt_from_string->truncate( to => 'day' );
217 $end_1 = $start_1->clone()->add( days => 4 );
218 $booking = Koha::Booking->new(
220 patron_id => $patron->borrowernumber,
221 biblio_id => $biblio->biblionumber,
222 item_id => $item_1->itemnumber,
223 start_date => $start_1,
227 throws_ok { $booking->store } 'Koha::Exceptions::Booking::Clash',
228 'Throws exception when passed booking dates would fall wholly inside another booking for the item passed';
230 my $item_2 = $builder->build_sample_item( { biblionumber => $biblio->biblionumber, bookable => 1 } );
231 my $item_3 = $builder->build_sample_item( { biblionumber => $biblio->biblionumber, bookable => 0 } );
236 $booking = Koha::Booking->new(
238 patron_id => $patron->borrowernumber,
239 biblio_id => $biblio->biblionumber,
240 item_id => $item_2->itemnumber,
241 start_date => $start_1,
246 $booking->in_storage,
247 'First booking on item 2 stored OK, even though it would overlap with a booking on item 1'
254 $booking = Koha::Booking->new(
256 patron_id => $patron->borrowernumber,
257 biblio_id => $biblio->biblionumber,
258 start_date => $start_1,
262 throws_ok { $booking->store } 'Koha::Exceptions::Booking::Clash',
263 'Throws exception when passed booking dates would fall wholly inside all existing bookings when no item specified';
269 $start_1 = dt_from_string->add( days => 5 )->truncate( to => 'day' );
270 $end_1 = $start_1->clone()->add( days => 4 );
271 $booking = Koha::Booking->new(
273 patron_id => $patron->borrowernumber,
274 biblio_id => $biblio->biblionumber,
275 start_date => $start_1,
279 ok( $booking->in_storage, 'Booking stored OK when item not specified and the booking slot is available' );
280 ok( $booking->item_id, 'An item was assigned to the booking' );
282 subtest '_assign_item_for_booking() tests' => sub {
284 is( $booking->item_id, $item_1->itemnumber, "Item 1 was assigned to the booking" );
292 $schema->storage->txn_rollback;