From aefaa211478561b43bf6a4064397d7cd9a0e139f Mon Sep 17 00:00:00 2001
From: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Date: Tue, 23 Jul 2019 14:06:49 +0100
Subject: [PATCH] Bug 23355: Add CASHUP actions

---
 Koha/Cash/Register.pm               | 117 +++++++++++++++++++++-
 Koha/Cash/Register/Action.pm        |  69 +++++++++++++
 Koha/Cash/Register/Actions.pm       |  58 +++++++++++
 t/db_dependent/Koha/Cash/Register.t | 145 ++++++++++++++++++++++++++--
 4 files changed, 382 insertions(+), 7 deletions(-)
 create mode 100644 Koha/Cash/Register/Action.pm
 create mode 100644 Koha/Cash/Register/Actions.pm

diff --git a/Koha/Cash/Register.pm b/Koha/Cash/Register.pm
index b3fe0f5413..8c87d0cfc3 100644
--- a/Koha/Cash/Register.pm
+++ b/Koha/Cash/Register.pm
@@ -19,6 +19,10 @@ use Modern::Perl;
 
 use Carp;
 
+use Koha::Account::Lines;
+use Koha::Account::Offsets;
+use Koha::Cash::Register::Action;
+use Koha::Cash::Register::Actions;
 use Koha::Database;
 
 use base qw(Koha::Object);
@@ -48,6 +52,95 @@ sub library {
     return Koha::Library->_new_from_dbic($rs);
 }
 
+=head3 cashups
+
+Return a set of cashup actions linked to this cash register
+
+=cut
+
+sub cashups {
+    my ( $self, $conditions, $attrs ) = @_;
+
+    my $local_conditions = { code => 'CASHUP' };
+    $conditions //= {};
+    my $merged_conditions = { %{$conditions}, %{$local_conditions} };
+
+    my $rs =
+      $self->_result->search_related( 'cash_register_actions',
+        $merged_conditions, $attrs );
+    return unless $rs;
+    return Koha::Cash::Register::Actions->_new_from_dbic($rs);
+}
+
+=head3 last_cashup
+
+Return a set of cashup actions linked to this cash register
+
+=cut
+
+sub last_cashup {
+    my ( $self, $conditions, $attrs ) = @_;
+
+    my $rs = $self->_result->search_related(
+        'cash_register_actions',
+        { code     => 'CASHUP' },
+        { order_by => { '-desc' => [ 'timestamp', 'id' ] }, rows => 1 }
+    )->single;
+
+    return unless $rs;
+    return Koha::Cash::Register::Action->_new_from_dbic($rs);
+}
+
+=head3 accountlines
+
+Return a set of accountlines linked to this cash register
+
+=cut
+
+sub accountlines {
+    my ($self) = @_;
+
+    my $rs = $self->_result->accountlines;
+    return unless $rs;
+    return Koha::Account::Lines->_new_from_dbic($rs);
+}
+
+=head3 outstanding_accountlines
+
+  my $lines = Koha::Cash::Registers->find($id)->outstanding_accountlines;
+
+Return a set of accountlines linked to this cash register since the last cashup action
+
+=cut
+
+sub outstanding_accountlines {
+    my ( $self, $conditions, $attrs ) = @_;
+
+    my $since = $self->_result->search_related(
+        'cash_register_actions',
+        { 'code' => 'CASHUP' },
+        {
+            order_by => { '-desc' => [ 'timestamp', 'id' ] },
+            rows     => 1
+        }
+    );
+
+    my $local_conditions =
+      $since->count
+      ? { 'timestamp' => { '>=' => $since->get_column('timestamp')->as_query } }
+      : {};
+    my $merged_conditions =
+      $conditions
+      ? { %{$conditions}, %{$local_conditions} }
+      : $local_conditions;
+
+    my $rs =
+      $self->_result->search_related( 'accountlines', $merged_conditions,
+        $attrs );
+    return unless $rs;
+    return Koha::Account::Lines->_new_from_dbic($rs);
+}
+
 =head3 store
 
 Local store method to prevent direct manipulation of the 'branch_default' field
@@ -63,7 +156,9 @@ sub store {
                     property => 'branch_default' );
             }
             else {
-                if ($self->_result->is_column_changed('branch') && $self->branch_default) {
+                if (   $self->_result->is_column_changed('branch')
+                    && $self->branch_default )
+                {
                 }
                 $self = $self->SUPER::store;
             }
@@ -113,6 +208,26 @@ sub drop_default {
     return $self;
 }
 
+=head3 add_cashup
+
+Add a new cashup action to the till, returns the added action.
+
+=cut
+
+sub add_cashup {
+    my ( $self, $params ) = @_;
+
+    my $rs = $self->_result->add_to_cash_register_actions(
+        {
+            code       => 'CASHUP',
+            manager_id => $params->{user_id},
+            amount     => $params->{amount}
+        }
+    )->discard_changes;
+
+    return Koha::Cash::Register::Action->_new_from_dbic($rs);
+}
+
 =head2 Internal methods
 
 =cut
diff --git a/Koha/Cash/Register/Action.pm b/Koha/Cash/Register/Action.pm
new file mode 100644
index 0000000000..2996e622fb
--- /dev/null
+++ b/Koha/Cash/Register/Action.pm
@@ -0,0 +1,69 @@
+package Koha::Cash::Register::Action;
+
+# 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::Action - Koha cashregister::action Object class
+
+=head1 API
+
+=head2 Class methods
+
+=cut
+
+=head3 manager
+
+Return the manager linked to this cash register::action
+
+=cut
+
+sub manager {
+    my ($self) = @_;
+    my $rs = $self->_result->manager;
+    return unless $rs;
+    return Koha::Patron->_new_from_dbic($rs);
+}
+
+=head2 Internal methods
+
+=cut
+
+=head3 _type
+
+=cut
+
+sub _type {
+    return 'CashRegisterAction';
+}
+
+1;
+
+=head1 AUTHORS
+
+Martin Renvoize <martin.renvoize@ptfs-europe.com>
+
+=cut
diff --git a/Koha/Cash/Register/Actions.pm b/Koha/Cash/Register/Actions.pm
new file mode 100644
index 0000000000..7c629e580c
--- /dev/null
+++ b/Koha/Cash/Register/Actions.pm
@@ -0,0 +1,58 @@
+package Koha::Cash::Register::Actions;
+
+# 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::Action;
+
+use base qw(Koha::Objects);
+
+=head1 NAME
+
+Koha::Cash::Register::Actions - Koha Cash Register Action Object set class
+
+=head1 API
+
+=head2 Class methods
+
+    my $cash_register::actions = Koha::Cash::Register::Actions->search({ ...  });
+
+Returns a list of cash register::actions.
+
+=head2 Internal methods
+
+=head3 _type
+
+=cut
+
+sub _type {
+    return 'CashRegisterAction';
+}
+
+=head3 object_class
+
+=cut
+
+sub object_class {
+    return 'Koha::Cash::Register::Action';
+}
+
+1;
diff --git a/t/db_dependent/Koha/Cash/Register.t b/t/db_dependent/Koha/Cash/Register.t
index 74bef789c8..567e125b33 100644
--- a/t/db_dependent/Koha/Cash/Register.t
+++ b/t/db_dependent/Koha/Cash/Register.t
@@ -19,7 +19,7 @@
 
 use Modern::Perl;
 
-use Test::More tests => 2;
+use Test::More tests => 4;
 
 use Test::Exception;
 
@@ -54,6 +54,42 @@ subtest 'library' => sub {
     $schema->storage->txn_rollback;
 };
 
+subtest 'accountlines' => sub {
+    plan tests => 3;
+
+    $schema->storage->txn_begin;
+
+    my $register =
+      $builder->build_object( { class => 'Koha::Cash::Registers' } );
+    my $accountline1 = $builder->build_object(
+        {
+            class => 'Koha::Account::Lines',
+            value => { register_id => $register->id },
+        }
+    );
+    my $accountline2 = $builder->build_object(
+        {
+            class => 'Koha::Account::Lines',
+            value => { register_id => $register->id },
+        }
+    );
+
+    my $accountlines = $register->accountlines;
+    is( ref($accountlines), 'Koha::Account::Lines',
+'Koha::Cash::Register->accountlines should return a set of Koha::Account::Lines'
+    );
+    is( $accountlines->count, 2,
+'Koha::Cash::Register->accountlines should return the correct number of accountlines'
+    );
+
+    $accountline1->delete;
+    is( $register->accountlines->next->id, $accountline2->id,
+'Koha::Cash::Register->accountlines should return the correct acocuntlines'
+    );
+
+    $schema->storage->txn_rollback;
+};
+
 subtest 'branch_default' => sub {
     plan tests => 3;
 
@@ -89,21 +125,118 @@ subtest 'branch_default' => sub {
     subtest 'make_default' => sub {
         plan tests => 3;
 
-        ok($register2->make_default,'Koha::Register->make_default ran');
+        ok( $register2->make_default, 'Koha::Register->make_default ran' );
 
         $register1 = $register1->get_from_storage;
         $register2 = $register2->get_from_storage;
-        is($register1->branch_default, 0, 'register1 was unset as expected');
-        is($register2->branch_default, 1, 'register2 was set as expected');
+        is( $register1->branch_default, 0, 'register1 was unset as expected' );
+        is( $register2->branch_default, 1, 'register2 was set as expected' );
     };
 
     subtest 'drop_default' => sub {
         plan tests => 2;
 
-        ok($register2->drop_default,'Koha::Register->drop_default ran');
+        ok( $register2->drop_default, 'Koha::Register->drop_default ran' );
 
         $register2 = $register2->get_from_storage;
-        is($register2->branch_default, 0, 'register2 was unset as expected');
+        is( $register2->branch_default, 0, 'register2 was unset as expected' );
+    };
+
+    $schema->storage->txn_rollback;
+};
+
+subtest 'cashup' => sub {
+    plan tests => 3;
+
+    $schema->storage->txn_begin;
+
+    my $register =
+      $builder->build_object( { class => 'Koha::Cash::Registers' } );
+    my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
+
+    my $cashup1;
+    subtest 'add_cashup' => sub {
+        plan tests => 6;
+
+        ok(
+            $cashup1 = $register->add_cashup(
+                { user_id => $patron->id, amount => '12.00' }
+            ),
+            'call successfull'
+        );
+
+        is(
+            ref($cashup1),
+            'Koha::Cash::Register::Action',
+            'return is Koha::Cash::Register::Action'
+        );
+        is( $cashup1->code, 'CASHUP',
+            'CASHUP code set in Koha::Cash::Register::Action' );
+        is( $cashup1->manager_id, $patron->id,
+            'manager_id set correctly in Koha::Cash::Register::Action' );
+        is( $cashup1->amount, '12.000000',
+            'amount set correctly in Koha::Cash::Register::Action' );
+        isnt( $cashup1->timestamp, undef,
+            'timestamp set in Koha::Cash::Register::Action' );
+    };
+
+    subtest 'last_cashup' => sub {
+        plan tests => 3;
+
+        my $cashup2 =
+          $register->add_cashup( { user_id => $patron->id, amount => '6.00' } );
+
+        my $last_cashup = $register->last_cashup;
+        is(
+            ref($last_cashup),
+            'Koha::Cash::Register::Action',
+            'A cashup was returned when one existed'
+        );
+        is( $last_cashup->id, $cashup2->id,
+            'The most recent cashup was returned' );
+        $cashup1->delete;
+        $cashup2->delete;
+        $last_cashup = $register->last_cashup;
+        is( $last_cashup, undef, 'undef is returned when no cashup exists' );
+    };
+
+    subtest 'outstanding_accountlines' => sub {
+        plan tests => 4;
+
+        my $accountline1 = $builder->build_object(
+            {
+                class => 'Koha::Account::Lines',
+                value => { register_id => $register->id },
+            }
+        );
+        my $accountline2 = $builder->build_object(
+            {
+                class => 'Koha::Account::Lines',
+                value => { register_id => $register->id },
+            }
+        );
+
+        my $accountlines = $register->outstanding_accountlines;
+        is( $accountlines->count, 2, 'No cashup, all accountlines returned' );
+
+        my $cashup3 =
+          $register->add_cashup( { user_id => $patron->id, amount => '2.50' } );
+
+        $accountlines = $register->outstanding_accountlines;
+        is( $accountlines->count, 0, 'Cashup added, no accountlines returned' );
+
+        my $accountline3 = $builder->build_object(
+            {
+                class => 'Koha::Account::Lines',
+                value => { register_id => $register->id },
+            }
+        );
+
+        $accountlines = $register->outstanding_accountlines;
+        is( $accountlines->count, 1,
+            'Accountline added, one accountline returned' );
+        is( $accountlines->next->id,
+            $accountline3->id, 'Correct accountline returned' );
     };
 
     $schema->storage->txn_rollback;
-- 
2.20.1