Bugzilla – Attachment 86645 Details for
Bug 6473
Test bug for Git-bz ✔ ❤ ★
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 18736: Calculate tax depending on rounding
Bug-18736-Calculate-tax-depending-on-rounding.patch (text/plain), 14.62 KB, created by
Marcel de Rooy
on 2019-03-15 10:03:53 UTC
(
hide
)
Description:
Bug 18736: Calculate tax depending on rounding
Filename:
MIME Type:
Creator:
Marcel de Rooy
Created:
2019-03-15 10:03:53 UTC
Size:
14.62 KB
patch
obsolete
>From 240a39b078ba77a5552fd142e3fe8d0ca0d83fd3 Mon Sep 17 00:00:00 2001 >From: Nick Clemens <nick@bywatersolutions.com> >Date: Tue, 15 Jan 2019 15:06:06 +0000 >Subject: [PATCH] Bug 18736: Calculate tax depending on rounding >Content-Type: text/plain; charset=utf-8 > >Marcel's comments pointed out that while I tried to avoid storing >rounded values it is required for tax generation. > >This patch makes that change and adds test coverage and POD for >populate_order_with_prices > >To test: >Follow plan on other patches, ensure that orders and totals match on the >basket, invoice, and budget pages > >prove -v t/db_dependent/Acquisition/populate_order_with_prices.t > >Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl> >--- > C4/Acquisition.pm | 56 +++++-- > acqui/ordered.pl | 2 +- > .../Acquisition/populate_order_with_prices.t | 165 +++++++++++++++++++++ > 3 files changed, 209 insertions(+), 14 deletions(-) > create mode 100644 t/db_dependent/Acquisition/populate_order_with_prices.t > >diff --git a/C4/Acquisition.pm b/C4/Acquisition.pm >index dfea465a5f..4bf8c17ae7 100644 >--- a/C4/Acquisition.pm >+++ b/C4/Acquisition.pm >@@ -3000,8 +3000,38 @@ sub GetBiblioCountByBasketno { > return $sth->fetchrow; > } > >-# Note this subroutine should be moved to Koha::Acquisition::Order >-# Will do when a DBIC decision will be taken. >+=head3 populate_order_with_prices >+ >+$order = populate_order_with_prices({ >+ order => $order #a hashref with the order values >+ booksellerid => $booksellerid #FIXME - should obtain from order basket >+ receiving => 1 # boolean representing order stage, should pass only this or ordering >+ ordering => 1 # boolean representing order stage >+}); >+ >+ >+Sets calculated values for an order - all values are stored with pull precision regardless of rounding preference except fot >+tax value which is calculated on rounded values if requested >+ >+For ordering the values set are: >+ rrp_tax_included >+ rrp_tax_excluded >+ ecost_tax_included >+ ecost_tax_excluded >+ tax_value_on_ordering >+For receiving the value set are: >+ unitprice_tax_included >+ unitprice_tax_excluded >+ tax_value_on_receiving >+ >+Note: When receiving if the rounded value of the unitprice matches the rounded value of the ecost then then ecost (full precision) is used. >+ >+Returns a hashref of the order >+ >+FIXME: Move this to Koha::Acquisition::Order.pm >+ >+=cut >+ > sub populate_order_with_prices { > my ($params) = @_; > >@@ -3025,11 +3055,15 @@ sub populate_order_with_prices { > # rrp tax excluded = rrp tax included / ( 1 + tax rate ) > $order->{rrp_tax_excluded} = $order->{rrp_tax_included} / ( 1 + $order->{tax_rate_on_ordering} ); > >+ # ecost tax included = rrp tax included ( 1 - discount ) >+ $order->{ecost_tax_included} = $order->{rrp_tax_included} * ( 1 - $discount ); >+ > # ecost tax excluded = rrp tax excluded * ( 1 - discount ) > $order->{ecost_tax_excluded} = $order->{rrp_tax_excluded} * ( 1 - $discount ); > >- # ecost tax included = rrp tax included ( 1 - discount ) >- $order->{ecost_tax_included} = $order->{rrp_tax_included} * ( 1 - $discount ); >+ # tax value = quantity * ecost tax excluded * tax rate >+ $order->{tax_value_on_ordering} = ( get_rounded_price($order->{ecost_tax_included}) - get_rounded_price($order->{ecost_tax_excluded}) ) * $order->{quantity}; >+ > } > else { > # The user entered the rrp tax excluded >@@ -3041,16 +3075,12 @@ sub populate_order_with_prices { > # ecost tax excluded = rrp tax excluded * ( 1 - discount ) > $order->{ecost_tax_excluded} = $order->{rrp_tax_excluded} * ( 1 - $discount ); > >- # ecost tax included = rrp tax excluded * ( 1 + tax rate ) * ( 1 - discount ) >- $order->{ecost_tax_included} = >- $order->{rrp_tax_excluded} * >- ( 1 + $order->{tax_rate_on_ordering} ) * >- ( 1 - $discount ); >- } >+ # ecost tax included = rrp tax excluded * ( 1 + tax rate ) * ( 1 - discount ) = ecost tax excluded * ( 1 + tax rate ) >+ $order->{ecost_tax_included} = $order->{ecost_tax_excluded} * ( 1 + $order->{tax_rate_on_ordering} ); > >- # tax value = quantity * ecost tax excluded * tax rate >- $order->{tax_value_on_ordering} = >- $order->{quantity} * get_rounded_price($order->{ecost_tax_excluded}) * $order->{tax_rate_on_ordering}; >+ # tax value = quantity * ecost tax included * tax rate >+ $order->{tax_value_on_ordering} = $order->{quantity} * get_rounded_price($order->{ecost_tax_excluded}) * $order->{tax_rate_on_ordering}; >+ } > } > > if ($receiving) { >diff --git a/acqui/ordered.pl b/acqui/ordered.pl >index b574d2eb39..3eb0519c65 100755 >--- a/acqui/ordered.pl >+++ b/acqui/ordered.pl >@@ -99,7 +99,7 @@ while ( my $data = $sth->fetchrow_hashref ) { > $left = $data->{'quantity'}; > } > if ( $left && $left > 0 ) { >- my $subtotal = $left * get_rounded_price($data->{'ecost_tax_included'}); >+ my $subtotal = get_rounded_price( $left * $data->{'ecost_tax_included'} ); > $data->{subtotal} = sprintf( "%.2f", $subtotal ); > $data->{'left'} = $left; > push @ordered, $data; >diff --git a/t/db_dependent/Acquisition/populate_order_with_prices.t b/t/db_dependent/Acquisition/populate_order_with_prices.t >new file mode 100644 >index 0000000000..16772e9eb8 >--- /dev/null >+++ b/t/db_dependent/Acquisition/populate_order_with_prices.t >@@ -0,0 +1,165 @@ >+#!/usr/bin/env perl >+ >+use Modern::Perl; >+ >+use Test::More tests => 34; >+use C4::Acquisition; >+use C4::Context; >+use Koha::Database; >+use t::lib::TestBuilder; >+use t::lib::Mocks; >+ >+# Start transaction >+my $schema = Koha::Database->new()->schema(); >+$schema->storage->txn_begin(); >+ >+my $dbh = C4::Context->dbh; >+$dbh->{RaiseError} = 1; >+ >+my $builder = t::lib::TestBuilder->new; >+ >+my $bookseller_inc_tax = Koha::Acquisition::Bookseller->new( >+ { >+ name => "Tax included", >+ address1 => "bookseller's address", >+ phone => "0123456", >+ active => 1, >+ listincgst => 1, >+ invoiceincgst => 1, >+ } >+)->store; >+ >+my $bookseller_exc_tax = Koha::Acquisition::Bookseller->new( >+ { >+ name => "Tax excluded", >+ address1 => "bookseller's address", >+ phone => "0123456", >+ active => 1, >+ listincgst => 0, >+ invoiceincgst => 0, >+ } >+)->store; >+ >+my $order_exc_tax = { >+ tax_rate => .1965, >+ discount => .42, >+ rrp => 16.99, >+ unitprice => 9.85, >+ quantity => 8, >+}; >+ >+#Vendor prices exclude tax, no rounding, ordering >+t::lib::Mocks::mock_preference('OrderPriceRounding', ''); >+my $order_with_prices = C4::Acquisition::populate_order_with_prices({ >+ ordering => 1, >+ booksellerid => $bookseller_exc_tax->id, >+ order => $order_exc_tax, >+}); >+ >+is( $order_with_prices->{rrp_tax_excluded}+0 ,16.99 ,"Ordering tax excluded, no round: rrp tax excluded is rrp"); >+is( $order_with_prices->{rrp_tax_included}+0 ,20.328535 ,"Ordering tax excluded, no round: rrp tax included is rr tax excluded * (1 + tax rate on ordering)"); >+is( $order_with_prices->{ecost_tax_excluded}+0 ,9.8542 ,"Ordering tax excluded, no round: ecost tax excluded is rrp * ( 1 - discount )"); >+is( $order_with_prices->{ecost_tax_included}+0 ,11.7905503 ,"Ordering tax excluded, no round: ecost tax included is ecost tax excluded * (1 + tax rate on ordering)"); >+is( $order_with_prices->{tax_value_on_ordering}+0 ,15.4908024 ,"Ordering tax excluded, no round: tax value on ordering is quantity * ecost_tax_excluded * tax rate on ordering"); >+ >+#Vendor prices exclude tax, no rounding, receiving >+$order_with_prices = C4::Acquisition::populate_order_with_prices({ >+ receiving => 1, >+ booksellerid => $bookseller_exc_tax->id, >+ order => $order_exc_tax, >+}); >+ >+is( $order_with_prices->{unitprice}+0 ,9.8542 ,"Receiving tax excluded, no round, rounded ecost tax excluded = rounded unitprice : unitprice is ecost tax excluded"); >+is( $order_with_prices->{unitprice_tax_excluded}+0 ,9.8542 ,"Receiving tax excluded, no round, rounded ecost tax excluded = rounded unitprice : unitprice tax excluded is ecost tax excluded"); >+is( $order_with_prices->{unitprice_tax_included}+0 ,11.7905503 ,"Receiving tax excluded, no round: unitprice tax included is unitprice tax excluded * (1 + tax rate on ordering)"); >+is( $order_with_prices->{tax_value_on_ordering}+0 ,15.4908024 ,"Receiving tax excluded, no round: tax value on receiving is quantity * unitprice_tax_excluded * tax rate on receiving"); >+ >+#Vendor prices exclude tax, rounding to nearest cent, ordering >+t::lib::Mocks::mock_preference('OrderPriceRounding', 'nearest_cent'); >+$order_with_prices = C4::Acquisition::populate_order_with_prices({ >+ ordering => 1, >+ booksellerid => $bookseller_exc_tax->id, >+ order => $order_exc_tax, >+}); >+ >+is( $order_with_prices->{rrp_tax_excluded}+0 ,16.99 ,"Ordering tax excluded, round: rrp tax excluded is rrp"); >+is( $order_with_prices->{rrp_tax_included}+0 ,20.328535 ,"Ordering tax excluded, round: rrp tax included is rr tax excluded * (1 + tax rate on ordering)"); >+is( $order_with_prices->{ecost_tax_excluded}+0 ,9.8542 ,"Ordering tax excluded, round: ecost tax excluded is rrp * ( 1 - discount )"); >+is( $order_with_prices->{ecost_tax_included}+0 ,11.7905503 ,"Ordering tax excluded, round: ecost tax included is ecost tax excluded * (1 + tax rate on ordering)"); >+is( $order_with_prices->{tax_value_on_ordering}+0 ,15.4842 ,"Ordering tax excluded, round: tax value on ordering is quantity * ecost_tax_excluded * tax rate on ordering"); >+ >+#Vendor prices exclude tax, no rounding, receiving >+$order_with_prices = C4::Acquisition::populate_order_with_prices({ >+ receiving => 1, >+ booksellerid => $bookseller_exc_tax->id, >+ order => $order_exc_tax, >+}); >+ >+is( $order_with_prices->{unitprice_tax_excluded}+0 ,9.8542 ,"Receiving tax excluded, round, rounded ecost tax excluded = rounded unitprice : unitprice tax excluded is ecost tax excluded"); >+is( $order_with_prices->{unitprice_tax_included}+0 ,11.7905503 ,"Receiving tax excluded, round: unitprice tax included is unitprice tax excluded * (1 + tax rate on ordering)"); >+is( $order_with_prices->{tax_value_on_receiving}+0 ,15.4842 ,"Receiving tax excluded, round: tax value on receiving is quantity * unitprice_tax_excluded * tax rate on receiving"); >+ >+ >+ >+my $order_inc_tax = { >+ tax_rate => .1965, >+ discount => .42, >+ rrp => 20.33, >+ unitprice => 11.79, >+ quantity => 8, >+}; >+ >+#Vendor prices include tax, no rounding, ordering >+t::lib::Mocks::mock_preference('OrderPriceRounding', ''); >+$order_with_prices = C4::Acquisition::populate_order_with_prices({ >+ ordering => 1, >+ booksellerid => $bookseller_inc_tax->id, >+ order => $order_inc_tax, >+}); >+ >+is( $order_with_prices->{rrp_tax_included}+0 ,20.33 ,"Ordering tax included, no round: rrp tax included is rrp"); >+is( $order_with_prices->{rrp_tax_excluded}+0 ,16.9912244045132 ,"Ordering tax included, no round: rrp tax excluded is rrp tax included / (1 + tax rate on ordering)"); >+is( $order_with_prices->{ecost_tax_included}+0 ,11.7914 ,"Ordering tax included, no round: ecost tax included is rrp tax included * (1 - discount)"); >+is( $order_with_prices->{ecost_tax_excluded}+0 ,9.85491015461764 ,"Ordering tax included, no round: ecost tax excluded is rrp tax excluded * ( 1 - discount )"); >+is( $order_with_prices->{tax_value_on_ordering}+0 ,15.4919187630589 ,"Ordering tax included, no round: tax value on ordering is ( ecost tax included - ecost tax excluded ) * quantity"); >+ >+ >+#Vendor prices include tax, no rounding, receiving >+$order_with_prices = C4::Acquisition::populate_order_with_prices({ >+ receiving => 1, >+ booksellerid => $bookseller_inc_tax->id, >+ order => $order_inc_tax, >+}); >+ >+is( $order_with_prices->{unitprice}+0 ,11.7914 ,"Receiving tax included, no round, rounded ecost tax excluded = rounded unitprice : unitprice is ecost tax excluded"); >+is( $order_with_prices->{unitprice_tax_included}+0 ,11.7914 ,"Receiving tax included, no round: unitprice tax included is unitprice"); >+is( $order_with_prices->{unitprice_tax_excluded}+0 ,9.85491015461764 ,"Receiving tax included, no round: unitprice tax excluded is unitprice tax included / (1 + tax rate on receiving)"); >+is( $order_with_prices->{tax_value_on_ordering}+0 ,15.4919187630589 ,"Receiving tax included, no round: tax value on receiving is quantity * unitprice_tax_excluded * tax rate on receiving"); >+ >+#Vendor prices include tax, rounding to nearest cent, ordering >+t::lib::Mocks::mock_preference('OrderPriceRounding', 'nearest_cent'); >+$order_with_prices = C4::Acquisition::populate_order_with_prices({ >+ ordering => 1, >+ booksellerid => $bookseller_inc_tax->id, >+ order => $order_inc_tax, >+}); >+ >+is( $order_with_prices->{rrp_tax_included}+0 ,20.33 ,"Ordering tax included, round: rrp tax included is rrp"); >+is( $order_with_prices->{rrp_tax_excluded}+0 ,16.9912244045132 ,"Ordering tax included, round: rrp tax excluded is rounded rrp tax included * (1 + tax rate on ordering)"); >+is( $order_with_prices->{ecost_tax_included}+0 ,11.7914 ,"Ordering tax included, round: ecost tax included is rounded rrp * ( 1 - discount )"); >+is( $order_with_prices->{ecost_tax_excluded}+0 ,9.85491015461764 ,"Ordering tax included, round: ecost tax excluded is rounded ecost tax excluded * (1 - discount)"); >+is( $order_with_prices->{tax_value_on_ordering}+0 ,15.52 ,"Ordering tax included, round: tax value on ordering is (ecost_tax_included - ecost_tax_excluded) * quantity"); >+ >+#Vendor prices include tax, no rounding, receiving >+$order_with_prices = C4::Acquisition::populate_order_with_prices({ >+ receiving => 1, >+ booksellerid => $bookseller_inc_tax->id, >+ order => $order_inc_tax, >+}); >+ >+is( $order_with_prices->{unitprice_tax_included}+0 ,11.7914 ,"Receiving tax included, round: rounded ecost tax included = rounded unitprice : unitprice tax excluded is ecost tax included"); >+is( $order_with_prices->{unitprice_tax_excluded}+0 ,9.85491015461764 ,"Receiving tax included, round: unitprice tax excluded is unitprice tax included / (1 + tax rate on ordering)"); >+is( $order_with_prices->{tax_value_on_receiving}+0 ,15.4842 ,"Receiving tax included, round: tax value on receiving is quantity * (rounded unitprice_tax_excluded) * tax rate on receiving"); >+ >+ >+$schema->storage->txn_rollback(); >-- >2.11.0
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 6473
:
4386
|
6837
|
6838
|
6839
|
6840
|
6841
|
6842
|
6843
|
7154
|
7155
|
7567
|
7994
|
7995
|
7996
|
7997
|
8018
|
9807
|
9808
|
9813
|
9831
|
9832
|
9836
|
9854
|
10842
|
10843
|
10844
|
10845
|
10846
|
10847
|
10848
|
10849
|
10850
|
10851
|
10852
|
10853
|
10854
|
10855
|
10856
|
10857
|
10858
|
11540
|
11543
|
11544
|
12502
|
12513
|
12514
|
12515
|
12516
|
12517
|
12518
|
12519
|
13473
|
13673
|
14955
|
14969
|
14970
|
14972
|
15201
|
18949
|
18950
|
18951
|
18952
|
18953
|
18954
|
18955
|
18956
|
18957
|
18958
|
18959
|
18960
|
18961
|
18962
|
18963
|
18971
|
18972
|
19518
|
19519
|
19591
|
19592
|
19871
|
19879
|
19880
|
19881
|
19882
|
20011
|
20012
|
20013
|
20014
|
22477
|
22481
|
22482
|
22496
|
22502
|
22503
|
31958
|
32444
|
32445
|
32446
|
32447
|
32448
|
32449
|
32450
|
32451
|
32452
|
34200
|
34201
|
34625
|
34999
|
35130
|
35269
|
35273
|
35274
|
35275
|
35276
|
35277
|
35279
|
35280
|
35303
|
40954
|
40957
|
45345
|
45349
|
45731
|
45732
|
45733
|
45734
|
47283
|
47284
|
47298
|
47299
|
47300
|
47334
|
47336
|
49083
|
56974
|
61059
|
61069
|
62038
|
65313
|
77301
|
78016
|
79959
|
80178
|
80179
|
80180
|
80181
|
80182
|
84400
|
86644
|
86645
|
87152
|
88128
|
95586
|
95716
|
97394
|
99026
|
99027
|
114217
|
114218
|
114219
|
114220
|
114221
|
114222
|
114223
|
114224
|
114225
|
114226
|
119255
|
121181
|
131891
|
131893
|
131894
|
134862
|
144109
|
144144
|
144671
|
144672
|
144673
|
147183
|
149030
|
149031
|
149032
|
149033
|
160566
|
160567
|
160568