]> wagnertech.de Git - mfinanz.git/blob - t/controllers/csvimport/aptransactions.t
date error in mapping
[mfinanz.git] / t / controllers / csvimport / aptransactions.t
1 use Test::More;
2
3 use strict;
4
5 use lib 't';
6
7 use Carp;
8 use Support::TestSetup;
9 use Test::Exception;
10
11 use SL::Dev::ALL qw(:ALL);
12
13 use SL::Controller::CsvImport;
14
15 use_ok 'SL::Controller::CsvImport::APTransaction';
16
17 use SL::DB::AccTransaction;
18 use SL::DB::Buchungsgruppe;
19 use SL::DB::Chart;
20 use SL::DB::Currency;
21 use SL::DB::Employee;
22 use SL::DB::Invoice;
23 use SL::DB::TaxZone;
24 use SL::DB::Vendor;
25
26 my ($vendor, $currency_id, $employee, $taxzone, $project, $department);
27 my ($transdate, $transdate_string);
28
29 sub clear_up {
30   SL::DB::Manager::AccTransaction->delete_all (all => 1);
31   SL::DB::Manager::PurchaseInvoice->delete_all(all => 1);
32   SL::DB::Manager::Vendor->delete_all         (all => 1);
33   SL::DB::Manager::Project->delete_all        (all => 1);
34   SL::DB::Manager::Department->delete_all     (all => 1);
35 };
36
37 sub reset_state {
38   # Create test data
39   my %params = @_;
40
41   $transdate = DateTime->today_local;
42   $transdate->set_year(2019) if $transdate->year == 2020; # hardcode for 2019 in 2020, because of tax rate change in Germany
43   $transdate_string = $transdate->to_kivitendo;
44
45   $params{$_} ||= {} for qw(buchungsgruppe vendor tax);
46
47   clear_up();
48   $employee    = SL::DB::Manager::Employee->current                          || croak "No employee";
49   $taxzone     = SL::DB::Manager::TaxZone->find_by( description => 'Inland') || croak "No taxzone";
50   $currency_id = $::instance_conf->get_currency_id;
51
52   $vendor      = new_vendor(
53     currency_id => $currency_id,
54     taxzone_id  => $taxzone->id,
55     %{ $params{vendor} },
56   )->save;
57
58   $project     = SL::DB::Project->new(
59     projectnumber  => 'P1',
60     description    => 'Project X',
61     project_type   => SL::DB::Manager::ProjectType->find_by(description => 'Standard'),
62     project_status => SL::DB::Manager::ProjectStatus->find_by(name => 'running'),
63   )->save;
64
65   $department  = SL::DB::Department->new(
66     description => 'Department 1',
67   )->save;
68 }
69
70 Support::TestSetup::login();
71
72 reset_state(vendor => {vendornumber => 2});
73
74 #####
75 sub test_import {
76   my $file = shift;
77
78   my $controller = SL::Controller::CsvImport->new(
79     type => 'ap_transactions'
80   );
81   $controller->load_default_profile;
82   $controller->profile->set(
83     charset      => 'utf-8',
84     sep_char     => ',',
85     quote_char   => '"',
86     numberformat => $::myconfig{numberformat},
87     duplicates   => 'check_db',
88     duplicates_vendor_and_invnumber => 1,
89   );
90
91   my $csv_aptransactions_import = SL::Controller::CsvImport::APTransaction->new(
92     settings    => {'ap_column'          => 'Rechnung',
93                     'transaction_column' => 'AccTransaction',
94                     'max_amount_diff'    => 0.02
95                   },
96     controller => $controller,
97     file       => $file,
98   );
99
100   $csv_aptransactions_import->run(test => 0);
101
102   # don't try and save objects that have errors
103   $csv_aptransactions_import->save_objects unless scalar @{$csv_aptransactions_import->controller->data->[0]->{errors}};
104
105  return $csv_aptransactions_import->controller->data;
106 }
107
108 ##### manually create an ap transaction from scratch, testing the methods
109 $::myconfig{numberformat} = '1000.00';
110 $::myconfig{dateformat}   = 'dd.mm.yyyy';
111 my $old_locale = $::locale;
112 # set locale to en so we can match errors
113 $::locale = Locale->new('en');
114
115 my $amount = 10;
116
117 my $ap = SL::DB::PurchaseInvoice->new(
118   invoice      => 0,
119   invnumber    => 'manual invoice',
120   taxzone_id   => $taxzone->id,
121   currency_id  => $currency_id,
122   taxincluded  => 'f',
123   vendor_id    => $vendor->id,
124   transdate    => $transdate,
125   employee_id  => SL::DB::Manager::Employee->current->id,
126   transactions => [],
127 );
128
129 my $tax9 = SL::DB::Manager::Tax->find_by(rate => 0.19, taxkey => 9) || die "can't find tax with taxkey 9";
130 my $income_chart = SL::DB::Manager::Chart->find_by(accno => '3400') || die "can't find expense chart";
131
132 $ap->add_ap_amount_row(
133   amount => $amount,
134   chart  => $income_chart,
135   tax_id => $tax9->id,
136 );
137
138 $ap->recalculate_amounts; # set amount and netamount from transactions
139 is $ap->amount, '10', 'amount of manual invoice is 10';
140 is $ap->netamount, '8.4', 'netamount of manual invoice is 10';
141
142 $ap->create_ap_row( chart => SL::DB::Manager::Chart->find_by(accno => '1600', link => 'AP') );
143 my $result = $ap->validate_acc_trans();
144 is $result, 1, 'manual $ap validates';
145
146 $ap->save;
147 is ${ $ap->transactions }[0]->chart->accno, '3400', 'assigned expense chart after save ok';
148 is ${ $ap->transactions }[2]->chart->accno, '1600', 'assigned payable chart after save ok';
149 is scalar @{$ap->transactions}, 3, 'manual invoice has 3 acc_trans entries';
150
151 $ap->pay_invoice(  chart_id      => SL::DB::Manager::Chart->find_by(accno => '1200')->id, # bank
152                    amount        => $ap->open_amount,
153                    transdate     => $transdate,
154                    payment_type  => 'without_skonto',  # default if not specified
155                   );
156 $result = $ap->validate_acc_trans();
157 is $result, 1, 'manual invoice validates after payment';
158
159 #####
160 reset_state(vendor => {vendornumber => 2});
161
162 my ($entries, $entry, $file);
163 my $saved_invoices = 0;
164
165 # starting test of csv imports
166 # to debug errors in certain tests, run after test_import:
167 #   $::lxdebug->dump(0, "entry 0 errors: ", $entry->{errors}->[0]);
168 ##### basic test
169 $file = \<<"EOL";
170 datatype,vendornumber,currency_id,invnumber,taxincluded,apchart,transdate
171 datatype,accno,amount,taxkey
172 "Rechnung",2,1,"invoice 1",f,1600,"$transdate_string"
173 "AccTransaction",3400,159.48,9
174 EOL
175 $entries = test_import($file);
176 is $entries->[0]->{errors}->[0], undef, 'basic test: no errors in ap row';
177 is $entries->[1]->{errors}->[0], undef, 'basic test: no errors in acc_trans row';
178
179 $entry = $entries->[0];
180 is $entry->{object}->validate_acc_trans, 1, 'basic test: acc_trans validates';
181 is $entry->{object}->invnumber, 'invoice 1', 'basic test: invnumber ok';
182 is $entry->{object}->vendor_id, $vendor->id, 'basic test: vendor_id ok';
183 is scalar @{$entry->{object}->transactions}, 3, 'basic test: invoice 1 has 3 acc_trans entries';
184 is $::form->round_amount($entry->{object}->transactions->[0]->amount, 2), -159.48, 'basic test: invoice 1 ap amount is -159.48';
185 is $entry->{object}->direct_debit, '0', 'basic test: no direct debit';
186 is $entry->{object}->taxincluded, '0', 'basic test: taxincluded is false';
187 is $entry->{object}->amount, '189.78', 'basic test: ap amount tax not included is 189.78';
188 is $entry->{object}->netamount, '159.48', 'basic test: ap netamount tax not included is 159.48';
189
190 $saved_invoices++;
191
192 ##### test for duplicate invnumber for same vendor
193 $file = \<<"EOL";
194 datatype,vendornumber,currency_id,invnumber,taxincluded,apchart,transdate
195 datatype,accno,amount,taxkey
196 "Rechnung",2,1,"invoice 1",f,1600,"$transdate_string"
197 "AccTransaction",3400,159.48,9
198 EOL
199
200 $entries = test_import($file);
201 $entry = $entries->[0];
202 is $entry->{errors}->[0], 'Duplicate in database', 'detects duplicate invnumer for same vendor';
203
204 ##### test for duplicate invnumber for different vendor
205 my $different_vendor = new_vendor(
206   name         => 'anderer Testlieferant',
207   currency_id  => $currency_id,
208   taxzone_id   => $taxzone->id,
209   vendornumber => 777,
210 )->save;
211
212 $file = \<<"EOL";
213 datatype,vendornumber,currency_id,invnumber,taxincluded,apchart,transdate
214 datatype,accno,amount,taxkey
215 "Rechnung",777,1,"invoice 1",f,1600,"$transdate_string"
216 "AccTransaction",3400,159.48,9
217 EOL
218
219 $entries = test_import($file);
220 is $entries->[0]->{errors}->[0], undef, 'duplicate invnumber, different vendor: no errors in ap row';
221 is $entries->[1]->{errors}->[0], undef, 'duplicate invnumber, different vendor: no errors in acc_trans row';
222
223 $entry = $entries->[0];
224 is $entry->{object}->invnumber, 'invoice 1',           'duplicate invnumber, different vendor: invnumber ok';
225 is $entry->{object}->vendor_id, $different_vendor->id, 'duplicate invnumber, different vendor: vendor_id ok';
226
227 $saved_invoices++;
228
229 ##### test for no invnumber given
230 $file = \<<"EOL";
231 datatype,vendornumber,currency_id,taxincluded,apchart,transdate
232 datatype,accno,amount,taxkey
233 "Rechnung",2,1,f,1600,"$transdate_string"
234 "AccTransaction",3400,159.48,9
235 EOL
236
237 $entries = test_import($file);
238 $entry = $entries->[0];
239 $entry->{object}->validate_acc_trans;
240 is $entry->{errors}->[0], 'Error: Invoice Number missing', 'detects missing invnubmer';
241
242
243 ##### basic test without amounts in Rechnung, only specified in AccTransaction
244 $file = \<<"EOL";
245 datatype,vendornumber,currency_id,invnumber,taxincluded,apchart,transdate
246 datatype,accno,amount,taxkey
247 "Rechnung",2,1,"invoice 1 no amounts",f,1600,"$transdate_string"
248 "AccTransaction",3400,159.48,9
249 EOL
250 $entries = test_import($file);
251 is $entries->[0]->{errors}->[0], undef, 'basic test no amounts: no errors in ap row';
252 is $entries->[1]->{errors}->[0], undef, 'basic test no amounts: no errors in acc_trans row';
253
254 $entry = $entries->[0];
255 is $entry->{object}->validate_acc_trans, 1, 'basic test no amounts: acc_trans validates';
256 is $entry->{object}->invnumber, 'invoice 1 no amounts', 'basic test no amounts: invnumber ok';
257 is $entry->{object}->vendor_id, $vendor->id, 'basic test no amounts: vendor_id ok';
258 is scalar @{$entry->{object}->transactions}, 3, 'basic test no amounts: invoice 1 has 3 acc_trans entries';
259 is $::form->round_amount($entry->{object}->amount, 2), '189.78', 'basic test no amounts: not taxincluded ap amount';
260 is $::form->round_amount($entry->{object}->transactions->[0]->amount, 2), '-159.48', 'basic test no amounts: not taxincluded acc_trans netamount';
261 is $::form->round_amount($entry->{object}->netamount, 2), 159.48, 'basic test no amounts: invoice 1 ap netamount is 159.48';
262
263 $saved_invoices++;
264
265 ##### basic test: credit_note
266 $file = \<<"EOL";
267 datatype,vendornumber,currency_id,invnumber,taxincluded,apchart,transdate
268 datatype,accno,amount,taxkey
269 "Rechnung",2,1,"credit note",f,1600,"$transdate_string"
270 "AccTransaction",3400,-159.48,9
271 EOL
272 $entries = test_import($file);
273 is $entries->[0]->{errors}->[0], undef, 'basic test: credit_note: no errors in ap row';
274 is $entries->[1]->{errors}->[0], undef, 'basic test: credit_note: no errors in acc_trans row';
275
276 $entry = $entries->[0];
277 is $entry->{object}->validate_acc_trans, 1, 'basic test: credit_note: acc_trans validates';
278 is $entry->{object}->invnumber, 'credit note', 'basic test: credit_note: invnumber ok';
279 is scalar @{$entry->{object}->transactions}, 3, 'basic test: credit_note: credit note has 3 acc_trans entries';
280 is $::form->round_amount($entry->{object}->amount, 2), '-189.78', 'basic test: credit_note: taxincluded ap amount';
281 is $::form->round_amount($entry->{object}->netamount, 2), '-159.48', 'basic test: credit_note: taxincluded ap net amount';
282 is $::form->round_amount($entry->{object}->transactions->[0]->amount, 2), 159.48, 'credit note ap amount is 159.48';
283
284 $saved_invoices++;
285
286 #### verify_amount differs: max_amount_diff = 0.02, 189.80 is ok, 189.81 is not
287 $file = \<<"EOL";
288 datatype,vendornumber,verify_amount,verify_netamount,currency_id,invnumber,taxincluded,apchart,transdate
289 datatype,accno,amount,taxkey
290 "Rechnung",2,189.81,159.48,1,"invoice amounts differing",f,1600,"$transdate_string"
291 "AccTransaction",3400,159.48,9
292 EOL
293 $entries = test_import($file);
294
295 $entry = $entries->[0];
296 is $entry->{errors}->[0], 'Amounts differ too much', 'detects verify_amount differences';
297
298 #####  direct debit
299 $file = \<<"EOL";
300 datatype,vendornumber,currency_id,invnumber,taxincluded,direct_debit,apchart,transdate
301 datatype,accno,amount,taxkey
302 "Rechnung",2,1,"invoice with direct debit",f,t,1600,"$transdate_string"
303 "AccTransaction",3400,159.48,9
304 EOL
305
306 $entries = test_import($file);
307 is $entries->[0]->{errors}->[0], undef, 'direct debit: no errors in ap row';
308 is $entries->[1]->{errors}->[0], undef, 'direct debit: no errors in acc_trans row';
309
310 $entry = $entries->[0];
311 is $entry->{object}->validate_acc_trans, 1, 'direct debit: acc_trans validates';
312 is $entry->{object}->direct_debit, '1', 'direct debit';
313
314 $saved_invoices++;
315
316 #### tax included
317 $file = \<<"EOL";
318 datatype,vendornumber,currency_id,invnumber,taxincluded,apchart,transdate
319 datatype,accno,amount,taxkey
320 "Rechnung",2,1,"invoice 1 tax included no amounts",t,1600,"$transdate_string"
321 "AccTransaction",3400,189.78,9
322 EOL
323
324 $entries = test_import($file);
325 $entry = $entries->[0];
326
327 is $entry->{errors}->[0], undef, 'tax included: no errors in ap row';
328 is $entry->{errors}->[1], undef, 'tax included: no errors in acc_trans row';
329
330 is $entry->{object}->validate_acc_trans, 1, 'tax included: acc_trans validates';
331
332 is $entry->{object}->taxincluded, '1', 'tax included: taxincluded is true';
333 is $::form->round_amount($entry->{object}->amount, 2), '189.78', 'tax included: ap amount';
334 is $::form->round_amount($entry->{object}->netamount, 2), '159.48', 'tax included: ap net amount';
335 is $::form->round_amount($entry->{object}->transactions->[0]->amount, 2), '-159.48', 'tax included: acc_trans netamount';
336
337 $saved_invoices++;
338
339 #### multiple tax included
340 $file = \<<"EOL";
341 datatype,vendornumber,currency_id,invnumber,taxincluded,apchart,transdate
342 datatype,accno,amount,taxkey
343 "Rechnung",2,1,"invoice multiple tax included",t,1600,"$transdate_string"
344 "AccTransaction",3400,94.89,9
345 "AccTransaction",3400,94.89,9
346 EOL
347
348 $entries = test_import($file);
349 is $entries->[0]->{errors}->[0], undef, 'multiple tax included: no errors in ap row';
350 is $entries->[1]->{errors}->[0], undef, 'multiple tax included: no errors in 1. acc_trans row';
351 is $entries->[2]->{errors}->[0], undef, 'multiple tax included: no errors in 2. acc_trans row';
352
353 $entry = $entries->[0];
354 is $entry->{object}->validate_acc_trans, 1, 'multiple tax included: acc_trans validates';
355
356 is $::form->round_amount($entry->{object}->amount, 2),    '189.78', 'multiple tax included: ap amount';
357 is $::form->round_amount($entry->{object}->netamount, 2), '159.48', 'multiple tax included: ap netamount';
358 is $::form->round_amount($entry->{object}->transactions->[0]->amount, 2), '-79.74', 'multiple tax included: amount';
359 is $::form->round_amount($entry->{object}->transactions->[1]->amount, 2), '-15.15', 'multiple tax included: tax';
360
361 $saved_invoices++;
362
363 # different payable chart
364 $file = \<<EOL;
365 datatype,vendornumber,currency_id,invnumber,taxincluded,apchart
366 datatype,accno,amount,taxkey
367 "Rechnung",2,1,"invoice mit apchart 1605",f,1605
368 "AccTransaction",3400,159.48,9
369 EOL
370
371 $entries = test_import($file);
372 is $entries->[0]->{errors}->[0], undef, 'different payable chart: no errors in ap row';
373 is $entries->[1]->{errors}->[0], undef, 'different payable chart: no errors in acc_trans row';
374
375 $entry = $entries->[0];
376 is $entry->{object}->validate_acc_trans, 1, 'different payable chart: acc_trans validates';
377 is $entry->{object}->transactions->[2]->chart->accno, '1605', 'different payable chart: apchart set to 1605';
378
379 $saved_invoices++;
380
381 # missing vendor
382 $file = \<<EOL;
383 datatype,currency_id,invnumber,taxincluded,apchart
384 datatype,accno,amount,taxkey
385 "Rechnung",1,"invoice missing vendor",f,1600
386 "AccTransaction",3400,159.48,9
387 EOL
388
389 $entries = test_import($file);
390 $entry = $entries->[0];
391 is $entry->{errors}->[0], 'Error: Vendor missing', 'detects missing vendor';
392
393 ##### vendor by name
394 $file = \<<EOL;
395 datatype,vendor,currency_id,invnumber,taxincluded,apchart
396 datatype,accno,amount,taxkey
397 "Rechnung","Testlieferant",1,"invoice vendor name",f,1600
398 "AccTransaction",3400,159.48,9
399 EOL
400
401 $entries = test_import($file);
402 is $entries->[0]->{errors}->[0], undef, 'vendor by name: no errors in ap row';
403 is $entries->[1]->{errors}->[0], undef, 'vendor by name: no errors in acc_trans row';
404
405 $entry = $entries->[0];
406 is $entry->{object}->validate_acc_trans, 1, 'vendor by name: acc_trans validates';
407 is $entry->{object}->vendor->name, "Testlieferant", 'detects vendor by name';
408
409 $saved_invoices++;
410
411 ##### detect missing chart
412 $file = \<<EOL;
413 datatype,currency_id,invnumber,vendor,apchart
414 datatype,amount,taxkey
415 "Rechnung",1,"invoice missing chart","Testlieferant",1600
416 "AccTransaction",4,9
417 EOL
418
419 $entries = test_import($file);
420
421 $entry = $entries->[1];
422 is $entry->{errors}->[0], 'Error: chart missing', 'detects missing chart (chart_id or accno)';
423
424 ##### detect illegal chart by accno
425 $file = \<<EOL;
426 datatype,currency_id,invnumber,vendor,apchart
427 datatype,accno,amount,taxkey
428 "Rechnung",1,"invoice illegal chart accno","Testlieferant",1600
429 "AccTransaction",9999,4,9
430 EOL
431
432 $entries = test_import($file);
433
434 $entry = $entries->[1];
435 is $entry->{errors}->[0], 'Error: invalid chart (accno)', 'detects invalid chart (chart_id or accno)';
436
437 # ##### detect illegal apchart
438 $file = \<<EOL;
439 datatype,currency_id,invnumber,vendor,taxincluded,apchart
440 datatype,accno,amount,taxkey
441 "Rechnung",1,"invoice illegal apchart","Testlieferant",f,11600
442 "AccTransaction",3400,159.48,9
443 EOL
444
445 $entries = test_import($file);
446
447 $entry = $entries->[0];
448 is $entry->{errors}->[0], "Error: can't find ap chart with accno 11600", 'detects illegal payable chart (apchart)';
449
450 ##### detect chart by id
451 $file = \<<EOL;
452 datatype,currency_id,invnumber,vendor,taxincluded,apchart
453 datatype,amount,chart_id,taxkey
454 "Rechnung",1,"invoice chart_id","Testlieferant",f,1600
455 "AccTransaction",159.48,37,9
456 EOL
457
458 $entries = test_import($file);
459 is $entries->[0]->{errors}->[0], undef, 'detect chart by id: no errors in ap row';
460 is $entries->[1]->{errors}->[0], undef, 'detect chart by id: no errors in acc_trans row';
461
462 $entry = $entries->[0];
463 is $entry->{object}->validate_acc_trans, 1, 'detect chart by id: acc_trans validates';
464
465 $entry = $entries->[1]; # acc_trans entry is at entry array pos 1
466 is $entry->{object}->chart->id, "37", 'detects chart by id';
467
468 $saved_invoices++;
469
470 ##### detect chart by accno
471 $file = \<<EOL;
472 datatype,currency_id,invnumber,vendor,taxincluded,apchart
473 datatype,amount,accno,taxkey
474 "Rechnung",1,"invoice by chart accno","Testlieferant",f,1600
475 "AccTransaction",159.48,3400,9
476 EOL
477
478 $entries = test_import($file);
479 is $entries->[0]->{errors}->[0], undef, 'detect chart by accno: no errors in ap row';
480 is $entries->[1]->{errors}->[0], undef, 'detect chart by accno: no errors in acc_trans row';
481
482 $entry = $entries->[0];
483 is $entry->{object}->validate_acc_trans, 1, 'detect chart by accno: acc_trans validates';
484
485 $entry = $entries->[1];
486 is $entry->{object}->chart->accno, "3400", 'detects chart by accno';
487
488 $saved_invoices++;
489
490 ##### detect chart isn't an ap_chart
491 $file = \<<EOL;
492 datatype,currency_id,invnumber,vendor,taxincluded,apchart
493 datatype,amount,accno,taxkey
494 "Rechnung",1,"invoice by chart accno","Testlieferant",f,1600
495 "AccTransaction",159.48,1600,9
496 EOL
497
498 $entries = test_import($file);
499
500 $entry = $entries->[1];
501 is $entry->{errors}->[0], 'Error: chart isn\'t an ap_amount chart', 'detects valid chart that is not an ap_amount chart';
502
503 # missing taxkey
504 $file = \<<EOL;
505 datatype,currency_id,invnumber,vendor,apchart
506 datatype,amount,accno
507 "Rechnung",1,"invoice missing taxkey chart accno","Testlieferant",1600
508 "AccTransaction",159.48,3400
509 EOL
510
511 $entries = test_import($file);
512
513 $entry = $entries->[1];
514 is $entry->{errors}->[0], 'Error: taxkey missing', 'detects missing taxkey (DATEV Steuerschlüssel)';
515
516 # illegal taxkey
517 $file = \<<EOL;
518 datatype,currency_id,invnumber,vendor,apchart
519 datatype,amount,accno,taxkey
520 "Rechnung",1,"invoice illegal taxkey","Testlieferant",1600
521 "AccTransaction",4,3400,123
522 EOL
523
524 $entries = test_import($file);
525
526 $entry = $entries->[1];
527 is $entry->{errors}->[0], 'Error: invalid taxkey', 'detects invalid taxkey (DATEV Steuerschlüssel)';
528
529 # taxkey
530 $file = \<<EOL;
531 datatype,vendornumber,currency_id,invnumber,apchart,taxincluded
532 datatype,accno,amount,taxkey
533 "Rechnung",2,1,"invoice by taxkey",1600,1
534 "AccTransaction",3400,4,9
535 EOL
536
537 $entries = test_import($file);
538 is $entries->[0]->{errors}->[0], undef, 'taxkey: no errors in ap row';
539 is $entries->[1]->{errors}->[0], undef, 'taxkey: no errors in acc_trans row';
540
541 $entry = $entries->[1];
542 is $entry->{object}->taxkey, 9, 'detects taxkey';
543
544 $saved_invoices++;
545
546 # acc_trans project
547 $file = \<<EOL;
548 datatype,vendornumber,currency_id,invnumber,apchart,taxincluded
549 datatype,accno,amount,taxkey,projectnumber
550 "Rechnung",2,1,"invoice with acc_trans project",1600,f
551 "AccTransaction",3400,159.48,9,P1
552 EOL
553
554 $entries = test_import($file);
555 is $entries->[0]->{errors}->[0], undef, 'acc_trans project: no errors in ap row';
556 is $entries->[1]->{errors}->[0], undef, 'acc_trans project: no errors in acc_trans row';
557
558 $entry = $entries->[1];
559 is $entry->{object}->project->projectnumber, 'P1', 'detects acc_trans project';
560
561 $saved_invoices++;
562
563 #####  various tests
564 $file = \<<EOL;
565 datatype,vendornumber,currency_id,invnumber,taxincluded,apchart,transdate,duedate,globalprojectnumber,department
566 datatype,accno,amount,taxkey,projectnumber
567 "Rechnung",2,1,"invoice various",t,1600,21.04.2016,30.04.2016,P1,Department 1
568 "AccTransaction",3400,119,9,P1
569 "AccTransaction",3300,107,8,P1
570 "AccTransaction",3559,100,0,P1
571 EOL
572
573 $entries = test_import($file);
574 is $entries->[0]->{errors}->[0], undef, 'various tests: errors in ap row';
575 is $entries->[1]->{errors}->[0], undef, 'various tests: no errors in 1. acc_trans row';
576 is $entries->[2]->{errors}->[0], undef, 'various tests: no errors in 2. acc_trans row';
577 is $entries->[3]->{errors}->[0], undef, 'various tests: no errors in 3. acc_trans row';
578
579 $entry = $entries->[0];
580 is $entry->{object}->validate_acc_trans, 1, 'various tests: acc_trans validates';
581
582 is $entry->{object}->duedate->to_kivitendo,      '30.04.2016',    'various tests: duedate';
583 is $entry->{object}->transdate->to_kivitendo,    '21.04.2016',    'various tests: transdate';
584 is $entry->{object}->globalproject->description, 'Project X',     'various tests: project';
585 is $entry->{object}->department->description,    'Department 1',  'various tests: department';
586 # 3300 is third entry after 3400 and tax for 3400
587 is $::form->round_amount($entry->{object}->transactions->[2]->amount),     '-100',       '3300 net amount: -100';
588 is $entry->{object}->transactions->[2]->taxkey,                            '8',          '3300 has taxkey 8';
589 is $entry->{object}->transactions->[2]->project_id,                        $project->id, 'AccTrans project';
590
591 $saved_invoices++;
592
593 #####  ap amount test
594 $file = \<<EOL;
595 datatype,vendornumber,currency_id,invnumber,taxincluded,apchart,transdate,duedate,globalprojectnumber,department
596 datatype,accno,amount,taxkey,projectnumber
597 "Rechnung",2,1,"invoice various 1",t,1600,21.04.2016,30.04.2016,P1,Department 1
598 "AccTransaction",3400,119,9,P1
599 "AccTransaction",3300,107,8,P1
600 "AccTransaction",3559,100,0,P1
601 "Rechnung",2,1,"invoice various 2",t,1600,21.04.2016,30.04.2016,P1,Department 1
602 "AccTransaction",3400,119,9,P1
603 "AccTransaction",3400,107,8,P1
604 "AccTransaction",3559,100,0,P1
605 EOL
606
607 $entries = test_import($file);
608 is $entries->[0]->{errors}->[0], undef, 'ap amount test: no errors in 1. ap row';
609 is $entries->[1]->{errors}->[0], undef, 'ap amount test: no errors in 1. acc_trans row (ap row 1)';
610 is $entries->[2]->{errors}->[0], undef, 'ap amount test: no errors in 2. acc_trans row (ap row 1)';
611 is $entries->[3]->{errors}->[0], undef, 'ap amount test: no errors in 3. acc_trans row (ap row 1)';
612 is $entries->[4]->{errors}->[0], undef, 'ap amount test: no errors in 2. ap row';
613 is $entries->[5]->{errors}->[0], undef, 'ap amount test: no errors in 1. acc_trans row (ap row 2)';
614 is $entries->[6]->{errors}->[0], undef, 'ap amount test: no errors in 2. acc_trans row (ap row 2)';
615 is $entries->[7]->{errors}->[0], undef, 'ap amount test: no errors in 3. acc_trans row (ap row 2)';
616
617 $entry = $entries->[0];
618 is $entry->{object}->validate_acc_trans,    1,               'ap amount test: acc_trans validates';
619 is $entry->{object}->duedate->to_kivitendo, '30.04.2016',    'duedate';
620 is $entry->{info_data}->{calc_amount},      '326.00',        "First calculated invoice amount displayed in info data";
621 $entry = $entries->[4];
622 is $entry->{info_data}->{calc_amount},      '326.00',        "Second calculated invoice amount displayed in info data";
623
624 $saved_invoices++;
625 $saved_invoices++;
626
627 # multiple entries, taxincluded = f
628 $file = \<<EOL;
629 datatype,vendornumber,currency_id,invnumber,taxincluded,apchart
630 datatype,accno,amount,taxkey
631 "Rechnung",2,1,"invoice 4 acc_trans",f,1600
632 "AccTransaction",3400,39.87,9
633 "AccTransaction",3400,39.87,9
634 "AccTransaction",3400,39.87,9
635 "AccTransaction",3400,39.87,9
636 "Rechnung",2,1,"invoice 4 acc_trans 2",f,1600
637 "AccTransaction",3400,39.87,9
638 "AccTransaction",3400,39.87,9
639 "AccTransaction",3400,39.87,9
640 "AccTransaction",3400,39.87,9
641 "Rechnung",2,1,"invoice 4 acc_trans 3",f,1600
642 "AccTransaction",3400,39.87,9
643 "AccTransaction",3400,39.87,9
644 "AccTransaction",3400,39.87,9
645 "AccTransaction",3400,39.87,9
646 "Rechnung",2,1,"invoice 4 acc_trans 4",f,1605
647 "AccTransaction",3400,39.87,9
648 "AccTransaction",3400,39.87,9
649 "AccTransaction",3400,39.87,9
650 "AccTransaction",3400,39.87,9
651 EOL
652
653 $entries = test_import($file);
654
655 my $i = 0;
656 foreach my $entry ( @$entries ) {
657   next unless $entry->{object}->isa('SL::DB::PurchaseInvoice');
658   $i++;
659   is scalar @{$entry->{object}->transactions}, 9, "multiple entries: invoice $i: 'acc_trans' has 9 acc_trans entries";
660   $entry->{object}->validate_acc_trans;
661   is $entry->{object}->validate_acc_trans,     1, "multiple entries: invoice $i: 'acc_trans validates'";
662 }
663
664 $saved_invoices++;
665 $saved_invoices++;
666 $saved_invoices++;
667 $saved_invoices++;
668
669 ##### missing acc_trans
670 $file = \<<EOL;
671 datatype,vendornumber,currency_id,invnumber,taxincluded,apchart,transdate,duedate,globalprojectnumber,department
672 datatype,accno,amount,taxkey,projectnumber
673 "Rechnung",2,1,"invoice acc_trans missing",t,1600,21.04.2016,30.04.2016,P1,Department 1
674 "Rechnung",2,1,"invoice various a",t,1600,21.04.2016,30.04.2016,P1,Department 1
675 "AccTransaction",3400,119,9,P1
676 "AccTransaction",3300,107,8,P1
677 EOL
678
679 $entries = test_import($file);
680
681 $entry = $entries->[0];
682 is $entry->{errors}->[0], "Error: ap transaction doesn't validate", 'detects invalid ap, maybe acc_trans entry missing';
683
684 ##### taxkey differs from active_taxkey
685 $file = \<<EOL;
686 datatype,vendornumber,currency_id,invnumber,taxincluded,apchart
687 datatype,accno,amount,taxkey
688 "Rechnung",2,1,"invoice 2 tax included no amounts",t,1600
689 "AccTransaction",3400,189.78,8
690 EOL
691
692 $entries = test_import($file);
693 is $entries->[0]->{errors}->[0], undef, 'taxkey differs from active_taxkey: no errors in ap row';
694 is $entries->[1]->{errors}->[0], undef, 'taxkey differs from active_taxkey: no errors in acc_trans row';
695
696 $entry = $entries->[0];
697 is $entry->{object}->transactions->[1]->taxkey, '8', 'taxkey differs from active_taxkey';
698
699 $saved_invoices++;
700
701 ##### verify amounts, error only once
702 $file = \<<EOL;
703 datatype,vendornumber,currency_id,invnumber,taxincluded,apchart,verify_netamount,verify_amount
704 datatype,accno,amount,taxkey
705 "Rechnung",2,1,"first invoice",f,1600,39.87,47.44
706 "AccTransaction",3400,39.87,9
707 "Rechnung",2,1,"second invoice",f,1600,39.78,78.39
708 "AccTransaction",3400,39.87,9
709 EOL
710
711 $entries = test_import($file);
712
713 $entry = $entries->[0];
714 is $entry->{errors}->[0], undef,                         'verify amounts, error only once: no error in first invoice';
715
716 $entry = $entries->[2];
717 is $entry->{errors}->[0], "Amounts differ too much",     'verify amounts, error only once: amount differs';
718 is $entry->{errors}->[1], "Net amounts differ too much", 'verify amounts, error only once: netamount differs';
719 is $entry->{errors}->[2], undef,                         'verify amounts, error only once: nothing else';
720
721 $saved_invoices++;
722
723 #####
724 my $number_of_imported_invoices = SL::DB::Manager::PurchaseInvoice->get_all_count;
725 is $number_of_imported_invoices, $saved_invoices, 'All invoices saved';
726
727 #####
728 clear_up(); # remove all data at end of tests
729
730 # end of tests
731 done_testing;
732
733 1;
734
735 #####
736 # vim: ft=perl
737 # set emacs to perl mode
738 # Local Variables:
739 # mode: perl
740 # End: