XML basiertes Menue, siehe Bug #771
[kivitendo-erp.git] / bin / mozilla / rp.pl
index a5f9a72..1a2999b 100644 (file)
@@ -39,13 +39,12 @@ use POSIX qw(strftime);
 
 use SL::PE;
 use SL::RP;
-use SL::USTVA;
 use SL::Iconv;
 use SL::ReportGenerator;
 
 require "bin/mozilla/arap.pl";
 require "bin/mozilla/common.pl";
-require "bin/mozilla/report_generator.pl";
+require "bin/mozilla/reportgenerator.pl";
 
 1;
 
@@ -107,8 +106,7 @@ sub report {
             'receipts'             => 'Receipts',
             'payments'             => 'Payments',
             'projects'             => 'Project Transactions',
-            'bwa'                  => 'Betriebswirtschaftliche Auswertung',
-            'ustva'                => 'Umsatzsteuervoranmeldung',);
+            'bwa'                  => 'Betriebswirtschaftliche Auswertung',);
 
   $form->{title} = $locale->text($title{ $form->{report} });
 
@@ -153,49 +151,43 @@ sub report {
   # use JavaScript Calendar or not
   $form->{jsscript} = 1;
   $jsscript = "";
-  if ($form->{report} eq "ustva") {
-    $department = "";
+  if ($form->{report} eq "balance_sheet") {
+    $name_1    = "asofdate";
+    $id_1      = "asofdate";
+    $value_1   = "$form->{asofdate}";
+    $trigger_1 = "trigger1";
+    $name_2    = "compareasofdate";
+    $id_2      = "compareasofdate";
+    $value_2   = "$form->{compareasofdate}";
+    $trigger_2 = "trigger2";
+  } elsif ($form->{report} =~ /(receipts|payments)$/) {
+    $name_1    = "fromdate";
+    $id_1      = "fromdate";
+    $value_1   = "$form->{fromdate}";
+    $trigger_1 = "trigger1";
+    $name_2    = "todate";
+    $id_2      = "todate";
+    $value_2   = "";
+    $trigger_2 = "trigger2";
+  } elsif (($form->{report} eq "ar_aging") || ($form->{report} eq "ap_aging")) {
+    $name_1    = "";
+    $id_1      = "";
+    $value_1   = "";
+    $trigger_1 = "";
+    $name_2    = "todate";
+    $id_2      = "todate";
+    $value_2   = "";
+    $trigger_2 = "trigger2";
+
   } else {
-    if ($form->{report} eq "balance_sheet") {
-      $name_1    = "asofdate";
-      $id_1      = "asofdate";
-      $value_1   = "$form->{asofdate}";
-      $trigger_1 = "trigger1";
-      $name_2    = "compareasofdate";
-      $id_2      = "compareasofdate";
-      $value_2   = "$form->{compareasofdate}";
-      $trigger_2 = "trigger2";
-    } elsif ($form->{report} =~ /(receipts|payments)$/) {
-      $name_1    = "fromdate";
-      $id_1      = "fromdate";
-      $value_1   = "$form->{fromdate}";
-      $trigger_1 = "trigger1";
-      $name_2    = "todate";
-      $id_2      = "todate";
-      $value_2   = "";
-      $trigger_2 = "trigger2";
-    } else {
-      if (($form->{report} eq "ar_aging") || ($form->{report} eq "ap_aging")) {
-        $name_1    = "";
-        $id_1      = "";
-        $value_1   = "";
-        $trigger_1 = "";
-        $name_2    = "todate";
-        $id_2      = "todate";
-        $value_2   = "";
-        $trigger_2 = "trigger2";
-
-      } else {
-        $name_1    = "fromdate";
-        $id_1      = "fromdate";
-        $value_1   = "$form->{fromdate}";
-        $trigger_1 = "trigger1";
-        $name_2    = "todate";
-        $id_2      = "todate";
-        $value_2   = "";
-        $trigger_2 = "trigger2";
-      }
-    }
+    $name_1    = "fromdate";
+    $id_1      = "fromdate";
+    $value_1   = "$form->{fromdate}";
+    $trigger_1 = "trigger1";
+    $name_2    = "todate";
+    $id_2      = "todate";
+    $value_2   = "";
+    $trigger_2 = "trigger2";
   }
 
   # with JavaScript Calendar
@@ -524,107 +516,6 @@ $jsscript
 |;
   }
 
-  if ($form->{report} eq "ustva") {
-
-    print qq|
-
-        <br>
-        <input type=hidden name=nextsub value=generate_ustva>
-</table>
-<table>
-       <tr>
-         <th align=left><input name=reporttype class=radio type=radio value="custom" checked> |
-      . $locale->text('Zeitraum') . qq|</th>
-       </tr>
-       <tr>
-         <th colspan=1>| . $locale->text('Year') . qq|</th>
-         <td><input name=year size=11 title="|
-      . $locale->text('YYYY') . qq|" value="$year"></td>
-       </tr>
-|;
-
-    print qq|
-       <tr>
-               <td align=right>
-<b> | . $locale->text('Yearly') . qq|</b> </td>
-               <th align=left>| . $locale->text('Quarterly') . qq|</th>
-               <th align=left colspan=3>| . $locale->text('Monthly') . qq|</th>
-       </tr>
-       <tr>
-               <td align=right>&nbsp; <input name=duetyp class=radio type=radio value="13"
-$checked></td>
-               <td><input name=duetyp class=radio type=radio value="A" $checked >&nbsp;1. |
-      . $locale->text('Quarter') . qq|</td>
-|;
-    $checked = "checked";
-    print qq|
-               <td><input name=duetyp class=radio type=radio value="1" $checked >&nbsp;|
-      . $locale->text('January') . qq|</td>
-|;
-    $checked = "";
-    print qq|
-               <td><input name=duetyp class=radio type=radio value="5" $checked >&nbsp;|
-      . $locale->text('May') . qq|</td>
-               <td><input name=duetyp class=radio type=radio value="9" $checked >&nbsp;|
-      . $locale->text('September') . qq|</td>
-
-       </tr>
-       <tr>
-               <td align= right>&nbsp;</td>
-               <td><input name=duetyp class=radio type=radio value="B" $checked>&nbsp;2. |
-      . $locale->text('Quarter') . qq|</td>
-               <td><input name=duetyp class=radio type=radio value="2" $checked >&nbsp;|
-      . $locale->text('February') . qq|</td>
-               <td><input name=duetyp class=radio type=radio value="6" $checked >&nbsp;|
-      . $locale->text('June') . qq|</td>
-               <td><input name=duetyp class=radio type=radio value="10" $checked >&nbsp;|
-      . $locale->text('October') . qq|</td>
-       </tr>
-       <tr>
-               <td> &nbsp;</td>
-               <td><input name=duetyp class=radio type=radio value="C" $checked>&nbsp;3. |
-      . $locale->text('Quarter') . qq|</td>
-               <td><input name=duetyp class=radio type=radio value="3" $checked >&nbsp;|
-      . $locale->text('March') . qq|</td>
-               <td><input name=duetyp class=radio type=radio value="7" $checked >&nbsp;|
-      . $locale->text('July') . qq|</td>
-               <td><input name=duetyp class=radio type=radio value="11" $checked >&nbsp;|
-      . $locale->text('November') . qq|</td>
-
-       </tr>
-       <tr>
-               <td> &nbsp;</td>
-               <td><input name=duetyp class=radio type=radio value="D" $checked>&nbsp;4. |
-      . $locale->text('Quarter') . qq|&nbsp;</td>
-               <td><input name=duetyp class=radio type=radio value="4" $checked >&nbsp;|
-      . $locale->text('April') . qq|</td>
-               <td><input name=duetyp class=radio type=radio value="8" $checked >&nbsp;|
-      . $locale->text('August') . qq|</td>
-               <td><input name=duetyp class=radio type=radio value="12" $checked >&nbsp;|
-      . $locale->text('December') . qq|</td>
-
-       </tr>
-       <tr>
-               <td colspan=5><hr size=3 noshade></td>
-       </tr>
-       <tr>
-         <th align=left>| . $locale->text('Method') . qq|</th>
-         <td colspan=3><input name=method class=radio type=radio value=accrual $accrual>|
-      . $locale->text('Accrual') . qq|
-         &nbsp;<input name=method class=radio type=radio value=cash $cash>|
-      . $locale->text('EUR') . qq|</td>
-       </tr>
-       <tr>
-         <th colspan=4>|;
-##########
-
-    &print_options();
-    print qq|
-         </th>
-       </tr>
-|;
-  }
-
   if ($form->{report} eq "balance_sheet") {
     print qq|
         <input type=hidden name=nextsub value=generate_balance_sheet>
@@ -986,27 +877,7 @@ $jsscript
 
 <input type=submit class=submit name=action value="|
     . $locale->text('Continue') . qq|">
-|;
-
-  # Hier Aufruf von get_config zum Einlesen der Finanzamtdaten
-  USTVA->get_config($userspath, 'finanzamt.ini');
 
-  $disabled = qq|disabled="disabled"|;
-  $disabled = '' if ($form->{elster} eq '1');
-  if ($form->{report} eq 'ustva') {
-    print qq|
-  <input type=submit class=submit name=action value="|
-      . $locale->text('debug') . qq|">
-  <input type=submit class=submit name=action $disabled
-   value="| . $locale->text('winston_export') . qq|">
-  |;
-    print qq|
-   <input type=submit class=submit name=action value="|
-      . $locale->text('config') . qq|">
-  |;
-  }
-
-  print qq|
 </form>
 
 </body>
@@ -1256,7 +1127,7 @@ sub generate_projects {
   $form->{title}   = $locale->text('Project Transactions');
   RP->trial_balance(\%myconfig, \%$form);
 
-  &list_accounts;
+  list_accounts('generate_projects');
 
   $lxdebug->leave_sub();
 }
@@ -1275,29 +1146,43 @@ sub generate_trial_balance {
 
   $form->{nextsub} = "generate_trial_balance";
   $form->{title}   = $locale->text('Trial Balance');
-  &list_accounts;
+  list_accounts('generate_trial_balance');
+
+  $lxdebug->leave_sub();
+}
+
+sub create_list_accounts_subtotal_row {
+  $lxdebug->enter_sub();
+
+  my ($subtotals, $columns, $fields, $class) = @_;
+
+  my $row = { map { $_ => { 'data' => '', 'class' => $class, 'align' => 'right' } } @{ $columns } };
+
+  map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $subtotals->{$_}, 2) } @{ $fields };
 
   $lxdebug->leave_sub();
+
+  return $row;
 }
 
 sub list_accounts {
   $lxdebug->enter_sub();
 
-  $title = $form->escape($form->{title});
+  my ($action) = @_;
 
+  my @options;
   if ($form->{department}) {
-    ($department) = split /--/, $form->{department};
-    $options    = $locale->text('Department') . " : $department<br>";
-    $department = $form->escape($form->{department});
+    my ($department) = split /--/, $form->{department};
+    push @options, $locale->text('Department') . " : $department";
   }
   if ($form->{projectnumber}) {
-    $options .=
-      $locale->text('Project Number') . " : $form->{projectnumber}<br>";
-    $projectnumber = $form->escape($form->{projectnumber});
+    push @options, $locale->text('Project Number') . " : $form->{projectnumber}";
   }
 
   # if there are any dates
   if ($form->{fromdate} || $form->{todate}) {
+    my ($fromdate, $todate);
+
     if ($form->{fromdate}) {
       $fromdate = $locale->date(\%myconfig, $form->{fromdate}, 1);
     }
@@ -1305,211 +1190,99 @@ sub list_accounts {
       $todate = $locale->date(\%myconfig, $form->{todate}, 1);
     }
 
-    $form->{period} = "$fromdate - $todate";
-  } else {
-    $form->{period} =
-      $locale->date(\%myconfig, $form->current_date(\%myconfig), 1);
+    push @options, "$fromdate - $todate";
 
+  } else {
+    push @options, $locale->date(\%myconfig, $form->current_date(\%myconfig), 1);
   }
-  $options .= $form->{period};
-
-  @column_index = qw(accno description begbalance debit credit endbalance);
-
-  $column_header{accno} =
-    qq|<th class=listheading>| . $locale->text('Account') . qq|</th>|;
-  $column_header{description} =
-    qq|<th class=listheading>| . $locale->text('Description') . qq|</th>|;
-  $column_header{debit} =
-    qq|<th class=listheading>| . $locale->text('Debit') . qq|</th>|;
-  $column_header{credit} =
-    qq|<th class=listheading>| . $locale->text('Credit') . qq|</th>|;
-  $column_header{begbalance} =
-    qq|<th class=listheading>| . $locale->text('Balance') . qq|</th>|;
-  $column_header{endbalance} =
-    qq|<th class=listheading>| . $locale->text('Balance') . qq|</th>|;
 
-  $form->header;
+  my @columns     = qw(accno description begbalance debit credit endbalance);
+  my %column_defs = (
+    'accno'       => { 'text' => $locale->text('Account'), },
+    'description' => { 'text' => $locale->text('Description'), },
+    'debit'       => { 'text' => $locale->text('Debit'), },
+    'credit'      => { 'text' => $locale->text('Credit'), },
+    'begbalance'  => { 'text' => $locale->text('Balance'), },
+    'endbalance'  => { 'text' => $locale->text('Balance'), },
+  );
+  my %column_alignment = map { $_ => 'right' } qw(debit credit begbalance endbalance);
 
-  print qq|
-<body>
+  my @hidden_variables = qw(fromdate todate department l_heading l_subtotal all_accounts sort accounttype eur projectnumber project_id title nextsub);
 
-<table width=100%>
-  <tr>
-    <th class=listtop>$form->{title}</th>
-  </tr>
-  <tr height="5"></tr>
-  <tr>
-    <td>$options</td>
-  </tr>
-  <tr>
-    <td>
-      <table width=100%>
-       <tr>|;
+  $form->{callback} = build_std_url("action=$action", grep { $form->{$_} } @hidden_variables);
 
-  map { print "$column_header{$_}\n" } @column_index;
+  my $report = SL::ReportGenerator->new(\%myconfig, $form);
 
-  print qq|
-        </tr>
-|;
+  $report->set_options('top_info_text'         => join("\n", @options),
+                       'output_format'         => 'HTML',
+                       'title'                 => $form->{title},
+                       'attachment_basename'   => $locale->text('list_of_transactions') . strftime('_%Y%m%d', localtime time),
+                       'std_column_visibility' => 1,
+    );
+  $report->set_options_from_form();
 
-  # sort the whole thing by account numbers and display
-  foreach $ref (sort { $a->{accno} cmp $b->{accno} } @{ $form->{TB} }) {
-
-    $description = $form->escape($ref->{description});
-
-    $href =
-      qq|ca.pl?action=list_transactions&accounttype=$form->{accounttype}&login=$form->{login}&password=$form->{password}&fromdate=$form->{fromdate}&todate=$form->{todate}&sort=transdate&l_heading=$form->{l_heading}&l_subtotal=$form->{l_subtotal}&department=$department&eur=$form->{eur}&projectnumber=$projectnumber&project_id=$form->{project_id}&title=$title&nextsub=$form->{nextsub}&accno=$ref->{accno}&description=$description|;
-
-    $ml = ($ref->{category} =~ /(A|C|E)/) ? -1 : 1;
-
-    $debit  = ($ref->{debit} != 0) ? $form->format_amount(\%myconfig, $ref->{debit},  2, "&nbsp;") : "&nbsp;";
-    $credit = ($ref->{credit} != 0) ? $form->format_amount(\%myconfig, $ref->{credit}, 2, "&nbsp;") : "&nbsp;";
-    $begbalance =
-      $form->format_amount(\%myconfig, $ref->{balance} * $ml, 2, "&nbsp;");
-    $endbalance =
-      $form->format_amount(\%myconfig,
-                           ($ref->{balance} + $ref->{amount}) * $ml,
-                           2, "&nbsp;");
-
-    #    next if ($ref->{debit} == 0 && $ref->{credit} == 0);
-
-    if ($ref->{charttype} eq "H" && $subtotal && $form->{l_subtotal}) {
-      map { $column_data{$_} = "<th>&nbsp;</th>" }
-        qw(accno begbalance endbalance);
-
-      $subtotalbegbalance =
-        $form->format_amount(\%myconfig, $subtotalbegbalance, 2, "&nbsp;");
-      $subtotalendbalance =
-        $form->format_amount(\%myconfig, $subtotalendbalance, 2, "&nbsp;");
-      $subtotaldebit =
-        $form->format_amount(\%myconfig, $subtotaldebit, 2, "&nbsp;");
-      $subtotalcredit =
-        $form->format_amount(\%myconfig, $subtotalcredit, 2, "&nbsp;");
-
-      $column_data{description} = "<th>$subtotaldescription</th>";
-      $column_data{begbalance}  = "<th align=right>$subtotalbegbalance</th>";
-      $column_data{endbalance}  = "<th align=right>$subtotalendbalance</th>";
-      $column_data{debit}       = "<th align=right>$subtotaldebit</th>";
-      $column_data{credit}      = "<th align=right>$subtotalcredit</th>";
-
-      print qq|
-       <tr class=listsubtotal>
-|;
-      map { print "$column_data{$_}\n" } @column_index;
+  $report->set_columns(%column_defs);
+  $report->set_column_order(@columns);
 
-      print qq|
-        </tr>
-|;
-    }
+  $report->set_export_options($action, @hidden_variables);
 
-    if ($ref->{charttype} eq "H") {
-      $subtotal            = 1;
-      $subtotaldescription = $ref->{description};
-      $subtotaldebit       = $ref->{debit};
-      $subtotalcredit      = $ref->{credit};
-      $subtotalbegbalance  = 0;
-      $subtotalendbalance  = 0;
+  $report->set_sort_indicator('accno', 1);
 
-      next unless $form->{l_heading};
+  my @totals_columns = qw(credit debit begbalance endbalance);
+  my %subtotals      = map { $_ => 0 } @totals_columns;
+  my %totals         = map { $_ => 0 } @totals_columns;
+  my $found_heading  = 0;
+  my @tb             = sort { $a->{accno} cmp $b->{accno} } @{ $form->{TB} };
 
-      map { $column_data{$_} = "<th>&nbsp;</th>" }
-        qw(accno debit credit begbalance endbalance);
-      $column_data{description} =
-        "<th class=listheading>$ref->{description}</th>";
-    }
+  # sort the whole thing by account numbers and display
+  foreach my $idx (0 .. scalar(@tb) - 1) {
+    my $ref  = $tb[$idx];
+    my $href = build_std_url('script=ca.pl', 'action=list_transactions', 'accno=' . E($ref->{accno}), 'description=' . E($ref->{description}), @hidden_variables);
 
-    if ($ref->{charttype} eq "A") {
-      $column_data{accno}       = "<td><a href=$href>$ref->{accno}</a></td>";
-      $column_data{description} = "<td>$ref->{description}</td>";
-      $column_data{debit}       = "<td align=right>$debit</td>";
-      $column_data{credit}      = "<td align=right>$credit</td>";
-      $column_data{begbalance}  = "<td align=right>$begbalance</td>";
-      $column_data{endbalance}  = "<td align=right>$endbalance</td>";
+    my $ml   = ($ref->{category} =~ /(A|C|E)/) ? -1 : 1;
 
-      $totaldebit  += $ref->{debit};
-      $totalcredit += $ref->{credit};
+    my $row  = { map { $_ => { 'align' => $column_alignment{$_} } } @columns };
 
-      $subtotalbegbalance += $ref->{balance} * $ml;
-      $subtotalendbalance += ($ref->{balance} + $ref->{amount}) * $ml;
+    if ($ref->{charttype} eq 'H') {
+      next unless ($form->{l_heading});
 
-    }
+      %subtotals                   = map { $_ => 0 } @totals_columns;
+      $found_heading               = 1;
+      $row->{description}->{class} = 'listheading';
+      $row->{description}->{data}  = $ref->{description};
 
-    if ($ref->{charttype} eq "H") {
-      print qq|
-      <tr class=listheading>
-|;
+      $report->add_data($row);
+
+      next;
     }
-    if ($ref->{charttype} eq "A") {
-      $i++;
-      $i %= 2;
-      print qq|
-      <tr class=listrow$i>
-|;
+
+    foreach (qw(debit credit)) {
+      $subtotals{$_} += $ref->{$_};
+      $totals{$_}    += $ref->{$_};
     }
 
-    map { print "$column_data{$_}\n" } @column_index;
+    $subtotals{begbalance} += $ref->{balance} * $ml;
+    $subtotals{endbalance} += ($ref->{balance} + $ref->{amount}) * $ml;
 
-    print qq|
-      </tr>
-|;
-  }
+    map { $row->{$_}->{data} = $ref->{$_} } qw(accno description);
+    map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $ref->{$_}, 2) if ($ref->{$_} != 0) } qw(credit debit);
 
-  # print last subtotal
-  if ($subtotal && $form->{l_subtotal}) {
-    map { $column_data{$_} = "<th>&nbsp;</th>" }
-      qw(accno begbalance endbalance);
-    $subtotalbegbalance =
-      $form->format_amount(\%myconfig, $subtotalbegbalance, 2, "&nbsp;");
-    $subtotalendbalance =
-      $form->format_amount(\%myconfig, $subtotalendbalance, 2, "&nbsp;");
-    $subtotaldebit =
-      $form->format_amount(\%myconfig, $subtotaldebit, 2, "&nbsp;");
-    $subtotalcredit =
-      $form->format_amount(\%myconfig, $subtotalcredit, 2, "&nbsp;");
-    $column_data{description} = "<th>$subdescription</th>";
-    $column_data{begbalance}  = "<th align=right>$subtotalbegbalance</th>";
-    $column_data{endbalance}  = "<th align=right>$subtotalendbalance</th>";
-    $column_data{debit}       = "<th align=right>$subtotaldebit</th>";
-    $column_data{credit}      = "<th align=right>$subtotalcredit</th>";
+    $row->{begbalance}->{data} = $form->format_amount(\%myconfig, $ref->{balance} * $ml, 2);
+    $row->{endbalance}->{data} = $form->format_amount(\%myconfig, ($ref->{balance} + $ref->{amount}) * $ml, 2);
 
-    print qq|
-      <tr class=listsubtotal>
-|;
-    map { print "$column_data{$_}\n" } @column_index;
+    $report->add_data($row);
 
-    print qq|
-      </tr>
-|;
+    if ($form->{l_heading} && $found_heading &&
+        (($idx == scalar(@tb) - 1) || ('H' eq $tb[$idx + 1]->{charttype}))) {
+      $report->add_data(create_list_accounts_subtotal_row(\%subtotals, \@columns, \@totals_columns, 'listsubtotal'));
+    }
   }
 
-  $totaldebit  = $form->format_amount(\%myconfig, $totaldebit,  2, "&nbsp;");
-  $totalcredit = $form->format_amount(\%myconfig, $totalcredit, 2, "&nbsp;");
-
-  map { $column_data{$_} = "<th>&nbsp;</th>" }
-    qw(accno description begbalance endbalance);
-
-  $column_data{debit}  = qq|<th align=right class=listtotal>$totaldebit</th>|;
-  $column_data{credit} = qq|<th align=right class=listtotal>$totalcredit</th>|;
-
-  print qq|
-        <tr class=listtotal>
-|;
+  $report->add_separator();
 
-  map { print "$column_data{$_}\n" } @column_index;
+  $report->add_data(create_list_accounts_subtotal_row(\%totals, \@columns, [ qw(debit credit) ], 'listtotal'));
 
-  print qq|
-       </tr>
-      </table>
-    </td>
-  </tr>
-  <tr>
-    <td><hr size=3 noshade></td>
-  </tr>
-</table>
-
-</body>
-</html>
-|;
+  $report->generate_with_headers();
 
   $lxdebug->leave_sub();
 }
@@ -1670,7 +1443,7 @@ sub aging {
   if ($form->{arap} eq 'ar') {
     $raw_top_info_text    = $form->parse_html_template('rp/aging_ar_top');
     $raw_bottom_info_text = $form->parse_html_template('rp/aging_ar_bottom', { 'row_idx' => $row_idx,
-                                                                               'PRINT_OPTIONS' => print_options(1), });
+                                                                               'PRINT_OPTIONS' => print_options(inline => 1), });
     $report->set_options('raw_top_info_text'    => $raw_top_info_text,
                          'raw_bottom_info_text' => $raw_bottom_info_text);
   }
@@ -2252,217 +2025,108 @@ sub list_payments {
 
   RP->payments(\%myconfig, \%$form);
 
-  @columns =
-    $form->sort_columns(qw(transdate reference name paid source memo));
-
-  # construct href
-  $account    = $form->escape($form->{account});
-  $title      = $form->escape($form->{title});
-  $department = $form->escape($form->{department});
-  $form->{paymentaccounts} =~ s/ /%20/g;
-  $reference = $form->escape($form->{reference});
-  $source    = $form->escape($form->{source});
-  $memo      = $form->escape($form->{memo});
+  my @hidden_variables = qw(account title department reference source memo fromdate todate
+                            fx_transaction db prepayment paymentaccounts sort);
 
-  $href =
-    "$form->{script}?action=list_payments&login=$form->{login}&password=$form->{password}&fromdate=$form->{fromdate}&todate=$form->{todate}&fx_transaction=$form->{fx_transaction}&db=$form->{db}&prepayment=$form->{prepayment}&title=$title&account=$account&department=$department&paymentaccounts=$form->{paymentaccounts}&reference=$reference&source=$source&memo=$memo";
+  my $href = build_std_url('action=list_payments', grep { $form->{$_} } @hidden_variables);
+  $form->{callback} = $href;
 
-  # construct callback
-  $account    = $form->escape($form->{account},    1);
-  $title      = $form->escape($form->{title},      1);
-  $department = $form->escape($form->{department}, 1);
-  $reference  = $form->escape($form->{reference},  1);
-  $source     = $form->escape($form->{source},     1);
-  $memo       = $form->escape($form->{memo},       1);
-
-  $form->{callback} =
-    "$form->{script}?action=list_payments&login=$form->{login}&password=$form->{password}&fromdate=$form->{fromdate}&todate=$form->{todate}&fx_transaction=$form->{fx_transaction}&db=$form->{db}&prepayment=$form->{prepayment}&title=$title&account=$account&department=$department&paymentaccounts=$form->{paymentaccounts}&reference=$reference&source=$source&memo=$memo&sort=$form->{sort}";
-  $callback = $form->escape($form->{callback});
+  my @columns     = qw(transdate invnumber name paid source memo);
+  my %column_defs = (
+    'name'      => { 'text' => $locale->text('Description'), },
+    'invnumber' => { 'text' => $locale->text('Reference'), },
+    'transdate' => { 'text' => $locale->text('Date'), },
+    'paid'      => { 'text' => $locale->text('Amount'), },
+    'source'    => { 'text' => $locale->text('Source'), },
+    'memo'      => { 'text' => $locale->text('Memo'), },
+  );
+  my %column_alignment = ('paid' => 'right');
 
-  $column_header{name} =
-      "<th><a class=listheading href=$href&sort=name>"
-    . $locale->text('Description')
-    . "</a></th>";
-  $column_header{reference} =
-      "<th><a class=listheading href=$href&sort=invnumber>"
-    . $locale->text('Reference')
-    . "</a></th>";
-  $column_header{transdate} =
-      "<th><a class=listheading href=$href&sort=transdate>"
-    . $locale->text('Date')
-    . "</a></th>";
-  $column_header{paid} =
-    "<th class=listheading>" . $locale->text('Amount') . "</a></th>";
-  $column_header{source} =
-      "<th><a class=listheading href=$href&sort=source>"
-    . $locale->text('Source')
-    . "</a></th>";
-  $column_header{memo} =
-      "<th><a class=listheading href=$href&sort=memo>"
-    . $locale->text('Memo')
-    . "</a></th>";
+  map { $column_defs{$_}->{link} = $href . "&sort=$_" } grep { $_ ne 'paid' } @columns;
 
+  my @options;
   if ($form->{fromdate}) {
-    $option .= "\n<br>" if ($option);
-    $option .=
-        $locale->text('From') . "&nbsp;"
-      . $locale->date(\%myconfig, $form->{fromdate}, 1);
+    push @options, $locale->text('From') . "&nbsp;" . $locale->date(\%myconfig, $form->{fromdate}, 1);
   }
   if ($form->{todate}) {
-    $option .= "\n<br>" if ($option);
-    $option .=
-        $locale->text('bis') . "&nbsp;"
-      . $locale->date(\%myconfig, $form->{todate}, 1);
+    push @options, $locale->text('bis') . "&nbsp;" . $locale->date(\%myconfig, $form->{todate}, 1);
   }
 
-  @column_index = @columns;
-  $colspan      = $#column_index + 1;
+  my $report = SL::ReportGenerator->new(\%myconfig, $form);
 
-  $form->header;
+  my $attachment_basename = $form->{db} eq 'ar' ? $locale->text('list_of_receipts') : $locale->text('list_of_payments');
 
-  print qq|
-<body>
+  $report->set_options('top_info_text'         => join("\n", @options),
+                       'output_format'         => 'HTML',
+                       'title'                 => $form->{title},
+                       'attachment_basename'   => $attachment_basename . strftime('_%Y%m%d', localtime time),
+                       'std_column_visibility' => 1,
+    );
+  $report->set_options_from_form();
 
-<table width=100%>
-  <tr>
-    <th class=listtop>$form->{title}</th>
-  </tr>
-  <tr height="5"></tr>
-  <tr>
-    <td>$option</td>
-  </tr>
-  <tr>
-    <td>
-      <table width=100%>
-       <tr class=listheading>
-|;
+  $report->set_columns(%column_defs);
+  $report->set_column_order(@columns);
 
-  map { print "\n$column_header{$_}" } @column_index;
+  $report->set_export_options('list_payments', @hidden_variables);
 
-  print qq|
-        </tr>
-|;
+  $report->set_sort_indicator($form->{sort}, 1);
 
-  foreach $ref (sort { $a->{accno} cmp $b->{accno} } @{ $form->{PR} }) {
+  my $total_paid    = 0;
 
+  foreach my $ref (sort { $a->{accno} cmp $b->{accno} } @{ $form->{PR} }) {
     next unless @{ $form->{ $ref->{id} } };
 
-    print qq|
-        <tr>
-         <th colspan=$colspan align=left>$ref->{accno}--$ref->{description}</th>
-       </tr>
-|;
+    $report->add_control({ 'type' => 'colspan_data', 'data' => "$ref->{accno}--$ref->{description}" });
 
-    foreach $payment (@{ $form->{ $ref->{id} } }) {
+    my $subtotal_paid = 0;
 
-      $module = $payment->{module};
+    foreach my $payment (@{ $form->{ $ref->{id} } }) {
+      my $module = $payment->{module};
       $module = 'is' if ($payment->{invoice} && $payment->{module} eq 'ar');
       $module = 'ir' if ($payment->{invoice} && $payment->{module} eq 'ap');
 
-      $href =
-        qq|${module}.pl?action=edit&id=$payment->{id}&login=$form->{login}&password=$form->{password}&callback=$callback|;
+      $subtotal_paid += $payment->{paid};
+      $total_paid    += $payment->{paid};
 
-      $column_data{name}      = "<td>$payment->{name}&nbsp;</td>";
-      $column_data{reference} =
-        qq|<td><a href=$href>$payment->{invnumber}</a></td>|;
-      $column_data{transdate} = "<td>$payment->{transdate}&nbsp;</td>";
-      $column_data{paid}      =
-          "<td align=right>"
-        . $form->format_amount(\%myconfig, $payment->{paid}, 2, "&nbsp;")
-        . "</td>";
-      $column_data{source} = "<td>$payment->{source}&nbsp;</td>";
-      $column_data{memo}   = "<td>$payment->{memo}&nbsp;</td>";
+      $payment->{paid} = $form->format_amount(\%myconfig, $payment->{paid}, 2);
 
-      $subtotalpaid += $payment->{paid};
-      $totalpaid    += $payment->{paid};
+      my $row = { };
 
-      $i++;
-      $i %= 2;
-      print qq|
-       <tr class=listrow$i>
-|;
+      foreach my $column (@columns) {
+        $row->{$column} = {
+          'data'  => $payment->{$column},
+          'align' => $column_alignment{$column},
+        };
+      }
 
-      map { print "\n$column_data{$_}" } @column_index;
-
-      print qq|
-        </tr>
-|;
+      $row->{invnumber}->{link} = build_std_url("script=${module}.pl", 'action=edit', 'id=' . E($payment->{id}), 'callback');
 
+      $report->add_data($row);
     }
 
-    # print subtotals
-    map { $column_data{$_} = "<td>&nbsp;</td>" } @column_index;
-
-    $column_data{paid} =
-      "<th class=listsubtotal align=right>"
-      . $form->format_amount(\%myconfig, $subtotalpaid, 2, "&nbsp;") . "</th>";
-
-    print qq|
-       <tr class=listsubtotal>
-|;
-
-    map { print "\n$column_data{$_}" } @column_index;
-
-    print qq|
-        </tr>
-|;
-
-    $subtotalpaid = 0;
+    my $row = { map { $_ => { 'class' => 'listsubtotal' } } @columns };
+    $row->{paid} = {
+      'data'  => $form->format_amount(\%myconfig, $subtotal_paid, 2),
+      'align' => 'right',
+      'class' => 'listsubtotal',
+    };
 
+    $report->add_data($row);
   }
 
-  # print total
-  map { $column_data{$_} = "<td>&nbsp;</td>" } @column_index;
-
-  $column_data{paid} =
-    "<th class=listtotal align=right>"
-    . $form->format_amount(\%myconfig, $totalpaid, 2, "&nbsp;") . "</th>";
-
-  print qq|
-        <tr class=listtotal>
-|;
-
-  map { print "\n$column_data{$_}" } @column_index;
+  $report->add_separator();
 
-  print qq|
-        </tr>
+  my $row = { map { $_ => { 'class' => 'listtotal' } } @columns };
+  $row->{paid} = {
+    'data'  => $form->format_amount(\%myconfig, $total_paid, 2),
+    'align' => 'right',
+    'class' => 'listtotal',
+  };
 
-      </table>
-    </td>
-  </tr>
-  <tr>
-    <td><hr size=3 noshade></td>
-  </tr>
-</table>
+  $report->add_data($row);
 
-</body>
-</html>
-|;
-
-  $lxdebug->leave_sub();
-}
-
-sub config {
-  $lxdebug->enter_sub();
-  edit();
-
-  #$form->header;
-  #print qq|Hallo|;
-  $lxdebug->leave_sub();
-}
-
-sub debug {
-
-  $form->debug();
-
-}
-
-sub winston_export {
-  $lxdebug->enter_sub();
+  $report->generate_with_headers();
 
-  #create_winston();
-  $form->{winston} = 1;
-  &generate_ustva();
   $lxdebug->leave_sub();
 }
 
@@ -2488,14 +2152,9 @@ sub print_options {
   $form->{OP}{ $form->{media} }    = "selected";
   $form->{SM}{ $form->{sendmode} } = "selected";
 
-  if ($form->{report} eq 'ustva') {
-    $type = qq|
-           <option value=ustva $form->{PD}{ustva}>| . $locale->text('ustva');
-  } else {
-    $type = qq|
+  $type = qq|
            <option value=statement $form->{PD}{statement}>|
       . $locale->text('Statement');
-  }
 
   if ($form->{media} eq 'email') {
     $media = qq|
@@ -2514,14 +2173,9 @@ sub print_options {
 
   if ($latex_templates) {
     $format .= qq|
-            <option value=html $form->{DF}{html}>|
-      . $locale->text('HTML') . qq|
-           <option value=pdf $form->{DF}{pdf}>| . $locale->text('PDF');
-    if ($form->{report} ne 'ustva') {
-      $format . qq|
-            <option value=postscript $form->{DF}{postscript}>|
-        . $locale->text('Postscript');
-    }
+            <option value=html $form->{DF}{html}>| . $locale->text('HTML')
+      . qq| <option value=pdf $form->{DF}{pdf}>| . $locale->text('PDF')
+      . qq| <option value=postscript $form->{DF}{postscript}>| . $locale->text('Postscript');
   }
 
   my $output = qq|
@@ -2743,232 +2397,3 @@ sub generate_bwa {
   $lxdebug->leave_sub();
 }
 
-sub generate_ustva {
-  $lxdebug->enter_sub();
-
-  # Hier Aufruf von get_config zum Einlesen der Finanzamtdaten
-  USTVA->get_config($userspath, 'finanzamt.ini');
-
-  #  &get_project(generate_bwa);
-  @anmeldungszeitraum =
-    qw(0401, 0402, 0403, 0404, 0405, 0405, 0406, 0407, 0408, 0409, 0410, 0411, 0412, 0441, 0442, 0443, 0444);
-
-  foreach $item (@anmeldungszeitraum) {
-    $form->{$item} = "";
-  }
-  if ($form->{reporttype} eq "custom") {
-
-    #forgotten the year --> thisyear
-    if ($form->{year} !~ m/^\d\d\d\d$/) {
-      $locale->date(\%myconfig, $form->current_date(\%myconfig), 0) =~
-        /(\d\d\d\d)/;
-      $form->{year} = $1;
-    }
-
-    #yearly report
-    if ($form->{duetyp} eq "13") {
-      $form->{fromdate} = "1.1.$form->{year}";
-      $form->{todate}   = "31.12.$form->{year}";
-    }
-
-    #Quater reports
-    if ($form->{duetyp} eq "A") {
-      $form->{fromdate} = "1.1.$form->{year}";
-      $form->{todate}   = "31.3.$form->{year}";
-      $form->{"0441"}   = "X";
-    }
-    if ($form->{duetyp} eq "B") {
-      $form->{fromdate} = "1.4.$form->{year}";
-      $form->{todate}   = "30.6.$form->{year}";
-      $form->{"0442"}   = "X";
-    }
-    if ($form->{duetyp} eq "C") {
-      $form->{fromdate} = "1.7.$form->{year}";
-      $form->{todate}   = "30.9.$form->{year}";
-      $form->{"0443"}   = "X";
-    }
-    if ($form->{duetyp} eq "D") {
-      $form->{fromdate} = "1.10.$form->{year}";
-      $form->{todate}   = "31.12.$form->{year}";
-      $form->{"0444"}   = "X";
-    }
-
-    #Monthly reports
-  SWITCH: {
-      $form->{duetyp} eq "1" && do {
-        $form->{fromdate} = "1.1.$form->{year}";
-        $form->{todate}   = "31.1.$form->{year}";
-        $form->{"0401"}   = "X";
-        last SWITCH;
-      };
-      $form->{duetyp} eq "2" && do {
-        $form->{fromdate} = "1.2.$form->{year}";
-
-        #this works from 1901 to 2099, 1900 and 2100 fail.
-        $leap = ($form->{year} % 4 == 0) ? "29" : "28";
-        $form->{todate} = "$leap.2.$form->{year}";
-        $form->{"0402"} = "X";
-        last SWITCH;
-      };
-      $form->{duetyp} eq "3" && do {
-        $form->{fromdate} = "1.3.$form->{year}";
-        $form->{todate}   = "31.3.$form->{year}";
-        $form->{"0403"}   = "X";
-        last SWITCH;
-      };
-      $form->{duetyp} eq "4" && do {
-        $form->{fromdate} = "1.4.$form->{year}";
-        $form->{todate}   = "30.4.$form->{year}";
-        $form->{"0404"}   = "X";
-        last SWITCH;
-      };
-      $form->{duetyp} eq "5" && do {
-        $form->{fromdate} = "1.5.$form->{year}";
-        $form->{todate}   = "31.5.$form->{year}";
-        $form->{"0405"}   = "X";
-        last SWITCH;
-      };
-      $form->{duetyp} eq "6" && do {
-        $form->{fromdate} = "1.6.$form->{year}";
-        $form->{todate}   = "30.6.$form->{year}";
-        $form->{"0406"}   = "X";
-        last SWITCH;
-      };
-      $form->{duetyp} eq "7" && do {
-        $form->{fromdate} = "1.7.$form->{year}";
-        $form->{todate}   = "31.7.$form->{year}";
-        $form->{"0407"}   = "X";
-        last SWITCH;
-      };
-      $form->{duetyp} eq "8" && do {
-        $form->{fromdate} = "1.8.$form->{year}";
-        $form->{todate}   = "31.8.$form->{year}";
-        $form->{"0408"}   = "X";
-        last SWITCH;
-      };
-      $form->{duetyp} eq "9" && do {
-        $form->{fromdate} = "1.9.$form->{year}";
-        $form->{todate}   = "30.9.$form->{year}";
-        $form->{"0409"}   = "X";
-        last SWITCH;
-      };
-      $form->{duetyp} eq "10" && do {
-        $form->{fromdate} = "1.10.$form->{year}";
-        $form->{todate}   = "31.10.$form->{year}";
-        $form->{"0410"}   = "X";
-        last SWITCH;
-      };
-      $form->{duetyp} eq "11" && do {
-        $form->{fromdate} = "1.11.$form->{year}";
-        $form->{todate}   = "30.11.$form->{year}";
-        $form->{"0411"}   = "X";
-        last SWITCH;
-      };
-      $form->{duetyp} eq "12" && do {
-        $form->{fromdate} = "1.12.$form->{year}";
-        $form->{todate}   = "31.12.$form->{year}";
-        $form->{"0412"}   = "X";
-        last SWITCH;
-      };
-    }
-  }
-
-  #    $locale->date(\%myconfig, $form->current_date(\%myconfig), 0)=~ /(\d\d\d\d)/;
-  #    $form->{year}= $1;
-  #    $form->{fromdate}="1.1.$form->{year}";
-  #    $form->{todate}="31.3.$form->{year}";
-  #    $form->{period} = $locale->date(\%myconfig, $form->current_date(\%myconfig), 1);
-  #  }
-
-  RP->ustva(\%myconfig, \%$form);
-
-  ($form->{department}) = split /--/, $form->{department};
-
-  $form->{period} =
-    $locale->date(\%myconfig, $form->current_date(\%myconfig), 1);
-  $form->{todate} = $form->current_date(\%myconfig) unless $form->{todate};
-
-  # if there are any dates construct a where
-  if ($form->{fromdate} || $form->{todate}) {
-
-    unless ($form->{todate}) {
-      $form->{todate} = $form->current_date(\%myconfig);
-    }
-
-    $longtodate  = $locale->date(\%myconfig, $form->{todate}, 1);
-    $shorttodate = $locale->date(\%myconfig, $form->{todate}, 0);
-
-    $longfromdate  = $locale->date(\%myconfig, $form->{fromdate}, 1);
-    $shortfromdate = $locale->date(\%myconfig, $form->{fromdate}, 0);
-
-    $form->{this_period} = "$shortfromdate\n$shorttodate";
-    $form->{period}      =
-        $locale->text('for Period')
-      . qq|<br>\n$longfromdate |
-      . $locale->text('bis')
-      . qq| $longtodate|;
-  }
-
-  if ($form->{comparefromdate} || $form->{comparetodate}) {
-    $longcomparefromdate =
-      $locale->date(\%myconfig, $form->{comparefromdate}, 1);
-    $shortcomparefromdate =
-      $locale->date(\%myconfig, $form->{comparefromdate}, 0);
-
-    $longcomparetodate  = $locale->date(\%myconfig, $form->{comparetodate}, 1);
-    $shortcomparetodate = $locale->date(\%myconfig, $form->{comparetodate}, 0);
-
-    $form->{last_period} = "$shortcomparefromdate\n$shortcomparetodate";
-    $form->{period} .=
-        "\n$longcomparefromdate "
-      . $locale->text('bis')
-      . qq| $longcomparetodate|;
-  }
-
-  $form->{Datum_heute} =
-    $locale->date(\%myconfig, $form->current_date(\%myconfig), 0);
-
-  if (   $form->{format} eq 'pdf'
-      or $form->{format} eq 'postscript') {
-    $form->{padding} = "~~";
-    $form->{bold}    = "\textbf{";
-    $form->{endbold} = "}";
-    $form->{br}      = '\\\\';
-
-    @numbers = qw(51r 86r 97r 93r 96 43 45
-      66 62 67);
-    foreach $number (@numbers) {
-      $form->{$number} =~ s/,/~~/g;
-    }
-
-      } elsif ($form->{format} eq 'html') {
-    $form->{padding} = "&nbsp;&nbsp;";
-    $form->{bold}    = "<b>";
-    $form->{endbold} = "</b>";
-    $form->{br}      = "<br>"
-
-  }
-
-  # setup variables for the form
-  @a = qw(company address businessnumber);
-  map { $form->{$_} = $myconfig{$_} } @a;
-
-  $form->{address} =~ s/\\n/$form->{br}/g;
-
-  if ($form->{winston} eq '1') {
-    create_winston();
-
-  } else {
-    $form->{templates} = $myconfig{templates};
-    $form->{IN}        = "$form->{type}";
-    $form->{IN} .= '.tex'
-      if (   $form->{format} eq 'pdf'
-          or $form->{format} eq 'postscript');
-    $form->{IN} .= '.html' if ($form->{format} eq 'html');
-
-    $form->parse_template(\%myconfig, $userspath);
-
-    # $form->parse_template;
-  }
-  $lxdebug->leave_sub();
-}