1 use Test::More tests => 211;
9 use Support::TestSetup;
11 use List::Util qw(sum);
13 use SL::DB::AccTransaction;
14 use SL::DB::BankTransactionAccTrans;
15 use SL::DB::Buchungsgruppe;
23 use SL::DB::BankAccount;
24 use SL::DB::PaymentTerm;
25 use SL::DB::PurchaseInvoice;
26 use SL::DB::BankTransaction;
27 use SL::Controller::BankTransaction;
28 use SL::Dev::ALL qw(:ALL);
31 my ($customer, $vendor, $currency_id, $unit, $tax, $tax0, $tax7, $tax_9, $payment_terms, $bank_account);
32 my ($transdate1, $transdate2, $currency);
33 my ($ar_chart,$bank,$ar_amount_chart, $ap_chart, $ap_amount_chart);
34 my ($ar_transaction, $ap_transaction);
38 SL::DB::Manager::BankTransactionAccTrans->delete_all(all => 1);
39 SL::DB::Manager::BankTransaction->delete_all(all => 1);
40 SL::DB::Manager::InvoiceItem->delete_all(all => 1);
41 SL::DB::Manager::InvoiceItem->delete_all(all => 1);
42 SL::DB::Manager::Invoice->delete_all(all => 1);
43 SL::DB::Manager::PurchaseInvoice->delete_all(all => 1);
44 SL::DB::Manager::Part->delete_all(all => 1);
45 SL::DB::Manager::Customer->delete_all(all => 1);
46 SL::DB::Manager::Vendor->delete_all(all => 1);
47 SL::DB::Manager::SepaExportItem->delete_all(all => 1);
48 SL::DB::Manager::SepaExport->delete_all(all => 1);
49 SL::DB::Manager::BankAccount->delete_all(all => 1);
50 SL::DB::Manager::PaymentTerm->delete_all(all => 1);
51 SL::DB::Manager::Currency->delete_all(where => [ name => 'CUR' ]);
56 sub save_btcontroller_to_string {
58 open(my $outputFH, '>', \$output) or die;
59 my $oldFH = select $outputFH;
61 $bt_controller = SL::Controller::BankTransaction->new;
62 $bt_controller->action_save_invoices;
70 Support::TestSetup::login();
73 reset_state(); # initialise customers/vendors/bank/currency/...
77 test_overpayment_with_partialpayment();
82 test_partial_payment();
84 test_ap_transaction();
85 test_neg_ap_transaction(invoice => 0);
86 test_neg_ap_transaction(invoice => 1);
87 test_ap_payment_transaction();
88 test_ap_payment_part_transaction();
89 test_neg_sales_invoice();
90 test_two_neg_ap_transaction();
91 test_one_inv_and_two_invoices_with_skonto_exact();
100 test_two_banktransactions();
101 # remove all created data at end of test
106 ###### functions for setting up data
111 $params{$_} ||= {} for qw(unit customer tax vendor);
115 $transdate1 = DateTime->today;
116 $transdate2 = DateTime->today->add(days => 5);
118 $tax = SL::DB::Manager::Tax->find_by(taxkey => 3, rate => 0.19, %{ $params{tax} }) || croak "No tax";
119 $tax7 = SL::DB::Manager::Tax->find_by(taxkey => 2, rate => 0.07) || croak "No tax for 7\%";
120 $tax_9 = SL::DB::Manager::Tax->find_by(taxkey => 9, rate => 0.19, %{ $params{tax} }) || croak "No tax for 19\%";
121 $tax0 = SL::DB::Manager::Tax->find_by(taxkey => 0, rate => 0.0) || croak "No tax for 0\%";
123 $currency_id = $::instance_conf->get_currency_id;
125 $bank_account = SL::DB::BankAccount->new(
126 account_number => '123',
131 chart_id => SL::DB::Manager::Chart->find_by(description => 'Bank')->id,
132 name => SL::DB::Manager::Chart->find_by(description => 'Bank')->description,
135 $customer = new_customer(
136 name => 'Test Customer OLÉ S.L. Årdbärg AB',
137 iban => 'DE12500105170648489890',
139 account_number => '648489890',
140 mandate_date_of_signature => $transdate1,
141 mandator_id => 'foobar',
143 bank_code => 'G1235',
144 depositor => 'Test Customer',
145 customernumber => 'CUST1704',
148 $payment_terms = create_payment_terms();
150 $vendor = new_vendor(
151 name => 'Test Vendor',
152 payment_id => $payment_terms->id,
153 iban => 'DE12500105170648489890',
155 account_number => '648489890',
157 bank_code => 'G1235',
158 depositor => 'Test Vendor',
159 vendornumber => 'VEND1704',
162 $ar_chart = SL::DB::Manager::Chart->find_by( accno => '1400' ); # Forderungen
163 $ap_chart = SL::DB::Manager::Chart->find_by( accno => '1600' ); # Verbindlichkeiten
164 $bank = SL::DB::Manager::Chart->find_by( accno => '1200' ); # Bank
165 $ar_amount_chart = SL::DB::Manager::Chart->find_by( accno => '8400' ); # Erlöse
166 $ap_amount_chart = SL::DB::Manager::Chart->find_by( accno => '3400' ); # Wareneingang 19%
170 sub test_ar_transaction {
172 my $netamount = $params{amount} || 100;
173 my $amount = $::form->round_amount($netamount * 1.19,2);
174 my $invoice = SL::DB::Invoice->new(
176 invnumber => $params{invnumber} || undef, # let it use its own invnumber
178 netamount => $netamount,
179 transdate => $transdate1,
180 taxincluded => $params{taxincluded } || 0,
181 customer_id => $customer->id,
182 taxzone_id => $customer->taxzone_id,
183 currency_id => $currency_id,
185 payment_id => $params{payment_id} || undef,
186 notes => 'test_ar_transaction',
188 $invoice->add_ar_amount_row(
189 amount => $invoice->netamount,
190 chart => $ar_amount_chart,
191 tax_id => $params{tax_id} || $tax->id,
194 $invoice->create_ar_row(chart => $ar_chart);
197 is($invoice->currency_id , $currency_id , 'currency_id has been saved');
198 is($invoice->netamount , $netamount , 'ar amount has been converted');
199 is($invoice->amount , $amount , 'ar amount has been converted');
200 is($invoice->taxincluded , 0 , 'ar transaction doesn\'t have taxincluded');
202 if ( $netamount == 100 ) {
203 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');
204 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');
209 sub test_ap_transaction {
211 my $testname = 'test_ap_transaction';
214 my $amount = $::form->round_amount($netamount * 1.19,2);
215 my $invoice = SL::DB::PurchaseInvoice->new(
217 invnumber => $params{invnumber} || $testname,
219 netamount => $netamount,
220 transdate => $transdate1,
222 vendor_id => $vendor->id,
223 taxzone_id => $vendor->taxzone_id,
224 currency_id => $currency_id,
226 notes => 'test_ap_transaction',
228 $invoice->add_ap_amount_row(
229 amount => $invoice->netamount,
230 chart => $ap_amount_chart,
231 tax_id => $params{tax_id} || $tax_9->id,
234 $invoice->create_ap_row(chart => $ap_chart);
237 is($invoice->currency_id , $currency_id , "$testname: currency_id has been saved");
238 is($invoice->netamount , 100 , "$testname: ap amount has been converted");
239 is($invoice->amount , 119 , "$testname: ap amount has been converted");
240 is($invoice->taxincluded , 0 , "$testname: ap transaction doesn\'t have taxincluded");
242 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');
243 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');
252 my $testname = 'test1';
254 $ar_transaction = test_ar_transaction(invnumber => 'salesinv1');
256 my $bt = create_bank_transaction(record => $ar_transaction) or die "Couldn't create bank_transaction";
258 $::form->{invoice_ids} = {
259 $bt->id => [ $ar_transaction->id ]
262 save_btcontroller_to_string();
264 $ar_transaction->load;
266 is($ar_transaction->paid , '119.00000' , "$testname: salesinv1 was paid");
267 is($ar_transaction->closed , 1 , "$testname: salesinv1 is closed");
268 is($bt->invoice_amount , '119.00000' , "$testname: bt invoice amount was assigned");
272 sub test_skonto_exact {
274 my $testname = 'test_skonto_exact';
276 $ar_transaction = test_ar_transaction(invnumber => 'salesinv skonto',
277 payment_id => $payment_terms->id,
280 my $bt = create_bank_transaction(record => $ar_transaction,
281 bank_chart_id => $bank->id,
282 amount => $ar_transaction->amount_less_skonto
283 ) or die "Couldn't create bank_transaction";
285 $::form->{invoice_ids} = {
286 $bt->id => [ $ar_transaction->id ]
288 $::form->{invoice_skontos} = {
289 $bt->id => [ 'with_skonto_pt' ]
292 save_btcontroller_to_string();
294 $ar_transaction->load;
296 is($ar_transaction->paid , '119.00000' , "$testname: salesinv skonto was paid");
297 is($ar_transaction->closed , 1 , "$testname: salesinv skonto is closed");
298 is($bt->invoice_amount , '113.05000' , "$testname: bt invoice amount was assigned");
304 my $testname = 'test_rollback_error';
305 # without type with_free_skonto the helper function (Payment.pm) looks ugly but not
308 $ar_transaction = test_ar_transaction(invnumber => 'salesinv skonto',
309 payment_id => $payment_terms->id,
311 amount => 168.58 / 1.19,
314 my $bt = create_bank_transaction(record => $ar_transaction,
315 bank_chart_id => $bank->id,
317 ) or die "Couldn't create bank_transaction";
318 $::form->{invoice_ids} = {
319 $bt->id => [ $ar_transaction->id ]
321 $::form->{invoice_skontos} = {
322 $bt->id => [ 'with_skonto_pt' ]
325 is($ar_transaction->paid , '0' , "$testname: salesinv is not paid");
327 # generate an error for testing rollback mechanism
328 my $saved_skonto_sales_chart_id = $tax->skonto_sales_chart_id;
329 $tax->skonto_sales_chart_id(undef);
332 save_btcontroller_to_string();
333 my @bt_errors = @{ $bt_controller->problems };
334 is(substr($bt_errors[0]->{message},0,38), 'Kein Skontokonto für Steuerschlüssel 3', "$testname: Fehlermeldung ok");
336 $tax->skonto_sales_chart_id($saved_skonto_sales_chart_id);
339 $ar_transaction->load;
341 is($ar_transaction->paid , '0.00000' , "$testname: salesinv was not paid");
342 is($bt->invoice_amount , '0.00000' , "$testname: bt invoice amount was not assigned");
346 sub test_two_invoices {
348 my $testname = 'test_two_invoices';
350 my $ar_transaction_1 = test_ar_transaction(invnumber => 'salesinv_1');
351 my $ar_transaction_2 = test_ar_transaction(invnumber => 'salesinv_2');
353 my $bt = create_bank_transaction(record => $ar_transaction_1,
354 amount => ($ar_transaction_1->amount + $ar_transaction_2->amount),
355 purpose => "Rechnungen " . $ar_transaction_1->invnumber . " und " . $ar_transaction_2->invnumber,
356 bank_chart_id => $bank->id,
357 ) or die "Couldn't create bank_transaction";
359 my ($agreement, $rule_matches) = $bt->get_agreement_with_invoice($ar_transaction_1);
360 is($agreement, 16, "points for ar_transaction_1 in test_two_invoices ok");
362 $::form->{invoice_ids} = {
363 $bt->id => [ $ar_transaction_1->id, $ar_transaction_2->id ]
366 save_btcontroller_to_string();
368 $ar_transaction_1->load;
369 $ar_transaction_2->load;
372 is($ar_transaction_1->paid , '119.00000' , "$testname: salesinv_1 wcsv_import_reportsas paid");
373 is($ar_transaction_1->closed , 1 , "$testname: salesinv_1 is closed");
374 is($ar_transaction_2->paid , '119.00000' , "$testname: salesinv_2 was paid");
375 is($ar_transaction_2->closed , 1 , "$testname: salesinv_2 is closed");
376 is($bt->invoice_amount , '238.00000' , "$testname: bt invoice amount was assigned");
380 sub test_one_inv_and_two_invoices_with_skonto_exact {
382 my $testname = 'test_two_invoices_with_skonto_exact';
384 my $ar_transaction_1 = test_ar_transaction(invnumber => 'salesinv 1 skonto',
385 payment_id => $payment_terms->id,
387 my $ar_transaction_2 = test_ar_transaction(invnumber => 'salesinv 2 skonto',
388 payment_id => $payment_terms->id,
390 my $ar_transaction_3 = test_ar_transaction(invnumber => 'salesinv 3 no skonto');
394 my $bt = create_bank_transaction(record => $ar_transaction_1,
395 bank_chart_id => $bank->id,
396 amount => $ar_transaction_1->amount_less_skonto * 2 + $ar_transaction_3->amount
397 ) or die "Couldn't create bank_transaction";
399 $::form->{invoice_ids} = {
400 $bt->id => [ $ar_transaction_1->id, $ar_transaction_3->id, $ar_transaction_2->id]
402 $::form->{invoice_skontos} = {
403 $bt->id => [ 'with_skonto_pt', 'without_skonto', 'with_skonto_pt' ]
406 save_btcontroller_to_string();
408 $ar_transaction_1->load;
409 $ar_transaction_2->load;
410 $ar_transaction_3->load;
411 my $skonto_1 = SL::DB::Manager::AccTransaction->find_by(trans_id => $ar_transaction_1->id, chart_id => 162);
412 my $skonto_2 = SL::DB::Manager::AccTransaction->find_by(trans_id => $ar_transaction_2->id, chart_id => 162);
414 is($skonto_1->amount , '-5.95000' , "$testname: salesinv 1 skonto was booked");
415 is($skonto_2->amount , '-5.95000' , "$testname: salesinv 2 skonto was booked");
416 is($ar_transaction_1->paid , '119.00000' , "$testname: salesinv 1 was paid");
417 is($ar_transaction_2->paid , '119.00000' , "$testname: salesinv 2 was paid");
418 is($ar_transaction_3->paid , '119.00000' , "$testname: salesinv 3 was paid");
419 is($ar_transaction_1->closed , 1 , "$testname: salesinv 1 skonto is closed");
420 is($ar_transaction_2->closed , 1 , "$testname: salesinv 2 skonto is closed");
421 is($ar_transaction_3->closed , 1 , "$testname: salesinv 2 skonto is closed");
422 is($bt->invoice_amount , '345.10000' , "$testname: bt invoice amount was assigned");
426 sub test_overpayment {
428 my $testname = 'test_overpayment';
430 $ar_transaction = test_ar_transaction(invnumber => 'salesinv overpaid');
433 my $bt = create_bank_transaction(record => $ar_transaction,
434 bank_chart_id => $bank->id,
436 ) or die "Couldn't create bank_transaction";
438 $::form->{invoice_ids} = {
439 $bt->id => [ $ar_transaction->id ]
442 save_btcontroller_to_string();
444 $ar_transaction->load;
447 is($ar_transaction->paid , '119.00000' , "$testname: 'salesinv overpaid' was not overpaid");
448 is($bt->invoice_amount , '119.00000' , "$testname: bt invoice amount was not fully assigned with the overpaid amount");
449 { local $TODO = 'this currently fails because closed ignores over-payments, see commit d90966c7';
450 is($ar_transaction->closed , 0 , "$testname: 'salesinv overpaid' is open (via 'closed' method')");
452 is($ar_transaction->open_amount == 0 ? 1 : 0 , 1 , "$testname: 'salesinv overpaid is closed (via amount-paid)");
456 sub test_overpayment_with_partialpayment {
458 # two payments on different days, 10 and 119. If there is only one invoice we
459 # don't want it to be overpaid.
460 my $testname = 'test_overpayment_with_partialpayment';
462 $ar_transaction = test_ar_transaction(invnumber => 'salesinv overpaid partial');
464 my $bt_1 = create_bank_transaction(record => $ar_transaction,
465 bank_chart_id => $bank->id,
467 ) or die "Couldn't create bank_transaction";
468 my $bt_2 = create_bank_transaction(record => $ar_transaction,
470 transdate => DateTime->today->add(days => 5),
471 bank_chart_id => $bank->id,
472 ) or die "Couldn't create bank_transaction";
474 $::form->{invoice_ids} = {
475 $bt_1->id => [ $ar_transaction->id ]
477 save_btcontroller_to_string();
480 is($bt_1->invoice_amount , '10.00000' , "$testname: bt_1 invoice amount was fully assigned");
481 $::form->{invoice_ids} = {
482 $bt_2->id => [ $ar_transaction->id ]
484 save_btcontroller_to_string();
486 $ar_transaction->load;
489 is($bt_1->invoice_amount , '10.00000' , "$testname: bt_1 invoice amount was fully assigned");
490 is($ar_transaction->paid , '119.00000' , "$testname: 'salesinv overpaid partial' was not overpaid");
491 is($bt_2->invoice_amount , '109.00000' , "$testname: bt_2 invoice amount was partly assigned");
495 sub test_partial_payment {
497 my $testname = 'test_partial_payment';
499 $ar_transaction = test_ar_transaction(invnumber => 'salesinv partial payment');
502 my $bt = create_bank_transaction(record => $ar_transaction,
503 bank_chart_id => $bank->id,
505 ) or die "Couldn't create bank_transaction";
507 $::form->{invoice_ids} = {
508 $bt->id => [ $ar_transaction->id ]
511 save_btcontroller_to_string();
513 $ar_transaction->load;
516 is($ar_transaction->paid , '100.00000' , "$testname: 'salesinv partial payment' was partially paid");
517 is($bt->invoice_amount , '100.00000' , "$testname: bt invoice amount was assigned partially paid amount");
521 sub test_credit_note {
523 my $testname = 'test_credit_note';
525 my $part1 = new_part( partnumber => 'T4254')->save;
526 my $part2 = new_service(partnumber => 'Serv1')->save;
527 my $credit_note = create_credit_note(
529 customer => $customer,
531 invoiceitems => [ create_invoice_item(part => $part1, qty => 3, sellprice => 70),
532 create_invoice_item(part => $part2, qty => 10, sellprice => 50),
535 my $bt = create_bank_transaction(record => $credit_note,
536 amount => $credit_note->amount,
537 bank_chart_id => $bank->id,
538 transdate => DateTime->today->add(days => 10),
540 my ($agreement, $rule_matches) = $bt->get_agreement_with_invoice($credit_note);
541 is($agreement, 13, "points for credit note ok");
542 is($rule_matches, 'remote_account_number(3) exact_amount(4) wrong_sign(-1) depositor_matches(2) remote_name(2) payment_within_30_days(1) datebonus14(2) ', "rules_matches for credit note ok");
544 $::form->{invoice_ids} = {
545 $bt->id => [ $credit_note->id ]
548 save_btcontroller_to_string();
552 is($credit_note->amount , '-844.90000', "$testname: amount ok");
553 is($credit_note->netamount, '-710.00000', "$testname: netamount ok");
554 is($credit_note->paid , '-844.90000', "$testname: paid ok");
557 sub test_neg_ap_transaction {
559 my $testname = 'test_neg_ap_transaction' . $params{invoice} ? ' invoice booking' : ' credit booking';
561 my $amount = $::form->round_amount($netamount * 1.19,2);
562 my $invoice = SL::DB::PurchaseInvoice->new(
563 invoice => $params{invoice} // 0,
564 invnumber => $params{invnumber} || 'test_neg_ap_transaction',
566 netamount => $netamount,
567 transdate => $transdate1,
569 vendor_id => $vendor->id,
570 taxzone_id => $vendor->taxzone_id,
571 currency_id => $currency_id,
573 notes => 'test_neg_ap_transaction',
575 $invoice->add_ap_amount_row(
576 amount => $invoice->netamount,
577 chart => $ap_amount_chart,
578 tax_id => $tax_9->id,
581 $invoice->create_ap_row(chart => $ap_chart);
584 is($invoice->netamount, -20 , "$testname: netamount ok");
585 is($invoice->amount , -23.8, "$testname: amount ok");
587 my $bt = create_bank_transaction(record => $invoice,
588 amount => $invoice->amount,
589 bank_chart_id => $bank->id,
590 transdate => DateTime->today->add(days => 10),
593 my ($agreement, $rule_matches) = $bt->get_agreement_with_invoice($invoice);
594 is($agreement, 15, "points for negative ap transaction ok");
596 $::form->{invoice_ids} = {
597 $bt->id => [ $invoice->id ]
600 save_btcontroller_to_string();
605 is($invoice->amount , '-23.80000', "$testname: amount ok");
606 is($invoice->netamount, '-20.00000', "$testname: netamount ok");
607 is($invoice->paid , '-23.80000', "$testname: paid ok");
608 is($bt->invoice_amount, '23.80000', "$testname: bt invoice amount for ap was assigned");
609 is($bt->amount, '23.80000', "$testname: bt amount for ap was assigned");
613 sub test_two_neg_ap_transaction {
614 my $testname='test_two_neg_ap_transaction';
616 my $amount = $::form->round_amount($netamount * 1.19,2);
617 my $invoice = SL::DB::PurchaseInvoice->new(
619 invnumber => 'test_neg_ap_transaction',
621 netamount => $netamount,
622 transdate => $transdate1,
624 vendor_id => $vendor->id,
625 taxzone_id => $vendor->taxzone_id,
626 currency_id => $currency_id,
628 notes => 'test_neg_ap_transaction',
630 $invoice->add_ap_amount_row(
631 amount => $invoice->netamount,
632 chart => $ap_amount_chart,
633 tax_id => $tax_9->id,
636 $invoice->create_ap_row(chart => $ap_chart);
639 is($invoice->netamount, -20 , "$testname: netamount ok");
640 is($invoice->amount , -23.8, "$testname: amount ok");
642 my $netamount_two = -1.14;
643 my $amount_two = $::form->round_amount($netamount_two * 1.19,2);
644 my $invoice_two = SL::DB::PurchaseInvoice->new(
646 invnumber => 'test_neg_ap_transaction_two',
647 amount => $amount_two,
648 netamount => $netamount_two,
649 transdate => $transdate1,
651 vendor_id => $vendor->id,
652 taxzone_id => $vendor->taxzone_id,
653 currency_id => $currency_id,
655 notes => 'test_neg_ap_transaction_two',
657 $invoice_two->add_ap_amount_row(
658 amount => $invoice_two->netamount,
659 chart => $ap_amount_chart,
660 tax_id => $tax_9->id,
663 $invoice_two->create_ap_row(chart => $ap_chart);
666 is($invoice_two->netamount, -1.14 , "$testname: netamount ok");
667 is($invoice_two->amount , -1.36, "$testname: amount ok");
670 my $bt = create_bank_transaction(record => $invoice_two,
671 amount => $invoice_two->amount + $invoice->amount,
672 bank_chart_id => $bank->id,
673 transdate => DateTime->today->add(days => 10),
675 # my ($agreement, $rule_matches) = $bt->get_agreement_with_invoice($invoice_two);
676 # is($agreement, 15, "points for negative ap transaction ok");
678 $::form->{invoice_ids} = {
679 $bt->id => [ $invoice->id, $invoice_two->id ]
682 save_btcontroller_to_string();
688 is($invoice->amount , '-23.80000', "$testname: first inv amount ok");
689 is($invoice->netamount, '-20.00000', "$testname: first inv netamount ok");
690 is($invoice->paid , '-23.80000', "$testname: first inv paid ok");
691 is($invoice_two->amount , '-1.36000', "$testname: second inv amount ok");
692 is($invoice_two->netamount, '-1.14000', "$testname: second inv netamount ok");
693 is($invoice_two->paid , '-1.36000', "$testname: second inv paid ok");
694 is($bt->invoice_amount, '25.16000', "$testname: bt invoice amount for both invoices were assigned");
697 return ($invoice, $invoice_two);
700 sub test_ap_payment_transaction {
702 my $testname = 'test_ap_payment_transaction';
704 my $amount = $::form->round_amount($netamount * 1.19,2);
705 my $invoice = SL::DB::PurchaseInvoice->new(
707 invnumber => $params{invnumber} || $testname,
709 netamount => $netamount,
710 transdate => $transdate1,
712 vendor_id => $vendor->id,
713 taxzone_id => $vendor->taxzone_id,
714 currency_id => $currency_id,
718 $invoice->add_ap_amount_row(
719 amount => $invoice->netamount,
720 chart => $ap_amount_chart,
721 tax_id => $tax_9->id,
724 $invoice->create_ap_row(chart => $ap_chart);
727 is($invoice->netamount, 115 , "$testname: netamount ok");
728 is($invoice->amount , 136.85, "$testname: amount ok");
730 my $bt = create_bank_transaction(record => $invoice,
731 amount => $invoice->amount,
732 bank_chart_id => $bank->id,
733 transdate => DateTime->today->add(days => 10),
735 $::form->{invoice_ids} = {
736 $bt->id => [ $invoice->id ]
739 save_btcontroller_to_string();
744 is($invoice->amount , '136.85000', "$testname: amount ok");
745 is($invoice->netamount, '115.00000', "$testname: netamount ok");
746 is($bt->amount, '-136.85000', "$testname: bt amount ok");
747 is($invoice->paid , '136.85000', "$testname: paid ok");
748 is($bt->invoice_amount, '-136.85000', "$testname: bt invoice amount for ap was assigned");
753 sub test_ap_payment_part_transaction {
755 my $testname = 'test_ap_payment_p_transaction';
757 my $amount = $::form->round_amount($netamount * 1.19,2);
758 my $invoice = SL::DB::PurchaseInvoice->new(
760 invnumber => $params{invnumber} || $testname,
762 netamount => $netamount,
763 transdate => $transdate1,
765 vendor_id => $vendor->id,
766 taxzone_id => $vendor->taxzone_id,
767 currency_id => $currency_id,
771 $invoice->add_ap_amount_row(
772 amount => $invoice->netamount,
773 chart => $ap_amount_chart,
774 tax_id => $tax_9->id,
777 $invoice->create_ap_row(chart => $ap_chart);
780 is($invoice->netamount, 115 , "$testname: netamount ok");
781 is($invoice->amount , 136.85, "$testname: amount ok");
783 my $bt = create_bank_transaction(record => $invoice,
784 amount => $invoice->amount-100,
785 bank_chart_id => $bank->id,
786 transdate => DateTime->today->add(days => 10),
788 $::form->{invoice_ids} = {
789 $bt->id => [ $invoice->id ]
792 save_btcontroller_to_string();
797 is($invoice->amount , '136.85000', "$testname: amount ok");
798 is($invoice->netamount, '115.00000', "$testname: netamount ok");
799 is($bt->amount, '-36.85000', "$testname: bt amount ok");
800 is($invoice->paid , '36.85000', "$testname: paid ok");
801 is($bt->invoice_amount, '-36.85000', "$testname: bt invoice amount for ap was assigned");
803 my $bt2 = create_bank_transaction(record => $invoice,
805 bank_chart_id => $bank->id,
806 transdate => DateTime->today->add(days => 10),
808 $::form->{invoice_ids} = {
809 $bt2->id => [ $invoice->id ]
812 save_btcontroller_to_string();
816 is($invoice->amount , '136.85000', "$testname: amount ok");
817 is($invoice->netamount, '115.00000', "$testname: netamount ok");
818 is($bt2->amount, '-100.00000',"$testname: bt amount ok");
819 is($invoice->paid , '136.85000', "$testname: paid ok");
820 is($bt2->invoice_amount,'-100.00000', "$testname: bt invoice amount for ap was assigned");
825 sub test_neg_sales_invoice {
827 my $testname = 'test_neg_sales_invoice';
829 my $part1 = new_part( partnumber => 'Funkenhaube öhm')->save;
830 my $part2 = new_service(partnumber => 'Service-Pauschale Pasch!')->save;
832 my $neg_sales_inv = create_sales_invoice(
833 invnumber => '20172201',
834 customer => $customer,
836 invoiceitems => [ create_invoice_item(part => $part1, qty => 3, sellprice => 70),
837 create_invoice_item(part => $part2, qty => 10, sellprice => -50),
840 my $bt = create_bank_transaction(record => $neg_sales_inv,
841 amount => $neg_sales_inv->amount,
842 bank_chart_id => $bank->id,
843 transdate => DateTime->today,
845 $::form->{invoice_ids} = {
846 $bt->id => [ $neg_sales_inv->id ]
849 save_btcontroller_to_string();
851 $neg_sales_inv->load;
853 is($neg_sales_inv->amount , '-345.10000', "$testname: amount ok");
854 is($neg_sales_inv->netamount, '-290.00000', "$testname: netamount ok");
855 is($neg_sales_inv->paid , '-345.10000', "$testname: paid ok");
856 is($bt->amount , '-345.10000', "$testname: bt amount ok");
857 is($bt->invoice_amount , '-345.10000', "$testname: bt invoice_amount ok");
862 my $testname = 'test_bt_rule1';
864 $ar_transaction = test_ar_transaction(invnumber => 'bt_rule1');
866 my $bt = create_bank_transaction(record => $ar_transaction) or die "Couldn't create bank_transaction";
868 $ar_transaction->load;
870 is($ar_transaction->paid , '0.00000' , "$testname: not paid");
871 is($bt->invoice_amount , '0.00000' , "$testname: bt invoice amount was not assigned");
873 my $bt_controller = SL::Controller::BankTransaction->new;
874 $::form->{dont_render_for_test} = 1;
875 $::form->{filter}{bank_account} = $bank_account->id;
876 my ( $bt_transactions, $proposals ) = $bt_controller->action_list;
878 is(scalar(@$bt_transactions) , 1 , "$testname: one bank_transaction");
879 is($bt_transactions->[0]->{agreement}, 20 , "$testname: agreement == 20");
880 my $match = join ( ' ',@{$bt_transactions->[0]->{rule_matches}});
881 #print "rule_matches='".$match."'\n";
883 "remote_account_number(3) exact_amount(4) own_invoice_in_purpose(5) depositor_matches(2) remote_name(2) payment_within_30_days(1) datebonus0(3) ",
884 "$testname: rule_matches ok");
885 $bt->invoice_amount($bt->amount);
887 is($bt->invoice_amount , '119.00000' , "$testname: bt invoice amount now set");
890 sub test_sepa_export {
892 my $testname = 'test_sepa_export';
894 $ar_transaction = test_ar_transaction(invnumber => 'sepa1');
896 my $bt = create_bank_transaction(record => $ar_transaction) or die "Couldn't create bank_transaction";
897 my $se = create_sepa_export();
898 my $sei = create_sepa_export_item(
899 chart_id => $bank->id,
900 ar_id => $ar_transaction->id,
901 sepa_export_id => $se->id,
902 vc_iban => $customer->iban,
903 vc_bic => $customer->bic,
904 vc_mandator_id => $customer->mandator_id,
905 vc_depositor => $customer->depositor,
906 amount => $ar_transaction->amount,
908 require SL::SEPA::XML;
909 my $sepa_xml = SL::SEPA::XML->new('company' => $customer->name,
910 'creditor_id' => "id",
911 'src_charset' => 'UTF-8',
912 'message_id' => "test",
916 is($sepa_xml->{company} , 'Test Customer OLE S.L. Ardbaerg AB');
918 $ar_transaction->load;
921 is($ar_transaction->paid , '0.00000' , "$testname: sepa1 not paid");
922 is($bt->invoice_amount , '0.00000' , "$testname: bt invoice amount was not assigned");
923 is($bt->amount , '119.00000' , "$testname: bt amount ok");
924 is($sei->amount , '119.00000' , "$testname: sepa export amount ok");
926 my $bt_controller = SL::Controller::BankTransaction->new;
927 $::form->{dont_render_for_test} = 1;
928 $::form->{filter}{bank_account} = $bank_account->id;
929 my ( $bt_transactions, $proposals ) = $bt_controller->action_list;
931 is(scalar(@$bt_transactions) , 1 , "$testname: one bank_transaction");
932 is($bt_transactions->[0]->{agreement}, 25 , "$testname: agreement == 25");
933 my $match = join ( ' ',@{$bt_transactions->[0]->{rule_matches}});
935 "remote_account_number(3) exact_amount(4) own_invoice_in_purpose(5) depositor_matches(2) remote_name(2) payment_within_30_days(1) datebonus0(3) sepa_export_item(5) ",
936 "$testname: rule_matches ok");
939 sub test_two_banktransactions {
941 my $testname = 'two_banktransactions';
943 my $ar_transaction_1 = test_ar_transaction(invnumber => 'salesinv10000' , amount => 2912.00 );
944 my $bt1 = create_bank_transaction(record => $ar_transaction_1,
945 amount => $ar_transaction_1->amount,
946 purpose => "Rechnung10000 beinahe",
947 bank_chart_id => $bank->id,
948 ) or die "Couldn't create bank_transaction";
950 my $bt2 = create_bank_transaction(record => $ar_transaction_1,
951 amount => $ar_transaction_1->amount + 0.01,
952 purpose => "sicher salesinv20000 vielleicht",
953 bank_chart_id => $bank->id,
954 ) or die "Couldn't create bank_transaction";
956 my ($agreement1, $rule_matches1) = $bt1->get_agreement_with_invoice($ar_transaction_1);
957 is($agreement1, 19, "bt1 19 points for ar_transaction_1 in $testname ok");
958 #print "rule_matches1=".$rule_matches1."\n";
960 "remote_account_number(3) exact_amount(4) own_invnumber_in_purpose(4) depositor_matches(2) remote_name(2) payment_within_30_days(1) datebonus0(3) ",
961 "$testname: rule_matches ok");
962 my ($agreement2, $rule_matches2) = $bt2->get_agreement_with_invoice($ar_transaction_1);
963 is($agreement2, 11, "bt2 11 points for ar_transaction_1 in $testname ok");
965 "remote_account_number(3) depositor_matches(2) remote_name(2) payment_within_30_days(1) datebonus0(3) ",
966 "$testname: rule_matches ok");
968 my $ar_transaction_2 = test_ar_transaction(invnumber => 'salesinv20000' , amount => 2912.01 );
969 my $ar_transaction_3 = test_ar_transaction(invnumber => 'zweitemit10000', amount => 2912.00 );
970 ($agreement1, $rule_matches1) = $bt1->get_agreement_with_invoice($ar_transaction_2);
972 is($agreement1, 11, "bt1 11 points for ar_transaction_2 in $testname ok");
974 ($agreement2, $rule_matches2) = $bt2->get_agreement_with_invoice($ar_transaction_2);
975 is($agreement2, 20, "bt2 20 points for ar_transaction_2 in $testname ok");
977 ($agreement2, $rule_matches2) = $bt2->get_agreement_with_invoice($ar_transaction_1);
978 is($agreement2, 11, "bt2 11 points for ar_transaction_1 in $testname ok");
980 my $bt3 = create_bank_transaction(record => $ar_transaction_3,
981 amount => $ar_transaction_3->amount,
982 purpose => "sicher Rechnung10000 vielleicht",
983 bank_chart_id => $bank->id,
984 ) or die "Couldn't create bank_transaction";
986 my ($agreement3, $rule_matches3) = $bt3->get_agreement_with_invoice($ar_transaction_3);
987 is($agreement3, 19, "bt3 19 points for ar_transaction_3 in $testname ok");
990 $ar_transaction_2->delete;
992 #nun sollten zwei gleichwertige Rechnungen $ar_transaction_1 und $ar_transaction_3 für $bt1 gefunden werden
993 #aber es darf keine Proposals geben mit mehreren Rechnungen
994 my $bt_controller = SL::Controller::BankTransaction->new;
995 $::form->{dont_render_for_test} = 1;
996 $::form->{filter}{bank_account} = $bank_account->id;
997 my ( $bt_transactions, $proposals ) = $bt_controller->action_list;
999 is(scalar(@$bt_transactions) , 2 , "$testname: two bank_transaction");
1000 is(scalar(@$proposals) , 0 , "$testname: no proposals");
1002 $ar_transaction_3->delete;
1004 # Jetzt gibt es zwei Kontobewegungen mit gleichen Punkten für eine Rechnung.
1005 # hier darf es auch keine Proposals geben
1007 ( $bt_transactions, $proposals ) = $bt_controller->action_list;
1009 is(scalar(@$bt_transactions) , 2 , "$testname: two bank_transaction");
1010 # odyn testfall - anforderungen so (noch) nicht in kivi
1011 # is(scalar(@$proposals) , 0 , "$testname: no proposals");
1013 # Jetzt gibt es zwei Kontobewegungen für eine Rechnung.
1014 # eine Bewegung bekommt mehr Punkte
1015 # hier darf es auch keine Proposals geben
1016 $bt3->update_attributes( purpose => "fuer Rechnung salesinv10000");
1018 ( $bt_transactions, $proposals ) = $bt_controller->action_list;
1020 is(scalar(@$bt_transactions) , 2 , "$testname: two bank_transaction");
1021 # odyn testfall - anforderungen so (noch) nicht in kivi
1022 # is(scalar(@$proposals) , 1 , "$testname: one proposal");