diff --git a/C4/Reserves.pm b/C4/Reserves.pm
index a8e70e57ec..6b26f7f213 100644
--- a/C4/Reserves.pm
+++ b/C4/Reserves.pm
@@ -1183,6 +1183,8 @@ for a bib.
If C<$rank> is 'del', the hold request is cancelled.
+If C<$rank> is 'recall', the hold request is converted to a recall request.
+
If C<$rank> is an integer greater than zero, the priority of
the request is set to that value. Since priority != 0 means
that the item is not waiting on the hold shelf, setting the
@@ -1240,6 +1242,43 @@ sub ModReserve {
if ( $rank eq "del" ) {
$hold->cancel( { cancellation_reason => $cancellation_reason } );
+ } elsif ( $rank eq "recall" ) {
+ if ( !$biblionumber ) {
+ $biblionumber = $hold->biblionumber;
+ }
+ my $biblio = Koha::Biblios->find($biblionumber);
+ if ( !$borrowernumber ) {
+ $borrowernumber = $hold->borrowernumber;
+ }
+ my $patron = Koha::Patrons->find($borrowernumber);
+ if ( $hold->item_level_hold ) {
+ if ( $hold->item->can_be_recalled( { patron => $patron, hold_convert => 1 } ) ) {
+ my ( $recall, $due_interval, $due_date ) = Koha::Recalls->add_recall(
+ {
+ patron => $patron,
+ biblio => $biblio,
+ branchcode => $branchcode,
+ expirationdate => $date,
+ interface => 'intranet',
+ item => $hold->item,
+ }
+ );
+ $hold->cancel( { cancellation_reason => $cancellation_reason } );
+ }
+ } else {
+ if ( $biblio->can_be_recalled( { patron => $patron, hold_convert => 1 } ) ) {
+ my ( $recall, $due_interval, $due_date ) = Koha::Recalls->add_recall(
+ {
+ patron => $patron,
+ biblio => $biblio,
+ branchcode => $branchcode,
+ expirationdate => $date,
+ interface => 'intranet',
+ }
+ );
+ $hold->cancel( { cancellation_reason => $cancellation_reason } );
+ }
+ }
} elsif ( $hold->found && $hold->priority eq '0' && $date ) {
# The only column that can be updated for a found hold is the expiration date
diff --git a/Koha/Biblio.pm b/Koha/Biblio.pm
index d8bf30c219..fc86dcbb1c 100644
--- a/Koha/Biblio.pm
+++ b/Koha/Biblio.pm
@@ -2239,6 +2239,8 @@ sub recalls {
Does biblio-level checks and returns the items attached to this biblio that are available for recall
+If hold_convert $param is included, this is a check to convert a hold to a recall, so we should not check for an existing hold.
+
=cut
sub can_be_recalled {
@@ -2264,7 +2266,7 @@ sub can_be_recalled {
my @all_itemnumbers;
foreach my $item (@all_items) {
push( @all_itemnumbers, $item->itemnumber );
- if ( $item->can_be_recalled( { patron => $patron } ) ) {
+ if ( $item->can_be_recalled( { patron => $patron, hold_convert => $params->{hold_convert} } ) ) {
push( @itemtypes, $item->effective_itemtype );
push( @itemnumbers, $item->itemnumber );
push( @items, $item );
diff --git a/Koha/Item.pm b/Koha/Item.pm
index d8f314a8b7..95ae6cbbdf 100644
--- a/Koha/Item.pm
+++ b/Koha/Item.pm
@@ -2643,6 +2643,8 @@ sub recall {
Does item-level checks and returns if items can be recalled by this borrower
+If hold_convert $param is included, this is a check to convert a hold to a recall, so we should not check for an existing hold.
+
=cut
sub can_be_recalled {
@@ -2704,9 +2706,12 @@ sub can_be_recalled {
->count > 0 );
# check if this patron has already reserved this item
- return 0
- if ( Koha::Holds->search( { itemnumber => $self->itemnumber, borrowernumber => $patron->borrowernumber } )
- ->count > 0 );
+ unless ( $params->{hold_convert} ) {
+ return 0
+ if (
+ Koha::Holds->search( { itemnumber => $self->itemnumber, borrowernumber => $patron->borrowernumber } )
+ ->count > 0 );
+ }
}
# check item availability
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/modals/holds_table_modals.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/modals/holds_table_modals.inc
index e8a458bfb1..668a6cc518 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/modals/holds_table_modals.inc
+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/modals/holds_table_modals.inc
@@ -95,3 +95,48 @@
[% END %]
+
+[% BLOCK 'convert-to-recall-modal' %]
+
+
+
+
+
Confirm conversion
+
+
+
+
+
+
+
+[% END %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/recalls/request.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/recalls/request.tt
index 4fb0832668..dbf329d8f2 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/recalls/request.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/recalls/request.tt
@@ -2,18 +2,36 @@
[% USE Asset %]
[% USE Koha %]
[% USE KohaDates %]
+[% USE Branches %]
+[% USE Categories %]
+[% USE AuthorisedValues %]
+[% USE ItemTypes %]
[% PROCESS 'i18n.inc' %]
[% SET footerjs = 1 %]
[% INCLUDE 'doc-head-open.inc' %]
+[% SET libraries = Branches.all %]
+[% SET categories = Categories.all.unblessed %]
+[% SET columns = ['name', 'cardnumber', 'dateofbirth', 'category', 'branch', 'address', 'phone'] %]
+[% PROCESS "patron-search.inc" %]
[% FILTER collapse %]
- [% t("Existing recalls") | html %]
+ [% t("Place a recall") | html %]
› [% t("Recalls") | html %] › [% t("Koha") | html %]
[% END %]
[% INCLUDE 'doc-head-close.inc' %]
+[% FILTER collapse %]
+
+[% END %]
-
+
[% WRAPPER 'header.inc' %]
[% INCLUDE 'circ-search.inc' %]
[% END %]
@@ -27,40 +45,264 @@
[% INCLUDE 'biblio-title.inc' link = 1 %]
[% END %]
[% WRAPPER breadcrumb_item bc_active= 1 %]
- Existing recalls
+ Place a recall
[% END %]
[% END #/ WRAPPER breadcrumbs %]
[% END #/ WRAPPER sub-header.inc %]
-[% WRAPPER 'main-container.inc' aside='biblio-view-menu' %]
-