@@ -, +, @@
hold
---
C4/Reserves.pm | 1 +
Koha/Hold.pm | 14 ++++
Koha/Holds.pm | 3 +
.../prog/en/includes/holds_table.inc | 2 +
.../prog/en/modules/reserve/request.tt | 80 ++++++++++++++++++-
reserve/placerequest.pl | 2 +
reserve/request.pl | 4 +
t/db_dependent/Koha/Holds.t | 27 +++++++
8 files changed, 129 insertions(+), 4 deletions(-)
--- a/C4/Reserves.pm
+++ a/C4/Reserves.pm
@@ -162,6 +162,7 @@ BEGIN {
itemnumber => $itemnumber,
found => $found,
itemtype => $itemtype,
+ item_gorup_id => $item_group_id
}
);
--- a/Koha/Hold.pm
+++ a/Koha/Hold.pm
@@ -525,6 +525,20 @@ sub item {
return $self->{_item};
}
+=head3 item_group
+
+Returns the related Koha::Biblio::ItemGroup object for this Hold
+
+=cut
+
+sub item_group {
+ my ($self) = @_;
+
+ my $item_group_rs = $self->_result->item_group;
+ return unless $item_group_rs;
+ return Koha::Biblio::ItemGroup->_new_from_dbic($item_group_rs);
+}
+
=head3 branch
Returns the related Koha::Library object for this Hold
--- a/Koha/Holds.pm
+++ a/Koha/Holds.pm
@@ -85,6 +85,9 @@ sub forced_hold_level {
my $item_level_count = $self->search( { itemnumber => { '!=' => undef } } )->count();
return 'item' if $item_level_count > 0;
+ my $item_group_level_count = $self->search( { item_group_id => { '!=' => undef } } )->count();
+ return 'item_group' if $item_group_level_count > 0;
+
my $record_level_count = $self->search( { itemnumber => undef } )->count();
return 'record' if $record_level_count > 0;
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/holds_table.inc
+++ a/koha-tmpl/intranet-tmpl/prog/en/includes/holds_table.inc
@@ -179,6 +179,8 @@
[%- ELSE -%]
[%- IF hold.itemtype -%]
Next available [% ItemTypes.GetDescription( hold.itemtype ) | html %] item
+ [%- ELSIF hold.object.item_group -%]
+ Next available item from group [% hold.object.item_group.description | html %]
[%- ELSE -%]
Next available
[%- END -%]
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt
+++ a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt
@@ -596,7 +596,7 @@
[% UNLESS ( multi_hold ) %]
- [% IF force_hold_level == 'item' %]
+ [% IF force_hold_level == 'item' || force_hold_level == 'item_group' %]
[% ELSIF force_hold_level == 'record' %]
@@ -655,6 +655,52 @@
[% END %]
+
+ [% IF Koha.Preference('EnableItemGroupHolds') && biblio.object.item_groups.count %]
+
+ Hold next available item from an item group
+ [% IF force_hold_level == 'item_group' %]
+ (Required)
+ [% END %]
+
+
+ [% IF force_hold_level == 'record' # Patron has placed a record level hold previously for this record %]
+
+
+ Hold must be record level
+
+ [% ELSIF force_hold_level == 'item' # Patron has placed an item level hold previously for this record %]
+
+
+ Hold must be item level
+
+ [% ELSE %]
+
+
+
+
Hold
+
Item group
+
+
+
+ [% FOREACH g IN biblio.object.item_groups.search({}, { order_by => ['display_order'] }) %]
+ [% IF g.items %]
+
+
+
+
+
+
+
+
+ [% END %]
+ [% END %]
+
+
+ [% END %]
+ [% END %]
+
+
Place a hold on a specific item
[% IF force_hold_level == 'item' %]
@@ -671,6 +717,9 @@
Item type
[% END %]
Barcode
+ [% IF Koha.Preference('EnableItemGroupHolds') && biblio.object.item_groups.count %]
+
Item group
+ [% END %]
Home library
Last location
[% IF itemdata_ccode %]
@@ -695,6 +744,11 @@
Hold must be record level
+ [% ELSIF force_hold_level == 'item_group' %]
+
+
+ Hold must be item group level
+
[% ELSIF ( itemloo.available ) %]
[% ELSIF ( itemloo.override ) %]
@@ -764,6 +818,11 @@
[% itemloo.barcode | html %]
+ [% IF Koha.Preference('EnableItemGroupHolds') && biblio.object.item_groups.count %]
+
+ [% itemloo.object.item_group.description | html %]
+
+ [% END %]
[% Branches.GetName( itemloo.homebranch ) | html %]
@@ -1336,6 +1395,8 @@
};
if($('input[name="checkitem"]:checked').length)
data.item_id = $('input[name="checkitem"]:checked').val();
+ if($('input[name="item_group_id"]:checked').length)
+ data.item_group_id = $('input[name="item_group_id"]:checked').val();
if($('input[name="borrowernumber"]').length)
data.patron_id = $('input[name="borrowernumber"]').val();
if($('textarea[name="notes"]').length)
@@ -1381,8 +1442,8 @@
});
[% UNLESS ( multi_hold ) %]
- $("#hold-request-form").on("submit", function(){
- return check($(this));
+ $("#hold-request-form").on("submit", function(e){
+ return check(e, $(this));
});
[% ELSE %]
$("#hold-request-form").on("submit", function(){
@@ -1426,7 +1487,7 @@
});
});
- function check( table ) {
+ function check( e, table ) {
var msg = "";
@@ -1457,6 +1518,7 @@
$('#hold-request-form').preventDoubleFormSubmit();
return(true);
} else {
+ e.preventDefault();
alert(msg);
return(false);
}
@@ -1610,6 +1672,16 @@
stickyClass: "floating"
});
+ [% IF Koha.Preference('EnableItemGroupHolds') %]
+ $(':radio[name="item_group_id"]').change(function(){
+ $(':radio[name="checkitem"]').prop('checked', false);
+ });
+
+ $(':radio[name="checkitem"]').change(function(){
+ $(':radio[name="item_group_id"]').prop('checked', false);
+ });
+ [% END %]
+
if(!localStorage.selectedHolds || document.referrer.replace(/\?.*/, '') !== document.location.origin+document.location.pathname) {
localStorage.selectedHolds = [];
}
--- a/reserve/placerequest.pl
+++ a/reserve/placerequest.pl
@@ -45,6 +45,7 @@ my $startdate = $input->param('reserve_date') || '';
my @rank = $input->multi_param('rank-request');
my $title = $input->param('title');
my $checkitem = $input->param('checkitem');
+my $item_group_id = $input->param('item_group_id');
my $expirationdate = $input->param('expiration_date');
my $itemtype = $input->param('itemtype') || undef;
my $non_priority = $input->param('non_priority');
@@ -140,6 +141,7 @@ if ( $patron ) {
found => $found,
itemtype => $itemtype,
non_priority => $non_priority,
+ item_group_id => $item_group_id,
}
);
}
--- a/reserve/request.pl
+++ a/reserve/request.pl
@@ -299,12 +299,15 @@ if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold )
my %biblioloopiter = ();
my $biblio = Koha::Biblios->find( $biblionumber );
+
unless ($biblio) {
$biblioloopiter{noitems} = 1;
$template->param('nobiblio' => 1);
last;
}
+ $biblioloopiter{object} = $biblio;
+
if ( $patron ) {
{ # CanBookBeReserved
my $canReserve = CanBookBeReserved( $patron->borrowernumber, $biblionumber );
@@ -397,6 +400,7 @@ if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold )
for my $item_object ( @items ) {
my $do_check;
my $item = $item_object->unblessed;
+ $item->{object} = $item_object;
if ( $patron ) {
$do_check = $patron->do_check_for_previous_checkout($item) if $wants_check;
if ( $do_check && $wants_check ) {
--- a/t/db_dependent/Koha/Holds.t
+++ a/t/db_dependent/Koha/Holds.t
@@ -25,6 +25,7 @@ use Test::Warn;
use C4::Circulation qw( AddIssue );
use C4::Reserves qw( AddReserve ModReserve ModReserveCancelAll );
use Koha::AuthorisedValueCategory;
+use Koha::Biblio::ItemGroups;
use Koha::Database;
use Koha::DateUtils qw( dt_from_string );
use Koha::Holds;
@@ -641,6 +642,32 @@ subtest 'set_waiting+patron_expiration_date' => sub {
};
};
+subtest 'Test Koha::Hold::item_group' => sub {
+ plan tests => 1;
+ my $library = $builder->build_object( { class => 'Koha::Libraries' } );
+ my $patron = $builder->build_object({ class => 'Koha::Patrons' });
+ my $item = $builder->build_sample_item;
+ my $item_group = $builder->build_object(
+ {
+ class => 'Koha::Biblio::ItemGroups',
+ value => { biblionumber => $item->biblionumber }
+ }
+ );
+ my $reserve_id = AddReserve(
+ {
+ branchcode => $library->branchcode,
+ borrowernumber => $patron->borrowernumber,
+ biblionumber => $item->biblionumber,
+ itemnumber => $item->itemnumber,
+ item_group_id => $item_group->id,
+ }
+ );
+
+ my $hold = Koha::Holds->find($reserve_id);
+ is( $hold->item_group_id, $item_group->id,
+ 'Koha::Hold::item_group returns the correct item_group' );
+};
+
$schema->storage->txn_rollback;
--