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