Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 8bf25ad5

Von Jan Büren vor etwa 7 Jahren hinzugefügt

  • ID 8bf25ad536af8805c1c59c6261b0cbae38903dc6
  • Vorgänger 254ef1b2
  • Nachfolger e428a414

Weitere Überarbeitung DATEV/CSV.pm

Default-Werte falls definiert in datev_csv gesetzt.
Pflichtfelder markiert
Kern-Algorithmus klarer definiert (Hinweise von Sven)
- Formatierung in Array pro Feldwert ausgelagert
- Eingangs-Werte prüfen (input_check)
- Logikstruktur klarer (kein unless nach if-bedingung)

Unterschiede anzeigen:

SL/DATEV.pm
375 375

  
376 376
  $self->generate_datev_data(from_to => $self->fromto);
377 377
  return if $self->errors;
378

  
379
  my $datev_ref, $self->warnings = SL::DATEV::CSV->new(datev_lines  => $self->generate_datev_lines,
378
  my $datev_ref;
379
  ($datev_ref, $self->{warnings}) = SL::DATEV::CSV->new(datev_lines  => $self->generate_datev_lines,
380 380
                                                       from         => $self->from,
381 381
                                                       to           => $self->to,
382 382
                                                       locked       => $self->locked,
SL/DATEV/CSV.pm
9 9
use Carp;
10 10
use DateTime;
11 11
use Encode qw(decode);
12
use Scalar::Util qw(looks_like_number);
12 13

  
13 14

  
14 15
my @kivitendo_to_datev = (
......
17 18
                              csv_header_name => t8('Transaction Value'),
18 19
                              max_length      => 13,
19 20
                              type            => 'Value',
21
                              required        => 1,
22
                              input_check     => sub { my ($input) = @_; return (looks_like_number($input) && length($input) <= 13) },
23
                              formatter       => sub { my ($input) = @_; return _format_amount($input) },
20 24
                              valid_check     => sub { my ($check) = @_; return ($check =~ m/^\d{1,10}(\,\d{1,2})?$/) },
21 25
                            },
22 26
                            {
......
24 28
                              csv_header_name => t8('Debit/Credit Label'),
25 29
                              max_length      => 1,
26 30
                              type            => 'Text',
31
                              required        => 1,
32
                              default         => 'S',
33
                              input_check     => sub { my ($check) = @_; return ($check =~ m/^(S|H)$/) },
34
                              formatter       => sub { my ($input) = @_; return $input eq 'H' ? 'H' : 'S' },
27 35
                              valid_check     => sub { my ($check) = @_; return ($check =~ m/^(S|H)$/) },
28 36
                            },
29 37
                            {
......
31 39
                              csv_header_name => t8('Transaction Value Currency Code'),
32 40
                              max_length      => 3,
33 41
                              type            => 'Text',
42
                              default         => '',
43
                              input_check     => sub { my ($check) = @_; return ($check eq '' || $check =~ m/^[A-Z]{3}$/) },
34 44
                              valid_check     => sub { my ($check) = @_; return ($check =~ m/^[A-Z]{3}$/) },
35 45
                            },
36 46
                            {
......
38 48
                              csv_header_name => t8('Exchange Rate'),
39 49
                              max_length      => 11,
40 50
                              type            => 'Number',
51
                              default         => '',
41 52
                              valid_check     => sub { my ($check) = @_; return ($check =~ m/^[0-9]*\.?[0-9]*$/) },
42 53
                            },
43 54
                            {
44 55
                              kivi_datev_name => 'not yet implemented',
45
                              csv_header_name => t8('Base Transaction Value'),
56
                              sv_header_name => t8('Base Transaction Value'),
46 57
                            },
47 58
                            {
48 59
                              kivi_datev_name => 'not yet implemented',
......
51 62
                            {
52 63
                              kivi_datev_name => 'konto',
53 64
                              csv_header_name => t8('Account'),
54
                              max_length      => 9, # May contain a maximum of 8 or 9 digits -> perldoc
65
                              max_length      => 9,
55 66
                              type            => 'Account',
56
                              valid_check     => sub { my ($check) = @_; return ($check =~ m/^[0-9]{4,9}$/) },
67
                              required        => 1,
68
                              input_check     => sub { my ($check) = @_; return ($check =~ m/^[0-9]{4,9}$/) },
57 69
                            },
58 70
                            {
59 71
                              kivi_datev_name => 'gegenkonto',
60 72
                              csv_header_name => t8('Contra Account'),
61
                              max_length      => 9, # May contain a maximum of 8 or 9 digits -> perldoc
73
                              max_length      => 9,
62 74
                              type            => 'Account',
63
                              valid_check     => sub { my ($check) = @_; return ($check =~ m/^[0-9]{4,9}$/) },
75
                              required        => 1,
76
                              input_check     => sub { my ($check) = @_; return ($check =~ m/^[0-9]{4,9}$/) },
64 77
                            },
65 78
                            {
66 79
                              kivi_datev_name => 'buchungsschluessel',
67 80
                              csv_header_name => t8('Posting Key'),
68 81
                              max_length      => 2,
69 82
                              type            => 'Text',
70
                              valid_check     => sub { my ($check) = @_; return ($check =~ m/^[0-9]{0,2}$/) },
83
                              default         => '',
84
                              input_check     => sub { my ($check) = @_; return ($check =~ m/^[0-9]{0,2}$/) },
71 85
                            },
72 86
                            {
73 87
                              kivi_datev_name => 'datum',
74 88
                              csv_header_name => t8('Invoice Date'),
75 89
                              max_length      => 4,
76 90
                              type            => 'Date',
91
                              required        => 1,
92
                              input_check     => sub { my ($check) = @_; return (ref (DateTime->from_kivitendo($check)) eq 'DateTime') },
93
                              formatter       => sub { my ($input) = @_; return DateTime->from_kivitendo($input)->strftime('%d%m') },
77 94
                              valid_check     => sub { my ($check) = @_; return ($check =~ m/^[0-9]{4}$/) },
78 95
                            },
79 96
                            {
......
81 98
                              csv_header_name => t8('Invoice Field 1'),
82 99
                              max_length      => 12,
83 100
                              type            => 'Text',
84
                              valid_check     => sub { my ($text) = @_; check_encoding($text); },
101
                              default         => '',
102
                              input_check     => sub { my ($text) = @_; check_encoding($text); },
103
                              formatter       => sub { my ($input) = @_; return substr($input, 0, 12) },
85 104
                            },
86 105
                            {
87 106
                              kivi_datev_name => 'not yet implemented',
88 107
                              csv_header_name => t8('Invoice Field 2'),
89
                             max_length      => 12,
108
                              max_length      => 12,
90 109
                              type            => 'Text',
110
                              default         => '',
91 111
                              valid_check     => sub { my ($check) = @_; return ($check =~ m/[ -~]{1,12}/) },
92 112
                            },
93 113
                            {
......
100 120
                              csv_header_name => t8('Posting Text'),
101 121
                              max_length      => 60,
102 122
                              type            => 'Text',
103
                              valid_check     => sub { my ($text) = @_; return 1 unless $text; check_encoding($text);  },
123
                              default         => '',
124
                              input_check     => sub { my ($text) = @_; return 1 unless $text; check_encoding($text);  },
125
                              formatter       => sub { my ($input) = @_; return substr($input, 0, 60) },
104 126
                            },  # pos 14
105 127
                            {
106 128
                              kivi_datev_name => 'not yet implemented',
......
177 199
                              csv_header_name => t8('Cost Center'),
178 200
                              max_length      => 8,
179 201
                              type            => 'Text',
180
                              valid_check     => sub { my ($text) = @_; return 1 unless $text; check_encoding($text);  },
202
                              default         => '',
203
                              input_check     => sub { my ($text) = @_; return 1 unless $text; check_encoding($text);  },
204
                              formatter       => sub { my ($input) = @_; return substr($input, 0, 8) },
181 205
                            }, # pos 37
182 206
                            {
183 207
                              kivi_datev_name => 'kost2',
184 208
                              csv_header_name => t8('Cost Center'),
185 209
                              max_length      => 8,
186 210
                              type            => 'Text',
187
                              valid_check     => sub { my ($text) = @_; return 1 unless $text; check_encoding($text);  },
211
                              default         => '',
212
                              input_check     => sub { my ($text) = @_; return 1 unless $text; check_encoding($text);  },
213
                              formatter       => sub { my ($input) = @_; return substr($input, 0, 8) },
188 214
                            }, # pos 38
189 215
                            {
190 216
                              kivi_datev_name => 'not yet implemented',
......
198 224
                              csv_header_name => t8('EU Member State and VAT ID Number'),
199 225
                              max_length      => 15,
200 226
                              type            => 'Text',
227
                              default         => '',
228
                              input_check     => sub { my ($check) = @_; return ($check eq '' || $check =~ m/[A-Z]{2}\w{5,13}/) },
229
                              formatter       => sub { my ($input) = @_; return ($input =~ s/\s//g) },
201 230
                              valid_check     => sub {
202 231
                                                       my ($ustid) = @_;
203
                                                       return 1 unless defined($ustid);
232
                                                       return 1 if ('' eq $ustid);
204 233
                                                       return ($ustid =~ m/^CH|^[A-Z]{2}\w{5,13}$/);
205 234
                                                     },
206 235
                            }, # pos 40
......
250 279

  
251 280
  # we need from and to in YYYYDDMM
252 281
  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}$/;
282
  croak "Wrong format for to $params{to}"     unless $params{to} =~ m/^[0-9]{8}$/;
254 283

  
255 284
  # who knows if we want locking and when our fiscal year starts
256 285
  # croak "Wrong state of locking"      unless $params{locked} =~ m/^(0|1)$/;
......
310 339
  foreach my $row (@{ $params{datev_lines} }) {
311 340
    my @current_datev_row;
312 341

  
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

  
342
    # 1. check all datev_lines and see if we have a defined value
343
    # 2. if we don't have a defined value set a default if exists
344
    # 3. otherwise die
329 345
    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};
346
      if ($column->{kivi_datev_name} eq 'not yet implemented') {
347
        push @current_datev_row, '';
348
        next;
349
      }
350
      my $data = $row->{$column->{kivi_datev_name}};
351
      if (!defined $data) {
352
        if (defined $column->{default}) {
353
          $data = $column->{default};
354
        } else {
355
           die 'No sensible value or a sensible default found for the entry: ' . $column->{kivi_datev_name};
356
        }
357
      }
358
      # checkpoint a: no undefined data. All strict checks now!
359
      if (exists $column->{input_check}) {
360
        die t8("Wrong field value '#1' for field '#2' for the transaction with amount '#3'",
361
                $data, $column->{kivi_datev_name}, $row->{umsatz})
362
          unless  $column->{input_check}->($data);
363
      }
364
      # checkpoint b: we can safely format the input
365
      if ($column->{formatter}) {
366
        $data = $column->{formatter}->($data);
333 367
      }
334
      if (exists $column->{valid_check} && $column->{kivi_datev_name} ne 'not yet implemented') {
335
        # more checks, listed as user warnings
368
      # checkpoint c: all soft checks now, will pop up as a user warning
369
      if (exists $column->{valid_check} && !$column->{valid_check}->($data)) {
336 370
        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} }));
371
                           " with amount '#3'", $data, $column->{kivi_datev_name}, $row->{umsatz});
340 372
      }
341
      push @current_datev_row, $row->{ $column->{kivi_datev_name} };
373
      push @current_datev_row, $data;
342 374
    }
343 375
    push @array_of_datev, \@current_datev_row;
344 376
  }

Auch abrufbar als: Unified diff