f726558510
Refactor the most performance critical subroutines in Circulation.pm to take objects instead of unblessed ones to reduce unnecessary unblessings and generally clean up the code. To test: 1) Ensure the following tests all pass: t/db_dependent/Circulation.t t/db_dependent/Circulation/CalcDateDue.t t/db_dependent/Circulation/CheckIfIssuedToPatron.t t/db_dependent/Circulation/GetPendingOnSiteCheckouts.t t/db_dependent/Circulation/GetTopIssues.t t/db_dependent/Circulation/IsItemIssued.t t/db_dependent/Circulation/MarkIssueReturned.t t/db_dependent/Circulation/ReturnClaims.t t/db_dependent/Circulation/Returns.t t/db_dependent/Circulation/SwitchOnSiteCheckouts.t t/db_dependent/Circulation/TooMany.t t/db_dependent/Circulation/dateexpiry.t t/db_dependent/Circulation/issue.t t/db_dependent/Circulation/maxsuspensiondays.t t/db_dependent/Circulation/transferbook.t t/db_dependent/Circulation_holdsqueue.t t/db_dependent/DecreaseLoanHighHolds.t t/db_dependent/Holds/DisallowHoldIfItemsAvailable.t t/db_dependent/Holds/RevertWaitingStatus.t t/db_dependent/ILSDI_Services.t t/db_dependent/Illrequests.t t/db_dependent/Koha/Account/Line.t t/db_dependent/Koha/Biblio.t t/db_dependent/Koha/Items.t t/db_dependent/Koha/Object.t t/db_dependent/Koha/Patrons.t t/db_dependent/Koha/Pseudonymization.t t/db_dependent/Koha/Template/Plugin/CirculationRules.t t/db_dependent/Letters/TemplateToolkit.t t/db_dependent/Members/GetAllIssues.t t/db_dependent/Members/IssueSlip.t t/db_dependent/Patron/Borrower_Discharge.t t/db_dependent/Patron/Borrower_PrevCheckout.t t/db_dependent/SIP/ILS.t t/db_dependent/Holds.t t/db_dependent/Holds/LocalHoldsPriority.t t/db_dependent/Holds/HoldFulfillmentPolicy.t t/db_dependent/Holds/HoldItemtypeLimit.t t/db_dependent/Reserves/GetReserveFee.t t/db_dependent/api/v1/return_claims.t t/db_dependent/api/v1/biblios.t t/db_dependent/api/v1/checkouts.t t/db_dependent/Reserves.t t/db_dependent/HoldsQueue.t t/db_dependent/selenium/regressions.t t/db_dependent/Koha/Plugins/Circulation_hooks.t t/db_dependent/Koha/Plugins/Recall_hooks.t t/db_dependent/Koha/Recalls.t t/db_dependent/Koha/Recall.t t/db_dependent/Circulation/_CalculateAndUpdateFine.t Sponsored-by: Gothenburg University Library Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org> Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl> Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
305 lines
7.7 KiB
Perl
305 lines
7.7 KiB
Perl
package Koha::CurbsidePickup;
|
|
|
|
# This file is part of Koha.
|
|
#
|
|
# Koha is free software; you can redistribute it and/or modify it
|
|
# under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# Koha is distributed in the hope that it will be useful, but
|
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with Koha; if not, see <http://www.gnu.org/licenses>.
|
|
|
|
use Modern::Perl;
|
|
|
|
use Carp;
|
|
|
|
use Koha::Database;
|
|
|
|
use base qw(Koha::Object);
|
|
|
|
use C4::Circulation qw( CanBookBeIssued AddIssue );
|
|
use C4::Members::Messaging qw( GetMessagingPreferences );
|
|
use C4::Letters qw( GetPreparedLetter EnqueueLetter );
|
|
use Koha::Calendar;
|
|
use Koha::DateUtils qw( dt_from_string );
|
|
use Koha::Patron;
|
|
use Koha::Library;
|
|
use Koha::CurbsidePickupIssues;
|
|
use Koha::Exceptions::CurbsidePickup;
|
|
|
|
=head1 NAME
|
|
|
|
Koha::CurbsidePickup - Koha Curbside Pickup Object class
|
|
|
|
=head1 API
|
|
|
|
=head2 Class methods
|
|
|
|
=cut
|
|
|
|
=head3 new
|
|
|
|
=cut
|
|
|
|
sub new {
|
|
my ( $self, $params ) = @_;
|
|
|
|
my $policy =
|
|
Koha::CurbsidePickupPolicies->find( { branchcode => $params->{branchcode} } );
|
|
|
|
Koha::Exceptions::CurbsidePickup::NotEnabled->throw
|
|
unless $policy && $policy->enabled;
|
|
|
|
my $calendar = Koha::Calendar->new( branchcode => $params->{branchcode} );
|
|
Koha::Exceptions::CurbsidePickup::LibraryIsClosed->throw
|
|
if $calendar->is_holiday( $params->{scheduled_pickup_datetime} );
|
|
|
|
if ( $policy->enable_waiting_holds_only ) {
|
|
my $patron = Koha::Patrons->find( $params->{borrowernumber} );
|
|
my $waiting_holds = $patron->holds->waiting->search( { branchcode => $params->{branchcode} } );
|
|
|
|
Koha::Exceptions::CurbsidePickup::NoWaitingHolds->throw
|
|
unless $waiting_holds->count;
|
|
}
|
|
my $existing_curbside_pickups = Koha::CurbsidePickups->search(
|
|
{
|
|
branchcode => $params->{branchcode},
|
|
borrowernumber => $params->{borrowernumber},
|
|
delivered_datetime => undef,
|
|
}
|
|
)->filter_by_scheduled_today;
|
|
Koha::Exceptions::CurbsidePickup::TooManyPickups->throw(
|
|
branchcode => $params->{branchcode},
|
|
borrowernumber => $params->{borrowernumber}
|
|
) if $existing_curbside_pickups->count;
|
|
|
|
my $is_valid =
|
|
$policy->is_valid_pickup_datetime( $params->{scheduled_pickup_datetime} );
|
|
unless ($is_valid) {
|
|
my $error = @{ $is_valid->messages }[0]->message;
|
|
Koha::Exceptions::CurbsidePickup::NoMatchingSlots->throw
|
|
if $error eq 'no_matching_slots';
|
|
Koha::Exceptions::CurbsidePickup::NoMorePickupsAvailable->throw
|
|
if $error eq 'no_more_available';
|
|
Koha::Exceptions->throw(
|
|
"Error message must raise the appropriate exception");
|
|
}
|
|
|
|
return $self->SUPER::new($params);
|
|
}
|
|
|
|
=head3 notify_new_pickup
|
|
|
|
$pickup->notify_new_pickup
|
|
|
|
Will notify the patron that the pickup has been created.
|
|
Letter 'NEW_CURBSIDE_PICKUP will be used', and depending on 'Hold_Filled' configuration.
|
|
|
|
=cut
|
|
|
|
sub notify_new_pickup {
|
|
my ( $self ) = @_;
|
|
|
|
my $patron = $self->patron;
|
|
|
|
my $library = $self->library;
|
|
|
|
$patron->queue_notice({ letter_params => {
|
|
module => 'reserves',
|
|
letter_code => 'NEW_CURBSIDE_PICKUP',
|
|
borrowernumber => $patron->borrowernumber,
|
|
branchcode => $self->branchcode,
|
|
tables => {
|
|
'branches' => $library->unblessed,
|
|
'borrowers' => $patron->unblessed,
|
|
},
|
|
substitute => {
|
|
curbside_pickup => $self,
|
|
}
|
|
}, message_name => 'Hold_Filled' });
|
|
}
|
|
|
|
=head3 checkouts
|
|
|
|
Return the checkouts linked to this pickup
|
|
|
|
=cut
|
|
|
|
sub checkouts {
|
|
my ( $self ) = @_;
|
|
|
|
my @pi = Koha::CurbsidePickupIssues->search({ curbside_pickup_id => $self->id })->as_list;
|
|
|
|
my @checkouts = map { $_->checkout } @pi;
|
|
@checkouts = grep { defined $_ } @checkouts;
|
|
|
|
return @checkouts;
|
|
}
|
|
|
|
=head3 patron
|
|
|
|
Return the patron linked to this pickup
|
|
|
|
=cut
|
|
|
|
sub patron {
|
|
my ( $self ) = @_;
|
|
my $rs = $self->_result->borrowernumber;
|
|
return unless $rs;
|
|
return Koha::Patron->_new_from_dbic( $rs );
|
|
}
|
|
|
|
=head3 staged_by_staff
|
|
|
|
Return the staff member that staged this pickup
|
|
|
|
=cut
|
|
|
|
sub staged_by_staff {
|
|
my ( $self ) = @_;
|
|
my $rs = $self->_result->staged_by;
|
|
return unless $rs;
|
|
return Koha::Patron->_new_from_dbic( $rs );
|
|
}
|
|
|
|
=head3 library
|
|
|
|
Return the branch associated with this pickup
|
|
|
|
=cut
|
|
|
|
sub library {
|
|
my ( $self ) = @_;
|
|
my $rs = $self->_result->branchcode;
|
|
return unless $rs;
|
|
return Koha::Library->_new_from_dbic( $rs );
|
|
}
|
|
|
|
=head3 mark_as_staged
|
|
|
|
Mark the pickup as staged
|
|
|
|
=cut
|
|
|
|
sub mark_as_staged {
|
|
my ( $self ) = @_;
|
|
my $staged_by = C4::Context->userenv ? C4::Context->userenv->{number} : undef;
|
|
$self->set(
|
|
{
|
|
staged_datetime => dt_from_string(),
|
|
staged_by => $staged_by,
|
|
arrival_datetime => undef,
|
|
}
|
|
)->store;
|
|
}
|
|
|
|
=head3 mark_as_unstaged
|
|
|
|
Mark the pickup as unstaged
|
|
|
|
=cut
|
|
|
|
sub mark_as_unstaged {
|
|
my ( $self ) = @_;
|
|
|
|
$self->set(
|
|
{
|
|
staged_datetime => undef,
|
|
staged_by => undef,
|
|
arrival_datetime => undef,
|
|
}
|
|
)->store;
|
|
}
|
|
|
|
=head3 mark_patron_has_arrived
|
|
|
|
Set the arrival time of the patron
|
|
|
|
=cut
|
|
|
|
sub mark_patron_has_arrived {
|
|
my ( $self ) = @_;
|
|
$self->set(
|
|
{
|
|
arrival_datetime => dt_from_string(),
|
|
}
|
|
)->store;
|
|
}
|
|
|
|
=head3 mark_as_delivered
|
|
|
|
Mark the pickup as delivered. The waiting holds will be filled.
|
|
|
|
=cut
|
|
|
|
sub mark_as_delivered {
|
|
my ( $self ) = @_;
|
|
my $patron = $self->patron;
|
|
my $holds = $patron->holds;
|
|
my $branchcode = C4::Context->userenv ? C4::Context->userenv->{branch} : undef;
|
|
foreach my $hold ( $holds->as_list ) {
|
|
if ( $hold->is_waiting && $branchcode && $hold->branchcode eq $branchcode ) {
|
|
my ( $issuingimpossible, $needsconfirmation ) =
|
|
C4::Circulation::CanBookBeIssued( $patron, $hold->item->barcode );
|
|
|
|
unless ( keys %$issuingimpossible ) {
|
|
my $issue =
|
|
C4::Circulation::AddIssue( $patron, $hold->item->barcode );
|
|
if ($issue) {
|
|
Koha::CurbsidePickupIssue->new(
|
|
{
|
|
curbside_pickup_id => $self->id,
|
|
issue_id => $issue->id,
|
|
reserve_id => $hold->id,
|
|
}
|
|
)->store();
|
|
}
|
|
else {
|
|
Koha::Exceptions->throw(sprintf("Cannot checkout hold %s for patron %s: %s", $patron->id, $hold->id, join(", ", keys %$issuingimpossible)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
my $delivered_by = C4::Context->userenv ? C4::Context->userenv->{number} : undef;
|
|
$self->arrival_datetime(dt_from_string) unless $self->arrival_datetime;
|
|
$self->set(
|
|
{
|
|
delivered_datetime => dt_from_string(),
|
|
delivered_by => $delivered_by,
|
|
}
|
|
)->store;
|
|
}
|
|
|
|
=head3 status
|
|
|
|
Return the status of the pickup, can be 'to-be-staged', 'staged-and-ready', 'patron-is-outside' or 'delivered'.
|
|
|
|
=cut
|
|
|
|
sub status {
|
|
my ($self) = @_;
|
|
return
|
|
!defined $self->staged_datetime ? 'to-be-staged'
|
|
: !defined $self->arrival_datetime ? 'staged-and-ready'
|
|
: !defined $self->delivered_datetime ? 'patron-is-outside'
|
|
: 'delivered';
|
|
}
|
|
|
|
=head2 Internal methods
|
|
|
|
=head3 _type
|
|
|
|
=cut
|
|
|
|
sub _type {
|
|
return 'CurbsidePickup';
|
|
}
|
|
|
|
1;
|