Revision 1dd06079
Von Jan Büren vor 11 Monaten hinzugefügt
SL/DATEV.pm | ||
---|---|---|
38 | 38 |
use SL::Locale::String qw(t8); |
39 | 39 |
use SL::VATIDNr; |
40 | 40 |
|
41 |
use Archive::Zip; |
|
41 | 42 |
use Data::Dumper; |
42 | 43 |
use DateTime; |
43 | 44 |
use Exporter qw(import); |
... | ... | |
48 | 49 |
use List::UtilsBy qw(partition_by sort_by); |
49 | 50 |
use Text::CSV_XS; |
50 | 51 |
use Time::HiRes qw(gettimeofday); |
52 |
use XML::LibXML; |
|
51 | 53 |
|
52 | 54 |
{ |
53 | 55 |
my $i = 0; |
... | ... | |
348 | 350 |
$csv_file->close; |
349 | 351 |
$self->{warnings} = $datev_csv->warnings; |
350 | 352 |
|
353 |
$self->_create_xml_and_documents if $self->{documents} && scalar @{ $self->{guids} }; |
|
354 |
|
|
351 | 355 |
# convert utf-8 to cp1252//translit if set |
352 | 356 |
if ($::instance_conf->get_datev_export_format eq 'cp1252-translit') { |
353 | 357 |
|
... | ... | |
402 | 406 |
} |
403 | 407 |
return $self->{imported}; |
404 | 408 |
} |
409 |
sub documents { |
|
410 |
my $self = shift; |
|
411 |
|
|
412 |
if (@_) { |
|
413 |
$self->{documents} = $_[0]; |
|
414 |
} |
|
415 |
return $self->{documents}; |
|
416 |
} |
|
417 |
sub _create_xml_and_documents { |
|
418 |
my $self = shift; |
|
419 |
|
|
420 |
die "No guids" unless scalar @{ $self->{guids} }; |
|
421 |
|
|
422 |
my $today = DateTime->now_local; |
|
423 |
my $doc = XML::LibXML::Document->new('1.0', 'utf-8'); |
|
424 |
|
|
425 |
my $root = $doc->createElement('archive'); |
|
426 |
#<archive xmlns="http://xml.datev.de/bedi/tps/document/v05.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xml.datev.de/bedi/tps/document/v05.0 Document_v050.xsd" version="5.0" generatingSystem="DATEV-Musterdaten"> |
|
427 |
|
|
428 |
$root->setAttribute('xmlns' => 'http://xml.datev.de/bedi/tps/document/v05.0'); |
|
429 |
$root->setAttribute('xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance'); |
|
430 |
$root->setAttribute('xsi:schemaLocation' => 'http://xml.datev.de/bedi/tps/document/v05.0 Document_v050.xsd'); |
|
431 |
$root->setAttribute('version' => '5.0'); |
|
432 |
$root->setAttribute('generatingSystem' => 'kivitendo'); |
|
433 |
|
|
434 |
# header with timestamp |
|
435 |
my $header_tag = $doc->createElement('header'); |
|
436 |
$root->appendChild($header_tag); |
|
437 |
my $date_tag = $doc->createElement('date'); |
|
438 |
$date_tag->appendTextNode($today); |
|
439 |
$header_tag->appendChild($date_tag); |
|
440 |
|
|
441 |
|
|
442 |
# content |
|
443 |
my $content_node = $doc->createElement('content'); |
|
444 |
$root->appendChild($content_node); |
|
445 |
# we have n document childs |
|
446 |
foreach my $guid (@{ $self->{guids} }) { |
|
447 |
# 1. get filename and file location |
|
448 |
my $file_version = SL::DB::Manager::FileVersion->find_by(guid => $guid); |
|
449 |
die "Invalid guid $guid" unless ref $file_version eq 'SL::DB::FileVersion'; |
|
450 |
# file_name has to be unique add guid if needed |
|
451 |
my $filename_for_zip = (exists $self->{files}{$file_version->file_name}) |
|
452 |
? $file_version->file_name . '__' . $guid |
|
453 |
: $file_version->file_name; |
|
454 |
$self->{files}{$filename_for_zip} = $file_version->get_system_location; |
|
455 |
# create xml metadata for files |
|
456 |
my $document_node = $doc->createElement('document'); |
|
457 |
# set attr |
|
458 |
$document_node->setAttribute('guid' => $guid); |
|
459 |
$document_node->setAttribute('processID' => '1'); |
|
460 |
$document_node->setAttribute('type' => '1'); |
|
461 |
$content_node->appendChild($document_node); |
|
462 |
my $extension_node = $doc->createElement('extension'); |
|
463 |
$extension_node->setAttribute('xsi:type' => 'File'); |
|
464 |
$extension_node->setAttribute('name' => $filename_for_zip); |
|
465 |
$document_node->appendChild($extension_node); |
|
466 |
} |
|
467 |
$doc->setDocumentElement($root); |
|
468 |
|
|
469 |
# create Archive::Zip in Export Path |
|
470 |
my $zip = Archive::Zip->new(); |
|
471 |
# add metadata document |
|
472 |
$zip->addString($doc->toString(), 'document.xml'); |
|
473 |
# add real files |
|
474 |
foreach my $filename (keys %{ $self->{files} }) { |
|
475 |
$zip->addFile($self->{files}{$filename}, $filename); |
|
476 |
} |
|
477 |
die "Cannot write Belege-XML.zip" unless ($zip->writeToFileNamed($self->export_path . 'Belege-XML.zip') |
|
478 |
== Archive::Zip::AZ_OK()); |
|
479 |
} |
|
405 | 480 |
|
406 | 481 |
sub generate_datev_data { |
407 | 482 |
$main::lxdebug->enter_sub(); |
... | ... | |
820 | 895 |
my $taxkey = 0; |
821 | 896 |
my $charttax = 0; |
822 | 897 |
my $ustid =""; |
898 |
my $document_guid =""; |
|
823 | 899 |
my ($haben, $soll); |
824 | 900 |
for (my $i = 0; $i < $trans_lines; $i++) { |
825 | 901 |
if ($trans_lines == 2) { |
... | ... | |
907 | 983 |
} |
908 | 984 |
# set lock for each transaction |
909 | 985 |
$datev_data{locked} = $self->locked; |
910 |
|
|
986 |
# add guids if datev export with documents is requested |
|
987 |
if ($self->documents) { |
|
988 |
# add exactly one document link for the latest created/uploaded document |
|
989 |
my $latest_document = SL::DB::Manager::File->get_first(query => |
|
990 |
[ |
|
991 |
object_id => $transaction->[$haben]->{trans_id}, |
|
992 |
file_type => 'document' |
|
993 |
], |
|
994 |
sort_by => 'itime DESC'); |
|
995 |
if (ref $latest_document eq 'SL::DB::File') { |
|
996 |
# if we have a booking document add guid from the latest version |
|
997 |
$datev_data{document_guid} = $latest_document->file_version->[-1]->guid; |
|
998 |
push @{ $self->{guids} }, $datev_data{document_guid}; |
|
999 |
} |
|
1000 |
} |
|
911 | 1001 |
push(@datev_lines, \%datev_data) if $datev_data{umsatz}; |
912 | 1002 |
} |
913 | 1003 |
|
... | ... | |
956 | 1046 |
return 1; |
957 | 1047 |
} |
958 | 1048 |
|
1049 |
sub check_document_export { |
|
1050 |
my ($self) = @_; |
|
1051 |
|
|
1052 |
# no dms enabled and works only for type Filesystem |
|
1053 |
return 0 unless $::instance_conf->get_doc_storage |
|
1054 |
&& $::instance_conf->get_doc_storage_for_documents eq 'Filesystem'; |
|
1055 |
|
|
1056 |
return 1; |
|
1057 |
|
|
1058 |
# TODO maybe needed |
|
1059 |
# not all last month ar ap gl booking have an entry -> rent ? |
|
1060 |
my $query = <<"SQL"; |
|
1061 |
select distinct trans_id,object_id from acc_trans |
|
1062 |
left join files on files.object_id=trans_id |
|
1063 |
where date_trunc('month', transdate) = date_trunc('month', current_date - interval '1 month') |
|
1064 |
and object_id is null |
|
1065 |
LIMIT 1 |
|
1066 |
SQL |
|
1067 |
my ($booking_has_no_document) = selectrow_query($::form, SL::DB->client->dbh, $query); |
|
1068 |
return defined $booking_has_no_document ? 0 : 1; |
|
1069 |
|
|
1070 |
} |
|
959 | 1071 |
sub DESTROY { |
960 | 1072 |
clean_temporary_directories(); |
961 | 1073 |
} |
Auch abrufbar als: Unified diff
DATEV-Export um Beleg-Export erweitert
Die Option steht bei aktivierten DMS und dem Backend-Typ 'Dateisystem'
zu Verfügung.