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