Revision 1d559eff
Von Jan Büren vor etwa 7 Jahren hinzugefügt
SL/DATEV.pm | ||
---|---|---|
372 | 372 |
die 'no exporttype set!' unless $self->has_exporttype; |
373 | 373 |
|
374 | 374 |
if ($self->exporttype == DATEV_ET_BUCHUNGEN) { |
375 |
_csv_buchungsexport_to_file($self, data => $self->csv_buchungsexport); |
|
375 |
|
|
376 |
$self->generate_datev_data(from_to => $self->fromto); |
|
377 |
return if $self->errors; |
|
378 |
|
|
379 |
my $datev_ref = SL::DATEV::CSV->new(datev_lines => $self->generate_datev_lines, |
|
380 |
from => $self->from, |
|
381 |
to => $self->to, |
|
382 |
locked => $self->locked, |
|
383 |
); |
|
384 |
|
|
385 |
my $filename = "EXTF_DATEV_kivitendo" . $self->from->ymd() . '-' . $self->to->ymd() . ".csv"; |
|
386 |
|
|
387 |
my $csv = Text::CSV_XS->new({ |
|
388 |
binary => 1, |
|
389 |
sep_char => ";", |
|
390 |
always_quote => 1, |
|
391 |
eol => "\r\n", |
|
392 |
}) or die "Cannot use CSV: ".Text::CSV_XS->error_diag(); |
|
393 |
|
|
394 |
my $csv_file = IO::File->new($self->export_path . '/' . $filename, '>:encoding(cp1252)') or die "Can't open: $!"; |
|
395 |
$csv->print($csv_file, $_) for @{ $datev_ref }; |
|
396 |
$csv_file->close; |
|
397 |
|
|
398 |
return { download_token => $self->download_token, filenames => $filename }; |
|
376 | 399 |
|
377 | 400 |
} elsif ($self->exporttype == DATEV_ET_STAMM) { |
378 | 401 |
die 'will never be implemented'; |
... | ... | |
404 | 427 |
$_[0] <=> 0; |
405 | 428 |
} |
406 | 429 |
|
430 |
sub locked { |
|
431 |
my $self = shift; |
|
432 |
|
|
433 |
if (@_) { |
|
434 |
$self->{locked} = $_[0]; |
|
435 |
} |
|
436 |
return $self->{locked}; |
|
437 |
} |
|
438 |
|
|
407 | 439 |
sub generate_datev_data { |
408 | 440 |
$main::lxdebug->enter_sub(); |
409 | 441 |
|
... | ... | |
1370 | 1402 |
return { download_token => $self->download_token, filenames => \@filenames }; |
1371 | 1403 |
} |
1372 | 1404 |
|
1373 |
sub csv_buchungsexport { |
|
1374 |
my $self = shift; |
|
1375 |
my %params = @_; |
|
1376 |
|
|
1377 |
$self->generate_datev_data(from_to => $self->fromto); |
|
1378 |
return if $self->errors; |
|
1379 |
|
|
1380 |
my @datev_lines = @{ $self->generate_datev_lines }; |
|
1381 |
|
|
1382 |
my @csv_columns = SL::DATEV::CSV->kivitendo_to_datev(); |
|
1383 |
my @csv_headers = SL::DATEV::CSV->generate_csv_header( |
|
1384 |
from => $self->from->ymd(''), |
|
1385 |
to => $self->to->ymd(''), |
|
1386 |
first_day_of_fiscal_year => $self->to->year . '0101', |
|
1387 |
locked => 0 |
|
1388 |
); |
|
1389 |
|
|
1390 |
my @array_of_datev; |
|
1391 |
|
|
1392 |
# 2 Headers |
|
1393 |
push @array_of_datev, \@csv_headers; |
|
1394 |
push @array_of_datev, [ map { $_->{csv_header_name} } @csv_columns ]; |
|
1395 |
|
|
1396 |
my @warnings; |
|
1397 |
foreach my $row ( @datev_lines ) { |
|
1398 |
my @current_datev_row; |
|
1399 |
|
|
1400 |
# shorten strings |
|
1401 |
if ($row->{belegfeld1}) { |
|
1402 |
$row->{buchungsbes} = $row->{belegfeld1} if $row->{belegfeld1}; |
|
1403 |
$row->{belegfeld1} = substr($row->{belegfeld1}, 0, 12); |
|
1404 |
$row->{buchungsbes} = substr($row->{buchungsbes}, 0, 60); |
|
1405 |
} |
|
1406 |
|
|
1407 |
$row->{datum} = datetofour($row->{datum}, 0); |
|
1408 |
$row->{kost1} = substr($row->{kost1}, 0, 8) if $row->{kost1}; |
|
1409 |
$row->{kost2} = substr($row->{kost2}, 0, 8) if $row->{kost2}; |
|
1410 |
|
|
1411 |
# , as decimal point and trim for UstID |
|
1412 |
$row->{umsatz} =~ s/\./,/; |
|
1413 |
$row->{ustid} =~ s/\s//g if $row->{ustid}; # trim whitespace |
|
1414 |
|
|
1415 |
foreach my $column (@csv_columns) { |
|
1416 |
if (exists $column->{max_length} && $column->{kivi_datev_name} ne 'not yet implemented') { |
|
1417 |
# check max length |
|
1418 |
die "Incorrect length of field" if length($row->{ $column->{kivi_datev_name} }) > $column->{max_length}; |
|
1419 |
} |
|
1420 |
if (exists $column->{valid_check} && $column->{kivi_datev_name} ne 'not yet implemented') { |
|
1421 |
# more checks, listed as user warnings |
|
1422 |
push @warnings, t8("Wrong field value '#1' for field '#2' for the transaction" . |
|
1423 |
" with amount '#3'",$row->{ $column->{kivi_datev_name} }, |
|
1424 |
$column->{kivi_datev_name},$row->{umsatz}) |
|
1425 |
unless ($column->{valid_check}->($row->{ $column->{kivi_datev_name} })); |
|
1426 |
} |
|
1427 |
push @current_datev_row, $row->{ $column->{kivi_datev_name} }; |
|
1428 |
} |
|
1429 |
push @array_of_datev, \@current_datev_row; |
|
1430 |
} |
|
1431 |
$self->warnings(@warnings) if @warnings; |
|
1432 |
return \@array_of_datev; |
|
1433 |
} |
|
1434 |
|
|
1435 |
sub _csv_buchungsexport_to_file { |
|
1436 |
my $self = shift; |
|
1437 |
my %params = @_; |
|
1438 |
|
|
1439 |
# we can definitely deny shorter data structures |
|
1440 |
croak ("Need at least 2 rows for header info") unless scalar @{ $params{data} } > 1; |
|
1441 |
|
|
1442 |
my $filename = "EXTF_DATEV_kivitendo" . $self->from->ymd() . '-' . $self->to->ymd() . ".csv"; |
|
1443 |
my @data = \$params{data}; |
|
1444 |
|
|
1445 |
my $csv = Text::CSV_XS->new({ |
|
1446 |
binary => 1, |
|
1447 |
sep_char => ";", |
|
1448 |
always_quote => 1, |
|
1449 |
eol => "\r\n", |
|
1450 |
}) or die "Cannot use CSV: ".Text::CSV_XS->error_diag(); |
|
1451 |
|
|
1452 |
if ($csv->version >= 1.18) { |
|
1453 |
# get rid of stupid datev warnings in "Validity program" |
|
1454 |
$csv->quote_empty(1); |
|
1455 |
} |
|
1456 |
|
|
1457 |
my $csv_file = IO::File->new($self->export_path . '/' . $filename, '>:encoding(cp1252)') or die "Can't open: $!"; |
|
1458 |
$csv->print($csv_file, $_) for @{ $params{data} }; |
|
1459 |
$csv_file->close; |
|
1460 |
|
|
1461 |
return { download_token => $self->download_token, filenames => $params{filename} }; |
|
1462 |
} |
|
1463 |
|
|
1464 | 1405 |
sub check_vcnumbers_are_valid_pk_numbers { |
1465 | 1406 |
my ($self) = @_; |
1466 | 1407 |
|
... | ... | |
1763 | 1704 |
|
1764 | 1705 |
Set boundary account numbers for the export. Only useful for a stammdaten export. |
1765 | 1706 |
|
1707 |
=item locked |
|
1708 |
|
|
1709 |
Boolean if the transactions are locked (read-only in kivitenod) or not. |
|
1710 |
Default value is false |
|
1711 |
|
|
1766 | 1712 |
=back |
1767 | 1713 |
|
1768 | 1714 |
=head1 CONSTANTS |
SL/DATEV/CSV.pm | ||
---|---|---|
4 | 4 |
|
5 | 5 |
use SL::Locale::String qw(t8); |
6 | 6 |
use SL::DB::Datev; |
7 |
use SL::Helper::DateTime; |
|
7 | 8 |
|
8 | 9 |
use Carp; |
9 | 10 |
use DateTime; |
... | ... | |
205 | 206 |
}, # pos 40 |
206 | 207 |
); |
207 | 208 |
|
209 |
sub new { |
|
210 |
my $class = shift; |
|
211 |
my %data = @_; |
|
212 |
|
|
213 |
my $obj = bless {}, $class; |
|
214 |
|
|
215 |
croak(t8('We need a valid from date')) unless (ref $data{from} eq 'DateTime'); |
|
216 |
croak(t8('We need a valid to date')) unless (ref $data{to} eq 'DateTime'); |
|
217 |
croak(t8('We need a array of datev_lines')) unless (ref $data{datev_lines} eq 'ARRAY'); |
|
218 |
|
|
219 |
# TODO no params here, better class variables/values |
|
220 |
return _csv_buchungsexport(from => $data{from}, |
|
221 |
to => $data{to}, |
|
222 |
datev_lines => $data{datev_lines}, |
|
223 |
locked => $data{locked}, |
|
224 |
); |
|
225 |
|
|
226 |
$obj; |
|
227 |
} |
|
228 |
|
|
208 | 229 |
sub check_encoding { |
209 | 230 |
my ($test) = @_; |
210 | 231 |
return undef unless $test; |
... | ... | |
216 | 237 |
} |
217 | 238 |
} |
218 | 239 |
|
219 |
sub kivitendo_to_datev { |
|
240 |
sub _kivitendo_to_datev {
|
|
220 | 241 |
my ($self) = @_; |
221 | 242 |
|
222 | 243 |
my $entries = scalar (@kivitendo_to_datev); |
... | ... | |
224 | 245 |
return @kivitendo_to_datev; |
225 | 246 |
} |
226 | 247 |
|
227 |
sub generate_csv_header { |
|
228 |
my ($self, %params) = @_;
|
|
248 |
sub _generate_csv_header {
|
|
249 |
my %params = @_;
|
|
229 | 250 |
|
230 | 251 |
# we need from and to in YYYYDDMM |
231 |
croak "Wrong format for from" unless $params{from} =~ m/^[0-9]{8}$/; |
|
232 |
croak "Wrong format for to" unless $params{to} =~ m/^[0-9]{8}$/; |
|
252 |
croak "Wrong format for from $params{from}" unless $params{from} =~ m/^[0-9]{8}$/;
|
|
253 |
croak "Wrong format for to $params{to}" unless $params{to} =~ m/^[0-9]{8}$/;
|
|
233 | 254 |
|
234 | 255 |
# who knows if we want locking and when our fiscal year starts |
235 |
croak "Wrong state of locking" unless $params{locked} =~ m/(0|1)/; |
|
256 |
# croak "Wrong state of locking" unless $params{locked} =~ m/^(0|1)$/; |
|
257 |
my $locked = defined($params{locked}) ? 1 : 0; |
|
236 | 258 |
croak "No startdate of fiscal year" unless $params{first_day_of_fiscal_year} =~ m/^[0-9]{8}$/; |
237 | 259 |
|
238 | 260 |
|
... | ... | |
260 | 282 |
"EXTF", "300", 21, "Buchungsstapel", 7, $created_on, "", "ki", |
261 | 283 |
"kivitendo-datev", "", $meta_datev{beraternr}, $meta_datev{mandantennr}, |
262 | 284 |
$params{first_day_of_fiscal_year}, $length_of_accounts, |
263 |
$params{from}, $params{to}, "", "", 1, "", $params{locked},
|
|
285 |
$params{from}, $params{to}, "", "", 1, "", $locked,
|
|
264 | 286 |
$default_curr, "", "", "","" |
265 | 287 |
); |
266 | 288 |
|
267 | 289 |
return @header; |
268 | 290 |
} |
269 | 291 |
|
292 |
sub _csv_buchungsexport { |
|
293 |
my %params = @_; |
|
294 |
|
|
295 |
my @csv_columns = _kivitendo_to_datev(); |
|
296 |
my @csv_headers = _generate_csv_header( |
|
297 |
from => $params{from}->ymd(''), |
|
298 |
to => $params{to}->ymd(''), |
|
299 |
first_day_of_fiscal_year => $params{to}->year . '0101', |
|
300 |
locked => $params{locked} |
|
301 |
); |
|
302 |
|
|
303 |
my @array_of_datev; |
|
304 |
|
|
305 |
# 2 Headers |
|
306 |
push @array_of_datev, \@csv_headers; |
|
307 |
push @array_of_datev, [ map { $_->{csv_header_name} } @csv_columns ]; |
|
308 |
|
|
309 |
my @warnings; |
|
310 |
foreach my $row (@{ $params{datev_lines} }) { |
|
311 |
my @current_datev_row; |
|
312 |
|
|
313 |
# shorten strings |
|
314 |
if ($row->{belegfeld1}) { |
|
315 |
$row->{buchungsbes} = $row->{belegfeld1} if $row->{belegfeld1}; |
|
316 |
$row->{belegfeld1} = substr($row->{belegfeld1}, 0, 12); |
|
317 |
$row->{buchungsbes} = substr($row->{buchungsbes}, 0, 60); |
|
318 |
} |
|
319 |
|
|
320 |
$row->{datum} = DateTime->from_kivitendo($row->{datum})->strftime('%d%m'); |
|
321 |
|
|
322 |
$row->{kost1} = substr($row->{kost1}, 0, 8) if $row->{kost1}; |
|
323 |
$row->{kost2} = substr($row->{kost2}, 0, 8) if $row->{kost2}; |
|
324 |
|
|
325 |
# , as decimal point and trim for UstID |
|
326 |
$row->{umsatz} = _format_amount($row->{umsatz}); |
|
327 |
$row->{ustid} =~ s/\s//g if $row->{ustid}; # trim whitespace |
|
328 |
|
|
329 |
foreach my $column (@csv_columns) { |
|
330 |
if (exists $column->{max_length} && $column->{kivi_datev_name} ne 'not yet implemented') { |
|
331 |
# check max length |
|
332 |
die "Incorrect length of field" if length($row->{ $column->{kivi_datev_name} }) > $column->{max_length}; |
|
333 |
} |
|
334 |
if (exists $column->{valid_check} && $column->{kivi_datev_name} ne 'not yet implemented') { |
|
335 |
# more checks, listed as user warnings |
|
336 |
push @warnings, t8("Wrong field value '#1' for field '#2' for the transaction" . |
|
337 |
" with amount '#3'",$row->{ $column->{kivi_datev_name} }, |
|
338 |
$column->{kivi_datev_name},$row->{umsatz}) |
|
339 |
unless ($column->{valid_check}->($row->{ $column->{kivi_datev_name} })); |
|
340 |
} |
|
341 |
push @current_datev_row, $row->{ $column->{kivi_datev_name} }; |
|
342 |
} |
|
343 |
push @array_of_datev, \@current_datev_row; |
|
344 |
} |
|
345 |
return (\@array_of_datev, \@warnings); |
|
346 |
} |
|
347 |
|
|
270 | 348 |
sub _format_amount { |
271 | 349 |
$::form->format_amount({ numberformat => '1000,00' }, @_); |
272 | 350 |
} |
... | ... | |
283 | 361 |
|
284 | 362 |
=head1 SYNOPSIS |
285 | 363 |
|
364 |
use SL::DATEV qw(:CONSTANTS); |
|
365 |
use SL::DATEV::CSV; |
|
366 |
|
|
367 |
my $startdate = DateTime->new(year => 2014, month => 9, day => 1); |
|
368 |
my $enddate = DateTime->new(year => 2014, month => 9, day => 31); |
|
369 |
my $datev = SL::DATEV->new( |
|
370 |
exporttype => DATEV_ET_BUCHUNGEN, |
|
371 |
format => DATEV_FORMAT_CSV, |
|
372 |
from => $startdate, |
|
373 |
to => $enddate, |
|
374 |
); |
|
375 |
$datev->generate_datev_data; |
|
376 |
|
|
377 |
my $datev_ref = SL::DATEV::CSV->new(datev_lines => $datev->generate_datev_lines, |
|
378 |
from => $datev->from, |
|
379 |
to => $datev->to, |
|
380 |
locked => $datev->locked, |
|
381 |
); |
|
382 |
|
|
383 |
=head1 DESCRIPTION |
|
384 |
|
|
286 | 385 |
The parsing of the DATEV CSV is index based, therefore the correct |
287 | 386 |
column must be present at the corresponding index, i.e.: |
288 | 387 |
Index 2 |
... | ... | |
348 | 447 |
|
349 | 448 |
=over 4 |
350 | 449 |
|
450 |
=item new PARAMS |
|
451 |
|
|
452 |
Constructor for CSV-DATEV export. |
|
453 |
Checks mandantory params as described in section synopsis. |
|
454 |
|
|
351 | 455 |
=item check_encoding |
352 | 456 |
|
353 | 457 |
Helper function, returns true if a string is not empty and cp1252 encoded |
... | ... | |
366 | 470 |
C<params{from}>, C<params{to}> |
367 | 471 |
and C<params{first_day_of_fiscal_year}> have to be in YYYYDDMM date string |
368 | 472 |
format. |
369 |
Furthermore C<params{locked}> needs to be a boolean in number format (0|1).
|
|
473 |
Furthermore C<params{locked}> is a perlish boolean.
|
|
370 | 474 |
|
371 | 475 |
|
372 | 476 |
=item kivitendo_to_datev |
... | ... | |
379 | 483 |
Expects a number in kivitendo database format and returns the same number |
380 | 484 |
in DATEV format. |
381 | 485 |
|
486 |
=item _csv_buchungsexport |
|
487 |
|
|
488 |
Generates the CSV-Format data for the CSV DATEV export and returns |
|
489 |
an 2-dimensional array as an array_ref. |
|
490 |
May additionally return a second array_ref with warnings. |
|
491 |
|
|
492 |
Requires the same date fields as the constructor for a valid DATEV header. |
|
493 |
|
|
494 |
Furthermore we assume that the first day of the fiscal year is |
|
495 |
the first of January and we cannot guarantee that our data in kivitendo |
|
496 |
is locked, that means a booking cannot be modified after a defined (vat tax) |
|
497 |
period. |
|
498 |
Some validity checks (max_length and regex) will be done if the |
|
499 |
data structure contains them and the field is defined. |
|
500 |
|
|
501 |
To add or alter the structure of the data take a look at the C<@kivitendo_to_datev> structure. |
|
502 |
|
|
503 |
|
|
382 | 504 |
=back |
t/datev/datev_format_2018.t | ||
---|---|---|
68 | 68 |
# check conversion to csv |
69 | 69 |
$datev1->from($startdate); |
70 | 70 |
$datev1->to($enddate); |
71 |
$datev1->csv_buchungsexport(); |
|
72 |
my @warnings = $datev1->warnings; |
|
71 |
my ($datev_ref, $warnings_ref) = SL::DATEV::CSV->new(datev_lines => $datev1->generate_datev_lines, |
|
72 |
from => $startdate, |
|
73 |
to => $enddate, |
|
74 |
locked => $datev1->locked, |
|
75 |
); |
|
76 |
my @warnings = $warnings_ref; |
|
73 | 77 |
is($warnings[0]->[0]->{untranslated}, |
74 | 78 |
'Wrong field value \'#1\' for field \'#2\' for the transaction with amount \'#3\'', 'wrong_encoding'); |
75 | 79 |
|
... | ... | |
87 | 91 |
$datev3->to($enddate); |
88 | 92 |
$datev3->generate_datev_data; |
89 | 93 |
$datev3->generate_datev_lines; |
90 |
$datev3->csv_buchungsexport; |
|
94 |
my ($datev_ref2, $warnings_ref2) = SL::DATEV::CSV->new(datev_lines => $datev3->generate_datev_lines, |
|
95 |
from => $startdate, |
|
96 |
to => $enddate, |
|
97 |
locked => $datev3->locked, |
|
98 |
); |
|
99 |
|
|
100 |
|
|
101 |
|
|
91 | 102 |
@warnings = []; |
92 |
@warnings = $datev3->warnings;
|
|
103 |
@warnings = $warnings_ref2;
|
|
93 | 104 |
is($warnings[0]->[0]->{untranslated}, |
94 | 105 |
'Wrong field value \'#1\' for field \'#2\' for the transaction with amount \'#3\'', 'mixed_wrong_encoding'); |
95 | 106 |
|
... | ... | |
157 | 168 |
$datev2->generate_datev_data; |
158 | 169 |
$datev2->generate_datev_lines; |
159 | 170 |
|
160 |
my @data_csv = splice @{ $datev2->csv_buchungsexport() }, 2, 5; |
|
161 |
@data_csv = sort { $a->[0] <=> $b->[0] } @data_csv; |
|
171 |
my ($datev_ref3, $warnings_ref3) = SL::DATEV::CSV->new(datev_lines => $datev2->generate_datev_lines, |
|
172 |
from => $startdate, |
|
173 |
to => $enddate, |
|
174 |
locked => $datev2->locked, |
|
175 |
); |
|
162 | 176 |
|
177 |
my @data_csv = splice @{ $datev_ref3 }, 2, 5; |
|
178 |
@data_csv = sort { $a->[0] cmp $b->[0] } @data_csv; |
|
163 | 179 |
|
164 | 180 |
my $cp1252_posting_text = SL::Iconv::convert("UTF-8", "CP1252", 'Reisekosten März 2018'); |
165 | 181 |
cmp_bag($data_csv[0], [ 100, 'H', 'EUR', undef, undef, undef, '4660', '1000', 9, '1703', 'Reisekosten ', |
t/datev/invoices.t | ||
---|---|---|
91 | 91 |
}, |
92 | 92 |
{ |
93 | 93 |
'belegfeld1' => "\x{de} sales \x{a5}& inv\x{f6}ice", |
94 |
'buchungstext' => 'Testcustomer', |
|
94 |
|
|
95 |
|
|
96 |
'buchungstext' => 'Testcustomer', |
|
95 | 97 |
'buchungstext' => 'Testcustomer', |
96 | 98 |
'datum' => '05.01.2017', |
97 | 99 |
'gegenkonto' => '1400', |
... | ... | |
152 | 154 |
# check conversion to csv |
153 | 155 |
$datev1->from($startdate); |
154 | 156 |
$datev1->to($enddate); |
155 |
$datev1->use_pk(0); # reset use_pk for csv_buchungsexport |
|
157 |
# reset use_pk for csv_buchungsexport |
|
158 |
$datev1->use_pk(0); |
|
159 |
$datev1->generate_datev_data; |
|
160 |
|
|
161 |
|
|
162 |
my ($datev_ref, $w_ref) = SL::DATEV::CSV->new(datev_lines => $datev1->generate_datev_lines, |
|
163 |
from => $startdate, |
|
164 |
to => $enddate, |
|
165 |
locked => $datev1->locked, |
|
166 |
); |
|
167 |
# warnings should be undef -> no array elements at all |
|
168 |
is(scalar @{ $w_ref }, 0); |
|
156 | 169 |
|
157 | 170 |
# splice away the header, because sort won't do |
158 | 171 |
# we need sort, because pay_invoice is not acc_trans_id order safe |
159 |
my @data_csv = splice @{ $datev1->csv_buchungsexport() }, 2, 5;
|
|
172 |
my @data_csv = splice @{ $datev_ref }, 2, 5;
|
|
160 | 173 |
@data_csv = sort { $a->[0] cmp $b->[0] } @data_csv; |
161 | 174 |
|
162 | 175 |
my $cp1252_belegfeld1 = SL::Iconv::convert("UTF-8", "CP1252", 'Þ sales ¥& i'); |
Auch abrufbar als: Unified diff
DATEV: csv_buchungsexport nach DATEV::CSV.pm ausgelagert
Testfälle angepasst. POD angepasst.
Details:
DATEV.pm
- Klassenvariable locked hinzugefügt.
- Aufruf der CSV-Klasse anstatt der internen Methode
CSV.pm
- Konstruktor wie in DATEV.pm ergänzt und um minimale
Pflichtfeldprüfung ergänzt.
- datetofour durch SL::Helper::DateTime ersetzt
- Helper _format_amount auch aufrufen
- Routinen umbenannt (pseudoprivat mit Unterstrich)
- Prüfung auf locked als perlish boolean
- _csv_buchungsexport um zweiten return array_ref mit warnungen ergänzt
t/datev/*
- Testfälle enstprechend dem neuen API-Call umgeschrieben
- Einen Testfall zur Überprüfung von keiner Warnung ergänzt