From c4c5f962628d29495824e6d8f22f7affa76b0749 Mon Sep 17 00:00:00 2001 From: Nick Clemens 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 | 91 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+) 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 . + +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 ec14e11..d8100c2 100755 --- a/t/db_dependent/Budgets.t +++ b/t/db_dependent/Budgets.t @@ -13,12 +13,16 @@ use Koha::Acquisition::Booksellers; use Koha::Acquisition::Orders; use Koha::Acquisition::Funds; use Koha::Patrons; +use Koha::Number::Price; use t::lib::TestBuilder; 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; @@ -472,6 +476,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"); @@ -924,6 +929,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