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