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