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