Bug 28530: Add float limits editor

Signed-off-by: Andrew Fuerste-Henry <andrewfh@dubcolib.org>
Signed-off-by: Kris Becker <kbecker@jcls.org>
Signed-off-by: Kris Becker <kbecker@jcls.org>
Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This commit is contained in:
Kyle M Hall 2023-12-18 14:23:09 -05:00 committed by Lucas Gass
parent a6a446ad39
commit be2cbf15de
No known key found for this signature in database
GPG Key ID: 60B447398B0D36CA
3 changed files with 239 additions and 36 deletions

80
admin/float_limits.pl Executable file
View File

@ -0,0 +1,80 @@
#!/usr/bin/perl
# Copyright 2023 ByWater Solutions
#
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Koha is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Koha; if not, see <http://www.gnu.org/licenses>.
use Modern::Perl;
use CGI qw ( -utf8 );
use C4::Context;
use C4::Output qw( output_html_with_http_headers );
use C4::Auth qw( get_template_and_user );
use Koha::ItemTypes;
use Koha::Libraries;
use Koha::Library::FloatLimits;
my $input = CGI->new;
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
{
template_name => "admin/float_limits.tt",
query => $input,
type => "intranet",
flagsrequired => { parameters => 'manage_transfers' },
}
);
my $op = $input->param('op');
if ( $op eq 'set_float_limits' ) {
my $schema = Koha::Database->new()->schema();
my @branches = Koha::Libraries->search()->as_list;
my @itemtypes = Koha::ItemTypes->search()->as_list;
$schema->txn_do(
sub {
$schema->storage->dbh->do("DELETE FROM library_float_limits");
foreach my $branch (@branches) {
foreach my $itemtype (@itemtypes) {
my $branchcode = $branch->id;
my $itype = $itemtype->id;
my $limit = $input->param( "limit_" . $branchcode . "_" . $itype );
Koha::Library::FloatLimit->new(
{
branchcode => $branchcode,
itemtype => $itype,
float_limit => $limit,
}
)->store()
if $limit ne q{}; # update or insert
}
}
$template->param( float_limits_updated => 1 );
}
);
}
my $limits_hash = {};
my $limits = Koha::Library::FloatLimits->search();
while ( my $l = $limits->next ) {
$limits_hash->{ $l->branchcode }->{ $l->itemtype } = $l->float_limit;
}
$template->param( limits => $limits_hash );
output_html_with_http_headers $input, $cookie, $template->output;

View File

@ -24,42 +24,40 @@
</ul>
[% END %]
[% IF ( CAN_user_parameters_manage_patron_categories || CAN_user_parameters_manage_circ_rules || CAN_user_parameters_manage_patron_attributes || CAN_user_parameters_manage_transfers || CAN_user_parameters_manage_item_circ_alerts || CAN_user_parameters_manage_cities || CAN_user_parameters_manage_curbside_pickups || CAN_user_parameters_manage_patron_restrictions ) %]
<h5>Patrons and circulation</h5>
<ul>
[% IF ( CAN_user_parameters_manage_patron_categories ) %]
<li><a href="/cgi-bin/koha/admin/categories.pl">Patron categories</a></li>
[% END %]
[% IF ( CAN_user_parameters_manage_circ_rules ) %]
<li><a href="/cgi-bin/koha/admin/smart-rules.pl">Circulation and fine rules</a></li>
[% END %]
[% IF ( CAN_user_parameters_manage_patron_attributes ) %]
<li><a href="/cgi-bin/koha/admin/patron-attr-types.pl">Patron attribute types</a></li>
[% END %]
[% IF ( CAN_user_parameters_manage_transfers ) %]
<li><a href="/cgi-bin/koha/admin/branch_transfer_limits.pl">Library transfer limits</a></li>
<li><a href="/cgi-bin/koha/admin/transport-cost-matrix.pl">Transport cost matrix</a></li>
[% END %]
[% IF ( CAN_user_sip2 ) %]
<li><a href="/cgi-bin/koha/sip2/sip2.pl">Self-service circulation (SIP2)</a></li>
[% END %]
[% IF ( CAN_user_parameters_manage_item_circ_alerts ) %]
<li><a href="/cgi-bin/koha/admin/item_circulation_alerts.pl">Item circulation alerts</a></li>
[% END %]
[% IF ( Koha.Preference('UseCirculationDesks') && CAN_user_parameters_manage_libraries ) %]
<li><a href="/cgi-bin/koha/admin/desks.pl">Desks</a></li>
[% END %]
[% IF ( CAN_user_parameters_manage_cities ) %]
<li><a href="/cgi-bin/koha/admin/cities.pl">Cities and towns</a></li>
[% END %]
[% IF ( CAN_user_parameters_manage_curbside_pickups ) %]
<li><a href="/cgi-bin/koha/admin/curbside_pickup.pl">Curbside pickup</a></li>
[% END %]
[% IF ( CAN_user_parameters_manage_patron_restrictions ) %]
<li><a href="/cgi-bin/koha/admin/restrictions.pl">Patron restriction types</a></li>
[% END %]
</ul>
[% END %]
[% IF ( CAN_user_parameters_manage_patron_categories || CAN_user_parameters_manage_circ_rules || CAN_user_parameters_manage_patron_attributes || CAN_user_parameters_manage_transfers || CAN_user_parameters_manage_item_circ_alerts || CAN_user_parameters_manage_cities || CAN_user_parameters_manage_curbside_pickups || CAN_user_parameters_manage_patron_restrictions ) %]
<h5>Patrons and circulation</h5>
<ul>
[% IF ( CAN_user_parameters_manage_patron_categories ) %]
<li><a href="/cgi-bin/koha/admin/categories.pl">Patron categories</a></li>
[% END %]
[% IF ( CAN_user_parameters_manage_circ_rules ) %]
<li><a href="/cgi-bin/koha/admin/smart-rules.pl">Circulation and fine rules</a></li>
[% END %]
[% IF ( CAN_user_parameters_manage_patron_attributes ) %]
<li><a href="/cgi-bin/koha/admin/patron-attr-types.pl">Patron attribute types</a></li>
[% END %]
[% IF ( CAN_user_parameters_manage_transfers ) %]
<li><a href="/cgi-bin/koha/admin/branch_transfer_limits.pl">Library transfer limits</a></li>
<li><a href="/cgi-bin/koha/admin/transport-cost-matrix.pl">Transport cost matrix</a></li>
<li><a href="/cgi-bin/koha/admin/float_limits.pl">Library float limits</a></li>
[% END %]
[% IF ( CAN_user_parameters_manage_item_circ_alerts ) %]
<li><a href="/cgi-bin/koha/admin/item_circulation_alerts.pl">Item circulation alerts</a></li>
[% END %]
[% IF ( Koha.Preference('UseCirculationDesks') && CAN_user_parameters_manage_libraries ) %]
<li><a href="/cgi-bin/koha/admin/desks.pl">Desks</a></li>
[% END %]
[% IF ( CAN_user_parameters_manage_cities ) %]
<li><a href="/cgi-bin/koha/admin/cities.pl">Cities and towns</a></li>
[% END %]
[% IF ( CAN_user_parameters_manage_curbside_pickups ) %]
<li><a href="/cgi-bin/koha/admin/curbside_pickup.pl">Curbside pickup</a></li>
[% END %]
[% IF ( CAN_user_parameters_manage_patron_restrictions ) %]
<li><a href="/cgi-bin/koha/admin/restrictions.pl">Patron restriction types</a></li>
[% END %]
</ul>
[% END %]
[% IF ( CAN_user_parameters_manage_accounts || ( Koha.Preference('UseCashRegisters') && CAN_user_parameters_manage_cash_registers ) ) %]
<h5>Accounting</h5>

View File

@ -0,0 +1,125 @@
[% USE raw %]
[% USE Asset %]
[% USE Branches %]
[% USE ItemTypes %]
[% USE Koha %]
[% SET footerjs = 1 %]
[% PROCESS 'i18n.inc' %]
[% INCLUDE 'doc-head-open.inc' %]
<title
>[% FILTER collapse %]
[% t("Library float limits") | html %]
&rsaquo; [% t("Administration") | html %] &rsaquo; [% t("Koha") | html %]
[% END %]</title
>
[% INCLUDE 'doc-head-close.inc' %]
<style>
.disabled-transfer {
background-color: #ff8888;
}
</style>
</head>
<body id="admin_library_float_limits" class="admin">
[% WRAPPER 'header.inc' %]
[% INCLUDE 'prefs-admin-search.inc' %]
[% END %]
[% WRAPPER 'sub-header.inc' %]
[% WRAPPER breadcrumbs %]
[% WRAPPER breadcrumb_item %]
<a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a>
[% END %]
[% WRAPPER breadcrumb_item bc_active= 1 %]
<span>Library float limits</span>
[% END %]
[% END #/ WRAPPER breadcrumbs %]
[% END #/ WRAPPER sub-header.inc %]
<div class="main container-fluid">
<div class="row">
<div class="col-sm-10 col-sm-push-2">
<main>
<h1 class="parameters"> Library float limits </h1>
[% UNLESS Koha.Preference('UseLibraryFloatLimits') %]
<div class="dialog message">
<p>Because the "UseLibraryFloatLimits" system preference is currently not enabled, float limits will not be enforced.</p>
<p>
Go to the <a href="/cgi-bin/koha/admin/preferences.pl?op=search&amp;searchfield=UseLibraryFloatLimits">UseLibraryFloatLimits</a>
system preference if you wish to enable this feature.
</p>
</div>
[% END %]
<form method="post" action="/cgi-bin/koha/admin/float_limits.pl" id="float_limit_form">
<input type="hidden" name="op" value="set_float_limits" />
<fieldset id="float_limits">
<div class="help">
<p>Specify the total number of items per itemtype that are allowed to float at each library.</p>
<p>
When an item is checked in, the librarian will get a request to transfer the item to the library with the lowest ratio of items held versus items allowed for that item type if the checkin library has reached
its' limit for that type of item.
</p>
<p> If a library and item type combination is left empty, that library will be ignored when finding the best library to transfer the item to. </p>
</div>
<div class="form_validation_errors"><span></span></div>
<table>
<tr>
<th>Item type \ Library</th>
[% FOR b IN Branches.all(unfiltered => 1) %]
<th>[% b.branchname | html %]</th>
[% END %]
</tr>
[% FOR i IN ItemTypes.Get() %]
<tr>
<th>[% i.description | html %]</th>
[% FOR b IN Branches.all(unfiltered => 1) %]
<td>
[% SET bc = b.branchcode %]
[% SET it = i.itemtype %]
<input name="limit_[% bc | html %]_[% it | html %]" size="4" class="float_limit" value="[% limits.$bc.$it | html %]" />
</td>
[% END %]
</tr>
[% END %]
</table>
</fieldset>
<div class="form_validation_errors"><span></span></div>
<fieldset class="action"> <input type="submit" class="btn btn-primary" value="Save" /> <a href="/cgi-bin/koha/admin/float_limits.pl" class="cancel">Cancel</a> </fieldset>
</form>
</main>
</div>
<!-- /.col-sm-10.col-sm-push-2 -->
<div class="col-sm-2 col-sm-pull-10">
<aside> [% INCLUDE 'admin-menu.inc' %] </aside>
</div>
<!-- /.col-sm-2.col-sm-pull-10 -->
</div>
<!-- /.row -->
[% MACRO jsinclude BLOCK %]
[% Asset.js("js/admin-menu.js") | $raw %]
<script>
$(document).ready(function () {
jQuery.validator.addClassRules("float_limit", {
digits: true,
});
$("#float_limit_form").validate({
errorContainer: ".form_validation_errors",
errorLabelContainer: ".form_validation_errors span",
});
});
</script>
[% END %]
[% INCLUDE 'intranet-bottom.inc' %]</div
>