+ $main::lxdebug->leave_sub();
+
+ return $file;
+}
+
+sub parse_html_template {
+ $main::lxdebug->enter_sub();
+
+ my ($self, $file, $additional_params) = @_;
+
+ $additional_params ||= { };
+
+ my $real_file = $self->_prepare_html_template($file, $additional_params);
+ my $template = $self->template || $self->init_template;
+
+ map { $additional_params->{$_} ||= $self->{$_} } keys %{ $self };
+
+ my $output;
+ $template->process($real_file, $additional_params, \$output) || die $template->error;
+
+ $main::lxdebug->leave_sub();
+
+ return $output;
+}
+
+sub init_template {
+ my $self = shift;
+
+ return if $self->template;
+
+ return $self->template(Template->new({
+ 'INTERPOLATE' => 0,
+ 'EVAL_PERL' => 0,
+ 'ABSOLUTE' => 1,
+ 'CACHE_SIZE' => 0,
+ 'PLUGIN_BASE' => 'SL::Template::Plugin',
+ 'INCLUDE_PATH' => '.:templates/webpages',
+ 'COMPILE_EXT' => '.tcc',
+ 'COMPILE_DIR' => $::lx_office_conf{paths}->{userspath} . '/templates-cache',
+ })) || die;
+}
+
+sub template {
+ my $self = shift;
+ $self->{template_object} = shift if @_;
+ return $self->{template_object};
+}
+
+sub show_generic_error {
+ $main::lxdebug->enter_sub();
+
+ my ($self, $error, %params) = @_;
+
+ if ($self->{__ERROR_HANDLER}) {
+ $self->{__ERROR_HANDLER}->($error);
+ $main::lxdebug->leave_sub();
+ return;
+ }
+
+ my $add_params = {
+ 'title_error' => $params{title},
+ 'label_error' => $error,
+ };
+
+ if ($params{action}) {
+ my @vars;
+
+ map { delete($self->{$_}); } qw(action);
+ map { push @vars, { "name" => $_, "value" => $self->{$_} } if (!ref($self->{$_})); } keys %{ $self };
+
+ $add_params->{SHOW_BUTTON} = 1;
+ $add_params->{BUTTON_LABEL} = $params{label} || $params{action};
+ $add_params->{VARIABLES} = \@vars;
+
+ } elsif ($params{back_button}) {
+ $add_params->{SHOW_BACK_BUTTON} = 1;
+ }
+
+ $self->{title} = $params{title} if $params{title};
+
+ $self->header();
+ print $self->parse_html_template("generic/error", $add_params);
+
+ print STDERR "Error: $error\n";
+
+ $main::lxdebug->leave_sub();
+
+ ::end_of_request();
+}
+
+sub show_generic_information {
+ $main::lxdebug->enter_sub();
+
+ my ($self, $text, $title) = @_;
+
+ my $add_params = {
+ 'title_information' => $title,
+ 'label_information' => $text,
+ };
+
+ $self->{title} = $title if ($title);
+
+ $self->header();
+ print $self->parse_html_template("generic/information", $add_params);
+
+ $main::lxdebug->leave_sub();
+
+ ::end_of_request();
+}
+
+# write Trigger JavaScript-Code ($qty = quantity of Triggers)
+# changed it to accept an arbitrary number of triggers - sschoeling
+sub write_trigger {
+ $main::lxdebug->enter_sub();
+
+ my $self = shift;
+ my $myconfig = shift;
+ my $qty = shift;
+
+ # set dateform for jsscript
+ # default
+ my %dateformats = (
+ "dd.mm.yy" => "%d.%m.%Y",
+ "dd-mm-yy" => "%d-%m-%Y",
+ "dd/mm/yy" => "%d/%m/%Y",
+ "mm/dd/yy" => "%m/%d/%Y",
+ "mm-dd-yy" => "%m-%d-%Y",
+ "yyyy-mm-dd" => "%Y-%m-%d",
+ );
+
+ my $ifFormat = defined($dateformats{$myconfig->{"dateformat"}}) ?
+ $dateformats{$myconfig->{"dateformat"}} : "%d.%m.%Y";
+
+ my @triggers;
+ while ($#_ >= 2) {
+ push @triggers, qq|
+ Calendar.setup(
+ {
+ inputField : "| . (shift) . qq|",
+ ifFormat :"$ifFormat",
+ align : "| . (shift) . qq|",
+ button : "| . (shift) . qq|"
+ }
+ );
+ |;
+ }
+ my $jsscript = qq|
+ <script type="text/javascript">
+ <!--| . join("", @triggers) . qq|//-->
+ </script>
+ |;
+
+ $main::lxdebug->leave_sub();
+
+ return $jsscript;
+} #end sub write_trigger
+
+sub redirect {
+ $main::lxdebug->enter_sub();
+
+ my ($self, $msg) = @_;
+
+ if (!$self->{callback}) {
+
+ $self->info($msg);
+ ::end_of_request();
+ }
+
+# my ($script, $argv) = split(/\?/, $self->{callback}, 2);
+# $script =~ s|.*/||;
+# $script =~ s|[^a-zA-Z0-9_\.]||g;
+# exec("perl", "$script", $argv);
+
+ print $::form->redirect_header($self->{callback});
+
+ $main::lxdebug->leave_sub();
+}
+
+# sort of columns removed - empty sub
+sub sort_columns {
+ $main::lxdebug->enter_sub();
+
+ my ($self, @columns) = @_;
+
+ $main::lxdebug->leave_sub();
+
+ return @columns;
+}
+#
+sub format_amount {
+ $main::lxdebug->enter_sub(2);
+
+ my ($self, $myconfig, $amount, $places, $dash) = @_;
+
+ if ($amount eq "") {
+ $amount = 0;
+ }
+
+ # Hey watch out! The amount can be an exponential term like 1.13686837721616e-13
+
+ my $neg = ($amount =~ s/^-//);
+ my $exp = ($amount =~ m/[e]/) ? 1 : 0;
+
+ if (defined($places) && ($places ne '')) {
+ if (not $exp) {
+ if ($places < 0) {
+ $amount *= 1;
+ $places *= -1;
+
+ my ($actual_places) = ($amount =~ /\.(\d+)/);
+ $actual_places = length($actual_places);
+ $places = $actual_places > $places ? $actual_places : $places;
+ }
+ }
+ $amount = $self->round_amount($amount, $places);
+ }
+
+ my @d = map { s/\d//g; reverse split // } my $tmp = $myconfig->{numberformat}; # get delim chars
+ my @p = split(/\./, $amount); # split amount at decimal point
+
+ $p[0] =~ s/\B(?=(...)*$)/$d[1]/g if $d[1]; # add 1,000 delimiters
+
+ $amount = $p[0];
+ $amount .= $d[0].$p[1].(0 x ($places - length $p[1])) if ($places || $p[1] ne '');
+
+ $amount = do {
+ ($dash =~ /-/) ? ($neg ? "($amount)" : "$amount" ) :
+ ($dash =~ /DRCR/) ? ($neg ? "$amount " . $main::locale->text('DR') : "$amount " . $main::locale->text('CR') ) :
+ ($neg ? "-$amount" : "$amount" ) ;
+ };
+
+
+ $main::lxdebug->leave_sub(2);
+ return $amount;
+}
+
+sub format_amount_units {
+ $main::lxdebug->enter_sub();
+
+ my $self = shift;
+ my %params = @_;
+
+ my $myconfig = \%main::myconfig;
+ my $amount = $params{amount} * 1;
+ my $places = $params{places};
+ my $part_unit_name = $params{part_unit};
+ my $amount_unit_name = $params{amount_unit};
+ my $conv_units = $params{conv_units};
+ my $max_places = $params{max_places};
+
+ if (!$part_unit_name) {
+ $main::lxdebug->leave_sub();
+ return '';
+ }
+
+ AM->retrieve_all_units();
+ my $all_units = $main::all_units;
+
+ if (('' eq ref $conv_units) && ($conv_units =~ /convertible/)) {
+ $conv_units = AM->convertible_units($all_units, $part_unit_name, $conv_units eq 'convertible_not_smaller');
+ }
+
+ if (!scalar @{ $conv_units }) {
+ my $result = $self->format_amount($myconfig, $amount, $places, undef, $max_places) . " " . $part_unit_name;
+ $main::lxdebug->leave_sub();
+ return $result;
+ }
+
+ my $part_unit = $all_units->{$part_unit_name};
+ my $conv_unit = ($amount_unit_name && ($amount_unit_name ne $part_unit_name)) ? $all_units->{$amount_unit_name} : $part_unit;
+
+ $amount *= $conv_unit->{factor};
+
+ my @values;
+ my $num;
+
+ foreach my $unit (@$conv_units) {
+ my $last = $unit->{name} eq $part_unit->{name};
+ if (!$last) {
+ $num = int($amount / $unit->{factor});
+ $amount -= $num * $unit->{factor};
+ }
+
+ if ($last ? $amount : $num) {
+ push @values, { "unit" => $unit->{name},
+ "amount" => $last ? $amount / $unit->{factor} : $num,
+ "places" => $last ? $places : 0 };
+ }
+
+ last if $last;
+ }
+
+ if (!@values) {
+ push @values, { "unit" => $part_unit_name,
+ "amount" => 0,
+ "places" => 0 };
+ }
+
+ my $result = join " ", map { $self->format_amount($myconfig, $_->{amount}, $_->{places}, undef, $max_places), $_->{unit} } @values;
+
+ $main::lxdebug->leave_sub();
+
+ return $result;
+}
+
+sub format_string {
+ $main::lxdebug->enter_sub(2);
+
+ my $self = shift;
+ my $input = shift;
+
+ $input =~ s/(^|[^\#]) \# (\d+) /$1$_[$2 - 1]/gx;
+ $input =~ s/(^|[^\#]) \#\{(\d+)\}/$1$_[$2 - 1]/gx;
+ $input =~ s/\#\#/\#/g;
+
+ $main::lxdebug->leave_sub(2);
+
+ return $input;
+}
+
+#
+
+sub parse_amount {
+ $main::lxdebug->enter_sub(2);
+
+ my ($self, $myconfig, $amount) = @_;
+
+ if ( ($myconfig->{numberformat} eq '1.000,00')
+ || ($myconfig->{numberformat} eq '1000,00')) {
+ $amount =~ s/\.//g;
+ $amount =~ s/,/\./;
+ }
+
+ if ($myconfig->{numberformat} eq "1'000.00") {
+ $amount =~ s/\'//g;
+ }
+
+ $amount =~ s/,//g;
+
+ $main::lxdebug->leave_sub(2);
+
+ return ($amount * 1);
+}
+
+sub round_amount {
+ $main::lxdebug->enter_sub(2);
+
+ my ($self, $amount, $places) = @_;
+ my $round_amount;
+
+ # Rounding like "Kaufmannsrunden" (see http://de.wikipedia.org/wiki/Rundung )
+
+ # Round amounts to eight places before rounding to the requested
+ # number of places. This gets rid of errors due to internal floating
+ # point representation.
+ $amount = $self->round_amount($amount, 8) if $places < 8;
+ $amount = $amount * (10**($places));
+ $round_amount = int($amount + .5 * ($amount <=> 0)) / (10**($places));
+
+ $main::lxdebug->leave_sub(2);
+
+ return $round_amount;
+
+}
+
+sub parse_template {
+ $main::lxdebug->enter_sub();
+
+ my ($self, $myconfig) = @_;
+ my $out;
+
+ local (*IN, *OUT);
+
+ my $userspath = $::lx_office_conf{paths}->{userspath};
+
+ $self->{"cwd"} = getcwd();
+ $self->{"tmpdir"} = $self->{cwd} . "/${userspath}";
+
+ my $ext_for_format;
+
+ my $template_type;
+ if ($self->{"format"} =~ /(opendocument|oasis)/i) {
+ $template_type = 'OpenDocument';
+ $ext_for_format = $self->{"format"} =~ m/pdf/ ? 'pdf' : 'odt';
+
+ } elsif ($self->{"format"} =~ /(postscript|pdf)/i) {
+ $ENV{"TEXINPUTS"} = ".:" . getcwd() . "/" . $myconfig->{"templates"} . ":" . $ENV{"TEXINPUTS"};
+ $template_type = 'LaTeX';
+ $ext_for_format = 'pdf';
+
+ } elsif (($self->{"format"} =~ /html/i) || (!$self->{"format"} && ($self->{"IN"} =~ /html$/i))) {
+ $template_type = 'HTML';
+ $ext_for_format = 'html';
+
+ } elsif (($self->{"format"} =~ /xml/i) || (!$self->{"format"} && ($self->{"IN"} =~ /xml$/i))) {
+ $template_type = 'XML';
+ $ext_for_format = 'xml';
+
+ } elsif ( $self->{"format"} =~ /elster(?:winston|taxbird)/i ) {
+ $template_type = 'XML';
+
+ } elsif ( $self->{"format"} =~ /excel/i ) {
+ $template_type = 'Excel';
+ $ext_for_format = 'xls';
+
+ } elsif ( defined $self->{'format'}) {
+ $self->error("Outputformat not defined. This may be a future feature: $self->{'format'}");
+
+ } elsif ( $self->{'format'} eq '' ) {
+ $self->error("No Outputformat given: $self->{'format'}");
+
+ } else { #Catch the rest
+ $self->error("Outputformat not defined: $self->{'format'}");
+ }
+
+ my $template = SL::Template::create(type => $template_type,
+ file_name => $self->{IN},
+ form => $self,
+ myconfig => $myconfig,
+ userspath => $userspath);
+
+ # Copy the notes from the invoice/sales order etc. back to the variable "notes" because that is where most templates expect it to be.
+ $self->{"notes"} = $self->{ $self->{"formname"} . "notes" };
+
+ if (!$self->{employee_id}) {
+ map { $self->{"employee_${_}"} = $myconfig->{$_}; } qw(email tel fax name signature company address businessnumber co_ustid taxnumber duns);
+ }
+
+ map { $self->{"${_}"} = $myconfig->{$_}; } qw(co_ustid);
+ map { $self->{"myconfig_${_}"} = $myconfig->{$_} } grep { $_ ne 'dbpasswd' } keys %{ $myconfig };
+
+ $self->{copies} = 1 if (($self->{copies} *= 1) <= 0);
+
+ # OUT is used for the media, screen, printer, email
+ # for postscript we store a copy in a temporary file
+ my $fileid = time;
+ my $prepend_userspath;
+
+ if (!$self->{tmpfile}) {
+ $self->{tmpfile} = "${fileid}.$self->{IN}";
+ $prepend_userspath = 1;
+ }
+
+ $prepend_userspath = 1 if substr($self->{tmpfile}, 0, length $userspath) eq $userspath;
+
+ $self->{tmpfile} =~ s|.*/||;
+ $self->{tmpfile} =~ s/[^a-zA-Z0-9\._\ \-]//g;
+ $self->{tmpfile} = "$userspath/$self->{tmpfile}" if $prepend_userspath;
+
+ if ($template->uses_temp_file() || $self->{media} eq 'email') {
+ $out = $self->{OUT};
+ $self->{OUT} = ">$self->{tmpfile}";
+ }
+
+ my $result;
+
+ if ($self->{OUT}) {
+ open OUT, "$self->{OUT}" or $self->error("$self->{OUT} : $!");
+ $result = $template->parse(*OUT);
+ close OUT;
+
+ } else {
+ $self->header;
+ $result = $template->parse(*STDOUT);
+ }
+
+ if (!$result) {
+ $self->cleanup();
+ $self->error("$self->{IN} : " . $template->get_error());
+ }
+
+ if ($self->{media} eq 'file') {
+ copy(join('/', $self->{cwd}, $userspath, $self->{tmpfile}), $out =~ m|^/| ? $out : join('/', $self->{cwd}, $out)) if $template->uses_temp_file;
+ $self->cleanup;
+ chdir("$self->{cwd}");
+
+ $::lxdebug->leave_sub();
+
+ return;
+ }
+
+ if ($template->uses_temp_file() || $self->{media} eq 'email') {
+
+ if ($self->{media} eq 'email') {
+
+ my $mail = new Mailer;
+
+ map { $mail->{$_} = $self->{$_} }
+ qw(cc bcc subject message version format);
+ $mail->{charset} = $::lx_office_conf{system}->{dbcharset} || Common::DEFAULT_CHARSET;
+ $mail->{to} = $self->{EMAIL_RECIPIENT} ? $self->{EMAIL_RECIPIENT} : $self->{email};
+ $mail->{from} = qq|"$myconfig->{name}" <$myconfig->{email}>|;
+ $mail->{fileid} = "$fileid.";
+ $myconfig->{signature} =~ s/\r//g;
+
+ # if we send html or plain text inline
+ if (($self->{format} eq 'html') && ($self->{sendmode} eq 'inline')) {
+ $mail->{contenttype} = "text/html";
+
+ $mail->{message} =~ s/\r//g;
+ $mail->{message} =~ s/\n/<br>\n/g;
+ $myconfig->{signature} =~ s/\n/<br>\n/g;
+ $mail->{message} .= "<br>\n-- <br>\n$myconfig->{signature}\n<br>";
+
+ open(IN, $self->{tmpfile})
+ or $self->error($self->cleanup . "$self->{tmpfile} : $!");
+ while (<IN>) {
+ $mail->{message} .= $_;
+ }
+
+ close(IN);