Bug 9525: Add option to define float groups and rules for float

Bug 22284 introduced ability to create hold groups.
We should have ability to create float groups in
same manner. This patch adds checkbox "Is local
float group" to group creation feature and new return
policy "Item floats by librarygroup".

To test:
1. Add new float group and some libraries to it.
2. From circulation and fine rules, set default
return policy as "Item floats by library group".
3. Check out an item for a patron.
4. Set library as one that belongs in the same
float group.
5. Check in the item.
=> Observe that notice for transfer doesn't pop up.
6. Check out again.
7. This time set library as one that doen's
belong in the same float group.
8. Check in.
=> Observe that notice for transfer pops up.

Experiment this feature by changing return policy
per library, item type etc.

Also prove t/db_dependent/Koha/Libraries.t

Sponsored-by: Koha-Suomi Oy

Signed-off-by: Lisette Scheer <lisettePalouse+Koha@gmail.com>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
This commit is contained in:
Emmi Takkinen 2021-09-08 08:58:14 +03:00 committed by Tomas Cohen Arazi
parent 2e5d60a83b
commit 7c22b12240
Signed by: tomascohen
GPG key ID: 0A272EA1B2F3C15F
7 changed files with 127 additions and 7 deletions

View file

@ -2128,8 +2128,19 @@ sub AddReturn {
# full item data, but no borrowernumber or checkout info (no issue)
my $hbr = Koha::CirculationRules->get_return_branch_policy($item);
# check if returnbranch and homebranch belong to the same float group
my $validate_float = Koha::Libraries->find( $item->homebranch )->validate_float_sibling({ branchcode => $branch });
# get the proper branch to which to return the item
my $returnbranch = $hbr ne 'noreturn' ? $item->$hbr : $branch;
my $returnbranch;
if($hbr eq 'noreturn'){
$returnbranch = $branch;
}elsif($hbr eq 'returnbylibrarygroup'){
# if library isn't in same the float group, transfer item to homebranch
$hbr = 'homebranch';
$returnbranch = $validate_float ? $branch : $item->$hbr;
}else{
$returnbranch = $item->$hbr;
}
# if $hbr was "noreturn" or any other non-item table value, then it should 'float' (i.e. stay at this branch)
my $transfer_trigger = $hbr eq 'homebranch' ? 'ReturnToHome' : $hbr eq 'holdingbranch' ? 'ReturnToHolding' : undef;

View file

@ -376,6 +376,48 @@ sub opac_info {
});
}
=head3 get_float_group_libraries
Return all libraries belonging to the same float group
=cut
sub get_float_libraries {
my ( $self ) = @_;
my $library_groups = $self->library_groups;
my @float_libraries;
while ( my $library_group = $library_groups->next ) {
my $root = Koha::Library::Groups->get_root_ancestor({id => $library_group->id});
if($root->ft_local_float_group) {
push @float_libraries, $root->all_libraries;
}
}
my %seen;
@float_libraries =
grep { !$seen{ $_->id }++ } @float_libraries;
return Koha::Libraries->search({ branchcode => { '-in' => [ keys %seen ] } });
}
=head3 validate_float_sibling
Return if given library is a valid float group member
=cut
sub validate_float_sibling {
my ( $self, $params ) = @_;
return 1 if $params->{branchcode} eq $self->id;
my $branchcode = $params->{branchcode};
return $self->get_float_libraries->search( { branchcode => $branchcode } )
->count > 0;
}
=head2 Internal methods
=head3 _type

View file

@ -51,6 +51,7 @@ if ( $action eq 'add' ) {
my $ft_search_groups_opac = $cgi->param('ft_search_groups_opac') || 0;
my $ft_search_groups_staff = $cgi->param('ft_search_groups_staff') || 0;
my $ft_local_hold_group = $cgi->param('ft_local_hold_group') || 0;
my $ft_local_float_group = $cgi->param('ft_local_float_group') || 0;
if ( !$branchcode && Koha::Library::Groups->search( { title => $title } )->count() ) {
$template->param( error_duplicate_title => $title );
@ -67,6 +68,7 @@ if ( $action eq 'add' ) {
ft_search_groups_staff => $ft_search_groups_staff,
ft_local_hold_group => $ft_local_hold_group,
ft_limit_item_editing => $ft_limit_item_editing,
ft_local_float_group => $ft_local_float_group,
branchcode => $branchcode,
}
)->store();
@ -88,6 +90,7 @@ elsif ( $action eq 'edit' ) {
my $ft_search_groups_opac = $cgi->param('ft_search_groups_opac') || 0;
my $ft_search_groups_staff = $cgi->param('ft_search_groups_staff') || 0;
my $ft_local_hold_group = $cgi->param('ft_local_hold_group') || 0;
my $ft_local_float_group = $cgi->param('ft_local_float_group') || 0;
if ($id) {
my $group = Koha::Library::Groups->find($id);
@ -101,6 +104,7 @@ elsif ( $action eq 'edit' ) {
ft_search_groups_opac => $ft_search_groups_opac,
ft_search_groups_staff => $ft_search_groups_staff,
ft_local_hold_group => $ft_local_hold_group,
ft_local_float_group => $ft_local_float_group,
}
)->store();

View file

@ -298,8 +298,10 @@ if ($barcode) {
# make sure return branch respects home branch circulation rules, default to homebranch
my $hbr = Koha::CirculationRules->get_return_branch_policy($item);
$returnbranch = $hbr ne 'noreturn' ? $item->$hbr : $userenv_branch; # can be noreturn, homebranch or holdingbranch
my $validate_float = Koha::Libraries->find( $item->homebranch )->validate_float_sibling({ branchcode => $userenv_branch });
# get the proper branch to which to return the item
# if library isn't in same the float group, transfer item to homelibrary
$returnbranch = $hbr eq 'noreturn' ? $userenv_branch : $hbr eq 'returnbylibrarygroup' ? $validate_float ? $userenv_branch : $item->homebranch : $item->$hbr;
my $materials = $item->materials;
my $descriptions = Koha::AuthorisedValues->get_description_by_koha_field({frameworkcode => '', kohafield =>'items.materials', authorised_value => $materials });
$materials = $descriptions->{lib} // $materials;

View file

@ -158,6 +158,12 @@
Is local hold group
</label>
</p>
<p>
<label>
<input type="checkbox" name="ft_local_float_group" id="add-group-modal-ft_local_float_group" value="1" />
Is local float group
</label>
</p>
</div>
</div>
</div>
@ -228,6 +234,12 @@
Is local hold group
</label>
</p>
<p>
<label>
<input type="checkbox" id="edit-group-modal-ft_local_float_group" name="ft_local_float_group" value="1" />
Is local float group
</label>
</p>
</div>
</div>
</div>
@ -309,7 +321,8 @@
var ft_search_groups_opac = $(this).data('groupFt_search_groups_opac');
var ft_search_groups_staff = $(this).data('groupFt_search_groups_staff');
var ft_local_hold_group = $(this).data('groupFt_local_hold_group');
edit_group( id, parent_id, title, description, ft_hide_patron_info, ft_search_groups_opac, ft_search_groups_staff, ft_local_hold_group, ft_limit_item_editing );
var ft_local_float_group = $(this).data('groupFt_local_float_group');
edit_group( id, parent_id, title, description, ft_hide_patron_info, ft_search_groups_opac, ft_search_groups_staff, ft_local_hold_group, ft_limit_item_editing, ft_local_float_group );
});
$('.delete-group').on('click', function(e) {
@ -346,6 +359,7 @@
$('#add-group-modal-ft_search_groups_opac').prop('checked', false);
$('#add-group-modal-ft_search_groups_staff').prop('checked', false);
$('#add-group-modal-ft_local_hold_group').prop('checked', false);
$('#add-group-modal-ft_local_float_group').prop('checked', false);
if ( parent_id ) {
$('#root-group-features-add').hide();
} else {
@ -355,17 +369,18 @@
}
function edit_group( id, parent_id, title, description, ft_hide_patron_info, ft_search_groups_opac, ft_search_groups_staff, ft_local_hold_group, ft_limit_item_editing ) {
function edit_group( id, parent_id, title, description, ft_hide_patron_info, ft_search_groups_opac, ft_search_groups_staff, ft_local_hold_group, ft_limit_item_editing, ft_local_float_group ) {
$('#edit-group-modal-id').val( id );
$('#edit-group-modal-title').val( title );
$('#edit-group-modal-description').val( description );
console.log(ft_local_float_group);
if ( parent_id ) {
$('#edit-group-modal-ft_hide_patron_info').prop('checked', false);
$('#edit-group-modal-ft_limit_item_editing').prop('checked', false);
$('#edit-group-modal-ft_search_groups_opac').prop('checked', false);
$('#edit-group-modal-ft_search_groups_staff').prop('checked', false);
$('#edit-group-modal-ft_local_hold_group').prop('checked', false);
$('#edit-group-modal-ft_local_float_group').prop('checked', false);
$('#root-group-features-edit').hide();
} else {
$('#edit-group-modal-ft_hide_patron_info').prop('checked', ft_hide_patron_info ? true : false );
@ -373,6 +388,7 @@
$('#edit-group-modal-ft_search_groups_opac').prop('checked', ft_search_groups_opac ? true : false );
$('#edit-group-modal-ft_search_groups_staff').prop('checked', ft_search_groups_staff ? true : false );
$('#edit-group-modal-ft_local_hold_group').prop('checked', ft_local_hold_group ? true : false );
$('#edit-group-modal-ft_local_float_group').prop('checked', ft_local_float_group ? true : false );
$('#root-group-features-edit').show();
}
@ -431,6 +447,9 @@
[% IF group.ft_local_hold_group %]
<li>Is local hold group</li>
[% END %]
[% IF group.ft_local_float_group %]
<li>Is local float group</li>
[% END %]
</ul>
[% END %]
</td>
@ -448,7 +467,7 @@
</li>
<li>
<a class="edit-group" id="edit-group-[% group.id | html %]" href="#" data-group-id="[% group.id | html %]" data-group-parent-id="[% group.parent_id | html %]" data-group-title="[% group.title | html %]" data-group-description="[% group.description | html %]" data-group-ft_hide_patron_info="[% group.ft_hide_patron_info | html %]" data-group-ft_search_groups_opac="[% group.ft_search_groups_opac | html %]" data-group-ft_search_groups_staff="[% group.ft_search_groups_staff | html %]" data-group-ft_local_hold_group="[% group.ft_local_hold_group | html %]" data-group-ft_limit_item_editing="[% group.ft_limit_item_editing | html %]" >
<a class="edit-group" id="edit-group-[% group.id | html %]" href="#" data-group-id="[% group.id | html %]" data-group-parent-id="[% group.parent_id | html %]" data-group-title="[% group.title | html %]" data-group-description="[% group.description | html %]" data-group-ft_hide_patron_info="[% group.ft_hide_patron_info | html %]" data-group-ft_search_groups_opac="[% group.ft_search_groups_opac | html %]" data-group-ft_search_groups_staff="[% group.ft_search_groups_staff | html %]" data-group-ft_local_hold_group="[% group.ft_local_hold_group | html %]" data-group-ft_limit_item_editing="[% group.ft_limit_item_editing | html %]" data-group-ft_local_float_group="[% group.ft_local_float_group | html %]" >
<i class="fa-solid fa-pencil" aria-hidden="true"></i> Edit
</a>
</li>

View file

@ -771,6 +771,13 @@
[% END %]
Item floats
</option>
[% IF returnbranch.rule_value == 'returnbylibrarygroup' %]
<option value="returnbylibrarygroup" selected="selected">
[% ELSE %]
<option value="returnbylibrarygroup">
[% END %]
Item floats by library group
</option>
</select>
</td>
<td class="actions">
@ -1323,6 +1330,8 @@
<span>Item returns to issuing branch</span>
[% ELSIF returnbranch == 'noreturn' %]
<span>Item floats</span>
[% ELSIF returnbranch == 'returnbylibrarygroup'%]
<span>Item floats by library group</span>
[% END %]
</td>
<td class="actions">
@ -1375,6 +1384,7 @@
<option value="homebranch">Item returns home</option>
<option value="holdingbranch">Item returns to issuing library</option>
<option value="noreturn">Item floats</option>
<option value="returnbylibrarygroup">Item floats by library group</option>
</select>
</td>
<td class="actions"><button type="submit" class="btn btn-default btn-xs"><i class="fa fa-plus"></i> Add</button></td>

View file

@ -331,6 +331,38 @@ subtest 'get_hold_libraries and validate_hold_sibling' => sub {
};
subtest 'get_float_libraries and validate_float_sibling' => sub {
plan tests => 4;
$schema->storage->txn_begin;
my $library1 = $builder->build_object({ class => 'Koha::Libraries' });
my $library2 = $builder->build_object({ class => 'Koha::Libraries' });
my $library3 = $builder->build_object({ class => 'Koha::Libraries' });
my $library4 = $builder->build_object({ class => 'Koha::Libraries' });
my $root1 = $builder->build_object( { class => 'Koha::Library::Groups', value => { ft_local_hold_group => 1 } } );
my $root2 = $builder->build_object( { class => 'Koha::Library::Groups', value => { ft_local_hold_group => 1 } } );
# Float group 1
$builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root1->id, branchcode => $library1->branchcode } } );
$builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root1->id, branchcode => $library2->branchcode } } );
# Float group 2
$builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root2->id, branchcode => $library3->branchcode } } );
$builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root2->id, branchcode => $library4->branchcode } } );
my @libraries1 = $library1->get_float_libraries();
is(scalar @libraries1, '2', '1st float group contains 2 libraries');
my @libraries2 = $library3->get_float_libraries();
is(scalar @libraries2, '2', '2nd float group also contains 2 libraries');
ok($library1->validate_float_sibling({ branchcode => $library2->branchcode }), "Library1 and library2 belong in to the same float group.");
ok($library3->validate_float_sibling({ branchcode => $library4->branchcode }), "Library3 and library5 belong in to the same float group.");
$schema->storage->txn_rollback;
};
subtest 'outgoing_transfers' => sub {
plan tests => 3;