Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision a607a2d0

Von Bernd Bleßmann vor mehr als 10 Jahren hinzugefügt

  • ID a607a2d0854ef2b2e85bff4ab9657166236129c0
  • Vorgänger 68e4c3a2
  • Nachfolger 81b492ac

Rundungsfehler bei periodischen Rechnungen mit Einzelpreisen ...

... mit einer Nachkommastelle und Rabatt behoben.

siehe auch commit a22b8118e0bd68acac8a2d7b02a2d4f9fd0eaff1

Zudem einen Test dazu angelegt. Allerdings weicht die Art, wie der
PriceTaxCalculator und die Beleg-Masken rechnen, von einander ab.
Da müsste nochmal geprüft werden, was die richtige Art ist
(erst Rabatt abziehen und dann runden,
oder gerundeten Rabatt abziehen und wieder runden).
Auch beim Errechnen des Amounts gibt es unterschiede
(netamount * (1+Steuersatz),
oder aufsummieren).

Unterschiede anzeigen:

SL/DB/Helper/PriceTaxCalculator.pm
our @EXPORT = qw(calculate_prices_and_taxes);
use Carp;
use List::Util qw(sum min);
use List::Util qw(sum min max);
sub calculate_prices_and_taxes {
my ($self, %params) = @_;
......
$item->base_qty($item_unit->convert_to($item->qty, $part_unit));
$item->fxsellprice($item->sellprice) if $data->{is_invoice};
my $num_dec = _num_decimal_places($item->sellprice) || 2;
# ^ we need at least 2 decimal places ^
# my test case 43.00 € with 0 decimal places and 0.5 discount ->
# : sellprice before:43.00000
# : num dec before:0
# : discount / sellprice ratio: 22 / 21
# : discount = 43 * 0.5 _round(21.5, 0) = 22
# TODO write a test case
my $num_dec = max 2, _num_decimal_places($item->sellprice);
my $discount = _round($item->sellprice * ($item->discount || 0), $num_dec);
my $sellprice = _round($item->sellprice - $discount, $num_dec);
t/db_helper/price_tax_calculator.t
}, "${title}: calculated data");
}
sub test_default_invoice_three_items_sellprice_rounding_discount() {
reset_state();
my $item1 = new_item(qty => 1, sellprice => 5.55, discount => .05);
my $item2 = new_item(qty => 1, sellprice => 5.50, discount => .05);
my $item3 = new_item(qty => 1, sellprice => 5.00, discount => .05);
my $invoice = new_invoice(
taxincluded => 0,
invoiceitems => [ $item1, $item2, $item3 ],
);
# this is how price_tax_calculator is implemented. It differs from
# the way sales_order / invoice - forms are calculating:
# linetotal = sellprice 5.55 * qty 1 * (1 - 0.05) = 5.2725; rounded 5.27
# linetotal = sellprice 5.50 * qty 1 * (1 - 0.05) = 5.225 rounded 5.23
# linetotal = sellprice 5.00 * qty 1 * (1 - 0.05) = 4.75; rounded 4.75
# ...
# item 1:
# discount = sellprice 5.55 * discount (0.05) = 0.2775; rounded 0.28
# sellprice = sellprice 5.55 - discount 0.28 = 5.27; rounded 5.27
# linetotal = sellprice 5.27 * qty 1 = 5.27; rounded 5.27
# 19%(5.27) = 1.0013; rounded = 1.00
# total rounded = 6.27
# lastcost 1.93 * qty 1 = 1.93; rounded 1.93
# line marge_total = 3.34
# line marge_percent = 63.3776091081594
# item 2:
# discount = sellprice 5.50 * discount 0.05 = 0.275; rounded 0.28
# sellprice = sellprice 5.50 - discount 0.28 = 5.22; rounded 5.22
# linetotal = sellprice 5.22 * qty 1 = 5.22; rounded 5.22
# 19%(5.22) = 0.9918; rounded = 0.99
# total rounded = 6.21
# lastcost 1.93 * qty 1 = 1.93; rounded 1.93
# line marge_total = 5.22 - 1.93 = 3.29
# line marge_percent = 3.29/5.22 = 0.630268199233716
# item 3:
# discount = sellprice 5.00 * discount 0.25 = 0.25; rounded 0.25
# sellprice = sellprice 5.00 - discount 0.25 = 4.75; rounded 4.75
# linetotal = sellprice 4.75 * qty 1 = 4.75; rounded 4.75
# 19%(4.75) = 0.9025; rounded = 0.90
# total rounded = 5.65
# lastcost 1.93 * qty 1 = 1.93; rounded 1.93
# line marge_total = 2.82
# line marge_percent = 59.3684210526316
my $title = 'default invoice, three items, sellprice, rounding, discount';
my %data = $invoice->calculate_prices_and_taxes;
is($item1->marge_total, 3.34, "${title}: item1 marge_total");
is($item1->marge_percent, 63.3776091081594, "${title}: item1 marge_percent");
is($item1->marge_price_factor, 1, "${title}: item1 marge_price_factor");
is($item2->marge_total, 3.29, "${title}: item2 marge_total");
is($item2->marge_percent, 63.0268199233716, "${title}: item2 marge_percent");
is($item2->marge_price_factor, 1, "${title}: item2 marge_price_factor");
is($item3->marge_total, 2.82, "${title}: item3 marge_total");
is($item3->marge_percent, 59.3684210526316, "${title}: item3 marge_percent");
is($item3->marge_price_factor, 1, "${title}: item3 marge_price_factor");
is($invoice->netamount, 5.27 + 5.22 + 4.75, "${title}: netamount");
# 6.27 + 6.21 + 5.65 = 18.13
# 1.19*(5.27 + 5.22 + 4.75) = 18.1356; rounded 18.14
#is($invoice->amount, 6.27 + 6.21 + 5.65, "${title}: amount");
is($invoice->amount, 18.14, "${title}: amount");
is($invoice->marge_total, 3.34 + 3.29 + 2.82, "${title}: marge_total");
is($invoice->marge_percent, 62.007874015748, "${title}: marge_percent");
is_deeply(\%data, {
allocated => {},
amounts => {
$buchungsgruppe->income_accno_id_0 => {
amount => 15.24,
tax_id => $tax->id,
taxkey => 3,
},
},
amounts_cogs => {},
assembly_items => [
[], [], [],
],
exchangerate => 1,
taxes => {
$tax->chart_id => 2.9,
},
}, "${title}: calculated data");
}
Support::TestSetup::login();
test_default_invoice_one_item_19_tax_not_included();
test_default_invoice_two_items_19_7_tax_not_included();
test_default_invoice_three_items_sellprice_rounding_discount();
done_testing();

Auch abrufbar als: Unified diff