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 / +186 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 wholy inside another booking for the item passed';
229
230
231
    my $item_2  = $builder->build_sample_item( { biblionumber => $biblio->biblionumber, bookable => 1 } );
232
    my $item_3  = $builder->build_sample_item( { biblionumber => $biblio->biblionumber, bookable => 0 } );
233
234
    # Bookings
235
    # ✓ Item 1    |----|
236
    # ✓ Item 2     |--|
237
    $booking = Koha::Booking->new(
238
        {
239
            patron_id => $patron->borrowernumber,
240
            biblio_id => $biblio->biblionumber,
241
            item_id => $item_2->itemnumber,
242
            start_date => $start_1,
243
            end_date => $end_1
244
        }
245
    )->store();
246
    ok($booking->in_storage, 'First booking on item 2 stored OK, even though it would overlap with a booking on item 1');
247
248
    # Bookings
249
    # ✓ Item 1    |----|
250
    # ✓ Item 2     |--|
251
    # ✘ Any        |--|
252
    $booking = Koha::Booking->new(
253
        {
254
            patron_id => $patron->borrowernumber,
255
            biblio_id => $biblio->biblionumber,
256
            start_date => $start_1,
257
            end_date => $end_1
258
        }
259
    );
260
    throws_ok { $booking->store } 'Koha::Exceptions::Booking::Clash',
261
        'Throws exception when passed booking dates would fall wholy inside all existing bookings when no item specified';
262
263
    # Bookings
264
    # ✓ Item 1    |----|
265
    # ✓ Item 2     |--|
266
    # ✓ Any             |--|
267
    $start_1 = dt_from_string->add( days => 5 )->truncate( to => 'day' );
268
    $end_1 = $start_1->clone()->add( days => 4 );
269
    $booking = Koha::Booking->new(
270
        {
271
            patron_id => $patron->borrowernumber,
272
            biblio_id => $biblio->biblionumber,
273
            start_date => $start_1,
274
            end_date => $end_1
275
        }
276
    )->store();
277
    ok($booking->in_storage, 'Booking stored OK when item not specified and the booking slot is available');
278
    ok($booking->item_id, 'An item was assigned to the booking');
96
279
280
    $schema->storage->txn_rollback;
97
};
281
};
98
- 

Return to bug 35248