View | Details | Raw Unified | Return to bug 35248
Collapse All | Expand All

(-)a/Koha/Booking.pm (-3 / +6 lines)
Lines 74-80 sub item { Link Here
74
74
75
=head3 store
75
=head3 store
76
76
77
Booking specific store method to catch booking clashes
77
Booking specific store method to catch booking clashes and ensure we have an item assigned
78
79
We assume that if an item is passed, it's bookability has already been checked. This is to allow
80
overrides in the future.
78
81
79
=cut
82
=cut
80
83
Lines 121-126 sub store { Link Here
121
                }
124
                }
122
                );
125
                );
123
126
127
            # FIXME: We should be able to combine the above two functions into one
128
124
            # Assign item at booking time
129
            # Assign item at booking time
125
            if ( !$self->item_id ) {
130
            if ( !$self->item_id ) {
126
                $self->item_id(
131
                $self->item_id(
Lines 133-140 sub store { Link Here
133
                );
138
                );
134
            }
139
            }
135
140
136
            # FIXME: We should be able to combine the above two functions into one
137
138
            $self = $self->SUPER::store;
141
            $self = $self->SUPER::store;
139
        }
142
        }
140
    );
143
    );
(-)a/t/db_dependent/Koha/Booking.t (-3 / +188 lines)
Lines 20-26 Link Here
20
use Modern::Perl;
20
use Modern::Perl;
21
use utf8;
21
use utf8;
22
22
23
use Test::More tests => 1;
23
use Test::More tests => 2;
24
25
use Test::Exception;
26
27
use Koha::DateUtils qw( dt_from_string );
24
28
25
use t::lib::TestBuilder;
29
use t::lib::TestBuilder;
26
use t::lib::Mocks;
30
use t::lib::Mocks;
Lines 76-82 subtest 'Relation accessor tests' => sub { Link Here
76
        plan tests => 3;
80
        plan tests => 3;
77
        $schema->storage->txn_begin;
81
        $schema->storage->txn_begin;
78
82
79
        my $item = $builder->build_object( { class => "Koha::Items" } );
83
        my $item = $builder->build_sample_item( { bookable => 1 } );
80
        my $booking =
84
        my $booking =
81
            $builder->build_object( { class => 'Koha::Bookings', value => { item_id => $item->itemnumber } } );
85
            $builder->build_object( { class => 'Koha::Bookings', value => { item_id => $item->itemnumber } } );
82
86
Lines 93-97 subtest 'Relation accessor tests' => sub { Link Here
93
97
94
        $schema->storage->txn_rollback;
98
        $schema->storage->txn_rollback;
95
    };
99
    };
100
};
101
102
subtest 'store() tests' => sub {
103
    plan tests => 12;
104
    $schema->storage->txn_begin;
105
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 );
111
112
    my $deleted_item = $builder->build_sample_item( { biblionumber => $biblio->biblionumber } );
113
    $deleted_item->delete;
114
115
    my $wrong_item = $builder->build_sample_item();
116
117
    my $booking = Koha::Booking->new(
118
        {
119
            patron_id  => $patron->borrowernumber,
120
            biblio_id  => $biblio->biblionumber,
121
            item_id    => $deleted_item->itemnumber,
122
            start_date => $start_0,
123
            end_date   => $end_0
124
        }
125
    );
126
127
    throws_ok { $booking->store() } 'Koha::Exceptions::Object::FKConstraint',
128
        'Throws exception if passed a deleted item';
129
130
    $booking = Koha::Booking->new(
131
        {
132
            patron_id  => $patron->borrowernumber,
133
            biblio_id  => $biblio->biblionumber,
134
            item_id    => $wrong_item->itemnumber,
135
            start_date => $start_0,
136
            end_date   => $end_0
137
        }
138
    );
139
140
    throws_ok { $booking->store() } 'Koha::Exceptions::Object::FKConstraint',
141
        "Throws exception if item passed doesn't match biblio passed";
142
143
    $booking = Koha::Booking->new(
144
        {
145
            patron_id  => $patron->borrowernumber,
146
            biblio_id  => $biblio->biblionumber,
147
            item_id    => $item_1->itemnumber,
148
            start_date => $start_0,
149
            end_date   => $end_0
150
        }
151
    );
152
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';
156
157
    $item_1->bookable(1)->store();
158
    $booking->store();
159
    ok( $booking->in_storage, 'First booking on item 1 stored OK' );
160
161
    # Bookings
162
    # ✓ Item 1    |----|
163
    # ✗ Item 1      |----|
164
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(
168
        {
169
            patron_id  => $patron->borrowernumber,
170
            biblio_id  => $biblio->biblionumber,
171
            item_id    => $item_1->itemnumber,
172
            start_date => $start_1,
173
            end_date   => $end_1
174
        }
175
    );
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';
178
179
    # Bookings
180
    # ✓ Item 1    |----|
181
    # ✗ Item 1  |----|
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(
185
        {
186
            patron_id  => $patron->borrowernumber,
187
            biblio_id  => $biblio->biblionumber,
188
            item_id    => $item_1->itemnumber,
189
            start_date => $start_1,
190
            end_date   => $end_1
191
        }
192
    );
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';
195
196
    # Bookings
197
    # ✓ Item 1    |----|
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(
202
        {
203
            patron_id  => $patron->borrowernumber,
204
            biblio_id  => $biblio->biblionumber,
205
            item_id    => $item_1->itemnumber,
206
            start_date => $start_1,
207
            end_date   => $end_1
208
        }
209
    );
210
    throws_ok { $booking->store } 'Koha::Exceptions::Booking::Clash',
211
        'Throws exception when passed booking dates would envelope another booking for the item passed';
212
213
    # Bookings
214
    # ✓ Item 1    |----|
215
    # ✗ Item 1     |--|
216
    $start_1 = dt_from_string->truncate( to => 'day' );
217
    $end_1   = $start_1->clone()->add( days => 4 );
218
    $booking = Koha::Booking->new(
219
        {
220
            patron_id  => $patron->borrowernumber,
221
            biblio_id  => $biblio->biblionumber,
222
            item_id    => $item_1->itemnumber,
223
            start_date => $start_1,
224
            end_date   => $end_1
225
        }
226
    );
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';
229
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 } );
232
233
    # Bookings
234
    # ✓ Item 1    |----|
235
    # ✓ Item 2     |--|
236
    $booking = Koha::Booking->new(
237
        {
238
            patron_id  => $patron->borrowernumber,
239
            biblio_id  => $biblio->biblionumber,
240
            item_id    => $item_2->itemnumber,
241
            start_date => $start_1,
242
            end_date   => $end_1
243
        }
244
    )->store();
245
    ok(
246
        $booking->in_storage,
247
        'First booking on item 2 stored OK, even though it would overlap with a booking on item 1'
248
    );
249
250
    # Bookings
251
    # ✓ Item 1    |----|
252
    # ✓ Item 2     |--|
253
    # ✘ Any        |--|
254
    $booking = Koha::Booking->new(
255
        {
256
            patron_id  => $patron->borrowernumber,
257
            biblio_id  => $biblio->biblionumber,
258
            start_date => $start_1,
259
            end_date   => $end_1
260
        }
261
    );
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';
264
265
    # Bookings
266
    # ✓ Item 1    |----|
267
    # ✓ Item 2     |--|
268
    # ✓ Any             |--|
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(
272
        {
273
            patron_id  => $patron->borrowernumber,
274
            biblio_id  => $biblio->biblionumber,
275
            start_date => $start_1,
276
            end_date   => $end_1
277
        }
278
    )->store();
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' );
96
281
282
    $schema->storage->txn_rollback;
97
};
283
};
98
- 

Return to bug 35248