Bugzilla – Attachment 138213 Details for
Bug 22456
Allow patrons to cancel their waiting holds
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 22456: Add cancellation request methods to Koha::Hold
Bug-22456-Add-cancellation-request-methods-to-Koha.patch (text/plain), 10.76 KB, created by
Kyle M Hall (khall)
on 2022-07-28 17:12:20 UTC
(
hide
)
Description:
Bug 22456: Add cancellation request methods to Koha::Hold
Filename:
MIME Type:
Creator:
Kyle M Hall (khall)
Created:
2022-07-28 17:12:20 UTC
Size:
10.76 KB
patch
obsolete
>From 430a7feb3d1b89457c3ad38f7444d24a8f841015 Mon Sep 17 00:00:00 2001 >From: Tomas Cohen Arazi <tomascohen@theke.io> >Date: Wed, 18 May 2022 14:05:04 -0300 >Subject: [PATCH] Bug 22456: Add cancellation request methods to Koha::Hold > >This patch adds the following helper methods for dealing with hold >cancellation requests to the Koha::Hold class: > > * cancellation_requests > * add_cancellation_request > * cancellation_requestable_from_opac > * cancellation_requested_by_owner > >To test: >1. Apply this patch >2. Run: > $ kshell > k$ prove t/db_dependent/Koha/Hold.t >=> SUCCESS: Tests pass! >3. Sign off :-D > >Sponsored-by: Montgomery County Public Libraries > >Signed-off-by: David Nind <david@davidnind.com> > >Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com> >--- > Koha/Exceptions.pm | 5 + > Koha/Hold.pm | 89 +++++++++++++++++ > Koha/Schema/Result/Reserve.pm | 7 ++ > t/db_dependent/Koha/Hold.t | 179 +++++++++++++++++++++++++++++++++- > 4 files changed, 279 insertions(+), 1 deletion(-) > >diff --git a/Koha/Exceptions.pm b/Koha/Exceptions.pm >index 56ab691df20..d257de87a3c 100644 >--- a/Koha/Exceptions.pm >+++ b/Koha/Exceptions.pm >@@ -15,6 +15,11 @@ use Exception::Class ( > isa => 'Koha::Exception', > description => 'Same object already exists', > }, >+ 'Koha::Exceptions::InvalidStatus' => { >+ isa => 'Koha::Exception', >+ description => 'The current status is not valid in context', >+ fields => ['invalid_status'], >+ }, > 'Koha::Exceptions::ObjectNotFound' => { > isa => 'Koha::Exception', > description => 'The required object doesn\'t exist', >diff --git a/Koha/Hold.pm b/Koha/Hold.pm >index 68d0c8581d6..74d1584aef6 100644 >--- a/Koha/Hold.pm >+++ b/Koha/Hold.pm >@@ -30,6 +30,7 @@ use Koha::AuthorisedValues; > use Koha::DateUtils qw( dt_from_string ); > use Koha::Patrons; > use Koha::Biblios; >+use Koha::Hold::CancellationRequests; > use Koha::Items; > use Koha::Libraries; > use Koha::Old::Holds; >@@ -38,6 +39,7 @@ use Koha::Plugins; > > use Koha::BackgroundJob::BatchUpdateBiblioHoldsQueue; > >+use Koha::Exceptions; > use Koha::Exceptions::Hold; > > use base qw(Koha::Object); >@@ -416,6 +418,57 @@ sub is_cancelable_from_opac { > return 0; # if ->is_in_transit or if ->is_waiting or ->is_in_processing > } > >+=head3 cancellation_requestable_from_opac >+ >+ if ( $hold->cancellation_requestable_from_opac ) { ... } >+ >+Returns a I<boolean> representing if a cancellation request can be placed on the hold >+from the OPAC. It targets holds that cannot be cancelled from the OPAC (see the >+B<is_cancelable_from_opac> method above), but for which circulation rules allow >+requesting cancellation. >+ >+Throws a B<Koha::Exceptions::InvalidStatus> exception with the following I<invalid_status> >+values: >+ >+=over 4 >+ >+=item B<'hold_not_waiting'>: the hold is expected to be waiting and it is not. >+ >+=item B<'no_item_linked'>: the waiting hold doesn't have an item properly linked. >+ >+=back >+ >+=cut >+ >+sub cancellation_requestable_from_opac { >+ my ( $self ) = @_; >+ >+ Koha::Exceptions::InvalidStatus->throw( invalid_status => 'hold_not_waiting' ) >+ unless $self->is_waiting; >+ >+ my $item = $self->item; >+ >+ Koha::Exceptions::InvalidStatus->throw( invalid_status => 'no_item_linked' ) >+ unless $item; >+ >+ my $patron = $self->patron; >+ >+ my $controlbranch = $patron->branchcode; >+ >+ if ( C4::Context->preference('ReservesControlBranch') eq 'ItemHomeLibrary' ) { >+ $controlbranch = $item->homebranch; >+ } >+ >+ return Koha::CirculationRules->get_effective_rule( >+ { >+ categorycode => $patron->categorycode, >+ itemtype => $item->itype, >+ branchcode => $controlbranch, >+ rule_name => 'waiting_hold_cancellation', >+ } >+ )->rule_value ? 1 : 0; >+} >+ > =head3 is_at_destination > > Returns true if hold is waiting >@@ -525,6 +578,42 @@ sub is_suspended { > return $self->suspend(); > } > >+=head3 add_cancellation_request >+ >+ my $cancellation_request = $hold->add_cancellation_request({ [ creation_date => $creation_date ] }); >+ >+Adds a cancellation request to the hold. Returns the generated >+I<Koha::Hold::CancellationRequest> object. >+ >+=cut >+ >+sub add_cancellation_request { >+ my ( $self, $params ) = @_; >+ >+ my $request = Koha::Hold::CancellationRequest->new( >+ { hold_id => $self->id, >+ ( $params->{creation_date} ? ( creation_date => $params->{creation_date} ) : () ), >+ } >+ )->store; >+ >+ $request->discard_changes; >+ >+ return $request; >+} >+ >+=head3 cancellation_requests >+ >+ my $cancellation_requests = $hold->cancellation_requests; >+ >+Returns related a I<Koha::Hold::CancellationRequests> resultset. >+ >+=cut >+ >+sub cancellation_requests { >+ my ($self) = @_; >+ >+ return Koha::Hold::CancellationRequests->search( { hold_id => $self->id } ); >+} > > =head3 cancel > >diff --git a/Koha/Schema/Result/Reserve.pm b/Koha/Schema/Result/Reserve.pm >index c280e277592..08aac12c2ed 100644 >--- a/Koha/Schema/Result/Reserve.pm >+++ b/Koha/Schema/Result/Reserve.pm >@@ -486,4 +486,11 @@ __PACKAGE__->belongs_to( > }, > ); > >+__PACKAGE__->has_many( >+ "cancellation_requests", >+ "Koha::Schema::Result::HoldCancellationRequest", >+ { "foreign.hold_id" => "self.reserve_id" }, >+ { cascade_copy => 0, cascade_delete => 0 }, >+); >+ > 1; >diff --git a/t/db_dependent/Koha/Hold.t b/t/db_dependent/Koha/Hold.t >index db5189db400..5aeebd073ae 100755 >--- a/t/db_dependent/Koha/Hold.t >+++ b/t/db_dependent/Koha/Hold.t >@@ -19,7 +19,7 @@ > > use Modern::Perl; > >-use Test::More tests => 7; >+use Test::More tests => 9; > > use Test::Exception; > use Test::MockModule; >@@ -686,3 +686,180 @@ subtest 'suspend_hold() and resume() tests' => sub { > > $schema->storage->txn_rollback; > }; >+ >+subtest 'cancellation_requests() and add_cancellation_request() tests' => sub { >+ >+ plan tests => 4; >+ >+ $schema->storage->txn_begin; >+ >+ t::lib::Mocks::mock_preference( 'RealTimeHoldsQueue', 0 ); >+ >+ my $hold = $builder->build_object( { class => 'Koha::Holds', } ); >+ >+ is( $hold->cancellation_requests->count, 0 ); >+ >+ # Add two cancellation requests >+ my $request_1 = $hold->add_cancellation_request; >+ isnt( $request_1->creation_date, undef, 'creation_date is set' ); >+ >+ my $requester = $builder->build_object( { class => 'Koha::Patrons' } ); >+ my $creation_date = '2021-06-25 14:05:35'; >+ >+ my $request_2 = $hold->add_cancellation_request( >+ { >+ creation_date => $creation_date, >+ } >+ ); >+ >+ is( $request_2->creation_date, $creation_date, 'Passed creation_date set' ); >+ >+ is( $hold->cancellation_requests->count, 2 ); >+ >+ $schema->storage->txn_rollback; >+}; >+ >+subtest 'cancellation_requestable_from_opac() tests' => sub { >+ >+ plan tests => 5; >+ >+ $schema->storage->txn_begin; >+ >+ my $category = >+ $builder->build_object( { class => 'Koha::Patron::Categories' } ); >+ my $item_home_library = >+ $builder->build_object( { class => 'Koha::Libraries' } ); >+ my $patron_home_library = >+ $builder->build_object( { class => 'Koha::Libraries' } ); >+ >+ my $item = >+ $builder->build_sample_item( { library => $item_home_library->id } ); >+ my $patron = $builder->build_object( >+ { >+ class => 'Koha::Patrons', >+ value => { branchcode => $patron_home_library->id } >+ } >+ ); >+ >+ subtest 'Exception cases' => sub { >+ >+ plan tests => 4; >+ >+ my $hold = $builder->build_object( >+ { >+ class => 'Koha::Holds', >+ value => { >+ itemnumber => undef, >+ found => undef, >+ borrowernumber => $patron->id >+ } >+ } >+ ); >+ >+ throws_ok { $hold->cancellation_requestable_from_opac; } >+ 'Koha::Exceptions::InvalidStatus', >+ 'Exception thrown because hold is not waiting'; >+ >+ is( $@->invalid_status, 'hold_not_waiting' ); >+ >+ $hold = $builder->build_object( >+ { >+ class => 'Koha::Holds', >+ value => { >+ itemnumber => undef, >+ found => 'W', >+ borrowernumber => $patron->id >+ } >+ } >+ ); >+ >+ throws_ok { $hold->cancellation_requestable_from_opac; } >+ 'Koha::Exceptions::InvalidStatus', >+ 'Exception thrown because waiting hold has no item linked'; >+ >+ is( $@->invalid_status, 'no_item_linked' ); >+ }; >+ >+ # set default rule to enabled >+ Koha::CirculationRules->set_rule( >+ { >+ categorycode => '*', >+ itemtype => '*', >+ branchcode => '*', >+ rule_name => 'waiting_hold_cancellation', >+ rule_value => 1, >+ } >+ ); >+ >+ my $hold = $builder->build_object( >+ { >+ class => 'Koha::Holds', >+ value => { >+ itemnumber => $item->id, >+ found => 'W', >+ borrowernumber => $patron->id >+ } >+ } >+ ); >+ >+ t::lib::Mocks::mock_preference( 'ReservesControlBranch', >+ 'ItemHomeLibrary' ); >+ >+ Koha::CirculationRules->set_rule( >+ { >+ categorycode => $patron->categorycode, >+ itemtype => $item->itype, >+ branchcode => $item->homebranch, >+ rule_name => 'waiting_hold_cancellation', >+ rule_value => 0, >+ } >+ ); >+ >+ ok( !$hold->cancellation_requestable_from_opac ); >+ >+ Koha::CirculationRules->set_rule( >+ { >+ categorycode => $patron->categorycode, >+ itemtype => $item->itype, >+ branchcode => $item->homebranch, >+ rule_name => 'waiting_hold_cancellation', >+ rule_value => 1, >+ } >+ ); >+ >+ ok( >+ $hold->cancellation_requestable_from_opac, >+ 'Make sure it is picking the right circulation rule' >+ ); >+ >+ t::lib::Mocks::mock_preference( 'ReservesControlBranch', 'PatronLibrary' ); >+ >+ Koha::CirculationRules->set_rule( >+ { >+ categorycode => $patron->categorycode, >+ itemtype => $item->itype, >+ branchcode => $patron->branchcode, >+ rule_name => 'waiting_hold_cancellation', >+ rule_value => 0, >+ } >+ ); >+ >+ ok( !$hold->cancellation_requestable_from_opac ); >+ >+ Koha::CirculationRules->set_rule( >+ { >+ categorycode => $patron->categorycode, >+ itemtype => $item->itype, >+ branchcode => $patron->branchcode, >+ rule_name => 'waiting_hold_cancellation', >+ rule_value => 1, >+ } >+ ); >+ >+ ok( >+ $hold->cancellation_requestable_from_opac, >+ 'Make sure it is picking the right circulation rule' >+ ); >+ >+ $schema->storage->txn_rollback; >+}; >-- >2.30.2
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 22456
:
135165
|
135166
|
135167
|
135168
|
135169
|
135170
|
135171
|
135319
|
135320
|
135321
|
135322
|
135323
|
135324
|
135325
|
135326
|
135349
|
135350
|
135351
|
135352
|
135396
|
135397
|
135398
|
135399
|
135400
|
135401
|
135402
|
135403
|
135404
|
135405
|
135406
|
135407
|
135408
|
135409
|
135410
|
135411
|
135430
|
135830
|
135831
|
135832
|
135838
|
135839
|
135840
|
135841
|
135842
|
135843
|
135844
|
135845
|
135846
|
137580
|
137581
|
137582
|
137583
|
137584
|
137585
|
137586
|
137587
|
137588
|
137589
|
137591
|
138209
|
138210
|
138211
|
138212
| 138213 |
138214
|
138215
|
138216
|
138217
|
138218