From 53df5ed34f861a9173dc00b916bcd9c5bbba4bdc Mon Sep 17 00:00:00 2001 From: Martin Renvoize <martin.renvoize@ptfs-europe.com> Date: Wed, 17 Jul 2019 08:13:02 +0100 Subject: [PATCH] Bug 23321: Add cash register management Add in administrative interfaces to allow the management of cash registers. --- Koha/Cash/Register.pm | 69 +++++++ Koha/Cash/Registers.pm | 58 ++++++ admin/cash_registers.pl | 139 ++++++++++++++ .../prog/en/modules/admin/admin-home.tt | 10 + .../prog/en/modules/admin/cash_registers.tt | 177 ++++++++++++++++++ 5 files changed, 453 insertions(+) create mode 100644 Koha/Cash/Register.pm create mode 100644 Koha/Cash/Registers.pm create mode 100755 admin/cash_registers.pl create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/admin/cash_registers.tt diff --git a/Koha/Cash/Register.pm b/Koha/Cash/Register.pm new file mode 100644 index 0000000000..15f8a49e23 --- /dev/null +++ b/Koha/Cash/Register.pm @@ -0,0 +1,69 @@ +package Koha::Cash::Register; + +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; + +use Carp; + +use Koha::Database; + +use base qw(Koha::Object); + +=encoding utf8 + +=head1 NAME + +Koha::Cash::Register - Koha cashregister Object class + +=head1 API + +=head2 Class methods + +=cut + +=head3 library + +Return the library linked to this cash register + +=cut + +sub library { + my ( $self ) = @_; + my $rs = $self->_result->branch; + return unless $rs; + return Koha::Library->_new_from_dbic( $rs ); +} + +=head2 Internal methods + +=cut + +=head3 _type + +=cut + +sub _type { + return 'CashRegister'; +} + +1; + +=head1 AUTHORS + +Martin Renvoize <martin.renvoize@ptfs-europe.com> + +=cut diff --git a/Koha/Cash/Registers.pm b/Koha/Cash/Registers.pm new file mode 100644 index 0000000000..2432dbb59a --- /dev/null +++ b/Koha/Cash/Registers.pm @@ -0,0 +1,58 @@ +package Koha::Cash::Registers; + +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; + +use Carp; + +use Koha::Database; + +use Koha::Cash::Register; + +use base qw(Koha::Objects); + +=head1 NAME + +Koha::Cash::Registers - Koha Cash Register Object set class + +=head1 API + +=head2 Class methods + + my $cash_registers = Koha::Cash::Registers->search({ ... }); + +Returns a list of cash registers. + +=head2 Internal methods + +=head3 _type + +=cut + +sub _type { + return 'CashRegister'; +} + +=head3 object_class + +=cut + +sub object_class { + return 'Koha::Cash::Register'; +} + +1; diff --git a/admin/cash_registers.pl b/admin/cash_registers.pl new file mode 100755 index 0000000000..4e76e72944 --- /dev/null +++ b/admin/cash_registers.pl @@ -0,0 +1,139 @@ +#!/usr/bin/perl +# +# Copyright 2019 PTFS Europe +# +# 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 strict; +use warnings; + +use CGI; +use Try::Tiny; + +use C4::Auth; +use Koha::Libraries; +use C4::Koha; +use C4::Context; +use C4::Output; +use Koha::Cash::Registers; + +my $cgi = CGI->new(); +my ( $template, $borrowernumber, $cookie ) = get_template_and_user( + { + template_name => 'admin/cash_registers.tt', + query => $cgi, + type => 'intranet', + authnotrequired => 0, + flagsrequired => { admin => 'edit_cash_registers' }, + } +); + +my $op = $cgi->param('op') || 'list'; +my $registerid = $cgi->param('id'); # update/archive +my $dbh = C4::Context->dbh; +my @messages; +if ( $op eq 'add_form' ) { + if ($registerid) { + my $cash_register = Koha::Cash::Registers->find($registerid); + $template->param( cash_register => $cash_register ); + } + my $libraries = + Koha::Libraries->search( {}, { order_by => ['branchcode'] }, ); + $template->param( + branch_list => $libraries, + add_form => 1 + ); +} +elsif ( $op eq 'add_validate' ) { + my $name = $cgi->param('name'); + $name ||= q{}; + my $description = $cgi->param('description'); + $description ||= q{}; + my $branch = $cgi->param('branch'); + my $float = $cgi->param('starting_float') // 0; + if ($registerid) { + try { + my $cash_register = Koha::Cash::Registers->find($registerid); + $cash_register->set( + { + name => $name, + description => $description, + branch => $branch, + starting_float => $float + } + )->store; + push @messages, { code => 'success_on_update', type => 'message' }; + } + catch { + push @messages, { code => 'error_on_update', type => 'alert' }; + } + } + else { + try { + my $cash_register = Koha::Cash::Register->new( + { + name => $name, + description => $description, + branch => $branch, + starting_float => $float, + } + )->store; + push @messages, { code => 'success_on_insert', type => 'message' }; + } + catch { + push @messages, { code => 'error_on_insert', type => 'alert' }; + } + } + $op = 'list'; +} + +elsif ( $op eq 'archive' ) { + if ($registerid) { + try { + my $cash_register = Koha::Cash::Registers->find($registerid); + $cash_register->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' ) { + if ($registerid) { + try { + my $cash_register = Koha::Cash::Registers->find($registerid); + $cash_register->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 $cash_registers = + Koha::Cash::Registers->search( {}, { prefetch => 'branch' } ); + $template->param( cash_registers => $cash_registers, ); +} + +$template->param( op => $op, messages => \@messages ); + +output_html_with_http_headers $cgi, $cookie, $template->output; diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt index 389b2ad406..4095e516e9 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt @@ -98,6 +98,16 @@ </dl> [% END %] + [% IF ( Koha.Preference('UseCashRegisters') && CAN_user_cash_management_manage_cash_registers ) %] + <h3>Accounting</h3> + <dl> + [% IF ( CAN_user_cash_management_manage_cash_registers ) %] + <dt><a href="/cgi-bin/koha/admin/cash_registers.pl">Cash registers</a></dt> + <dd>Define cash registers</dd> + [% END %] + </dl> + [% END %] + [% IF CAN_user_plugins && plugins_enabled %] <h3>Plugins</h3> <dl> diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/cash_registers.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/cash_registers.tt new file mode 100644 index 0000000000..e251ee6060 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/cash_registers.tt @@ -0,0 +1,177 @@ +[% USE raw %] +[% USE Asset %] +[% SET footerjs = 1 %] +[% USE ColumnsSettings %] +[% INCLUDE 'doc-head-open.inc' %] +<title>Koha › Administration › Cash Registers +[% IF op == 'add_form' %] + ›[% IF cash_register %]Modify cash register[% ELSE %]New cash register [% cash_register.id | html %][% END %] +[% ELSIF op == 'delete_confirm' %] + › Confirm deletion of cash register '[% cash_register.id | html %]' +[% END %] +</title> +[% INCLUDE 'doc-head-close.inc' %] +</head> + +<body id="admin_cash_registers" class="admin"> +[% INCLUDE 'header.inc' %] +[% INCLUDE 'prefs-admin-search.inc' %] + +<div id="breadcrumbs"> + <a href="/cgi-bin/koha/mainpage.pl">Home</a> +› <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a> +› <a href="/cgi-bin/koha/admin/cash_registers.pl">Cash registers</a> +[% IF op == 'add_form' %] +› [% IF cash_register %]Modify cash register [% cash_register.id | html %][% ELSE %]New cash register[% END %] +[% ELSIF op == 'delete_confirm' %] +› Confirm deletion of cash register '[% cash_register.id | html %]' +[% 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 'error_on_update' %] + An error occurred when updating this cash register. + [% CASE 'error_on_insert' %] + An error occurred when adding this cash register. + [% CASE 'success_on_update' %] + Cash register updated successfully. + [% CASE 'success_on_insert' %] + Cash register added successfully. + [% CASE 'success_on_archive' %] + Cash register archived successfully. + [% CASE 'success_on_restore' %] + Cash register restored successfully. + [% CASE 'success_on_delete' %] + Cash register deleted successfully. + [% CASE %] + [% m.code | html %] + [% END %] + </div> + [% END %] + + [% IF op == 'add_form' %] + <h3>[% IF cash_register %]Modify cash register[% ELSE %]Add new cash_register[% END %]</h3> + <form action="/cgi-bin/koha/admin/cash_registers.pl" id="Aform" name="Aform" class="validated" method="post"> + + <fieldset class="rows"> + <input type="hidden" name="op" value="add_validate" /> + <ol> + [% IF cash_register %] + <li> + <span class="label">Cash Register ID: </span>[% cash_register.id | html %] + <input type="hidden" name="id" value="[% cash_register.id %]" /> + </li> + [% END %] + + <li> + <label for="name" class="required">Name: </label> + <input type="text" name="name" id="name" size="80" value="[% cash_register.name | html %]" class="required" /> + <span class="required">Required</span> + </li> + + <li> + <label for="description">Description: </label> + <input type="text" name="description" id="description" value="[% cash_register.description %]"/> + </li> + <li> + <label for="branch">Branch: </label> + <select id="branch" name="branch"> + [% FOREACH branch IN branch_list %] + [% IF cash_register.branch == branch.branchcode %] + <option value="[% branch.branchcode %]" selected="1">[% branch.branchname %]</option> + [% ELSE %] + <option value="[% branch.branchcode %]">[% branch.branchname %]</option> + [% END %] + [% END %] + </select> + </li> + + <li> + <label for="starting_float">Initial float: </label> + <input type="text" pattern='^\d+(?:\.\d{0,2})$' name="starting_float" id="starting_float" value="[% cash_register.starting_float %]" /> + </li> + </ol> + </fieldset> + + <fieldset class="action"> + [% IF cash_register %] + <input type="submit" value="Save" /> + [% ELSE %] + <input type="submit" value="Add" /> + [% END %] + <a class=cancel" href="/cgi-bin/koha/admin/cash_registers.pl?op=list">Cancel</a> + </fieldset> + </form> + [% END %] + + [% IF op == 'list' %] + <div id="toolbar" class="btn-toolbar"> + <a class="btn btn-default" id="newcashregister" href="/cgi-bin/koha/admin/cash_registers.pl?op=add_form"><i class="fa fa-plus"></i> New cash register</a> + </div> + + <h3>Cash Registers</h3> + [% IF cash_registers.count %] + <table id="table_cash_registers"> + <thead> + <th>Id</th> + <th>Name</th> + <th>Description</th> + <th>Branch</th> + <th>Initial float</th> + <th>Actions</th> + </thead> + <tbody> + [% FOREACH cash_register IN cash_registers %] + <tr> + <td>[% cash_register.id %]</td> + <td>[% cash_register.name %]</td> + <td>[% cash_register.description %]</td> + <td>[% cash_register.library.branchname %]</td> + <td>[% cash_register.starting_float %]</td> + [% IF cash_register.archived == '0' %] + <td class="actions"><a class="btn btn-default btn-xs" href="cash_registers.pl?op=add_form&id=[% cash_register.id | uri %]"><i class="fa fa-pencil"></i> Edit</a><a class="btn btn-default btn-xs" href="cash_registers.pl?op=archive&id=[% cash_register.id %]"><i class="fa fa-archive"></i> Archive</a></td> + [% ELSE %] + <td class="actions"><a class="btn btn-default btn-xs" href="cash_registers.pl?op=unarchive&id=[% cash_register.id %]"><i class="fa fa-trash-restore"></i> Restore</a></td> + [% END %] + </tr> + [% END %] + </tbody> + </table> + [% ELSE %] + <div class="dialog message">There are no cash registers defined. <a href="/cgi-bin/koha/admin/cash_registers.pl?op=add_form">Start adding cash registers</a>.</div> + [% END # /cash_register.count %] + [% END # /op == 'list' %] + </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() { + $("#table_cash_registers").dataTable($.extend(true, {}, dataTablesDefaults, { + "aoColumnDefs": [ + { "aTargets": [ -1, -2 ], "bSortable": false, "bSearchable":false }, + ], + "aaSorting": [[ 1, "asc" ]], + })); + }); + </script> +[% END %] + +[% INCLUDE 'intranet-bottom.inc' %] -- 2.20.1