+ exchangerate => 1,
+ taxes_by_chart_id => {
+ $tax->chart_id => 1.11,
+ $tax7->chart_id => 0.82,
+ },
+ taxes_by_tax_id => {
+ $tax->id => 1.1115,
+ $tax7->id => 0.8162,
+ },
+ items => [
+ { linetotal => 5.85,
+ linetotal_cost => 4.83,
+ sellprice => 2.34,
+ tax_amount => 1.1115,
+ taxkey_id => $taxkey1->id,
+ },
+ { linetotal => 11.66,
+ linetotal_cost => 6.57,
+ sellprice => 9.714,
+ tax_amount => 0.8162,
+ taxkey_id => $taxkey2->id,
+ },
+ ],
+ rounding => 0,
+ }, "${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 ],
+ );
+
+ my %taxkeys = map { ($_->id => $_->get_taxkey(date => $transdate, is_sales => 1, taxzone => $invoice->taxzone_id)) } uniq map { $_->part } ($item1, $item2, $item3);
+
+ # item 1:
+ # discount = sellprice 5.55 * discount (0.05) = 0.2775; rounded 0.28
+ # linetotal = sellprice 5.55 * (1 - discount 0.05) * qty 1 = 5.2725; 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 = 5.27 - 1.93 = 3.34
+ # line marge_percent = 63.3776091081594
+
+ # item 2:
+ # discount = sellprice 5.50 * discount 0.05 = 0.275; rounded 0.28
+ # linetotal = sellprice 5.50 * (1 - discount 0.05) * qty 1 = 5.225; rounded 5.23
+ # 19%(5.23) = .99370; rounded = 0.99
+ # total rounded = 6.22
+
+ # lastcost 1.93 * qty 1 = 1.93; rounded 1.93
+ # line marge_total = 5.23 - 1.93 = 3.30
+ # line marge_percent = 3.30/5.23 = 0.630975143403442
+
+ # item 3:
+ # discount = sellprice 5.00 * discount 0.05 = 0.05 = 0.25; rounded 0.25
+ # linetotal = sellprice 5.00 (1 - discount 0.05) * 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 = 4.75 - 1.93 = 2.82
+ # line marge_percent = 2.82/4.75 = 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.30, "${title}: item2 marge_total");
+ is($item2->marge_percent, 63.0975143403442, "${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.23 + 4.75, "${title}: netamount");
+
+ # 6.27 + 6.22 + 5.65 = 18.14
+ # 1.19*(5.27 + 5.23 + 4.75) = 18.1475; rounded 18.15
+ #is($invoice->amount, 6.27 + 6.22 + 5.65, "${title}: amount");
+ is($invoice->amount, 18.15, "${title}: amount");
+
+ is($invoice->marge_total, 3.34 + 3.30 + 2.82, "${title}: marge_total");
+ is($invoice->marge_percent, 62.0327868852459, "${title}: marge_percent");
+
+ is_deeply(\%data, {
+ allocated => {},
+ amounts => {
+ $buchungsgruppe->income_accno_id($taxzone) => {
+ amount => 15.25,
+ tax_id => $tax->id,
+ taxkey => 3,
+ },
+ },
+ amounts_cogs => {},
+ assembly_items => [
+ [], [], [],
+ ],
+ exchangerate => 1,
+ taxes_by_chart_id => {
+ $tax->chart_id => 2.9,
+ },
+ taxes_by_tax_id => {
+ $tax->id => 2.89750,
+ },
+ items => [
+ { linetotal => 5.27,
+ linetotal_cost => 1.93,
+ sellprice => 5.27,
+ tax_amount => 1.0013,
+ taxkey_id => $taxkeys{$item1->parts_id}->id,
+ },
+ { linetotal => 5.23,
+ linetotal_cost => 1.93,
+ sellprice => 5.23,
+ tax_amount => 0.9937,
+ taxkey_id => $taxkeys{$item2->parts_id}->id,
+ },
+ { linetotal => 4.75,
+ linetotal_cost => 1.93,
+ sellprice => 4.75,
+ tax_amount => 0.9025,
+ taxkey_id => $taxkeys{$item3->parts_id}->id,
+ }
+ ],
+ rounding => 0,
+ }, "${title}: calculated data");
+}
+
+sub test_default_invoice_one_item_19_tax_not_included_rounding_discount() {
+ reset_state();
+
+ my $item = new_item(qty => 6, part => $parts[2], discount => 0.03);
+ my $invoice = new_invoice(
+ taxincluded => 0,
+ invoiceitems => [ $item ],
+ );
+
+ my %taxkeys = map { ($_->id => $_->get_taxkey(date => $transdate, is_sales => 1, taxzone => $invoice->taxzone_id)) } uniq map { $_->part } ($item);
+
+ # 6 parts for 0.60 with 3% discount
+ #
+ # linetotal = sellprice 0.60 * qty 6 * discount (1 - 0.03) = 3.492 rounded 3.49
+ # total = 3.49 + 0.66 = 4.15
+ #
+
+ my $title = 'default invoice, one item, sellprice, rounding, discount';
+ my %data = $invoice->calculate_prices_and_taxes;
+
+ is($invoice->netamount, 3.49, "${title}: netamount");
+
+ is($invoice->amount, 4.15, "${title}: amount");
+
+ is($invoice->marge_total, 3.49, "${title}: marge_total");
+ is($invoice->marge_percent, 100, "${title}: marge_percent");
+
+ is_deeply(\%data, {
+ allocated => {},
+ amounts => {
+ $buchungsgruppe->income_accno_id($taxzone) => {
+ amount => 3.49,
+ tax_id => $tax->id,
+ taxkey => 3,
+ },
+ },
+ amounts_cogs => {},
+ assembly_items => [
+ [],
+ ],
+ exchangerate => 1,
+ taxes_by_chart_id => {
+ $tax->chart_id => 0.66,
+ },
+ taxes_by_tax_id => {
+ $tax->id => 0.66310,
+ },
+ items => [
+ { linetotal => 3.49,
+ linetotal_cost => 0,
+ sellprice => 0.58,
+ tax_amount => 0.6631,
+ taxkey_id => $taxkeys{$item->parts_id}->id,
+ },
+ ],
+ rounding => 0,
+ }, "${title}: calculated data");
+}
+
+sub test_default_invoice_one_item_19_tax_not_included_rounding_discount_huge_qty() {
+ reset_state();
+
+ my $item = new_item(qty => 100000, part => $parts[2], discount => 0.03, sellprice => 0.10);
+ my $invoice = new_invoice(
+ taxincluded => 0,
+ invoiceitems => [ $item ],
+ );
+
+ my %taxkeys = map { ($_->id => $_->get_taxkey(date => $transdate, is_sales => 1, taxzone => $invoice->taxzone_id)) } uniq map { $_->part } ($item);
+
+ my $title = 'default invoice, one item, 19% tax not included, rounding, discount, huge qty';
+ my %data = $invoice->calculate_prices_and_taxes;
+
+ is($invoice->netamount, 9700, "${title}: netamount");
+
+ is($invoice->amount, 11543, "${title}: amount");
+
+ is($invoice->marge_total, 9700, "${title}: marge_total");
+ is($invoice->marge_percent, 100, "${title}: marge_percent");
+
+ is_deeply(\%data, {
+ allocated => {},
+ amounts => {
+ $buchungsgruppe->income_accno_id($taxzone) => {
+ amount => 9700,
+ tax_id => $tax->id,
+ taxkey => 3,
+ },
+ },
+ amounts_cogs => {},
+ assembly_items => [
+ [],
+ ],
+ exchangerate => 1,
+ taxes_by_chart_id => {
+ $tax->chart_id => 1843,
+ },
+ taxes_by_tax_id => {
+ $tax->id => 1843,
+ },
+ items => [
+ { linetotal => 9700,
+ linetotal_cost => 0,
+ sellprice => 0.1,
+ tax_amount => 1843,
+ taxkey_id => $taxkeys{$item->parts_id}->id,
+ },
+ ],
+ rounding => 0,
+ }, "${title}: calculated data");
+}
+
+sub test_default_invoice_one_item_19_tax_not_included_rounding_discount_big_qty_low_sellprice() {
+ reset_state();
+
+ my $item = new_item(qty => 10001, sellprice => 0.007, discount => 0.035);
+ my $invoice = new_invoice(
+ taxincluded => 0,
+ invoiceitems => [ $item ],
+ );
+
+ my %taxkeys = map { ($_->id => $_->get_taxkey(date => $transdate, is_sales => 1, taxzone => $invoice->taxzone_id)) } uniq map { $_->part } ($item);
+
+ # item 1:
+ # discount = sellprice 0.007 * discount (0.035) = 0.000245; rounded 0.00
+ # sellprice = sellprice 0.007 - discount 0.00 = 0.007
+ # linetotal = sellprice 0.007 * qty 10001 * (1 - 0.035) = 67.556755; rounded 67.56
+ # 19%(67.56) = 12.8364; rounded = 12.84
+ # total rounded = 80.40
+
+ # lastcost 1.93 * qty 10001 = 19301.93; rounded 19301.93
+ # line marge_total = 67.56-19301.93 = -19234.37
+ # line marge_percent = 100*-19234.37/67.56 = -28470.0562462996
+
+ my $title = 'default invoice one item 19 tax not included rounding discount big qty low sellprice';
+ my %data = $invoice->calculate_prices_and_taxes;
+
+ is($invoice->netamount, 67.56, "${title}: netamount");
+
+ is($invoice->amount, 80.40, "${title}: amount");
+
+ is($invoice->marge_total, -19234.37, "${title}: marge_total");
+ is($invoice->marge_percent, -28470.0562462996, "${title}: marge_percent");
+
+ is_deeply(\%data, {
+ allocated => {},
+ amounts => {
+ $buchungsgruppe->income_accno_id($taxzone) => {
+ amount => 67.56,
+ tax_id => $tax->id,
+ taxkey => 3,
+ },
+ },
+ amounts_cogs => {},
+ assembly_items => [
+ [],
+ ],
+ exchangerate => 1,
+ taxes_by_chart_id => {
+ $tax->chart_id => 12.84,