Bugzilla – Attachment 77616 Details for
Bug 18736
Problems in order calculations (rounding errors)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 18736: Unit tests for rounding
Bug-18736-Unit-tests-for-rounding.patch (text/plain), 9.02 KB, created by
Nick Clemens (kidclamp)
on 2018-08-09 10:30:27 UTC
(
hide
)
Description:
Bug 18736: Unit tests for rounding
Filename:
MIME Type:
Creator:
Nick Clemens (kidclamp)
Created:
2018-08-09 10:30:27 UTC
Size:
9.02 KB
patch
obsolete
>From 4206beb1a034d5cf136f959ed54fef49c6862817 Mon Sep 17 00:00:00 2001 >From: Nick Clemens <nick@bywatersolutions.com> >Date: Tue, 6 Jun 2017 10:37:17 -0400 >Subject: [PATCH] Bug 18736: Unit tests for rounding > >Unit tests to highlight the issue > >To test: >Prove t/db_dependent/Budgets.t >prove t/Acquisition.t >--- > t/Acquisition.t | 68 +++++++++++++++++++++++++++++++++++ > t/db_dependent/Budgets.t | 93 +++++++++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 160 insertions(+), 1 deletion(-) > create mode 100644 t/Acquisition.t > >diff --git a/t/Acquisition.t b/t/Acquisition.t >new file mode 100644 >index 0000000..1acca9c >--- /dev/null >+++ b/t/Acquisition.t >@@ -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)" ); >+ >+}; >diff --git a/t/db_dependent/Budgets.t b/t/db_dependent/Budgets.t >index e28e20c..f7936bf 100755 >--- a/t/db_dependent/Budgets.t >+++ b/t/db_dependent/Budgets.t >@@ -1,6 +1,6 @@ > #!/usr/bin/perl > use Modern::Perl; >-use Test::More tests => 145; >+use Test::More tests => 146; > > BEGIN { > use_ok('C4::Budgets') >@@ -12,11 +12,15 @@ use C4::Acquisition; > use Koha::Acquisition::Booksellers; > use Koha::Acquisition::Orders; > use Koha::Patrons; >+use Koha::Number::Price; > > use t::lib::TestBuilder; > > 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; >@@ -470,6 +474,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"); >@@ -909,6 +914,92 @@ subtest 'GetBudgetSpent and GetBudgetOrdered' => sub { > $ordered = GetBudgetOrdered( $budget->{budget_id} ); > is( $spent, 6, "After adding invoice adjustment on a different budget should be 6 spent/budget unaffected"); > is( $ordered, 3, "After adding invoice adjustment on a different budget, should still be 3 ordered/budget unaffected"); >+}; >+ >+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"); > > }; > >-- >2.1.4
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 18736
:
64061
|
64065
|
70187
|
70188
|
70189
|
70768
|
71062
|
71063
|
71627
|
71628
|
71629
|
71630
|
71631
|
71632
|
74335
|
74336
|
74337
|
74338
|
74339
|
74340
|
74341
|
74342
|
74370
|
74371
|
74374
|
74397
|
74398
|
74422
|
74427
|
74438
|
76979
|
76980
|
76981
|
76982
|
76983
|
76984
|
76985
|
76986
|
76987
|
76988
|
76989
|
76990
|
76991
|
77614
|
77615
|
77616
|
77617
|
77618
|
78101
|
78120
|
78981
|
78982
|
78983
|
78984
|
78985
|
78986
|
78987
|
78988
|
79087
|
79088
|
79089
|
79090
|
79091
|
79092
|
79093
|
79094
|
79098
|
79099
|
79100
|
79101
|
79102
|
79103
|
79104
|
79105
|
79187
|
79223
|
79562
|
79563
|
82967
|
82968
|
82969
|
82970
|
82971
|
82972
|
82973
|
82974
|
82975
|
82976
|
82977
|
83212
|
83213
|
83214
|
83973
|
83974
|
83975
|
83976
|
83977
|
83978
|
83979
|
83980
|
83981
|
83982
|
83983
|
83984
|
83985
|
86646
|
86647
|
86648
|
86649
|
86650
|
86651
|
86652
|
86653
|
86654
|
86655
|
86656
|
86657
|
86658