Testfälle für DATEV angepasst
[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 $buchungsgruppe7 = SL::DB::Manager::Buchungsgruppe->find_by(description => 'Standard 7%') || die "No accounting group for 7\%";
27 my $date            = DateTime->new(year => 2017, month =>  7, day => 19);
28 my $department      = create_department(description => 'Kästchenweiße heiße Preise');
29 my $project         = create_project(projectnumber => 2017, description => '299');
30 my $customer        = new_customer(name => 'Test customer', ustid => 'DE12345678')->save();
31 my $part1 = new_part(partnumber => '19', description => 'Part 19%')->save;
32 my $part2 = new_part(
33   partnumber         => '7',
34   description        => 'Part 7%',
35   buchungsgruppen_id => $buchungsgruppe7->id,
36 )->save;
37
38 my $invoice = create_sales_invoice(
39   invnumber    => "ݗݘݰݶ",
40   itime        => $date,
41   gldate       => $date,
42   taxincluded  => 0,
43   transdate    => $date,
44   invoiceitems => [ create_invoice_item(part => $part1, qty =>  3, sellprice => 550),
45                     create_invoice_item(part => $part2, qty => 10, sellprice => 50),
46                   ],
47   department_id    => $department->id,
48   globalproject_id => $project->id,
49   customer_id      => $customer->id,
50 );
51
52 # lets make a boom
53 # generate_datev_* doesnt care about encoding but
54 # csv_buchungsexport does! all arabic will be deleted
55 # and no string will be left as invnumber
56
57 my $datev1 = SL::DATEV->new(
58   dbh        => $dbh,
59   trans_id   => $invoice->id,
60 );
61
62 my $startdate = DateTime->new(year => 2017, month =>  1, day =>  1);
63 my $enddate   = DateTime->new(year => 2017, month =>  12, day => 31);
64 my $today     = DateTime->new(year => 2017, month =>  3, day => 17);
65
66
67 $datev1->from($startdate);
68 $datev1->to($enddate);
69
70 $datev1->generate_datev_data;
71 $datev1->generate_datev_lines;
72
73 # check conversion to csv
74 $datev1->from($startdate);
75 $datev1->to($enddate);
76 my ($datev_csv, $die_message);
77 eval {
78   $datev_csv = SL::DATEV::CSV->new(datev_lines  => $datev1->generate_datev_lines,
79                                    from         => $startdate,
80                                    to           => $enddate,
81                                    locked       => $datev1->locked,
82                                   );
83   my $lines_aref = $datev_csv->lines; # dies only if we assign (do stuff with the data)
84   1;
85 } or do {
86   $die_message = $@;
87 };
88 ok($die_message =~ m/Falscher Feldwert 'ݗݘݰݶ' für Feld 'belegfeld1' bei der Transaktion mit dem Umsatz von/, 'wrong_encoding');
89
90
91 $invoice->invnumber('ݗݘݰݶmuh');
92 $invoice->save();
93
94 my $datev3 = SL::DATEV->new(
95   dbh        => $dbh,
96   trans_id   => $invoice->id,
97 );
98
99 $datev3->from($startdate);
100 $datev3->to($enddate);
101 $datev3->generate_datev_data;
102 $datev3->generate_datev_lines;
103 my ($datev_csv2, $die_message2);
104 eval {
105   $datev_csv2 = SL::DATEV::CSV->new(datev_lines  => $datev3->generate_datev_lines,
106                                     from         => $startdate,
107                                     to           => $enddate,
108                                     locked       => $datev3->locked,
109                                    );
110 my $lines_aref = $datev_csv2->lines; # dies only if we assign (do stuff with the data)
111
112   1;
113 } or do {
114   $die_message2 = $@;
115 };
116
117 # redefine invnumber, we have mixed encodings, should still fail
118 ok($die_message2 =~ m/Falscher Feldwert 'ݗݘݰݶmuh' für Feld 'belegfeld1' bei der Transaktion mit dem Umsatz von/, 'mixed_wrong_encoding');
119
120 # check with good number
121 $invoice->invnumber('meine muh');
122 $invoice->save();
123
124 my $datev4 = SL::DATEV->new(
125   dbh        => $dbh,
126   trans_id   => $invoice->id,
127 );
128
129 $datev4->from($startdate);
130 $datev4->to($enddate);
131 $datev4->generate_datev_data;
132 $datev4->generate_datev_lines;
133 my ($datev_csv4, $die_message3, $lines_aref);
134 eval {
135   $datev_csv4 = SL::DATEV::CSV->new(datev_lines  => $datev4->generate_datev_lines,
136                                     from         => $startdate,
137                                     to           => $enddate,
138                                     locked       => $datev4->locked,
139                                    );
140   $lines_aref = $datev_csv4->lines; # dies only if we assign (do stuff with the data)
141
142   1;
143 } or do {
144   $die_message3 = $@;
145 };
146 ok(!($die_message3), 'no die message');
147 ok(scalar @{ $datev_csv4->warnings } == 0, 'no warnings');
148
149 my @sorted =  sort { $a->[0] cmp $b->[0] } @{ $lines_aref };
150 cmp_deeply $sorted[0],    [ '1963,5', 'S', 'EUR', '', '', '',
151                             '1400', '8400', '', '1907', 'meine muh',
152                             '', '', 'Test customer', '', '', '', '', '', '',
153                             '', '', '', '', '', '', '', '', '',
154                             '', '', '', '', '', '', '', "K\x{e4}stchen",
155                             '299', '','DE12345678', '', '', '',
156                             '', '', '', '', '', '', '', '', '',
157                             '', '', '', '', '', '', '', '', '',
158                             '', '', '', '', '', '', '', '', '',
159                             '', '', '', '', '', '', '', '', '',
160                             '', '', '', '', '', '', '', '', '',
161                             '', '', '', '', '', '', '', '', '',
162                             '', '', '', '', '', '', '', '', '',
163                             '', '', '', '', '', '', '', '', '',
164                             '',
165                           ];
166 cmp_deeply $sorted[1],     [ '535', 'S', 'EUR', '', '', '',
167                              '1400', '8300', '', '1907','meine muh',
168                             '', '', 'Test customer', '', '', '', '', '', '',
169                             '', '', '', '', '', '', '', '', '',
170                             '', '', '', '', '', '', '', "K\x{e4}stchen",
171                             '299', '','DE12345678', '', '', '',
172                             '', '', '', '', '', '', '', '', '',
173                             '', '', '', '', '', '', '', '', '',
174                             '', '', '', '', '', '', '', '', '',
175                             '', '', '', '', '', '', '', '', '',
176                             '', '', '', '', '', '', '', '', '',
177                             '', '', '', '', '', '', '', '', '',
178                             '', '', '', '', '', '', '', '', '',
179                             '', '', '', '', '', '', '', '', '',
180                             '',
181                           ];
182 # create one haben buchung with GLTransaction today
183
184 my $expense_chart = SL::DB::Manager::Chart->find_by(accno => '4660'); # Reisekosten
185 my $cash_chart    = SL::DB::Manager::Chart->find_by(accno => '1000'); # Kasse
186 my $tax_chart     = SL::DB::Manager::Chart->find_by(accno => '1576'); # Vorsteuer
187 my $tax_9         = SL::DB::Manager::Tax->find_by(taxkey => 9, rate => 0.19) || die "No tax";
188
189 my @acc_trans;
190 push(@acc_trans, SL::DB::AccTransaction->new(
191                                       chart_id   => $expense_chart->id,
192                                       chart_link => $expense_chart->link,
193                                       amount     => -84.03,
194                                       transdate  => $today,
195                                       source     => '',
196                                       taxkey     => 9,
197                                       tax_id     => $tax_9->id,
198                                       project_id => $project->id,
199 ));
200 push(@acc_trans, SL::DB::AccTransaction->new(
201                                       chart_id   => $tax_chart->id,
202                                       chart_link => $tax_chart->link,
203                                       amount     => -15.97,
204                                       transdate  => $today,
205                                       source     => '',
206                                       taxkey     => 9,
207                                       tax_id     => $tax_9->id,
208                                       project_id => $project->id,
209 ));
210 push(@acc_trans, SL::DB::AccTransaction->new(
211                                       chart_id   => $cash_chart->id,
212                                       chart_link => $cash_chart->link,
213                                       amount     => 100,
214                                       transdate  => $today,
215                                       source     => '',
216                                       taxkey     => 0,
217                                       tax_id     => 0,
218 ));
219
220 my $gl_transaction = SL::DB::GLTransaction->new(
221   reference      => "Reise März 2018",
222   description    => "Reisekonsten März 2018 / Ma Schmidt",
223   transdate      => $today,
224   gldate         => $today,
225   employee_id    => SL::DB::Manager::Employee->current->id,
226   taxincluded    => 1,
227   type           => undef,
228   ob_transaction => 0,
229   cb_transaction => 0,
230   storno         => 0,
231   storno_id      => undef,
232   transactions   => \@acc_trans,
233 )->save;
234 my $datev2 = SL::DATEV->new(
235   dbh        => $dbh,
236   trans_id   => $gl_transaction->id,
237 );
238
239 $datev2->from($startdate);
240 $datev2->to($enddate);
241 $datev2->generate_datev_data;
242
243 my $datev_csv3  = SL::DATEV::CSV->new(datev_lines  => $datev2->generate_datev_lines,
244                                       from         => $startdate,
245                                       to           => $enddate,
246                                       locked       => $datev2->locked,
247                                      );
248
249 my @data_csv    = sort { $a->[0] cmp $b->[0] } @{ $datev_csv3->lines };
250 cmp_deeply($data_csv[0], [ '100', 'S', 'EUR', '', '', '', '4660', '1000', 9, '1703', 'Reise März 2',
251                      '', '', 'Reisekonsten März 2018 / Ma Schmidt', '', '', '', '', '', '', '', '',
252                      '', '', '', '', '', '', '', '', '', '', '', '', '',
253                      '', '', '', '', '', '', '', '', '', '', '',
254                      '', '', '', '', '', '', '', '', '', '', '', '', '',
255                      '', '', '', '', '', '', '', '', '', '', '', '', '',
256                      '', '', '', '', '', '', '', '', '', '', '', '', '',
257                      '', '', '', '', '', '', '', '', '', '', '', '', '',
258                      '', '', '', '', '', '', '', '', '', '', '', '', '',
259                      '', '', '', '', '' ]
260        );
261
262 # TODO warnings are not yet tested
263 # currently most of the valid_checks are senseless because of
264 # the strict input_checks before. Maybe something like encoding mismatch of invnumber,
265 # can be altered to just a warning (not a mandantory field!)
266
267 done_testing();
268 clear_up();
269
270
271 sub clear_up {
272   SL::DB::Manager::AccTransaction->delete_all( all => 1);
273   SL::DB::Manager::GLTransaction->delete_all(  all => 1);
274   SL::DB::Manager::InvoiceItem->delete_all(    all => 1);
275   SL::DB::Manager::Invoice->delete_all(        all => 1);
276   SL::DB::Manager::Customer->delete_all(       all => 1);
277   SL::DB::Manager::Part->delete_all(           all => 1);
278   SL::DB::Manager::Project->delete_all(        all => 1);
279   SL::DB::Manager::Department->delete_all(     all => 1);
280   SL::DATEV->clean_temporary_directories;
281 };
282
283 1;