Merge branch 'master' of ssh://git-grichardson@lx-office.linet-services.de/~/lx-offic...
authorG. Richardson <information@lx-office-hosting.de>
Fri, 30 Apr 2010 08:41:12 +0000 (10:41 +0200)
committerG. Richardson <information@lx-office-hosting.de>
Fri, 30 Apr 2010 08:41:12 +0000 (10:41 +0200)
29 files changed:
SL/AccTransCorrections.pm
SL/CT.pm
SL/Form.pm
SL/ReportGenerator.pm
SL/Template.pm
SL/WH.pm
bin/mozilla/arap.pl
bin/mozilla/ca.pl
bin/mozilla/io.pl
bin/mozilla/rp.pl
config/lx-erp.conf
doc/changelog
doc/excel_templates.txt [new file with mode: 0644]
locale/de/all
locale/de/am
locale/de/dn
locale/de/do
locale/de/ic
locale/de/io
locale/de/ir
locale/de/is
locale/de/locales.pl
locale/de/login
locale/de/oe
locale/de/todo
templates/webpages/acctranscorrections/analyze_overview_de.html
templates/webpages/acctranscorrections/analyze_overview_master.html
templates/webpages/acctranscorrections/assistant_for_wrong_taxkeys_de.html
templates/webpages/acctranscorrections/assistant_for_wrong_taxkeys_master.html

index 44f3afd..ec440f1 100644 (file)
@@ -288,6 +288,49 @@ sub _check_trans_invoices_inventory_with_taxkeys {
   return 0;
 }
 
+# Problemfall: Verkaufsrechnungen, bei denen Steuern verbucht wurden, obwohl
+# kein Steuerschlüssel eingetragen ist.
+sub _check_missing_taxkeys_in_invoices {
+  $::lxdebug->enter_sub;
+
+  my $self        = shift;
+  my %params      = @_;
+  my $transaction = $params{transaction};
+  my $found_broken = 0;
+
+  $::lxdebug->leave_sub and return 0
+    if    !$transaction->[0]->{invoice};
+
+  my @sub_transactions = $self->_group_sub_transactions($transaction);
+
+  for my $sub_transaction (@sub_transactions) {
+    $::lxdebug->leave_sub and return 0
+      if    _is_split_transaction($sub_transaction)
+         || _is_simple_transaction($sub_transaction);
+
+    my $split_side_entries = _get_splitted_side($sub_transaction);
+    my $num_tax_rows;
+    my $num_taxed_rows;
+    for my $entry (@{ $split_side_entries }) {
+      my $is_tax = grep { m/(?:AP_tax|AR_tax)/ } keys %{ $entry->{chartlinks} };
+
+      $num_tax_rows++   if  $is_tax;
+      $num_taxed_rows++ if !$is_tax && $entry->{tax_key} != 0;
+    }
+
+    # now if this has tax rows but NO taxed rows, something is wrong.
+    if ($num_tax_rows > 0 && $num_taxed_rows == 0) {
+      $params{problem}->{type} = 'missing_taxkeys_in_invoices';
+      push @{ $self->{missing_taxkeys_in_invoices} ||= [] }, $params{problem};
+      $found_broken = 1;
+    }
+  }
+
+  $::lxdebug->leave_sub;
+
+  return $found_broken;
+}
+
 # Problemfall: Kreditorenbuchungen, bei denen mit Umsatzsteuerschlüsseln
 # gebucht wurde und Debitorenbuchungen, bei denen mit Vorsteuerschlüsseln
 # gebucht wurde.
@@ -623,8 +666,18 @@ sub analyze {
     unshift @problems, $problem;
   }
 
+  if (0 != scalar @{ $self->{missing_taxkeys_in_invoices} }) {
+    my $problem = {
+      'type'        => 'missing_taxkeys_in_invoices',
+      'ap_problems' => [ grep { $_->{data}->{module} eq 'ap' } @{ $self->{missing_taxkeys_in_invoices} } ],
+      'ar_problems' => [ grep { $_->{data}->{module} eq 'ar' } @{ $self->{missing_taxkeys_in_invoices} } ],
+    };
+    unshift @problems, $problem;
+  }
+
   $main::lxdebug->leave_sub();
 
+#  $::lxdebug->dump(0, 'problems:', \@problems);
 
   return @problems;
 }
index a661e8c..9089aab 100644 (file)
--- a/SL/CT.pm
+++ b/SL/CT.pm
@@ -1089,4 +1089,80 @@ sub get_bank_info {
   return $result;
 }
 
+sub parse_excel_file {
+  $main::lxdebug->enter_sub();
+
+  my ($self, $myconfig, $form) = @_;
+  my $locale = $main::locale;
+
+  $form->{formname}   = 'sales_quotation';
+  $form->{type}   = 'sales_quotation';
+  $form->{format} = 'excel';
+  $form->{media}  = 'screen';
+  $form->{quonumber} = 1;
+
+
+  # $form->{"notes"} will be overridden by the customer's/vendor's "notes" field. So save it here.
+  $form->{ $form->{"formname"} . "notes" } = $form->{"notes"};
+
+  my $inv                  = "quo";
+  my $due                  = "req";
+  $form->{"${inv}date"} = $form->{transdate};
+  $form->{label}        = $locale->text('Quotation');
+  my $numberfld            = "sqnumber";
+  my $order                = 1;
+
+  # assign number
+  $form->{what_done} = $form->{formname};
+
+  map({ delete($form->{$_}); } grep(/^cp_/, keys(%{ $form })));
+
+  my $output_dateformat = $myconfig->{"dateformat"};
+  my $output_numberformat = $myconfig->{"numberformat"};
+  my $output_longdates = 1;
+
+  # map login user variables
+  map { $form->{"login_$_"} = $myconfig->{$_} } ("name", "email", "fax", "tel", "company");
+
+  # format item dates
+  for my $field (qw(transdate_oe deliverydate_oe)) {
+    map {
+      $form->{$field}[$_] = $locale->date($myconfig, $form->{$field}[$_], 1);
+    } 0 .. $#{ $form->{$field} };
+  }
+
+  if ($form->{shipto_id}) {
+    $form->get_shipto($myconfig);
+  }
+
+  $form->{notes} =~ s/^\s+//g;
+
+  $form->{templates} = $myconfig->{templates};
+
+  delete $form->{printer_command};
+
+  $form->get_employee_info($myconfig);
+
+  my ($cvar_date_fields, $cvar_number_fields) = CVar->get_field_format_list('module' => 'CT', 'prefix' => 'vc_');
+
+  if (scalar @{ $cvar_date_fields }) {
+    format_dates($output_dateformat, $output_longdates, @{ $cvar_date_fields });
+  }
+
+  while (my ($precision, $field_list) = each %{ $cvar_number_fields }) {
+    reformat_numbers($output_numberformat, $precision, @{ $field_list });
+  }
+
+  $form->{excel} = 1;
+  my $extension            = 'xls';
+
+  my $form->{IN}         = "$form->{formname}.${extension}";
+
+  delete $form->{OUT};
+
+  $form->parse_template($myconfig, $main::userspath);
+
+  $main::lxdebug->leave_sub();
+}
+
 1;
index 2ba19b6..11f88ad 100644 (file)
@@ -1178,6 +1178,10 @@ sub parse_template {
   } elsif ( $self->{"format"} =~ /elstertaxbird/i ) {
     $template = XMLTemplate->new($self->{"IN"}, $self, $myconfig, $userspath);
 
+  } elsif ( $self->{"format"} =~ /excel/i ) {
+    $template = ExcelTemplate->new($self->{"IN"}, $self, $myconfig, $userspath);
+    $ext_for_format = 'xls';
+
   } elsif ( defined $self->{'format'}) {
     $self->error("Outputformat not defined. This may be a future feature: $self->{'format'}");
 
@@ -1385,6 +1389,7 @@ sub get_extension_for_format {
   my $extension = $self->{format} =~ /pdf/i          ? ".pdf"
                 : $self->{format} =~ /postscript/i   ? ".ps"
                 : $self->{format} =~ /opendocument/i ? ".odt"
+                : $self->{format} =~ /excel/i        ? ".xls"
                 : $self->{format} =~ /html/i         ? ".html"
                 :                                      "";
 
index b90b655..e23bf77 100644 (file)
@@ -512,7 +512,7 @@ sub generate_pdf_content {
       my $col_idx = 0;
       foreach my $col_name (@visible_columns) {
         my $col = $row->{$col_name};
-        push @{ $data_row }, $self->_decode_text(join("\n", @{ $col->{data} }));
+        push @{ $data_row }, $self->_decode_text(join("\n", @{ $col->{data} || [] }));
 
         $column_props[$col_idx]->{justify} = 'right' if ($col->{align} eq 'right');
 
index 3556dc4..7f4d275 100644 (file)
@@ -1477,4 +1477,95 @@ sub uses_temp_file {
   return 1;
 }
 
+
+##########################################################
+####
+#### ExcelTemplate
+####
+##########################################################
+
+package ExcelTemplate;
+
+use vars qw(@ISA);
+
+@ISA = qw(SimpleTemplate);
+
+sub new {
+  my $type = shift;
+
+  my $self = $type->SUPER::new(@_);
+
+  return $self;
+}
+sub _init {
+  my $self = shift;
+
+  $self->{source}    = shift;
+  $self->{form}      = shift;
+  $self->{myconfig}  = shift;
+  $self->{userspath} = shift;
+
+  $self->{error}     = undef;
+
+  $self->set_tag_style('<<', '>>');
+}
+
+sub get_mime_type() {
+  my ($self) = @_;
+
+  return "application/msexcel";
+}
+
+sub uses_temp_file {
+  return 1;
+}
+
+sub parse {
+  $main::lxdebug->enter_sub();
+
+  my $self   = shift;
+  local *OUT = shift;
+  my $form   = $self->{"form"};
+
+  open(IN, "$form->{templates}/$form->{IN}") or do { $self->{"error"} = "$!"; return 0; };
+  my @lines = <IN>;
+  close IN;
+
+  my $contents = join("", @lines);
+  my @indices;
+  $contents =~ s{
+    $self->{tag_start} [<]* (\s?) [<>\s]* ([\w\s]+) [<>\s]* $self->{tag_end}
+  }{
+    $self->format_vars(align_right => $1 ne '', varstring => $2, length => length($&), indices =>  \@indices)
+  }egx;
+
+  if (!defined($contents)) {
+    $main::lxdebug->leave_sub();
+    return 0;
+  }
+
+  print OUT $contents;
+
+  $main::lxdebug->leave_sub();
+  return 1;
+}
+
+sub format_vars {
+  my ($self, %params) = @_;
+  my $form            = $self->{"form"};
+  my @indices         = @{ $params{indices} };
+  my $align_right     = $params{align_right};
+  my $varstring       = $params{varstring};
+  my $length          = $params{length};
+
+  $varstring =~ s/(\w+)/ $self->_get_loop_variable($1, 0, @indices) /eg;
+  my $old_string=$varstring;
+  my $new_string = sprintf "%*s", ($align_right ? 1 : -1 ) * $length, $varstring;
+  if (!defined($new_string) || $new_string eq ''){
+    $main::lxdebug->message(0, 'varstring' . $varstring . "old" . $old_string); 
+    #  return substr $varstring, ($align_right ? (0, $length) : -$length);
+  }
+  return substr $new_string, ($align_right ? (0, $length) : -$length);
+}
+
 1;
index 44feb83..b164a30 100644 (file)
--- a/SL/WH.pm
+++ b/SL/WH.pm
@@ -170,11 +170,11 @@ sub transfer_assembly {
   my $sthTransferPartSQL   = prepare_query($form, $dbh, $transferPartSQL);
 
   # der return-string für die fehlermeldung inkl. welche waren zum fertigen noch fehlen
-  my $kannNichtFertigen ="Für dieses Erzeugnis sind keine Einzelteile definiert.
-                          Dementsprechend kann auch nichts hergestellt werden";
 
+  my $kannNichtFertigen ="";  # Falls leer dann erfolgreich
+  my $schleife_durchlaufen=0; # Falls die Schleife nicht ausgeführt wird -> Keine Einzelteile definiert. Bessere Idee? jan
   while (my $hash_ref = $sth_part_qty_assembly->fetchrow_hashref()) { #Schleife für select parts_id,(...) from assembly
-    $kannNichtFertigen ="";  # Wieder auf erfolgreich setzen LEER == keine Fehlermeldung
+    $schleife_durchlaufen=1;  # Erzeugnis definiert
     my $partsQTY = $hash_ref->{qty} * $params{qty}; # benötigte teile * anzahl erzeugnisse
     my $currentPart_ID = $hash_ref->{parts_id};
 
@@ -236,6 +236,14 @@ sub transfer_assembly {
       }
     }  # ende while SELECT SUM(qty), bin_id, chargenumber, bestbefore   FROM inventory  WHERE warehouse_id
   } #ende while select parts_id,qty from assembly where id = ?
+
+  if ($schleife_durchlaufen==0){  # falls die schleife nicht durchlaufen wurde, wurden auch
+                                  # keine einzelteile definiert
+      $kannNichtFertigen ="Für dieses Erzeugnis sind keine Einzelteile definiert.
+                           Dementsprechend kann auch nichts hergestellt werden";
+ }
+  # gibt die Fehlermeldung zurück. A.) Keine Teile definiert
+  #                                B.) Artikel und Anzahl der fehlenden Teile/Dienstleistungen
   if ($kannNichtFertigen) {
     return $kannNichtFertigen;
   }
index 0278aa5..ac7747e 100644 (file)
@@ -486,3 +486,112 @@ sub project_selected {
 
 sub continue       { call_sub($main::form->{"nextsub"}); }
 
+
+1;
+
+__END__
+
+=head1 NAME
+
+bin/mozilla/arap.pl - helper routines for invoiceing frontend.
+
+=head1 SYNOPSIS
+
+nothing yet
+
+=head1 DESCRIPTION
+
+nothing yet
+
+=head1 FUNCTIONS
+
+=head2 check_name customer|vendor
+
+check_name was originally meant to update the selected customer or vendor. The
+way it does that has generted more hate than almost any other part of this
+software.
+
+What it does is:
+
+=over 4
+
+=item
+
+It checks if a vendor or customer is given. No failsafe, vendor fallback if
+$_[0] is something fancy.
+
+=item
+
+It assumes, that there is a field named customer or vendor in $form.
+
+=item
+
+It assumes, that this field is filled with name--id, and tries to split that.
+sql ledger uses that combination to get ids into the select keys.
+
+=item
+
+It looks for a field selectcustomer or selectvendor in $form. sql ledger used
+to store a copy of the html select in there. (again, don't ask)
+
+=item
+
+If this field exists, it looks for a field called oldcustomer or oldvendor, in
+which the old name--id string was stored in sql ledger, and compares those.
+
+=item
+
+if they don't match, it will set customer_id or vendor_id in $form, load the
+entry (which will clobber everything in $form named like a column in customer
+oder vendor) and return.
+
+=item
+
+If there was no select* entry, it assumes that vclimit was lower than the
+number of entries, and that an input field was generated. In that case the
+splitting is omitted (since users don't generally include ids in entered names)
+
+=item
+
+It looks for a *_id field, and combines it with the given input into a name--id
+entry and compares it to the old* entry. (Missing any of these will instantly
+break check_namea.
+
+=item
+
+If those do not match, $form->get_name is called to get matching results.
+get_name only matches by *number and name, not by id, don't try to get it to do
+so.
+
+=item
+
+The results are stored in $form>{name_list} but a count is returned, and
+checked.
+
+=item
+
+If only one result was found, *_id, * and old* are copied into $form, the entry
+is loaded (like above, clobbering)
+
+=item
+
+If there is more than one, a selection dialog is rendered
+
+=item
+
+If none is found, an error is generated.
+
+=back
+
+=head3 I built a customer/vendor box somewhere and it doesn't work, what's wrong?
+
+Make sure a select* field is given if and only if you render a select box. The
+actual contents are ignored, but recognition fails if not present.
+
+Make sure old* and *_id fields are set correctly (name--id form for old*). They
+are necessary in all steps and branches.
+
+Since get_customer and get_vendor clobber a lot of fields, make sure what
+changes exactly.
+
+=cut
index e4185ab..8aeabdc 100644 (file)
@@ -543,9 +543,9 @@ sub list_transactions {
     'description' => { 'text' => $locale->text('Description'), },
     'debit'       => { 'text' => $locale->text('Debit'), },
     'credit'      => { 'text' => $locale->text('Credit'), },
-    'gegenkonto'     => { 'text' => $locale->text('Gegenkonto'), },
-    'ustkonto'     => { 'text' => $locale->text('USt-Konto'), },
-    'balance'          => { 'text' => $locale->text('Balance'), },
+    'gegenkonto'  => { 'text' => $locale->text('Gegenkonto'), },
+    'ustkonto'    => { 'text' => $locale->text('USt-Konto'), },
+    'balance'     => { 'text' => $locale->text('Balance'), },
     'ustrate'     => { 'text' => $locale->text('Satz %'), },
  );
 
index 5666d63..46b7c28 100644 (file)
@@ -1184,7 +1184,9 @@ sub print_options {
     (!$options{no_html}) ?
       opthash("html", $form->{DF}{html}, "HTML") : undef,
     ($main::opendocument_templates && !$options{no_opendocument}) ?
-      opthash("opendocument",        $form->{DF}{opendocument},        $locale->text("OpenDocument/OASIS")) : undef;
+      opthash("opendocument",        $form->{DF}{opendocument},        $locale->text("OpenDocument/OASIS")) : undef,
+    ($main::excel_templates && !$options{no_excel}) ?
+      opthash("excel",               $form->{DF}{excel},               $locale->text("Excel")) : undef;
 
   push @LANGUAGE_ID,
     map { opthash($_->{id}, ($_->{id} eq $form->{language_id} ? 'selected' : ''), $_->{description}) } +{}, @{ $form->{languages} }
@@ -1592,6 +1594,9 @@ sub print_form {
   } elsif ($form->{"format"} =~ /opendocument/) {
     $form->{opendocument} = 1;
     $extension            = 'odt';
+  } elsif ($form->{"format"} =~ /excel/) {
+    $form->{excel} = 1;
+    $extension            = 'xls';
   }
 
   my $email_extension = '_email' if (($form->{media} eq 'email') && (-f "$myconfig{templates}/$form->{formname}_email$form->{language}${printer_code}.${extension}"));
index f618c5b..663a20e 100644 (file)
@@ -1660,8 +1660,8 @@ sub aging {
     'invnumber' => { 'text' => $locale->text('Invoice'), },
     'transdate' => { 'text' => $locale->text('Date'), },
     'duedate'   => { 'text' => $locale->text('Due'), },
-    'amount'        => { 'text' => $locale->text('Amount'), },
-    'open'       => { 'text' => $locale->text('Open'), },
+    'amount'    => { 'text' => $locale->text('Amount'), },
+    'open'      => { 'text' => $locale->text('Open'), },
   );
 
   my %column_alignment = ('statement' => 'center',
index 91bfc83..300d1a7 100644 (file)
@@ -42,6 +42,7 @@ $ENV{PERL5LIB} .= ":/sw/lib/perl5";
 $webdav = 0;
 $lizenzen = 1;
 $vertreter = 0;
+$excel_templates = 0; # Minimalunterstützung für Excel-Druckvorlagen
 
 # Zeige Felder für Mindesthaltbarkeitsdatum
 $show_best_before = 0;
index 8b25926..c2fcdda 100644 (file)
@@ -2,6 +2,23 @@
 # Veränderungen von Lx-Office ERP #
 ###################################
 
+
+
+
+
+
+  Kleinere neue Features und Detailverbesserungen:
+
+  - Druckvorlage optional auf Excel erweitert, um Variablen die sich nicht in foreach-Schleifen
+    befinden anzuzeigen (s.a.: doc/excel_templates.txt).
+
+
+  Liste gefixter Bugs aus dem Bugtracker:
+
+   - Bug 1409 -  Bei "Erzeugnis fertigen" wird nur der Bestand der letzten Komponente geprüft
+
+
+
 2010-03-24 - Release 2.6.1
 
   Größere neue Features:
diff --git a/doc/excel_templates.txt b/doc/excel_templates.txt
new file mode 100644 (file)
index 0000000..f081862
--- /dev/null
@@ -0,0 +1,79 @@
+Table of Contents
+-----------------
+
+Inhalt der Anleitung
+1 Zusammenfassung
+2 Bedienung
+3 Exceltemplate Syntax
+4 Einschränkungen
+
+
+
+Zusammenfassung
+---------------
+
+Dieses Dokument beschreibt den Mechanismus, mit dem Exceltemplates abgearbeitet
+werden, und die Einschränkungen die damit einhergehen.
+
+
+
+Bedienung
+---------
+
+Der Excel Mechanismus muss in der Konfigurationsdatei aktiviert werden. Die
+Konfigurationsoption heißt:
+
+  $excel_templates = 1;
+
+Eine Excelvorlage kann dann unter dem Namen einer beliebigen anderen Vorlage mit
+der Endung .xls gespeichert werden. In den normalen Verkaufsmasken taucht nun
+"Excel" als auswählbares Format auf, und kann von da an bnutzt weren wie Latex
+oder OpenOffice Vorlagen.
+
+Der Sonderfall der Angebote aus der Kundenmaske ist ebenfalls eine
+Angebotsvorlage, und wird unter dem internen Namen der Angebote
+"sales_quotation.xls" gespeichert.
+
+
+
+Exceltemplate Syntax
+--------------------
+
+Einfache Syntax:  <<varname>>
+
+Wobei "<<" und ">>" die Delimiter sind. Da Excel auf festen Breiten besteht,
+kann der Tag künstlich verlängert werden, indem weitere "<" oder ">" gegefügt
+werden. Der Tag muss nicht symmetrisch sein.
+
+Beispiel: <<<<<varname>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+Um die Limitierung der festen Breite zu reduzieren, können weitere Variablen in
+einem Block interpoliert werden. Whitespace wird dazwishen dann erhalten.
+
+Beispiel: <<<<<varname1 varname2   varname3>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+Die Variablen werden interpoliert, und linksbündig mit Leerzeichen auf die
+gewünschte Länge aufgefüllt. Ist der String zu lang, werden überzählige Zeichen
+abgeschnitten.
+
+Es ist ausserdem möglich Daten rechtsbündig darzustellen, wenn der Block mit
+einem Leerzeichen anfängt.
+
+Beispiel:  <<<<<<            varname>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+würde rechtsbündig triggern. Wenn bei rechtsbündiger Ausrichtung Text
+abgeschnitten werden muss, wird er vom linken Ende entfernt.
+
+
+
+Einschränkungen
+---------------
+
+Das Excelformat bis 2002 ist ein binäres Format, und kann nicht mit vertretbarem
+Aufwand editiert werden. Der Templatemechanismus beschränkt sich daher darauf,
+Textstellen _exakt_ durch einen anderen Text zu ersetzen.
+
+Aus dem gleichen Grund sind die Templatekonstrukte <% if %> und <% foreach %>
+nicht vorhanden. Der Delimiter <% %> kommt in den Headerinformationen evtl vor,
+deshalb wurde auf den sichereren "<<"/">>" gewechselt.
+
index 3a8060a..68a557f 100644 (file)
@@ -19,6 +19,7 @@ $self->{texts} = {
   '&lt;%netto_date%&gt; -- Date the payment is due in full' => '&lt;%netto_date%&gt; -- Das Datum, bis die Rechnung in voller H&ouml;he bezahlt werden muss',
   '&lt;%skonto_amount%&gt; -- The deductible amount' => '&lt;%skonto_amount%&gt; -- Der abziehbare Skontobetrag',
   '&lt;%skonto_date%&gt; -- Date the payment is due with discount' => '&lt;%skonto_date%&gt; -- Das Datum, bis die Rechnung unter Abzug von Skonto bezahlt werden kann',
+  '&lt;%skonto_in_percent%&gt; -- The discount in percent' => '&lt;%skonto_in_percent%&gt; -- Der prozentuale Rabatt',
   '&lt;%terms_netto%&gt; -- The number of days for full payment' => '&lt;%terms_netto%&gt; -- Die Anzahl Tage, bis die Rechnung in voller H&ouml;he bezahlt werden muss',
   '&lt;%total%&gt; -- Amount payable' => '&lt;%total%&gt; -- Noch zu bezahlender Betrag',
   '&lt;%total_wo_skonto%&gt; -- Amount payable less discount' => '&lt;%total_wo_skonto%&gt; -- Noch zu bezahlender Betrag abz&uuml;glich Skonto',
@@ -686,6 +687,7 @@ $self->{texts} = {
   'Ertrag prozentual'           => 'Ertrag prozentual',
   'Escape character'            => 'Escape-Zeichen',
   'Exact'                       => 'Genau',
+  'Excel'                       => 'Excel',
   'Exch'                        => 'Wechselkurs.',
   'Exchangerate'                => 'Wechselkurs',
   'Exchangerate Difference'     => 'Wechselkursunterschied',
@@ -996,6 +998,7 @@ $self->{texts} = {
   'Missing amount'              => 'Fehlbetrag',
   'Missing parameter #1 in call to sub #2.' => 'Fehlernder Parameter \'#1\' in Funktionsaufruf \'#2\'.',
   'Missing parameter (at least one of #1) in call to sub #2.' => 'Fehlernder Parameter (mindestens einer aus \'#1\') in Funktionsaufruf \'#2\'.',
+  'Missing taxkeys in invoices with taxes.' => 'Fehlende Steuerschl&uuml;ssel in Rechnungen mit Steuern',
   'Mitarbeiter'                 => 'Mitarbeiter',
   'Mobile1'                     => 'Mobile 1',
   'Mobile2'                     => 'Mobile 2',
index c4e043a..5883e35 100644 (file)
@@ -10,7 +10,7 @@ $self->{texts} = {
   '&lt;%netto_date%&gt; -- Date the payment is due in full' => '&lt;%netto_date%&gt; -- Das Datum, bis die Rechnung in voller H&ouml;he bezahlt werden muss',
   '&lt;%skonto_amount%&gt; -- The deductible amount' => '&lt;%skonto_amount%&gt; -- Der abziehbare Skontobetrag',
   '&lt;%skonto_date%&gt; -- Date the payment is due with discount' => '&lt;%skonto_date%&gt; -- Das Datum, bis die Rechnung unter Abzug von Skonto bezahlt werden kann',
-  '&lt;%skonto_in_percent%&gt; -- The discount in percent' => '&lt;%skonto_in_percent%&gt; -- Skonto in Prozent',
+  '&lt;%skonto_in_percent%&gt; -- The discount in percent' => '&lt;%skonto_in_percent%&gt; -- Der prozentuale Rabatt',
   '&lt;%terms_netto%&gt; -- The number of days for full payment' => '&lt;%terms_netto%&gt; -- Die Anzahl Tage, bis die Rechnung in voller H&ouml;he bezahlt werden muss',
   '&lt;%total%&gt; -- Amount payable' => '&lt;%total%&gt; -- Noch zu bezahlender Betrag',
   '&lt;%total_wo_skonto%&gt; -- Amount payable less discount' => '&lt;%total_wo_skonto%&gt; -- Noch zu bezahlender Betrag abz&uuml;glich Skonto',
index a2bd8a7..ea01b63 100644 (file)
@@ -107,6 +107,7 @@ $self->{texts} = {
   'Enter longdescription'       => 'Langtext eingeben',
   'Error in database control file \'%s\': %s' => 'Fehler in Datenbankupgradekontrolldatei \'%s\': %s',
   'Ertrag'                      => 'Ertrag',
+  'Excel'                       => 'Excel',
   'Extended'                    => 'Gesamt',
   'Falsches Datumsformat!'      => 'Falsches Datumsformat!',
   'Fax'                         => 'Fax',
index 6e891b1..d2f4471 100644 (file)
@@ -115,6 +115,7 @@ $self->{texts} = {
   'Error in position #1: You must either assign no transfer at all or the full quantity of #2 #3.' => 'Fehler in Position #1: Sie m&uuml;ssen einer Position entweder gar keinen Lagerausgang oder die vollst&auml;ndige im Lieferschein vermerkte Menge von #2 #3 zuweisen.',
   'Error in row #1: The quantity you entered is bigger than the stocked quantity.' => 'Fehler in Zeile #1: Die angegebene Menge ist gr&ouml;&szlig;er als die vorhandene Menge.',
   'Ertrag'                      => 'Ertrag',
+  'Excel'                       => 'Excel',
   'Extended'                    => 'Gesamt',
   'Fax'                         => 'Fax',
   'Feb'                         => 'Feb',
index 5dd9f51..97b3c81 100644 (file)
@@ -112,6 +112,7 @@ $self->{texts} = {
   'Enter longdescription'       => 'Langtext eingeben',
   'Error in database control file \'%s\': %s' => 'Fehler in Datenbankupgradekontrolldatei \'%s\': %s',
   'Ertrag'                      => 'Ertrag',
+  'Excel'                       => 'Excel',
   'Extended'                    => 'Gesamt',
   'Fax'                         => 'Fax',
   'Feb'                         => 'Feb',
index 775cb77..ebfdc15 100644 (file)
@@ -90,6 +90,7 @@ $self->{texts} = {
   'Enter longdescription'       => 'Langtext eingeben',
   'Error in database control file \'%s\': %s' => 'Fehler in Datenbankupgradekontrolldatei \'%s\': %s',
   'Ertrag'                      => 'Ertrag',
+  'Excel'                       => 'Excel',
   'Extended'                    => 'Gesamt',
   'Fax'                         => 'Fax',
   'Feb'                         => 'Feb',
index 3fa4ab2..f6614b3 100644 (file)
@@ -105,6 +105,7 @@ $self->{texts} = {
   'Enter longdescription'       => 'Langtext eingeben',
   'Error in database control file \'%s\': %s' => 'Fehler in Datenbankupgradekontrolldatei \'%s\': %s',
   'Ertrag'                      => 'Ertrag',
+  'Excel'                       => 'Excel',
   'Exchangerate for payment missing!' => 'Es fehlt der Wechselkurs für die Bezahlung!',
   'Exchangerate missing!'       => 'Es fehlt der Wechselkurs!',
   'Extended'                    => 'Gesamt',
index 164f431..9b7ee61 100644 (file)
@@ -111,6 +111,7 @@ $self->{texts} = {
   'Enter longdescription'       => 'Langtext eingeben',
   'Error in database control file \'%s\': %s' => 'Fehler in Datenbankupgradekontrolldatei \'%s\': %s',
   'Ertrag'                      => 'Ertrag',
+  'Excel'                       => 'Excel',
   'Exchangerate for payment missing!' => 'Es fehlt der Wechselkurs für die Bezahlung!',
   'Exchangerate missing!'       => 'Es fehlt der Wechselkurs!',
   'Extended'                    => 'Gesamt',
index 57bf8c1..701cace 100755 (executable)
@@ -570,11 +570,11 @@ sub scanhtmlfile {
                         [\-~#]*         # Whitespace-Unterdrückung
                         \%\]            # Template-Ende-Tag
                        /ix) {
-#        print "Found filter >>>$1<<<\n";
+#        print "Found filter '$1' in string '$line'\n";
         $cached{$_[0]}{all}{$1}  = 1;
         $cached{$_[0]}{html}{$1} = 1;
         $plugins{needed}->{T8}   = 1;
-        substr $line, $-[1], $+[0] - $-[0], '';
+        substr $line, $-[0], $+[0] - $-[0], '';
       }
 
       while ("" ne $line) {
index 0e9b682..fa52176 100644 (file)
@@ -149,6 +149,7 @@ $self->{texts} = {
   'Error in row #1: The quantity you entered is bigger than the stocked quantity.' => 'Fehler in Zeile #1: Die angegebene Menge ist gr&ouml;&szlig;er als die vorhandene Menge.',
   'Ertrag'                      => 'Ertrag',
   'Ertrag prozentual'           => 'Ertrag prozentual',
+  'Excel'                       => 'Excel',
   'Exchangerate'                => 'Wechselkurs',
   'Exchangerate missing!'       => 'Es fehlt der Wechselkurs!',
   'Extended'                    => 'Gesamt',
index 99a891a..46e5e18 100644 (file)
@@ -138,6 +138,7 @@ $self->{texts} = {
   'Error in row #1: The quantity you entered is bigger than the stocked quantity.' => 'Fehler in Zeile #1: Die angegebene Menge ist gr&ouml;&szlig;er als die vorhandene Menge.',
   'Ertrag'                      => 'Ertrag',
   'Ertrag prozentual'           => 'Ertrag prozentual',
+  'Excel'                       => 'Excel',
   'Exchangerate'                => 'Wechselkurs',
   'Exchangerate missing!'       => 'Es fehlt der Wechselkurs!',
   'Extended'                    => 'Gesamt',
index f9e7ef5..2072ad4 100644 (file)
@@ -148,6 +148,7 @@ $self->{texts} = {
   'Error in row #1: The quantity you entered is bigger than the stocked quantity.' => 'Fehler in Zeile #1: Die angegebene Menge ist gr&ouml;&szlig;er als die vorhandene Menge.',
   'Ertrag'                      => 'Ertrag',
   'Ertrag prozentual'           => 'Ertrag prozentual',
+  'Excel'                       => 'Excel',
   'Exchangerate'                => 'Wechselkurs',
   'Exchangerate missing!'       => 'Es fehlt der Wechselkurs!',
   'Extended'                    => 'Gesamt',
index 8a6876c..99eb3db 100644 (file)
        [%- END %]
       [%- END %]
 
+     [%- ELSIF problem.type == 'missing_taxkeys_in_invoices' %]
+      [%- IF problem.ar_problems.size %]
+       Verkaufsrechnungen
+       [%- FOREACH subproblem = problem.ar_problems %]
+        [%- UNLESS loop.first %], [%- END %]
+        <a href="[% subproblem.link %]">[% HTML.escape(subproblem.data.reference) %]</a>
+       [%- END %]
+      [%- END %]
+
+      [%- IF problem.ap_problems.size %]
+       [%- IF problem.ar_problems.size %]; [%- END %]
+       Einkaufsrechnungen
+       [%- FOREACH subproblem = problem.ap_problems %]
+        [%- UNLESS loop.first %], [%- END %]
+        <a href="[% subproblem.link %]">[% HTML.escape(subproblem.data.reference) %]</a>
+       [%- END %]
+      [%- END %]
+
      [%- ELSE %]
 
      <a href="[% problem.link %]">
      [%- ELSIF problem.type == 'invoice_inventory_with_taxkeys' %]
      Einkaufs- und Verkaufsrechnungen mit Warenbestandsbuchungen mit Steuerschlüsseln
 
+     [%- ELSIF problem.type == 'missing_taxkeys_in_invoices' %]
+     Fehlende Steuerschl&uuml;ssel in Rechnungen mit Steuern
+
      [%- END %]
     </td>
 
index bb574ca..408bc04 100644 (file)
        [%- END %]
       [%- END %]
 
+     [%- ELSIF problem.type == 'missing_taxkeys_in_invoices' %]
+      [%- IF problem.ar_problems.size %]
+       <translate>Sales invoices</translate>
+       [%- FOREACH subproblem = problem.ar_problems %]
+        [%- UNLESS loop.first %], [%- END %]
+        <a href="[% subproblem.link %]">[% HTML.escape(subproblem.data.reference) %]</a>
+       [%- END %]
+      [%- END %]
+
+      [%- IF problem.ap_problems.size %]
+       [%- IF problem.ar_problems.size %]; [%- END %]
+       <translate>Purchase invoices</translate>
+       [%- FOREACH subproblem = problem.ap_problems %]
+        [%- UNLESS loop.first %], [%- END %]
+        <a href="[% subproblem.link %]">[% HTML.escape(subproblem.data.reference) %]</a>
+       [%- END %]
+      [%- END %]
+
      [%- ELSE %]
 
      <a href="[% problem.link %]">
      [%- ELSIF problem.type == 'invoice_inventory_with_taxkeys' %]
      <translate>Sales and purchase invoices with inventory transactions with taxkeys</translate>
 
+     [%- ELSIF problem.type == 'missing_taxkeys_in_invoices' %]
+     <translate>Missing taxkeys in invoices with taxes.</translate>
+
      [%- END %]
     </td>
 
index a528305..611f76e 100644 (file)
   <!--
     function enable_fix_button_maybe() {
       var all_set = true;
-      $("[@name='fixes[].taxkey']").each(function () {
+      $("[name='fixes[].taxkey']").each(function () {
         var val = $(this).attr('value');
         if (val == '')
           all_set = false;
index 00742d6..44fb603 100644 (file)
   <!--
     function enable_fix_button_maybe() {
       var all_set = true;
-      $("[@name='fixes[].taxkey']").each(function () {
+      $("[name='fixes[].taxkey']").each(function () {
         var val = $(this).attr('value');
         if (val == '')
           all_set = false;