785cff7e56d6f83952fee680049c89c683102523
[kivitendo-erp.git] / t / datev / datev_format_2018.t
1 use strict;
2 use Test::More;
3 use Test::Deep qw(cmp_deeply);
4
5 use lib 't';
6
7 use_ok 'Support::TestSetup';
8 use SL::DATEV qw(:CONSTANTS);
9 use SL::Dev::ALL qw(:ALL);
10 use List::Util qw(sum);
11 use SL::DB::Buchungsgruppe;
12 use SL::DB::Chart;
13 use DateTime;
14 use Data::Dumper;
15 use utf8;
16
17 Support::TestSetup::login();
18
19 my $dbh = SL::DB->client->dbh;
20
21 clear_up();
22
23 my $d = SL::DB::Default->get;
24 $d->update_attributes(datev_export_format => 'cp1252');
25
26 my $ustid           = 'DE123456788';
27 my $buchungsgruppe7 = SL::DB::Manager::Buchungsgruppe->find_by(description => 'Standard 7%') || die "No accounting group for 7\%";
28 my $date            = DateTime->new(year => 2017, month =>  7, day => 19);
29 my $department      = create_department(description => 'Kästchenweiße heiße Preise');
30 my $project         = create_project(projectnumber => 2017, description => '299');
31 my $customer        = new_customer(name => 'Test customer', ustid => $ustid)->save();
32 my $part1 = new_part(partnumber => '19', description => 'Part 19%')->save;
33 my $part2 = new_part(
34   partnumber         => '7',
35   description        => 'Part 7%',
36   buchungsgruppen_id => $buchungsgruppe7->id,
37 )->save;
38
39 my $invoice = create_sales_invoice(
40   invnumber    => "ݗݘݰݶ",
41   itime        => $date,
42   gldate       => $date,
43   taxincluded  => 0,
44   transdate    => $date,
45   invoiceitems => [ create_invoice_item(part => $part1, qty =>  3, sellprice => 550),
46                     create_invoice_item(part => $part2, qty => 10, sellprice => 50),
47                   ],
48   department_id    => $department->id,
49   globalproject_id => $project->id,
50   customer_id      => $customer->id,
51 );
52
53 # lets make a boom
54 # generate_datev_* doesnt care about encoding but
55 # csv_buchungsexport does! all arabic will be deleted
56 # and no string will be left as invnumber
57
58 my $datev1 = SL::DATEV->new(
59   dbh        => $dbh,
60   trans_id   => $invoice->id,
61 );
62
63 my $startdate = DateTime->new(year => 2017, month =>  1, day =>  1);
64 my $enddate   = DateTime->new(year => 2017, month =>  12, day => 31);
65 my $today     = DateTime->new(year => 2017, month =>  3, day => 17);
66
67
68 $datev1->from($startdate);
69 $datev1->to($enddate);
70
71 $datev1->generate_datev_data;
72 $datev1->generate_datev_lines;
73
74 # check conversion to csv
75 $datev1->from($startdate);
76 $datev1->to($enddate);
77 my ($datev_csv, $die_message);
78 eval {
79   $datev_csv = SL::DATEV::CSV->new(datev_lines  => $datev1->generate_datev_lines,
80                                    from         => $startdate,
81                                    to           => $enddate,
82                                    locked       => $datev1->locked,
83                                   );
84   my $lines_aref = $datev_csv->lines; # dies only if we assign (do stuff with the data)
85   1;
86 } or do {
87   $die_message = $@;
88 };
89 ok($die_message =~ m/Falscher Feldwert 'ݗݘݰݶ' für Feld 'belegfeld1' bei der Transaktion mit dem Umsatz von/, 'wrong_encoding');
90
91
92 $invoice->invnumber('ݗݘݰݶmuh');
93 $invoice->save();
94
95 my $datev3 = SL::DATEV->new(
96   dbh        => $dbh,
97   trans_id   => $invoice->id,
98 );
99
100 $datev3->from($startdate);
101 $datev3->to($enddate);
102 $datev3->generate_datev_data;
103 $datev3->generate_datev_lines;
104 my ($datev_csv2, $die_message2);
105 eval {
106   $datev_csv2 = SL::DATEV::CSV->new(datev_lines  => $datev3->generate_datev_lines,
107                                     from         => $startdate,
108                                     to           => $enddate,
109                                     locked       => $datev3->locked,
110                                    );
111 my $lines_aref = $datev_csv2->lines; # dies only if we assign (do stuff with the data)
112
113   1;
114 } or do {
115   $die_message2 = $@;
116 };
117
118 # redefine invnumber, we have mixed encodings, should still fail
119 ok($die_message2 =~ m/Falscher Feldwert 'ݗݘݰݶmuh' für Feld 'belegfeld1' bei der Transaktion mit dem Umsatz von/, 'mixed_wrong_encoding');
120
121 # check with good number
122 $invoice->invnumber('meine muh');
123 $invoice->save();
124
125 my $datev4 = SL::DATEV->new(
126   dbh        => $dbh,
127   trans_id   => $invoice->id,
128 );
129
130 $datev4->from($startdate);
131 $datev4->to($enddate);
132 $datev4->generate_datev_data;
133 $datev4->generate_datev_lines;
134
135 my ($datev_csv4, $die_message3, $lines_aref);
136 eval {
137   $datev_csv4 = SL::DATEV::CSV->new(datev_lines  => $datev4->generate_datev_lines,
138                                     from         => $startdate,
139                                     to           => $enddate,
140                                     locked       => $datev4->locked,
141                                    );
142   $lines_aref = $datev_csv4->lines; # dies only if we assign (do stuff with the data)
143
144   1;
145 } or do {
146   $die_message3 = $@;
147 };
148 ok(!($die_message3), 'no die message');
149 ok(scalar @{ $datev_csv4->warnings } == 0, 'no warnings');
150
151 my @sorted =  sort { $a->[0] cmp $b->[0] } @{ $lines_aref };
152 cmp_deeply $sorted[0],    [ '1963,5', 'S', 'EUR', '', '', '',
153                             '1400', '8400', '', '1907', 'meine muh',
154                             '', '', 'Test customer', '', '', '', '', '', '',
155                             '', '', '', '', '', '', '', '', '',
156                             '', '', '', '', '', '', '', "K\x{e4}stchen",
157                             '299', '', $ustid, '', '', '',
158                             '', '', '', '', '', '', '', '', '',
159                             '', '', '', '', '', '', '', '', '',
160                             '', '', '', '', '', '', '', '', '',
161                             '', '', '', '', '', '', '', '', '',
162                             '', '', '', '', '', '', '', '', '',
163                             '', '', '', '', '', '', '', '', '',
164                             '', '', '', '', '', '', '', '', '',
165                             '', '', '', '', '', '', '', '1', '',
166                             '', '', '', '', '',
167                           ];
168 cmp_deeply $sorted[1],     [ '535', 'S', 'EUR', '', '', '',
169                              '1400', '8300', '', '1907','meine muh',
170                             '', '', 'Test customer', '', '', '', '', '', '',
171                             '', '', '', '', '', '', '', '', '',
172                             '', '', '', '', '', '', '', "K\x{e4}stchen",
173                             '299', '', $ustid, '', '', '',
174                             '', '', '', '', '', '', '', '', '',
175                             '', '', '', '', '', '', '', '', '',
176                             '', '', '', '', '', '', '', '', '',
177                             '', '', '', '', '', '', '', '', '',
178                             '', '', '', '', '', '', '', '', '',
179                             '', '', '', '', '', '', '', '', '',
180                             '', '', '', '', '', '', '', '', '',
181                             '', '', '', '', '', '', '', '1', '',
182                             '', '', '', '', '',
183                           ];
184 # create one haben buchung with GLTransaction today
185
186 my $expense_chart = SL::DB::Manager::Chart->find_by(accno => '4660'); # Reisekosten
187 my $cash_chart    = SL::DB::Manager::Chart->find_by(accno => '1000'); # Kasse
188
189 my $gl_transaction = create_gl_transaction(
190   reference      => "Reise März 2018",
191   description    => "Reisekonsten März 2018 / Ma Schmidt",
192   transdate      => $today,
193   taxincluded    => 1,
194   type           => undef,
195   bookings       => [
196                       {
197                         chart  => $expense_chart,
198                         taxkey => 9,
199                         debit  => 100, # net 84.03
200                       },
201                       {
202                         chart  => $cash_chart,
203                         taxkey => 0,
204                         credit => 100,
205                       },
206                     ],
207 );
208
209 my $datev2 = SL::DATEV->new(
210   dbh        => $dbh,
211   trans_id   => $gl_transaction->id,
212 );
213
214 $datev2->from($startdate);
215 $datev2->to($enddate);
216 $datev2->generate_datev_data;
217
218 my $datev_csv3  = SL::DATEV::CSV->new(datev_lines  => $datev2->generate_datev_lines,
219                                       from         => $startdate,
220                                       to           => $enddate,
221                                       locked       => $datev2->locked,
222                                      );
223
224 my @data_csv    = sort { $a->[0] cmp $b->[0] } @{ $datev_csv3->lines };
225 cmp_deeply($data_csv[0], [ '100', 'S', 'EUR', '', '', '', '4660', '1000', 9, '1703', 'Reise März 2',
226                      '', '', 'Reisekonsten März 2018 / Ma Schmidt', '', '', '', '', '', '', '', '',
227                      '', '', '', '', '', '', '', '', '', '', '', '', '',
228                      '', '', '', '', '', '', '', '', '', '', '',
229                      '', '', '', '', '', '', '', '', '', '', '', '', '',
230                      '', '', '', '', '', '', '', '', '', '', '', '', '',
231                      '', '', '', '', '', '', '', '', '', '', '', '', '',
232                      '', '', '', '', '', '', '', '', '', '', '', '', '',
233                      '', '', '', '', '', '', '', '', '', '', '', '', '',
234                      '', '', '1', '', '', '', '', '', '', ]
235        );
236
237
238 # check deliverydate
239 $invoice->deliverydate(DateTime->new(year => 2017, month =>  7, day => 18));
240 $invoice->save();
241
242 $datev1 = SL::DATEV->new(
243   dbh        => $dbh,
244   trans_id   => $invoice->id,
245 );
246
247 $datev1->from($startdate);
248 $datev1->to($enddate);
249 $datev1->generate_datev_data;
250 $datev1->generate_datev_lines;
251
252 $datev_csv = SL::DATEV::CSV->new(datev_lines  => $datev1->generate_datev_lines,
253                                  from         => $startdate,
254                                  to           => $enddate,
255                                  locked       => $datev1->locked,
256 );
257 @sorted    = sort { $a->[0] cmp $b->[0] } @{ $datev_csv->lines };
258 cmp_deeply $sorted[0],    [ '1963,5', 'S', 'EUR', '', '', '',
259                             '1400', '8400', '', '1907', 'meine muh',
260                             '', '', 'Test customer', '', '', '', '', '', '',
261                             '', '', '', '', '', '', '', '', '',
262                             '', '', '', '', '', '', '', "K\x{e4}stchen",
263                             '299', '', $ustid, '', '', '',
264                             '', '', '', '', '', '', '', '', '',
265                             '', '', '', '', '', '', '', '', '',
266                             '', '', '', '', '', '', '', '', '',
267                             '', '', '', '', '', '', '', '', '',
268                             '', '', '', '', '', '', '', '', '',
269                             '', '', '', '', '', '', '', '', '',
270                             '', '', '', '', '', '', '', '', '',
271                             '', '', '', '', '', '', '', '1', '18072017',
272                             '', '', '', '', '',
273                           ];
274 cmp_deeply $sorted[1],     [ '535', 'S', 'EUR', '', '', '',
275                              '1400', '8300', '', '1907','meine muh',
276                             '', '', 'Test customer', '', '', '', '', '', '',
277                             '', '', '', '', '', '', '', '', '',
278                             '', '', '', '', '', '', '', "K\x{e4}stchen",
279                             '299', '', $ustid, '', '', '',
280                             '', '', '', '', '', '', '', '', '',
281                             '', '', '', '', '', '', '', '', '',
282                             '', '', '', '', '', '', '', '', '',
283                             '', '', '', '', '', '', '', '', '',
284                             '', '', '', '', '', '', '', '', '',
285                             '', '', '', '', '', '', '', '', '',
286                             '', '', '', '', '', '', '', '', '',
287                             '', '', '', '', '', '', '', '1', '18072017',
288                             '', '', '', '', '',
289                           ];
290
291 $gl_transaction->deliverydate(DateTime->new(year => 2017, month =>  7, day => 18));
292 $gl_transaction->save;
293
294 $datev1 = SL::DATEV->new(
295   dbh        => $dbh,
296   trans_id   => $gl_transaction->id,
297 );
298
299 $datev1->from($startdate);
300 $datev1->to($enddate);
301 $datev1->generate_datev_data;
302
303 $datev_csv   = SL::DATEV::CSV->new(datev_lines  => $datev1->generate_datev_lines,
304                                    from         => $startdate,
305                                    to           => $enddate,
306                                    locked       => $datev1->locked,
307 );
308
309 @sorted      = sort { $a->[0] cmp $b->[0] } @{ $datev_csv->lines };
310 cmp_deeply($sorted[0], [ '100', 'S', 'EUR', '', '', '', '4660', '1000', 9, '1703', 'Reise März 2',
311                          '', '', 'Reisekonsten März 2018 / Ma Schmidt', '', '', '', '', '', '', '', '',
312                          '', '', '', '', '', '', '', '', '', '', '', '', '',
313                          '', '', '', '', '', '', '', '', '', '', '',
314                          '', '', '', '', '', '', '', '', '', '', '', '', '',
315                          '', '', '', '', '', '', '', '', '', '', '', '', '',
316                          '', '', '', '', '', '', '', '', '', '', '', '', '',
317                          '', '', '', '', '', '', '', '', '', '', '', '', '',
318                          '', '', '', '', '', '', '', '', '', '', '', '', '',
319                          '', '', '1', '18072017', '', '', '', '', '', ]
320 );
321
322
323 # TODO warnings are not yet tested
324 # currently most of the valid_checks are senseless because of
325 # the strict input_checks before. Maybe something like encoding mismatch of invnumber,
326 # can be altered to just a warning (not a mandantory field!)
327
328 done_testing();
329 clear_up();
330
331
332 sub clear_up {
333   SL::DB::Manager::AccTransaction->delete_all( all => 1);
334   SL::DB::Manager::GLTransaction->delete_all(  all => 1);
335   SL::DB::Manager::InvoiceItem->delete_all(    all => 1);
336   SL::DB::Manager::Invoice->delete_all(        all => 1);
337   SL::DB::Manager::Customer->delete_all(       all => 1);
338   SL::DB::Manager::Part->delete_all(           all => 1);
339   SL::DB::Manager::Project->delete_all(        all => 1);
340   SL::DB::Manager::Department->delete_all(     all => 1);
341   SL::DATEV->clean_temporary_directories;
342 };
343
344 1;