Merge branch 'f-cvar-htmlfield'
[kivitendo-erp.git] / SL / Form.pm
index 630c0f2..29d9d6c 100644 (file)
@@ -59,7 +59,9 @@ use SL::CVar;
 use SL::DB;
 use SL::DBConnect;
 use SL::DBUtils;
+use SL::DB::AdditionalBillingAddress;
 use SL::DB::Customer;
+use SL::DB::CustomVariableConfig;
 use SL::DB::Default;
 use SL::DB::PaymentTerm;
 use SL::DB::Vendor;
@@ -550,8 +552,10 @@ sub _prepare_html_template {
   }
   $language = "de" unless ($language);
 
-  if (-f "templates/webpages/${file}.html") {
-    $file = "templates/webpages/${file}.html";
+  my $webpages_path = $::request->layout->webpages_path;
+
+  if (-f "${webpages_path}/${file}.html") {
+    $file = "${webpages_path}/${file}.html";
 
   } elsif (ref $file eq 'SCALAR') {
     # file is a scalarref, use inline mode
@@ -707,74 +711,6 @@ sub format_amount {
   SL::Helper::Number::_format_number($amount, $places, %$myconfig, dash => $dash);
 }
 
-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 '';
-  }
-
-  my $all_units        = AM->retrieve_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);
 
@@ -1152,6 +1088,7 @@ sub get_formname_translation {
     bin_list                => $main::locale->text('Bin List'),
     credit_note             => $main::locale->text('Credit Note'),
     invoice                 => $main::locale->text('Invoice'),
+    invoice_copy            => $main::locale->text('Invoice Copy'),
     pick_list               => $main::locale->text('Pick List'),
     proforma                => $main::locale->text('Proforma Invoice'),
     purchase_order          => $main::locale->text('Purchase Order'),
@@ -2777,19 +2714,48 @@ sub lastname_used {
 }
 
 sub get_variable_content_types {
-  my %html_variables  = (
-      longdescription => 'html',
-      partnotes       => 'html',
-      notes           => 'html',
-      orignotes       => 'html',
-      notes1          => 'html',
-      notes2          => 'html',
-      notes3          => 'html',
-      notes4          => 'html',
-      header_text     => 'html',
-      footer_text     => 'html',
+  my ($self) = @_;
+
+  my %html_variables = (
+    longdescription  => 'html',
+    partnotes        => 'html',
+    notes            => 'html',
+    orignotes        => 'html',
+    notes1           => 'html',
+    notes2           => 'html',
+    notes3           => 'html',
+    notes4           => 'html',
+    header_text      => 'html',
+    footer_text      => 'html',
   );
-  return \%html_variables;
+
+  return {
+    %html_variables,
+    $self->get_variable_content_types_for_cvars,
+  };
+}
+
+sub get_variable_content_types_for_cvars {
+  my ($self)       = @_;
+  my $html_configs = SL::DB::Manager::CustomVariableConfig->get_all(where => [ type => 'htmlfield' ]);
+  my %types;
+
+  if (@{ $html_configs }) {
+    my %prefix_by_module = (
+      Contacts => 'cp_cvar_',
+      CT       => 'vc_cvar_',
+      IC       => 'ic_cvar_',
+      Projects => 'project_cvar_',
+      ShipTo   => 'shiptocvar_',
+    );
+
+    foreach my $cfg (@{ $html_configs }) {
+      my $prefix = $prefix_by_module{$cfg->module};
+      $types{$prefix . $cfg->name} = 'html' if $prefix;
+    }
+  }
+
+  return %types;
 }
 
 sub current_date {
@@ -3020,7 +2986,7 @@ sub get_history {
       qq|SELECT h.employee_id, h.itime::timestamp(0) AS itime, h.addition, h.what_done, emp.name, h.snumbers, h.trans_id AS id | .
       qq|FROM history_erp h | .
       qq|LEFT JOIN employee emp ON (emp.id = h.employee_id) | .
-      qq|WHERE (trans_id = | . $trans_id . qq|) $restriction | .
+      qq|WHERE (trans_id = | . $dbh->quote($trans_id) . qq|) $restriction | .
       $order;
 
     my $sth = $dbh->prepare($query) || $self->dberror($query);
@@ -3219,6 +3185,8 @@ sub prepare_for_printing {
     IS->invoice_details(\%::myconfig, $self, $::locale);
   }
 
+  $self->set_addition_billing_address_print_variables;
+
   # Chose extension & set source file name
   my $extension = 'html';
   if ($self->{format} eq 'postscript') {
@@ -3279,6 +3247,43 @@ sub prepare_for_printing {
     today     => DateTime->today,
   };
 
+  if ($defaults->print_interpolate_variables_in_positions) {
+    $self->substitute_placeholders_in_template_arrays({ field => 'description', type => 'text' }, { field => 'longdescription', type => 'html' });
+  }
+
+  return $self;
+}
+
+sub set_addition_billing_address_print_variables {
+  my ($self) = @_;
+
+  return if !$self->{billing_address_id};
+
+  my $address = SL::DB::Manager::AdditionalBillingAddress->find_by(id => $self->{billing_address_id});
+  return if !$address;
+
+  $self->{"billing_address_${_}"} = $address->$_ for map { $_->name } @{ $address->meta->columns };
+}
+
+sub substitute_placeholders_in_template_arrays {
+  my ($self, @fields) = @_;
+
+  foreach my $spec (@fields) {
+    $spec     = { field => $spec, type => 'text' } if !ref($spec);
+    my $field = $spec->{field};
+
+    next unless exists $self->{TEMPLATE_ARRAYS} && exists $self->{TEMPLATE_ARRAYS}->{$field};
+
+    my $tag_start = $spec->{type} eq 'html' ? '&lt;%' : '<%';
+    my $tag_end   = $spec->{type} eq 'html' ? '%&gt;' : '%>';
+    my $formatter = $spec->{type} eq 'html' ? sub { $::locale->quote_special_chars('html', $_[0] // '') } : sub { $_[0] };
+
+    $self->{TEMPLATE_ARRAYS}->{$field} = [
+      apply { s{${tag_start}(.+?)${tag_end}}{ $formatter->($self->{$1}) }eg }
+        @{ $self->{TEMPLATE_ARRAYS}->{$field} }
+    ];
+  }
+
   return $self;
 }