X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=SL%2FDATEV%2FCSV.pm;h=8b8e8859822facac10eb86eded3cf49e5368bd3c;hb=991369b17d679e2855f4d5086d0b9769dc2ae1aa;hp=b7ce84ffe70959fb905b8df251f9099cbef4c5d0;hpb=cf8942d3f90f2c1bc430da72fa84c4e5316b0c52;p=kivitendo-erp.git diff --git a/SL/DATEV/CSV.pm b/SL/DATEV/CSV.pm index b7ce84ffe..8b8e88598 100644 --- a/SL/DATEV/CSV.pm +++ b/SL/DATEV/CSV.pm @@ -3,13 +3,15 @@ package SL::DATEV::CSV; use strict; use Carp; use DateTime; -use Encode qw(decode); +use Encode qw(encode); use Scalar::Util qw(looks_like_number); use SL::DB::Datev; use SL::DB::Chart; use SL::Helper::DateTime; use SL::Locale::String qw(t8); +use SL::Util qw(trim); +use SL::VATIDNr; use Rose::Object::MakeMethods::Generic ( scalar => [ qw(datev_lines from to locked warnings) ], @@ -22,7 +24,7 @@ my @kivitendo_to_datev = ( max_length => 13, type => 'Value', required => 1, - input_check => sub { my ($input) = @_; return (looks_like_number($input) && length($input) <= 13) }, + input_check => sub { my ($input) = @_; return (looks_like_number($input) && length($input) <= 13 && $input > 0) }, formatter => \&_format_amount, valid_check => sub { my ($check) = @_; return ($check =~ m/^\d{1,10}(\,\d{1,2})?$/) }, }, @@ -56,7 +58,7 @@ my @kivitendo_to_datev = ( }, { kivi_datev_name => 'not yet implemented', - sv_header_name => t8('Base Transaction Value'), + csv_header_name => t8('Base Transaction Value'), }, { kivi_datev_name => 'not yet implemented', @@ -102,16 +104,21 @@ my @kivitendo_to_datev = ( max_length => 12, type => 'Text', default => '', - input_check => sub { my ($text) = @_; check_encoding($text); }, + input_check => sub { return 1 unless $::instance_conf->get_datev_export_format eq 'cp1252'; + my ($text) = @_; check_encoding($text); }, + valid_check => sub { return 1 if $::instance_conf->get_datev_export_format eq 'cp1252'; + my ($text) = @_; check_encoding($text); }, formatter => sub { my ($input) = @_; return substr($input, 0, 12) }, }, { - kivi_datev_name => 'not yet implemented', + kivi_datev_name => 'belegfeld2', csv_header_name => t8('Invoice Field 2'), max_length => 12, type => 'Text', default => '', - valid_check => sub { my ($check) = @_; return ($check =~ m/[ -~]{1,12}/) }, + input_check => sub { my ($check) = @_; return 1 unless $check; return (ref (DateTime->from_kivitendo($check)) eq 'DateTime') }, + formatter => sub { my ($input) = @_; return '' unless $input; return trim(DateTime->from_kivitendo($input)->strftime('%e%m%y')) }, + valid_check => sub { my ($check) = @_; return 1 unless $check; return ($check =~ m/^[0-9]{5,6}$/) }, }, { kivi_datev_name => 'not yet implemented', @@ -119,12 +126,15 @@ my @kivitendo_to_datev = ( type => 'Value', }, { - kivi_datev_name => 'buchungsbes', + kivi_datev_name => 'buchungstext', csv_header_name => t8('Posting Text'), max_length => 60, type => 'Text', default => '', - input_check => sub { my ($text) = @_; return 1 unless $text; check_encoding($text); }, + input_check => sub { return 1 unless $::instance_conf->get_datev_export_format eq 'cp1252'; + my ($text) = @_; check_encoding($text); }, + valid_check => sub { return 1 if $::instance_conf->get_datev_export_format eq 'cp1252'; + my ($text) = @_; check_encoding($text); }, formatter => sub { my ($input) = @_; return substr($input, 0, 60) }, }, # pos 14 { @@ -228,14 +238,270 @@ my @kivitendo_to_datev = ( max_length => 15, type => 'Text', default => '', - input_check => sub { my ($check) = @_; return ($check eq '' || $check =~ m/[A-Z]{2}\w{5,13}/) }, + input_check => sub { + my ($ustid) = @_; + return 1 if ('' eq $ustid); + return SL::VATIDNr->validate($ustid); + }, formatter => sub { my ($input) = @_; $input =~ s/\s//g; return $input }, valid_check => sub { my ($ustid) = @_; return 1 if ('' eq $ustid); - return ($ustid =~ m/^CH|^[A-Z]{2}\w{5,13}$/); + return SL::VATIDNr->validate($ustid); }, }, # pos 40 + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, # pos 50 + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, # pos 60 + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, # pos 70 + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, # pos 80 + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, # pos 90 + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, # pos 100 + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, # pos 110 + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'locked', + csv_header_name => t8('Lock'), + max_length => 1, + type => 'Number', + default => 1, + valid_check => sub { my ($check) = @_; return ($check =~ m/^(0|1)$/) }, + }, # pos 114 + { + kivi_datev_name => 'leistungsdatum', + csv_header_name => t8('Payment Date'), + max_length => 8, + type => 'Date', + default => '', + input_check => sub { my ($check) = @_; return 1 if ('' eq $check); return (ref (DateTime->from_kivitendo($check)) eq 'DateTime') }, + formatter => sub { my ($input) = @_; return '' if ('' eq $input); return DateTime->from_kivitendo($input)->strftime('%d%m%Y') }, + valid_check => sub { my ($check) = @_; return 1 if ('' eq $check); return ($check =~ m/^[0-9]{8}$/) }, + }, # pos 115 + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, + { + kivi_datev_name => 'not yet implemented', + }, # pos 120 ); sub new { @@ -255,29 +521,21 @@ sub check_encoding { my ($test) = @_; return undef unless $test; if (eval { - decode('Windows-1252', $test, Encode::FB_CROAK|Encode::LEAVE_SRC); + encode('Windows-1252', $test, Encode::FB_CROAK|Encode::LEAVE_SRC); 1 }) { return 1; } } -sub _kivitendo_to_datev { - my ($self) = @_; - - my $entries = scalar (@kivitendo_to_datev); - push @kivitendo_to_datev, { kivi_datev_name => 'not yet implemented' } for 1 .. (116 - $entries); - return @kivitendo_to_datev; -} - sub header { my ($self) = @_; my @header; # we can safely set these defaults - # TODO use Helper::DateTime and get length_of_accounts from DATEV.pm - my $today = DateTime->now(time_zone => "local"); + # TODO get length_of_accounts from DATEV.pm + my $today = DateTime->now_local; my $created_on = $today->ymd('') . $today->hms('') . '000'; my $length_of_accounts = length(SL::DB::Manager::Chart->get_first(where => [charttype => 'A'])->accno) // 4; my $default_curr = SL::DB::Default->get_default_currency; @@ -298,7 +556,7 @@ sub header { } my @header_row_1 = ( - "EXTF", "300", 21, "Buchungsstapel", 7, $created_on, "", "ki", + "EXTF", "510", 21, "Buchungsstapel", 7, $created_on, "", "ki", "kivitendo-datev", "", $meta_datev{beraternr}, $meta_datev{mandantennr}, $self->first_day_of_fiscal_year->ymd(''), $length_of_accounts, $self->from->ymd(''), $self->to->ymd(''), "", "", 1, "", $self->locked, @@ -307,7 +565,7 @@ sub header { push @header, [ @header_row_1 ]; # second header row, just the column names - push @header, [ map { $_->{csv_header_name} } _kivitendo_to_datev() ]; + push @header, [ map { $_->{csv_header_name} } @kivitendo_to_datev ]; return \@header; } @@ -316,7 +574,6 @@ sub lines { my ($self) = @_; my (@array_of_datev, @warnings); - my @csv_columns = _kivitendo_to_datev(); foreach my $row (@{ $self->datev_lines }) { my @current_datev_row; @@ -324,7 +581,7 @@ sub lines { # 1. check all datev_lines and see if we have a defined value # 2. if we don't have a defined value set a default if exists # 3. otherwise die - foreach my $column (@csv_columns) { + foreach my $column (@kivitendo_to_datev) { if ($column->{kivi_datev_name} eq 'not yet implemented') { push @current_datev_row, ''; next; @@ -534,14 +791,7 @@ To add or alter the structure of the data take a look at the C<@kivitendo_to_dat =head1 TODO CAVEAT - -Currently no effort has be done that _kivitenod_to_datev is only intializied once: -Therefore the second call may generate integrity faults: - - my $datev_csv_1 = SL::DATEV::CSV->new(...)->lines; - my $datev_csv_2 = SL::DATEV::CSV->new(...)->lines; - -Secondly one can circumevent the check of the warnings.quite easily, +One can circumevent the check of the warnings.quite easily, becaus warnings are generated after the call to lines: # WRONG usage @@ -552,4 +802,3 @@ becaus warnings are generated after the call to lines: my $lines = $datev_csv->lines; die if @{ $datev_csv->warnings }; somethin_with($lines); -