2 use Test::More tests => 197;
10 use Support::TestSetup;
12 use List::Util qw(sum);
14 use SL::Dev::Record qw(create_invoice_item create_sales_invoice create_credit_note);
15 use SL::Dev::CustomerVendor qw(new_customer new_vendor);
16 use SL::Dev::Part qw(new_part);
17 use SL::DB::Buchungsgruppe;
19 use SL::DB::Exchangerate;
27 use SL::DB::BankAccount;
28 use SL::DB::PaymentTerm;
29 use SL::DBUtils qw(selectfirst_array_query);
32 my ($customer, $vendor, $currency_id, @parts, $buchungsgruppe, $buchungsgruppe7, $unit, $employee, $tax, $tax7, $tax_9, $taxzone, $payment_terms, $bank_account);
33 my ($transdate1, $transdate2, $transdate3, $transdate4, $currency, $exchangerate, $exchangerate2, $exchangerate3, $exchangerate4);
34 my ($ar_chart,$bank,$ar_amount_chart, $ap_chart, $ap_amount_chart, $fxloss_chart, $fxgain_chart);
36 my $purchase_invoice_counter = 0; # used for generating purchase invnumber
38 Support::TestSetup::login();
42 # test cases: without_skonto
43 test_default_invoice_one_item_19_without_skonto();
44 test_default_invoice_two_items_19_7_tax_with_skonto();
45 test_default_invoice_two_items_19_7_without_skonto();
46 test_default_invoice_two_items_19_7_without_skonto_incomplete_payment();
47 test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments();
48 test_default_purchase_invoice_two_charts_19_7_without_skonto();
49 test_default_purchase_invoice_two_charts_19_7_tax_partial_unrounded_payment_without_skonto();
50 test_default_invoice_one_item_19_without_skonto_overpaid();
51 test_credit_note_two_items_19_7_tax_tax_not_included();
53 # test cases: difference_as_skonto
54 test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto();
55 test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto_1cent();
56 test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto_2cent();
57 test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto();
58 test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto_1cent();
59 test_default_purchase_invoice_two_charts_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto();
61 # test cases: with_skonto_pt
62 test_default_invoice_two_items_19_7_tax_with_skonto_50_50();
63 test_default_invoice_four_items_19_7_tax_with_skonto_4x_25();
64 test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_multiple();
65 test_default_purchase_invoice_two_charts_19_7_with_skonto();
66 test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_tax_included();
67 test_default_invoice_two_items_19_7_tax_with_skonto_tax_included();
69 # test payment of ar and ap transactions with currency and tax included/not included
70 # exchangerate = 1.33333
71 test_ar_currency_tax_not_included_and_payment();
72 test_ar_currency_tax_included();
73 test_ap_currency_tax_not_included_and_payment();
74 test_ap_currency_tax_included();
76 test_ar_currency_tax_not_included_and_payment_2(); # exchangerate 0.8
77 test_ar_currency_tax_not_included_and_payment_2_credit_note(); # exchangerate 0.8
79 test_ap_currency_tax_not_included_and_payment_2(); # two exchangerates, with fx_gain_loss
80 test_ap_currency_tax_not_included_and_payment_2_credit_note(); # two exchangerates, with fx_gain_loss
82 is(SL::DB::Manager::Invoice->get_all_count(), 21, "number of invoices at end of tests ok");
84 local $TODO = "currently this test fails because the code writing the invoice is buggy, the calculation of skonto is correct";
85 my ($acc_trans_sum) = selectfirst_array_query($::form, $currency->db->dbh, 'SELECT SUM(amount) FROM acc_trans');
86 is($acc_trans_sum, '0.00000', "sum of all acc_trans at end of all tests is 0");
89 # remove all created data at end of test
96 SL::DB::Manager::InvoiceItem->delete_all(all => 1);
97 SL::DB::Manager::Invoice->delete_all(all => 1);
98 SL::DB::Manager::PurchaseInvoice->delete_all(all => 1);
99 SL::DB::Manager::Part->delete_all(all => 1);
100 SL::DB::Manager::Customer->delete_all(all => 1);
101 SL::DB::Manager::Vendor->delete_all(all => 1);
102 SL::DB::Manager::BankAccount->delete_all(all => 1);
103 SL::DB::Manager::PaymentTerm->delete_all(all => 1);
104 SL::DB::Manager::Exchangerate->delete_all(all => 1);
105 SL::DB::Manager::Currency->delete_all(where => [ name => 'CUR' ]);
113 $transdate1 = DateTime->today;
114 $transdate2 = DateTime->today->add(days => 1);
115 $transdate3 = DateTime->today->add(days => 2);
116 $transdate4 = DateTime->today->add(days => 3);
118 $buchungsgruppe = SL::DB::Manager::Buchungsgruppe->find_by(description => 'Standard 19%') || croak "No accounting group";
119 $buchungsgruppe7 = SL::DB::Manager::Buchungsgruppe->find_by(description => 'Standard 7%') || croak "No accounting group for 7\%";
120 $unit = SL::DB::Manager::Unit->find_by(name => 'kg') || croak "No unit";
121 $employee = SL::DB::Manager::Employee->current || croak "No employee";
122 $tax = SL::DB::Manager::Tax->find_by(taxkey => 3, rate => 0.19) || croak "No tax";
123 $tax7 = SL::DB::Manager::Tax->find_by(taxkey => 2, rate => 0.07) || croak "No tax for 7\%";
124 $taxzone = SL::DB::Manager::TaxZone->find_by( description => 'Inland') || croak "No taxzone";
125 $tax_9 = SL::DB::Manager::Tax->find_by(taxkey => 9, rate => 0.19) || croak "No tax";
126 # $tax7 = SL::DB::Manager::Tax->find_by(taxkey => 2, rate => 0.07) || croak "No tax for 7\%";
128 $currency_id = $::instance_conf->get_currency_id;
130 $currency = SL::DB::Currency->new(name => 'CUR')->save;
132 $fxgain_chart = SL::DB::Manager::Chart->find_by(accno => '2660') or die "Can't find fxgain_chart in test";
133 $fxloss_chart = SL::DB::Manager::Chart->find_by(accno => '2150') or die "Can't find fxloss_chart in test";
135 $currency->db->dbh->do('UPDATE defaults SET fxgain_accno_id = ' . $fxgain_chart->id);
136 $currency->db->dbh->do('UPDATE defaults SET fxloss_accno_id = ' . $fxloss_chart->id);
137 $::instance_conf->reload->data;
138 is($fxgain_chart->id, $::instance_conf->get_fxgain_accno_id, "fxgain_chart was updated in defaults");
139 is($fxloss_chart->id, $::instance_conf->get_fxloss_accno_id, "fxloss_chart was updated in defaults");
141 $exchangerate = SL::DB::Exchangerate->new(transdate => $transdate1,
144 currency_id => $currency->id,
146 $exchangerate2 = SL::DB::Exchangerate->new(transdate => $transdate2,
149 currency_id => $currency->id,
151 $exchangerate3 = SL::DB::Exchangerate->new(transdate => $transdate3,
154 currency_id => $currency->id,
156 $exchangerate4 = SL::DB::Exchangerate->new(transdate => $transdate4,
159 currency_id => $currency->id,
162 $customer = new_customer(
163 name => 'Test Customer',
164 currency_id => $currency_id,
165 taxzone_id => $taxzone->id,
168 $bank_account = SL::DB::BankAccount->new(
169 account_number => '123',
174 chart_id => SL::DB::Manager::Chart->find_by( description => 'Bank' )->id,
175 name => SL::DB::Manager::Chart->find_by( description => 'Bank' )->description,
178 $payment_terms = SL::DB::PaymentTerm->new(
179 description => 'payment',
180 description_long => 'payment',
183 percent_skonto => '0.05',
184 auto_calculation => 1,
187 $vendor = new_vendor(
188 name => 'Test Vendor',
189 currency_id => $currency_id,
190 taxzone_id => $taxzone->id,
191 payment_id => $payment_terms->id,
196 push @parts, new_part(
197 partnumber => 'T4254',
198 description => 'Fourty-two fifty-four',
201 buchungsgruppen_id => $buchungsgruppe->id,
206 push @parts, new_part(
207 partnumber => 'T0815',
208 description => 'Zero EIGHT fifteeN @ 7%',
211 buchungsgruppen_id => $buchungsgruppe7->id,
215 push @parts, new_part(
217 description => 'Testware 19%',
220 buchungsgruppen_id => $buchungsgruppe->id,
224 push @parts, new_part(
226 description => 'Testware 7%',
229 buchungsgruppen_id => $buchungsgruppe7->id,
234 $ar_chart = SL::DB::Manager::Chart->find_by( accno => '1400' ); # Forderungen
235 $ap_chart = SL::DB::Manager::Chart->find_by( accno => '1600' ); # Verbindlichkeiten
236 $bank = SL::DB::Manager::Chart->find_by( accno => '1200' ); # Bank
237 $ar_amount_chart = SL::DB::Manager::Chart->find_by( accno => '8400' ); # Erlöse
238 $ap_amount_chart = SL::DB::Manager::Chart->find_by( accno => '3400' ); # Wareneingang 19%
241 sub new_purchase_invoice {
243 # manually create a Kreditorenbuchung from scratch, ap + acc_trans bookings, as no helper exists yet, like $invoice->post.
244 # arap-Booking must come last in the acc_trans order
245 $purchase_invoice_counter++;
247 my $purchase_invoice = SL::DB::PurchaseInvoice->new(
248 vendor_id => $vendor->id,
249 invnumber => 'newap ' . $purchase_invoice_counter ,
250 currency_id => $currency_id,
251 employee_id => $employee->id,
252 gldate => $transdate1,
253 taxzone_id => $taxzone->id,
254 transdate => $transdate1,
264 my $expense_chart = SL::DB::Manager::Chart->find_by(accno => '3400');
265 my $expense_chart_booking= SL::DB::AccTransaction->new(
266 trans_id => $purchase_invoice->id,
267 chart_id => $expense_chart->id,
268 chart_link => $expense_chart->link,
270 transdate => $transdate1,
273 tax_id => SL::DB::Manager::Tax->find_by(taxkey => 9)->id);
274 $expense_chart_booking->save;
276 my $tax_chart = SL::DB::Manager::Chart->find_by(accno => '1576');
277 my $tax_chart_booking= SL::DB::AccTransaction->new(
278 trans_id => $purchase_invoice->id,
279 chart_id => $tax_chart->id,
280 chart_link => $tax_chart->link,
282 transdate => $transdate1,
285 tax_id => SL::DB::Manager::Tax->find_by(taxkey => 9)->id);
286 $tax_chart_booking->save;
287 $expense_chart = SL::DB::Manager::Chart->find_by(accno => '3300');
288 $expense_chart_booking= SL::DB::AccTransaction->new(
289 trans_id => $purchase_invoice->id,
290 chart_id => $expense_chart->id,
291 chart_link => $expense_chart->link,
293 transdate => $transdate1,
296 tax_id => SL::DB::Manager::Tax->find_by(taxkey => 8)->id);
297 $expense_chart_booking->save;
300 $tax_chart = SL::DB::Manager::Chart->find_by(accno => '1571');
301 $tax_chart_booking= SL::DB::AccTransaction->new(
302 trans_id => $purchase_invoice->id,
303 chart_id => $tax_chart->id,
304 chart_link => $tax_chart->link,
306 transdate => $transdate1,
309 tax_id => SL::DB::Manager::Tax->find_by(taxkey => 8)->id);
310 $tax_chart_booking->save;
311 my $arap_chart = SL::DB::Manager::Chart->find_by(accno => '1600');
312 my $arap_booking= SL::DB::AccTransaction->new(trans_id => $purchase_invoice->id,
313 chart_id => $arap_chart->id,
314 chart_link => $arap_chart->link,
316 transdate => $transdate1,
319 tax_id => SL::DB::Manager::Tax->find_by(taxkey => 0)->id);
322 return $purchase_invoice;
325 sub number_of_payments {
328 my $number_of_payments;
330 foreach my $transaction ( @{ $invoice->transactions } ) {
331 if ( $transaction->chart_link =~ /(AR_paid|AP_paid)/ ) {
332 $paid_amount += $transaction->amount ;
333 $number_of_payments++;
336 return ($number_of_payments, $paid_amount);
342 my $total = sum map { $_->amount } @{ $invoice->transactions };
344 return $::form->round_amount($total, 5);
350 sub test_default_invoice_one_item_19_without_skonto() {
351 my $title = 'default invoice, one item, 19% tax, without_skonto';
352 my $item = create_invoice_item(part => $parts[0], qty => 2.5);
353 my $invoice = create_sales_invoice(
355 invoiceitems => [ $item ],
356 payment_id => $payment_terms->id,
359 my $purchase_invoice = new_purchase_invoice();
362 my %params = ( chart_id => $bank_account->chart_id,
363 transdate => DateTime->today_local->to_kivitendo
366 $params{amount} = '6.96';
367 $params{payment_type} = 'without_skonto';
369 $invoice->pay_invoice( %params );
371 my ($number_of_payments, $paid_amount) = number_of_payments($invoice);
372 my $total = total_amount($invoice);
374 is($invoice->netamount, 5.85, "${title}: netamount");
375 is($invoice->amount, 6.96, "${title}: amount");
376 is($paid_amount, -6.96, "${title}: paid amount");
377 is($number_of_payments, 1, "${title}: 1 AR_paid booking");
378 is($invoice->paid, 6.96, "${title}: paid");
379 is($total, 0, "${title}: even balance");
383 sub test_default_invoice_one_item_19_without_skonto_overpaid() {
384 my $title = 'default invoice, one item, 19% tax, without_skonto';
386 my $item = create_invoice_item(part => $parts[0], qty => 2.5);
387 my $invoice = create_sales_invoice(
389 invoiceitems => [ $item ],
390 payment_id => $payment_terms->id,
393 my $purchase_invoice = new_purchase_invoice();
397 my %params = ( chart_id => $bank_account->chart_id,
398 transdate => DateTime->today_local->to_kivitendo
401 $params{amount} = '16.96';
402 $params{payment_type} = 'without_skonto';
403 $invoice->pay_invoice( %params );
405 $params{amount} = '-10.00';
406 $invoice->pay_invoice( %params );
408 my ($number_of_payments, $paid_amount) = number_of_payments($invoice);
409 my $total = total_amount($invoice);
411 is($invoice->netamount, 5.85, "${title}: netamount");
412 is($invoice->amount, 6.96, "${title}: amount");
413 is($paid_amount, -6.96, "${title}: paid amount");
414 is($number_of_payments, 2, "${title}: 1 AR_paid booking");
415 is($invoice->paid, 6.96, "${title}: paid");
416 is($total, 0, "${title}: even balance");
422 sub test_default_invoice_two_items_19_7_tax_with_skonto() {
423 my $title = 'default invoice, two items, 19/7% tax with_skonto_pt';
425 my $item1 = create_invoice_item(part => $parts[0], qty => 2.5);
426 my $item2 = create_invoice_item(part => $parts[1], qty => 1.2);
427 my $invoice = create_sales_invoice(
429 invoiceitems => [ $item1, $item2 ],
430 payment_id => $payment_terms->id,
434 my %params = ( chart_id => $bank_account->chart_id,
435 transdate => DateTime->today_local->to_kivitendo
438 $params{payment_type} = 'with_skonto_pt';
439 $params{amount} = $invoice->amount_less_skonto;
441 $invoice->pay_invoice( %params );
443 my ($number_of_payments, $paid_amount) = number_of_payments($invoice);
444 my $total = total_amount($invoice);
446 is($invoice->netamount, 5.85 + 11.66, "${title}: netamount");
447 is($invoice->amount, 6.96 + 12.48, "${title}: amount");
448 is($paid_amount, -19.44, "${title}: paid amount");
449 is($invoice->paid, 19.44, "${title}: paid");
450 is($number_of_payments, 3, "${title}: 3 AR_paid bookings");
451 is($total, 0, "${title}: even balance");
454 sub test_default_invoice_two_items_19_7_tax_with_skonto_tax_included() {
455 my $title = 'default invoice, two items, 19/7% tax with_skonto_pt';
457 my $item1 = create_invoice_item(part => $parts[0], qty => 2.5);
458 my $item2 = create_invoice_item(part => $parts[1], qty => 1.2);
459 my $invoice = create_sales_invoice(
461 invoiceitems => [ $item1, $item2 ],
462 payment_id => $payment_terms->id,
466 my %params = ( chart_id => $bank_account->chart_id,
467 transdate => DateTime->today_local->to_kivitendo
470 $params{payment_type} = 'with_skonto_pt';
471 $params{amount} = $invoice->amount_less_skonto;
473 $invoice->pay_invoice( %params );
475 my ($number_of_payments, $paid_amount) = number_of_payments($invoice);
476 my $total = total_amount($invoice);
478 is($invoice->netamount, 15.82, "${title}: netamount");
479 is($invoice->amount, 17.51, "${title}: amount");
480 is($paid_amount, -17.51, "${title}: paid amount");
481 is($invoice->paid, 17.51, "${title}: paid");
482 is($number_of_payments, 3, "${title}: 3 AR_paid bookings");
485 local $TODO = "currently this test fails because the code writing the invoice is buggy, the calculation of skonto is correct";
486 is($total, 0, "${title}: even balance");
490 # test 3 : two items, without skonto
491 sub test_default_invoice_two_items_19_7_without_skonto() {
492 my $title = 'default invoice, two items, 19/7% tax without skonto';
494 my $item1 = create_invoice_item(part => $parts[0], qty => 2.5);
495 my $item2 = create_invoice_item(part => $parts[1], qty => 1.2);
496 my $invoice = create_sales_invoice(
498 invoiceitems => [ $item1, $item2 ],
499 payment_id => $payment_terms->id,
503 my %params = ( chart_id => $bank_account->chart_id,
504 transdate => DateTime->today_local->to_kivitendo
507 $params{amount} = '19.44'; # pass full amount
508 $params{payment_type} = 'without_skonto';
510 $invoice->pay_invoice( %params );
512 my ($number_of_payments, $paid_amount) = number_of_payments($invoice);
513 my $total = total_amount($invoice);
515 is($invoice->netamount, 5.85 + 11.66, "${title}: netamount");
516 is($invoice->amount, 6.96 + 12.48, "${title}: amount");
517 is($paid_amount, -19.44, "${title}: paid amount");
518 is($invoice->paid, 19.44, "${title}: paid");
519 is($number_of_payments, 1, "${title}: 1 AR_paid bookings");
520 is($total, 0, "${title}: even balance");
524 sub test_default_invoice_two_items_19_7_without_skonto_incomplete_payment() {
525 my $title = 'default invoice, two items, 19/7% tax without skonto incomplete payment';
527 my $item1 = create_invoice_item(part => $parts[0], qty => 2.5);
528 my $item2 = create_invoice_item(part => $parts[1], qty => 1.2);
529 my $invoice = create_sales_invoice(
531 invoiceitems => [ $item1, $item2 ],
532 payment_id => $payment_terms->id,
535 $invoice->pay_invoice( amount => '9.44',
536 payment_type => 'without_skonto',
537 chart_id => $bank_account->chart_id,
538 transdate => DateTime->today_local->to_kivitendo,
541 my ($number_of_payments, $paid_amount) = number_of_payments($invoice);
542 my $total = total_amount($invoice);
544 is($invoice->netamount, 5.85 + 11.66, "${title}: netamount");
545 is($invoice->amount, 6.96 + 12.48, "${title}: amount");
546 is($paid_amount, -9.44, "${title}: paid amount");
547 is($invoice->paid, 9.44, "${title}: paid");
548 is($number_of_payments, 1, "${title}: 1 AR_paid bookings");
549 is($total, 0, "${title}: even balance");
553 sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments() {
554 my $title = 'default invoice, two items, 19/7% tax not included';
556 my $item1 = create_invoice_item(part => $parts[0], qty => 2.5);
557 my $item2 = create_invoice_item(part => $parts[1], qty => 1.2);
558 my $invoice = create_sales_invoice(
560 invoiceitems => [ $item1, $item2 ],
561 payment_id => $payment_terms->id,
564 $invoice->pay_invoice( amount => '9.44',
565 payment_type => 'without_skonto',
566 chart_id => $bank_account->chart_id,
567 transdate => DateTime->today_local->to_kivitendo
569 $invoice->pay_invoice( amount => '10.00',
570 chart_id => $bank_account->chart_id,
571 transdate => DateTime->today_local->to_kivitendo
574 my ($number_of_payments, $paid_amount) = number_of_payments($invoice);
575 my $total = total_amount($invoice);
577 is($invoice->netamount, 5.85 + 11.66, "${title}: netamount");
578 is($invoice->amount, 6.96 + 12.48, "${title}: amount");
579 is($paid_amount, -19.44, "${title}: paid amount");
580 is($invoice->paid, 19.44, "${title}: paid");
581 is($number_of_payments, 2, "${title}: 2 AR_paid bookings");
582 is($total, 0, "${title}: even balance");
587 sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto() {
588 my $title = 'default invoice, two items, 19/7% tax not included';
590 my $item1 = create_invoice_item(part => $parts[0], qty => 2.5);
591 my $item2 = create_invoice_item(part => $parts[1], qty => 1.2);
592 my $invoice = create_sales_invoice(
594 invoiceitems => [ $item1, $item2 ],
595 payment_id => $payment_terms->id,
598 $invoice->pay_invoice( amount => '9.44',
599 payment_type => 'without_skonto',
600 chart_id => $bank_account->chart_id,
601 transdate => DateTime->today_local->to_kivitendo
603 $invoice->pay_invoice( amount => '8.73',
604 payment_type => 'without_skonto',
605 chart_id => $bank_account->chart_id,
606 transdate => DateTime->today_local->to_kivitendo
608 $invoice->pay_invoice( amount => $invoice->open_amount,
609 payment_type => 'difference_as_skonto',
610 chart_id => $bank_account->chart_id,
611 transdate => DateTime->today_local->to_kivitendo
614 my ($number_of_payments, $paid_amount) = number_of_payments($invoice);
615 my $total = total_amount($invoice);
617 is($invoice->netamount, 5.85 + 11.66, "${title}: netamount");
618 is($invoice->amount, 6.96 + 12.48, "${title}: amount");
619 is($paid_amount, -19.44, "${title}: paid amount");
620 is($invoice->paid, 19.44, "${title}: paid");
621 is($number_of_payments, 4, "${title}: 4 AR_paid bookings");
622 is($total, 0, "${title}: even balance");
626 sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto_1cent() {
627 my $title = 'default invoice, two items, 19/7% tax not included';
629 # if there is only one cent left there can only be one skonto booking, the
630 # error handling should choose the highest amount, which is the 7% account
631 # (11.66) rather than the 19% account (5.85). The actual tax amount is
632 # higher for the 19% case, though (1.11 compared to 0.82)
634 my $item1 = create_invoice_item(part => $parts[0], qty => 2.5);
635 my $item2 = create_invoice_item(part => $parts[1], qty => 1.2);
636 my $invoice = create_sales_invoice(
638 invoiceitems => [ $item1, $item2 ],
639 payment_id => $payment_terms->id,
642 $invoice->pay_invoice( amount => '19.42',
643 payment_type => 'without_skonto',
644 chart_id => $bank_account->chart_id,
645 transdate => DateTime->today_local->to_kivitendo
647 $invoice->pay_invoice( amount => $invoice->open_amount,
648 payment_type => 'difference_as_skonto',
649 chart_id => $bank_account->chart_id,
650 transdate => DateTime->today_local->to_kivitendo
653 my ($number_of_payments, $paid_amount) = number_of_payments($invoice);
654 my $total = total_amount($invoice);
656 is($invoice->netamount, 5.85 + 11.66, "${title}: netamount");
657 is($invoice->amount, 6.96 + 12.48, "${title}: amount");
658 is($paid_amount, -19.44, "${title}: paid amount");
659 is($invoice->paid, 19.44, "${title}: paid");
660 is($number_of_payments, 3, "${title}: 2 AR_paid bookings");
661 is($total, 0, "${title}: even balance");
665 sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto_2cent() {
666 my $title = 'default invoice, two items, 19/7% tax not included';
668 # if there are two cents left there will be two skonto bookings, 1 cent each
669 my $item1 = create_invoice_item(part => $parts[0], qty => 2.5);
670 my $item2 = create_invoice_item(part => $parts[1], qty => 1.2);
671 my $invoice = create_sales_invoice(
673 invoiceitems => [ $item1, $item2 ],
674 payment_id => $payment_terms->id,
677 $invoice->pay_invoice( amount => '19.42',
678 payment_type => 'without_skonto',
679 chart_id => $bank_account->chart_id,
680 transdate => DateTime->today_local->to_kivitendo
682 $invoice->pay_invoice( amount => $invoice->open_amount,
683 payment_type => 'difference_as_skonto',
684 chart_id => $bank_account->chart_id,
685 transdate => DateTime->today_local->to_kivitendo
688 my ($number_of_payments, $paid_amount) = number_of_payments($invoice);
689 my $total = total_amount($invoice);
691 is($invoice->netamount, 5.85 + 11.66, "${title}: netamount");
692 is($invoice->amount, 6.96 + 12.48, "${title}: amount");
693 is($paid_amount, -19.44, "${title}: paid amount");
694 is($invoice->paid, 19.44, "${title}: paid");
695 is($number_of_payments, 3, "${title}: 3 AR_paid bookings");
696 is($total, 0, "${title}: even balance");
700 sub test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto() {
701 my $title = 'default invoice, one item, 19% tax, without_skonto';
703 my $item = create_invoice_item(part => $parts[0], qty => 2.5);
704 my $invoice = create_sales_invoice(
706 invoiceitems => [ $item ],
707 payment_id => $payment_terms->id,
711 my %params = ( chart_id => $bank_account->chart_id,
712 transdate => DateTime->today_local->to_kivitendo
715 $params{amount} = '2.32';
716 $params{payment_type} = 'without_skonto';
717 $invoice->pay_invoice( %params );
719 $params{amount} = '3.81';
720 $params{payment_type} = 'without_skonto';
721 $invoice->pay_invoice( %params );
723 $params{amount} = $invoice->open_amount; # set amount, otherwise previous 3.81 is used
724 $params{payment_type} = 'difference_as_skonto';
725 $invoice->pay_invoice( %params );
727 my ($number_of_payments, $paid_amount) = number_of_payments($invoice);
728 my $total = total_amount($invoice);
730 is($invoice->netamount, 5.85, "${title}: netamount");
731 is($invoice->amount, 6.96, "${title}: amount");
732 is($paid_amount, -6.96, "${title}: paid amount");
733 is($number_of_payments, 3, "${title}: 3 AR_paid booking");
734 is($invoice->paid, 6.96, "${title}: paid");
735 is($total, 0, "${title}: even balance");
739 sub test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto_1cent() {
740 my $title = 'default invoice, one item, 19% tax, without_skonto';
742 my $item = create_invoice_item(part => $parts[0], qty => 2.5);
743 my $invoice = create_sales_invoice(
745 invoiceitems => [ $item ],
746 payment_id => $payment_terms->id,
750 my %params = ( chart_id => $bank_account->chart_id,
751 transdate => DateTime->today_local->to_kivitendo
754 $params{amount} = '6.95';
755 $params{payment_type} = 'without_skonto';
756 $invoice->pay_invoice( %params );
758 $params{amount} = $invoice->open_amount; # set amount, otherwise previous value 6.95 is used
759 $params{payment_type} = 'difference_as_skonto';
760 $invoice->pay_invoice( %params );
762 my ($number_of_payments, $paid_amount) = number_of_payments($invoice);
763 my $total = total_amount($invoice);
765 is($invoice->netamount, 5.85, "${title}: netamount");
766 is($invoice->amount, 6.96, "${title}: amount");
767 is($paid_amount, -6.96, "${title}: paid amount");
768 is($number_of_payments, 2, "${title}: 3 AR_paid booking");
769 is($invoice->paid, 6.96, "${title}: paid");
770 is($total, 0, "${title}: even balance");
774 # test 3 : two items, without skonto
775 sub test_default_purchase_invoice_two_charts_19_7_without_skonto() {
776 my $title = 'default invoice, two items, 19/7% tax without skonto';
778 my $purchase_invoice = new_purchase_invoice();
780 my %params = ( chart_id => $bank_account->chart_id,
781 transdate => DateTime->today_local->to_kivitendo
784 $params{amount} = '226'; # pass full amount
785 $params{payment_type} = 'without_skonto';
787 $purchase_invoice->pay_invoice( %params );
789 my ($number_of_payments, $paid_amount) = number_of_payments($purchase_invoice);
790 my $total = total_amount($purchase_invoice);
792 is($paid_amount, 226, "${title}: paid amount");
793 is($number_of_payments, 1, "${title}: 1 AP_paid bookings");
794 is($total, 0, "${title}: even balance");
798 sub test_default_purchase_invoice_two_charts_19_7_with_skonto() {
799 my $title = 'default invoice, two items, 19/7% tax without skonto';
801 my $purchase_invoice = new_purchase_invoice();
803 my %params = ( chart_id => $bank_account->chart_id,
804 transdate => DateTime->today_local->to_kivitendo
807 # $params{amount} = '226'; # pass full amount
808 $params{payment_type} = 'with_skonto_pt';
810 $purchase_invoice->pay_invoice( %params );
812 my ($number_of_payments, $paid_amount) = number_of_payments($purchase_invoice);
813 my $total = total_amount($purchase_invoice);
815 is($paid_amount, 226, "${title}: paid amount");
816 is($number_of_payments, 3, "${title}: 1 AP_paid bookings");
817 is($total, 0, "${title}: even balance");
821 sub test_default_purchase_invoice_two_charts_19_7_tax_partial_unrounded_payment_without_skonto() {
822 my $title = 'default purchase_invoice, two charts, 19/7% tax multiple payments with final difference as skonto';
824 # check whether unrounded amounts passed via $params{amount} are rounded for without_skonto case
825 my $purchase_invoice = new_purchase_invoice();
826 $purchase_invoice->pay_invoice(
827 amount => ( $purchase_invoice->amount / 3 * 2),
828 payment_type => 'without_skonto',
829 chart_id => $bank_account->chart_id,
830 transdate => DateTime->today_local->to_kivitendo
832 my ($number_of_payments, $paid_amount) = number_of_payments($purchase_invoice);
833 my $total = total_amount($purchase_invoice);
835 is($paid_amount, 150.67, "${title}: paid amount");
836 is($number_of_payments, 1, "${title}: 1 AP_paid bookings");
837 is($total, 0, "${title}: even balance");
841 sub test_default_purchase_invoice_two_charts_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto() {
842 my $title = 'default purchase_invoice, two charts, 19/7% tax multiple payments with final difference as skonto';
844 my $purchase_invoice = new_purchase_invoice();
846 # pay 2/3 and 1/5, leaves 3.83% to be used as Skonto
847 $purchase_invoice->pay_invoice(
848 amount => ( $purchase_invoice->amount / 3 * 2),
849 payment_type => 'without_skonto',
850 chart_id => $bank_account->chart_id,
851 transdate => DateTime->today_local->to_kivitendo
853 $purchase_invoice->pay_invoice(
854 amount => ( $purchase_invoice->amount / 5 ),
855 payment_type => 'without_skonto',
856 chart_id => $bank_account->chart_id,
857 transdate => DateTime->today_local->to_kivitendo
859 $purchase_invoice->pay_invoice(
860 payment_type => 'difference_as_skonto',
861 chart_id => $bank_account->chart_id,
862 transdate => DateTime->today_local->to_kivitendo
865 my ($number_of_payments, $paid_amount) = number_of_payments($purchase_invoice);
866 my $total = total_amount($purchase_invoice);
868 is($paid_amount, 226, "${title}: paid amount");
869 is($number_of_payments, 4, "${title}: 1 AP_paid bookings");
870 is($total, 0, "${title}: even balance");
875 sub test_default_invoice_two_items_19_7_tax_with_skonto_50_50() {
876 my $title = 'default invoice, two items, 19/7% tax with_skonto_pt 50/50';
878 my $item1 = create_invoice_item(part => $parts[2], qty => 1);
879 my $item2 = create_invoice_item(part => $parts[3], qty => 1);
880 my $invoice = create_sales_invoice(
882 invoiceitems => [ $item1, $item2 ],
883 payment_id => $payment_terms->id,
887 my %params = ( chart_id => $bank_account->chart_id,
888 transdate => DateTime->today_local->to_kivitendo
891 $params{amount} = $invoice->amount_less_skonto;
892 $params{payment_type} = 'with_skonto_pt';
894 $invoice->pay_invoice( %params );
896 my ($number_of_payments, $paid_amount) = number_of_payments($invoice);
897 my $total = total_amount($invoice);
899 is($invoice->netamount, 100, "${title}: netamount");
900 is($invoice->amount, 113, "${title}: amount");
901 is($paid_amount, -113, "${title}: paid amount");
902 is($invoice->paid, 113, "${title}: paid");
903 is($number_of_payments, 3, "${title}: 3 AR_paid bookings");
904 is($total, 0, "${title}: even balance");
908 sub test_default_invoice_four_items_19_7_tax_with_skonto_4x_25() {
909 my $title = 'default invoice, four items, 19/7% tax with_skonto_pt 4x25';
911 my $item1 = create_invoice_item(part => $parts[2], qty => 0.5);
912 my $item2 = create_invoice_item(part => $parts[3], qty => 0.5);
913 my $item3 = create_invoice_item(part => $parts[2], qty => 0.5);
914 my $item4 = create_invoice_item(part => $parts[3], qty => 0.5);
915 my $invoice = create_sales_invoice(
917 invoiceitems => [ $item1, $item2, $item3, $item4 ],
918 payment_id => $payment_terms->id,
922 my %params = ( chart_id => $bank_account->chart_id,
923 transdate => DateTime->today_local->to_kivitendo
926 $params{amount} = $invoice->amount_less_skonto;
927 $params{payment_type} = 'with_skonto_pt';
929 $invoice->pay_invoice( %params );
931 my ($number_of_payments, $paid_amount) = number_of_payments($invoice);
932 my $total = total_amount($invoice);
934 is($invoice->netamount , 100 , "${title}: netamount");
935 is($invoice->amount , 113 , "${title}: amount");
936 is($paid_amount , -113 , "${title}: paid amount");
937 is($invoice->paid , 113 , "${title}: paid");
938 is($number_of_payments , 3 , "${title}: 3 AR_paid bookings");
939 is($total , 0 , "${title}: even balance");
942 sub test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_tax_included() {
943 my $title = 'default invoice, four items, 19/7% tax with_skonto_pt 4x25';
945 my $item1 = create_invoice_item(part => $parts[2], qty => 0.5);
946 my $item2 = create_invoice_item(part => $parts[3], qty => 0.5);
947 my $item3 = create_invoice_item(part => $parts[2], qty => 0.5);
948 my $item4 = create_invoice_item(part => $parts[3], qty => 0.5);
949 my $invoice = create_sales_invoice(
951 invoiceitems => [ $item1, $item2, $item3, $item4 ],
952 payment_id => $payment_terms->id,
956 my %params = ( chart_id => $bank_account->chart_id,
957 transdate => DateTime->today_local->to_kivitendo
960 $params{amount} = $invoice->amount_less_skonto;
961 $params{payment_type} = 'with_skonto_pt';
963 $invoice->pay_invoice( %params );
965 my ($number_of_payments, $paid_amount) = number_of_payments($invoice);
966 my $total = total_amount($invoice);
968 is($invoice->netamount, 88.75, "${title}: netamount");
969 is($invoice->amount, 100, "${title}: amount");
970 is($paid_amount, -100, "${title}: paid amount");
971 is($invoice->paid, 100, "${title}: paid");
972 is($number_of_payments, 3, "${title}: 3 AR_paid bookings");
974 local $TODO = "currently this test fails because the code writing the invoice is buggy, the calculation of skonto is correct";
975 is($total, 0, "${title}: even balance");
979 sub test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_multiple() {
980 my $title = 'default invoice, four items, 19/7% tax with_skonto_pt 4x25';
982 my $item1 = create_invoice_item(part => $parts[2], qty => 0.5);
983 my $item2 = create_invoice_item(part => $parts[3], qty => 0.5);
984 my $item3 = create_invoice_item(part => $parts[2], qty => 0.5);
985 my $item4 = create_invoice_item(part => $parts[3], qty => 0.5);
986 my $invoice = create_sales_invoice(
988 invoiceitems => [ $item1, $item2, $item3, $item4 ],
989 payment_id => $payment_terms->id,
992 $invoice->pay_invoice( amount => '90',
993 payment_type => 'without_skonto',
994 chart_id => $bank_account->chart_id,
995 transdate => DateTime->today_local->to_kivitendo
997 $invoice->pay_invoice( payment_type => 'difference_as_skonto',
998 chart_id => $bank_account->chart_id,
999 transdate => DateTime->today_local->to_kivitendo
1002 my ($number_of_payments, $paid_amount) = number_of_payments($invoice);
1003 my $total = total_amount($invoice);
1005 is($invoice->netamount, 100, "${title}: netamount");
1006 is($invoice->amount, 113, "${title}: amount");
1007 is($paid_amount, -113, "${title}: paid amount");
1008 is($invoice->paid, 113, "${title}: paid");
1009 is($number_of_payments, 3, "${title}: 3 AR_paid bookings");
1010 is($total, 0, "${title}: even balance: this will fail due to rounding error in invoice post, not the skonto");
1013 sub test_ar_currency_tax_not_included_and_payment {
1014 my $title = 'test_ar_currency_tax_not_included_and_payment_2';
1016 my $netamount = $::form->round_amount(75 * $exchangerate->sell,2); # 75 in CUR, 100.00 in EUR
1017 my $amount = $::form->round_amount($netamount * 1.19,2); # 100 in CUR, 119.00 in EUR
1018 my $invoice = SL::DB::Invoice->new(
1021 netamount => $netamount,
1022 transdate => $transdate1,
1024 customer_id => $customer->id,
1025 taxzone_id => $customer->taxzone_id,
1026 currency_id => $currency->id,
1028 notes => 'test_ar_currency_tax_not_included_and_payment',
1030 $invoice->add_ar_amount_row(
1031 amount => $invoice->netamount,
1032 chart => $ar_amount_chart,
1036 $invoice->create_ar_row(chart => $ar_chart);
1039 is(SL::DB::Manager::Invoice->get_all_count(where => [ invoice => 0 ]), 1, 'there is one ar transaction');
1040 is($invoice->currency_id , $currency->id , 'currency_id has been saved');
1041 is($invoice->netamount , 100 , 'ar amount has been converted');
1042 is($invoice->amount , 119 , 'ar amount has been converted');
1043 is($invoice->taxincluded , 0 , 'ar transaction doesn\'t have taxincluded');
1044 is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ar_amount_chart->id, trans_id => $invoice->id)->amount, '100.00000', $ar_amount_chart->accno . ': has been converted for currency');
1045 is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ar_chart->id, trans_id => $invoice->id)->amount, '-119.00000', $ar_chart->accno . ': has been converted for currency');
1047 $invoice->pay_invoice(chart_id => $bank->id,
1050 transdate => $transdate1->to_kivitendo,
1052 $invoice->pay_invoice(chart_id => $bank->id,
1055 transdate => $transdate1->to_kivitendo,
1057 # $invoice->pay_invoice(chart_id => $bank->id,
1059 # transdate => $transdate2->to_kivitendo,
1061 is(scalar @{$invoice->transactions}, 9, 'ar transaction has 9 transactions (incl. fxtransactions)');
1062 is($invoice->paid, $invoice->amount, 'ar transaction paid = amount in default currency');
1065 sub test_ar_currency_tax_included {
1066 my $title = 'test_ar_currency_tax_included';
1068 # we want the acc_trans amount to be 100
1069 my $amount = $::form->round_amount(75 * $exchangerate->sell * 1.19);
1070 my $netamount = $::form->round_amount($amount / 1.19,2);
1071 my $invoice = SL::DB::Invoice->new(
1075 transdate => $transdate1,
1077 customer_id => $customer->id,
1078 taxzone_id => $customer->taxzone_id,
1079 currency_id => $currency->id,
1080 notes => 'test_ar_currency_tax_included',
1083 $invoice->add_ar_amount_row( # should take care of taxincluded
1084 amount => $invoice->amount, # tax included in local currency
1085 chart => $ar_amount_chart,
1089 $invoice->create_ar_row( chart => $ar_chart );
1091 is(SL::DB::Manager::Invoice->get_all_count(where => [ invoice => 0 ]), 2, 'there are now two ar transactions');
1092 is($invoice->currency_id , $currency->id , 'currency_id has been saved');
1093 is($invoice->amount , $amount , 'amount ok');
1094 is($invoice->netamount , $netamount , 'netamount ok');
1095 is($invoice->taxincluded , 1 , 'ar transaction has taxincluded');
1096 is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ar_amount_chart->id, trans_id => $invoice->id)->amount, '100.00000', $ar_amount_chart->accno . ': has been converted for currency');
1097 is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ar_chart->id, trans_id => $invoice->id)->amount, '-119.00000', $ar_chart->accno . ': has been converted for currency');
1098 $invoice->pay_invoice(chart_id => $bank->id,
1101 transdate => $transdate1->to_kivitendo,
1106 sub test_ap_currency_tax_not_included_and_payment {
1107 my $title = 'test_ap_currency_tax_not_included_and_payment';
1109 my $netamount = $::form->round_amount(75 * $exchangerate->buy,2); # 75 in CUR, 100.00 in EUR
1110 my $amount = $::form->round_amount($netamount * 1.19,2); # 100 in CUR, 119.00 in EUR
1111 my $invoice = SL::DB::PurchaseInvoice->new(
1113 invnumber => 'test_ap_currency_tax_not_included_and_payment',
1115 netamount => $netamount,
1116 transdate => $transdate1,
1118 vendor_id => $vendor->id,
1119 taxzone_id => $vendor->taxzone_id,
1120 currency_id => $currency->id,
1122 notes => 'test_ap_currency_tax_not_included_and_payment',
1124 $invoice->add_ap_amount_row(
1125 amount => $invoice->netamount,
1126 chart => $ap_amount_chart,
1127 tax_id => $tax_9->id,
1130 $invoice->create_ap_row(chart => $ap_chart);
1133 is($invoice->currency_id, $currency->id, 'currency_id has been saved');
1134 is($invoice->netamount, 100, 'ap amount has been converted');
1135 is($invoice->amount, 119, 'ap amount has been converted');
1136 is($invoice->taxincluded, 0, 'ap transaction doesn\'t have taxincluded');
1137 is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ap_amount_chart->id, trans_id => $invoice->id)->amount, '-100.00000', $ap_amount_chart->accno . ': has been converted for currency');
1138 is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ap_chart->id, trans_id => $invoice->id)->amount, '119.00000', $ap_chart->accno . ': has been converted for currency');
1140 $invoice->pay_invoice(chart_id => $bank->id,
1143 transdate => $transdate1->to_kivitendo,
1145 $invoice->pay_invoice(chart_id => $bank->id,
1148 transdate => $transdate1->to_kivitendo,
1150 is(scalar @{$invoice->transactions}, 9, 'ap transaction has 9 transactions (incl. fxtransactions)');
1151 is($invoice->paid, $invoice->amount, 'ap transaction paid = amount in default currency');
1154 sub test_ap_currency_tax_included {
1155 my $title = 'test_ap_currency_tax_included';
1157 # we want the acc_trans amount to be 100
1158 my $amount = $::form->round_amount(75 * $exchangerate->buy * 1.19);
1159 my $netamount = $::form->round_amount($amount / 1.19,2);
1160 my $invoice = SL::DB::PurchaseInvoice->new(
1162 amount => 119, #$amount,
1163 netamount => 100, #$netamount,
1164 transdate => $transdate1,
1166 vendor_id => $vendor->id,
1167 taxzone_id => $vendor->taxzone_id,
1168 currency_id => $currency->id,
1169 notes => 'test_ap_currency_tax_included',
1170 invnumber => 'test_ap_currency_tax_included',
1173 $invoice->add_ap_amount_row( # should take care of taxincluded
1174 amount => $invoice->amount, # tax included in local currency
1175 chart => $ap_amount_chart,
1176 tax_id => $tax_9->id,
1179 $invoice->create_ap_row( chart => $ap_chart );
1181 is($invoice->currency_id , $currency->id , 'currency_id has been saved');
1182 is($invoice->amount , $amount , 'amount ok');
1183 is($invoice->netamount , $netamount , 'netamount ok');
1184 is($invoice->taxincluded , 1 , 'ap transaction has taxincluded');
1185 is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ap_amount_chart->id, trans_id => $invoice->id)->amount, '-100.00000', $ap_amount_chart->accno . ': has been converted for currency');
1186 is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ap_chart->id, trans_id => $invoice->id)->amount, '119.00000', $ap_chart->accno . ': has been converted for currency');
1188 $invoice->pay_invoice(chart_id => $bank->id,
1191 transdate => $transdate1->to_kivitendo,
1196 sub test_ar_currency_tax_not_included_and_payment_2 {
1197 my $title = 'test_ar_currency_tax_not_included_and_payment_2';
1199 my $netamount = $::form->round_amount(125 * $exchangerate2->sell,2); # 125.00 in CUR, 100.00 in EUR
1200 my $amount = $::form->round_amount($netamount * 1.19,2); # 148.75 in CUR, 119.00 in EUR
1201 my $invoice = SL::DB::Invoice->new(
1204 netamount => $netamount,
1205 transdate => $transdate2,
1207 customer_id => $customer->id,
1208 taxzone_id => $customer->taxzone_id,
1209 currency_id => $currency->id,
1211 notes => 'test_ar_currency_tax_not_included_and_payment 0.8',
1212 invnumber => 'test_ar_currency_tax_not_included_and_payment 0.8',
1214 $invoice->add_ar_amount_row(
1215 amount => $invoice->netamount,
1216 chart => $ar_amount_chart,
1220 $invoice->create_ar_row(chart => $ar_chart);
1223 is($invoice->currency_id , $currency->id , "$title: currency_id has been saved");
1224 is($invoice->netamount , 100 , "$title: ar amount has been converted");
1225 is($invoice->amount , 119 , "$title: ar amount has been converted");
1226 is($invoice->taxincluded , 0 , "$title: ar transaction doesn\"t have taxincluded");
1227 is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ar_amount_chart->id, trans_id => $invoice->id)->amount, '100.00000', $title . " " . $ar_amount_chart->accno . ": has been converted for currency");
1228 is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ar_chart->id, trans_id => $invoice->id)->amount, '-119.00000', $title . " " . $ar_chart->accno . ': has been converted for currency');
1230 $invoice->pay_invoice(chart_id => $bank->id,
1233 transdate => $transdate2->to_kivitendo,
1235 $invoice->pay_invoice(chart_id => $bank->id,
1238 transdate => $transdate3->to_kivitendo,
1240 $invoice->pay_invoice(chart_id => $bank->id,
1243 transdate => $transdate4->to_kivitendo,
1245 # $invoice->pay_invoice(chart_id => $bank->id,
1247 # transdate => $transdate2->to_kivitendo,
1249 my $fx_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, fx_transaction => 1 ], sort_by => ('acc_trans_id'));
1250 is(scalar @{$fx_transactions}, 3, "$title: ar transaction has 3 fx transactions");
1251 is($fx_transactions->[0]->amount, '24.69000', "$title fx transactions 1: 123.45-(123.45*0.8) = 24.69");
1253 is(scalar @{$invoice->transactions}, 14, "$title ar transaction has 14 transactions (incl. fxtransactions and fx_gain)");
1254 is($invoice->paid, $invoice->amount, "$title ar transaction paid = amount in default currency");
1257 sub test_ar_currency_tax_not_included_and_payment_2_credit_note {
1258 my $title = 'test_ar_currency_tax_not_included_and_payment_2_credit_note';
1260 my $netamount = $::form->round_amount(-125 * $exchangerate2->sell,2); # 125.00 in CUR, 100.00 in EUR
1261 my $amount = $::form->round_amount($netamount * 1.19,2); # 148.75 in CUR, 119.00 in EUR
1262 my $invoice = SL::DB::Invoice->new(
1265 netamount => $netamount,
1266 transdate => $transdate2,
1268 customer_id => $customer->id,
1269 taxzone_id => $customer->taxzone_id,
1270 currency_id => $currency->id,
1272 notes => 'test_ar_currency_tax_not_included_and_payment credit note 0.8',
1273 invnumber => 'test_ar_currency_tax_not_included_and_payment credit note 0.8',
1275 $invoice->add_ar_amount_row(
1276 amount => $invoice->netamount,
1277 chart => $ar_amount_chart,
1281 $invoice->create_ar_row(chart => $ar_chart);
1284 is($invoice->currency_id , $currency->id , 'currency_id has been saved');
1285 is($invoice->netamount , -100 , 'ar amount has been converted');
1286 is($invoice->amount , -119 , 'ar amount has been converted');
1287 is($invoice->taxincluded , 0 , 'ar transaction doesn\'t have taxincluded');
1288 is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ar_amount_chart->id, trans_id => $invoice->id)->amount, '-100.00000', $ar_amount_chart->accno . ': has been converted for currency');
1289 is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ar_chart->id, trans_id => $invoice->id)->amount, '119.00000', $ar_chart->accno . ': has been converted for currency');
1291 $invoice->pay_invoice(chart_id => $bank->id,
1294 transdate => $transdate2->to_kivitendo,
1296 $invoice->pay_invoice(chart_id => $bank->id,
1299 transdate => $transdate2->to_kivitendo,
1301 my $fx_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, fx_transaction => 1 ], sort_by => ('acc_trans_id'));
1302 is(scalar @{$fx_transactions}, 2, 'ar transaction has 2 fx transactions');
1303 is($fx_transactions->[0]->amount, '-24.69000', 'fx transactions 1: 123.45-(123.45*0.8) = 24.69');
1305 is(scalar @{$invoice->transactions}, 9, 'ar transaction has 9 transactions (incl. fxtransactions)');
1306 is($invoice->paid, $invoice->amount, 'ar transaction paid = amount in default currency');
1309 sub test_ap_currency_tax_not_included_and_payment_2 {
1310 my $title = 'test_ap_currency_tax_not_included_and_payment_2';
1312 my $netamount = $::form->round_amount(125 * $exchangerate2->sell,2); # 125.00 in CUR, 100.00 in EUR
1313 my $amount = $::form->round_amount($netamount * 1.19,2); # 148.75 in CUR, 119.00 in EUR
1314 my $invoice = SL::DB::PurchaseInvoice->new(
1317 netamount => $netamount,
1318 transdate => $transdate2,
1320 vendor_id => $vendor->id,
1321 taxzone_id => $vendor->taxzone_id,
1322 currency_id => $currency->id,
1324 notes => 'test_ap_currency_tax_not_included_and_payment_2 0.8 + 1.33333',
1325 invnumber => 'test_ap_currency_tax_not_included_and_payment_2 0.8 + 1.33333',
1327 $invoice->add_ap_amount_row(
1328 amount => $invoice->netamount,
1329 chart => $ap_amount_chart,
1330 tax_id => $tax_9->id,
1333 $invoice->create_ap_row(chart => $ap_chart);
1336 is($invoice->currency_id , $currency->id , "$title: currency_id has been saved");
1337 is($invoice->netamount , 100 , "$title: ap amount has been converted");
1338 is($invoice->amount , 119 , "$title: ap amount has been converted");
1339 is($invoice->taxincluded , 0 , "$title: ap transaction doesn\'t have taxincluded");
1340 is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ap_amount_chart->id, trans_id => $invoice->id)->amount, '-100.00000', $ap_amount_chart->accno . ': has been converted for currency');
1341 is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ap_chart->id, trans_id => $invoice->id)->amount, '119.00000', $ap_chart->accno . ': has been converted for currency');
1343 $invoice->pay_invoice(chart_id => $bank->id,
1346 transdate => $transdate2->to_kivitendo,
1348 $invoice->pay_invoice(chart_id => $bank->id,
1351 transdate => $transdate3->to_kivitendo,
1353 $invoice->pay_invoice(chart_id => $bank->id,
1356 transdate => $transdate4->to_kivitendo,
1358 my $fx_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, fx_transaction => 1 ], sort_by => ('acc_trans_id'));
1359 is(scalar @{$fx_transactions}, 3, "$title: ap transaction has 3 fx transactions");
1360 is($fx_transactions->[0]->amount, '-2.00000', "$title: fx transaction 1: 10.00-( 10.00*0.80000) = 2.00000");
1361 is($fx_transactions->[1]->amount, '68.59000', "$title: fx transaction 2: 123.45-(123.45*1.55557) = -68.58511");
1362 is($fx_transactions->[2]->amount, '-3.40000', "$title: fx transaction 3: 15.30-(15.30 *0.77777) = 3.40012");
1364 my $fx_loss_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, chart_id => $fxloss_chart->id ], sort_by => ('acc_trans_id'));
1365 my $fx_gain_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, chart_id => $fxgain_chart->id ], sort_by => ('acc_trans_id'));
1366 is($fx_gain_transactions->[0]->amount, '0.34000', "$title: fx gain amount ok");
1367 is($fx_loss_transactions->[0]->amount, '-93.28000', "$title: fx loss amount ok");
1369 is(scalar @{$invoice->transactions}, 14, "$title: ap transaction has 14 transactions (incl. fxtransactions and gain_loss)");
1370 is($invoice->paid, $invoice->amount, "$title: ap transaction paid = amount in default currency");
1371 is(total_amount($invoice), 0, "$title: even balance");
1374 sub test_ap_currency_tax_not_included_and_payment_2_credit_note {
1375 my $title = 'test_ap_currency_tax_not_included_and_payment_2_credit_note';
1377 my $netamount = $::form->round_amount(-125 * $exchangerate2->sell,2); # 125.00 in CUR, 100.00 in EUR
1378 my $amount = $::form->round_amount($netamount * 1.19,2); # 148.75 in CUR, 119.00 in EUR
1379 my $invoice = SL::DB::PurchaseInvoice->new(
1382 netamount => $netamount,
1383 transdate => $transdate2,
1385 vendor_id => $vendor->id,
1386 taxzone_id => $vendor->taxzone_id,
1387 currency_id => $currency->id,
1389 notes => 'test_ap_currency_tax_not_included_and_payment credit note 0.8 + 1.33333',
1390 invnumber => 'test_ap_currency_tax_not_included_and_payment credit note 0.8 + 1.33333',
1392 $invoice->add_ap_amount_row(
1393 amount => $invoice->netamount,
1394 chart => $ap_amount_chart,
1395 tax_id => $tax_9->id,
1398 $invoice->create_ap_row(chart => $ap_chart);
1401 is($invoice->currency_id , $currency->id , "$title: currency_id has been saved");
1402 is($invoice->netamount , -100 , "$title: ap amount has been converted");
1403 is($invoice->amount , -119 , "$title: ap amount has been converted");
1404 is($invoice->taxincluded , 0 , "$title: ap transaction doesn\'t have taxincluded");
1405 is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ap_amount_chart->id, trans_id => $invoice->id)->amount, '100.00000', $ap_amount_chart->accno . ': has been converted for currency');
1406 is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ap_chart->id, trans_id => $invoice->id)->amount, '-119.00000', $ap_chart->accno . ': has been converted for currency');
1408 $invoice->pay_invoice(chart_id => $bank->id,
1411 transdate => $transdate2->to_kivitendo,
1413 $invoice->pay_invoice(chart_id => $bank->id,
1416 transdate => $transdate3->to_kivitendo,
1418 $invoice->pay_invoice(chart_id => $bank->id,
1421 transdate => $transdate4->to_kivitendo,
1423 my $fx_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, fx_transaction => 1 ], sort_by => ('acc_trans_id'));
1424 is(scalar @{$fx_transactions}, 3, "$title: ap transaction has 3 fx transactions");
1425 is($fx_transactions->[0]->amount, '2.00000', "$title: fx transaction 1: 10.00-( 10.00*0.80000) = 2.00000");
1426 is($fx_transactions->[1]->amount, '-68.59000', "$title: fx transaction 2: 123.45-(123.45*1.55557) = -68.58511");
1427 is($fx_transactions->[2]->amount, '3.40000', "$title: fx transaction 3: 15.30-(15.30 *0.77777) = 3.40012");
1429 my $fx_gain_loss_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, chart_id => $fxgain_chart->id ], sort_by => ('acc_trans_id'));
1430 is($fx_gain_loss_transactions->[0]->amount, '93.28000', "$title: fx gain loss amount ok");
1432 is(scalar @{$invoice->transactions}, 14, "$title: ap transaction has 14 transactions (incl. fxtransactions and gain_loss)");
1433 is($invoice->paid, $invoice->amount, "$title: ap transaction paid = amount in default currency");
1434 is(total_amount($invoice), 0, "$title: even balance");
1437 sub test_credit_note_two_items_19_7_tax_tax_not_included {
1438 my $title = 'test_credit_note_two_items_19_7_tax_tax_not_included';
1440 my $item1 = create_invoice_item(part => $parts[0], qty => 5);
1441 my $item2 = create_invoice_item(part => $parts[1], qty => 3);
1442 my $invoice = create_credit_note(
1445 invoiceitems => [ $item1, $item2 ],
1449 my %params = ( chart_id => $bank_account->chart_id,
1450 transdate => DateTime->today_local->to_kivitendo,
1453 $params{amount} = $invoice->amount,
1455 $invoice->pay_invoice( %params );
1457 my ($number_of_payments, $paid_amount) = number_of_payments($invoice);
1458 my $total = total_amount($invoice);
1460 is($invoice->netamount, -40.84, "${title}: netamount");
1461 is($invoice->amount, -45.10, "${title}: amount");
1462 is($paid_amount, 45.10, "${title}: paid amount according to acc_trans is positive (Haben)");
1463 is($invoice->paid, -45.10, "${title}: paid");
1464 is($number_of_payments, 1, "${title}: 1 AR_paid bookings");
1465 is($total, 0, "${title}: even balance");