Bug 17702: Add UI to manage account credit types

It is the same as for debit types.

It adds a new column `archived` in table `account_credit_types` that has
the same purpose than `account_debit_types.archived`

Test plan:
0. Apply patch && run updatedatabase && update_dbix_class_files
1. Go to Admin » Credit types
2. Add a new credit type, give it a code and a description and check
   'Can be manually added'
3. Go to a patron's accounting section, 'Create manual credit' tab
4. Verify that the new credit type appears
5. Return to Admin » Credit types and archive the credit type
6. Verify that the new credit type is not available anymore in 'Create
   manual credit'
7. Restore the credit type and verify that it is available again
8. Create a manual credit with the new credit type
9. Go to Reports » Cash register and make sure you can find the
   transaction by filtering on transaction type
10. Edit the new credit type and set some library limitations, make sure
    that the credit type doesn't appear if you're connected to a library
    you didn't selected, and that it appears if you're connected to a
    library you selected.

Note to QA team:
The change in Koha/Account.pm, I added it because otherwise Koha died
when adding a manual credit with a custom type.
In that case, offset type will default to 'Manual Credit'. I'm not sure
if that is the best thing to do. I'm open to suggestions :)

Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
This commit is contained in:
Julian Maurice 2020-02-07 13:17:54 +01:00 committed by Martin Renvoize
parent fbd0687718
commit 50a733f09c
No known key found for this signature in database
GPG Key ID: 422B469130441A0F
7 changed files with 367 additions and 2 deletions

View File

@ -396,7 +396,7 @@ sub add_credit {
my $account_offset = Koha::Account::Offset->new(
{
credit_id => $line->id,
type => $Koha::Account::offset_type->{$credit_type},
type => $Koha::Account::offset_type->{$credit_type} // $Koha::Account::offset_type->{CREDIT},
amount => $amount
}
)->store();

131
admin/credit_types.pl Executable file
View File

@ -0,0 +1,131 @@
#! /usr/bin/perl
# Copyright 2020 Koha Development Team
#
# 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 Try::Tiny;
use C4::Context;
use C4::Auth;
use C4::Output;
use Koha::Account::CreditType;
use Koha::Account::CreditTypes;
my $input = new CGI;
my $code = $input->param('code');
my $op = $input->param('op') || 'list';
my @messages;
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
{
template_name => "admin/credit_types.tt",
query => $input,
type => "intranet",
authnotrequired => 0,
flagsrequired => { parameters => 'parameters_remaining_permissions' },
debug => 1,
}
);
my $credit_type;
if ($code) {
$credit_type = Koha::Account::CreditTypes->find($code);
}
if ( $op eq 'add_form' ) {
my $selected_branches =
$credit_type ? $credit_type->get_library_limits : undef;
my $branches =
Koha::Libraries->search( {}, { order_by => ['branchname'] } )->unblessed;
my @branches_loop;
foreach my $branch (@$branches) {
my $selected =
( $selected_branches
&& grep { $_->branchcode eq $branch->{branchcode} }
@{ $selected_branches->as_list } ) ? 1 : 0;
push @branches_loop,
{
branchcode => $branch->{branchcode},
branchname => $branch->{branchname},
selected => $selected,
};
}
$template->param(
credit_type => $credit_type,
branches_loop => \@branches_loop
);
}
elsif ( $op eq 'add_validate' ) {
my $description = $input->param('description');
my $can_be_added_manually = $input->param('can_be_added_manually') || 0;
my @branches = grep { $_ ne q{} } $input->multi_param('branches');
if ( not defined $credit_type ) {
$credit_type = Koha::Account::CreditType->new( { code => $code } );
}
$credit_type->description($description);
$credit_type->can_be_added_manually($can_be_added_manually);
try {
$credit_type->store;
$credit_type->replace_library_limits( \@branches );
push @messages, { type => 'message', code => 'success_on_saving' };
}
catch {
push @messages, { type => 'error', code => 'error_on_saving' };
};
$op = 'list';
}
elsif ( $op eq 'archive' ) {
try {
$credit_type->archived(1)->store();
push @messages, { code => 'success_on_archive', type => 'message' };
}
catch {
push @messages, { code => 'error_on_archive', type => 'alert' };
};
$op = 'list';
}
elsif ( $op eq 'unarchive' ) {
try {
$credit_type->archived(0)->store();
push @messages, { code => 'success_on_restore', type => 'message' };
}
catch {
push @messages, { code => 'error_on_restore', type => 'alert' };
};
$op = 'list';
}
if ( $op eq 'list' ) {
my $credit_types = Koha::Account::CreditTypes->search();
$template->param( credit_types => $credit_types, );
}
$template->param(
code => $code,
messages => \@messages,
op => $op,
);
output_html_with_http_headers $input, $cookie, $template->output;

View File

@ -0,0 +1,9 @@
$DBversion = 'XXX';
if( CheckVersion( $DBversion ) ) {
if (!column_exists('account_credit_types', 'archived')) {
$dbh->do('ALTER TABLE account_credit_types ADD COLUMN archived tinyint(1) NOT NULL DEFAULT 0 AFTER is_system');
}
SetVersion( $DBversion );
print "Upgrade to $DBversion done (Bug 17702 - Add column account_credit_types.archived)\n";
}

View File

@ -56,6 +56,7 @@
<ul>
[% IF ( CAN_user_parameters_manage_accounts ) %]
<li><a href="/cgi-bin/koha/admin/debit_types.pl">Debit types</a></li>
<li><a href="/cgi-bin/koha/admin/credit_types.pl">Credit types</a></li>
[% END %]
[% IF ( Koha.Preference('UseCashRegisters') && CAN_user_parameters_manage_cash_registers ) %]
<li><a href="/cgi-bin/koha/admin/cash_registers.pl">Cash registers</a></li>

View File

@ -113,6 +113,8 @@
[% IF ( CAN_user_parameters_manage_accounts ) %]
<dt><a href="/cgi-bin/koha/admin/debit_types.pl">Debit types</a></dt>
<dd>Define debit types.</dd>
<dt><a href="/cgi-bin/koha/admin/credit_types.pl">Credit types</a></dt>
<dd>Define credit types.</dd>
[% END %]
[% IF ( Koha.Preference('UseCashRegisters') && CAN_user_parameters_manage_cash_registers ) %]
<dt><a href="/cgi-bin/koha/admin/cash_registers.pl">Cash registers</a></dt>

View File

@ -0,0 +1,222 @@
[% USE raw %]
[% USE Asset %]
[% USE Branches %]
[% PROCESS i18n.inc %]
[% SET footerjs = 1 %]
[% INCLUDE 'doc-head-open.inc' %]
<title>Koha &rsaquo; Administration &rsaquo;
[% IF op =='add_form' %]
[% t('Credit types') %] &rsaquo;
[% IF credit_type.code %]
[% t('Modify credit type') %]
[% ELSE %]
[% t('New credit type') %]
[% END %]
[% ELSE %]
[% t('Credit types') %]
[% END %]
</title>
[% INCLUDE 'doc-head-close.inc' %]
</head>
<body id="admin_credit_types" class="admin">
[% INCLUDE 'header.inc' %]
[% INCLUDE 'prefs-admin-search.inc' %]
<div id="breadcrumbs">
<a href="/cgi-bin/koha/mainpage.pl">[% t('Home') %]</a>
&rsaquo; <a href="/cgi-bin/koha/admin/admin-home.pl">[% t('Administration') %]</a>
&rsaquo; <a href="/cgi-bin/koha/admin/credit_types.pl">[% t('Credit types') %]</a>
[% IF op == 'add_form' %]
&rsaquo; [% IF credit_type.code %][% t('Modify credit type') %][% ELSE %][% t('New credit type') %][% END %]
[% END %]
</div>
<div class="main container-fluid">
<div class="row">
<div class="col-sm-10 col-sm-push-2">
<main>
[% FOREACH m IN messages %]
<div class="dialog [% m.type | html %]">
[% SWITCH m.code %]
[% CASE 'success_on_saving' %]
[% t('Credit type saved successfully.') %]
[% CASE 'error_on_saving' %]
[% t('An error occurred when saving this credit type.') %]
[% CASE 'success_on_archive' %]
[% t('Credit type archived successfully.') %]
[% CASE 'success_on_restore' %]
[% t('Credit type restored successfully.') %]
[% CASE %]
[% m.code | html %]
[% END %]
</div>
[% END %]
[% IF op == 'add_form' %]
[% IF credit_type %]
<h3>[% t('Modify a credit type') %]</h3>
[% ELSE %]
<h3>[% t('New credit type') %]</h3>
[% END %]
<form action="/cgi-bin/koha/admin/credit_types.pl" name="Aform" method="post" class="validated">
<input type="hidden" name="op" value="add_validate" />
<fieldset class="rows">
<ol>
<li>
<label for="code" class="required">[% t('Credit type code:') %] </label>
[% IF credit_type %]
<strong>[% credit_type.code | html %]</strong>
<input type="hidden" name="code" value="[% code | html %]" />
[% ELSE %]
<input type="text" name="code" id="code" size="80" maxlength="64" class="required" required="required"><span class="required">[% t('Required. Maximum length is 64 letters') %]</span>
[% END %]
</li>
<li>
<label for="description" class="required">[% t('Description:') %] </label>
<input type="text" name="description" id="description" required="required" class="required" size="80" maxlength="100" value="[% credit_type.description | html %]" /> <span class="required">[% t('Required') %]</span>
</li>
<li>
<label for="can_be_added_manually">[% t('Can be manually added ?') %] </label>
[% IF credit_type.can_be_added_manually %]
<input type="checkbox" name="can_be_added_manually" id="can_be_added_manually" checked="checked" value="1" />
[% ELSE %]
<input type="checkbox" name="can_be_added_manually" id="can_be_added_manually" value="1" />
[% END %]
</li>
<li>
<label for="branches">[% t('Libraries limitation:') %] </label>
<select id="branches" name="branches" multiple size="10">
<option value="">[% t('All libraries') %]</option>
[% FOREACH branch IN branches_loop %]
[% IF ( branch.selected ) %]
<option selected="selected" value="[% branch.branchcode | html %]">[% branch.branchname | html %]</option>
[% ELSE %]
<option value="[% branch.branchcode | html %]">[% branch.branchname | html %]</option>
[% END %]
[% END %]
</select>
<span>[% t("Select 'All libraries' if this credit type should be available at all libraries. Otherwise select libraries you want to associate credit type with.") %]</span>
</li>
</ol>
</fieldset>
<fieldset class="action">
<button id="save_credit_type" class="btn btn-default"><i class="fa fa-save"></i> [% t('Save') %]</button>
<a class="cancel btn-link" href="/cgi-bin/koha/admin/credit_types.pl"><i class="fa fa-times"></i> [% t('Cancel') %]</a>
</fieldset>
</form>
[% END %]
[% IF op == 'list' %]
<div id="toolbar" class="btn-toolbar">
<a class="btn btn-default" id="newcredittype" href="/cgi-bin/koha/admin/credit_types.pl?op=add_form"><i class="fa fa-plus"></i> [% t('New credit type') %]</a>
</div>
<h3>[% t('Account credit types') %]</h3>
[% IF credit_types.count %]
<table id="table_credit_types">
<thead>
<th>[% t('Archived') %]</th>
<th>[% t('System') %]</th>
<th>[% t('Code') %]</th>
<th>[% t('Description') %]</th>
<th>[% t('Available for') %]</th>
<th>[% t('Library limitations') %]</th>
<th>[% t('Actions') %]</th>
</thead>
<tbody>
[% FOREACH credit_type IN credit_types %]
<tr>
<td>[% credit_type.archived | html %]</td>
<td>[% credit_type.is_system | html %]</td>
<td>[% credit_type.code | html %]</td>
<td>[% credit_type.description | html %]</td>
<td>[% IF credit_type.can_be_added_manually %][% t('Manual credit') %][% END %]</td>
<td>
[% IF credit_type.library_limits.count > 0 %]
[% library_limits_str = "" %]
[% FOREACH library IN credit_type.library_limits %]
[%- IF loop.first -%]
[% library_limits_str = library.branchname _ " (" _ library.branchcode _ ")" %]
[% ELSE %]
[% library_limits_str = library_limits_str _ "\n" _ library.branchname _ " (" _ library.branchcode _ ")" %]
[% END %]
[% END %]
<span class="library_limitation" title="[% library_limits_str | html %]">
[% limits_count = credit_type.library_limits.count %]
[% tnx('{count} library limitation', '{count} library limitations', limits_count, { count => limits_count }) %]
[% ELSE %]
[% t('No limitation') %]
[% END %]
</td>
<td class="actions">
[% IF !credit_type.is_system && !credit_type.archived %]
<a class="btn btn-default btn-xs" href="/cgi-bin/koha/admin/credit_types.pl?op=add_form&amp;code=[% credit_type.code | uri %]&type=credit"><i class="fa fa-pencil"></i> [% t('Edit') %]</a>
<a class="btn btn-default btn-xs" href="/cgi-bin/koha/admin/credit_types.pl?op=archive&amp;code=[% credit_type.code | uri %]"><i class="fa fa-archive"></i> [% t('Archive') %]</a>
[% ELSIF credit_type.archived %]
<a class="btn btn-default btn-xs" href="/cgi-bin/koha/admin/credit_types.pl?op=unarchive&amp;code=[% credit_type.code | uri %]"><i class="fa fa-undo"></i> [% t('Restore') %]</a>
[% END %]
</td>
</tr>
[% END %]
</tbody>
</table>
[% ELSE %]
<div class="dialog message">
[% t('There are no account credit types defined.') %]
<a href="/cgi-bin/koha/admin/credit_types.pl?op=add_form">[% t('Create new credit type') %]</a>
</div>
[% END %]
[% END %]
</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 %]
[% INCLUDE 'datatables.inc' %]
<script>
$(document).ready(function() {
var txtActivefilter = _("Filter system credit types");
var txtInactivefilter = _("Show all credit types");
var table_credit_types = $("#table_credit_types").dataTable($.extend(true, {}, dataTablesDefaults, {
"aoColumnDefs": [
{ "aTargets": [ -1 ], "bSortable": false, "bSearchable": false },
{ "aTargets": [ 0, 1 ], "bSortable": false, "bVisible": false },
],
"aaSorting": [[ 0, "asc" ],[ 2, "asc" ]],
"sDom": 'C<"top pager"ilpfB><"#filter_s">tr<"bottom pager"ip>',
"iDisplayLength": 20,
"sPaginationType": "full_numbers"
}));
$("#filter_s").html('<p><a href="#" id="filter_system"><i class="fa fa-filter"></i> '+txtActivefilter+'</a>');
$('#filter_system').click(function(e) {
e.preventDefault();
if ($(this).hasClass('filtered')) {
var filteredValue = '';
$(this).html('<i class="fa fa-filter"></i> '+txtActivefilter);
} else { //Not filtered. Let's do it!
var filteredValue = '0';
$(this).html('<i class="fa fa-filter"></i> '+txtInactivefilter);
}
table_credit_types.fnFilter(filteredValue, 1, false, false);
$(this).toggleClass('filtered');
});
//Start filtered
$('#filter_system').click();
});
</script>
[% END %]
[% INCLUDE 'intranet-bottom.inc' %]

View File

@ -116,7 +116,7 @@ if ($add) {
else {
my @credit_types = Koha::Account::CreditTypes->search_with_library_limits(
{ can_be_added_manually => 1 },
{ can_be_added_manually => 1, archived => 0 },
{}, $library_id );
$template->param(