Dazu werden einige neue Perl-Module (Text::CSV_XS und IO::Wrap) sowie zwei weitere Hilfsprogramme (html2ps und Ghostscript) benötigt, deren Pfade über die lx-erp.conf eingestellt werden müssen.
{ "name" => "Text::Iconv", "url" => "http://search.cpan.org/~mpiotr/" },
{ "name" => "Time::HiRes", "url" => "http://search.cpan.org/~jhi/" },
{ "name" => "YAML", "url" => "http://search.cpan.org/~ingy/" },
+ { "name" => "IO::Wrap", "url" => "http://search.cpan.org/~dskoll/IO-stringy-2.110/" },
+ { "name" => "Text::CSV_XS", "url" => "http://search.cpan.org/~hmbrand/Text-CSV_XS-0.29/" },
);
sub module_available {
--- /dev/null
+package SL::ReportGenerator;
+
+use IO::Wrap;
+use Text::CSV_XS;
+
+use SL::Form;
+
+sub new {
+ my $type = shift;
+
+ my $self = { };
+
+ $self->{myconfig} = shift;
+ $self->{form} = shift;
+
+ $self->{data} = [];
+ $self->{options} = {
+ 'std_column_visibility' => 0,
+ 'output_format' => 'HTML',
+ 'allow_pdf_export' => 1,
+ 'allow_csv_export' => 1,
+ 'pdf_export' => {
+ 'paper_size' => 'A4',
+ 'orientation' => 'landscape',
+ 'font_size' => '10',
+ 'margin_top' => 1.5,
+ 'margin_left' => 1.5,
+ 'margin_bottom' => 1.5,
+ 'margin_right' => 1.5,
+ 'number' => 1,
+ },
+ 'csv_export' => {
+ 'quote_char' => '"',
+ 'sep_char' => ';',
+ 'escape_char' => '"',
+ 'eol_style' => 'DOS',
+ 'headers' => 1,
+ },
+ };
+ $self->{export} = {
+ 'nextsub' => '',
+ 'variable_list' => '',
+ };
+
+ $self->set_options(@_) if (@_);
+
+ return bless $self, $type;
+}
+
+sub set_columns {
+ my $self = shift;
+ my %columns = @_;
+
+ $self->{columns} = \%columns;
+
+ foreach my $column (values %{ $self->{columns} }) {
+ $column->{visible} = $self->{options}->{std_column_visibility} unless defined $column->{visible};
+ }
+
+ $self->set_column_order(sort keys %{ $self->{columns} });
+}
+
+sub set_column_order {
+ my $self = shift;
+
+ my $order = 0;
+ my %columns = map { $order++; ($_, $order) } @_;
+
+ foreach my $column (sort keys %{ $self->{columns} }) {
+ next if $columns{$column};
+
+ $order++;
+ $columns{$column} = $order;
+ }
+
+ $self->{column_order} = [ sort { $columns{$a} <=> $columns{$b} } keys %columns ];
+}
+
+sub set_sort_indicator {
+ my $self = shift;
+
+ $self->{options}->{sort_indicator_column} = shift;
+ $self->{options}->{sort_indicator_direction} = shift;
+}
+
+sub add_data {
+ my $self = shift;
+
+ while (my $arg = shift) {
+ if ('ARRAY' eq ref $arg) {
+ push @{ $self->{data} }, $arg;
+
+ } elsif ('HASH' eq ref $arg) {
+ push @{ $self->{data} }, [ $arg ];
+
+ } else {
+ $self->{form}->error('Incorrect usage -- expecting hash or array ref');
+ }
+ }
+}
+
+sub clear_data {
+ my $self = shift;
+
+ $self->{data} = [];
+}
+
+sub set_options {
+ my $self = shift;
+ my %options = @_;
+
+ map { $self->{options}->{$_} = $options{$_} } keys %options;
+}
+
+sub set_options_from_form {
+ my $self = shift;
+
+ my $form = $self->{form};
+ my $myconfig = $self->{myconfig};
+
+ foreach my $key (qw(output_format)) {
+ my $full_key = "report_generator_${key}";
+ $self->{options}->{$key} = $form->{$full_key} if (defined $form->{$full_key});
+ }
+
+ foreach my $format (qw(pdf csv)) {
+ my $opts = $self->{options}->{"${format}_export"};
+ foreach my $key (keys %{ $opts }) {
+ my $full_key = "report_generator_${format}_options_${key}";
+ $opts->{$key} = $key =~ /^margin/ ? $form->parse_amount($myconfig, $form->{$full_key}) : $form->{$full_key};
+ }
+ }
+}
+
+sub set_export_options {
+ my $self = shift;
+
+ $self->{export} = {
+ 'nextsub' => shift,
+ 'variable_list' => join(" ", @_),
+ };
+}
+
+sub generate_content {
+ my $self = shift;
+ my $format = lc $self->{options}->{output_format};
+
+ if (!$self->{columns}) {
+ $self->{form}->error('Incorrect usage -- no columns specified');
+ }
+
+ if ($format eq 'html') {
+ return $self->generate_html_content();
+
+ } elsif ($format eq 'csv') {
+ return $self->generate_csv_content();
+
+ } elsif ($format eq 'pdf') {
+ return $self->generate_pdf_content();
+
+ } else {
+ $self->{form}->error('Incorrect usage -- unknown format (supported are HTML, CSV, PDF)');
+ }
+}
+
+sub generate_with_headers {
+ my $self = shift;
+ my $format = lc $self->{options}->{output_format};
+
+ if (!$self->{columns}) {
+ $self->{form}->error('Incorrect usage -- no columns specified');
+ }
+
+ my $filename = $self->{options}->{attachment_basename} || 'report';
+ $filename =~ s|.*\\||;
+ $filename =~ s|.*/||;
+
+ if ($format eq 'html') {
+ $self->{form}->{title} = $self->{title};
+ $self->{form}->header();
+ print $self->generate_html_content();
+
+ } elsif ($format eq 'csv') {
+ print qq|content-type: text/plain\n\n|;
+# print qq|content-disposition: attachment; filename=${filename}.csv\n\n|;
+ $self->generate_csv_content();
+
+ } elsif ($format eq 'pdf') {
+ print qq|content-type: application/pdf\n|;
+ print qq|content-disposition: attachment; filename=${filename}.pdf\n\n|;
+ $self->generate_pdf_content();
+
+ } else {
+ $self->{form}->error('Incorrect usage -- unknown format (supported are HTML, CSV, PDF)');
+ }
+}
+
+sub get_visible_columns {
+ my $self = shift;
+ my $format = shift;
+
+ return grep { my $c = $self->{columns}->{$_}; $c && $c->{visible} && (($c->{visible} == 1) || ($c->{visible} =~ /${format}/i)) } @{ $self->{column_order} };
+}
+
+sub prepare_html_content {
+ my $self = shift;
+
+ my ($column, $name, @column_headers);
+
+ my $opts = $self->{options};
+ my @visible_columns = $self->get_visible_columns('HTML');
+
+ foreach $name (@visible_columns) {
+ $column = $self->{columns}->{$name};
+
+ my $header = {
+ 'name' => $name,
+ 'link' => $column->{link},
+ 'text' => $column->{text},
+ 'show_sort_indicator' => $name eq $opts->{sort_indicator_column},
+ 'sort_indicator_direction' => $opts->{sort_indicator_direction},
+ };
+
+ push @column_headers, $header;
+ }
+
+ my ($outer_idx, $inner_idx) = (0, 0);
+ my @rows;
+
+ foreach my $row_set (@{ $self->{data} }) {
+ $outer_idx++;
+
+ foreach my $row (@{ $row_set }) {
+ $inner_idx++;
+
+ my $row_data = {
+ 'COLUMNS' => [ map { $row->{$_} } @visible_columns ],
+ 'outer_idx' => $outer_idx,
+ 'outer_idx_odd' => $outer_idx % 2,
+ 'inner_idx' => $inner_idx,
+ };
+
+ push @rows, $row_data;
+ }
+ }
+
+ my @export_variables;
+ foreach my $key (split m/ +/, $self->{export}->{variable_list}) {
+ push @export_variables, { 'key' => $key, 'value' => $self->{form}->{$key} };
+ }
+
+ my $allow_pdf_export = $opts->{allow_pdf_export} && (-x $main::html2ps_bin) && (-x $main::ghostscript_bin);
+
+ my $variables = {
+ 'TITLE' => $opts->{title},
+ 'TOP_INFO_TEXT' => $opts->{top_info_text},
+ 'RAW_TOP_INFO_TEXT' => $opts->{raw_top_info_text},
+ 'BOTTOM_INFO_TEXT' => $opts->{bottom_info_text},
+ 'RAW_BOTTOM_INFO_TEXT' => $opts->{raw_bottom_info_text},
+ 'ALLOW_PDF_EXPORT' => $allow_pdf_export,
+ 'ALLOW_CSV_EXPORT' => $opts->{allow_csv_export},
+ 'SHOW_EXPORT_BUTTONS' => $allow_pdf_export || $opts->{allow_csv_export},
+ 'COLUMN_HEADERS' => \@column_headers,
+ 'NUM_COLUMNS' => scalar @column_headers,
+ 'ROWS' => \@rows,
+ 'EXPORT_VARIABLES' => \@export_variables,
+ 'EXPORT_VARIABLE_LIST' => $self->{export}->{variable_list},
+ 'EXPORT_NEXTSUB' => $self->{export}->{nextsub},
+ };
+
+ return $variables;
+}
+
+sub generate_html_content {
+ my $self = shift;
+ my $variables = $self->prepare_html_content();
+
+ return $self->{form}->parse_html_template('report_generator/html_report', $variables);
+}
+
+sub verify_paper_size {
+ my $self = shift;
+ my $requested_paper_size = lc shift;
+ my $default_paper_size = shift;
+
+ my %allowed_paper_sizes = map { $_ => 1 } qw(a3 a4 letter legal);
+
+ return $allowed_paper_sizes{$requested_paper_size} ? $requested_paper_size : $default_paper_size;
+}
+
+sub generate_pdf_content {
+ my $self = shift;
+ my $variables = $self->prepare_html_content();
+ my $form = $self->{form};
+ my $myconfig = $self->{myconfig};
+ my $opt = $self->{options}->{pdf_export};
+
+ my $opt_number = $opt->{number} ? 'number : 1' : '';
+ my $opt_landscape = $opt->{orientation} eq 'landscape' ? 'landscape : 1' : '';
+
+ my $opt_paper_size = $self->verify_paper_size($opt->{paper_size}, 'a4');
+
+ my $html2ps_config = <<"END"
+\@html2ps {
+ option {
+ titlepage: 0;
+ hyphenate: 0;
+ colour: 1;
+ ${opt_landscape};
+ ${opt_number};
+ }
+ paper {
+ type: ${opt_paper_size};
+ }
+ break-table: 1;
+}
+
+\@page {
+ margin-top: $opt->{margin_top}cm;
+ margin-left: $opt->{margin_left}cm;
+ margin-bottom: $opt->{margin_bottom}cm;
+ margin-right: $opt->{margin_right}cm;
+}
+
+BODY {
+ font-family: Helvetica;
+ font-size: $opt->{font_size}pt;
+}
+
+END
+ ;
+
+ my $cfg_file_name = Common::tmpname() . '-html2ps-config';
+ my $cfg_file = IO::File->new($cfg_file_name, 'w') || $form->error($locale->text('Could not write the html2ps config file.'));
+
+ $cfg_file->print($html2ps_config);
+ $cfg_file->close();
+
+ my $html_file_name = Common::tmpname() . '.html';
+ my $html_file = IO::File->new($html_file_name, 'w');
+
+ if (!$html_file) {
+ unlink $cfg_file_name;
+ $form->error($locale->text('Could not write the temporary HTML file.'));
+ }
+
+ $html_file->print($form->parse_html_template('report_generator/pdf_report', $variables));
+ $html_file->close();
+
+ my $gs = IO::File->new("\"${main::html2ps_bin}\" -f \"${cfg_file_name}\" \"${html_file_name}\" | " .
+ "\"${main::ghostscript_bin}\" -q -dSAFER -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sPAPERSIZE=${opt_paper_size} -sOutputFile=- -c .setpdfwrite - |");
+ if ($gs) {
+ while (my $line = <$gs>) {
+ print $line;
+ }
+ $gs->close();
+ unlink $cfg_file_name, $html_file_name;
+
+ } else {
+ unlink $cfg_file_name, $html_file_name;
+ $form->error($locale->text('Could not spawn html2ps or GhostScript.'));
+ }
+}
+
+sub generate_csv_content {
+ my $self = shift;
+
+ my %valid_sep_chars = (';' => ';', ',' => ',', ':' => ':', 'TAB' => "\t");
+ my %valid_escape_chars = ('"' => 1, "'" => 1);
+ my %valid_quote_chars = ('"' => 1, "'" => 1);
+
+ my $opts = $self->{options}->{csv_export};
+ my $eol = $opts->{eol_style} eq 'DOS' ? "\r\n" : "\n";
+ my $sep_char = $valid_sep_chars{$opts->{sep_char}} ? $valid_sep_chars{$opts->{sep_char}} : ';';
+ my $escape_char = $valid_escape_chars{$opts->{escape_char}} ? $opts->{escape_char} : '"';
+ my $quote_char = $valid_quote_chars{$opts->{quote_char}} ? $opts->{quote_char} : '"';
+
+ $escape_char = $quote_char if ($opts->{escape_char} eq 'QUOTE_CHAR');
+
+ my $csv = Text::CSV_XS->new({ 'binary' => 1,
+ 'sep_char' => $sep_char,
+ 'escape_char' => $escape_char,
+ 'quote_char' => $quote_char,
+ 'eol' => $eol, });
+
+ my $stdout = wraphandle(\*STDOUT);
+ my @visible_columns = $self->get_visible_columns('CSV');
+
+ if ($opts->{headers}) {
+ $csv->print($stdout, [ map { $self->{columns}->{$_}->{text} } @visible_columns ]);
+ }
+
+ foreach my $row_set (@{ $self->{data} }) {
+ foreach my $row (@{ $row_set }) {
+ $csv->print($stdout, [ map { $row->{$_}->{data} } @visible_columns ]);
+ }
+ }
+}
+
+1;
--- /dev/null
+#=====================================================================
+# LX-Office ERP
+# Copyright (C) 2004
+# Based on SQL-Ledger Version 2.1.9
+# Web http://www.lx-office.org
+######################################################################
+#
+# Stuff that can be used from other modules
+#
+######################################################################
+
+use SL::Form;
+use SL::Common;
+use SL::MoreCommon;
+use SL::ReportGenerator;
+
+sub export_as_pdf {
+ $lxdebug->enter_sub();
+
+ if ($form->{report_generator_pdf_options_set}) {
+ report_generator_do('PDF');
+ $lxdebug->leave_sub();
+ return;
+ }
+
+ my @form_values;
+ map { push @form_values, { 'key' => $_, 'value' => $form->{$_} } } keys %{ $form };
+
+ $form->{title} = $locale->text('PDF export -- options');
+ $form->header();
+ print $form->parse_html_template('report_generator/pdf_export_options',
+ { 'HIDDEN' => \@form_values,
+ 'default_margin' => $form->format_amount(\%myconfig, 1.5) });
+
+ $lxdebug->leave_sub();
+}
+
+sub export_as_csv {
+ $lxdebug->enter_sub();
+
+ if ($form->{report_generator_csv_options_set}) {
+ report_generator_do('CSV');
+ $lxdebug->leave_sub();
+ return;
+ }
+
+ my @form_values;
+ map { push @form_values, { 'key' => $_, 'value' => $form->{$_} } } keys %{ $form };
+
+ $form->{title} = $locale->text('CSV export -- options');
+ $form->header();
+ print $form->parse_html_template('report_generator/csv_export_options', { 'HIDDEN' => \@form_values });
+
+ $lxdebug->leave_sub();
+}
+
+sub report_generator_do {
+ $lxdebug->enter_sub();
+
+ my $format = shift;
+
+ my $nextsub = $form->{report_generator_nextsub};
+ if (!$nextsub) {
+ $form->error($locale->text('report_generator_nextsub is not defined.'));
+ }
+
+ foreach my $key (split m/ +/, $form->{report_generator_variable_list}) {
+ $form->{$key} = $form->{"report_generator_hidden_${key}"};
+ }
+
+ $form->{report_generator_output_format} = $format;
+
+ delete @{$form}{map { "report_generator_$_" } qw(nextsub variable_list)};
+
+ call_sub($nextsub);
+
+ $lxdebug->leave_sub();
+}
+
+1;
* Class::Accessor
* Archive::Zip
* Text::Iconv
+* Text::CSV_XS
+* IO::Wrap (aus dem Paket IO::Stringy)
* YAML
Diese Pakete können bei den unterschiedlichen Distributionen anders heißen.
-(Debian: apache, postgresql, libdbi-perl, libdbd-pg-perl, libpgperl, libhtml-template-perl, libclass-accessor-perl, libarchive-zip-perl, libtext-iconv-perl, libyaml-perl)
-(Fedora: httpd, postgresql-server, perl-DBI, perl-DBD-Pg)
-(SuSE: apache2, postgresql-server, perl-DBI, perl-DBD-Pg)
+(Debian: apache, postgresql, libdbi-perl, libdbd-pg-perl, libpgperl, libhtml-template-perl, libclass-accessor-perl, libarchive-zip-perl, libtext-iconv-perl, libyaml-perl, libtext-csv-perl, libio-stringy-perl)
+(Fedora: httpd, postgresql-server, perl-DBI, perl-DBD-Pg)
+(SuSE: apache2, postgresql-server, perl-DBI, perl-DBD-Pg, perl-Archive-Zip, perl-Class-Accessor, perl-Text-Iconv, perl-Text-CSV_XS, perl-HTML-Template, perl-IO-stringy)
Da Perl-CGI-Ajax nicht als Paket für Distributionen bereit steht, muß es mit der CPAN-Shell installiert werden.
-Leider ist dazu nicht jeder in der Lage. LxO liefert daher das Paket im CGI-Verzeichnis mit. Das sollte als Fall-Back greifen.
+Leider gibt es Fälle, in denen das nicht möglich oder praktikabel ist. LxO liefert daher das Paket im CGI-Verzeichnis mit. Das sollte als Fall-Back greifen.
Die PostgreSQL Konfiguration muß angepasst werden.
** BITTE FERTIGEN SIE VOR DEM UPGRADE EIN BACKUP IHRER DATENBANK(EN) AN! **
-Upgrade von v2.4.0 auf 2.4.1 sowie von 2.4.1 auf 2.4.2
-======================================================
+Upgrade von v2.4.0 und neuer auf v2.6.0
+=======================================
-Ein Upgrade von v2.4.0 auf v2.4.1 oder von v2.4.1 auf v2.4.2 besteht
-aus zwei Teilen: den Dateien (einfaches Entpacken und Kopieren in das
+Ein Upgrade von v2.4.0 oder neuer auf v2.6.0 aus zwei Teilen: den
+Dateien (einfaches Entpacken und Kopieren in das
Installationsverzeichnis genügen) sowie dem Datenbankupgrade.
Bitte beachten Sie auch die Liste der benötigten Perl-Module am Anfang
der Datei "doc/INSTALL". Besonders nach einem Upgrade auf 2.4.2 muss
-sichergestellt werden, dass das Modul "YAML" installiert ist.
+sichergestellt werden, dass das Modul "YAML" installiert ist. v2.6.0
+benötigt zusätzlich die Module "Text::CSV_XS" und "IO::Wrap".
Das Datenbankupgrade wird automatisch gestartet, wenn sich der erste
Benutzer nach dem Upgrade der Dateien an Lx-Office anmeldet.
** BITTE FERTIGEN SIE VOR DEM UPGRADE EIN BACKUP IHRER DATENBANK(EN) AN! **
Anders als beim Upgrade auf 2.4.0 handelt es bei den Datenbankupgrades
-auf 2.4.1 und 2.4.2 nur um automatisch ablaufende Scripte, die keine
-Benutzereingaben erfordern.
+auf Versionen nach 2.4.0 nur um automatisch ablaufende Scripte, die
+keine Benutzereingaben erfordern.
Upgrade von v2.2.0 bis 2.2.2 auf 2.4.0
'Body:' => 'Text:',
'Books are open' => 'Die Bücher sind geöffnet.',
'Both' => 'Sowohl als auch',
+ 'Bottom' => 'Unten',
'Bought' => 'Gekauft',
'Buchungsdatum' => 'Buchungsdatum',
'Buchungsgruppe' => 'Buchungsgruppe',
'Business saved!' => 'Firma gespeichert.',
'C' => 'G',
'CANCELED' => 'Storniert',
+ 'CSV export -- options' => 'CSV-Export -- Optionen',
'Calculate' => 'Berechnen',
'Cancel Accounts Payables Transaction' => 'Kreditorenbuchung stornieren',
'Cancel Accounts Receivables Transaction' => 'Debitorenbuchung stornieren',
'Could not print dunning.' => 'Die Mahnungen konnten nicht gedruckt werden.',
'Could not rename %s to %s. Reason: %s' => 'Die Datei "%s" konnte nicht in "%s" umbenannt werden. Grund: %s',
'Could not spawn ghostscript.' => 'Die Anwendung "ghostscript" konnte nicht gestartet werden.',
+ 'Could not spawn html2ps or GhostScript.' => 'html2ps oder GhostScript konnte nicht gestartet werden.',
'Could not spawn the printer command.' => 'Die Druckanwendung konnte nicht gestartet werden.',
'Could not update prices!' => 'Preise konnten nicht aktualisiert werden!',
+ 'Could not write the html2ps config file.' => 'Die temporäre html2ps-Konfigurationsdatei konnte nicht geschrieben werden.',
+ 'Could not write the temporary HTML file.' => 'Eine temporäre HTML-Datei konnte nicht geschrieben werden.',
'Country' => 'Land',
'Create Buchungsgruppen' => 'Buchungsgruppe erfassen',
'Create Chart of Accounts' => 'Kontenplan anlegen',
'Error' => 'Fehler',
'Error in database control file \'%s\': %s' => 'Fehler in Datenbankupgradekontrolldatei \'%s\': %s',
'Error!' => 'Fehler!',
+ 'Escape character' => 'Escape-Zeichen',
'Exch' => 'Wechselkurs.',
'Exchangerate' => 'Wechselkurs',
'Exchangerate Difference' => 'Wechselkursunterschied',
'Expiring in x month(s)' => 'Die in x Monat(en) ablaufen',
'Export Buchungsdaten' => 'Export Buchungsdaten',
'Export Stammdaten' => 'Export Stammdaten',
+ 'Export as CSV' => 'Als CSV exportieren',
+ 'Export as PDF' => 'Als PDF exportieren',
'Extended' => 'Gesamt',
'Extension Of Time' => 'Dauerfristverlängerung',
'Factor' => 'Faktor',
'File locked!' => 'Datei gesperrt!',
'Files created by Lx-Office\'s "Backup Dataset" function are such files.' => 'Dateien, die von Lx-Office\' Funktion "Datenbank sichern" erstellt wurden, erfüllen diese Kriterien.',
'Folgekonto' => 'Folgekonto',
+ 'Font size' => 'Schriftgröße',
'For each unit there\'s either no or exactly one base unit. If you chose a base unit then you also have to chose a factor. That way the new unit will be defined as a multiple of the base unit. The base unit must be the "smaller" one. A factor may not be less than 1. Therefore you may define "kg" with the base unit "g" and a factor of "1", but not the other way round.' => 'Einheiten haben entweder keine oder genau eine Basiseinheit, von der sie ein Vielfaches sind. Wenn Sie eine Basiseinheit auswählen, dann müssen Sie auch einen Faktor eingeben. Sie müssen Einheiten als ein Vielfaches einer kleineren Einheit eingeben. So ist die Definition von "kg" mit der Basiseinheit "g" und dem Faktor 1000 zulässig, die Definition von "g" mit der Basiseinheit "kg" und dem Faktor "0,001" hingegen nicht.',
'Foreign Exchange Gain' => 'Wechselkurserträge',
'Foreign Exchange Loss' => 'Wechselkursaufwendungen',
'In-line' => 'im Text',
'Inactive' => 'Inaktiv',
'Include Exchangerate Difference' => 'Wechselkursunterschied einbeziehen',
+ 'Include column headings' => 'Spaltenüberschriften erzeugen',
'Include in Report' => 'In Bericht aufnehmen',
'Include in drop-down menus' => 'In Aufklappmenü aufnehmen',
'Income Statement' => 'GuV',
'Kundennummer' => 'Kundennummer',
'L' => 'L',
'LaTeX Templates' => 'LaTeX-Vorlagen',
+ 'Landscape' => 'Querformat',
'Language' => 'Sprache',
'Language Values' => 'Sprachübersetzungen',
'Language deleted!' => 'Sprache gelöscht!',
'Last Vendor Number' => 'Letzte Lieferantennummer',
'Lead' => 'Kundenquelle',
'Leave host and port field empty unless you want to make a remote connection.' => 'Für lokale Verbindungen "Rechner" und "Port" freilassen.',
+ 'Left' => 'Links',
'Liability' => 'Passiva/Mittelherkunft',
'License' => 'Lizenz',
'License key' => 'Lizenzschlüssel',
'Licenses' => 'Lizenzen',
'Lieferungen' => 'Lieferungen',
'Line Total' => 'Zeilensumme',
+ 'Line endings' => 'Zeilenumbrüche',
'List Accounting Groups' => 'Buchungsgruppen anzeigen',
'List Accounts' => 'Konten anzeigen',
'List Businesses' => 'Kunden-/Lieferantentypen anzeigen',
'List Pricegroups' => 'Preisgruppen anzeigen',
'List Printer' => 'Drucker anzeigen',
'List Transactions' => 'Buchungsliste',
+ 'List export' => 'Listenexport',
'Load draft' => 'Entwurf laden',
'Local Tax Office Preferences' => 'Angaben zum Finanzamt',
'Lock System' => 'System sperren',
'Mandantennummer' => 'Mandantennummer',
'Mar' => 'März',
'March' => 'März',
+ 'Margins' => 'Seitenränder',
'Mark as paid?' => 'Als bezahlt markieren?',
'Marked as paid' => 'Als bezahlt markiert',
'Marked entries printed!' => 'Markierte Einträge wurden gedruckt!',
'Number Format' => 'Zahlenformat',
'Number missing in Row' => 'Nummer fehlt in Zeile',
'Number of copies' => 'Anzahl Kopien',
+ 'Number pages' => 'Seiten nummerieren',
'O' => 'O',
'OBE-Export erfolgreich!' => 'OBE-Export erfolgreich!',
'Obsolete' => 'Ungültig',
'Order deleted!' => 'Auftrag gelöscht!',
'Ordered' => 'Vom Kunde bestellt',
'Orders' => 'Aufträge',
+ 'Orientation' => 'Seitenformat',
'Orphaned' => 'Nie benutzt',
'Out of balance transaction!' => 'Buchung ist nicht ausgeglichen!',
'Out of balance!' => 'Summen stimmen nicht berein!',
'PAYMENT POSTED' => 'Rechung gebucht',
'PDF' => 'PDF',
'PDF (OpenDocument/OASIS)' => 'PDF (OpenDocument/OASIS)',
+ 'PDF export -- options' => 'PDF-Export -- Optionen',
'POSTED' => 'Gebucht',
'POSTED AS NEW' => 'Als neu gebucht',
'PRINTED' => 'Gedruckt',
'Please seletct the dataset you want to delete:' => 'Bitte wählen Sie die zu löschende Datenbank aus:',
'Plural' => 'Plural',
'Port' => 'Port',
+ 'Portrait' => 'Hochformat',
'Post' => 'Buchen',
'Post Payment' => 'Zahlung buchen',
'Postscript' => 'Postscript',
'Quotation Number missing!' => 'Angebotsnummer fehlt!',
'Quotation deleted!' => 'Angebot wurde gelöscht.',
'Quotations' => 'Angebote',
+ 'Quote chararacter' => 'Anführungszeichen',
'Quoted' => 'Angeboten',
'RFQ' => 'Anfrage',
'RFQ Number' => 'Anfragenummer',
'Revenue Account' => 'Erlöskonto',
'Revenues EU with UStId' => 'Erlöse EU m. UStId',
'Revenues EU without UStId' => 'Erlöse EU o. UStId',
+ 'Right' => 'Rechts',
'SAVED' => 'Gespeichert',
'SAVED FOR DUNNING' => 'Gespeichert',
'SCREENED' => 'Angezeigt',
'Sales invoice number' => 'Ausgangsrechnungsnummer',
'Salesman' => 'Verkäufer/in',
'Salesperson' => 'Verkäufer',
+ 'Same as the quote character' => 'Wie Anführungszeichen',
'Sat. Fax' => 'Sat. Fax',
'Sat. Phone' => 'Sat. Tel.',
'Save' => 'Speichern',
'Sell Price' => 'Verkaufspreis',
'Send the backup via Email' => 'Die Sicherungsdatei per Email verschicken',
'Sep' => 'Sep',
+ 'Separator chararacter' => 'Feldtrennzeichen',
'September' => 'September',
'Serial No.' => 'Seriennummer',
'Serial Number' => 'Seriennummer',
'The restoration process has started. Here\'s the output of the "pg_restore" command:' => 'Der Wiederherstellungsprozess wurde gestartet. Hier ist die Ausgabe des "pg_restore"-Programmes:',
'The restoration process is complete. Please review "pg_restore"\'s output to find out if the restoration was successful.' => 'Die Wiederherstellung ist abgeschlossen. Bitte sehen Sie sich die Ausgabe von "pg_restore" an, um festzustellen, ob die Wiederherstellung erfolgreich war.',
'The second way is to use Perl\'s CPAN module and let it download and install the module for you.' => 'Die zweite Variante besteht darin, Perls CPAN-Modul zu benutzen und es das Modul für Sie installieren zu lassen.',
+ 'The tabulator character' => 'Das Tabulator-Symbol',
'The third way is to download the module from the above mentioned URL and to install the module manually following the installations instructions contained in the source archive.' => 'Die dritte Variante besteht darin, das Paket von der oben genannten URL herunterzuladen und es manuell zu installieren. Beachten Sie dabei die im Paket enthaltenen Installationsanweisungen.',
'The unit has been saved.' => 'Die Einheit wurde gespeichert.',
'The unit in row %d has been deleted in the meantime.' => 'Die Einheit in Zeile %d ist in der Zwischentzeit gelöscht worden.',
'To' => 'An',
'To (time)' => 'Bis',
'To add a user to a group edit a name, change the login name and save. A new user with the same variables will then be saved under the new login name.' => 'Um einer Gruppe einen neuen Benutzer hinzuzufügen, ändern und speichern Sie am einfachsten einen bestehen den Zugriffsnamen. Unter dem neuen Namen wird dann ein Benutzer mit denselben Einstellungen angelegt.',
+ 'Top' => 'Oben',
'Top (CSS)' => 'Oben (mit CSS)',
'Top (Javascript)' => 'Oben (mit Javascript)',
'Top 100' => 'Top 100',
'proforma' => 'Proforma',
'purchase_order' => 'Auftrag',
'quarter' => 'Vierteljährliche (quartalsweise) Abgabe',
+ 'report_generator_nextsub is not defined.' => 'report_generator_nextsub ist nicht definiert.',
'request_quotation' => 'Angebotsanforderung',
'reset' => 'zurücksetzen',
's' => 's',
$dbcharset = "ISO-8859-15";
+# Pfad zu 'html2ps' zum Export von Listenansichten als PDF
+$html2ps_bin = "/usr/bin/html2ps";
+$ghostscript_bin = "/usr/bin/gs";
+
+
+
# Datenbankbackups werden mit dem externen Programm "pg_dump" erledigt.
# Wenn es nicht im aktuellen Pfad vorhanden ist, so muss hier der vollständige
# Pfad eingetragen werden. Wenn die Variable auf "DISABLED" gesetzt wird,