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