BankTransaction(closed_period) Prüft Valutadatum gegen closedto
[kivitendo-erp.git] / t / bank / bank_transactions.t
1 use Test::More tests => 290;
2
3 use strict;
4
5 use lib 't';
6 use utf8;
7
8 use Carp;
9 use Support::TestSetup;
10 use Test::Exception;
11 use List::Util qw(sum);
12
13 use SL::DB::AccTransaction;
14 use SL::DB::BankTransactionAccTrans;
15 use SL::DB::Buchungsgruppe;
16 use SL::DB::Currency;
17 use SL::DB::Customer;
18 use SL::DB::Default;
19 use SL::DB::Vendor;
20 use SL::DB::Invoice;
21 use SL::DB::Unit;
22 use SL::DB::Part;
23 use SL::DB::TaxZone;
24 use SL::DB::BankAccount;
25 use SL::DB::PaymentTerm;
26 use SL::DB::PurchaseInvoice;
27 use SL::DB::BankTransaction;
28 use SL::Controller::BankTransaction;
29 use SL::Controller::Reconciliation;
30 use SL::Dev::ALL qw(:ALL);
31 use Data::Dumper;
32
33 my ($customer, $vendor, $currency_id, $unit, $tax, $tax0, $tax7, $tax_9, $payment_terms, $bank_account);
34 my ($transdate1, $transdate2, $currency);
35 my ($ar_chart,$bank,$ar_amount_chart, $ap_chart, $ap_amount_chart);
36 my ($ar_transaction, $ap_transaction);
37
38 sub clear_up {
39
40   SL::DB::Manager::BankTransactionAccTrans->delete_all(all => 1);
41   SL::DB::Manager::BankTransaction->delete_all(all => 1);
42   SL::DB::Manager::InvoiceItem->delete_all(all => 1);
43   SL::DB::Manager::InvoiceItem->delete_all(all => 1);
44   SL::DB::Manager::Invoice->delete_all(all => 1);
45   SL::DB::Manager::PurchaseInvoice->delete_all(all => 1);
46   SL::DB::Manager::Part->delete_all(all => 1);
47   SL::DB::Manager::Customer->delete_all(all => 1);
48   SL::DB::Manager::Vendor->delete_all(all => 1);
49   SL::DB::Manager::SepaExportItem->delete_all(all => 1);
50   SL::DB::Manager::SepaExport->delete_all(all => 1);
51   SL::DB::Manager::BankAccount->delete_all(all => 1);
52   SL::DB::Manager::PaymentTerm->delete_all(all => 1);
53   SL::DB::Manager::Currency->delete_all(where => [ name => 'CUR' ]);
54 };
55
56 my $bt_controller;
57
58 sub save_btcontroller_to_string {
59   my $output;
60   open(my $outputFH, '>', \$output) or die;
61   my $oldFH = select $outputFH;
62
63   $bt_controller = SL::Controller::BankTransaction->new;
64   $bt_controller->action_save_invoices;
65
66   select $oldFH;
67   close $outputFH;
68   return $output;
69 }
70
71 # starting test:
72 Support::TestSetup::login();
73
74 clear_up();
75 reset_state(); # initialise customers/vendors/bank/currency/...
76
77 test1();
78
79 test_overpayment_with_partialpayment();
80 test_overpayment();
81 reset_state();
82 test_skonto_exact();
83 test_two_invoices();
84 test_partial_payment();
85 test_credit_note();
86 test_ap_transaction();
87 test_neg_ap_transaction(invoice => 0);
88 test_neg_ap_transaction(invoice => 1);
89 test_ap_payment_transaction();
90 test_ap_payment_part_transaction();
91 test_neg_sales_invoice();
92 test_two_neg_ap_transaction();
93 test_one_inv_and_two_invoices_with_skonto_exact();
94 test_bt_error();
95 test_full_workflow_ar_multiple_inv_skonto_reconciliate_and_undo();
96 reset_state();
97 test_sepa_export();
98
99 reset_state();
100 test_bt_rule1();
101 reset_state();
102 test_two_banktransactions();
103 # remove all created data at end of test
104 test_closedto();
105 clear_up();
106
107 done_testing();
108
109 ###### functions for setting up data
110
111 sub reset_state {
112   my %params = @_;
113
114   $params{$_} ||= {} for qw(unit customer tax vendor);
115
116   clear_up();
117
118   $transdate1 = DateTime->today;
119   $transdate2 = DateTime->today->add(days => 5);
120
121   $tax             = SL::DB::Manager::Tax->find_by(taxkey => 3, rate => 0.19, %{ $params{tax} }) || croak "No tax";
122   $tax7            = SL::DB::Manager::Tax->find_by(taxkey => 2, rate => 0.07)                    || croak "No tax for 7\%";
123   $tax_9           = SL::DB::Manager::Tax->find_by(taxkey => 9, rate => 0.19, %{ $params{tax} }) || croak "No tax for 19\%";
124   $tax0            = SL::DB::Manager::Tax->find_by(taxkey => 0, rate => 0.0)                     || croak "No tax for 0\%";
125
126   $currency_id     = $::instance_conf->get_currency_id;
127
128   $bank_account     =  SL::DB::BankAccount->new(
129     account_number  => '123',
130     bank_code       => '123',
131     iban            => '123',
132     bic             => '123',
133     bank            => '123',
134     chart_id        => SL::DB::Manager::Chart->find_by(description => 'Bank')->id,
135     name            => SL::DB::Manager::Chart->find_by(description => 'Bank')->description,
136   )->save;
137
138   $customer = new_customer(
139     name                      => 'Test Customer OLÉ S.L. Årdbärg AB',
140     iban                      => 'DE12500105170648489890',
141     bic                       => 'TESTBIC',
142     account_number            => '648489890',
143     mandate_date_of_signature => $transdate1,
144     mandator_id               => 'foobar',
145     bank                      => 'Geizkasse',
146     bank_code                 => 'G1235',
147     depositor                 => 'Test Customer',
148     customernumber            => 'CUST1704',
149   )->save;
150
151   $payment_terms = create_payment_terms();
152
153   $vendor = new_vendor(
154     name           => 'Test Vendor',
155     payment_id     => $payment_terms->id,
156     iban           => 'DE12500105170648489890',
157     bic            => 'TESTBIC',
158     account_number => '648489890',
159     bank           => 'Geizkasse',
160     bank_code      => 'G1235',
161     depositor      => 'Test Vendor',
162     vendornumber   => 'VEND1704',
163   )->save;
164
165   $ar_chart        = SL::DB::Manager::Chart->find_by( accno => '1400' ); # Forderungen
166   $ap_chart        = SL::DB::Manager::Chart->find_by( accno => '1600' ); # Verbindlichkeiten
167   $bank            = SL::DB::Manager::Chart->find_by( accno => '1200' ); # Bank
168   $ar_amount_chart = SL::DB::Manager::Chart->find_by( accno => '8400' ); # Erlöse
169   $ap_amount_chart = SL::DB::Manager::Chart->find_by( accno => '3400' ); # Wareneingang 19%
170
171 }
172
173 sub test_ar_transaction {
174   my (%params) = @_;
175   my $netamount = $params{amount} || 100;
176   my $amount    = $::form->round_amount($netamount * 1.19,2);
177   my $invoice   = SL::DB::Invoice->new(
178       invoice      => 0,
179       invnumber    => $params{invnumber} || undef, # let it use its own invnumber
180       amount       => $amount,
181       netamount    => $netamount,
182       transdate    => $transdate1,
183       taxincluded  => $params{taxincluded } || 0,
184       customer_id  => $customer->id,
185       taxzone_id   => $customer->taxzone_id,
186       currency_id  => $currency_id,
187       transactions => [],
188       payment_id   => $params{payment_id} || undef,
189       notes        => 'test_ar_transaction',
190   );
191   $invoice->add_ar_amount_row(
192     amount => $invoice->netamount,
193     chart  => $ar_amount_chart,
194     tax_id => $params{tax_id} || $tax->id,
195   );
196
197   $invoice->create_ar_row(chart => $ar_chart);
198   $invoice->save;
199
200   is($invoice->currency_id , $currency_id , 'currency_id has been saved');
201   is($invoice->netamount   , $netamount   , 'ar amount has been converted');
202   is($invoice->amount      , $amount      , 'ar amount has been converted');
203   is($invoice->taxincluded , 0            , 'ar transaction doesn\'t have taxincluded');
204
205   if ( $netamount == 100 ) {
206     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');
207     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');
208   }
209   return $invoice;
210 };
211
212 sub test_ap_transaction {
213   my (%params) = @_;
214   my $testname = 'test_ap_transaction';
215
216   my $netamount = 100;
217   my $amount    = $::form->round_amount($netamount * 1.19,2);
218   my $invoice   = SL::DB::PurchaseInvoice->new(
219     invoice      => 0,
220     invnumber    => $params{invnumber} || $testname,
221     amount       => $amount,
222     netamount    => $netamount,
223     transdate    => $transdate1,
224     taxincluded  => 0,
225     vendor_id    => $vendor->id,
226     taxzone_id   => $vendor->taxzone_id,
227     currency_id  => $currency_id,
228     transactions => [],
229     notes        => 'test_ap_transaction',
230   );
231   $invoice->add_ap_amount_row(
232     amount     => $invoice->netamount,
233     chart      => $ap_amount_chart,
234     tax_id     => $params{tax_id} || $tax_9->id,
235   );
236
237   $invoice->create_ap_row(chart => $ap_chart);
238   $invoice->save;
239
240   is($invoice->currency_id , $currency_id , "$testname: currency_id has been saved");
241   is($invoice->netamount   , 100          , "$testname: ap amount has been converted");
242   is($invoice->amount      , 119          , "$testname: ap amount has been converted");
243   is($invoice->taxincluded , 0            , "$testname: ap transaction doesn\'t have taxincluded");
244
245   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');
246   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');
247
248   return $invoice;
249 };
250
251 ###### test cases
252
253 sub test1 {
254
255   my $testname = 'test1';
256
257   $ar_transaction = test_ar_transaction(invnumber => 'salesinv1');
258
259   my $bt = create_bank_transaction(record => $ar_transaction) or die "Couldn't create bank_transaction";
260
261   $::form->{invoice_ids} = {
262     $bt->id => [ $ar_transaction->id ]
263   };
264
265   save_btcontroller_to_string();
266
267   $ar_transaction->load;
268   $bt->load;
269   is($ar_transaction->paid   , '119.00000' , "$testname: salesinv1 was paid");
270   is($ar_transaction->closed , 1           , "$testname: salesinv1 is closed");
271   is($bt->invoice_amount     , '119.00000' , "$testname: bt invoice amount was assigned");
272
273 };
274
275 sub test_skonto_exact {
276
277   my $testname = 'test_skonto_exact';
278
279   $ar_transaction = test_ar_transaction(invnumber => 'salesinv skonto',
280                                         payment_id => $payment_terms->id,
281                                        );
282
283   my $bt = create_bank_transaction(record        => $ar_transaction,
284                                    bank_chart_id => $bank->id,
285                                    amount        => $ar_transaction->amount_less_skonto
286                                   ) or die "Couldn't create bank_transaction";
287
288   $::form->{invoice_ids} = {
289     $bt->id => [ $ar_transaction->id ]
290   };
291   $::form->{invoice_skontos} = {
292     $bt->id => [ 'with_skonto_pt' ]
293   };
294
295   save_btcontroller_to_string();
296
297   $ar_transaction->load;
298   $bt->load;
299   is($ar_transaction->paid   , '119.00000' , "$testname: salesinv skonto was paid");
300   is($ar_transaction->closed , 1           , "$testname: salesinv skonto is closed");
301   is($bt->invoice_amount     , '113.05000' , "$testname: bt invoice amount was assigned");
302
303 };
304
305 sub test_bt_error {
306
307   my $testname = 'test_rollback_error';
308   # without type with_free_skonto the helper function (Payment.pm) looks ugly but not
309   # breakable
310
311   $ar_transaction = test_ar_transaction(invnumber   => 'salesinv skonto',
312                                         payment_id  => $payment_terms->id,
313                                         taxincluded => 0,
314                                         amount      => 168.58 / 1.19,
315                                        );
316
317   my $bt = create_bank_transaction(record        => $ar_transaction,
318                                    bank_chart_id => $bank->id,
319                                    amount        => 160.15,
320                                   ) or die "Couldn't create bank_transaction";
321   $::form->{invoice_ids} = {
322     $bt->id => [ $ar_transaction->id ]
323   };
324   $::form->{invoice_skontos} = {
325     $bt->id => [ 'with_skonto_pt' ]
326   };
327
328   is($ar_transaction->paid   , '0' , "$testname: salesinv is not paid");
329
330   # generate an error for testing rollback mechanism
331   my $saved_skonto_sales_chart_id = $tax->skonto_sales_chart_id;
332   $tax->skonto_sales_chart_id(undef);
333   $tax->save;
334
335   save_btcontroller_to_string();
336   my @bt_errors = @{ $bt_controller->problems };
337   is(substr($bt_errors[0]->{message},0,38), 'Kein Skontokonto für Steuerschlüssel 3', "$testname: Fehlermeldung ok");
338   # set original value
339   $tax->skonto_sales_chart_id($saved_skonto_sales_chart_id);
340   $tax->save;
341
342   $ar_transaction->load;
343   $bt->load;
344   is($ar_transaction->paid   , '0.00000' , "$testname: salesinv was not paid");
345   is($bt->invoice_amount     , '0.00000' , "$testname: bt invoice amount was not assigned");
346
347 };
348
349 sub test_two_invoices {
350
351   my $testname = 'test_two_invoices';
352
353   my $ar_transaction_1 = test_ar_transaction(invnumber => 'salesinv_1');
354   my $ar_transaction_2 = test_ar_transaction(invnumber => 'salesinv_2');
355
356   my $bt = create_bank_transaction(record        => $ar_transaction_1,
357                                    amount        => ($ar_transaction_1->amount + $ar_transaction_2->amount),
358                                    purpose       => "Rechnungen " . $ar_transaction_1->invnumber . " und " . $ar_transaction_2->invnumber,
359                                    bank_chart_id => $bank->id,
360                                   ) or die "Couldn't create bank_transaction";
361
362   my ($agreement, $rule_matches) = $bt->get_agreement_with_invoice($ar_transaction_1);
363   is($agreement, 16, "points for ar_transaction_1 in test_two_invoices ok");
364
365   $::form->{invoice_ids} = {
366     $bt->id => [ $ar_transaction_1->id, $ar_transaction_2->id ]
367   };
368
369   save_btcontroller_to_string();
370
371   $ar_transaction_1->load;
372   $ar_transaction_2->load;
373   $bt->load;
374
375   is($ar_transaction_1->paid   , '119.00000' , "$testname: salesinv_1 wcsv_import_reportsas paid");
376   is($ar_transaction_1->closed , 1           , "$testname: salesinv_1 is closed");
377   is($ar_transaction_2->paid   , '119.00000' , "$testname: salesinv_2 was paid");
378   is($ar_transaction_2->closed , 1           , "$testname: salesinv_2 is closed");
379   is($bt->invoice_amount       , '238.00000' , "$testname: bt invoice amount was assigned");
380
381 }
382
383 sub test_one_inv_and_two_invoices_with_skonto_exact {
384
385   my $testname = 'test_two_invoices_with_skonto_exact';
386
387   my $ar_transaction_1 = test_ar_transaction(invnumber => 'salesinv 1 skonto',
388                                              payment_id => $payment_terms->id,
389                                             );
390   my $ar_transaction_2 = test_ar_transaction(invnumber => 'salesinv 2 skonto',
391                                              payment_id => $payment_terms->id,
392                                             );
393   my $ar_transaction_3 = test_ar_transaction(invnumber => 'salesinv 3 no skonto');
394
395
396
397   my $bt = create_bank_transaction(record        => $ar_transaction_1,
398                                    bank_chart_id => $bank->id,
399                                    amount        => $ar_transaction_1->amount_less_skonto * 2 + $ar_transaction_3->amount
400                                   ) or die "Couldn't create bank_transaction";
401
402   $::form->{invoice_ids} = {
403     $bt->id => [ $ar_transaction_1->id, $ar_transaction_3->id, $ar_transaction_2->id]
404   };
405   $::form->{invoice_skontos} = {
406     $bt->id => [ 'with_skonto_pt', 'without_skonto', 'with_skonto_pt' ]
407   };
408
409   save_btcontroller_to_string();
410
411   $ar_transaction_1->load;
412   $ar_transaction_2->load;
413   $ar_transaction_3->load;
414   my $skonto_1 = SL::DB::Manager::AccTransaction->find_by(trans_id => $ar_transaction_1->id, chart_id => 162);
415   my $skonto_2 = SL::DB::Manager::AccTransaction->find_by(trans_id => $ar_transaction_2->id, chart_id => 162);
416   $bt->load;
417   is($skonto_1->amount   , '-5.95000' , "$testname: salesinv 1 skonto was booked");
418   is($skonto_2->amount   , '-5.95000' , "$testname: salesinv 2 skonto was booked");
419   is($ar_transaction_1->paid   , '119.00000' , "$testname: salesinv 1 was paid");
420   is($ar_transaction_2->paid   , '119.00000' , "$testname: salesinv 2 was paid");
421   is($ar_transaction_3->paid   , '119.00000' , "$testname: salesinv 3 was paid");
422   is($ar_transaction_1->closed , 1           , "$testname: salesinv 1 skonto is closed");
423   is($ar_transaction_2->closed , 1           , "$testname: salesinv 2 skonto is closed");
424   is($ar_transaction_3->closed , 1           , "$testname: salesinv 2 skonto is closed");
425   is($bt->invoice_amount     , '345.10000' , "$testname: bt invoice amount was assigned");
426
427 }
428
429 sub test_overpayment {
430
431   my $testname = 'test_overpayment';
432
433   $ar_transaction = test_ar_transaction(invnumber => 'salesinv overpaid');
434
435   # amount 135 > 119
436   my $bt = create_bank_transaction(record        => $ar_transaction,
437                                    bank_chart_id => $bank->id,
438                                    amount        => 135
439                                   ) or die "Couldn't create bank_transaction";
440
441   $::form->{invoice_ids} = {
442     $bt->id => [ $ar_transaction->id ]
443   };
444
445   save_btcontroller_to_string();
446
447   $ar_transaction->load;
448   $bt->load;
449
450   is($ar_transaction->paid                     , '119.00000' , "$testname: 'salesinv overpaid' was not overpaid");
451   is($bt->invoice_amount                       , '119.00000' , "$testname: bt invoice amount was not fully assigned with the overpaid amount");
452 { local $TODO = 'this currently fails because closed ignores over-payments, see commit d90966c7';
453   is($ar_transaction->closed                   , 0           , "$testname: 'salesinv overpaid' is open (via 'closed' method')");
454 }
455   is($ar_transaction->open_amount == 0 ? 1 : 0 , 1           , "$testname: 'salesinv overpaid is closed (via amount-paid)");
456
457 };
458
459 sub test_overpayment_with_partialpayment {
460
461   # two payments on different days, 10 and 119. If there is only one invoice we
462   # don't want it to be overpaid.
463   my $testname = 'test_overpayment_with_partialpayment';
464
465   $ar_transaction = test_ar_transaction(invnumber => 'salesinv overpaid partial');
466
467   my $bt_1 = create_bank_transaction(record        => $ar_transaction,
468                                      bank_chart_id => $bank->id,
469                                      amount        =>  10
470                                     ) or die "Couldn't create bank_transaction";
471   my $bt_2 = create_bank_transaction(record        => $ar_transaction,
472                                      amount        => 119,
473                                      transdate     => DateTime->today->add(days => 5),
474                                      bank_chart_id => $bank->id,
475                                     ) or die "Couldn't create bank_transaction";
476
477   $::form->{invoice_ids} = {
478     $bt_1->id => [ $ar_transaction->id ]
479   };
480   save_btcontroller_to_string();
481
482   $bt_1->load;
483   is($bt_1->invoice_amount ,  '10.00000' , "$testname: bt_1 invoice amount was fully assigned");
484   $::form->{invoice_ids} = {
485     $bt_2->id => [ $ar_transaction->id ]
486   };
487   save_btcontroller_to_string();
488
489   $ar_transaction->load;
490   $bt_2->load;
491
492   is($bt_1->invoice_amount ,  '10.00000' , "$testname: bt_1 invoice amount was fully assigned");
493   is($ar_transaction->paid , '119.00000' , "$testname: 'salesinv overpaid partial' was not overpaid");
494   is($bt_2->invoice_amount , '109.00000' , "$testname: bt_2 invoice amount was partly assigned");
495
496 };
497
498 sub test_partial_payment {
499
500   my $testname = 'test_partial_payment';
501
502   $ar_transaction = test_ar_transaction(invnumber => 'salesinv partial payment');
503
504   # amount 100 < 119
505   my $bt = create_bank_transaction(record        => $ar_transaction,
506                                    bank_chart_id => $bank->id,
507                                    amount        => 100
508                                   ) or die "Couldn't create bank_transaction";
509
510   $::form->{invoice_ids} = {
511     $bt->id => [ $ar_transaction->id ]
512   };
513
514   save_btcontroller_to_string();
515
516   $ar_transaction->load;
517   $bt->load;
518
519   is($ar_transaction->paid , '100.00000' , "$testname: 'salesinv partial payment' was partially paid");
520   is($bt->invoice_amount   , '100.00000' , "$testname: bt invoice amount was assigned partially paid amount");
521
522 };
523
524 sub test_full_workflow_ar_multiple_inv_skonto_reconciliate_and_undo {
525
526   my $testname = 'test_partial_payment';
527
528   $ar_transaction = test_ar_transaction(invnumber => 'salesinv partial payment two');
529   my $ar_transaction_2 = test_ar_transaction(invnumber => 'salesinv 2 22d2', amount => 22);
530
531   # amount 299.29 > 119
532   my $bt = create_bank_transaction(record        => $ar_transaction,
533                                    bank_chart_id => $bank->id,
534                                    amount        => 299.29
535                                   ) or die "Couldn't create bank_transaction";
536
537   $::form->{invoice_ids} = {
538     $bt->id => [ $ar_transaction->id ]
539   };
540
541   save_btcontroller_to_string();
542
543   $ar_transaction->load;
544   $bt->load;
545
546   is($ar_transaction->paid , '119.00000' , "$testname: 'salesinv partial payment' was fully paid");
547   is($bt->invoice_amount   , '119.00000' , "$testname: bt invoice amount was assigned partially paid amount");
548   is($bt->amount           , '299.29000' , "$testname: bt amount is stil there");
549   # next invoice, same bank transaction
550   $::form->{invoice_ids} = {
551     $bt->id => [ $ar_transaction_2->id ]
552   };
553
554   save_btcontroller_to_string();
555
556   $ar_transaction_2->load;
557   $bt->load;
558   is($ar_transaction_2->paid , '26.18000' , "$testname: 'salesinv partial payment' was fully paid");
559   is($bt->invoice_amount   , '145.18000' , "$testname: bt invoice amount was assigned partially paid amount");
560   is($bt->amount           , '299.29000' , "$testname: bt amount is stil there");
561   is(scalar @{ SL::DB::Manager::BankTransactionAccTrans->get_all(where => [bank_transaction_id => $bt->id ] )}, 4, "$testname 4 acc_trans entries created");
562
563   #  now check all 4 entries done so far and save paid acc_trans_ids for later use with reconcile
564   foreach my $acc_trans_id_entry (@{ SL::DB::Manager::BankTransactionAccTrans->get_all(where => [bank_transaction_id => $bt->id ] )}) {
565     isnt($acc_trans_id_entry->ar_id, undef, "$testname: bt linked with acc_trans and trans_id set");
566     my $rl = SL::DB::Manager::RecordLink->get_all(where => [ from_id => $bt->id, from_table => 'bank_transactions', to_id => $acc_trans_id_entry->ar_id ]);
567     is (ref $rl->[0], 'SL::DB::RecordLink', "$testname record link created");
568     my $acc_trans = SL::DB::Manager::AccTransaction->get_all(where => [acc_trans_id => $acc_trans_id_entry->acc_trans_id]);
569     foreach my $entry (@{ $acc_trans }) {
570       like(abs($entry->amount), qr/(119|26.18)/, "$testname: abs amount correct");
571       like($entry->chart_link, qr/(paid|AR)/, "$testname chart_link correct");
572       push @{ $::form->{bb_ids} }, $entry->acc_trans_id if $entry->chart_link =~ m/paid/;
573     }
574   }
575   # great we need one last booking to clear the whole bank transaction - we include skonto
576   my $ar_transaction_skonto = test_ar_transaction(invnumber  => 'salesinv skonto last case',
577                                                   payment_id => $payment_terms->id,
578                                                   amount     => 136.32,
579                                                  );
580
581   $::form->{invoice_ids} = {
582     $bt->id => [ $ar_transaction_skonto->id ]
583   };
584   $::form->{invoice_skontos} = {
585     $bt->id => [ 'with_skonto_pt' ]
586   };
587
588   save_btcontroller_to_string();
589
590   $ar_transaction_skonto->load;
591   $bt->load;
592   is($ar_transaction_skonto->paid , '162.22000' , "$testname: 'salesinv skonto fully paid");
593   is($bt->invoice_amount   , '299.29000' , "$testname: bt invoice amount was assigned partially paid amount");
594   is($bt->amount           , '299.29000' , "$testname: bt amount is stil there");
595   is(scalar @{ SL::DB::Manager::BankTransactionAccTrans->get_all(where => [bank_transaction_id => $bt->id ] )},
596        7, "$testname 7 acc_trans entries created");
597
598   # same loop as above, but only for the 3rd ar_id
599   foreach my $acc_trans_id_entry (@{ SL::DB::Manager::BankTransactionAccTrans->get_all(where => [ar_id => $ar_transaction_skonto->id ] )}) {
600     isnt($acc_trans_id_entry->ar_id, '', "$testname: bt linked with acc_trans and trans_id set");
601     my $rl = SL::DB::Manager::RecordLink->get_all(where => [ from_id => $bt->id, from_table => 'bank_transactions', to_id => $acc_trans_id_entry->ar_id ]);
602     is (ref $rl->[0], 'SL::DB::RecordLink', "$testname record link created");
603     my $acc_trans = SL::DB::Manager::AccTransaction->get_all(where => [acc_trans_id => $acc_trans_id_entry->acc_trans_id]);
604     foreach my $entry (@{ $acc_trans }) {
605       like($entry->chart_link, qr/(paid|AR)/, "$testname chart_link correct");
606       is ($entry->amount, '162.22000', "$testname full amont") if $entry->chart_link eq 'AR'; # full amount
607       like(abs($entry->amount), qr/(154.11|8.11)/, "$testname: abs amount correct") if $entry->chart_link =~ m/paid/;
608       push @{ $::form->{bb_ids} }, $entry->acc_trans_id if ($entry->chart_link =~ m/paid/ && $entry->amount == -154.11);
609     }
610   }
611   # done, now reconciliate all bookings
612   $::form->{bt_ids} = [ $bt->id ];
613   my $rec_controller = SL::Controller::Reconciliation->new;
614   my @errors = $rec_controller->_get_elements_and_validate;
615
616   is (scalar @errors, 0, "$testname unsuccesfull reconciliation with error: " . Dumper(@errors));
617   $rec_controller->_reconcile;
618   $bt->load;
619
620   # and check the cleared state of bt and the acc_transactions
621   is($bt->cleared, '1' , "$testname: bt cleared");
622   foreach (@{ $::form->{bb_ids} }) {
623     my $acc_trans = SL::DB::Manager::AccTransaction->find_by(acc_trans_id => $_);
624     is($acc_trans->cleared, '1' , "$testname: acc_trans entry cleared");
625   }
626   # now, this was a really bad idea and in general a major mistake. better undo and redo the whole bank transactions
627
628   $::form->{ids} = [ $bt->id ];
629   $bt_controller = SL::Controller::BankTransaction->new;
630   $bt_controller->action_unlink_bank_transaction('testcase' => 1);
631
632   $bt->load;
633
634   # and check the cleared state of bt and the acc_transactions
635   is($bt->cleared, '0' , "$testname: bt undo cleared");
636   is($bt->invoice_amount, '0.00000' , "$testname: bt undo invoice amount");
637   foreach (@{ $::form->{bb_ids} }) {
638     my $acc_trans = SL::DB::Manager::AccTransaction->find_by(acc_trans_id => $_);
639     is($acc_trans, undef , "$testname: cleared acc_trans entry completely removed");
640   }
641   # this was for data integrity for reconcile, now all the other options
642   is(scalar @{ SL::DB::Manager::BankTransactionAccTrans->get_all(where => [bank_transaction_id => $bt->id ] )},
643        0, "$testname 7 acc_trans entries deleted");
644   my $rl = SL::DB::Manager::RecordLink->get_all(where => [ from_id => $bt->id, from_table => 'bank_transactions' ]);
645   is (ref $rl->[0], '', "$testname record link removed");
646   # double safety and check ar.paid
647   # load all three invoices and check for paid-link via acc_trans and paid in general
648
649   $ar_transaction->load;
650   $ar_transaction_2->load;
651   $ar_transaction_skonto->load;
652
653   is(scalar @{ SL::DB::Manager::AccTransaction->get_all(
654      where => [ trans_id => $ar_transaction->id, chart_link => { like => '%paid%' } ])},
655      0, "$testname no more paid entries in acc_trans for ar_transaction");
656   is(scalar @{ SL::DB::Manager::AccTransaction->get_all(
657      where => [ trans_id => $ar_transaction_2->id, chart_link => { like => '%paid%' } ])},
658      0, "$testname no more paid entries in acc_trans for ar_transaction_2");
659   is(scalar @{ SL::DB::Manager::AccTransaction->get_all(
660      where => [ trans_id => $ar_transaction_skonto->id, chart_link => { like => '%paid%' } ])},
661      0, "$testname no more paid entries in acc_trans for ar_transaction_skonto");
662
663   is($ar_transaction->paid , '0.00000' , "$testname: 'salesinv fully unpaid");
664   is($ar_transaction_2->paid , '0.00000' , "$testname: 'salesinv 2 fully unpaid");
665   is($ar_transaction_skonto->paid , '0.00000' , "$testname: 'salesinv skonto fully unpaid");
666
667   # whew. w(h)a(n)t a whole lotta test
668 }
669
670
671 sub test_credit_note {
672
673   my $testname = 'test_credit_note';
674
675   my $part1 = new_part(   partnumber => 'T4254')->save;
676   my $part2 = new_service(partnumber => 'Serv1')->save;
677   my $credit_note = create_credit_note(
678     invnumber    => 'cn 1',
679     customer     => $customer,
680     taxincluded  => 0,
681     invoiceitems => [ create_invoice_item(part => $part1, qty =>  3, sellprice => 70),
682                       create_invoice_item(part => $part2, qty => 10, sellprice => 50),
683                     ]
684   );
685   my $bt            = create_bank_transaction(record        => $credit_note,
686                                                                 amount        => $credit_note->amount,
687                                                                 bank_chart_id => $bank->id,
688                                                                 transdate     => DateTime->today->add(days => 10),
689                                                                );
690   my ($agreement, $rule_matches) = $bt->get_agreement_with_invoice($credit_note);
691   is($agreement, 13, "points for credit note ok");
692   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");
693
694   $::form->{invoice_ids} = {
695     $bt->id => [ $credit_note->id ]
696   };
697
698   save_btcontroller_to_string();
699
700   $credit_note->load;
701   $bt->load;
702   is($credit_note->amount   , '-844.90000', "$testname: amount ok");
703   is($credit_note->netamount, '-710.00000', "$testname: netamount ok");
704   is($credit_note->paid     , '-844.90000', "$testname: paid ok");
705 }
706
707 sub test_neg_ap_transaction {
708   my (%params) = @_;
709   my $testname = 'test_neg_ap_transaction' . $params{invoice} ? ' invoice booking' : ' credit booking';
710   my $netamount = -20;
711   my $amount    = $::form->round_amount($netamount * 1.19,2);
712   my $invoice   = SL::DB::PurchaseInvoice->new(
713     invoice      => $params{invoice} // 0,
714     invnumber    => $params{invnumber} || 'test_neg_ap_transaction',
715     amount       => $amount,
716     netamount    => $netamount,
717     transdate    => $transdate1,
718     taxincluded  => 0,
719     vendor_id    => $vendor->id,
720     taxzone_id   => $vendor->taxzone_id,
721     currency_id  => $currency_id,
722     transactions => [],
723     notes        => 'test_neg_ap_transaction',
724   );
725   $invoice->add_ap_amount_row(
726     amount     => $invoice->netamount,
727     chart      => $ap_amount_chart,
728     tax_id     => $tax_9->id,
729   );
730
731   $invoice->create_ap_row(chart => $ap_chart);
732   $invoice->save;
733
734   is($invoice->netamount, -20  , "$testname: netamount ok");
735   is($invoice->amount   , -23.8, "$testname: amount ok");
736
737   my $bt            = create_bank_transaction(record        => $invoice,
738                                               amount        => $invoice->amount,
739                                               bank_chart_id => $bank->id,
740                                               transdate     => DateTime->today->add(days => 10),
741                                                                );
742
743   my ($agreement, $rule_matches) = $bt->get_agreement_with_invoice($invoice);
744   is($agreement, 15, "points for negative ap transaction ok");
745
746   $::form->{invoice_ids} = {
747     $bt->id => [ $invoice->id ]
748   };
749
750   save_btcontroller_to_string();
751
752   $invoice->load;
753   $bt->load;
754
755   is($invoice->amount   , '-23.80000', "$testname: amount ok");
756   is($invoice->netamount, '-20.00000', "$testname: netamount ok");
757   is($invoice->paid     , '-23.80000', "$testname: paid ok");
758   is($bt->invoice_amount, '23.80000', "$testname: bt invoice amount for ap was assigned");
759   is($bt->amount,         '23.80000', "$testname: bt  amount for ap was assigned");
760
761   return $invoice;
762 };
763 sub test_two_neg_ap_transaction {
764   my $testname='test_two_neg_ap_transaction';
765   my $netamount = -20;
766   my $amount    = $::form->round_amount($netamount * 1.19,2);
767   my $invoice   = SL::DB::PurchaseInvoice->new(
768     invoice      =>  0,
769     invnumber    => 'test_neg_ap_transaction',
770     amount       => $amount,
771     netamount    => $netamount,
772     transdate    => $transdate1,
773     taxincluded  => 0,
774     vendor_id    => $vendor->id,
775     taxzone_id   => $vendor->taxzone_id,
776     currency_id  => $currency_id,
777     transactions => [],
778     notes        => 'test_neg_ap_transaction',
779   );
780   $invoice->add_ap_amount_row(
781     amount     => $invoice->netamount,
782     chart      => $ap_amount_chart,
783     tax_id     => $tax_9->id,
784   );
785
786   $invoice->create_ap_row(chart => $ap_chart);
787   $invoice->save;
788
789   is($invoice->netamount, -20  , "$testname: netamount ok");
790   is($invoice->amount   , -23.8, "$testname: amount ok");
791
792   my $netamount_two = -1.14;
793   my $amount_two    = $::form->round_amount($netamount_two * 1.19,2);
794   my $invoice_two   = SL::DB::PurchaseInvoice->new(
795     invoice      => 0,
796     invnumber    => 'test_neg_ap_transaction_two',
797     amount       => $amount_two,
798     netamount    => $netamount_two,
799     transdate    => $transdate1,
800     taxincluded  => 0,
801     vendor_id    => $vendor->id,
802     taxzone_id   => $vendor->taxzone_id,
803     currency_id  => $currency_id,
804     transactions => [],
805     notes        => 'test_neg_ap_transaction_two',
806   );
807   $invoice_two->add_ap_amount_row(
808     amount     => $invoice_two->netamount,
809     chart      => $ap_amount_chart,
810     tax_id     => $tax_9->id,
811   );
812
813   $invoice_two->create_ap_row(chart => $ap_chart);
814   $invoice_two->save;
815
816   is($invoice_two->netamount, -1.14  , "$testname: netamount ok");
817   is($invoice_two->amount   , -1.36, "$testname: amount ok");
818
819
820   my $bt            = create_bank_transaction(record        => $invoice_two,
821                                               amount        => $invoice_two->amount + $invoice->amount,
822                                               bank_chart_id => $bank->id,
823                                               transdate     => DateTime->today->add(days => 10),
824                                                                );
825   # my ($agreement, $rule_matches) = $bt->get_agreement_with_invoice($invoice_two);
826   # is($agreement, 15, "points for negative ap transaction ok");
827
828   $::form->{invoice_ids} = {
829     $bt->id => [ $invoice->id, $invoice_two->id ]
830   };
831
832   save_btcontroller_to_string();
833
834   $invoice->load;
835   $invoice_two->load;
836   $bt->load;
837
838   is($invoice->amount   , '-23.80000', "$testname: first inv amount ok");
839   is($invoice->netamount, '-20.00000', "$testname: first inv netamount ok");
840   is($invoice->paid     , '-23.80000', "$testname: first inv paid ok");
841   is($invoice_two->amount   , '-1.36000', "$testname: second inv amount ok");
842   is($invoice_two->netamount, '-1.14000', "$testname: second inv netamount ok");
843   is($invoice_two->paid     , '-1.36000', "$testname: second inv paid ok");
844   is($bt->invoice_amount, '25.16000', "$testname: bt invoice amount for both invoices were assigned");
845
846
847   return ($invoice, $invoice_two);
848 };
849
850 sub test_ap_payment_transaction {
851   my (%params) = @_;
852   my $testname = 'test_ap_payment_transaction';
853   my $netamount = 115;
854   my $amount    = $::form->round_amount($netamount * 1.19,2);
855   my $invoice   = SL::DB::PurchaseInvoice->new(
856     invoice      => 0,
857     invnumber    => $params{invnumber} || $testname,
858     amount       => $amount,
859     netamount    => $netamount,
860     transdate    => $transdate1,
861     taxincluded  => 0,
862     vendor_id    => $vendor->id,
863     taxzone_id   => $vendor->taxzone_id,
864     currency_id  => $currency_id,
865     transactions => [],
866     notes        => $testname,
867   );
868   $invoice->add_ap_amount_row(
869     amount     => $invoice->netamount,
870     chart      => $ap_amount_chart,
871     tax_id     => $tax_9->id,
872   );
873
874   $invoice->create_ap_row(chart => $ap_chart);
875   $invoice->save;
876
877   is($invoice->netamount, 115  , "$testname: netamount ok");
878   is($invoice->amount   , 136.85, "$testname: amount ok");
879
880   my $bt            = create_bank_transaction(record        => $invoice,
881                                               amount        => $invoice->amount,
882                                               bank_chart_id => $bank->id,
883                                               transdate     => DateTime->today->add(days => 10),
884                                              );
885   $::form->{invoice_ids} = {
886     $bt->id => [ $invoice->id ]
887   };
888
889   save_btcontroller_to_string();
890
891   $invoice->load;
892   $bt->load;
893
894   is($invoice->amount   , '136.85000', "$testname: amount ok");
895   is($invoice->netamount, '115.00000', "$testname: netamount ok");
896   is($bt->amount,         '-136.85000', "$testname: bt amount ok");
897   is($invoice->paid     , '136.85000', "$testname: paid ok");
898   is($bt->invoice_amount, '-136.85000', "$testname: bt invoice amount for ap was assigned");
899
900   return $invoice;
901 };
902
903 sub test_ap_payment_part_transaction {
904   my (%params) = @_;
905   my $testname = 'test_ap_payment_p_transaction';
906   my $netamount = 115;
907   my $amount    = $::form->round_amount($netamount * 1.19,2);
908   my $invoice   = SL::DB::PurchaseInvoice->new(
909     invoice      => 0,
910     invnumber    => $params{invnumber} || $testname,
911     amount       => $amount,
912     netamount    => $netamount,
913     transdate    => $transdate1,
914     taxincluded  => 0,
915     vendor_id    => $vendor->id,
916     taxzone_id   => $vendor->taxzone_id,
917     currency_id  => $currency_id,
918     transactions => [],
919     notes        => $testname,
920   );
921   $invoice->add_ap_amount_row(
922     amount     => $invoice->netamount,
923     chart      => $ap_amount_chart,
924     tax_id     => $tax_9->id,
925   );
926
927   $invoice->create_ap_row(chart => $ap_chart);
928   $invoice->save;
929
930   is($invoice->netamount, 115  , "$testname: netamount ok");
931   is($invoice->amount   , 136.85, "$testname: amount ok");
932
933   my $bt            = create_bank_transaction(record        => $invoice,
934                                               amount        => $invoice->amount-100,
935                                               bank_chart_id => $bank->id,
936                                               transdate     => DateTime->today->add(days => 10),
937                                              );
938   $::form->{invoice_ids} = {
939     $bt->id => [ $invoice->id ]
940   };
941
942   save_btcontroller_to_string();
943
944   $invoice->load;
945   $bt->load;
946
947   is($invoice->amount   , '136.85000', "$testname: amount ok");
948   is($invoice->netamount, '115.00000', "$testname: netamount ok");
949   is($bt->amount,         '-36.85000', "$testname: bt amount ok");
950   is($invoice->paid     ,  '36.85000', "$testname: paid ok");
951   is($bt->invoice_amount, '-36.85000', "$testname: bt invoice amount for ap was assigned");
952
953   my $bt2           = create_bank_transaction(record        => $invoice,
954                                               amount        => 100,
955                                               bank_chart_id => $bank->id,
956                                               transdate     => DateTime->today->add(days => 10),
957                                              );
958   $::form->{invoice_ids} = {
959     $bt2->id => [ $invoice->id ]
960   };
961
962   save_btcontroller_to_string();
963   $invoice->load;
964   $bt2->load;
965
966   is($invoice->amount   , '136.85000', "$testname: amount ok");
967   is($invoice->netamount, '115.00000', "$testname: netamount ok");
968   is($bt2->amount,        '-100.00000',"$testname: bt amount ok");
969   is($invoice->paid     , '136.85000', "$testname: paid ok");
970   is($bt2->invoice_amount,'-100.00000', "$testname: bt invoice amount for ap was assigned");
971
972   return $invoice;
973 };
974
975 sub test_neg_sales_invoice {
976
977   my $testname = 'test_neg_sales_invoice';
978
979   my $part1 = new_part(   partnumber => 'Funkenhaube öhm')->save;
980   my $part2 = new_service(partnumber => 'Service-Pauschale Pasch!')->save;
981
982   my $neg_sales_inv = create_sales_invoice(
983     invnumber    => '20172201',
984     customer     => $customer,
985     taxincluded  => 0,
986     invoiceitems => [ create_invoice_item(part => $part1, qty =>  3, sellprice => 70),
987                       create_invoice_item(part => $part2, qty => 10, sellprice => -50),
988                     ]
989   );
990   my $bt            = create_bank_transaction(record        => $neg_sales_inv,
991                                                                 amount        => $neg_sales_inv->amount,
992                                                                 bank_chart_id => $bank->id,
993                                                                 transdate     => DateTime->today,
994                                                                );
995   $::form->{invoice_ids} = {
996     $bt->id => [ $neg_sales_inv->id ]
997   };
998
999   save_btcontroller_to_string();
1000
1001   $neg_sales_inv->load;
1002   $bt->load;
1003   is($neg_sales_inv->amount   , '-345.10000', "$testname: amount ok");
1004   is($neg_sales_inv->netamount, '-290.00000', "$testname: netamount ok");
1005   is($neg_sales_inv->paid     , '-345.10000', "$testname: paid ok");
1006   is($bt->amount              , '-345.10000', "$testname: bt amount ok");
1007   is($bt->invoice_amount      , '-345.10000', "$testname: bt invoice_amount ok");
1008 }
1009
1010 sub test_bt_rule1 {
1011
1012   my $testname = 'test_bt_rule1';
1013
1014   $ar_transaction = test_ar_transaction(invnumber => 'bt_rule1');
1015
1016   my $bt = create_bank_transaction(record => $ar_transaction) or die "Couldn't create bank_transaction";
1017
1018   $ar_transaction->load;
1019   $bt->load;
1020   is($ar_transaction->paid   , '0.00000' , "$testname: not paid");
1021   is($bt->invoice_amount     , '0.00000' , "$testname: bt invoice amount was not assigned");
1022
1023   my $bt_controller = SL::Controller::BankTransaction->new;
1024   $::form->{dont_render_for_test} = 1;
1025   $::form->{filter}{bank_account} = $bank_account->id;
1026   my ( $bt_transactions, $proposals ) = $bt_controller->action_list;
1027
1028   is(scalar(@$bt_transactions)         , 1  , "$testname: one bank_transaction");
1029   is($bt_transactions->[0]->{agreement}, 20 , "$testname: agreement == 20");
1030   my $match = join ( ' ',@{$bt_transactions->[0]->{rule_matches}});
1031   #print "rule_matches='".$match."'\n";
1032   is($match,
1033      "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) ",
1034      "$testname: rule_matches ok");
1035   $bt->invoice_amount($bt->amount);
1036   $bt->save;
1037   is($bt->invoice_amount     , '119.00000' , "$testname: bt invoice amount now set");
1038 };
1039
1040 sub test_sepa_export {
1041
1042   my $testname = 'test_sepa_export';
1043
1044   $ar_transaction = test_ar_transaction(invnumber => 'sepa1');
1045
1046   my $bt  = create_bank_transaction(record => $ar_transaction) or die "Couldn't create bank_transaction";
1047   my $se  = create_sepa_export();
1048   my $sei = create_sepa_export_item(
1049     chart_id       => $bank->id,
1050     ar_id          => $ar_transaction->id,
1051     sepa_export_id => $se->id,
1052     vc_iban        => $customer->iban,
1053     vc_bic         => $customer->bic,
1054     vc_mandator_id => $customer->mandator_id,
1055     vc_depositor   => $customer->depositor,
1056     amount         => $ar_transaction->amount,
1057   );
1058   require SL::SEPA::XML;
1059   my $sepa_xml   = SL::SEPA::XML->new('company'     => $customer->name,
1060                                       'creditor_id' => "id",
1061                                       'src_charset' => 'UTF-8',
1062                                       'message_id'  => "test",
1063                                       'grouped'     => 1,
1064                                       'collection'  => 1,
1065                                      );
1066   is($sepa_xml->{company}    , 'Test Customer OLE S.L. Ardbaerg AB');
1067
1068   $ar_transaction->load;
1069   $bt->load;
1070   $sei->load;
1071   is($ar_transaction->paid   , '0.00000' , "$testname: sepa1 not paid");
1072   is($bt->invoice_amount     , '0.00000' , "$testname: bt invoice amount was not assigned");
1073   is($bt->amount             , '119.00000' , "$testname: bt amount ok");
1074   is($sei->amount            , '119.00000' , "$testname: sepa export amount ok");
1075
1076   my $bt_controller = SL::Controller::BankTransaction->new;
1077   $::form->{dont_render_for_test} = 1;
1078   $::form->{filter}{bank_account} = $bank_account->id;
1079   my ( $bt_transactions, $proposals ) = $bt_controller->action_list;
1080
1081   is(scalar(@$bt_transactions)         , 1  , "$testname: one bank_transaction");
1082   is($bt_transactions->[0]->{agreement}, 25 , "$testname: agreement == 25");
1083   my $match = join ( ' ',@{$bt_transactions->[0]->{rule_matches}});
1084   is($match,
1085      "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) ",
1086      "$testname: rule_matches ok");
1087 };
1088
1089 sub test_two_banktransactions {
1090
1091   my $testname = 'two_banktransactions';
1092
1093   my $ar_transaction_1 = test_ar_transaction(invnumber => 'salesinv10000' , amount => 2912.00 );
1094   my $bt1 = create_bank_transaction(record        => $ar_transaction_1,
1095                                     amount        => $ar_transaction_1->amount,
1096                                     purpose       => "Rechnung10000 beinahe",
1097                                     bank_chart_id => $bank->id,
1098                                   ) or die "Couldn't create bank_transaction";
1099
1100   my $bt2 = create_bank_transaction(record        => $ar_transaction_1,
1101                                     amount        => $ar_transaction_1->amount + 0.01,
1102                                     purpose       => "sicher salesinv20000 vielleicht",
1103                                     bank_chart_id => $bank->id,
1104                                   ) or die "Couldn't create bank_transaction";
1105
1106   my ($agreement1, $rule_matches1) = $bt1->get_agreement_with_invoice($ar_transaction_1);
1107   is($agreement1, 19, "bt1 19 points for ar_transaction_1 in $testname ok");
1108   #print "rule_matches1=".$rule_matches1."\n";
1109   is($rule_matches1,
1110      "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) ",
1111      "$testname: rule_matches ok");
1112   my ($agreement2, $rule_matches2) = $bt2->get_agreement_with_invoice($ar_transaction_1);
1113   is($agreement2, 11, "bt2 11 points for ar_transaction_1 in $testname ok");
1114   is($rule_matches2,
1115      "remote_account_number(3) depositor_matches(2) remote_name(2) payment_within_30_days(1) datebonus0(3) ",
1116      "$testname: rule_matches ok");
1117
1118   my $ar_transaction_2 = test_ar_transaction(invnumber => 'salesinv20000' , amount => 2912.01 );
1119   my $ar_transaction_3 = test_ar_transaction(invnumber => 'zweitemit10000', amount => 2912.00 );
1120      ($agreement1, $rule_matches1) = $bt1->get_agreement_with_invoice($ar_transaction_2);
1121
1122   is($agreement1, 11, "bt1 11 points for ar_transaction_2 in $testname ok");
1123
1124      ($agreement2, $rule_matches2) = $bt2->get_agreement_with_invoice($ar_transaction_2);
1125   is($agreement2, 20, "bt2 20 points for ar_transaction_2 in $testname ok");
1126
1127      ($agreement2, $rule_matches2) = $bt2->get_agreement_with_invoice($ar_transaction_1);
1128   is($agreement2, 11, "bt2 11 points for ar_transaction_1 in $testname ok");
1129
1130   my $bt3 = create_bank_transaction(record        => $ar_transaction_3,
1131                                     amount        => $ar_transaction_3->amount,
1132                                     purpose       => "sicher Rechnung10000 vielleicht",
1133                                     bank_chart_id => $bank->id,
1134                                   ) or die "Couldn't create bank_transaction";
1135
1136   my ($agreement3, $rule_matches3) = $bt3->get_agreement_with_invoice($ar_transaction_3);
1137   is($agreement3, 19, "bt3 19 points for ar_transaction_3 in $testname ok");
1138
1139   $bt2->delete;
1140   $ar_transaction_2->delete;
1141
1142   #nun sollten zwei gleichwertige Rechnungen $ar_transaction_1 und $ar_transaction_3 für $bt1 gefunden werden
1143   #aber es darf keine Proposals geben mit mehreren Rechnungen
1144   my $bt_controller = SL::Controller::BankTransaction->new;
1145   $::form->{dont_render_for_test} = 1;
1146   $::form->{filter}{bank_account} = $bank_account->id;
1147   my ( $bt_transactions, $proposals ) = $bt_controller->action_list;
1148
1149   is(scalar(@$bt_transactions)   , 2  , "$testname: two bank_transaction");
1150   is(scalar(@$proposals)         , 0  , "$testname: no proposals");
1151
1152   $ar_transaction_3->delete;
1153
1154   # Jetzt gibt es zwei Kontobewegungen mit gleichen Punkten für eine Rechnung.
1155   # hier darf es auch keine Proposals geben
1156
1157   ( $bt_transactions, $proposals ) = $bt_controller->action_list;
1158
1159   is(scalar(@$bt_transactions)   , 2  , "$testname: two bank_transaction");
1160   # odyn testfall - anforderungen so (noch) nicht in kivi
1161   # is(scalar(@$proposals)         , 0  , "$testname: no proposals");
1162
1163   # Jetzt gibt es zwei Kontobewegungen für eine Rechnung.
1164   # eine Bewegung bekommt mehr Punkte
1165   # hier darf es auch keine Proposals geben
1166   $bt3->update_attributes( purpose => "fuer Rechnung salesinv10000");
1167
1168   ( $bt_transactions, $proposals ) = $bt_controller->action_list;
1169
1170   is(scalar(@$bt_transactions)   , 2  , "$testname: two bank_transaction");
1171   # odyn testfall - anforderungen so (noch) nicht in kivi
1172   # is(scalar(@$proposals)         , 1  , "$testname: one proposal");
1173
1174 };
1175 sub test_closedto {
1176
1177   my $testname = 'closedto';
1178
1179   my $ar_transaction_1 = test_ar_transaction(invnumber => 'salesinv10000' , amount => 2912.00 );
1180   my $bt1 = create_bank_transaction(record        => $ar_transaction_1,
1181                                     amount        => $ar_transaction_1->amount,
1182                                     purpose       => "Rechnung10000 beinahe",
1183                                     bank_chart_id => $bank->id,
1184                                   ) or die "Couldn't create bank_transaction";
1185
1186   $bt1->valutadate(DateTime->new(year => 2019, month => 12, day => 30));
1187   $bt1->save();
1188
1189   is($bt1->closed_period, 0, "$testname undefined closedto");
1190
1191   my $defaults = SL::DB::Manager::Default->get_all(limit => 1)->[0];
1192   $defaults->closedto(DateTime->new(year => 2019, month => 12, day => 30));
1193   $defaults->save();
1194   $::instance_conf->reload->data;
1195   $bt1->load();
1196
1197   is($bt1->closed_period, 1, "$testname defined and same date closedto");
1198
1199   $bt1->valutadate(DateTime->new(year => 2019, month => 12, day => 31));
1200   $bt1->save();
1201   $bt1->load();
1202
1203   is($bt1->closed_period, 0, "$testname defined closedto and next date valuta");
1204
1205 }
1206
1207 1;