Konjunkturpaket 2020 Anpassung der Mehrwertsteuersätze und Test
[kivitendo-erp.git] / t / tax / tax.t
1 use Test::More tests => 38;
2 use Test::Deep qw(cmp_deeply);
3
4 use strict;
5
6 use lib 't';
7 use utf8;
8
9 use Support::TestSetup;
10 use Test::Exception;
11
12 use SL::DB::Customer;
13 use SL::DB::Vendor;
14 use SL::DB::Invoice;
15 use SL::DB::GLTransaction;
16 use SL::DB::Part;
17 use SL::DBUtils qw(selectall_hashref_query);
18 use SL::Dev::Record qw(:ALL);
19 use SL::Dev::CustomerVendor qw(new_customer new_vendor);
20 use SL::Dev::Part qw(new_part);
21 use Data::Dumper;
22
23 Support::TestSetup::login();
24 my $dbh = SL::DB->client->dbh;
25
26 my $test_kontenrahmen = 'skr03';
27
28 clear_up();
29
30 # TODOs: Storno muß noch korrekt funktionieren
31 #  neue Konten für 5% anlegen
32 #  Leistungszeitraum vs. Datum Zuord. Steuerperiodest
33
34 note('checking if all tax entries exist for Konjunkturprogramm');
35
36 # create dates to test on
37 my $date_2006   = DateTime->new(year => 2006, month => 6, day => 15);
38 my $date_2020_1 = DateTime->new(year => 2020, month => 6, day => 15);
39 my $date_2020_2 = DateTime->new(year => 2020, month => 7, day => 15);
40 my $date_2021   = DateTime->new(year => 2021, month => 1, day => 15);
41
42 # The only way to discern the pre-2007 16% tax from the 2020 16% tax is by
43 # their configured automatic tax charts, so look them up here:
44
45 my ($chart_vst_19, $chart_vst_16, $chart_vst_5, $chart_vst_7);
46 my ($chart_ust_19, $chart_ust_16, $chart_ust_5, $chart_ust_7);
47 my ($income_19_accno, $income_7_accno);
48 my ($ar_accno, $ap_accno);
49 my ($chart_reisekosten_accno, $chart_cash_accno, $chart_bank_accno);
50
51
52 if ( $test_kontenrahmen eq 'skr03' ) {
53
54   is(SL::DB::Default->get->coa, 'Germany-DATEV-SKR03EU', "coa SKR03 ok");
55
56   $chart_vst_19 = '1776';
57   $chart_vst_16 = '1775';
58   $chart_vst_5  = '1773';
59   $chart_vst_7  = '1771';
60
61   $chart_ust_19 = '1576';
62   $chart_ust_16 = '1575';
63   $chart_ust_5  = '1568';
64   $chart_ust_7  = '1571';
65
66   $income_19_accno = '8400';
67   $income_7_accno  = '8300';
68
69   $chart_reisekosten_accno = 4660;
70   $chart_cash_accno        = 1000;
71
72   $ar_accno = 1400;
73   $ap_accno = 1600;
74
75 } elsif ( $test_kontenrahmen eq 'skr04') { # skr04 - test can be ran manually by running t/000setup_database.t with coa for SKR04
76   is(SL::DB::Default->get->coa, 'Germany-DATEV-SKR04EU', "coa SKR04 ok");
77   $chart_ust_19 = '1406';
78   $chart_ust_16 = '1405';
79   $chart_ust_5  = '1403';
80   $chart_ust_7  = '1401';
81
82   $chart_vst_19 = '3806';
83   $chart_vst_16 = '3805';
84   $chart_vst_5  = '3803';
85   $chart_vst_7  = '3801';
86
87   $income_19_accno = '4400';
88   $income_7_accno  = '4300';
89
90   $chart_reisekosten_accno = 6650;
91   $chart_cash_accno        = 1600;
92
93   $ar_accno = 1200;
94   $ap_accno = 3300;
95 }
96
97 my $tax_vst_19 = SL::DB::Manager::Chart->find_by(accno => $chart_vst_19) or die; # 19%
98 my $tax_vst_16 = SL::DB::Manager::Chart->find_by(accno => $chart_vst_16) or die; # 16%
99 my $tax_vst_5  = SL::DB::Manager::Chart->find_by(accno => $chart_vst_5 ) or die; #  5%
100 my $tax_vst_7  = SL::DB::Manager::Chart->find_by(accno => $chart_vst_7 ) or die; #  7%
101
102 my $tax_ust_19 = SL::DB::Manager::Chart->find_by(accno => $chart_ust_19) or die; # 19%
103 my $tax_ust_16 = SL::DB::Manager::Chart->find_by(accno => $chart_ust_16) or die; # 16%
104 my $tax_ust_5  = SL::DB::Manager::Chart->find_by(accno => $chart_ust_5) or die;  #  5%
105 my $tax_ust_7  = SL::DB::Manager::Chart->find_by(accno => $chart_ust_7) or die;  #  7%
106
107 my $chart_income_19  = SL::DB::Manager::Chart->find_by(accno => $income_19_accno) or die;
108 my $chart_income_7   = SL::DB::Manager::Chart->find_by(accno => $income_7_accno) or die;
109
110 my $chart_reisekosten = SL::DB::Manager::Chart->find_by(accno => $chart_reisekosten_accno) or die;
111 my $chart_cash        = SL::DB::Manager::Chart->find_by(accno => $chart_cash_accno) or die;
112
113 is(defined SL::DB::Manager::Tax->find_by(taxkey => 2, rate => 0.05), 1, "tax for taxkey 2 with 5% was created ok");
114 is(defined SL::DB::Manager::Tax->find_by(taxkey => 3, rate => 0.16, chart_id => $tax_vst_16->id), 1, "new sales tax for taxkey 3 with 16% exists ok");
115 is(defined SL::DB::Manager::Tax->find_by(taxkey => 3, rate => 0.19, chart_id => $tax_vst_19->id), 1, "old sales tax for taxkey 3 with 19% exists ok");
116 is(defined SL::DB::Manager::Tax->find_by(taxkey => 5, rate => 0.16, chart_id => $tax_vst_16->id), 1, "new sales tax for taxkey 5 with 16% exists ok");
117
118 is(defined SL::DB::Manager::Tax->find_by(taxkey => 7, rate => 0.16, chart_id => $tax_ust_16->id), 1, "old purchase tax for taxkey 7 with 16% exists ok");
119 # is(defined SL::DB::Manager::Tax->find_by(taxkey => 8, rate => 0.07, chart_id => $tax_ust_16->id), 1, "old purchase tax for taxkey 7 with 16% exists ok");
120 is(defined SL::DB::Manager::Tax->find_by(taxkey => 9, rate => 0.19, chart_id => $tax_ust_19->id), 1, "old purchase tax for taxkey 9 with 19% exists ok");
121 is(defined SL::DB::Manager::Tax->find_by(taxkey => 9, rate => 0.16, chart_id => $tax_ust_16->id), 1, "new purchase tax for taxkey 9 with 16% exists ok");
122
123 my $vendor   = new_vendor(  name => 'Testvendor')->save;
124 my $customer = new_customer(name => 'Testcustomer')->save;
125
126 # cmp_ok($chart_income_7->get_active_taxkey($date_2020_1)->tax->rate, '==', 0.07, "get_active_taxkey rate for 8300 in 2020_1 ok");
127 # cmp_ok($chart_income_7->get_active_taxkey($date_2020_2)->tax->rate, '==', 0.05, "get_active_taxkey rate for 8300 in 2020_2 ok");
128 # cmp_ok($chart_income_7->get_active_taxkey($date_2021  )->tax->rate, '==', 0.07, "get_active_taxkey rate for 8300 in 2021   ok");
129 cmp_ok($chart_income_7->get_active_taxkey($date_2020_1)->tax->rate, '==', 0.07, "get_active_taxkey rate for $income_7_accno in 2020_1 ok");
130 cmp_ok($chart_income_7->get_active_taxkey($date_2020_2)->tax->rate, '==', 0.05, "get_active_taxkey rate for $income_7_accno in 2020_2 ok");
131 cmp_ok($chart_income_7->get_active_taxkey($date_2021  )->tax->rate, '==', 0.07, "get_active_taxkey rate for $income_7_accno in 2021   ok");
132 cmp_ok($chart_income_7->get_active_taxkey($date_2006  )->tax->rate, '==', 0.07, "get_active_taxkey rate for $income_7_accno in 2016   ok");
133
134 cmp_ok($chart_income_19->get_active_taxkey($date_2020_1)->tax->rate, '==', 0.19, "get_active_taxkey rate for $income_19_accno in 2020_1 ok");
135 cmp_ok($chart_income_19->get_active_taxkey($date_2020_2)->tax->rate, '==', 0.16, "get_active_taxkey rate for $income_19_accno in 2020_2 ok");
136 cmp_ok($chart_income_19->get_active_taxkey($date_2021  )->tax->rate, '==', 0.19, "get_active_taxkey rate for $income_19_accno in 2021   ok");
137 cmp_ok($chart_income_19->get_active_taxkey($date_2006  )->tax->rate, '==', 0.16, "get_active_taxkey rate for $income_19_accno in 2016   ok");
138
139 my $bugru19 = SL::DB::Manager::Buchungsgruppe->find_by(description => 'Standard 19%') or die "Can't find bugru19";
140 my $bugru7  = SL::DB::Manager::Buchungsgruppe->find_by(description => 'Standard 7%' ) or die "Can't find bugru7";
141
142 my $part1 = new_part(partnumber => '1', description => 'part19', buchungsgruppen_id => $bugru19->id)->save;
143 my $part2 = new_part(partnumber => '2', description => 'part7',  buchungsgruppen_id => $bugru7->id )->save;
144
145 note('sales invoices');
146 my $sales_invoice_2006   = create_invoice_for_date('2006',   $date_2006);
147 my $sales_invoice_2020_1 = create_invoice_for_date('2020_1', $date_2020_1);
148 my $sales_invoice_2020_2 = create_invoice_for_date('2020_2', $date_2020_2);
149 my $sales_invoice_2021   = create_invoice_for_date('2021',   $date_2021);
150
151 is($sales_invoice_2006->amount,   223, '2006 sales invoice has 16% and 7% tax ok'   ); # 116 + 7
152 is($sales_invoice_2020_1->amount, 226, '2020_01 sales invoice has 19% and 7% tax ok'); # 119 + 7
153 is($sales_invoice_2020_2->amount, 221, '2020_02 sales invoice has 16% and 5% tax ok'); # 116 + 5
154 is($sales_invoice_2021->amount,   226, '2021 sales invoice has 19% and 7% tax ok'   ); # 119 + 7
155
156 &datev_test($sales_invoice_2020_2,
157            [
158              {
159                'belegfeld1' => 'test is 2020_2',
160                'buchungstext' => 'Testcustomer',
161                'datum' => '15.07.2020',
162                'leistungsdatum' => '15.07.2020', # should leistungsdatum be empty if it doesn't exist?
163                'gegenkonto' => $income_7_accno,
164                'konto' => $ar_accno,
165                'kost1' => undef,
166                'kost2' => undef,
167                'locked' => undef,
168                'umsatz' => 105,
169                'waehrung' => 'EUR'
170              },
171              {
172                'belegfeld1' => 'test is 2020_2',
173                'buchungstext' => 'Testcustomer',
174                'datum' => '15.07.2020',
175                'leistungsdatum' => '15.07.2020',
176                'gegenkonto' => $income_19_accno,
177                'konto' => $ar_accno,
178                'kost1' => undef,
179                'kost2' => undef,
180                'locked' => undef,
181                'umsatz' => 116,
182                'waehrung' => 'EUR'
183              }
184           ],
185           "datev check for 16/5 ok, no taxkey"
186 );
187
188 note('sales invoice with differing delivery dates');
189 my $sales_invoice_2020_1_with_delivery_date_2020_2 = create_invoice_for_date('deliverydate 2020_1', $date_2020_1, $date_2020_2);
190 is($sales_invoice_2020_1_with_delivery_date_2020_2->amount, 221, "sales_invoice from 2020_1 with future delivery_date 2020_2 tax ok");
191
192 my $sales_invoice_2020_2_with_delivery_date_2020_1 = create_invoice_for_date('deliverydate 2020_2', $date_2020_2, $date_2020_1);
193 is($sales_invoice_2020_2_with_delivery_date_2020_1->amount, 226, "sales_invoice from 2020_2 with   past delivery_date 2020_1 tax ok");
194
195 &datev_test($sales_invoice_2020_2_with_delivery_date_2020_1,
196             [
197               {
198                 'belegfeld1' => 'test is deliverydate 2020_2',
199                 'buchungstext' => 'Testcustomer',
200                 'datum' => '15.07.2020',
201                 'gegenkonto' => $income_7_accno,
202                 'konto' => $ar_accno,
203                 'kost1' => undef,
204                 'kost2' => undef,
205                 'leistungsdatum' => '15.06.2020',
206                 'locked' => undef,
207                 'umsatz' => 107,
208                 'waehrung' => 'EUR'
209               },
210               {
211                 'belegfeld1' => 'test is deliverydate 2020_2',
212                 'buchungstext' => 'Testcustomer',
213                 'datum' => '15.07.2020',
214                 'gegenkonto' => $income_19_accno,
215                 'konto' => $ar_accno,
216                 'kost1' => undef,
217                 'kost2' => undef,
218                 'leistungsdatum' => '15.06.2020',
219                 'locked' => undef,
220                 'umsatz' => 119,
221                 'waehrung' => 'EUR'
222               }
223             ],
224             "datev check for datev export with delivery_date 19/7 ok, no taxkey"
225 );
226
227 my $sales_invoice_2021_with_delivery_date_2020_2   = create_invoice_for_date('deliverydate 2020_2', $date_2021, $date_2020_2);
228 is($sales_invoice_2021_with_delivery_date_2020_2->amount,   221, "sales_invoice from 2021   with   past delivery_date 2020_2 tax ok");
229
230 my $sales_invoice_2020_2_with_delivery_date_2021   = create_invoice_for_date('deliverydate 2021', $date_2020_2, $date_2021);
231 is($sales_invoice_2020_2_with_delivery_date_2021->amount,   226, "sales_invoice from 2020_2 with future delivery_date 2021   tax ok");
232
233
234 note('ap transactions');
235 # in the test we want to test for Reisekosten with 19% and 7%. Normally the user
236 # would select the entries from the dropdown, as they may differ from the
237 # default, so we have to pass the tax we want to create_ap_transaction
238
239 my $tax_9_16_old = SL::DB::Manager::Tax->find_by(taxkey => 7, rate => 0.16, chart_id => $tax_ust_16->id);
240 my $tax_9_19     = SL::DB::Manager::Tax->find_by(taxkey => 9, rate => 0.19, chart_id => $tax_ust_19->id);
241 my $tax_9_16     = SL::DB::Manager::Tax->find_by(taxkey => 9, rate => 0.16, chart_id => $tax_ust_16->id);
242 my $tax_8_7      = SL::DB::Manager::Tax->find_by(taxkey => 8, rate => 0.07, chart_id => $tax_ust_7->id);
243 my $tax_8_5      = SL::DB::Manager::Tax->find_by(taxkey => 8, rate => 0.05, chart_id => $tax_ust_5->id);
244
245 # simulate user selecting the "correct" taxes in dropdown:
246 my $ap_transaction_2006   = create_ap_transaction_for_date('2006',   $date_2006,   undef, $tax_9_16_old, $tax_8_7);
247 my $ap_transaction_2020_1 = create_ap_transaction_for_date('2020_1', $date_2020_1, undef, $tax_9_19,     $tax_8_7);
248 my $ap_transaction_2020_2 = create_ap_transaction_for_date('2020_2', $date_2020_2, undef, $tax_9_16,     $tax_8_5);
249 my $ap_transaction_2021   = create_ap_transaction_for_date('2021',   $date_2021,   undef, $tax_9_19,     $tax_8_7);
250
251
252 is($ap_transaction_2006->amount,   223, '2006    ap transaction has 16% and 7% tax ok'); # 116 + 7
253 is($ap_transaction_2020_1->amount, 226, '2020_01 ap transaction has 19% and 7% tax ok'); # 119 + 7
254 is($ap_transaction_2020_2->amount, 221, '2020_02 ap transaction has 16% and 5% tax ok'); # 116 + 5
255 is($ap_transaction_2021->amount,   226, '2021    ap transaction has 19% and 7% tax ok'); # 119 + 7
256
257 # ap transaction in july, but use old tax
258 my $ap_transaction_2020_2_with_delivery_date_2020_1 = create_ap_transaction_for_date('2020_2 with delivery date 2020_1', $date_2020_2, $date_2020_1, $tax_9_19, $tax_8_7);
259 is($ap_transaction_2020_2_with_delivery_date_2020_1->amount,   226, 'ap transaction 2020_2 with delivery date 2020_1, 19% and 7% tax ok'); # 119 + 7
260 &datev_test($ap_transaction_2020_2_with_delivery_date_2020_1,
261             [
262               {
263                 'belegfeld1' => 'test ap_transaction 2020_2 with delivery date 2020_1',
264                 'buchungsschluessel' => 8,
265                 'buchungstext' => 'Testvendor',
266                 'datum' => '15.07.2020',
267                 'gegenkonto' => $ap_accno,
268                 'konto' => $chart_reisekosten_accno,
269                 'kost1' => undef,
270                 'kost2' => undef,
271                 'leistungsdatum' => '15.06.2020',
272                 'locked' => undef,
273                 'umsatz' => 107,
274                 'waehrung' => 'EUR'
275               },
276               {
277                 'belegfeld1' => 'test ap_transaction 2020_2 with delivery date 2020_1',
278                 'buchungsschluessel' => 9,
279                 'buchungstext' => 'Testvendor',
280                 'datum' => '15.07.2020',
281                 'gegenkonto' => $ap_accno,
282                 'konto' => $chart_reisekosten_accno,
283                 'kost1' => undef,
284                 'kost2' => undef,
285                 'leistungsdatum' => '15.06.2020',
286                 'locked' => undef,
287                 'umsatz' => 119,
288                 'waehrung' => 'EUR'
289               }
290             ],
291             "datev check for ap transaction 2020_2 with delivery date 2020_1, 19% and 7% tax ok"
292 );
293
294 note('ar transactions');
295
296 my $ar_transaction_2006   = create_ar_transaction_for_date('2006',   $date_2006);
297 my $ar_transaction_2020_1 = create_ar_transaction_for_date('2020_1', $date_2020_1);
298 my $ar_transaction_2020_2 = create_ar_transaction_for_date('2020_2', $date_2020_2);
299 my $ar_transaction_2021   = create_ar_transaction_for_date('2021',   $date_2021);
300
301 is($ar_transaction_2006->amount,   223, '2006    ar transaction has 16% and 7% tax ok'); # 116 + 7
302 is($ar_transaction_2020_1->amount, 226, '2020_01 ar transaction has 19% and 7% tax ok'); # 119 + 7
303 is($ar_transaction_2020_2->amount, 221, '2020_02 ar transaction has 16% and 5% tax ok'); # 116 + 5
304 is($ar_transaction_2021->amount,   226, '2021    ar transaction has 19% and 7% tax ok'); # 119 + 7
305
306 note('gl transactions');
307
308 my $gl_2006   = create_gl_transaction_for_date('glincome 2006',   $date_2006,   223);
309 my $gl_2020_1 = create_gl_transaction_for_date('glincome 2020_1', $date_2020_1, 226);
310 my $gl_2020_2 = create_gl_transaction_for_date('glincome 2020_2', $date_2020_2, 221);
311 my $gl_2021   = create_gl_transaction_for_date('glincome 2021',   $date_2021,   226);
312
313 is(SL::DB::Manager::GLTransaction->get_all_count(), 4, "4 gltransactions created correctly");
314
315 my $result = &get_account_balances;
316 # print Dumper($result);
317 is_deeply( &get_account_balances,
318  [
319           # {
320           #   'accno' => '1000',
321           #   # 'description' => 'Kasse',
322           #   'sum' => '-896.00000'
323           # },
324           # {
325           #   'accno' => '1400',
326           #   # 'description' => 'Ford. a.Lieferungen und Leistungen',
327           #   'sum' => '-2686.00000'
328           # },
329           {
330             'accno' => '1568',
331             # 'description' => 'Abziehbare Vorsteuer 7%',
332             'sum' => '-5.00000'
333           },
334           {
335             'accno' => '1571',
336             # 'description' => 'Abziehbare Vorsteuer 7%',
337             'sum' => '-28.00000'
338           },
339           {
340             'accno' => '1575',
341             # 'description' => 'Abziehbare Vorsteuer 16%',
342             'sum' => '-32.00000'
343           },
344           {
345             'accno' => '1576',
346             # 'description' => 'Abziehbare Vorsteuer 19 %',
347             'sum' => '-57.00000'
348           },
349           # {
350           #   'accno' => '1600',
351           #   # 'description' => 'Verbindlichkeiten aus Lief.u.Leist.',
352           #   'sum' => '896.00000'
353           # },
354           {
355             'accno' => '1771',
356             # 'description' => 'Umsatzsteuer 7%',
357             'sum' => '77.00000'
358           },
359           {
360             'accno' => '1773',
361             # 'description' => 'Umsatzsteuer 5 %',
362             'sum' => '25.00000'
363           },
364           {
365             'accno' => '1775',
366             # 'description' => 'Umsatzsteuer 16%',
367             'sum' => '128.00000'
368           },
369           {
370             'accno' => '1776',
371             # 'description' => 'Umsatzsteuer 19 %',
372             'sum' => '152.00000'
373           },
374           # {
375           #   'accno' => '4660',
376           #   # 'description' => 'Reisekosten Arbeitnehmer',
377           #   'sum' => '-800.00000'
378           # },
379           # {
380           #   'accno' => $income_7_accno,
381           #   # 'description' => "Erl\x{f6}se 7%USt",
382           #   'sum' => '1600.00000'
383           # },
384           # {
385           #   'accno' => $income_19_accno,
386           #   # 'description' => "Erl\x{f6}se 16%/19% USt.",
387           #   'sum' => '1600.00000'
388           # }
389         ],
390         'account balances after invoices'
391 );
392
393 clear_up();
394
395 done_testing();
396
397 ###### functions for setting up data
398
399 sub create_invoice_for_date {
400   my ($invnumber, $transdate, $deliverydate) = @_;
401
402   $deliverydate = $transdate unless defined $deliverydate;
403
404   my $sales_invoice = create_sales_invoice(
405     invnumber    => 'test is ' . $invnumber,
406     transdate    => $transdate,
407     customer     => $customer,
408     deliverydate => $deliverydate,
409     taxincluded  => 0,
410     invoiceitems => [ create_invoice_item(part => $part1, qty => 10, sellprice => 10),
411                       create_invoice_item(part => $part2, qty => 10, sellprice => 10),
412                     ]
413   );
414   return $sales_invoice;
415 }
416
417 sub create_ar_transaction_for_date {
418   my ($invnumber, $transdate) = @_;
419
420   my $ar_transaction = create_ar_transaction(
421     customer      => $customer,
422     invnumber   => 'test ar' . $invnumber,
423     taxincluded => 0,
424     transdate   => $transdate,
425     ar_chart     => SL::DB::Manager::Chart->find_by(accno => $ar_accno), # pass ar_chart, as it is hardcoded for SKR03 in SL::Dev::Record
426     bookings    => [
427                      {
428                        chart  => $chart_income_19,
429                        amount => 100,
430                      },
431                      {
432                        chart  => $chart_income_7,
433                        amount => 100,
434                      },
435                    ]
436   );
437   return $ar_transaction;
438 }
439
440 sub create_ap_transaction_for_date {
441   my ($invnumber, $transdate, $deliverydate, $tax_high, $tax_low) = @_;
442
443   # printf("invnumber = %s  tax_high = %s   tax_low = %s\n", $invnumber, $tax_high->accno , $tax_low->accno);
444   my $taxkey_ = $chart_reisekosten->get_active_taxkey($transdate);
445
446   my $ap_transaction = create_ap_transaction(
447     vendor       => $vendor,
448     invnumber    => 'test ap_transaction ' . $invnumber,
449     taxincluded  => 0,
450     transdate    => $transdate,
451     deliverydate => $deliverydate,
452     ap_chart     => SL::DB::Manager::Chart->find_by(accno => $ap_accno), # pass ap_chart, as it is hardcoded for SKR03 in SL::Dev::Record
453     bookings     => [
454                      {
455                        chart  => $chart_reisekosten,
456                        amount => 100,
457                        tax_id => $tax_high->id,
458                      },
459                      {
460                        chart  => $chart_reisekosten,
461                        amount => 100,
462                        tax_id => $tax_low->id,
463                      },
464                    ]
465   );
466   return $ap_transaction;
467 }
468
469 sub create_gl_transaction_for_date {
470   my ($reference, $transdate, $debitamount) = @_;
471
472   my $gl_transaction = create_gl_transaction(
473     reference   => $reference,
474     taxincluded => 0,
475     transdate   => $transdate,
476     bookings    => [
477                      {
478                        chart  => $chart_income_19,
479                        memo   => 'gl 19',
480                        source => 'gl 19',
481                        credit => 100,
482                      },
483                      {
484                        chart  => $chart_income_7,
485                        memo   => 'gl 7',
486                        source => 'gl 7',
487                        credit => 100,
488                      },
489                      {
490                        chart  => $chart_cash,
491                        debit  => $debitamount,
492                        memo   => 'gl 19+7',
493                        source => 'gl 19+7',
494                      },
495                    ],
496   );
497   return $gl_transaction;
498 }
499
500 sub get_account_balances {
501   my $query = <<SQL;
502   select c.accno, sum(a.amount)
503     from acc_trans a
504          left join chart c on (c.id = a.chart_id)
505    where c.accno ~ '^17' or c.accno ~ '^15'
506 group by c.accno, c.description
507 order by c.accno
508 SQL
509
510   my $result = selectall_hashref_query($::form, $dbh, $query);
511   return $result;
512 };
513
514 sub datev_test {
515   my ($invoice, $expected_data, $msg) = @_;
516
517   my $datev = SL::DATEV->new(
518     dbh        => $invoice->db->dbh,
519     trans_id   => $invoice->id,
520   );
521
522   $datev->generate_datev_data;
523   my @data_datev   = sort { $a->{umsatz} <=> $b->{umsatz} } @{ $datev->generate_datev_lines() };
524
525   # print Dumper(\@data_datev);
526
527   cmp_deeply(\@data_datev, $expected_data, $msg);
528 }
529
530 sub clear_up {
531   SL::DB::Manager::OrderItem->delete_all(all => 1);
532   SL::DB::Manager::Order->delete_all(all => 1);
533   SL::DB::Manager::InvoiceItem->delete_all(all => 1);
534   SL::DB::Manager::Invoice->delete_all(all => 1);
535   SL::DB::Manager::PurchaseInvoice->delete_all(all => 1);
536   SL::DB::Manager::GLTransaction->delete_all(all => 1);
537   SL::DB::Manager::Part->delete_all(all => 1);
538   SL::DB::Manager::Customer->delete_all(all => 1);
539   SL::DB::Manager::Vendor->delete_all(all => 1);
540 };
541
542 1;