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 &rsaquo; Administration &rsaquo; Cash Registers
+[% IF op == 'add_form' %]
+    &rsaquo;[% IF cash_register %]Modify cash register[% ELSE %]New cash register [% cash_register.id | html %][% END %]
+[% ELSIF op == 'delete_confirm' %]
+    &rsaquo; 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>
+&rsaquo; <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a>
+&rsaquo; <a href="/cgi-bin/koha/admin/cash_registers.pl">Cash registers</a>
+[% IF op == 'add_form'  %]
+&rsaquo; [% IF cash_register %]Modify cash register [% cash_register.id | html %][% ELSE %]New cash register[% END %]
+[% ELSIF op == 'delete_confirm' %]
+&rsaquo; 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&amp;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&amp;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&amp;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