Bug 18736: Unit tests for rounding
authorNick Clemens <nick@bywatersolutions.com>
Tue, 6 Jun 2017 14:37:17 +0000 (10:37 -0400)
committerMartin Renvoize <martin.renvoize@ptfs-europe.com>
Mon, 25 Mar 2019 14:29:29 +0000 (14:29 +0000)
Unit tests to highlight the issue

To test:
Prove t/db_dependent/Budgets.t
prove t/Acquisition.t

Signed-off-by: Julian Maurice <julian.maurice@biblibre.com>

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>

Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
(cherry picked from commit bf0882252f242efa8cc9f08625c0abe305d205a6)
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>

t/Acquisition.t [new file with mode: 0644]
t/db_dependent/Budgets.t

diff --git a/t/Acquisition.t b/t/Acquisition.t
new file mode 100644 (file)
index 0000000..1acca9c
--- /dev/null
@@ -0,0 +1,68 @@
+#!/usr/bin/perl
+
+# This file is part of Koha.
+#
+# Copyright (C) 2018  Mark Tompsett
+#
+# 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 Test::More tests => 3;
+use t::lib::Mocks;
+
+use_ok( 'C4::Acquisition' );
+
+subtest 'Tests for _get_rounding_sql' => sub {
+
+    plan tests => 2;
+
+    my $value = '3.141592';
+
+    t::lib::Mocks::mock_preference( 'OrderPriceRounding', q{} );
+    my $no_rounding_result = C4::Acquisition::_get_rounding_sql($value);
+    t::lib::Mocks::mock_preference( 'OrderPriceRounding', q{nearest_cent} );
+    my $rounding_result = C4::Acquisition::_get_rounding_sql($value);
+
+    ok( $no_rounding_result eq $value, "Value ($value) not to be rounded" );
+    ok( $rounding_result =~ /CAST/,    "Value ($value) will be rounded" );
+
+};
+
+subtest 'Test for get_rounded_price' => sub {
+
+    plan tests => 6;
+
+    my $exact_price      = 3.14;
+    my $up_price         = 3.145592;
+    my $down_price       = 3.141592;
+    my $round_up_price   = sprintf( '%0.2f', $up_price );
+    my $round_down_price = sprintf( '%0.2f', $down_price );
+
+    t::lib::Mocks::mock_preference( 'OrderPriceRounding', q{} );
+    my $not_rounded_result1 = C4::Acquisition::get_rounded_price($exact_price);
+    my $not_rounded_result2 = C4::Acquisition::get_rounded_price($up_price);
+    my $not_rounded_result3 = C4::Acquisition::get_rounded_price($down_price);
+    t::lib::Mocks::mock_preference( 'OrderPriceRounding', q{nearest_cent} );
+    my $rounded_result1 = C4::Acquisition::get_rounded_price($exact_price);
+    my $rounded_result2 = C4::Acquisition::get_rounded_price($up_price);
+    my $rounded_result3 = C4::Acquisition::get_rounded_price($down_price);
+
+    is( $not_rounded_result1, $exact_price,      "Price ($exact_price) was correctly not rounded ($not_rounded_result1)" );
+    is( $not_rounded_result2, $up_price,         "Price ($up_price) was correctly not rounded ($not_rounded_result2)" );
+    is( $not_rounded_result3, $down_price,       "Price ($down_price) was correctly not rounded ($not_rounded_result3)" );
+    is( $rounded_result1,     $exact_price,      "Price ($exact_price) was correctly rounded ($rounded_result1)" );
+    is( $rounded_result2,     $round_up_price,   "Price ($up_price) was correctly rounded ($rounded_result2)" );
+    is( $rounded_result3,     $round_down_price, "Price ($down_price) was correctly rounded ($rounded_result3)" );
+
+};
index 6cb87a7..816d97a 100755 (executable)
@@ -13,6 +13,7 @@ use Koha::Acquisition::Booksellers;
 use Koha::Acquisition::Orders;
 use Koha::Acquisition::Funds;
 use Koha::Patrons;
+use Koha::Number::Price;
 
 use t::lib::TestBuilder;
 use t::lib::Mocks;
@@ -20,6 +21,9 @@ use Koha::DateUtils;
 
 use YAML;
 
+use t::lib::Mocks;
+t::lib::Mocks::mock_preference('OrderPriceRounding','');
+
 my $schema  = Koha::Database->new->schema;
 $schema->storage->txn_begin;
 my $builder = t::lib::TestBuilder->new;
@@ -477,6 +481,7 @@ ModReceiveOrder({
    invoice           => $test_invoice,
    received_items    => [],
 } );
+t::lib::Mocks::mock_preference('OrderPriceRounding','');
 
 is ( GetBudgetSpent( $fund ), 6, "total shipping cost is 6");
 is ( GetBudgetOrdered( $fund ), '20', "total ordered price is 20");
@@ -959,6 +964,92 @@ subtest 'GetBudgetSpent and GetBudgetOrdered' => sub {
     is( $ordered, 3, "After adding invoice adjustment on a child budget, should still be 3 ordered/budget unaffected");
     is( @$hierarchy[0]->{total_spent},9,"After adding invoice adjustment on child budget, budget hierarchy shows 9 spent");
     is( @$hierarchy[0]->{total_ordered},6,"After adding invoice adjustment on child budget, budget hierarchy shows 6 ordered");
+};
+
+subtest 'OrderPriceRounding GetBudgetSpent GetBudgetOrdered tests' => sub {
+
+    plan tests => 8;
+
+#Let's build an order, we need a couple things though
+
+    my $spent_biblio = $builder->build({ source => 'Biblio' });
+    my $spent_basket = $builder->build({ source => 'Aqbasket', value => { is_standing => 0 } });
+    my $spent_invoice = $builder->build({ source => 'Aqinvoice'});
+    my $spent_currency = $builder->build({ source => 'Currency', value => { active => 1, archived => 0, symbol => 'F', rate => 2, isocode => undef, currency => 'FOO' }  });
+    my $spent_vendor = $builder->build({ source => 'Aqbookseller',value => { listincgst => 0, listprice => $spent_currency->{currency}, invoiceprice => $spent_currency->{currency} } });
+    my $spent_orderinfo = {
+        basketno => $spent_basket->{basketno},
+        booksellerid => $spent_vendor->{id},
+        rrp => 16.99,
+        discount => .42,
+        ecost => 16.91,
+        biblionumber => $spent_biblio->{biblionumber},
+        currency => $spent_currency->{currency},
+        tax_rate_on_ordering => 0,
+        tax_value_on_ordering => 0,
+        tax_rate_on_receiving => 0,
+        tax_value_on_receiving => 0,
+        quantity => 8,
+        quantityreceived => 0,
+        datecancellationprinted => undef,
+        datereceived => undef,
+    };
+
+#Okay we have basically what the user would enter, now we do some maths
+
+    $spent_orderinfo = C4::Acquisition::populate_order_with_prices({
+            order        => $spent_orderinfo,
+            booksellerid => $spent_orderinfo->{booksellerid},
+            ordering     => 1,
+    });
+
+#And let's place the order
+
+    my $spent_order = $builder->build({ source => 'Aqorder', value => $spent_orderinfo });
+    t::lib::Mocks::mock_preference('OrderPriceRounding','');
+    my $spent_ordered = GetBudgetOrdered( $spent_order->{budget_id} );
+
+    is($spent_orderinfo->{ecost_tax_excluded}, 9.854200,'We store extra precision in price calculation');
+    is( Koha::Number::Price->new($spent_orderinfo->{ecost_tax_excluded})->format(), 9.85,'But the price as formatted is two digits');
+    is($spent_ordered,'78.8336',"We expect the ordered amount to be equal to the estimated price times quantity with full precision");
+
+    t::lib::Mocks::mock_preference('OrderPriceRounding','nearest_cent');
+    $spent_ordered = GetBudgetOrdered( $spent_order->{budget_id} );
+    is($spent_ordered,'78.8',"We expect the ordered amount to be equal to the estimated price rounded times quantity");
+
+#Okay, now we can receive the order, giving the price as the user would
+
+    $spent_orderinfo->{unitprice} = 9.85; #we are paying what we expected
+
+#Do our maths
+
+    $spent_orderinfo = C4::Acquisition::populate_order_with_prices({
+            order        => $spent_orderinfo,
+            booksellerid => $spent_orderinfo->{booksellerid},
+            receiving    => 1,
+    });
+    my $received_order = $builder->build({ source => 'Aqorder', value => $spent_orderinfo });
+
+#And receive
+
+    ModReceiveOrder({
+            biblionumber => $spent_order->{biblionumber},
+            order => $received_order,
+            invoice => $spent_invoice,
+            quantityreceived => $spent_order->{quantity},
+            budget_id => $spent_order->{budget_id},
+            received_items => [],
+    });
+
+    t::lib::Mocks::mock_preference('OrderPriceRounding','');
+    my $spent_spent = GetBudgetSpent( $spent_order->{budget_id} );
+    is($spent_orderinfo->{unitprice_tax_excluded}, 9.854200,'We store extra precision in price calculation');
+    is( Koha::Number::Price->new($spent_orderinfo->{unitprice_tax_excluded})->format(), 9.85,'But the price as formatted is two digits');
+    is($spent_spent,'78.8336',"We expect the spent amount to be equal to the estimated price times quantity with full precision");
+
+    t::lib::Mocks::mock_preference('OrderPriceRounding','nearest_cent');
+    $spent_spent = GetBudgetSpent( $spent_order->{budget_id} );
+    is($spent_spent,'78.8',"We expect the spent amount to be equal to the estimated price rounded times quantity");
 
 };