commit 60457bb7f2f36a9f3bf90358bfe68f75ced915bd
Author: Cem Aydin <cem.aydin@gmx.ch>
Date:   Fri Dec 15 14:29:34 2023 +0100

    Reclamation Controller: Support für Drucken via internem Kivi parser hinzugefügt
    
    Dazu werden die benötigten Druck Variablen aus dem Rose DB objekt
    ins template array geschrieben.
    
    Helfer Funktionen unter SL/DB/Helper/LegacyPrinting.pm erstellt.
    Siehe auch perldoc in dieser Datei.

diff --git a/SL/Controller/Reclamation.pm b/SL/Controller/Reclamation.pm
index b56887a43..540ec0fef 100644
--- a/SL/Controller/Reclamation.pm
+++ b/SL/Controller/Reclamation.pm
@@ -2188,6 +2188,10 @@ sub generate_pdf {
   if ($print_form->{format} =~ /(opendocument|oasis)/i) {
     $template_ext  = 'odt';
     $template_type = 'OpenDocument';
+
+    # add variables for printing with the built-in parser
+    $reclamation->flatten_to_form($print_form, format_amounts => 1);
+    $reclamation->add_legacy_template_arrays($print_form);
   }
 
   # search for the template
diff --git a/SL/DB/Helper/LegacyPrinting.pm b/SL/DB/Helper/LegacyPrinting.pm
new file mode 100644
index 000000000..ae7319ef7
--- /dev/null
+++ b/SL/DB/Helper/LegacyPrinting.pm
@@ -0,0 +1,114 @@
+package SL::DB::Helper::LegacyPrinting;
+
+use strict;
+
+use parent qw(Exporter);
+our @EXPORT = qw(map_keys_to_arrays format_as_number);
+
+sub map_keys_to_arrays {
+  my ($items, $keys, $template_arrays) = @_;
+
+  for my $key (@$keys) {
+    # handle nested keys
+    if ($key =~ /\./) {
+      my ($k1, $k2) = split /\./, $key;
+      $template_arrays->{$k1} = [ map { { $k2 => $_->{$k1}->{$k2} } } @$items ];
+    } else {
+      $template_arrays->{$key} = [ map {
+        $_->can($key) ? $_->$key
+                      : $_->{$key}
+      } @$items ];
+    }
+  }
+}
+
+sub format_as_number {
+  my ($keys, $template_arrays) = @_;
+
+  for my $key (@$keys) {
+    $template_arrays->{$key} = [ map {
+      $::form->format_amount(\%::myconfig, $_, 2, 0),
+    } @{ $template_arrays->{$key} } ];
+  }
+}
+
+1;
+
+__END__
+
+=pod
+
+=encoding utf8
+
+=head1 NAME
+
+SL::DB::Helper::LegacyPrinting - Helper functions to support printing using the built-it template parser
+
+=head1 DESCRIPTION
+
+The new Reclamation controller, and possibly other future controllers, only support printing using Template Toolkit (TT)
+for parsing the templates. For OpenDocument templates however, template toolkit cannot be used.
+
+Template Toolkit (TT) can access Rose DB objects directly, which is a feature not available in the built-in parser.
+For positions in a loop, such as positions in a table, the built-in parser expects the data in a specific format.
+Therefore, we need to prepare the data accordingly before it can be processed by the built-in parser.
+
+In the past this was done in the respective modules, e.g. SL/OE.pm. The idea would be to extract the data from the Rose
+DB objects. That should hopefully result in less and simpler code.
+
+=head1 FUNCTIONS
+
+=head2 C<map_keys_to_arrays ($items, $keys, $template_arrays)>
+
+Extracts the given keys from the given list of Rose DB objects and adds them to the given hash reference,
+in the format that the built in template parser expects.
+
+The expected format looks like the following, e.g.:
+
+  # 'qty_as_number' => [
+  #                      '1.00',
+  #                      '3.00'
+  #                    ],
+  # 'part' => [
+  #             {
+  #               'partnumber' => '000013'
+  #             },
+  #             {
+  #               'partnumber' => '000004'
+  #             }
+  #           ],
+  # 'position' => [
+  #                 1,
+  #                 2
+  #               ],
+  # 'unit' => [
+  #             'Stck',
+  #             'Stck'
+  #           ],
+
+=over 4
+
+=item C<$items>
+
+A reference to a list of Rose DB objects from which the keys should be extracted.
+
+=item C<$keys>
+
+A reference to a list of keys that should be extracted from the Rose DB object.
+Nested keys should be denoted by a dot. E.g.:
+
+  qw( qty_as_number part.partnumber position unit )
+
+=item C<$template_arrays>
+
+A reference to a hash to which the extracted keys should be added.
+
+=back
+
+=head2 C<format_as_number ($keys, $template_arrays)>
+
+Formats the given keys in the given hash reference as numbers.
+
+=head1 AUTHOR
+
+Cem Aydin E<lt>cem.aydin@revamp-it.chE<gt>
diff --git a/SL/DB/Reclamation.pm b/SL/DB/Reclamation.pm
index 829687226..02273a285 100644
--- a/SL/DB/Reclamation.pm
+++ b/SL/DB/Reclamation.pm
@@ -26,6 +26,7 @@ use SL::DB::Helper::RecordLink qw(RECORD_ID RECORD_TYPE_REF);
 use SL::Locale::String qw(t8);
 use SL::RecordLinks;
 use Rose::DB::Object::Helpers qw(as_tree strip);
+use SL::DB::Helper::LegacyPrinting qw(map_keys_to_arrays format_as_number);
 
 __PACKAGE__->meta->add_relationship(
 
@@ -233,6 +234,24 @@ sub convert_to_delivery_order {
   return $delivery_order;
 }
 
+sub add_legacy_template_arrays {
+  my ($self, $print_form) = @_;
+
+  # for now using the keys that are used in the latex template: template/print/marei/sales_reclamation.tex
+  # (nested keys: part.partnumber, reason.description)
+  my @keys = qw( position part.partnumber description longdescription reqdate serialnumber projectnumber reason.description
+    reason_description_ext qty_as_number unit sellprice_as_number discount_as_number discount_as_percent linetotal );
+
+  my @tax_keys = qw( tax.taxdescription amount );
+
+  my %template_arrays;
+  map_keys_to_arrays($self->items_sorted, \@keys, \%template_arrays);
+  map_keys_to_arrays($self->taxes, \@tax_keys, \%template_arrays);
+
+  format_as_number([ qw(linetotal) ], \%template_arrays);
+  $print_form->{TEMPLATE_ARRAYS} = \%template_arrays;
+}
+
 #TODO(Werner): überprüfen ob alle Felder richtig gestetzt werden
 sub new_from {
   my ($class, $source, %params) = @_;
@@ -571,6 +590,14 @@ nothing is created or changed in the database.
 
 At the moment only sales quotations and sales reclamations can be converted.
 
+=head2 C<add_legacy_template_arrays $print_form>
+
+For printing OpenDocument documents we need to extract loop variables (items and
+taxes) from the Rose DB object and add them to the form, in the format that the
+built-in template parser expects.
+
+<$print_form> Print form used in the controller.
+
 =head2 C<new_from $source, %params>
 
 Creates a new C<SL::DB::Reclamation> instance and copies as much
diff --git a/SL/Form.pm b/SL/Form.pm
index 97366b221..71c223f24 100644
--- a/SL/Form.pm
+++ b/SL/Form.pm
@@ -3205,6 +3205,8 @@ sub prepare_for_printing {
     DO->order_details(\%::myconfig, $self);
   } elsif ($self->{type} =~ /sales_order|sales_quotation|request_quotation|purchase_order|purchase_quotation_intake/) {
     OE->order_details(\%::myconfig, $self);
+  } elsif ($self->{type} =~ /reclamation/) {
+    # skip reclamation here, legacy template arrays are added in the reclamation controller
   } else {
     IS->invoice_details(\%::myconfig, $self, $::locale);
   }
