Merge pull request #11 from freiphone/patch-3
[kivitendo-erp.git] / t / bank / bank_transactions.t
1 use Test::More tests => 130;
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::Buchungsgruppe;
14 use SL::DB::Currency;
15 use SL::DB::Customer;
16 use SL::DB::Vendor;
17 use SL::DB::Invoice;
18 use SL::DB::Unit;
19 use SL::DB::Part;
20 use SL::DB::TaxZone;
21 use SL::DB::BankAccount;
22 use SL::DB::PaymentTerm;
23 use SL::DB::PurchaseInvoice;
24 use SL::DB::BankTransaction;
25 use SL::Controller::BankTransaction;
26 use SL::Dev::ALL qw(:ALL);
27 use Data::Dumper;
28
29 my ($customer, $vendor, $currency_id, $unit, $tax, $tax7, $tax_9, $payment_terms, $bank_account);
30 my ($transdate1, $transdate2, $currency);
31 my ($ar_chart,$bank,$ar_amount_chart, $ap_chart, $ap_amount_chart);
32 my ($ar_transaction, $ap_transaction);
33
34 sub clear_up {
35
36   SL::DB::Manager::BankTransaction->delete_all(all => 1);
37   SL::DB::Manager::InvoiceItem->delete_all(all => 1);
38   SL::DB::Manager::InvoiceItem->delete_all(all => 1);
39   SL::DB::Manager::Invoice->delete_all(all => 1);
40   SL::DB::Manager::PurchaseInvoice->delete_all(all => 1);
41   SL::DB::Manager::Part->delete_all(all => 1);
42   SL::DB::Manager::Customer->delete_all(all => 1);
43   SL::DB::Manager::Vendor->delete_all(all => 1);
44   SL::DB::Manager::SepaExportItem->delete_all(all => 1);
45   SL::DB::Manager::SepaExport->delete_all(all => 1);
46   SL::DB::Manager::BankAccount->delete_all(all => 1);
47   SL::DB::Manager::PaymentTerm->delete_all(all => 1);
48   SL::DB::Manager::Currency->delete_all(where => [ name => 'CUR' ]);
49 };
50
51 sub save_btcontroller_to_string {
52   my $output;
53   open(my $outputFH, '>', \$output) or die;
54   my $oldFH = select $outputFH;
55
56   my $bt_controller = SL::Controller::BankTransaction->new;
57   $bt_controller->action_save_invoices;
58
59   select $oldFH;
60   close $outputFH;
61   return $output;
62 }
63
64 # starting test:
65 Support::TestSetup::login();
66
67 clear_up();
68 reset_state(); # initialise customers/vendors/bank/currency/...
69
70 test1();
71
72 test_overpayment_with_partialpayment();
73 test_overpayment();
74 test_skonto_exact();
75 test_two_invoices();
76 test_partial_payment();
77 test_credit_note();
78 test_ap_transaction();
79 test_neg_ap_transaction();
80 test_ap_payment_transaction();
81 test_ap_payment_part_transaction();
82 test_neg_sales_invoice();
83
84 test_bt_rule1();
85 test_sepa_export();
86
87 # remove all created data at end of test
88 clear_up();
89
90 done_testing();
91
92 ###### functions for setting up data
93
94 sub reset_state {
95   my %params = @_;
96
97   $params{$_} ||= {} for qw(unit customer tax vendor);
98
99   clear_up();
100
101   $transdate1 = DateTime->today;
102   $transdate2 = DateTime->today->add(days => 5);
103
104   $tax             = SL::DB::Manager::Tax->find_by(taxkey => 3, rate => 0.19, %{ $params{tax} }) || croak "No tax";
105   $tax7            = SL::DB::Manager::Tax->find_by(taxkey => 2, rate => 0.07)                    || croak "No tax for 7\%";
106   $tax_9           = SL::DB::Manager::Tax->find_by(taxkey => 9, rate => 0.19, %{ $params{tax} }) || croak "No tax";
107
108   $currency_id     = $::instance_conf->get_currency_id;
109
110   $bank_account     =  SL::DB::BankAccount->new(
111     account_number  => '123',
112     bank_code       => '123',
113     iban            => '123',
114     bic             => '123',
115     bank            => '123',
116     chart_id        => SL::DB::Manager::Chart->find_by(description => 'Bank')->id,
117     name            => SL::DB::Manager::Chart->find_by(description => 'Bank')->description,
118   )->save;
119
120   $customer = new_customer(
121     name                      => 'Test Customer',
122     iban                      => 'DE12500105170648489890',
123     bic                       => 'TESTBIC',
124     account_number            => '648489890',
125     mandate_date_of_signature => $transdate1,
126     mandator_id               => 'foobar',
127     bank                      => 'Geizkasse',
128     bank_code                 => 'G1235',
129     depositor                 => 'Test Customer',
130     customernumber            => 'CUST1704',
131   )->save;
132
133   $payment_terms = create_payment_terms();
134
135   $vendor = new_vendor(
136     name           => 'Test Vendor',
137     payment_id     => $payment_terms->id,
138     iban           => 'DE12500105170648489890',
139     bic            => 'TESTBIC',
140     account_number => '648489890',
141     bank           => 'Geizkasse',
142     bank_code      => 'G1235',
143     depositor      => 'Test Vendor',
144     vendornumber   => 'VEND1704',
145   )->save;
146
147   $ar_chart        = SL::DB::Manager::Chart->find_by( accno => '1400' ); # Forderungen
148   $ap_chart        = SL::DB::Manager::Chart->find_by( accno => '1600' ); # Verbindlichkeiten
149   $bank            = SL::DB::Manager::Chart->find_by( accno => '1200' ); # Bank
150   $ar_amount_chart = SL::DB::Manager::Chart->find_by( accno => '8400' ); # Erlöse
151   $ap_amount_chart = SL::DB::Manager::Chart->find_by( accno => '3400' ); # Wareneingang 19%
152
153 }
154
155 sub test_ar_transaction {
156   my (%params) = @_;
157   my $netamount = 100;
158   my $amount    = $params{amount} || $::form->round_amount(100 * 1.19,2);
159   my $invoice   = SL::DB::Invoice->new(
160       invoice      => 0,
161       invnumber    => $params{invnumber} || undef, # let it use its own invnumber
162       amount       => $amount,
163       netamount    => $netamount,
164       transdate    => $transdate1,
165       taxincluded  => 0,
166       customer_id  => $customer->id,
167       taxzone_id   => $customer->taxzone_id,
168       currency_id  => $currency_id,
169       transactions => [],
170       payment_id   => $params{payment_id} || undef,
171       notes        => 'test_ar_transaction',
172   );
173   $invoice->add_ar_amount_row(
174     amount => $invoice->netamount,
175     chart  => $ar_amount_chart,
176     tax_id => $tax->id,
177   );
178
179   $invoice->create_ar_row(chart => $ar_chart);
180   $invoice->save;
181
182   is($invoice->currency_id , $currency_id , 'currency_id has been saved');
183   is($invoice->netamount   , 100          , 'ar amount has been converted');
184   is($invoice->amount      , 119          , 'ar amount has been converted');
185   is($invoice->taxincluded , 0            , 'ar transaction doesn\'t have taxincluded');
186
187   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');
188   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');
189
190   return $invoice;
191 };
192
193 sub test_ap_transaction {
194   my (%params) = @_;
195   my $testname = 'test_ap_transaction';
196
197   my $netamount = 100;
198   my $amount    = $::form->round_amount($netamount * 1.19,2);
199   my $invoice   = SL::DB::PurchaseInvoice->new(
200     invoice      => 0,
201     invnumber    => $params{invnumber} || $testname,
202     amount       => $amount,
203     netamount    => $netamount,
204     transdate    => $transdate1,
205     taxincluded  => 0,
206     vendor_id    => $vendor->id,
207     taxzone_id   => $vendor->taxzone_id,
208     currency_id  => $currency_id,
209     transactions => [],
210     notes        => 'test_ap_transaction',
211   );
212   $invoice->add_ap_amount_row(
213     amount     => $invoice->netamount,
214     chart      => $ap_amount_chart,
215     tax_id     => $tax_9->id,
216   );
217
218   $invoice->create_ap_row(chart => $ap_chart);
219   $invoice->save;
220
221   is($invoice->currency_id , $currency_id , "$testname: currency_id has been saved");
222   is($invoice->netamount   , 100          , "$testname: ap amount has been converted");
223   is($invoice->amount      , 119          , "$testname: ap amount has been converted");
224   is($invoice->taxincluded , 0            , "$testname: ap transaction doesn\'t have taxincluded");
225
226   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');
227   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');
228
229   return $invoice;
230 };
231
232 ###### test cases
233
234 sub test1 {
235
236   my $testname = 'test1';
237
238   $ar_transaction = test_ar_transaction(invnumber => 'salesinv1');
239
240   my $bt = create_bank_transaction(record => $ar_transaction) or die "Couldn't create bank_transaction";
241
242   $::form->{invoice_ids} = {
243     $bt->id => [ $ar_transaction->id ]
244   };
245
246   save_btcontroller_to_string();
247
248   $ar_transaction->load;
249   $bt->load;
250   is($ar_transaction->paid   , '119.00000' , "$testname: salesinv1 was paid");
251   is($ar_transaction->closed , 1           , "$testname: salesinv1 is closed");
252   is($bt->invoice_amount     , '119.00000' , "$testname: bt invoice amount was assigned");
253
254 };
255
256 sub test_skonto_exact {
257
258   my $testname = 'test_skonto_exact';
259
260   $ar_transaction = test_ar_transaction(invnumber => 'salesinv skonto',
261                                         payment_id => $payment_terms->id,
262                                        );
263
264   my $bt = create_bank_transaction(record        => $ar_transaction,
265                                    bank_chart_id => $bank->id,
266                                    amount        => $ar_transaction->amount_less_skonto
267                                   ) or die "Couldn't create bank_transaction";
268
269   $::form->{invoice_ids} = {
270     $bt->id => [ $ar_transaction->id ]
271   };
272   $::form->{invoice_skontos} = {
273     $bt->id => [ 'with_skonto_pt' ]
274   };
275
276   save_btcontroller_to_string();
277
278   $ar_transaction->load;
279   $bt->load;
280   is($ar_transaction->paid   , '119.00000' , "$testname: salesinv skonto was paid");
281   is($ar_transaction->closed , 1           , "$testname: salesinv skonto is closed");
282   is($bt->invoice_amount     , '113.05000' , "$testname: bt invoice amount was assigned");
283
284 };
285
286 sub test_two_invoices {
287
288   my $testname = 'test_two_invoices';
289
290   my $ar_transaction_1 = test_ar_transaction(invnumber => 'salesinv_1');
291   my $ar_transaction_2 = test_ar_transaction(invnumber => 'salesinv_2');
292
293   my $bt = create_bank_transaction(record        => $ar_transaction_1,
294                                    amount        => ($ar_transaction_1->amount + $ar_transaction_2->amount),
295                                    purpose       => "Rechnungen " . $ar_transaction_1->invnumber . " und " . $ar_transaction_2->invnumber,
296                                    bank_chart_id => $bank->id,
297                                   ) or die "Couldn't create bank_transaction";
298
299   my ($agreement, $rule_matches) = $bt->get_agreement_with_invoice($ar_transaction_1);
300   is($agreement, 16, "points for ar_transaction_1 in test_two_invoices ok");
301
302   $::form->{invoice_ids} = {
303     $bt->id => [ $ar_transaction_1->id, $ar_transaction_2->id ]
304   };
305
306   save_btcontroller_to_string();
307
308   $ar_transaction_1->load;
309   $ar_transaction_2->load;
310   $bt->load;
311
312   is($ar_transaction_1->paid   , '119.00000' , "$testname: salesinv_1 was paid");
313   is($ar_transaction_1->closed , 1           , "$testname: salesinv_1 is closed");
314   is($ar_transaction_2->paid   , '119.00000' , "$testname: salesinv_2 was paid");
315   is($ar_transaction_2->closed , 1           , "$testname: salesinv_2 is closed");
316   is($bt->invoice_amount       , '238.00000' , "$testname: bt invoice amount was assigned");
317
318 };
319
320 sub test_overpayment {
321
322   my $testname = 'test_overpayment';
323
324   $ar_transaction = test_ar_transaction(invnumber => 'salesinv overpaid');
325
326   # amount 135 > 119
327   my $bt = create_bank_transaction(record        => $ar_transaction,
328                                    bank_chart_id => $bank->id,
329                                    amount        => 135
330                                   ) or die "Couldn't create bank_transaction";
331
332   $::form->{invoice_ids} = {
333     $bt->id => [ $ar_transaction->id ]
334   };
335
336   save_btcontroller_to_string();
337
338   $ar_transaction->load;
339   $bt->load;
340
341   is($ar_transaction->paid                     , '135.00000' , "$testname: 'salesinv overpaid' was overpaid");
342   is($bt->invoice_amount                       , '135.00000' , "$testname: bt invoice amount was assigned overpaid amount");
343 { local $TODO = 'this currently fails because closed ignores over-payments, see commit d90966c7';
344   is($ar_transaction->closed                   , 0           , "$testname: 'salesinv overpaid' is open (via 'closed' method')");
345 }
346   is($ar_transaction->open_amount == 0 ? 1 : 0 , 0           , "$testname: 'salesinv overpaid is open (via amount-paid)");
347
348 };
349
350 sub test_overpayment_with_partialpayment {
351
352   # two payments on different days, 10 and 119. If there is only one invoice we want it be overpaid.
353   my $testname = 'test_overpayment_with_partialpayment';
354
355   $ar_transaction = test_ar_transaction(invnumber => 'salesinv overpaid partial');
356
357   my $bt_1 = create_bank_transaction(record        => $ar_transaction,
358                                      bank_chart_id => $bank->id,
359                                      amount        =>  10
360                                     ) or die "Couldn't create bank_transaction";
361   my $bt_2 = create_bank_transaction(record        => $ar_transaction,
362                                      amount        => 119,
363                                      transdate     => DateTime->today->add(days => 5),
364                                      bank_chart_id => $bank->id,
365                                     ) or die "Couldn't create bank_transaction";
366
367   $::form->{invoice_ids} = {
368     $bt_1->id => [ $ar_transaction->id ]
369   };
370   save_btcontroller_to_string();
371
372   $::form->{invoice_ids} = {
373     $bt_2->id => [ $ar_transaction->id ]
374   };
375   save_btcontroller_to_string();
376
377   $ar_transaction->load;
378   $bt_1->load;
379   $bt_2->load;
380
381   is($ar_transaction->paid , '129.00000' , "$testname: 'salesinv overpaid partial' was overpaid");
382   is($bt_1->invoice_amount ,  '10.00000' , "$testname: bt_1 invoice amount was assigned overpaid amount");
383   is($bt_2->invoice_amount , '119.00000' , "$testname: bt_2 invoice amount was assigned overpaid amount");
384
385 };
386
387 sub test_partial_payment {
388
389   my $testname = 'test_partial_payment';
390
391   $ar_transaction = test_ar_transaction(invnumber => 'salesinv partial payment');
392
393   # amount 100 < 119
394   my $bt = create_bank_transaction(record        => $ar_transaction,
395                                    bank_chart_id => $bank->id,
396                                    amount        => 100
397                                   ) or die "Couldn't create bank_transaction";
398
399   $::form->{invoice_ids} = {
400     $bt->id => [ $ar_transaction->id ]
401   };
402
403   save_btcontroller_to_string();
404
405   $ar_transaction->load;
406   $bt->load;
407
408   is($ar_transaction->paid , '100.00000' , "$testname: 'salesinv partial payment' was partially paid");
409   is($bt->invoice_amount   , '100.00000' , "$testname: bt invoice amount was assigned partially paid amount");
410
411 };
412
413 sub test_credit_note {
414
415   my $testname = 'test_credit_note';
416
417   my $part1 = new_part(   partnumber => 'T4254')->save;
418   my $part2 = new_service(partnumber => 'Serv1')->save;
419   my $credit_note = create_credit_note(
420     invnumber    => 'cn 1',
421     customer     => $customer,
422     taxincluded  => 0,
423     invoiceitems => [ create_invoice_item(part => $part1, qty =>  3, sellprice => 70),
424                       create_invoice_item(part => $part2, qty => 10, sellprice => 50),
425                     ]
426   );
427   my $bt            = create_bank_transaction(record        => $credit_note,
428                                                                 amount        => $credit_note->amount,
429                                                                 bank_chart_id => $bank->id,
430                                                                 transdate     => DateTime->today->add(days => 10),
431                                                                );
432   my ($agreement, $rule_matches) = $bt->get_agreement_with_invoice($credit_note);
433   is($agreement, 13, "points for credit note ok");
434   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");
435
436   $::form->{invoice_ids} = {
437     $bt->id => [ $credit_note->id ]
438   };
439
440   save_btcontroller_to_string();
441
442   $credit_note->load;
443   $bt->load;
444   is($credit_note->amount   , '-844.90000', "$testname: amount ok");
445   is($credit_note->netamount, '-710.00000', "$testname: netamount ok");
446   is($credit_note->paid     , '-844.90000', "$testname: paid ok");
447 }
448
449 sub test_neg_ap_transaction {
450   my (%params) = @_;
451   my $testname = 'test_neg_ap_transaction';
452   my $netamount = -20;
453   my $amount    = $::form->round_amount($netamount * 1.19,2);
454   my $invoice   = SL::DB::PurchaseInvoice->new(
455     invoice      => 0,
456     invnumber    => $params{invnumber} || 'test_neg_ap_transaction',
457     amount       => $amount,
458     netamount    => $netamount,
459     transdate    => $transdate1,
460     taxincluded  => 0,
461     vendor_id    => $vendor->id,
462     taxzone_id   => $vendor->taxzone_id,
463     currency_id  => $currency_id,
464     transactions => [],
465     notes        => 'test_neg_ap_transaction',
466   );
467   $invoice->add_ap_amount_row(
468     amount     => $invoice->netamount,
469     chart      => $ap_amount_chart,
470     tax_id     => $tax_9->id,
471   );
472
473   $invoice->create_ap_row(chart => $ap_chart);
474   $invoice->save;
475
476   is($invoice->netamount, -20  , "$testname: netamount ok");
477   is($invoice->amount   , -23.8, "$testname: amount ok");
478
479   my $bt            = create_bank_transaction(record        => $invoice,
480                                               amount        => $invoice->amount,
481                                               bank_chart_id => $bank->id,
482                                               transdate     => DateTime->today->add(days => 10),
483                                                                );
484   my ($agreement, $rule_matches) = $bt->get_agreement_with_invoice($invoice);
485   is($agreement, 15, "points for negative ap transaction ok");
486
487   $::form->{invoice_ids} = {
488     $bt->id => [ $invoice->id ]
489   };
490
491   save_btcontroller_to_string();
492
493   $invoice->load;
494   $bt->load;
495
496   is($invoice->amount   , '-23.80000', "$testname: amount ok");
497   is($invoice->netamount, '-20.00000', "$testname: netamount ok");
498   is($invoice->paid     , '-23.80000', "$testname: paid ok");
499   is($bt->invoice_amount, '23.80000', "$testname: bt invoice amount for ap was assigned");
500
501   return $invoice;
502 };
503
504 sub test_ap_payment_transaction {
505   my (%params) = @_;
506   my $testname = 'test_ap_payment_transaction';
507   my $netamount = 115;
508   my $amount    = $::form->round_amount($netamount * 1.19,2);
509   my $invoice   = SL::DB::PurchaseInvoice->new(
510     invoice      => 0,
511     invnumber    => $params{invnumber} || $testname,
512     amount       => $amount,
513     netamount    => $netamount,
514     transdate    => $transdate1,
515     taxincluded  => 0,
516     vendor_id    => $vendor->id,
517     taxzone_id   => $vendor->taxzone_id,
518     currency_id  => $currency_id,
519     transactions => [],
520     notes        => $testname,
521   );
522   $invoice->add_ap_amount_row(
523     amount     => $invoice->netamount,
524     chart      => $ap_amount_chart,
525     tax_id     => $tax_9->id,
526   );
527
528   $invoice->create_ap_row(chart => $ap_chart);
529   $invoice->save;
530
531   is($invoice->netamount, 115  , "$testname: netamount ok");
532   is($invoice->amount   , 136.85, "$testname: amount ok");
533
534   my $bt            = create_bank_transaction(record        => $invoice,
535                                               amount        => $invoice->amount,
536                                               bank_chart_id => $bank->id,
537                                               transdate     => DateTime->today->add(days => 10),
538                                              );
539   $::form->{invoice_ids} = {
540     $bt->id => [ $invoice->id ]
541   };
542
543   save_btcontroller_to_string();
544
545   $invoice->load;
546   $bt->load;
547
548   is($invoice->amount   , '136.85000', "$testname: amount ok");
549   is($invoice->netamount, '115.00000', "$testname: netamount ok");
550   is($bt->amount, '-136.85000', "$testname: bt amount ok");
551   is($invoice->paid     , '136.85000', "$testname: paid ok");
552   is($bt->invoice_amount, '-136.85000', "$testname: bt invoice amount for ap was assigned");
553
554   return $invoice;
555 };
556
557 sub test_ap_payment_part_transaction {
558   my (%params) = @_;
559   my $testname = 'test_ap_payment_p_transaction';
560   my $netamount = 115;
561   my $amount    = $::form->round_amount($netamount * 1.19,2);
562   my $invoice   = SL::DB::PurchaseInvoice->new(
563     invoice      => 0,
564     invnumber    => $params{invnumber} || $testname,
565     amount       => $amount,
566     netamount    => $netamount,
567     transdate    => $transdate1,
568     taxincluded  => 0,
569     vendor_id    => $vendor->id,
570     taxzone_id   => $vendor->taxzone_id,
571     currency_id  => $currency_id,
572     transactions => [],
573     notes        => $testname,
574   );
575   $invoice->add_ap_amount_row(
576     amount     => $invoice->netamount,
577     chart      => $ap_amount_chart,
578     tax_id     => $tax_9->id,
579   );
580
581   $invoice->create_ap_row(chart => $ap_chart);
582   $invoice->save;
583
584   is($invoice->netamount, 115  , "$testname: netamount ok");
585   is($invoice->amount   , 136.85, "$testname: amount ok");
586
587   my $bt            = create_bank_transaction(record        => $invoice,
588                                               amount        => $invoice->amount-100,
589                                               bank_chart_id => $bank->id,
590                                               transdate     => DateTime->today->add(days => 10),
591                                              );
592   $::form->{invoice_ids} = {
593     $bt->id => [ $invoice->id ]
594   };
595
596   save_btcontroller_to_string();
597
598   $invoice->load;
599   $bt->load;
600
601   is($invoice->amount   , '136.85000', "$testname: amount ok");
602   is($invoice->netamount, '115.00000', "$testname: netamount ok");
603   is($bt->amount,         '-36.85000', "$testname: bt amount ok");
604   is($invoice->paid     ,  '36.85000', "$testname: paid ok");
605   is($bt->invoice_amount, '-36.85000', "$testname: bt invoice amount for ap was assigned");
606
607   my $bt2           = create_bank_transaction(record        => $invoice,
608                                               amount        => 100,
609                                               bank_chart_id => $bank->id,
610                                               transdate     => DateTime->today->add(days => 10),
611                                              );
612   $::form->{invoice_ids} = {
613     $bt2->id => [ $invoice->id ]
614   };
615
616   save_btcontroller_to_string();
617   $invoice->load;
618   $bt2->load;
619
620   is($invoice->amount   , '136.85000', "$testname: amount ok");
621   is($invoice->netamount, '115.00000', "$testname: netamount ok");
622   is($bt2->amount,        '-100.00000',"$testname: bt amount ok");
623   is($invoice->paid     , '136.85000', "$testname: paid ok");
624   is($bt2->invoice_amount,'-100.00000', "$testname: bt invoice amount for ap was assigned");
625
626   return $invoice;
627 };
628
629 sub test_neg_sales_invoice {
630
631   my $testname = 'test_neg_sales_invoice';
632
633   my $part1 = new_part(   partnumber => 'Funkenhaube öhm')->save;
634   my $part2 = new_service(partnumber => 'Service-Pauschale Pasch!')->save;
635
636   my $neg_sales_inv = create_sales_invoice(
637     invnumber    => '20172201',
638     customer     => $customer,
639     taxincluded  => 0,
640     invoiceitems => [ create_invoice_item(part => $part1, qty =>  3, sellprice => 70),
641                       create_invoice_item(part => $part2, qty => 10, sellprice => -50),
642                     ]
643   );
644   my $bt            = create_bank_transaction(record        => $neg_sales_inv,
645                                                                 amount        => $neg_sales_inv->amount,
646                                                                 bank_chart_id => $bank->id,
647                                                                 transdate     => DateTime->today,
648                                                                );
649   $::form->{invoice_ids} = {
650     $bt->id => [ $neg_sales_inv->id ]
651   };
652
653   save_btcontroller_to_string();
654
655   $neg_sales_inv->load;
656   $bt->load;
657   is($neg_sales_inv->amount   , '-345.10000', "$testname: amount ok");
658   is($neg_sales_inv->netamount, '-290.00000', "$testname: netamount ok");
659   is($neg_sales_inv->paid     , '-345.10000', "$testname: paid ok");
660   is($bt->amount              , '-345.10000', "$testname: bt amount ok");
661   is($bt->invoice_amount      , '-345.10000', "$testname: bt invoice_amount ok");
662 }
663
664 sub test_bt_rule1 {
665
666   my $testname = 'test_bt_rule1';
667
668   $ar_transaction = test_ar_transaction(invnumber => 'bt_rule1');
669
670   my $bt = create_bank_transaction(record => $ar_transaction) or die "Couldn't create bank_transaction";
671
672   $ar_transaction->load;
673   $bt->load;
674   is($ar_transaction->paid   , '0.00000' , "$testname: not paid");
675   is($bt->invoice_amount     , '0.00000' , "$testname: bt invoice amount was not assigned");
676
677   my $bt_controller = SL::Controller::BankTransaction->new;
678   $::form->{dont_render_for_test} = 1;
679   $::form->{filter}{bank_account} = $bank_account->id;
680   my $bt_transactions = $bt_controller->action_list;
681
682   is(scalar(@$bt_transactions)         , 1  , "$testname: one bank_transaction");
683   is($bt_transactions->[0]->{agreement}, 20 , "$testname: agreement == 20");
684   my $match = join ( ' ',@{$bt_transactions->[0]->{rule_matches}});
685   #print "rule_matches='".$match."'\n";
686   is($match,
687      "remote_account_number(3) exact_amount(4) own_invnumber_in_purpose(5) depositor_matches(2) remote_name(2) payment_within_30_days(1) datebonus0(3) ",
688      "$testname: rule_matches ok");
689   $bt->invoice_amount($bt->amount);
690   $bt->save;
691   is($bt->invoice_amount     , '119.00000' , "$testname: bt invoice amount now set");
692 };
693
694 sub test_sepa_export {
695
696   my $testname = 'test_sepa_export';
697
698   $ar_transaction = test_ar_transaction(invnumber => 'sepa1');
699
700   my $bt  = create_bank_transaction(record => $ar_transaction) or die "Couldn't create bank_transaction";
701   my $se  = create_sepa_export();
702   my $sei = create_sepa_export_item(
703     chart_id       => $bank->id,
704     ar_id          => $ar_transaction->id,
705     sepa_export_id => $se->id,
706     vc_iban        => $customer->iban,
707     vc_bic         => $customer->bic,
708     vc_mandator_id => $customer->mandator_id,
709     vc_depositor   => $customer->depositor,
710     amount         => $ar_transaction->amount,
711   );
712
713   $ar_transaction->load;
714   $bt->load;
715   $sei->load;
716   is($ar_transaction->paid   , '0.00000' , "$testname: sepa1 not paid");
717   is($bt->invoice_amount     , '0.00000' , "$testname: bt invoice amount was not assigned");
718   is($bt->amount             , '119.00000' , "$testname: bt amount ok");
719   is($sei->amount            , '119.00000' , "$testname: sepa export amount ok");
720
721   my $bt_controller = SL::Controller::BankTransaction->new;
722   $::form->{dont_render_for_test} = 1;
723   $::form->{filter}{bank_account} = $bank_account->id;
724   my $bt_transactions = $bt_controller->action_list;
725
726   is(scalar(@$bt_transactions)         , 1  , "$testname: one bank_transaction");
727   is($bt_transactions->[0]->{agreement}, 25 , "$testname: agreement == 25");
728   my $match = join ( ' ',@{$bt_transactions->[0]->{rule_matches}});
729   is($match,
730      "remote_account_number(3) exact_amount(4) own_invnumber_in_purpose(5) depositor_matches(2) remote_name(2) payment_within_30_days(1) datebonus0(3) sepa_export_item(5) ",
731      "$testname: rule_matches ok");
732 };
733
734
735 1;