Revision dd75973a
Von Kivitendo Admin vor etwa 6 Jahren hinzugefügt
SL/DB/Helper/PriceTaxCalculator.pm | ||
---|---|---|
95 | 95 |
$item->fxsellprice($item->sellprice) if $data->{is_invoice}; |
96 | 96 |
|
97 | 97 |
my $num_dec = max 2, _num_decimal_places($item->sellprice); |
98 |
my $discount = _round($item->sellprice * ($item->discount || 0), $num_dec); |
|
99 |
my $sellprice = _round($item->sellprice - $discount, $num_dec); |
|
98 |
# my $discount = _round($item->sellprice * ($item->discount || 0), $num_dec); |
|
99 |
# my $sellprice; # = _round($item->sellprice - $discount, $num_dec); |
|
100 |
my $sellprice = $item->sellprice; # don't include rounded discount into sellprice |
|
101 |
# any time the sellprice is multiplied with qty discount has to be considered as part of the multiplication |
|
100 | 102 |
|
101 | 103 |
$item->price_factor( ! $item->price_factor_obj ? 1 : ($item->price_factor_obj->factor || 1)); |
102 | 104 |
$item->marge_price_factor(! $part->price_factor ? 1 : ($part->price_factor->factor || 1)); |
103 |
my $linetotal = _round($sellprice * $item->qty / $item->price_factor, 2) * $data->{exchangerate}; |
|
105 |
my $linetotal = _round($sellprice * (1-$item->discount) * $item->qty / $item->price_factor, 2) * $data->{exchangerate};
|
|
104 | 106 |
$linetotal = _round($linetotal, 2); |
105 | 107 |
|
106 |
$data->{invoicediff} += $sellprice * $item->qty * $data->{exchangerate} / $item->price_factor - $linetotal if $self->taxincluded; |
|
108 |
$data->{invoicediff} += $sellprice * (1-$item->discount) * $item->qty * $data->{exchangerate} / $item->price_factor - $linetotal if $self->taxincluded;
|
|
107 | 109 |
|
108 | 110 |
my $linetotal_cost = 0; |
109 | 111 |
|
... | ... | |
141 | 143 |
die "tax_amount != 0 but no chart_id for taxkey " . $taxkey->id . " tax " . $taxkey->tax->id; |
142 | 144 |
} |
143 | 145 |
|
144 |
$self->netamount($self->netamount + $sellprice * $item->qty / $item->price_factor); |
|
146 |
$self->netamount($self->netamount + $sellprice * (1-$item->discount) * $item->qty / $item->price_factor);
|
|
145 | 147 |
|
146 | 148 |
my $chart = $part->get_chart(type => $data->{is_sales} ? 'income' : 'expense', taxzone => $self->taxzone_id); |
147 | 149 |
$data->{amounts}->{ $chart->id } ||= { taxkey => $taxkey->taxkey_id, tax_id => $taxkey->tax_id, amount => 0 }; |
... | ... | |
244 | 246 |
|
245 | 247 |
next unless $qty; |
246 | 248 |
|
247 |
my $linetotal = _round(($entry->sellprice * $qty) / $base_factor, 2); |
|
249 |
my $linetotal = _round(($entry->sellprice * (1-$entry->discount) * $qty) / $base_factor, 2);
|
|
248 | 250 |
|
249 | 251 |
$data->{amounts_cogs}->{ $expense_income_chart->id } -= $linetotal; |
250 | 252 |
$data->{amounts_cogs}->{ $inventory_chart->id } += $linetotal; |
t/db_helper/price_tax_calculator.t | ||
---|---|---|
403 | 403 |
my $title = 'default invoice, one item, sellprice, rounding, discount'; |
404 | 404 |
my %data = $invoice->calculate_prices_and_taxes; |
405 | 405 |
|
406 |
is($invoice->netamount, 3.48, "${title}: netamount");
|
|
406 |
is($invoice->netamount, 3.49, "${title}: netamount");
|
|
407 | 407 |
|
408 |
is($invoice->amount, 4.14, "${title}: amount");
|
|
408 |
is($invoice->amount, 4.15, "${title}: amount");
|
|
409 | 409 |
|
410 |
is($invoice->marge_total, 3.48, "${title}: marge_total");
|
|
410 |
is($invoice->marge_total, 3.49, "${title}: marge_total");
|
|
411 | 411 |
is($invoice->marge_percent, 100, "${title}: marge_percent"); |
412 | 412 |
|
413 | 413 |
is_deeply(\%data, { |
414 | 414 |
allocated => {}, |
415 | 415 |
amounts => { |
416 | 416 |
$buchungsgruppe->income_accno_id($taxzone) => { |
417 |
amount => 3.48,
|
|
417 |
amount => 3.49,
|
|
418 | 418 |
tax_id => $tax->id, |
419 | 419 |
taxkey => 3, |
420 | 420 |
}, |
... | ... | |
428 | 428 |
$tax->chart_id => 0.66, |
429 | 429 |
}, |
430 | 430 |
items => [ |
431 |
{ linetotal => 3.48,
|
|
431 |
{ linetotal => 3.49,
|
|
432 | 432 |
linetotal_cost => 0, |
433 | 433 |
sellprice => 0.58, |
434 |
tax_amount => 0.6612, |
|
434 |
tax_amount => 0.6631, |
|
435 |
taxkey_id => $taxkeys{$item->parts_id}->id, |
|
436 |
}, |
|
437 |
], |
|
438 |
}, "${title}: calculated data"); |
|
439 |
} |
|
440 |
|
|
441 |
sub test_default_invoice_one_item_19_tax_not_included_rounding_discount_huge_qty() { |
|
442 |
reset_state(); |
|
443 |
|
|
444 |
my $item = new_item(qty => 100000, part => $parts[2], discount => 0.03, sellprice => 0.10); |
|
445 |
my $invoice = new_invoice( |
|
446 |
taxincluded => 0, |
|
447 |
invoiceitems => [ $item ], |
|
448 |
); |
|
449 |
|
|
450 |
my %taxkeys = map { ($_->id => $_->get_taxkey(date => DateTime->today_local, is_sales => 1, taxzone => $invoice->taxzone_id)) } uniq map { $_->part } ($item); |
|
451 |
|
|
452 |
# PTC and ar form calculate linetotal differently: |
|
453 |
# 6 parts for 0.60 with 3% discount |
|
454 |
# |
|
455 |
# ar form: |
|
456 |
# linetotal = sellprice 0.60 * qty 6 * discount (1 - 0.03) = 3.492 rounded 3.49 |
|
457 |
# total = 3.49 + 0.66 = 4.15 |
|
458 |
# |
|
459 |
# PTC: |
|
460 |
# discount = sellprice 0.60 * discount (0.03) = 0.018; rounded 0.02 |
|
461 |
# sellprice = sellprice 0.60 - discount 0.02 = 0.58 |
|
462 |
# linetotal = sellprice 0.58 * qty 6 = 3.48 |
|
463 |
# 19%(3.48) = 0.6612; rounded = 0.66 |
|
464 |
# total rounded = 3.48 + 0.66 = 4.14 |
|
465 |
|
|
466 |
my $title = 'default invoice, one item, sellprice, rounding, discount'; |
|
467 |
my %data = $invoice->calculate_prices_and_taxes; |
|
468 |
|
|
469 |
is($invoice->netamount, 9700, "${title}: netamount"); |
|
470 |
|
|
471 |
is($invoice->amount, 11543, "${title}: amount"); |
|
472 |
|
|
473 |
is($invoice->marge_total, 9700, "${title}: marge_total"); |
|
474 |
is($invoice->marge_percent, 100, "${title}: marge_percent"); |
|
475 |
|
|
476 |
is_deeply(\%data, { |
|
477 |
allocated => {}, |
|
478 |
amounts => { |
|
479 |
$buchungsgruppe->income_accno_id($taxzone) => { |
|
480 |
amount => 9700, |
|
481 |
tax_id => $tax->id, |
|
482 |
taxkey => 3, |
|
483 |
}, |
|
484 |
}, |
|
485 |
amounts_cogs => {}, |
|
486 |
assembly_items => [ |
|
487 |
[], |
|
488 |
], |
|
489 |
exchangerate => 1, |
|
490 |
taxes => { |
|
491 |
$tax->chart_id => 1843, |
|
492 |
}, |
|
493 |
items => [ |
|
494 |
{ linetotal => 9700, |
|
495 |
linetotal_cost => 0, |
|
496 |
sellprice => 0.1, |
|
497 |
tax_amount => 1843, |
|
435 | 498 |
taxkey_id => $taxkeys{$item->parts_id}->id, |
436 | 499 |
}, |
437 | 500 |
], |
... | ... | |
445 | 508 |
test_default_invoice_two_items_19_7_tax_not_included(); |
446 | 509 |
test_default_invoice_three_items_sellprice_rounding_discount(); |
447 | 510 |
test_default_invoice_one_item_19_tax_not_included_rounding_discount(); |
511 |
test_default_invoice_one_item_19_tax_not_included_rounding_discount_huge_qty(); |
|
448 | 512 |
|
449 | 513 |
clear_up(); |
450 | 514 |
done_testing(); |
Auch abrufbar als: Unified diff
PTC rundet nicht mehr Rabatt vor Mengenmultiplikation
siehe Ticket #82
Neuer Test für 100000 Artikel zu 0,10€ bei 3% Rabatt
Einen weiteren Test angepasst an die neuen Zahlen.