Bug 32171: Store after populating order
[koha.git] / t / db_dependent / Koha / CurbsidePickups.t
1 #!/usr/bin/perl
2
3 # This file is part of Koha
4 #
5 # Koha is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # Koha is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18 use Modern::Perl;
19
20 use Test::More tests => 4;
21 use Test::Exception;
22
23 use C4::Calendar;
24 use Koha::CurbsidePickups;
25 use Koha::CurbsidePickupPolicies;
26 use Koha::Calendar;
27 use Koha::Database;
28 use Koha::DateUtils qw( dt_from_string );
29
30 use t::lib::TestBuilder;
31 use t::lib::Dates;
32 use t::lib::Mocks;
33
34 my $schema = Koha::Database->new->schema;
35 $schema->storage->txn_begin;
36
37 my $builder          = t::lib::TestBuilder->new;
38 my $library          = $builder->build_object( { class => 'Koha::Libraries' } );
39 my $library_disabled = $builder->build_object( { class => 'Koha::Libraries' } );
40 my $logged_in_patron = $builder->build_object(
41     {
42         class => 'Koha::Patrons',
43         value => { branchcode => $library->branchcode }
44     }
45 );
46 t::lib::Mocks::mock_userenv( { patron => $logged_in_patron } );
47 my $patron = $builder->build_object(
48     {
49         class => 'Koha::Patrons',
50         value => { branchcode => $library->branchcode }
51     }
52 );
53
54 my $policy = Koha::CurbsidePickupPolicy->new(
55     {
56         branchcode              => $library->branchcode,
57         enabled                 => 1,
58         enable_waiting_holds_only => 0,
59         pickup_interval         => 30,
60         patrons_per_interval    => 2,
61         patron_scheduled_pickup => 1
62     }
63 )->store;
64 my $policy_disabled = Koha::CurbsidePickupPolicy->new(
65     {
66         branchcode              => $library_disabled->branchcode,
67         enabled                 => 0,
68         enable_waiting_holds_only => 0,
69         pickup_interval         => 30,
70         patrons_per_interval    => 2,
71         patron_scheduled_pickup => 1
72     }
73 )->store;
74
75 # Open Mondays from 12 to 18
76 $policy->add_opening_slot('1-12:00-18:00');
77
78 my $today = dt_from_string;
79
80 subtest 'Create a pickup' => sub {
81     plan tests => 9;
82
83     # Day and datetime are ok
84     my $next_monday =
85       $today->clone->add( days => ( 1 - $today->day_of_week ) % 7 );
86     my $schedule_dt =
87       $next_monday->set_hour(15)->set_minute(00)->set_second(00);
88     my $params =
89         {
90             branchcode                => $library->branchcode,
91             borrowernumber            => $patron->borrowernumber,
92             scheduled_pickup_datetime => $schedule_dt,
93             notes                     => 'just a note'
94         };
95
96     throws_ok {
97         Koha::CurbsidePickup->new({%$params, branchcode => $library_disabled->branchcode})->store;
98     }
99     'Koha::Exceptions::CurbsidePickup::NotEnabled',
100       'Cannot create pickup if the policy does not allow it';
101
102     $policy->enable_waiting_holds_only(1)->store;
103     throws_ok {
104         Koha::CurbsidePickup->new($params)->store;
105     }
106     'Koha::Exceptions::CurbsidePickup::NoWaitingHolds',
107       'Cannot create pickup for a patron without waiting hold if flag is set';
108
109     $policy->enable_waiting_holds_only(0)->store;
110     my $cp = Koha::CurbsidePickup->new($params)->store;
111     is( $cp->status, 'to-be-staged' );
112     is( $patron->curbside_pickups->count, 1, 'Koha::Patron->curbside_pickups' );
113
114     throws_ok {
115         Koha::CurbsidePickup->new($params)->store
116     }
117     'Koha::Exceptions::CurbsidePickup::TooManyPickups',
118       'Cannot create 2 pickups for the same patron';
119
120     $cp->delete;
121
122     # Day is not ok
123     my $next_tuesday =
124       $today->clone->add( days => ( 2 - $today->day_of_week ) % 7 );
125     $schedule_dt = $next_tuesday->set_hour(15)->set_minute(00)->set_second(00);
126     throws_ok {
127         Koha::CurbsidePickup->new({%$params, scheduled_pickup_datetime => $schedule_dt})->store;
128     }
129     'Koha::Exceptions::CurbsidePickup::NoMatchingSlots',
130       'Cannot create a pickup on a day without opening slots defined';
131
132     # Day ok but datetime not ok
133     $schedule_dt = $next_monday->set_hour(19)->set_minute(00)->set_second(00);
134     throws_ok {
135         Koha::CurbsidePickup->new({%$params, scheduled_pickup_datetime => $schedule_dt})->store;
136     }
137     'Koha::Exceptions::CurbsidePickup::NoMatchingSlots',
138       'Cannot create a pickup on a time without opening slots defined';
139
140     # Day ok, datetime inside the opening slot, but wrong (15:15 for instance)
141     $schedule_dt = $next_monday->set_hour(15)->set_minute(15)->set_second(00);
142     throws_ok {
143         Koha::CurbsidePickup->new({%$params, scheduled_pickup_datetime => $schedule_dt})->store;
144     }
145     'Koha::Exceptions::CurbsidePickup::NoMatchingSlots',
146 'Cannot create a pickup on a time that is not matching the start of an interval';
147
148     # Day is a holiday
149     Koha::Caches->get_instance->flush_all;
150     C4::Calendar->new( branchcode => $library->branchcode )->insert_week_day_holiday(
151         weekday     => 1,
152         title       => '',
153         description => 'Mondays',
154     );
155     my $calendar = Koha::Calendar->new( branchcode => $library->branchcode );
156     throws_ok {
157         Koha::CurbsidePickup->new({%$params, scheduled_pickup_datetime => $schedule_dt})->store;
158     }
159     'Koha::Exceptions::CurbsidePickup::LibraryIsClosed',
160       'Cannot create a pickup on a holiday';
161
162     C4::Context->dbh->do(q{DELETE FROM repeatable_holidays});
163     Koha::Caches->get_instance->flush_all;
164 };
165
166 subtest 'workflow' => sub {
167     plan tests => 11;
168
169     my $pickups =
170       Koha::CurbsidePickups->search( { branchcode => $library->branchcode } );
171
172     my $next_monday =
173       $today->clone->add( days => ( 1 - $today->day_of_week ) % 7 );
174     my $schedule_dt =
175       $next_monday->set_hour(15)->set_minute(00)->set_second(00);
176     my $cp = Koha::CurbsidePickup->new(
177         {
178             branchcode                => $library->branchcode,
179             borrowernumber            => $patron->borrowernumber,
180             scheduled_pickup_datetime => $schedule_dt,
181             notes                     => 'just a note'
182         }
183     )->store;
184     is( $cp->status, 'to-be-staged' );
185     is( $pickups->filter_by_to_be_staged->count, 1 );
186
187     $cp->mark_as_staged;
188     is( $cp->status, 'staged-and-ready' );
189     is( $pickups->filter_by_staged_and_ready->count, 1 );
190
191     $cp->mark_as_unstaged;
192     is( $cp->status, 'to-be-staged' );
193
194     $cp->mark_as_staged;
195
196     $cp->mark_patron_has_arrived;
197     is( $cp->status, 'patron-is-outside' );
198     is( $pickups->filter_by_patron_outside->count, 1 );
199
200     $cp->mark_as_delivered;
201     is( $cp->status, 'delivered' );
202     is( $pickups->filter_by_delivered->count, 1 );
203
204     is( $pickups->filter_by_scheduled_today->count, 1 );
205     $cp->scheduled_pickup_datetime($today->clone->subtract(days => 1))->store;
206     is( $pickups->filter_by_scheduled_today->count, 0 );
207
208     $cp->delete;
209 };
210
211 subtest 'mark_as_delivered' => sub {
212     plan tests => 3;
213
214     my $item = $builder->build_sample_item({ library => $library->branchcode });
215     my $reserve_id = C4::Reserves::AddReserve(
216         {
217             branchcode     => $library->branchcode,
218             borrowernumber => $patron->borrowernumber,
219             biblionumber   => $item->biblionumber,
220             priority       => 1,
221             itemnumber     => $item->itemnumber,
222         }
223     );
224     my $hold = Koha::Holds->find($reserve_id);
225     $hold->set_waiting;
226
227     my $next_monday =
228       $today->clone->add( days => ( 1 - $today->day_of_week ) % 7 );
229     my $schedule_dt =
230       $next_monday->set_hour(15)->set_minute(00)->set_second(00);
231     my $cp = Koha::CurbsidePickup->new(
232         {
233             branchcode                => $library->branchcode,
234             borrowernumber            => $patron->borrowernumber,
235             scheduled_pickup_datetime => $schedule_dt,
236             notes                     => 'just a note'
237         }
238     )->store;
239
240     $cp->mark_as_delivered;
241     $cp->discard_changes;
242     is( t::lib::Dates::compare( $cp->arrival_datetime, dt_from_string), 0, 'Arrival time has been set to now' );
243
244     is( $hold->get_from_storage, undef, 'Hold has been filled' );
245     my $checkout = Koha::Checkouts->find({ itemnumber => $item->itemnumber });
246     is( $checkout->borrowernumber, $patron->borrowernumber, 'Item has correctly been checked out' );
247
248     $cp->delete;
249 };
250
251 subtest 'notify_new_pickup' => sub {
252     plan tests => 2;
253
254     my $item =
255       $builder->build_sample_item( { library => $library->branchcode } );
256     my $reserve_id = C4::Reserves::AddReserve(
257         {
258             branchcode     => $library->branchcode,
259             borrowernumber => $patron->borrowernumber,
260             biblionumber   => $item->biblionumber,
261             priority       => 1,
262             itemnumber     => $item->itemnumber,
263         }
264     );
265     my $hold = Koha::Holds->find($reserve_id);
266     $hold->set_waiting;
267
268     my $next_monday =
269       $today->clone->add( days => ( 1 - $today->day_of_week ) % 7 );
270     my $schedule_dt =
271       $next_monday->set_hour(15)->set_minute(00)->set_second(00);
272     my $cp = Koha::CurbsidePickup->new(
273         {
274             branchcode                => $library->branchcode,
275             borrowernumber            => $patron->borrowernumber,
276             scheduled_pickup_datetime => $schedule_dt,
277             notes                     => 'just a note'
278         }
279     )->store;
280
281     $patron->set( { email => 'test@example.org' } )->store;
282     my $dbh = C4::Context->dbh;
283     $dbh->do( q|INSERT INTO borrower_message_preferences( borrowernumber, message_attribute_id ) VALUES ( ?, ?)|,
284         undef, $patron->borrowernumber, 4
285     );
286     my $borrower_message_preference_id =
287       $dbh->last_insert_id( undef, undef, "borrower_message_preferences", undef );
288     $dbh->do(
289         q|INSERT INTO borrower_message_transport_preferences( borrower_message_preference_id, message_transport_type) VALUES ( ?, ? )|,
290         undef, $borrower_message_preference_id, 'email'
291     );
292
293     $cp->notify_new_pickup;
294
295     my $messages = C4::Letters::GetQueuedMessages(
296         { borrowernumber => $patron->borrowernumber } );
297     is(
298         $messages->[0]->{subject},
299         sprintf ("You have scheduled a curbside pickup for %s", $library->branchname),
300         "Notice correctly generated"
301     );
302     my $biblio_title = $item->biblio->title;
303     like( $messages->[0]->{content},
304         qr{$biblio_title}, "Content contains the list of waiting holds" );
305 };
306
307 $schema->storage->txn_rollback;