Alex Buckley
7b66b90fe7
If 'Actual cost' has not been set then it has the value of 0.00 which Perl evaluates to true so this patchset resets it to 0, so the fallback to ecost_tax_included/ecost_tax_excluded happens. Test plan: 1. Add item to acquisition basket (make sure the vendor has: tax rate: 15%, 'List prices: Include tax', 'Invoice prices: Include tax') 2. Set 'Vendor price' = 10 and do not set 'Actual cost' 3. Save order 4. Observe basket.pl shows 'Total tax exc.' has a value of 0.00 and GST column has value of -8.70 5. Jump into the database: select tax_value_on_ordering from aqorders where ordernumber=<ordernumber>; [You can get the ordernumber from clicking on the 'Modify' line the item is listed in] 6. Observe a negative value: -8.70 7. Apply patch and restart plack 8. Add a second item to the basket 9. Set 'Vendor price' = 10 and don't set 'Actual cost' 10. Save order 11. Observe basket.pl shows 'Total tax exc' has value of 8.70 and GST has value of 1.30 12. Repeat step 5 and observe tax_value_on_ordering = 1.30 13. Run t/Prices.t unit test: sudo koha-shell <instancename> prove t/Prices.t Sponsored-by: Horowhenua District Council, NZ Signed-off-by: Andrew Fuerste-Henry <andrew@bywatersolutions.com> Signed-off-by: Nick Clemens <nick@bywatersolutions.com> Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
561 lines
17 KiB
Perl
561 lines
17 KiB
Perl
use Modern::Perl;
|
|
use Test::More;
|
|
use Test::MockModule;
|
|
|
|
use t::lib::Mocks;
|
|
|
|
use Module::Load::Conditional qw/check_install/;
|
|
|
|
BEGIN {
|
|
if ( check_install( module => 'Test::DBIx::Class' ) ) {
|
|
plan tests => 16;
|
|
} else {
|
|
plan skip_all => "Need Test::DBIx::Class"
|
|
}
|
|
}
|
|
|
|
use_ok('C4::Acquisition');
|
|
use_ok('C4::Context');
|
|
use_ok('Koha::Number::Price');
|
|
|
|
t::lib::Mocks::mock_preference( 'gist', '0.02|0.05|0.196' );
|
|
|
|
use Test::DBIx::Class;
|
|
|
|
my $db = Test::MockModule->new('Koha::Database');
|
|
$db->mock( _new_schema => sub { return Schema(); } );
|
|
Koha::Database::flush_schema_cache();
|
|
|
|
fixtures_ok [
|
|
Currency => [
|
|
[ qw/ currency symbol rate active / ],
|
|
[ 'my_cur', '€', 1, 1, ],
|
|
],
|
|
Aqbookseller => [
|
|
[ qw/ id name listincgst invoiceincgst / ],
|
|
[ 1, '0 0', 0, 0 ],
|
|
[ 2, '0 1', 0, 1 ],
|
|
[ 3, '1 0', 1, 0 ],
|
|
[ 4, '1 1', 1, 1 ],
|
|
],
|
|
], 'add currency fixtures';
|
|
|
|
my $bookseller_module = Test::MockModule->new('Koha::Acquisition::Bookseller');
|
|
|
|
my ( $basketno_0_0, $basketno_1_1 );
|
|
my ( $invoiceid_0_0, $invoiceid_1_1 );
|
|
my $today;
|
|
|
|
for my $currency_format ( qw( US FR ) ) {
|
|
t::lib::Mocks::mock_preference( 'CurrencyFormat', $currency_format );
|
|
subtest 'Configuration 1: 0 0 (Vendor List prices do not include tax / Invoice prices do not include tax)' => sub {
|
|
plan tests => 8;
|
|
|
|
my $biblionumber_0_0 = 42;
|
|
|
|
my $order_0_0 = {
|
|
biblionumber => $biblionumber_0_0,
|
|
quantity => 2,
|
|
listprice => 82,
|
|
unitprice => 73.80,
|
|
quantityreceived => 2,
|
|
basketno => $basketno_0_0,
|
|
invoiceid => $invoiceid_0_0,
|
|
rrp => 82.00,
|
|
ecost => 73.80,
|
|
tax_rate => 0.0500,
|
|
discount => 10,
|
|
datereceived => $today
|
|
};
|
|
$order_0_0 = C4::Acquisition::populate_order_with_prices(
|
|
{
|
|
order => $order_0_0,
|
|
booksellerid => 1,
|
|
ordering => 1,
|
|
}
|
|
);
|
|
|
|
compare(
|
|
{
|
|
got => $order_0_0->{rrp_tax_included},
|
|
expected => 86.10,
|
|
conf => '0 0',
|
|
field => 'rrp_tax_included'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_0_0->{rrp_tax_excluded},
|
|
expected => 82.00,
|
|
conf => '0 0',
|
|
field => 'rrp_tax_excluded'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_0_0->{ecost_tax_included},
|
|
expected => 77.49,
|
|
conf => '0 0',
|
|
field => 'ecost_tax_included'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_0_0->{ecost_tax_excluded},
|
|
expected => 73.80,
|
|
conf => '0 0',
|
|
field => 'ecost_tax_excluded'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_0_0->{tax_value_on_ordering},
|
|
expected => 7.38,
|
|
conf => '0 0',
|
|
field => 'tax_value'
|
|
}
|
|
);
|
|
|
|
$order_0_0 = C4::Acquisition::populate_order_with_prices(
|
|
{
|
|
order => $order_0_0,
|
|
booksellerid => 1,
|
|
receiving => 1,
|
|
}
|
|
);
|
|
|
|
compare(
|
|
{
|
|
got => $order_0_0->{unitprice_tax_included},
|
|
expected => 77.49,
|
|
conf => '0 0',
|
|
field => 'unitprice_tax_included'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_0_0->{unitprice_tax_excluded},
|
|
expected => 73.80,
|
|
conf => '0 0',
|
|
field => 'unitprice_tax_excluded'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_0_0->{tax_value_on_receiving},
|
|
expected => 7.38,
|
|
conf => '0 0',
|
|
field => 'tax_value'
|
|
}
|
|
);
|
|
};
|
|
|
|
subtest 'Configuration 1: 1 1 (Vendor List prices do include tax / Invoice prices include tax)' => sub {
|
|
plan tests => 11;
|
|
|
|
my $biblionumber_1_1 = 43;
|
|
my $order_1_1 = {
|
|
biblionumber => $biblionumber_1_1,
|
|
quantity => 2,
|
|
listprice => 82,
|
|
unitprice => 73.80,
|
|
quantityreceived => 2,
|
|
basketno => $basketno_1_1,
|
|
invoiceid => $invoiceid_1_1,
|
|
rrp => 82.00,
|
|
ecost => 73.80,
|
|
tax_rate => 0.0500,
|
|
discount => 10,
|
|
datereceived => $today
|
|
};
|
|
|
|
$order_1_1 = C4::Acquisition::populate_order_with_prices(
|
|
{
|
|
order => $order_1_1,
|
|
booksellerid => 4,
|
|
ordering => 1,
|
|
}
|
|
);
|
|
|
|
compare(
|
|
{
|
|
got => $order_1_1->{rrp_tax_included},
|
|
expected => 82.00,
|
|
conf => '1 1',
|
|
field => 'rrp_tax_included'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_1_1->{rrp_tax_excluded},
|
|
expected => 78.10,
|
|
conf => '1 1',
|
|
field => 'rrp_tax_excluded'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_1_1->{ecost_tax_included},
|
|
expected => 73.80,
|
|
conf => '1 1',
|
|
field => 'ecost_tax_included'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_1_1->{ecost_tax_excluded},
|
|
expected => 70.29,
|
|
conf => '1 1',
|
|
field => 'ecost_tax_excluded'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_1_1->{tax_value_on_ordering},
|
|
expected => 7.03,
|
|
conf => '1 1',
|
|
field => 'tax_value'
|
|
}
|
|
);
|
|
|
|
$order_1_1 = C4::Acquisition::populate_order_with_prices(
|
|
{
|
|
order => $order_1_1,
|
|
booksellerid => 4,
|
|
receiving => 1,
|
|
}
|
|
);
|
|
|
|
compare(
|
|
{
|
|
got => $order_1_1->{unitprice_tax_included},
|
|
expected => 73.80,
|
|
conf => '1 1',
|
|
field => 'unitprice_tax_included'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_1_1->{unitprice_tax_excluded},
|
|
expected => 70.29,
|
|
conf => '1 1',
|
|
field => 'unitprice_tax_excluded'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_1_1->{tax_value_on_receiving},
|
|
expected => 7.03,
|
|
conf => '1 1',
|
|
field => 'tax_value'
|
|
}
|
|
);
|
|
|
|
# When unitprice is 0.00 C4::Acquisition->populate_order_with_prices() falls back to using ecost_tax_included and ecost_tax_excluded
|
|
$order_1_1 = {
|
|
biblionumber => $biblionumber_1_1,
|
|
quantity => 1,
|
|
listprice => 10,
|
|
unitprice => '0.00',
|
|
quantityreceived => 1,
|
|
basketno => $basketno_1_1,
|
|
invoiceid => $invoiceid_1_1,
|
|
rrp => 10.00,
|
|
ecost => 10.00,
|
|
tax_rate => 0.1500,
|
|
discount => 0,
|
|
datereceived => $today
|
|
};
|
|
|
|
$order_1_1 = C4::Acquisition::populate_order_with_prices(
|
|
{
|
|
order => $order_1_1,
|
|
booksellerid => 4,
|
|
ordering => 1,
|
|
}
|
|
);
|
|
|
|
compare(
|
|
{
|
|
got => $order_1_1->{ecost_tax_included},
|
|
expected => 10.00,
|
|
conf => '1 1',
|
|
field => 'ecost_tax_included'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_1_1->{ecost_tax_excluded},
|
|
expected => 8.70,
|
|
conf => '1 1',
|
|
field => 'ecost_tax_excluded'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_1_1->{tax_value_on_ordering},
|
|
expected => 1.30,
|
|
conf => '1 1',
|
|
field => 'tax_value'
|
|
}
|
|
);
|
|
};
|
|
|
|
subtest 'Configuration 1: 1 0 (Vendor List prices include tax / Invoice prices do not include tax)' => sub {
|
|
plan tests => 9;
|
|
|
|
my $biblionumber_1_0 = 44;
|
|
my $order_1_0 = {
|
|
biblionumber => $biblionumber_1_0,
|
|
quantity => 2,
|
|
listprice => 82,
|
|
unitprice => 0,
|
|
quantityreceived => 2,
|
|
basketno => $basketno_1_1,
|
|
invoiceid => $invoiceid_1_1,
|
|
rrp => 82.00,
|
|
ecost => 73.80,
|
|
tax_rate => 0.0500,
|
|
discount => 10,
|
|
datereceived => $today
|
|
};
|
|
|
|
$order_1_0 = C4::Acquisition::populate_order_with_prices(
|
|
{
|
|
order => $order_1_0,
|
|
booksellerid => 3,
|
|
ordering => 1,
|
|
}
|
|
);
|
|
|
|
compare(
|
|
{
|
|
got => $order_1_0->{rrp_tax_included},
|
|
expected => 82,
|
|
conf => '1 0',
|
|
field => 'rrp_tax_included'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_1_0->{rrp_tax_excluded},
|
|
expected => 78.10,
|
|
conf => '1 0',
|
|
field => 'rrp_tax_excluded'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_1_0->{ecost_tax_included},
|
|
expected => 73.80,
|
|
conf => '1 0',
|
|
field => 'ecost_tax_included'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_1_0->{ecost_tax_excluded},
|
|
expected => 70.29,
|
|
conf => '1 0',
|
|
field => 'ecost_tax_excluded'
|
|
}
|
|
);
|
|
# If we order with unitprice = 0, tax is calculated from the ecost
|
|
# (note that in addorder.pl and addorderiso2709 the unitprice may/will be set to the ecost
|
|
compare(
|
|
{
|
|
got => $order_1_0->{tax_value_on_ordering},
|
|
expected => 7.03,
|
|
conf => '1 0',
|
|
field => 'tax_value'
|
|
}
|
|
);
|
|
$order_1_0->{unitprice} = 70.29;
|
|
$order_1_0 = C4::Acquisition::populate_order_with_prices(
|
|
{
|
|
order => $order_1_0,
|
|
booksellerid => 3,
|
|
ordering => 1,
|
|
}
|
|
);
|
|
# If a unitprice is provided at ordering, we calculate the tax from that
|
|
compare(
|
|
{
|
|
got => $order_1_0->{tax_value_on_ordering},
|
|
expected => 6.69,
|
|
conf => '1 0',
|
|
field => 'tax_value'
|
|
}
|
|
);
|
|
|
|
$order_1_0 = C4::Acquisition::populate_order_with_prices(
|
|
{
|
|
order => $order_1_0,
|
|
booksellerid => 3,
|
|
receiving => 1,
|
|
}
|
|
);
|
|
|
|
compare(
|
|
{
|
|
got => $order_1_0->{unitprice_tax_included},
|
|
expected => 73.80,
|
|
conf => '1 0',
|
|
field => 'unitprice_tax_included'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_1_0->{unitprice_tax_excluded},
|
|
expected => 70.29,
|
|
conf => '1 0',
|
|
field => 'unitprice_tax_excluded'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_1_0->{tax_value_on_receiving},
|
|
expected => 7.03,
|
|
conf => '1 0',
|
|
field => 'tax_value'
|
|
}
|
|
);
|
|
};
|
|
|
|
subtest 'Configuration 1: 0 1 (Vendor List prices do not include tax / Invoice prices include tax)' => sub {
|
|
plan tests => 9;
|
|
|
|
my $biblionumber_0_1 = 45;
|
|
my $order_0_1 = {
|
|
biblionumber => $biblionumber_0_1,
|
|
quantity => 2,
|
|
listprice => 82,
|
|
unitprice => 0,
|
|
quantityreceived => 2,
|
|
basketno => $basketno_1_1,
|
|
invoiceid => $invoiceid_1_1,
|
|
rrp => 82.00,
|
|
ecost => 73.80,
|
|
tax_rate => 0.0500,
|
|
discount => 10,
|
|
datereceived => $today
|
|
};
|
|
|
|
$order_0_1 = C4::Acquisition::populate_order_with_prices(
|
|
{
|
|
order => $order_0_1,
|
|
booksellerid => 2,
|
|
ordering => 1,
|
|
}
|
|
);
|
|
|
|
compare(
|
|
{
|
|
got => $order_0_1->{rrp_tax_included},
|
|
expected => 86.10,
|
|
conf => '0 1',
|
|
field => 'rrp_tax_included'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_0_1->{rrp_tax_excluded},
|
|
expected => 82.00,
|
|
conf => '0 1',
|
|
field => 'rrp_tax_excluded'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_0_1->{ecost_tax_included},
|
|
expected => 77.49,
|
|
conf => '0 1',
|
|
field => 'ecost_tax_included'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_0_1->{ecost_tax_excluded},
|
|
expected => 73.80,
|
|
conf => '0 1',
|
|
field => 'ecost_tax_excluded'
|
|
}
|
|
);
|
|
# If we order with unitprice = 0, tax is calculated from the ecost
|
|
# (note that in addorder.pl and addorderiso2709 the unitprice may/will be set to the ecost
|
|
compare(
|
|
{
|
|
got => $order_0_1->{tax_value_on_ordering},
|
|
expected => 7.38,
|
|
conf => '0 1',
|
|
field => 'tax_value'
|
|
}
|
|
);
|
|
$order_0_1->{unitprice} = 77.490000;
|
|
$order_0_1 = C4::Acquisition::populate_order_with_prices(
|
|
{
|
|
order => $order_0_1,
|
|
booksellerid => 2,
|
|
ordering => 1,
|
|
}
|
|
);
|
|
# If a unitprice is provided at ordering, we calculate the tax from that
|
|
compare(
|
|
{
|
|
got => $order_0_1->{tax_value_on_ordering},
|
|
expected => 7.75,
|
|
conf => '0 1',
|
|
field => 'tax_value'
|
|
}
|
|
);
|
|
$order_0_1 = C4::Acquisition::populate_order_with_prices(
|
|
{
|
|
order => $order_0_1,
|
|
booksellerid => 2,
|
|
receiving => 1,
|
|
}
|
|
);
|
|
|
|
compare(
|
|
{
|
|
got => $order_0_1->{unitprice_tax_included},
|
|
expected => 77.49,
|
|
conf => '0 1',
|
|
field => 'unitprice_tax_included'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_0_1->{unitprice_tax_excluded},
|
|
expected => 73.80,
|
|
conf => '0 1',
|
|
field => 'unitprice_tax_excluded'
|
|
}
|
|
);
|
|
compare(
|
|
{
|
|
got => $order_0_1->{tax_value_on_receiving},
|
|
expected => 7.38,
|
|
conf => '0 1',
|
|
field => 'tax_value'
|
|
}
|
|
);
|
|
};
|
|
|
|
}
|
|
|
|
sub compare {
|
|
my ($params) = @_;
|
|
is(
|
|
Koha::Number::Price->new( $params->{got} )->format,
|
|
Koha::Number::Price->new( $params->{expected} )->format,
|
|
"configuration $params->{conf}: $params->{field} should be correctly calculated"
|
|
);
|
|
}
|
|
|
|
# format_for_editing
|
|
for my $currency_format ( qw( US FR ) ) {
|
|
t::lib::Mocks::mock_preference( 'CurrencyFormat', $currency_format );
|
|
is( Koha::Number::Price->new( 1234567 )->format_for_editing, '1234567.00', 'format_for_editing should return unformated integer part with 2 decimals' );
|
|
is( Koha::Number::Price->new( 1234567.89 )->format_for_editing, '1234567.89', 'format_for_editing should return unformated integer part with 2 decimals' );
|
|
}
|