Bugzilla – Attachment 181232 Details for
Bug 31698
Add ability to move a hold to a new bibliographic record/item
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 31698: Add support for moving record level holds
Bug-31698-Add-support-for-moving-record-level-hold.patch (text/plain), 14.65 KB, created by
Lucas Gass (lukeg)
on 2025-04-21 21:35:49 UTC
(
hide
)
Description:
Bug 31698: Add support for moving record level holds
Filename:
MIME Type:
Creator:
Lucas Gass (lukeg)
Created:
2025-04-21 21:35:49 UTC
Size:
14.65 KB
patch
obsolete
>From 529ea2f4ce1302290ddd3a27c31db9d9503a592a Mon Sep 17 00:00:00 2001 >From: Lucas Gass <lucas@bywatersolutions.com> >Date: Mon, 21 Apr 2025 21:35:01 +0000 >Subject: [PATCH] Bug 31698: Add support for moving record level holds > >--- > Koha/Hold.pm | 52 ++++++++ > .../prog/en/modules/reserve/request.tt | 125 +++++++++++++++++- > reserve/request.pl | 41 +++--- > 3 files changed, 193 insertions(+), 25 deletions(-) > >diff --git a/Koha/Hold.pm b/Koha/Hold.pm >index 392cda0e234..1de478c35fd 100644 >--- a/Koha/Hold.pm >+++ b/Koha/Hold.pm >@@ -230,6 +230,58 @@ sub move_hold_item { > return $self; > } > >+=head3 move_hold_biblio >+ >+$hold->move_hold_biblio(); >+ >+=cut >+ >+sub move_hold_biblio { >+ my ( $self, $args ) = @_; >+ >+ my $new_biblionumber = $args->{new_biblionumber}; >+ >+ my $original = $self; >+ my $original_biblionumber = $self->biblionumber; >+ >+ my $patron = Koha::Patrons->find( { borrowernumber => $self->borrowernumber } ); >+ >+ if ($new_biblionumber) { >+ >+ #check to see if moving this hold is allowed >+ my $canReserve = C4::Reserves::CanBookBeReserved( >+ $patron->borrowernumber, $new_biblionumber, $self->branchcode, >+ { ignore_hold_counts => 1 } >+ ); >+ >+ if ( $canReserve->{status} eq 'OK' ) { >+ my $max = Koha::Holds->search( >+ { biblionumber => $new_biblionumber }, >+ { order_by => { -desc => 'priority' }, rows => 1 } >+ )->next; >+ my $base_priority = $max ? $max->priority : 0; >+ my $priority = $base_priority + 1; >+ my $new_priority = C4::Reserves::_ShiftPriority( $new_biblionumber, $priority ); >+ >+ $self->update( >+ { >+ itemnumber => undef, >+ biblionumber => $new_biblionumber, >+ priority => $new_priority, >+ } >+ ); >+ >+ C4::Log::logaction( 'HOLDS', 'MODIFY', $self->reserve_id, $self, undef, $original ) >+ if C4::Context->preference('HoldsLog'); >+ >+ return { success => 1, hold => $self }; >+ } else { >+ return { success => 0, error => $canReserve->{status} }; >+ } >+ } >+ return $self; >+} >+ > =head3 set_transfer > > =cut >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt >index 697f7c02e72..790fe2dd15a 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt >@@ -1505,7 +1505,7 @@ > </div> > <hr /> > <div id="move_hold_item_search" class="alert alert-danger" style="display:none;"></div> >- <form id="searchForm"> >+ <form id="itemSearchForm"> > <div id="move_hold_item_searchform"> > <h3>2. Enter the item barcode of new hold target: </h3> > <fieldset class="action"> >@@ -1515,12 +1515,62 @@ > </div> > </form> > <form id="move_hold_item_form" method="post" action="request.pl"> >- <div id="resultMessage" class="mt-3"> </div> >+ <div id="itemResultMessage" class="mt-3"> </div> > <div id="move_hold_item_confirm" style="display:none;"> > <h3>3. Confirm moving of holds:</h3> > [% INCLUDE 'csrf-token.inc' %] > <input type="hidden" name="op" value="cud-move_hold_item" /> > <button type="submit" class="btn btn-primary mt-3">Move selected holds</button> >+ <input type="hidden" name="original_biblionumber" value="[% biblio.biblionumber %]" /> >+ </div> >+ </form> >+ </div> >+ <div class="modal-footer"> >+ <button type="button" class="btn btn-default" data-bs-dismiss="modal">Cancel</button> >+ </div> >+ </div> >+ </div> >+</div> >+<div id="moveHoldBiblioModal" class="modal modal-lg" tabindex="-1" role="dialog" aria-hidden="true"> >+ <div class="modal-dialog"> >+ <div class="modal-content"> >+ <div class="modal-header"> >+ <h1 class="modal-title">Move hold(s) to a different record</h1> >+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> >+ </div> >+ <div class="modal-body"> >+ <div id="move_hold_item_selection"> >+ <h3>1. Review holds to move</h3> >+ <table class="table table-striped"> >+ <thead> >+ <tr> >+ <th>Hold ID</th> >+ <th>Original hold</th> >+ <th>Problem</th> >+ </tr> >+ </thead> >+ <tbody> </tbody> >+ </table> >+ </div> >+ <hr /> >+ <div id="move_hold_biblio_search" class="alert alert-danger" style="display:none;"></div> >+ <form id="biblioSearchForm"> >+ <div id="move_hold_item_searchform"> >+ <h3>2. Enter the bibloinumber of the new hold target: </h3> >+ <fieldset class="action"> >+ <input type="text" class="form-control" name="biblio_id" id="biblio_id" required /> >+ <button type="submit" class="btn btn-default mt-3">Search</button> >+ </fieldset> >+ </div> >+ </form> >+ <form id="move_hold_biblio_form" method="post" action="request.pl"> >+ <div id="biblioResultMessage" class="mt-3"> </div> >+ <div id="move_hold_biblio_confirm" style="display:none;"> >+ <h3>3. Confirm moving of holds:</h3> >+ [% INCLUDE 'csrf-token.inc' %] >+ <input type="hidden" name="op" value="cud-move_hold_biblio" /> >+ <button type="submit" class="btn btn-primary mt-3">Move selected holds</button> >+ <input type="hidden" name="original_biblionumber" value="[% biblio.biblionumber %]" /> > </div> > </form> > </div> >@@ -1846,7 +1896,7 @@ > } > > $(document).ready(function() { >- $("#searchForm").on("submit", function (event) { >+ $("#itemSearchForm").on("submit", function (event) { > event.preventDefault(); > > let externalID = $("#external_id").val(); >@@ -1871,9 +1921,9 @@ > <hr /> > `; > }); >- $("#resultMessage").html(resultHtml); >+ $("#itemResultMessage").html(resultHtml); > } else { >- $("#resultMessage").html(` >+ $("#itemResultMessage").html(` > <div class="alert alert-warning">No item found with barcode: ${externalID}.</div> > `); > } >@@ -1881,6 +1931,39 @@ > }); > }); > >+ $("#biblioSearchForm").on("submit", function (event) { >+ event.preventDefault(); >+ >+ let biblioID = $("#biblio_id").val(); >+ let apiUrl = `/api/v1/items?q={"biblio_id":"${encodeURIComponent(biblioID)}"}`; >+ >+ $.ajax({ >+ url: apiUrl, >+ method: "GET", >+ dataType: "json", >+ success: function (data) { >+ if (data.length > 0) { >+ let resultHtml = ""; >+ $.each(data, function (index, item) { >+ resultHtml += ` >+ <div class="alert alert-success"> >+ <strong>Biblionumber:</strong> ${item.biblio_id} <br> >+ <input id="new_biblionumber_${item.biblio_id}" name="new_biblionumber" type="checkbox" value="${item.biblio_id}"> >+ <label for="new_biblionumber_${item.biblio_id}">Move all selected record level holds to this record</label> >+ </div> >+ <hr /> >+ `; >+ }); >+ $("#biblioResultMessage").html(resultHtml); >+ } else { >+ $("#biblioResultMessage").html(` >+ <div class="alert alert-warning">No item found with barcode: ${biblioID}.</div> >+ `); >+ } >+ }, >+ }); >+ }); >+ > $(document).on("change", 'input[name="new_itemnumber"]', function() { > $('input[name="new_itemnumber"]').not(this).prop("checked", false); > if ( $('input[name="new_itemnumber"]:checked').length ){ >@@ -1890,6 +1973,15 @@ > } > }); > >+ $(document).on("change", 'input[name="new_biblionumber"]', function() { >+ $('input[name="new_biblionumber"]').not(this).prop("checked", false); >+ if ( $('input[name="new_biblionumber"]:checked').length ){ >+ $('#move_hold_biblio_confirm').show(); >+ } else { >+ $('#move_hold_biblio_confirm').hide(); >+ } >+ }); >+ > $("#always_show_holds").change(function(){ > if( $(this).prop('checked') ){ > document.cookie = 'always_show_holds=DO'; >@@ -2020,7 +2112,7 @@ > $('.move_hold_item').click(function(e) { > e.preventDefault(); > if($('.holds_table .select_hold:checked').length) { >- $('#moveHoldItemModal #resultMessage').empty(); >+ $('#itemResultMessage').empty(); > $('#move_hold_item_selection table tbody').empty(); > $('#moveHoldItemModal').modal('show'); > $('.select_hold:checked').each( function() { >@@ -2038,6 +2130,27 @@ > } > }); > >+ $('.move_hold_record').click(function(e) { >+ e.preventDefault(); >+ if($('.holds_table .select_hold:checked').length) { >+ $('#biblioResultMessage').empty(); >+ $('#move_hold_item_selection table tbody').empty(); >+ $('#moveHoldBiblioModal').modal('show'); >+ $('.select_hold:checked').each( function() { >+ let reserve_id = $(this).data('id'); >+ let reserve_biblionumber = $(this).data('biblionumber'); >+ let reserve_itemnumber = $(this).data('itemnumber'); >+ let item_level_hold = $(this).data('item_level_hold'); >+ let error_message = $(this).data('item_level_hold') ? _("Cannot move a waiting or item level hold") : ""; >+ let found_status = $(this).data('found'); >+ $('#move_hold_item_selection table').append(`<tr><td>${reserve_id}</td><td>Biblionumber: <a target="_blank" href="/cgi-bin/koha/reserve/request.pl?biblionumber=${reserve_biblionumber}">${reserve_biblionumber}</a></td><td>${error_message}</td></tr>`) >+ if ( !item_level_hold ) { >+ $('#move_hold_biblio_form').append(`<input type="hidden" name="hold_id" value="${reserve_id}">`); >+ } >+ }); >+ } >+ }); >+ > $('.cancel_selected_holds').click(function(e) { > e.preventDefault(); > if($('.holds_table .select_hold:checked').length) { >diff --git a/reserve/request.pl b/reserve/request.pl >index e3d3282608b..02099434f6f 100755 >--- a/reserve/request.pl >+++ b/reserve/request.pl >@@ -111,36 +111,38 @@ if ( $op eq 'cud-move' ) { > $next_priority, $first_priority, $last_priority > ); > } >-} elsif ( $op eq 'cud-move_hold_item' ) { >- my $new_itemnumber = $input->param('new_itemnumber'); >- my $new_biblionumber = $input->param('new_biblionumber'); >- my $target_biblio = Koha::Biblios->find($new_biblionumber); >- my @hold_ids = $input->multi_param('hold_id'); >- >- my @success_messages; >- my @error_messages; >+} elsif ( $op eq 'cud-move_hold_item' or $op eq 'cud-move_hold_biblio' ) { >+ my @hold_ids = $input->multi_param('hold_id'); >+ my $original_biblionumber = $input->param('original_biblionumber'); > >- #Get a list of all the holds to move, ordered by current priority > my @moving_holds = Koha::Holds->search( > { reserve_id => \@hold_ids }, > { order_by => { -asc => 'priority' } } > )->as_list; > >- #need to get the biblionumber of the original hold >- my $original_biblionumber = $moving_holds[0]->biblionumber; >+ my $new_biblionumber = $input->param('new_biblionumber'); >+ my $target_biblio = Koha::Biblios->find($new_biblionumber); >+ >+ my $move_method; >+ my %args; >+ >+ if ( $op eq 'cud-move_hold_item' ) { >+ $args{new_itemnumber} = $input->param('new_itemnumber'); >+ $args{new_biblionumber} = $new_biblionumber; >+ $move_method = 'move_hold_item'; >+ } else { >+ $args{new_biblionumber} = $new_biblionumber; >+ $move_method = 'move_hold_biblio'; >+ } >+ >+ my @success_messages; >+ my @error_messages; > >- my $offset = 0; > foreach my $hold (@moving_holds) { > my $original_biblio = Koha::Biblios->find( $hold->biblionumber ); > >- my $result = $hold->move_hold_item( >- { >- new_itemnumber => $new_itemnumber, >- new_biblionumber => $new_biblionumber, >- } >- ); >+ my $result = $hold->$move_method( \%args ); > >- #push info about successes and errors to the template > if ( $result->{success} ) { > push @success_messages, { > hold_id => $hold->id, >@@ -166,6 +168,7 @@ if ( $op eq 'cud-move' ) { > hold_move_successes => \@success_messages, > hold_move_failures => \@error_messages, > ); >+ > } elsif ( $op eq 'cud-cancel' ) { > my $reserve_id = $input->param('reserve_id'); > my $cancellation_reason = $input->param("cancellation-reason"); >-- >2.39.5
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 31698
:
179226
|
179235
|
179236
|
179279
|
179287
|
179290
|
179291
|
179292
|
179295
|
179704
|
179711
|
179713
|
181222
|
181223
|
181224
|
181225
|
181226
|
181228
|
181229
|
181230
|
181231
|
181232
|
181233
|
181234
|
181929
|
181930
|
181944
|
181945
|
181946
|
181947
|
181948
|
181951
|
181952
|
181953
|
181954
|
181955
|
181956
|
181957
|
181958
|
181959
|
181960
|
181961
|
181962
|
182639
|
182640
|
182641