1 package Koha::CurbsidePickup;
3 # This file is part of Koha.
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.
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.
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>.
24 use base qw(Koha::Object);
26 use C4::Circulation qw( CanBookBeIssued AddIssue );
27 use C4::Members::Messaging qw( GetMessagingPreferences );
28 use C4::Letters qw( GetPreparedLetter EnqueueLetter );
30 use Koha::DateUtils qw( dt_from_string );
33 use Koha::CurbsidePickupIssues;
34 use Koha::Exceptions::CurbsidePickup;
38 Koha::CurbsidePickup - Koha Curbside Pickup Object class
51 my ( $self, $params ) = @_;
54 Koha::CurbsidePickupPolicies->find( { branchcode => $params->{branchcode} } );
56 Koha::Exceptions::CurbsidePickup::NotEnabled->throw
57 unless $policy && $policy->enabled;
59 my $calendar = Koha::Calendar->new( branchcode => $params->{branchcode} );
60 Koha::Exceptions::CurbsidePickup::LibraryIsClosed->throw
61 if $calendar->is_holiday( $params->{scheduled_pickup_datetime} );
63 if ( $policy->enable_waiting_holds_only ) {
64 my $patron = Koha::Patrons->find( $params->{borrowernumber} );
65 my $waiting_holds = $patron->holds->search(
66 { found => 'W', branchcode => $params->{branchcode} } );
68 Koha::Exceptions::CurbsidePickup::NoWaitingHolds->throw
69 unless $waiting_holds->count;
71 my $existing_curbside_pickups = Koha::CurbsidePickups->search(
73 branchcode => $params->{branchcode},
74 borrowernumber => $params->{borrowernumber},
75 delivered_datetime => undef,
77 )->filter_by_scheduled_today;
78 Koha::Exceptions::CurbsidePickup::TooManyPickups->throw(
79 branchcode => $params->{branchcode},
80 borrowernumber => $params->{borrowernumber}
81 ) if $existing_curbside_pickups->count;
84 $policy->is_valid_pickup_datetime( $params->{scheduled_pickup_datetime} );
86 my $error = @{ $is_valid->messages }[0]->message;
87 Koha::Exceptions::CurbsidePickup::NoMatchingSlots->throw
88 if $error eq 'no_matching_slots';
89 Koha::Exceptions::CurbsidePickup::NoMorePickupsAvailable->throw
90 if $error eq 'no_more_available';
91 Koha::Exceptions->throw(
92 "Error message must raise the appropriate exception");
95 return $self->SUPER::new($params);
98 =head3 notify_new_pickup
100 $pickup->notify_new_pickup
102 Will notify the patron that the pickup has been created.
103 Letter 'NEW_CURBSIDE_PICKUP will be used', and depending on 'Hold_Filled' configuration.
107 sub notify_new_pickup {
110 my $patron = $self->patron;
112 my $library = $self->library;
114 $patron->queue_notice({ letter_params => {
115 module => 'reserves',
116 letter_code => 'NEW_CURBSIDE_PICKUP',
117 borrowernumber => $patron->borrowernumber,
118 branchcode => $self->branchcode,
120 'branches' => $library->unblessed,
121 'borrowers' => $patron->unblessed,
124 curbside_pickup => $self,
126 }, message_name => 'Hold_Filled' });
131 Return the checkouts linked to this pickup
138 my @pi = Koha::CurbsidePickupIssues->search({ curbside_pickup_id => $self->id })->as_list;
140 my @checkouts = map { $_->checkout } @pi;
141 @checkouts = grep { defined $_ } @checkouts;
148 Return the patron linked to this pickup
154 my $rs = $self->_result->borrowernumber;
156 return Koha::Patron->_new_from_dbic( $rs );
159 =head3 staged_by_staff
161 Return the staff member that staged this pickup
165 sub staged_by_staff {
167 my $rs = $self->_result->staged_by;
169 return Koha::Patron->_new_from_dbic( $rs );
174 Return the branch associated with this pickup
180 my $rs = $self->_result->branchcode;
182 return Koha::Library->_new_from_dbic( $rs );
185 =head3 mark_as_staged
187 Mark the pickup as staged
193 my $staged_by = C4::Context->userenv ? C4::Context->userenv->{number} : undef;
196 staged_datetime => dt_from_string(),
197 staged_by => $staged_by,
198 arrival_datetime => undef,
203 =head3 mark_as_unstaged
205 Mark the pickup as unstaged
209 sub mark_as_unstaged {
214 staged_datetime => undef,
216 arrival_datetime => undef,
221 =head3 mark_patron_has_arrived
223 Set the arrival time of the patron
227 sub mark_patron_has_arrived {
231 arrival_datetime => dt_from_string(),
236 =head3 mark_as_delivered
238 Mark the pickup as delivered. The waiting holds will be filled.
242 sub mark_as_delivered {
244 my $patron = $self->patron;
245 my $holds = $patron->holds;
246 my $branchcode = C4::Context->userenv ? C4::Context->userenv->{branch} : undef;
247 foreach my $hold ( $holds->as_list ) {
248 if ( $hold->found eq 'W' && $branchcode && $hold->branchcode eq $branchcode ) {
249 my ( $issuingimpossible, $needsconfirmation ) =
250 C4::Circulation::CanBookBeIssued( $patron, $hold->item->barcode );
252 unless ( keys %$issuingimpossible ) {
254 C4::Circulation::AddIssue( $patron->unblessed, $hold->item->barcode );
256 Koha::CurbsidePickupIssue->new(
258 curbside_pickup_id => $self->id,
259 issue_id => $issue->id,
260 reserve_id => $hold->id,
265 Koha::Exceptions->throw(sprintf("Cannot checkout hold %s for patron %s: %s", $patron->id, $hold->id, join(", ", keys %$issuingimpossible)));
271 my $delivered_by = C4::Context->userenv ? C4::Context->userenv->{number} : undef;
272 $self->arrival_datetime(dt_from_string) unless $self->arrival_datetime;
275 delivered_datetime => dt_from_string(),
276 delivered_by => $delivered_by,
283 Return the status of the pickup, can be 'to-be-staged', 'staged-and-ready', 'patron-is-outside' or 'delivered'.
290 !defined $self->staged_datetime ? 'to-be-staged'
291 : !defined $self->arrival_datetime ? 'staged-and-ready'
292 : !defined $self->delivered_datetime ? 'patron-is-outside'
296 =head2 Internal methods
303 return 'CurbsidePickup';