DATEV-Tests nach Erweiterung f. Festschreibungskennzeichen gefixed
[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
134 my ($datev_csv4, $die_message3, $lines_aref);
135 eval {
136   $datev_csv4 = SL::DATEV::CSV->new(datev_lines  => $datev4->generate_datev_lines,
137                                     from         => $startdate,
138                                     to           => $enddate,
139                                     locked       => $datev4->locked,
140                                    );
141   $lines_aref = $datev_csv4->lines; # dies only if we assign (do stuff with the data)
142
143   1;
144 } or do {
145   $die_message3 = $@;
146 };
147 ok(!($die_message3), 'no die message');
148 ok(scalar @{ $datev_csv4->warnings } == 0, 'no warnings');
149
150 my @sorted =  sort { $a->[0] cmp $b->[0] } @{ $lines_aref };
151 cmp_deeply $sorted[0],    [ '1963,5', 'S', 'EUR', '', '', '',
152                             '1400', '8400', '', '1907', 'meine muh',
153                             '', '', 'Test customer', '', '', '', '', '', '',
154                             '', '', '', '', '', '', '', '', '',
155                             '', '', '', '', '', '', '', "K\x{e4}stchen",
156                             '299', '','DE12345678', '', '', '',
157                             '', '', '', '', '', '', '', '', '',
158                             '', '', '', '', '', '', '', '', '',
159                             '', '', '', '', '', '', '', '', '',
160                             '', '', '', '', '', '', '', '', '',
161                             '', '', '', '', '', '', '', '', '',
162                             '', '', '', '', '', '', '', '', '',
163                             '', '', '', '', '', '', '', '', '',
164                             '', '', '', '', '', '', '', '1', '',
165                             '', '', '', '', '',
166                           ];
167 cmp_deeply $sorted[1],     [ '535', 'S', 'EUR', '', '', '',
168                              '1400', '8300', '', '1907','meine muh',
169                             '', '', 'Test customer', '', '', '', '', '', '',
170                             '', '', '', '', '', '', '', '', '',
171                             '', '', '', '', '', '', '', "K\x{e4}stchen",
172                             '299', '','DE12345678', '', '', '',
173                             '', '', '', '', '', '', '', '', '',
174                             '', '', '', '', '', '', '', '', '',
175                             '', '', '', '', '', '', '', '', '',
176                             '', '', '', '', '', '', '', '', '',
177                             '', '', '', '', '', '', '', '', '',
178                             '', '', '', '', '', '', '', '', '',
179                             '', '', '', '', '', '', '', '', '',
180                             '', '', '', '', '', '', '', '1', '',
181                             '', '', '', '', '',
182                           ];
183 # create one haben buchung with GLTransaction today
184
185 my $expense_chart = SL::DB::Manager::Chart->find_by(accno => '4660'); # Reisekosten
186 my $cash_chart    = SL::DB::Manager::Chart->find_by(accno => '1000'); # Kasse
187
188 my $gl_transaction = create_gl_transaction(
189   reference      => "Reise März 2018",
190   description    => "Reisekonsten März 2018 / Ma Schmidt",
191   transdate      => $today,
192   taxincluded    => 1,
193   type           => undef,
194   bookings       => [
195                       {
196                         chart  => $expense_chart,
197                         taxkey => 9,
198                         debit  => 100, # net 84.03
199                       },
200                       {
201                         chart  => $cash_chart,
202                         taxkey => 0,
203                         credit => 100,
204                       },
205                     ],
206 );
207
208 my $datev2 = SL::DATEV->new(
209   dbh        => $dbh,
210   trans_id   => $gl_transaction->id,
211 );
212
213 $datev2->from($startdate);
214 $datev2->to($enddate);
215 $datev2->generate_datev_data;
216
217 my $datev_csv3  = SL::DATEV::CSV->new(datev_lines  => $datev2->generate_datev_lines,
218                                       from         => $startdate,
219                                       to           => $enddate,
220                                       locked       => $datev2->locked,
221                                      );
222
223 my @data_csv    = sort { $a->[0] cmp $b->[0] } @{ $datev_csv3->lines };
224 cmp_deeply($data_csv[0], [ '100', 'S', 'EUR', '', '', '', '4660', '1000', 9, '1703', 'Reise März 2',
225                      '', '', 'Reisekonsten März 2018 / Ma Schmidt', '', '', '', '', '', '', '', '',
226                      '', '', '', '', '', '', '', '', '', '', '', '', '',
227                      '', '', '', '', '', '', '', '', '', '', '',
228                      '', '', '', '', '', '', '', '', '', '', '', '', '',
229                      '', '', '', '', '', '', '', '', '', '', '', '', '',
230                      '', '', '', '', '', '', '', '', '', '', '', '', '',
231                      '', '', '', '', '', '', '', '', '', '', '', '', '',
232                      '', '', '', '', '', '', '', '', '', '', '', '', '',
233                      '', '', '1', '', '', '', '', '', '', ]
234        );
235
236 # TODO warnings are not yet tested
237 # currently most of the valid_checks are senseless because of
238 # the strict input_checks before. Maybe something like encoding mismatch of invnumber,
239 # can be altered to just a warning (not a mandantory field!)
240
241 done_testing();
242 clear_up();
243
244
245 sub clear_up {
246   SL::DB::Manager::AccTransaction->delete_all( all => 1);
247   SL::DB::Manager::GLTransaction->delete_all(  all => 1);
248   SL::DB::Manager::InvoiceItem->delete_all(    all => 1);
249   SL::DB::Manager::Invoice->delete_all(        all => 1);
250   SL::DB::Manager::Customer->delete_all(       all => 1);
251   SL::DB::Manager::Part->delete_all(           all => 1);
252   SL::DB::Manager::Project->delete_all(        all => 1);
253   SL::DB::Manager::Department->delete_all(     all => 1);
254   SL::DATEV->clean_temporary_directories;
255 };
256
257 1;