View | Details | Raw Unified | Return to bug 18736
Collapse All | Expand All

(-)a/C4/Acquisition.pm (-14 / +44 lines)
Lines 2990-2997 sub GetBiblioCountByBasketno { Link Here
2990
    return $sth->fetchrow;
2990
    return $sth->fetchrow;
2991
}
2991
}
2992
2992
2993
# Note this subroutine should be moved to Koha::Acquisition::Order
2993
=head3 populate_order_with_prices
2994
# Will do when a DBIC decision will be taken.
2994
2995
$order = populate_order_with_prices({
2996
    order        => $order #a hashref with the order values
2997
    booksellerid => $booksellerid #FIXME - should obtain from order basket
2998
    receiving    => 1 # boolean representing order stage, should pass only this or ordering
2999
    ordering     => 1 # boolean representing order stage
3000
});
3001
3002
3003
Sets calculated values for an order - all values are stored with pull precision regardless of rounding preference except fot
3004
tax value which is calculated on rounded values if requested
3005
3006
For ordering the values set are:
3007
    rrp_tax_included
3008
    rrp_tax_excluded
3009
    ecost_tax_included
3010
    ecost_tax_excluded
3011
    tax_value_on_ordering
3012
For receiving the value set are:
3013
    unitprice_tax_included
3014
    unitprice_tax_excluded
3015
    tax_value_on_receiving
3016
3017
Note: When receiving if the rounded value of the unitprice matches the rounded value of the ecost then then ecost (full precision) is used.
3018
3019
Returns a hashref of the order
3020
3021
FIXME: Move this to Koha::Acquisition::Order.pm
3022
3023
=cut
3024
2995
sub populate_order_with_prices {
3025
sub populate_order_with_prices {
2996
    my ($params) = @_;
3026
    my ($params) = @_;
2997
3027
Lines 3015-3025 sub populate_order_with_prices { Link Here
3015
            # rrp tax excluded = rrp tax included / ( 1 + tax rate )
3045
            # rrp tax excluded = rrp tax included / ( 1 + tax rate )
3016
            $order->{rrp_tax_excluded} = $order->{rrp_tax_included} / ( 1 + $order->{tax_rate_on_ordering} );
3046
            $order->{rrp_tax_excluded} = $order->{rrp_tax_included} / ( 1 + $order->{tax_rate_on_ordering} );
3017
3047
3018
            # ecost tax excluded = rrp tax excluded * ( 1 - discount )
3019
            $order->{ecost_tax_excluded} = $order->{rrp_tax_excluded} * ( 1 - $discount );
3020
3021
            # ecost tax included = rrp tax included  ( 1 - discount )
3048
            # ecost tax included = rrp tax included  ( 1 - discount )
3022
            $order->{ecost_tax_included} = $order->{rrp_tax_included} * ( 1 - $discount );
3049
            $order->{ecost_tax_included} = $order->{rrp_tax_included} * ( 1 - $discount );
3050
3051
            # ecost tax excluded = rrp tax excluded * ( 1 - discount ) 
3052
            $order->{ecost_tax_excluded} = $order->{rrp_tax_excluded} * ( 1 - $discount );
3053
3054
            # tax value = quantity * ecost tax excluded * tax rate
3055
            $order->{tax_value_on_ordering} = ( get_rounded_price($order->{ecost_tax_included}) - get_rounded_price($order->{ecost_tax_excluded}) ) * $order->{quantity};
3056
3023
        }
3057
        }
3024
        else {
3058
        else {
3025
            # The user entered the rrp tax excluded
3059
            # The user entered the rrp tax excluded
Lines 3031-3046 sub populate_order_with_prices { Link Here
3031
            # ecost tax excluded = rrp tax excluded * ( 1 - discount )
3065
            # ecost tax excluded = rrp tax excluded * ( 1 - discount )
3032
            $order->{ecost_tax_excluded} = $order->{rrp_tax_excluded} * ( 1 - $discount );
3066
            $order->{ecost_tax_excluded} = $order->{rrp_tax_excluded} * ( 1 - $discount );
3033
3067
3034
            # ecost tax included = rrp tax excluded * ( 1 + tax rate ) * ( 1 - discount )
3068
            # ecost tax included = rrp tax excluded * ( 1 + tax rate ) * ( 1 - discount ) = ecost tax excluded * ( 1 + tax rate )
3035
            $order->{ecost_tax_included} =
3069
            $order->{ecost_tax_included} = $order->{ecost_tax_excluded} * ( 1 + $order->{tax_rate_on_ordering} );
3036
                $order->{rrp_tax_excluded} *
3037
                ( 1 + $order->{tax_rate_on_ordering} ) *
3038
                ( 1 - $discount );
3039
        }
3040
3070
3041
        # tax value = quantity * ecost tax excluded * tax rate
3071
            # tax value = quantity * ecost tax included * tax rate
3042
        $order->{tax_value_on_ordering} =
3072
            $order->{tax_value_on_ordering} = $order->{quantity} * get_rounded_price($order->{ecost_tax_excluded}) * $order->{tax_rate_on_ordering};
3043
            $order->{quantity} * get_rounded_price($order->{ecost_tax_excluded}) * $order->{tax_rate_on_ordering};
3073
        }
3044
    }
3074
    }
3045
3075
3046
    if ($receiving) {
3076
    if ($receiving) {
(-)a/acqui/ordered.pl (-1 / +1 lines)
Lines 93-99 while ( my $data = $sth->fetchrow_hashref ) { Link Here
93
        $left = $data->{'quantity'};
93
        $left = $data->{'quantity'};
94
    }
94
    }
95
    if ( $left && $left > 0 ) {
95
    if ( $left && $left > 0 ) {
96
        my $subtotal = $left * get_rounded_price($data->{'ecost_tax_included'});
96
        my $subtotal = get_rounded_price( $left * $data->{'ecost_tax_included'} );
97
        $data->{subtotal} = sprintf( "%.2f", $subtotal );
97
        $data->{subtotal} = sprintf( "%.2f", $subtotal );
98
        $data->{'left'} = $left;
98
        $data->{'left'} = $left;
99
        push @ordered, $data;
99
        push @ordered, $data;
(-)a/t/db_dependent/Acquisition/populate_order_with_prices.t (-1 / +165 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/env perl
2
3
use Modern::Perl;
4
5
use Test::More tests => 34;
6
use C4::Acquisition;
7
use C4::Context;
8
use Koha::Database;
9
use t::lib::TestBuilder;
10
use t::lib::Mocks;
11
12
# Start transaction
13
my $schema = Koha::Database->new()->schema();
14
$schema->storage->txn_begin();
15
16
my $dbh = C4::Context->dbh;
17
$dbh->{RaiseError} = 1;
18
19
my $builder = t::lib::TestBuilder->new;
20
21
my $bookseller_inc_tax = Koha::Acquisition::Bookseller->new(
22
    {
23
        name          => "Tax included",
24
        address1      => "bookseller's address",
25
        phone         => "0123456",
26
        active        => 1,
27
        listincgst    => 1,
28
        invoiceincgst => 1,
29
    }
30
)->store;
31
32
my $bookseller_exc_tax = Koha::Acquisition::Bookseller->new(
33
    {
34
        name          => "Tax excluded",
35
        address1      => "bookseller's address",
36
        phone         => "0123456",
37
        active        => 1,
38
        listincgst    => 0,
39
        invoiceincgst => 0,
40
    }
41
)->store;
42
43
my $order_exc_tax = {
44
    tax_rate  => .1965,
45
    discount  => .42,
46
    rrp       => 16.99,
47
    unitprice => 9.85,
48
    quantity  => 8,
49
};
50
51
#Vendor prices exclude tax, no rounding, ordering
52
t::lib::Mocks::mock_preference('OrderPriceRounding', '');
53
my $order_with_prices = C4::Acquisition::populate_order_with_prices({
54
    ordering     => 1,
55
    booksellerid => $bookseller_exc_tax->id,
56
    order        => $order_exc_tax,
57
});
58
59
is( $order_with_prices->{rrp_tax_excluded}+0      ,16.99      ,"Ordering tax excluded, no round: rrp tax excluded is rrp");
60
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)");
61
is( $order_with_prices->{ecost_tax_excluded}+0    ,9.8542     ,"Ordering tax excluded, no round: ecost tax excluded is rrp * ( 1 - discount )");
62
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)");
63
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");
64
65
#Vendor prices exclude tax, no rounding, receiving
66
$order_with_prices = C4::Acquisition::populate_order_with_prices({
67
    receiving     => 1,
68
    booksellerid => $bookseller_exc_tax->id,
69
    order        => $order_exc_tax,
70
});
71
72
is( $order_with_prices->{unitprice}+0              ,9.8542     ,"Receiving tax excluded, no round, rounded ecost tax excluded = rounded unitprice : unitprice is ecost tax excluded");
73
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");
74
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)");
75
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");
76
77
#Vendor prices exclude tax, rounding to nearest cent, ordering
78
t::lib::Mocks::mock_preference('OrderPriceRounding', 'nearest_cent');
79
$order_with_prices = C4::Acquisition::populate_order_with_prices({
80
    ordering     => 1,
81
    booksellerid => $bookseller_exc_tax->id,
82
    order        => $order_exc_tax,
83
});
84
85
is( $order_with_prices->{rrp_tax_excluded}+0      ,16.99      ,"Ordering tax excluded, round: rrp tax excluded is rrp");
86
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)");
87
is( $order_with_prices->{ecost_tax_excluded}+0    ,9.8542     ,"Ordering tax excluded, round: ecost tax excluded is rrp * ( 1 - discount )");
88
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)");
89
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");
90
91
#Vendor prices exclude tax, no rounding, receiving
92
$order_with_prices = C4::Acquisition::populate_order_with_prices({
93
    receiving     => 1,
94
    booksellerid => $bookseller_exc_tax->id,
95
    order        => $order_exc_tax,
96
});
97
98
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");
99
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)");
100
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");
101
102
103
104
my $order_inc_tax = {
105
    tax_rate  => .1965,
106
    discount  => .42,
107
    rrp       => 20.33,
108
    unitprice => 11.79,
109
    quantity  => 8,
110
};
111
112
#Vendor prices include tax, no rounding, ordering
113
t::lib::Mocks::mock_preference('OrderPriceRounding', '');
114
$order_with_prices = C4::Acquisition::populate_order_with_prices({
115
    ordering     => 1,
116
    booksellerid => $bookseller_inc_tax->id,
117
    order        => $order_inc_tax,
118
});
119
120
is( $order_with_prices->{rrp_tax_included}+0      ,20.33            ,"Ordering tax included, no round: rrp tax included is rrp");
121
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)");
122
is( $order_with_prices->{ecost_tax_included}+0    ,11.7914          ,"Ordering tax included, no round: ecost tax included is rrp tax included * (1 - discount)");
123
is( $order_with_prices->{ecost_tax_excluded}+0    ,9.85491015461764 ,"Ordering tax included, no round: ecost tax excluded is rrp tax excluded * ( 1 - discount )");
124
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");
125
126
127
#Vendor prices include tax, no rounding, receiving
128
$order_with_prices = C4::Acquisition::populate_order_with_prices({
129
    receiving     => 1,
130
    booksellerid => $bookseller_inc_tax->id,
131
    order        => $order_inc_tax,
132
});
133
134
is( $order_with_prices->{unitprice}+0              ,11.7914          ,"Receiving tax included, no round, rounded ecost tax excluded = rounded unitprice : unitprice is ecost tax excluded");
135
is( $order_with_prices->{unitprice_tax_included}+0 ,11.7914          ,"Receiving tax included, no round: unitprice tax included is unitprice");
136
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)");
137
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");
138
139
#Vendor prices include tax, rounding to nearest cent, ordering
140
t::lib::Mocks::mock_preference('OrderPriceRounding', 'nearest_cent');
141
$order_with_prices = C4::Acquisition::populate_order_with_prices({
142
    ordering     => 1,
143
    booksellerid => $bookseller_inc_tax->id,
144
    order        => $order_inc_tax,
145
});
146
147
is( $order_with_prices->{rrp_tax_included}+0      ,20.33            ,"Ordering tax included, round: rrp tax included is rrp");
148
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)");
149
is( $order_with_prices->{ecost_tax_included}+0    ,11.7914          ,"Ordering tax included, round: ecost tax included is rounded rrp * ( 1 - discount )");
150
is( $order_with_prices->{ecost_tax_excluded}+0    ,9.85491015461764 ,"Ordering tax included, round: ecost tax excluded is rounded ecost tax excluded * (1 - discount)");
151
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");
152
153
#Vendor prices include tax, no rounding, receiving
154
$order_with_prices = C4::Acquisition::populate_order_with_prices({
155
    receiving     => 1,
156
    booksellerid => $bookseller_inc_tax->id,
157
    order        => $order_inc_tax,
158
});
159
160
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");
161
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)");
162
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");
163
164
165
$schema->storage->txn_rollback();

Return to bug 18736