commit b77889e107ab1184153b28136e1af9cb81f126f9
Author: Bernd Bleßmann <bernd@kivitendo-premium.de>
Date:   Mon Jan 9 12:55:15 2023 +0100

    Reports als Chart: mehrere Y-Werte

diff --git a/SL/ReportGenerator.pm b/SL/ReportGenerator.pm
index 45b1236eb..14019c26d 100644
--- a/SL/ReportGenerator.pm
+++ b/SL/ReportGenerator.pm
@@ -55,8 +55,8 @@ sub new {
       'encoding'            => 'UTF-8',
     },
     'chart_export'          => {
-      'assignment_x'        => 'x',
-      'assignment_y'        => 'y1',
+      'assignment_x'        => '',
+      'assignments_y'       => [],
     },
   };
   $self->{export}   = {
@@ -876,19 +876,24 @@ sub generate_chart_content {
 
   my $opts            = $self->{options};
 
-  my $assignment_x = $opts->{chart_export}->{assignment_x};
-  my $assignment_y = $opts->{chart_export}->{assignment_y};
+  my $assignment_x  = $opts->{chart_export}->{assignment_x};
+  my $assignments_y = $opts->{chart_export}->{assignments_y};
 
-  my @data_x;
-  my @data_y;
+  my @labels;
+  my @datasets;
   foreach my $row_set (@{ $self->{data} }) {
     next if ('ARRAY' ne ref $row_set);
     foreach my $row (@{ $row_set }) {
-      my $x = $row->{$assignment_x}->{data}->[0];
-      my $y = $row->{$assignment_y}->{data}->[0];
-      if ($x) {
-        push @data_x, $x;
-        push @data_y, $y//0;
+      my $label = $row->{$assignment_x}->{data}->[0];
+      if ($label) {
+        push @labels, $label;
+
+        my @set;
+        foreach my $assignment_y (@$assignments_y) {
+          my $y = $row->{$assignment_y}->{data}->[0];
+          push @set, $y;
+        }
+        push @datasets, \@set;
       }
     }
   }
@@ -912,10 +917,9 @@ sub generate_chart_content {
   $::form->header;
   print $::form->parse_html_template('report_generator/chart_report',
                                       {
-                                        data_x => to_json(\@data_x),
-                                        data_y => to_json(\@data_y),
-                                        label_x => $assignment_x,
-                                        label_y => $assignment_y,
+                                        labels      => to_json(\@labels),
+                                        datasets    => to_json(\@datasets),
+                                        data_labels => to_json($assignments_y),
                                         %$variables,
                                       }
   );
diff --git a/js/kivi.ChartReport.js b/js/kivi.ChartReport.js
index fcc9a9cb1..30bae4f82 100644
--- a/js/kivi.ChartReport.js
+++ b/js/kivi.ChartReport.js
@@ -3,36 +3,60 @@ namespace('kivi.ChartReport', function(ns) {
 
   ns.data = undefined;
 
+  ns.background_colors = function() { return [
+    'rgba(255, 0, 0, 0.2)',
+    'rgba(63, 0, 0, 0.2)',
+    'rgba(0, 127, 0, 0.2)',
+    'rgba(0, 0, 191, 0.2)',
+    'rgba(191, 0, 0, 0.2)',
+    'rgba(0, 255, 0, 0.2)',
+    'rgba(0, 63, 0, 0.2)',
+    'rgba(0, 0, 127, 0.2)',
+    'rgba(127, 0, 0, 0.2)',
+    'rgba(0, 191, 0, 0.2)',
+    'rgba(0, 0, 255, 0.2)',
+    'rgba(0, 0, 63, 0.2)'
+  ]};
+
+  ns.border_colors = function() { return [
+    'rgba(255, 0, 0, 1.0)',
+    'rgba(63, 0, 0, 1.0)',
+    'rgba(0, 127, 0, 1.0)',
+    'rgba(0, 0, 191, 1.0)',
+    'rgba(191, 0, 0, 1.0)',
+    'rgba(0, 255, 0, 1.0)',
+    'rgba(0, 63, 0, 1.0)',
+    'rgba(0, 0, 127, 1.0)',
+    'rgba(127, 0, 0, 1.0)',
+    'rgba(0, 191, 0, 1.0)',
+    'rgba(0, 0, 255, 1.0)',
+    'rgba(0, 0, 63, 1.0)'
+  ]};
+
   ns.chart = function() {
-    $(ns.data.data_y).each(function(idx) {ns.data.data_y[idx] = kivi.parse_amount('' + ns.data.data_y[idx]);});
-    console.log("bb: data_y (parsed): "); console.log(ns.data.data_y);
+    $(ns.data.datasets).each(function(idx, elt) {
+      $(elt).each(function(idx) {elt[idx] = kivi.parse_amount('' + elt[idx]);console.log(elt[idx]);});
+    });
+
+    const datasets = [];
+    for (let i = 0; i < ns.data.data_labels.length; i++) {
+      const set = [];
+      $(ns.data.datasets).each(function(idx, elt) {set.push(elt[i]);});
+      const colots = [];
+      datasets.push({label: ns.data.data_labels[i],
+                     data: set,
+                     backgroundColor: ns.background_colors()[i % ns.background_colors().length],
+                     borderColor: ns.border_colors()[i % ns.border_colors().length],
+                     borderWidth: 1
+                    });
+    }
 
     const ctx = 'chart';
     const chart = new Chart(ctx, {
       type: 'bar',
       data: {
-        labels: ns.data.data_x,
-        datasets: [{
-            label: ns.data.label_y,
-          data: ns.data.data_y,
-            backgroundColor: [
-                'rgba(255, 99, 132, 0.2)',
-                'rgba(54, 162, 235, 0.2)',
-                'rgba(255, 206, 86, 0.2)',
-                'rgba(75, 192, 192, 0.2)',
-                'rgba(153, 102, 255, 0.2)',
-                'rgba(255, 159, 64, 0.2)'
-            ],
-            borderColor: [
-                'rgba(255, 99, 132, 1)',
-                'rgba(54, 162, 235, 1)',
-                'rgba(255, 206, 86, 1)',
-                'rgba(75, 192, 192, 1)',
-                'rgba(153, 102, 255, 1)',
-                'rgba(255, 159, 64, 1)'
-            ],
-            borderWidth: 1
-        }]
+        labels: ns.data.labels,
+        datasets: datasets,
       },
       options: {
         scales: {
@@ -45,10 +69,9 @@ namespace('kivi.ChartReport', function(ns) {
   };
 
   ns.debug = function() {
-    console.log("bb: data_x: "); console.log(ns.data.data_x);
-    console.log("bb: data_y: "); console.log(ns.data.data_y);
-    console.log("bb: label_x: "); console.log(ns.data.label_x);
-    console.log("bb: label_y: "); console.log(ns.data.label_y);
+    console.log("bb: labels: "); console.log(ns.data.labels);
+    console.log("bb: datasets: "); console.log(ns.data.datasets);
+    console.log("bb: data_labels: "); console.log(ns.data.data_labels);
   };
 
   $(function() {
diff --git a/templates/webpages/report_generator/chart_export_options.html b/templates/webpages/report_generator/chart_export_options.html
index f6a1ee8a9..2e95231e3 100644
--- a/templates/webpages/report_generator/chart_export_options.html
+++ b/templates/webpages/report_generator/chart_export_options.html
@@ -1,6 +1,8 @@
 [%- USE T8 %]
 [%- USE HTML %]
 [%- USE L %]
+[%- USE P %]
+[%- USE LxERP %]
 
  <h1>[% HTML.escape(title) %]</h1>
 
@@ -13,7 +15,7 @@
   <input type="hidden" name="report_generator_chart_options_set" value="1">
   <input type="hidden" name="report_generator_dispatch_to" value="">
 
-  <table>
+  <table id="assigment_table">
    <tr>
      <th valign="top" align="right">[% 'Chart assignments' | $T8 %]: [% 'X axis' | $T8 %]</th>
      <td>
@@ -24,18 +26,20 @@
                        title_key = 'text') %]
      </td>
    </tr>
-   <tr>
+    <tr id="y_assignment_row">
      <th valign="top" align="right">[% 'Chart assignments' | $T8 %]: [% 'Y axis' | $T8 %]</th>
      <td>
-       [% L.select_tag('report_generator_chart_options_assignment_y',
+       [% L.select_tag('report_generator_chart_options_assignments_y[]',
                        fields,
-                       default = SELF.report_generator_chart_options_assignment_y
                        value_key = 'name',
                        title_key = 'text') %]
+       [% P.link_tag('', "✘", class='remove_data_assignment interact cursor-pointer', onclick='remove_data_assignment(this)', style='display:none') %]
      </td>
-   </tr>
+    </tr>
   </table>
 
+  [% L.button_tag('add_data_assignement()', LxERP.t8('Add row')) %]
+
 [%- IF CONTROLLER_DISPATCH %]
     <input type="hidden" name="CONTROLLER_DISPATCH" value="[% CONTROLLER_DISPATCH | html %]">
 [%- ELSE %]
@@ -44,3 +48,18 @@
 
 
  </form>
+
+ <script type="text/javascript">
+  <!--
+   function add_data_assignement() {
+     const new_row = $('#y_assignment_row').clone();
+     new_row.removeAttr('id');
+     new_row.find('a').show();
+     new_row.find('*').removeAttr('id');
+     new_row.appendTo("#assigment_table");
+   }
+   function remove_data_assignment(clicked) {
+     $(clicked).closest('tr').remove();
+   }
+  -->
+ </script>
diff --git a/templates/webpages/report_generator/chart_report.html b/templates/webpages/report_generator/chart_report.html
index 5f537bf79..a59a2df33 100644
--- a/templates/webpages/report_generator/chart_report.html
+++ b/templates/webpages/report_generator/chart_report.html
@@ -22,9 +22,8 @@
 
 
 <script>
-  kivi.ChartReport.data = { data_x: [% data_x %],
-                            data_y: [% data_y %],
-                            label_y: "[% label_y %]",
-                            label_x: "[% label_x %]"
+  kivi.ChartReport.data = { labels: [% labels %],
+                            datasets: [% datasets %],
+                            data_labels: [% data_labels %],
                           };
 </script>
