Bug 30650: Add link from the circ patron page
[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 => 9;
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     $cp->delete;
188 };
189
190 subtest 'mark_as_delivered' => sub {
191     plan tests => 3;
192
193     my $item = $builder->build_sample_item({ library => $library->branchcode });
194     my $reserve_id = C4::Reserves::AddReserve(
195         {
196             branchcode     => $library->branchcode,
197             borrowernumber => $patron->borrowernumber,
198             biblionumber   => $item->biblionumber,
199             priority       => 1,
200             itemnumber     => $item->itemnumber,
201         }
202     );
203     my $hold = Koha::Holds->find($reserve_id);
204     $hold->set_waiting;
205
206     my $next_monday =
207       $today->clone->add( days => ( 1 - $today->day_of_week ) % 7 );
208     my $schedule_dt =
209       $next_monday->set_hour(15)->set_minute(00)->set_second(00);
210     my $cp = Koha::CurbsidePickup->new(
211         {
212             branchcode                => $library->branchcode,
213             borrowernumber            => $patron->borrowernumber,
214             scheduled_pickup_datetime => $schedule_dt,
215             notes                     => 'just a note'
216         }
217     )->store;
218
219     $cp->mark_as_delivered;
220     $cp->discard_changes;
221     is( t::lib::Dates::compare( $cp->arrival_datetime, dt_from_string), 0, 'Arrival time has been set to now' );
222
223     is( $hold->get_from_storage, undef, 'Hold has been filled' );
224     my $checkout = Koha::Checkouts->find({ itemnumber => $item->itemnumber });
225     is( $checkout->borrowernumber, $patron->borrowernumber, 'Item has correctly been checked out' );
226
227     $cp->delete;
228 };
229
230 subtest 'notify_new_pickup' => sub {
231     plan tests => 2;
232
233     my $item =
234       $builder->build_sample_item( { library => $library->branchcode } );
235     my $reserve_id = C4::Reserves::AddReserve(
236         {
237             branchcode     => $library->branchcode,
238             borrowernumber => $patron->borrowernumber,
239             biblionumber   => $item->biblionumber,
240             priority       => 1,
241             itemnumber     => $item->itemnumber,
242         }
243     );
244     my $hold = Koha::Holds->find($reserve_id);
245     $hold->set_waiting;
246
247     my $next_monday =
248       $today->clone->add( days => ( 1 - $today->day_of_week ) % 7 );
249     my $schedule_dt =
250       $next_monday->set_hour(15)->set_minute(00)->set_second(00);
251     my $cp = Koha::CurbsidePickup->new(
252         {
253             branchcode                => $library->branchcode,
254             borrowernumber            => $patron->borrowernumber,
255             scheduled_pickup_datetime => $schedule_dt,
256             notes                     => 'just a note'
257         }
258     )->store;
259
260     $patron->set( { email => 'test@example.org' } )->store;
261     my $dbh = C4::Context->dbh;
262     $dbh->do( q|INSERT INTO borrower_message_preferences( borrowernumber, message_attribute_id ) VALUES ( ?, ?)|,
263         undef, $patron->borrowernumber, 4
264     );
265     my $borrower_message_preference_id =
266       $dbh->last_insert_id( undef, undef, "borrower_message_preferences", undef );
267     $dbh->do(
268         q|INSERT INTO borrower_message_transport_preferences( borrower_message_preference_id, message_transport_type) VALUES ( ?, ? )|,
269         undef, $borrower_message_preference_id, 'email'
270     );
271
272     $cp->notify_new_pickup;
273
274     my $messages = C4::Letters::GetQueuedMessages(
275         { borrowernumber => $patron->borrowernumber } );
276     is(
277         $messages->[0]->{subject},
278         sprintf ("You have schedule a curbside pickup for %s.", $library->branchname),
279         "Notice correctly generated"
280     );
281     my $biblio_title = $item->biblio->title;
282     like( $messages->[0]->{content},
283         qr{$biblio_title}, "Content contains the list of waiting holds" );
284 };
285
286 $schema->storage->txn_rollback;