Zahlungsbedingungen nicht unter Angebot/Auftrag überschreiben.
[kivitendo-erp.git] / bin / mozilla / gl.pl
index e0a5811..fb6166f 100644 (file)
 #
 #======================================================================
 
-use SL::GL;
-use SL::PE;
-
-use Data::Dumper;
+use utf8;
+use strict;
 
-require "$form->{path}/arap.pl";
+use POSIX qw(strftime);
+use List::Util qw(sum);
 
-1;
+use SL::FU;
+use SL::GL;
+use SL::IS;
+use SL::PE;
+use SL::ReportGenerator;
 
-# end of main
+require "bin/mozilla/common.pl";
+require "bin/mozilla/drafts.pl";
+require "bin/mozilla/reportgenerator.pl";
 
 # this is for our long dates
 # $locale->text('January')
@@ -71,919 +76,567 @@ require "$form->{path}/arap.pl";
 # $locale->text('Dec')
 
 sub add {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  $main::auth->assert('general_ledger');
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+
+  return $main::lxdebug->leave_sub() if (load_draft_maybe());
 
   $form->{title} = "Add";
 
-  $form->{callback} =
-    "$form->{script}?action=add&path=$form->{path}&login=$form->{login}&password=$form->{password}"
-    unless $form->{callback};
+  $form->{callback} = "gl.pl?action=add" unless $form->{callback};
 
   # we use this only to set a default date
+  # yep. aber er holt hier auch schon ALL_CHARTS. Aufwand / Nutzen? jb
   GL->transaction(\%myconfig, \%$form);
 
-  map {
-    $chart .=
-      "<option value=\"$_->{accno}--$_->{taxkey_id}\">$_->{accno}--$_->{description}</option>"
-  } @{ $form->{chart} };
-  map {
-    $tax .=
-      qq|<option value="$_->{taxkey}--$_->{rate}">$_->{taxdescription}  |
-      . ($_->{rate} * 100) . qq| %|
-  } @{ $form->{TAX} };
-
-  $form->{chart} = $chart;
-
-  $form->{debitchart}  = $chart;
-  $form->{creditchart} = $chart;
-  $form->{taxchart}    = $tax;
+  $form->{rowcount}  = 2;
 
   $form->{debit}  = 0;
   $form->{credit} = 0;
   $form->{tax}    = 0;
 
-  $form->{creditrowcount} = 2;
-  $form->{debitrowcount}  = 2;
-
   # departments
   $form->all_departments(\%myconfig);
-  if (@{ $form->{all_departments} }) {
+  if (@{ $form->{all_departments} || [] }) {
     $form->{selectdepartment} = "<option>\n";
 
     map {
       $form->{selectdepartment} .=
         "<option>$_->{description}--$_->{id}\n"
-    } (@{ $form->{all_departments} });
+    } (@{ $form->{all_departments} || [] });
   }
 
-  &display_form;
+  $form->{show_details} = $myconfig{show_form_details} unless defined $form->{show_details};
+
+  &display_form(1);
+  $main::lxdebug->leave_sub();
 
-  $lxdebug->leave_sub();
 }
 
-sub edit {
-  $lxdebug->enter_sub();
+sub prepare_transaction {
+  $main::lxdebug->enter_sub();
 
-  GL->transaction(\%myconfig, \%$form);
+  $main::auth->assert('general_ledger');
 
-  map {
-    if ($form->{debitaccno} eq $_->{accno}) {
-      $form->{debitchart} .=
-        "<option value=\"$_->{accno}--$_->{taxkey_id}\">$_->{accno}--$_->{description}";
-    }
-  } @{ $form->{chart} };
-  map {
-    if ($form->{creditaccno} eq $_->{accno}) {
-      $form->{creditchart} .=
-        "<option value=\"$_->{accno}--$_->{taxkey_id}\">$_->{accno}--$_->{description}";
-    }
-  } @{ $form->{chart} };
-  map {
-    $tax .=
-      qq|<option value="$_->{taxkey}--$_->{rate}">$_->{taxdescription}  |
-      . ($_->{rate} * 100) . qq| %|
-  } @{ $form->{TAX} };
-
-  if ($form->{creditrowcount} > 2) {
-    for $i (2 .. $form->{creditrowcount}) {
-      map {
-        if ($form->{"creditchartselected_$i"} eq $_->{accno}) {
-          $form->{"creditchartselected_$i"} = "$_->{accno}--$_->{taxkey_id}";
-        }
-      } @{ $form->{chart} };
-      map {
-        if ($form->{"taxchartselected_$i"} eq $_->{taxkey}) {
-          $form->{"taxchartselected_$i"} = "$_->{taxkey}--$_->{rate}";
-        }
-      } @{ $form->{TAX} };
-    }
-  }
-  if ($form->{debitrowcount} > 2) {
-    for $i (2 .. $form->{debitrowcount}) {
-      map {
-        if ($form->{"debitchartselected_$i"} eq $_->{accno}) {
-          $form->{"debitchartselected_$i"} = "$_->{accno}--$_->{taxkey_id}";
-        }
-      } @{ $form->{chart} };
-      map {
-        if ($form->{"taxchartselected_$i"} eq $_->{taxkey}) {
-          $form->{"taxchartselected_$i"} = "$_->{taxkey}--$_->{rate}";
-        }
-      } @{ $form->{TAX} };
-    }
-  }
-  map {
-    $chart .=
-      "<option value=\"$_->{accno}--$_->{taxkey_id}\">$_->{accno}--$_->{description}</option>"
-  } @{ $form->{chart} };
-  $form->{chart} = $chart;
-  map {
-    $tax .=
-      qq|<option value="$_->{taxkey}--$_->{rate}">$_->{taxdescription}  |
-      . ($_->{rate} * 100) . qq| %|
-  } @{ $form->{TAX} };
-  $form->{taxchart} = $tax;
-
-  if ($form->{tax} < 0) {
-    $form->{tax} = $form->{tax} * (-1);
-  }
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+
+  GL->transaction(\%myconfig, \%$form);
 
   $form->{amount} = $form->format_amount(\%myconfig, $form->{amount}, 2);
 
   # departments
   $form->all_departments(\%myconfig);
-  if (@{ $form->{all_departments} }) {
+  if (@{ $form->{all_departments} || [] }) {
     $form->{selectdepartment} = "<option>\n";
 
     map {
       $form->{selectdepartment} .=
         "<option>$_->{description}--$_->{id}\n"
-    } (@{ $form->{all_departments} });
+    } (@{ $form->{all_departments} || [] });
   }
 
-  $form->{locked} =
-    ($form->datetonum($form->{transdate}, \%myconfig) <=
-     $form->datetonum($form->{closedto}, \%myconfig));
-
-  $form->{title} = "Edit";
+  my $i        = 1;
+  my $tax      = 0;
+  my $taxaccno = "";
+  foreach my $ref (@{ $form->{GL} }) {
+    my $j = $i - 1;
+    if ($tax && ($ref->{accno} eq $taxaccno)) {
+      $form->{"tax_$j"}      = abs($ref->{amount});
+      $form->{"taxchart_$j"} = $ref->{id} . "--" . $ref->{taxrate};
+      if ($form->{taxincluded}) {
+        if ($ref->{amount} < 0) {
+          $form->{"debit_$j"} += $form->{"tax_$j"};
+        } else {
+          $form->{"credit_$j"} += $form->{"tax_$j"};
+        }
+      }
+      $form->{"project_id_$j"} = $ref->{project_id};
 
-  &form_header;
+    } else {
+      $form->{"accno_$i"} = "$ref->{accno}--$ref->{tax_id}";
+      for (qw(fx_transaction source memo)) { $form->{"${_}_$i"} = $ref->{$_} }
+      if ($ref->{amount} < 0) {
+        $form->{totaldebit} -= $ref->{amount};
+        $form->{"debit_$i"} = $ref->{amount} * -1;
+      } else {
+        $form->{totalcredit} += $ref->{amount};
+        $form->{"credit_$i"} = $ref->{amount};
+      }
+      $form->{"taxchart_$i"} = "0--0.00";
+      $form->{"project_id_$i"} = $ref->{project_id};
+      $i++;
+    }
+    if ($ref->{taxaccno} && !$tax) {
+      $taxaccno = $ref->{taxaccno};
+      $tax      = 1;
+    } else {
+      $taxaccno = "";
+      $tax      = 0;
+    }
+  }
 
-  &form_footer;
+  $form->{rowcount} = $i;
+  $form->{locked}   =
+    ($form->datetonum($form->{transdate}, \%myconfig) <=
+     $form->datetonum($form->{closedto}, \%myconfig));
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
-sub search {
-  $lxdebug->enter_sub();
+sub edit {
+  $main::lxdebug->enter_sub();
 
-  $form->{title} = $locale->text('Buchungsjournal');
+  $main::auth->assert('general_ledger');
 
-  $form->all_departments(\%myconfig);
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
 
-  # departments
-  if (@{ $form->{all_departments} }) {
-    $form->{selectdepartment} = "<option>\n";
+  prepare_transaction();
 
-    map {
-      $form->{selectdepartment} .=
-        "<option>$_->{description}--$_->{id}\n"
-    } (@{ $form->{all_departments} });
-  }
+  $form->{title} = "Edit";
 
-  $department = qq|
-       <tr>
-         <th align=right nowrap>| . $locale->text('Department') . qq|</th>
-         <td colspan=3><select name=department>$form->{selectdepartment}</select></td>
-       </tr>
-| if $form->{selectdepartment};
-
-  # use JavaScript Calendar or not
-  $form->{jsscript} = $jscalendar;
-  $jsscript = "";
-  if ($form->{jsscript}) {
-
-    # with JavaScript Calendar
-    $button1 = qq|
-       <td><input name=datefrom id=datefrom size=11 title="$myconfig{dateformat}">
-       <input type=button name=datefrom id="trigger1" value=|
-      . $locale->text('button')
-      . qq|></td>
-       |;
-    $button2 = qq|
-       <td><input name=dateto id=dateto size=11 title="$myconfig{dateformat}">
-       <input type=button name=dateto id="trigger2" value=|
-      . $locale->text('button')
-      . qq|></td>
-     |;
-
-    #write Trigger
-    $jsscript =
-      Form->write_trigger(\%myconfig, "2", "datefrom", "BR", "trigger1",
-                          "dateto", "BL", "trigger2");
-  } else {
+  $form->{show_details} = $myconfig{show_form_details} unless defined $form->{show_details};
 
-    # without JavaScript Calendar
-    $button1 =
-      qq|<td><input name=datefrom id=datefrom size=11 title="$myconfig{dateformat}"></td>|;
-    $button2 =
-      qq|<td><input name=dateto id=dateto size=11 title="$myconfig{dateformat}"></td>|;
-  }
+  form_header();
+  display_rows();
+  form_footer();
 
-  $form->header;
+  $main::lxdebug->leave_sub();
+}
 
-  print qq|
-<body>
 
-<form method=post action=$form->{script}>
+sub search {
+  $::lxdebug->enter_sub;
+  $::auth->assert('general_ledger');
+
+  $::form->all_departments(\%::myconfig);
+  $::form->get_lists(
+    projects  => { key => "ALL_PROJECTS", all => 1 },
+  );
+  $::form->{ALL_EMPLOYEES} = SL::DB::Manager::Employee->get_all(query => [ deleted => 0 ]);
+
+  my $onload = "focus()"
+             . qq|;setupDateFormat('|. $::myconfig{dateformat} . qq|', '| . $::locale->text("Falsches Datumsformat!") . qq|')|
+             . qq|;setupPoints('|. $::myconfig{numberformat} .   qq|', '| . $::locale->text("wrongformat") . qq|')|;
+
+  $::form->header;
+  print $::form->parse_html_template('gl/search', {
+    onload => $onload,
+    department_label => sub { ("$_[0]{description}--$_[0]{id}")x2 },
+    employee_label => sub { "$_[0]{id}--$_[0]{name}" },
+  });
+
+  $::lxdebug->leave_sub;
+}
 
-<input type=hidden name=sort value=transdate>
+sub create_subtotal_row {
+  $main::lxdebug->enter_sub();
 
-<table width=100%>
-  <tr>
-    <th class=listtop>$form->{title}</th>
-  </tr>
-  <tr height="5"></tr>
-  <tr>
-    <td>
-      <table>
-       <tr>
-         <th align=right>| . $locale->text('Reference') . qq|</th>
-         <td><input name=reference size=20></td>
-         <th align=right>| . $locale->text('Source') . qq|</th>
-         <td><input name=source size=20></td>
-       </tr>
-       $department
-       <tr>
-         <th align=right>| . $locale->text('Description') . qq|</th>
-         <td colspan=3><input name=description size=40></td>
-       </tr>
-       <tr>
-         <th align=right>| . $locale->text('Notes') . qq|</th>
-         <td colspan=3><input name=notes size=40></td>
-       </tr>
-       <tr>
-         <th align=right>| . $locale->text('From') . qq|</th>
-          $button1
-          $button2
-       </tr>
-       <tr>
-         <th align=right>| . $locale->text('Include in Report') . qq|</th>
-         <td colspan=3>
-           <table>
-             <tr>
-               <td>
-                 <input name="category" class=radio type=radio value=X checked>&nbsp;|
-    . $locale->text('All') . qq|
-                 <input name="category" class=radio type=radio value=A>&nbsp;|
-    . $locale->text('Asset') . qq|
-                         <input name="category" class=radio type=radio value=L>&nbsp;|
-    . $locale->text('Liability') . qq|
-                 <input name="category" class=radio type=radio value=I>&nbsp;|
-    . $locale->text('Revenue') . qq|
-                 <input name="category" class=radio type=radio value=E>&nbsp;|
-    . $locale->text('Expense') . qq|
-               </td>
-             </tr>
-             <tr>
-               <table>
-                 <tr>
-                   <td align=right><input name="l_id" class=checkbox type=checkbox value=Y></td>
-                   <td>| . $locale->text('ID') . qq|</td>
-                   <td align=right><input name="l_transdate" class=checkbox type=checkbox value=Y checked></td>
-                   <td>| . $locale->text('Date') . qq|</td>
-                   <td align=right><input name="l_reference" class=checkbox type=checkbox value=Y checked></td>
-                   <td>| . $locale->text('Reference') . qq|</td>
-                   <td align=right><input name="l_description" class=checkbox type=checkbox value=Y checked></td>
-                   <td>| . $locale->text('Description') . qq|</td>
-                   <td align=right><input name="l_notes" class=checkbox type=checkbox value=Y></td>
-                   <td>| . $locale->text('Notes') . qq|</td>
-                 </tr>
-                 <tr>
-                   <td align=right><input name="l_debit" class=checkbox type=checkbox value=Y checked></td>
-                   <td>| . $locale->text('Debit') . qq|</td>
-                   <td align=right><input name="l_credit" class=checkbox type=checkbox value=Y checked></td>
-                   <td>| . $locale->text('Credit') . qq|</td>
-                   <td align=right><input name="l_source" class=checkbox type=checkbox value=Y checked></td>
-                   <td>| . $locale->text('Source') . qq|</td>
-                   <td align=right><input name="l_accno" class=checkbox type=checkbox value=Y checked></td>
-                   <td>| . $locale->text('Account') . qq|</td>
-                   <td align=right><input name="l_gifi_accno" class=checkbox type=checkbox value=Y></td>
-                   <td>| . $locale->text('GIFI') . qq|</td>
-                 </tr>
-                 <tr>
-                   <td align=right><input name="l_subtotal" class=checkbox type=checkbox value=Y></td>
-                   <td>| . $locale->text('Subtotal') . qq|</td>
-                 </tr>
-               </table>
-             </tr>
-           </table>
-       </tr>
-      </table>
-    </td>
-  </tr>
-  <tr>
-    <td><hr size=3 noshade></td>
-  </tr>
-</table>
+  my ($totals, $columns, $column_alignment, $subtotal_columns, $class) = @_;
 
-$jsscript
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
 
-<input type=hidden name=nextsub value=generate_report>
+  my $row = { map { $_ => { 'data' => '', 'class' => $class, 'align' => $column_alignment->{$_}, } } @{ $columns } };
 
-<input type=hidden name=path value=$form->{path}>
-<input type=hidden name=login value=$form->{login}>
-<input type=hidden name=password value=$form->{password}>
+  map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $totals->{$_}, 2) } @{ $subtotal_columns };
 
-<br>
-<input class=submit type=submit name=action value="|
-    . $locale->text('Continue') . qq|">
-</form>
+  map { $totals->{$_} = 0 } @{ $subtotal_columns };
 
-</body>
-</html>
-|;
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
+
+  return $row;
 }
 
 sub generate_report {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
 
-  $form->{sort} = "transdate" unless $form->{sort};
+  $main::auth->assert('general_ledger');
 
-  GL->all_transactions(\%myconfig, \%$form);
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $locale   = $main::locale;
 
-  $callback =
-    "$form->{script}?action=generate_report&path=$form->{path}&login=$form->{login}&password=$form->{password}";
+  # generate_report wird beim ersten Aufruf per Weiter-Knopf und POST mit der hidden Variablen sort mit Wert "datesort" (früher "transdate" als Defaultsortiervariable) übertragen
 
-  $href = $callback;
+  # <form method=post action=gl.pl>
+  # <input type=hidden name=sort value=datesort>    # form->{sort} setzen
+  # <input type=hidden name=nextsub value=generate_report>
 
-  %acctype = ('A' => $locale->text('Asset'),
-              'C' => $locale->text('Contra'),
-              'L' => $locale->text('Liability'),
-              'Q' => $locale->text('Equity'),
-              'I' => $locale->text('Revenue'),
-              'E' => $locale->text('Expense'),);
+  # anhand von neuer Variable datesort wird jetzt $form->{sort} auf transdate oder gldate gesetzt
+  # damit ist die Hidden Variable "sort" wahrscheinlich sogar überflüssig
 
-  $form->{title} = $locale->text('General Ledger');
+  # ändert man die Sortierreihenfolge per Klick auf eine der Überschriften wird die Variable "sort" per GET übergeben, z.B. id,transdate, gldate, ...
+  # gl.pl?action=generate_report&employee=18383--Jan%20B%c3%bcren&datesort=transdate&category=X&l_transdate=Y&l_gldate=Y&l_id=Y&l_reference=Y&l_description=Y&l_source=Y&l_debit=Y&l_credit=Y&sort=gldate&sortdir=0
 
-  $ml = ($form->{ml} =~ /(A|E)/) ? -1 : 1;
+  if ( $form->{sort} eq 'datesort' ) {   # sollte bei einem Post (Aufruf aus Suchmaske) immer wahr sein
+      # je nachdem ob in Suchmaske "transdate" oder "gldate" ausgesucht wurde erstes Suchergebnis entsprechend sortieren
+      $form->{sort} = $form->{datesort};
+  };
 
-  unless ($form->{category} eq 'X') {
-    $form->{title} .= " : " . $locale->text($acctype{ $form->{category} });
-  }
-  if ($form->{accno}) {
-    $href .= "&accno=" . $form->escape($form->{accno});
-    $callback .= "&accno=" . $form->escape($form->{accno}, 1);
-    $option =
-      $locale->text('Account')
-      . " : $form->{accno} $form->{account_description}";
-  }
-  if ($form->{gifi_accno}) {
-    $href     .= "&gifi_accno=" . $form->escape($form->{gifi_accno});
-    $callback .= "&gifi_accno=" . $form->escape($form->{gifi_accno}, 1);
-    $option   .= "\n<br>" if $option;
-    $option   .=
-      $locale->text('GIFI')
-      . " : $form->{gifi_accno} $form->{gifi_account_description}";
-  }
-  if ($form->{source}) {
-    $href     .= "&source=" . $form->escape($form->{source});
-    $callback .= "&source=" . $form->escape($form->{source}, 1);
-    $option   .= "\n<br>" if $option;
-    $option   .= $locale->text('Source') . " : $form->{source}";
-  }
-  if ($form->{reference}) {
-    $href     .= "&reference=" . $form->escape($form->{reference});
-    $callback .= "&reference=" . $form->escape($form->{reference}, 1);
-    $option   .= "\n<br>" if $option;
-    $option   .= $locale->text('Reference') . " : $form->{reference}";
-  }
-  if ($form->{department}) {
-    $href .= "&department=" . $form->escape($form->{department});
-    $callback .= "&department=" . $form->escape($form->{department}, 1);
-    ($department) = split /--/, $form->{department};
-    $option .= "\n<br>" if $option;
-    $option .= $locale->text('Department') . " : $department";
-  }
+  # was passiert hier?
+  report_generator_set_default_sort("$form->{datesort}", 1);
+#  report_generator_set_default_sort('transdate', 1);
 
-  if ($form->{description}) {
-    $href     .= "&description=" . $form->escape($form->{description});
-    $callback .= "&description=" . $form->escape($form->{description}, 1);
-    $option   .= "\n<br>" if $option;
-    $option   .= $locale->text('Description') . " : $form->{description}";
-  }
-  if ($form->{notes}) {
-    $href     .= "&notes=" . $form->escape($form->{notes});
-    $callback .= "&notes=" . $form->escape($form->{notes}, 1);
-    $option   .= "\n<br>" if $option;
-    $option   .= $locale->text('Notes') . " : $form->{notes}";
-  }
+  GL->all_transactions(\%myconfig, \%$form);
 
-  if ($form->{datefrom}) {
-    $href     .= "&datefrom=$form->{datefrom}";
-    $callback .= "&datefrom=$form->{datefrom}";
-    $option   .= "\n<br>" if $option;
-    $option   .=
-        $locale->text('From') . " "
-      . $locale->date(\%myconfig, $form->{datefrom}, 1);
-  }
-  if ($form->{dateto}) {
-    $href     .= "&dateto=$form->{dateto}";
-    $callback .= "&dateto=$form->{dateto}";
-    if ($form->{datefrom}) {
-      $option .= " ";
-    } else {
-      $option .= "\n<br>" if $option;
-    }
-    $option .=
-        $locale->text('Bis') . " "
-      . $locale->date(\%myconfig, $form->{dateto}, 1);
+  my %acctype = ('A' => $locale->text('Asset'),
+                 'C' => $locale->text('Contra'),
+                 'L' => $locale->text('Liability'),
+                 'Q' => $locale->text('Equity'),
+                 'I' => $locale->text('Revenue'),
+                 'E' => $locale->text('Expense'),);
+
+  $form->{title} = $locale->text('Journal');
+  if ($form->{category} ne 'X') {
+    $form->{title} .= " : " . $locale->text($acctype{ $form->{category} });
   }
 
-  @columns =
-    $form->sort_columns(
-    qw(transdate id reference description notes source debit debit_accno credit credit_accno debit_tax debit_tax_accno credit_tax credit_tax_accno accno gifi_accno)
-    );
+  $form->{landscape} = 1;
 
-  if ($form->{accno} || $form->{gifi_accno}) {
-    @columns = grep !/(accno|gifi_accno)/, @columns;
-    push @columns, "balance";
-    $form->{l_balance} = "Y";
+  my $ml = ($form->{ml} =~ /(A|E|Q)/) ? -1 : 1;
+
+  my @columns = qw(
+    gldate         transdate        id             reference      description
+    notes          source           debit          debit_accno
+    credit         credit_accno     debit_tax      debit_tax_accno
+    credit_tax     credit_tax_accno projectnumbers balance employee
+  );
+
+  # add employee here, so that variable is still known and passed in url when choosing a different sort order in resulting table
+  my @hidden_variables = qw(accno source reference department description notes project_id datefrom dateto employee datesort category l_subtotal);
+  push @hidden_variables, map { "l_${_}" } @columns;
+  foreach ( @hidden_variables ) {
+      print URL "$_\n";
+  };
+
+  my (@options, @date_options);
+  push @options,      $locale->text('Account')     . " : $form->{accno} $form->{account_description}" if ($form->{accno});
+  push @options,      $locale->text('Source')      . " : $form->{source}"                             if ($form->{source});
+  push @options,      $locale->text('Reference')   . " : $form->{reference}"                          if ($form->{reference});
+  push @options,      $locale->text('Description') . " : $form->{description}"                        if ($form->{description});
+  push @options,      $locale->text('Notes')       . " : $form->{notes}"                              if ($form->{notes});
+  push @options,      $locale->text('Employee')       . " : $form->{employee_name}"                              if ($form->{employee_name});
+  my $datesorttext = $form->{datesort} eq 'transdate' ? $locale->text('Invoice Date') :  $locale->text('Booking Date');
+  push @date_options,      "$datesorttext"                              if ($form->{datesort} and ($form->{datefrom} or $form->{dateto}));
+  push @date_options, $locale->text('From'), $locale->date(\%myconfig, $form->{datefrom}, 1)          if ($form->{datefrom});
+  push @date_options, $locale->text('Bis'),  $locale->date(\%myconfig, $form->{dateto},   1)          if ($form->{dateto});
+  push @options,      join(' ', @date_options)                                                        if (scalar @date_options);
 
+  if ($form->{department}) {
+    my ($department) = split /--/, $form->{department};
+    push @options, $locale->text('Department') . " : $department";
   }
 
-  $form->{l_credit_accno}     = "Y";
-  $form->{l_debit_accno}      = "Y";
-  $form->{l_credit_tax}       = "Y";
-  $form->{l_debit_tax}        = "Y";
-  $form->{l_credit_tax_accno} = "Y";
-  $form->{l_debit_tax_accno}  = "Y";
-  $form->{l_accno}            = "N";
-  foreach $item (@columns) {
-    if ($form->{"l_$item"} eq "Y") {
-      push @column_index, $item;
-
-      # add column to href and callback
-      $callback .= "&l_$item=Y";
-      $href     .= "&l_$item=Y";
-    }
-  }
 
-  if ($form->{l_subtotal} eq 'Y') {
-    $callback .= "&l_subtotal=Y";
-    $href     .= "&l_subtotal=Y";
+  my $callback = build_std_url('action=generate_report', grep { $form->{$_} } @hidden_variables);
+  print URL $callback;
+  close URL;
+
+  $form->{l_credit_accno}     = 'Y';
+  $form->{l_debit_accno}      = 'Y';
+  $form->{l_credit_tax}       = 'Y';
+  $form->{l_debit_tax}        = 'Y';
+#  $form->{l_gldate}           = 'Y';  # Spalte mit gldate immer anzeigen
+  $form->{l_credit_tax_accno} = 'Y';
+  $form->{l_datesort} = 'Y';
+  $form->{l_debit_tax_accno}  = 'Y';
+  $form->{l_balance}          = $form->{accno} ? 'Y' : '';
+
+  my %column_defs = (
+    'id'               => { 'text' => $locale->text('ID'), },
+    'transdate'        => { 'text' => $locale->text('Invoice Date'), },
+    'gldate'           => { 'text' => $locale->text('Booking Date'), },
+    'reference'        => { 'text' => $locale->text('Reference'), },
+    'source'           => { 'text' => $locale->text('Source'), },
+    'description'      => { 'text' => $locale->text('Description'), },
+    'notes'            => { 'text' => $locale->text('Notes'), },
+    'debit'            => { 'text' => $locale->text('Debit'), },
+    'debit_accno'      => { 'text' => $locale->text('Debit Account'), },
+    'credit'           => { 'text' => $locale->text('Credit'), },
+    'credit_accno'     => { 'text' => $locale->text('Credit Account'), },
+    'debit_tax'        => { 'text' => $locale->text('Debit Tax'), },
+    'debit_tax_accno'  => { 'text' => $locale->text('Debit Tax Account'), },
+    'credit_tax'       => { 'text' => $locale->text('Credit Tax'), },
+    'credit_tax_accno' => { 'text' => $locale->text('Credit Tax Account'), },
+    'balance'          => { 'text' => $locale->text('Balance'), },
+    'projectnumbers'   => { 'text' => $locale->text('Project Numbers'), },
+    'employee'         => { 'text' => $locale->text('Employee'), },
+  );
+
+  foreach my $name (qw(id transdate gldate reference description debit_accno credit_accno debit_tax_accno credit_tax_accno)) {
+    my $sortname                = $name =~ m/accno/ ? 'accno' : $name;
+    my $sortdir                 = $sortname eq $form->{sort} ? 1 - $form->{sortdir} : $form->{sortdir};
+    $column_defs{$name}->{link} = $callback . "&sort=$sortname&sortdir=$sortdir";
   }
 
-  $callback .= "&category=$form->{category}";
-  $href     .= "&category=$form->{category}";
-
-  $column_header{id} =
-      "<th><a class=listheading href=$href&sort=id>"
-    . $locale->text('ID')
-    . "</a></th>";
-  $column_header{transdate} =
-      "<th><a class=listheading href=$href&sort=transdate>"
-    . $locale->text('Date')
-    . "</a></th>";
-  $column_header{reference} =
-      "<th><a class=listheading href=$href&sort=reference>"
-    . $locale->text('Reference')
-    . "</a></th>";
-  $column_header{source} =
-      "<th><a class=listheading href=$href&sort=source>"
-    . $locale->text('Source')
-    . "</a></th>";
-  $column_header{description} =
-      "<th><a class=listheading href=$href&sort=description>"
-    . $locale->text('Description')
-    . "</a></th>";
-  $column_header{notes} =
-    "<th class=listheading>" . $locale->text('Notes') . "</th>";
-  $column_header{debit} =
-    "<th class=listheading>" . $locale->text('Debit') . "</th>";
-  $column_header{debit_accno} =
-      "<th><a class=listheading href=$href&sort=accno>"
-    . $locale->text('Debit Account')
-    . "</a></th>";
-  $column_header{credit} =
-    "<th class=listheading>" . $locale->text('Credit') . "</th>";
-  $column_header{credit_accno} =
-      "<th><a class=listheading href=$href&sort=accno>"
-    . $locale->text('Credit Account')
-    . "</a></th>";
-  $column_header{debit_tax} =
-      "<th><a class=listheading href=$href&sort=accno>"
-    . $locale->text('Debit Tax')
-    . "</a></th>";
-  $column_header{debit_tax_accno} =
-      "<th><a class=listheading href=$href&sort=accno>"
-    . $locale->text('Debit Tax Account')
-    . "</a></th>";
-  $column_header{credit_tax} =
-      "<th><a class=listheading href=$href&sort=accno>"
-    . $locale->text('Credit Tax')
-    . "</a></th>";
-  $column_header{credit_tax_accno} =
-      "<th><a class=listheading href=$href&sort=accno>"
-    . $locale->text('Credit Tax Account')
-    . "</a></th>";
-  $column_header{gifi_accno} =
-      "<th><a class=listheading href=$href&sort=gifi_accno>"
-    . $locale->text('GIFI')
-    . "</a></th>";
-  $column_header{balance} = "<th>" . $locale->text('Balance') . "</th>";
+  map { $column_defs{$_}->{visible} = $form->{"l_${_}"} ? 1 : 0 } @columns;
+  map { $column_defs{$_}->{visible} = 0 } qw(debit_accno credit_accno debit_tax_accno credit_tax_accno) if $form->{accno};
 
-  $form->{landscape} = 1;
+  my %column_alignment;
+  map { $column_alignment{$_}     = 'right'  } qw(balance id debit credit debit_tax credit_tax balance);
+  map { $column_alignment{$_}     = 'center' } qw(transdate gldate reference debit_accno credit_accno debit_tax_accno credit_tax_accno);
+  map { $column_alignment{$_}     = 'left' } qw(description source notes);
+  map { $column_defs{$_}->{align} = $column_alignment{$_} } keys %column_alignment;
 
-  $form->header;
+  my $report = SL::ReportGenerator->new(\%myconfig, $form);
 
-  print qq|
-<body>
+  $report->set_columns(%column_defs);
+  $report->set_column_order(@columns);
 
-<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%>
-       <thead>
-       <tr class=listheading>
-|;
+  $report->set_export_options('generate_report', @hidden_variables, qw(sort sortdir));
 
-  map { print "$column_header{$_}\n" } @column_index;
+  $report->set_sort_indicator($form->{sort} eq 'accno' ? 'debit_accno' : $form->{sort}, $form->{sortdir});
 
-  print "
-        </tr>
-        </thead>
-        </tfoot>
-        <tbody>
-";
+  $report->set_options('top_info_text'        => join("\n", @options),
+                       'output_format'        => 'HTML',
+                       'title'                => $form->{title},
+                       'attachment_basename'  => $locale->text('general_ledger_list') . strftime('_%Y%m%d', localtime time),
+    );
+  $report->set_options_from_form();
+  $locale->set_numberformat_wo_thousands_separator(\%myconfig) if lc($report->{options}->{output_format}) eq 'csv';
 
   # add sort to callback
-  $form->{callback} = "$callback&sort=$form->{sort}";
-  $callback = $form->escape($form->{callback});
-
-  # initial item for subtotals
-  if (@{ $form->{GL} }) {
-    $sameitem = $form->{GL}->[0]->{ $form->{sort} };
-  }
+  $form->{callback} = "$callback&sort=" . E($form->{sort}) . "&sortdir=" . E($form->{sortdir});
 
-  if (($form->{accno} || $form->{gifi_accno}) && $form->{balance}) {
 
-    map { $column_data{$_} = "<td>&nbsp;</td>" } @column_index;
-    $column_data{balance} =
-        "<td align=right>"
-      . $form->format_amount(\%myconfig, $form->{balance} * $ml, 2, 0)
-      . "</td>";
-
-    $i++;
-    $i %= 2;
-    print qq|
-        <tr class=listrow$i>
-|;
-    map { print "$column_data{$_}\n" } @column_index;
-
-    print qq|
-        </tr>
-|;
-  }
+  my @totals_columns = qw(debit credit debit_tax credit_tax);
+  my %subtotals      = map { $_ => 0 } @totals_columns;
+  my %totals         = map { $_ => 0 } @totals_columns;
+  my $idx            = 0;
 
-  foreach $ref (@{ $form->{GL} }) {
+  foreach my $ref (@{ $form->{GL} }) {
 
-    # if item ne sort print subtotal
-    if ($form->{l_subtotal} eq 'Y') {
-      if ($sameitem ne $ref->{ $form->{sort} }) {
-        &gl_subtotal;
-      }
-    }
-    foreach $key (sort keys(%{ $ref->{amount} })) {
-      $form->{balance} += $ref->{amount}{$key};
-    }
+    my %rows;
 
-    $debit = "";
-    foreach $key (sort keys(%{ $ref->{debit} })) {
-      $subtotaldebit += $ref->{debit}{$key};
-      $totaldebit    += $ref->{debit}{$key};
-      if ($key == 0) {
-        $debit = $form->format_amount(\%myconfig, $ref->{debit}{$key}, 2, 0);
-      } else {
-        $debit .=
-          "<br>" . $form->format_amount(\%myconfig, $ref->{debit}{$key}, 2, 0);
+    foreach my $key (qw(debit credit debit_tax credit_tax)) {
+      $rows{$key} = [];
+      foreach my $idx (sort keys(%{ $ref->{$key} })) {
+        my $value         = $ref->{$key}->{$idx};
+        $subtotals{$key} += $value;
+        $totals{$key}    += $value;
+        if ($key =~ /debit.*/) {
+          $ml = -1;
+        } else {
+          $ml = 1;
+        }
+        $form->{balance}  = $form->{balance} + $value * $ml;
+        push @{ $rows{$key} }, $form->format_amount(\%myconfig, $value, 2);
       }
     }
 
-    $credit = "";
-    foreach $key (sort keys(%{ $ref->{credit} })) {
-      $subtotalcredit += $ref->{credit}{$key};
-      $totalcredit    += $ref->{credit}{$key};
-      if ($key == 0) {
-        $credit = $form->format_amount(\%myconfig, $ref->{credit}{$key}, 2, 0);
-      } else {
-        $credit .= "<br>"
-          . $form->format_amount(\%myconfig, $ref->{credit}{$key}, 2, 0);
-      }
+    foreach my $key (qw(debit_accno credit_accno debit_tax_accno credit_tax_accno ac_transdate source)) {
+      my $col = $key eq 'ac_transdate' ? 'transdate' : $key;
+      $rows{$col} = [ map { $ref->{$key}->{$_} } sort keys(%{ $ref->{$key} }) ];
     }
 
-    $debittax = "";
-    foreach $key (sort keys(%{ $ref->{debit_tax} })) {
-      $subtotaldebittax += $ref->{debit_tax}{$key};
-      $totaldebittax    += $ref->{debit_tax}{$key};
-      if ($key == 0) {
-        $debittax =
-          $form->format_amount(\%myconfig, $ref->{debit_tax}{$key}, 2, 0);
-      } else {
-        $debittax .= "<br>"
-          . $form->format_amount(\%myconfig, $ref->{debit_tax}{$key}, 2, 0);
-      }
-    }
+    my $row = { };
+    map { $row->{$_} = { 'data' => '', 'align' => $column_alignment{$_} } } @columns;
 
-    $credittax = "";
-    foreach $key (sort keys(%{ $ref->{credit_tax} })) {
-      $subtotalcredittax += $ref->{credit_tax}{$key};
-      $totalcredittax    += $ref->{credit_tax}{$key};
-      if ($key == 0) {
-        $credittax =
-          $form->format_amount(\%myconfig, $ref->{credit_tax}{$key}, 2, 0);
-      } else {
-        $credittax .= "<br>"
-          . $form->format_amount(\%myconfig, $ref->{credit_tax}{$key}, 2, 0);
-      }
+    my $sh = "";
+    if ($form->{balance} < 0) {
+      $sh = " S";
+      $ml = -1;
+    } elsif ($form->{balance} > 0) {
+      $sh = " H";
+      $ml = 1;
     }
+    my $data = $form->format_amount(\%myconfig, ($form->{balance} * $ml), 2);
+    $data .= $sh;
 
-    $debitaccno  = "";
-    $debittaxkey = "";
-    $taxaccno    = "";
-    foreach $key (sort keys(%{ $ref->{debit_accno} })) {
-      if ($key == 0) {
-        $debitaccno =
-          "<a href=$href&accno=$ref->{accno}&callback=$callback>$ref->{debit_accno}{$key}</a>";
-      } else {
-        $debitaccno .=
-          "<br><a href=$href&accno=$ref->{accno}&callback=$callback>$ref->{debit_accno}{$key}</a>";
-      }
-      if ($ref->{debit_taxkey}{$key} eq $debittaxkey) {
-        $ref->{debit_tax_accno}{$key} = $taxaccno;
-      }
-      $taxaccno    = $ref->{debit_tax_accno}{$key};
-      $debittaxkey = $ref->{debit_taxkey}{$key};
-    }
+    $row->{balance}->{data}        = $data;
+    $row->{projectnumbers}->{data} = join ", ", sort { lc($a) cmp lc($b) } keys %{ $ref->{projectnumbers} };
 
-    $creditaccno  = "";
-    $credittaxkey = "";
-    $taxaccno     = "";
-    foreach $key (sort keys(%{ $ref->{credit_accno} })) {
-      if ($key == 0) {
-        $creditaccno =
-          "<a href=$href&accno=$ref->{accno}&callback=$callback>$ref->{credit_accno}{$key}</a>";
-      } else {
-        $creditaccno .=
-          "<br><a href=$href&accno=$ref->{accno}&callback=$callback>$ref->{credit_accno}{$key}</a>";
-      }
-      if ($ref->{credit_taxkey}{$key} eq $credittaxkey) {
-        $ref->{credit_tax_accno}{$key} = $taxaccno;
-      }
-      $taxaccno     = $ref->{credit_tax_accno}{$key};
-      $credittaxkey = $ref->{credit_taxkey}{$key};
-    }
+    map { $row->{$_}->{data} = $ref->{$_} } qw(id reference description notes gldate employee);
 
-    $debittaxaccno = "";
-    foreach $key (sort keys(%{ $ref->{debit_tax_accno} })) {
-      if ($key == 0) {
-        $debittaxaccno =
-          "<a href=$href&accno=$ref->{accno}&callback=$callback>$ref->{debit_tax_accno}{$key}</a>";
-      } else {
-        $debittaxaccno .=
-          "<br><a href=$href&accno=$ref->{accno}&callback=$callback>$ref->{debit_tax_accno}{$key}</a>";
-      }
-    }
+    map { $row->{$_}->{data} = \@{ $rows{$_} }; } qw(transdate debit credit debit_accno credit_accno debit_tax_accno credit_tax_accno source);
 
-    $credittaxaccno = "";
-    foreach $key (sort keys(%{ $ref->{credit_tax_accno} })) {
-      if ($key == 0) {
-        $credittaxaccno =
-          "<a href=$href&accno=$ref->{accno}&callback=$callback>$ref->{credit_tax_accno}{$key}</a>";
-      } else {
-        $credittaxaccno .=
-          "<br><a href=$href&accno=$ref->{accno}&callback=$callback>$ref->{credit_tax_accno}{$key}</a>";
-      }
+    foreach my $col (qw(debit_accno credit_accno debit_tax_accno credit_tax_accno)) {
+      $row->{$col}->{link} = [ map { "${callback}&accno=" . E($_) } @{ $rows{$col} } ];
     }
 
-    #    $ref->{debit} = $form->format_amount(\%myconfig, $ref->{debit}, 2, "&nbsp;");
-    #    $ref->{credit} = $form->format_amount(\%myconfig, $ref->{credit}, 2, "&nbsp;");
-
-    $column_data{id}        = "<td align=right>&nbsp;$ref->{id}&nbsp;</td>";
-    $column_data{transdate} =
-      "<td align=center>&nbsp;$ref->{transdate}&nbsp;</td>";
-    $column_data{reference} =
-      "<td align=center><a href=$ref->{module}.pl?action=edit&id=$ref->{id}&path=$form->{path}&login=$form->{login}&password=$form->{password}&callback=$callback>$ref->{reference}</td>";
-    $column_data{description} =
-      "<td align=center>$ref->{description}&nbsp;</td>";
-    $column_data{source}       = "<td align=center>$ref->{source}&nbsp;</td>";
-    $column_data{notes}        = "<td align=center>$ref->{notes}&nbsp;</td>";
-    $column_data{debit}        = "<td align=right>$debit</td>";
-    $column_data{debit_accno}  = "<td align=center>$debitaccno</td>";
-    $column_data{credit}       = "<td align=right>$credit</td>";
-    $column_data{credit_accno} = "<td align=center>$creditaccno</td>";
-    $column_data{debit_tax}    =
-      ($ref->{debit_tax_accno} ne "")
-      ? "<td align=right>$debittax</td>"
-      : "<td></td>";
-    $column_data{debit_tax_accno} = "<td align=center>$debittaxaccno</td>";
-    $column_data{gifi_accno}      =
-      "<td><a href=$href&gifi_accno=$ref->{gifi_accno}&callback=$callback>$ref->{gifi_accno}</a>&nbsp;</td>";
-    $column_data{credit_tax} =
-      ($ref->{credit_tax_accno} ne "")
-      ? "<td align=right>$credittax</td>"
-      : "<td></td>";
-    $column_data{credit_tax_accno} = "<td align=center>$credittaxaccno</td>";
-    $column_data{gifi_accno}       =
-      "<td><a href=$href&gifi_accno=$ref->{gifi_accno}&callback=$callback>$ref->{gifi_accno}</a>&nbsp;</td>";
-    $column_data{balance} =
-        "<td align=right>"
-      . $form->format_amount(\%myconfig, $form->{balance} * $ml, 2, 0)
-      . "</td>";
-
-    $i++;
-    $i %= 2;
-    print "
-        <tr class=listrow$i>";
-    map { print "$column_data{$_}\n" } @column_index;
-    print "</tr>";
-
-  }
+    map { $row->{$_}->{data} = \@{ $rows{$_} } if ($ref->{"${_}_accno"} ne "") } qw(debit_tax credit_tax);
 
-  &gl_subtotal if ($form->{l_subtotal} eq 'Y');
-
-  map { $column_data{$_} = "<td>&nbsp;</td>" } @column_index;
-
-  $column_data{debit} =
-    "<th align=right class=listtotal>"
-    . $form->format_amount(\%myconfig, $totaldebit, 2, "&nbsp;") . "</th>";
-  $column_data{credit} =
-    "<th align=right class=listtotal>"
-    . $form->format_amount(\%myconfig, $totalcredit, 2, "&nbsp;") . "</th>";
-  $column_data{debit_tax} =
-    "<th align=right class=listtotal>"
-    . $form->format_amount(\%myconfig, $totaldebittax, 2, "&nbsp;") . "</th>";
-  $column_data{credit_tax} =
-    "<th align=right class=listtotal>"
-    . $form->format_amount(\%myconfig, $totalcredittax, 2, "&nbsp;") . "</th>";
-  $column_data{balance} =
-    "<th align=right class=listtotal>"
-    . $form->format_amount(\%myconfig, $form->{balance} * $ml, 2, 0) . "</th>";
+    $row->{reference}->{link} = build_std_url("script=$ref->{module}.pl", 'action=edit', 'id=' . E($ref->{id}), 'callback');
 
-  print qq|
-       <tr class=listtotal>
-|;
+    my $row_set = [ $row ];
 
-  map { print "$column_data{$_}\n" } @column_index;
+    if ( ($form->{l_subtotal} eq 'Y' && !$form->{report_generator_csv_options_for_import} )
+        && (($idx == (scalar @{ $form->{GL} } - 1))
+            || ($ref->{ $form->{sort} } ne $form->{GL}->[$idx + 1]->{ $form->{sort} }))) {
+      push @{ $row_set }, create_subtotal_row(\%subtotals, \@columns, \%column_alignment, [ qw(debit credit) ], 'listsubtotal');
+    }
 
-  print qq|
-        </tr>
-        </tbody>
-      </table>
-    </td>
-  </tr>
-  <tr>
-    <td><hr size=3 noshade></td>
-  </tr>
-</table>
+    $report->add_data($row_set);
 
-<br>
+    $idx++;
+  }
 
-<form method=post action=$form->{script}>
+  # = 0 for balanced ledger
+  my $balanced_ledger = $totals{debit} + $totals{debit_tax} - $totals{credit} - $totals{credit_tax};
 
-<input name=callback type=hidden value="$form->{callback}">
+  my $row = create_subtotal_row(\%totals, \@columns, \%column_alignment, [ qw(debit credit debit_tax credit_tax) ], 'listtotal');
 
-<input type=hidden name=path value=$form->{path}>
-<input type=hidden name=login value=$form->{login}>
-<input type=hidden name=password value=$form->{password}>
+  my $sh = "";
+  if ($form->{balance} < 0) {
+    $sh = " S";
+    $ml = -1;
+  } elsif ($form->{balance} > 0) {
+    $sh = " H";
+    $ml = 1;
+  }
+  my $data = $form->format_amount(\%myconfig, ($form->{balance} * $ml), 2);
+  $data .= $sh;
+
+  $row->{balance}->{data}        = $data;
+    
+  if ( !$form->{report_generator_csv_options_for_import} ) {
+    $report->add_separator();
+    $report->add_data($row);
+  }
 
-<input class=submit type=submit name=action value="|
-    . $locale->text('GL Transaction') . qq|">
-<input class=submit type=submit name=action value="|
-    . $locale->text('AR Transaction') . qq|">
-<input class=submit type=submit name=action value="|
-    . $locale->text('AP Transaction') . qq|">
-<input class=submit type=submit name=action value="|
-    . $locale->text('Sales Invoice') . qq|">
-<input class=submit type=submit name=action value="|
-    . $locale->text('Vendor Invoice') . qq|">|;
+  my $raw_bottom_info_text;
 
-  if ($form->{menubar}) {
-    require "$form->{path}/menu.pl";
-    &menubar;
+  if (!$form->{accno} && (abs($balanced_ledger) >  0.001)) {
+    $raw_bottom_info_text .=
+        '<p><span class="unbalanced_ledger">'
+      . $locale->text('Unbalanced Ledger')
+      . ': '
+      . $form->format_amount(\%myconfig, $balanced_ledger, 3)
+      . '</span></p> ';
   }
 
-  print qq|
+  $raw_bottom_info_text .= $form->parse_html_template('gl/generate_report_bottom');
 
-</form>
+  $report->set_options('raw_bottom_info_text' => $raw_bottom_info_text);
 
-</body>
-</html>
-|;
+  $report->generate_with_headers();
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
-sub gl_subtotal {
-  $lxdebug->enter_sub();
+sub update {
+  $main::lxdebug->enter_sub();
 
-  $subtotaldebit =
-    $form->format_amount(\%myconfig, $subtotaldebit, 2, "&nbsp;");
-  $subtotalcredit =
-    $form->format_amount(\%myconfig, $subtotalcredit, 2, "&nbsp;");
+  $main::auth->assert('general_ledger');
 
-  map { $column_data{$_} = "<td>&nbsp;</td>" }
-    qw(transdate id reference source description accno);
-  $column_data{debit}  = "<th align=right>$subtotaldebit</td>";
-  $column_data{credit} = "<th align=right>$subtotalcredit</td>";
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
 
-  print "<tr class=listsubtotal>";
-  map { print "$column_data{$_}\n" } @column_index;
-  print "</tr>";
+  $form->{oldtransdate} = $form->{transdate};
 
-  $subtotaldebit  = 0;
-  $subtotalcredit = 0;
+  my @a           = ();
+  my $count       = 0;
+  my $debittax    = 0;
+  my $credittax   = 0;
+  my $debitcount  = 0;
+  my $creditcount = 0;
+  my ($debitcredit, $amount);
 
-  $sameitem = $ref->{ $form->{sort} };
+  my @flds =
+    qw(accno debit credit projectnumber fx_transaction source memo tax taxchart);
 
-  $lxdebug->leave_sub();
+  for my $i (1 .. $form->{rowcount}) {
 
-  return $sameitem;
-}
+    unless (($form->{"debit_$i"} eq "") && ($form->{"credit_$i"} eq "")) {
+      for (qw(debit credit tax)) {
+        $form->{"${_}_$i"} =
+          $form->parse_amount(\%myconfig, $form->{"${_}_$i"});
+      }
 
-sub update {
-  $lxdebug->enter_sub();
-
-  @a     = ();
-  $count = 0;
-  @flds  = (qw(accno debit credit projectnumber project_id oldprojectnumber));
-  $credit_save = $form->{credit};
-  $debit_save  = $form->{debit};
-
-  if ($form->{chart} eq "") {
-    $form->{creditchart} =
-      "<option>" . $form->{creditchartselected} . "</option>";
-    $form->{debitchart} =
-      "<option>" . $form->{debitchartselected} . "</option>";
-  } else {
-    $form->{creditchart} = $form->{chart};
-    $form->{creditchart} =~
-      s/value=\"$form->{creditchartselected}\"/value=\"$form->{creditchartselected}\" selected/;
+      push @a, {};
+      $debitcredit = ($form->{"debit_$i"} == 0) ? "0" : "1";
+      if ($debitcredit) {
+        $debitcount++;
+      } else {
+        $creditcount++;
+      }
 
-    $form->{debitchart} = $form->{chart};
-    $form->{debitchart} =~
-      s/value=\"$form->{debitchartselected}\"/value=\"$form->{debitchartselected}\" selected/;
-  }
-  ($debitaccno,  $debittaxkey)  = split(/--/, $form->{debitchartselected});
-  ($creditaccno, $credittaxkey) = split(/--/, $form->{creditchartselected});
-  if ($debittaxkey > 0) {
-    $form->{taxchart} = $form->unescape($form->{taxchart});
-    $form->{taxchart} =~ s/selected//ig;
-    $form->{taxchart} =~
-      s/\"$debittaxkey--([^\"]*)\"/\"$debittaxkey--$1\" selected/;
-
-    $rate = $1;
-
-    if ($form->{taxincluded}) {
-      $form->{debit} =
-        $form->parse_amount(\%myconfig, $form->{amount}) / ($rate + 1);
-      $form->{credit} = $form->parse_amount(\%myconfig, $form->{amount}) * 1;
-      $form->{tax} =
-        $form->parse_amount(\%myconfig, $form->{amount}) / ($rate + 1) * $rate;
-    } else {
-      $form->{debit} = $form->parse_amount(\%myconfig, $form->{amount}) * 1;
-      $form->{credit} =
-        $form->parse_amount(\%myconfig, $form->{amount}) * ($rate + 1);
-      $form->{tax} = $form->parse_amount(\%myconfig, $form->{amount}) * $rate;
-    }
-  } else {
-    $form->{taxchart} = $form->unescape($form->{taxchart});
-    $form->{taxchart} =~ s/selected//ig;
-    $form->{taxchart} =~
-      s/\"$credittaxkey--([^\"]*)\"/\"$credittaxkey--$1\" selected/;
-    $rate = $1;
-
-    if ($form->{taxincluded}) {
-      $form->{debit} = $form->parse_amount(\%myconfig, $form->{amount}) * 1;
-      $form->{credit} =
-        $form->parse_amount(\%myconfig, $form->{amount}) / ($rate + 1);
-      $form->{tax} =
-        $form->parse_amount(\%myconfig, $form->{amount}) / ($rate + 1) * $rate;
-    } else {
-      $form->{debit} =
-        $form->parse_amount(\%myconfig, $form->{amount}) * ($rate + 1);
-      $form->{credit} = $form->parse_amount(\%myconfig, $form->{amount}) * 1;
-      $form->{tax} = $form->parse_amount(\%myconfig, $form->{amount}) * $rate;
+      if (($debitcount >= 2) && ($creditcount == 2)) {
+        $form->{"credit_$i"} = 0;
+        $form->{"tax_$i"}    = 0;
+        $creditcount--;
+        $form->{creditlock} = 1;
+      }
+      if (($creditcount >= 2) && ($debitcount == 2)) {
+        $form->{"debit_$i"} = 0;
+        $form->{"tax_$i"}   = 0;
+        $debitcount--;
+        $form->{debitlock} = 1;
+      }
+      if (($creditcount == 1) && ($debitcount == 2)) {
+        $form->{creditlock} = 1;
+      }
+      if (($creditcount == 2) && ($debitcount == 1)) {
+        $form->{debitlock} = 1;
+      }
+      if ($debitcredit && $credittax) {
+        $form->{"taxchart_$i"} = "0--0.00";
+      }
+      if (!$debitcredit && $debittax) {
+        $form->{"taxchart_$i"} = "0--0.00";
+      }
+      $amount =
+        ($form->{"debit_$i"} == 0)
+        ? $form->{"credit_$i"}
+        : $form->{"debit_$i"};
+      my $j = $#a;
+      if (($debitcredit && $credittax) || (!$debitcredit && $debittax)) {
+        $form->{"taxchart_$i"} = "0--0.00";
+        $form->{"tax_$i"}      = 0;
+      }
+      my ($taxkey, $rate) = split(/--/, $form->{"taxchart_$i"});
+      if ($taxkey > 1) {
+        if ($debitcredit) {
+          $debittax = 1;
+        } else {
+          $credittax = 1;
+        }
+        if ($form->{taxincluded}) {
+          $form->{"tax_$i"} = $amount / ($rate + 1) * $rate;
+        } else {
+          $form->{"tax_$i"} = $amount * $rate;
+        }
+      } else {
+        $form->{"tax_$i"} = 0;
+      }
+
+      for (@flds) { $a[$j]->{$_} = $form->{"${_}_$i"} }
+      $count++;
     }
   }
-  if ($form->{credit_splited}) {
-    $form->{debit}  = $form->parse_amount(\%myconfig, $form->{amount}) * 1;
-    $form->{credit} = $credit_save;
-    $form->{tax}    = 0;
-  } elsif ($form->{debit_splited}) {
-    $form->{credit} = $form->parse_amount(\%myconfig, $form->{amount}) * 1;
-    $form->{debit}  = $debit_save;
-    $form->{tax}    = 0;
+
+  for my $i (1 .. $count) {
+    my $j = $i - 1;
+    for (@flds) { $form->{"${_}_$i"} = $a[$j]->{$_} }
+  }
+
+  for my $i ($count + 1 .. $form->{rowcount}) {
+    for (@flds) { delete $form->{"${_}_$i"} }
   }
-  &check_project;
+
+  $form->{rowcount} = $count + 1;
 
   &display_form;
+  $main::lxdebug->leave_sub();
 
-  $lxdebug->leave_sub();
 }
 
 sub display_form {
-  $lxdebug->enter_sub();
+  my ($init) = @_;
+  $main::lxdebug->enter_sub();
+
+  $main::auth->assert('general_ledger');
 
-  &form_header;
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+
+  &form_header($init);
 
   #   for $i (1 .. $form->{rowcount}) {
   #     $form->{totaldebit} += $form->parse_amount(\%myconfig, $form->{"debit_$i"});
@@ -991,376 +644,302 @@ sub display_form {
   #
   #     &form_row($i);
   #   }
-
+  &display_rows($init);
   &form_footer;
+  $main::lxdebug->leave_sub();
 
-  $lxdebug->leave_sub();
 }
 
-sub form_header {
-  $lxdebug->enter_sub();
-
-  $title         = $form->{title};
-  $form->{title} = $locale->text("$title General Ledger Transaction");
-  $readonly      = ($form->{id}) ? "readonly" : "";
+sub display_rows {
+  my ($init) = @_;
+  $main::lxdebug->enter_sub();
 
-  $form->{urldebit} =
-    "$form->{script}?action=split_debit&path=$form->{path}&login=$form->{login}&password=$form->{password}";
-  $form->{urlcredit} =
-    "$form->{script}?action=split_credit&path=$form->{path}&login=$form->{login}&password=$form->{password}";
+  $main::auth->assert('general_ledger');
 
-  # $locale->text('Add General Ledger Transaction')
-  # $locale->text('Edit General Ledger Transaction')
-  map { $form->{$_} =~ s/\"/&quot;/g } qw(reference description chart);
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $cgi      = $::request->{cgi};
 
-  $form->{selectdepartment} =~ s/ selected//;
-  $form->{taxchart}         =~ s/ selected//;
-  $form->{selectdepartment} =~
-    s/option>\Q$form->{department}\E/option selected>$form->{department}/;
+  $form->{debit_1}     = 0 if !$form->{"debit_1"};
+  $form->{totaldebit}  = 0;
+  $form->{totalcredit} = 0;
 
-  if (($rows = $form->numtextrows($form->{description}, 50)) > 1) {
-    $description =
-      qq|<textarea name=description rows=$rows cols=50 wrap=soft $readonly >$form->{description}</textarea>|;
-  } else {
-    $description =
-      qq|<input name=description size=50 value="$form->{description}" tabindex="3" $readonly>|;
+  my %project_labels = ();
+  my @project_values = ("");
+  foreach my $item (@{ $form->{"ALL_PROJECTS"} }) {
+    push(@project_values, $item->{"id"});
+    $project_labels{$item->{"id"}} = $item->{"projectnumber"};
   }
 
-  $taxincluded = ($form->{taxincluded}) ? "checked" : "";
+  my %chart_labels = ();
+  my @chart_values = ();
+  my %charts = ();
+  my $taxchart_init;
+  foreach my $item (@{ $form->{ALL_CHARTS} }) {
+    if ($item->{charttype} eq 'H'){ #falls überschrift
+      next;                         #überspringen (Bug 1150)
+    }
+    my $key = $item->{accno} . "--" . $item->{tax_id};
+    $taxchart_init = $item->{tax_id} unless (@chart_values);
+    push(@chart_values, $key);
+    $chart_labels{$key} = $item->{accno} . "--" . $item->{description};
+    $charts{$item->{accno}} = $item;
+  }
 
-  if (!$form->{id}) {
-    $taxincluded = "checked";
+  my %taxchart_labels = ();
+  my @taxchart_values = ();
+  my %taxcharts = ();
+  foreach my $item (@{ $form->{ALL_TAXCHARTS} }) {
+    my $key = $item->{id} . "--" . $item->{rate};
+    $taxchart_init = $key if ($taxchart_init == $item->{id});
+    push(@taxchart_values, $key);
+    $taxchart_labels{$key} = $item->{taxdescription} . " " . $item->{rate} * 100 . ' %';
+    $taxcharts{$item->{id}} = $item;
   }
 
-  $amount =
-    qq|<input name=amount size=20 value="$form->{amount}" tabindex="4" $readonly>|;
-
-  $department = qq|
-       <tr>
-         <th align=right nowrap>| . $locale->text('Department') . qq|</th>
-         <td colspan=3><select name=department>$form->{selectdepartment}</select></td>
-         <input type=hidden name=selectdepartment value="$form->{selectdepartment}">
-       </tr>
-| if $form->{selectdepartment};
-
-  $form->{fokus}  = "gl.reference";
-  $form->{remote} = 1;
-
-  # use JavaScript Calendar or not
-  $form->{jsscript} = $jscalendar;
-  $jsscript = "";
-  if ($form->{jsscript}) {
-
-    # with JavaScript Calendar
-    $button1 = qq|
-       <td><input name=transdate id=transdate size=11 title="$myconfig{dateformat}" value=$form->{transdate} tabindex="2" $readonly></td>
-       <td><input type=button name=transdate id="trigger1" value=|
-      . $locale->text('button')
-      . qq|></td>
-       |;
-
-    #write Trigger
-    $jsscript =
-      Form->write_trigger(\%myconfig, "1", "transdate", "BL", "trigger1", "",
-                          "", "");
-  } else {
+  my ($source, $memo, $source_hidden, $memo_hidden);
+  for my $i (1 .. $form->{rowcount}) {
+    if ($form->{show_details}) {
+      $source = qq|
+      <td><input name="source_$i" value="$form->{"source_$i"}" size="16"></td>|;
+      $memo = qq|
+      <td><input name="memo_$i" value="$form->{"memo_$i"}" size="16"></td>|;
+    } else {
+      $source_hidden = qq|
+      <input type="hidden" name="source_$i" value="$form->{"source_$i"}" size="16">|;
+      $memo_hidden = qq|
+      <input type="hidden" name="memo_$i" value="$form->{"memo_$i"}" size="16">|;
+    }
 
-    # without JavaScript Calendar
-    $button1 =
-      qq|<td><input name=transdate id=transdate size=11 title="$myconfig{dateformat}" value=$form->{transdate} tabindex="2" $readonly></td>|;
-  }
+    my $selected_accno_full;
+    my ($accno_row) = split(/--/, $form->{"accno_$i"});
+    my $item = $charts{$accno_row};
+    $selected_accno_full = "$item->{accno}--$item->{tax_id}";
 
-  $form->header;
+    my $selected_taxchart = $form->{"taxchart_$i"};
+    my ($selected_accno, $selected_tax_id) = split(/--/, $selected_accno_full);
+    my ($previous_accno, $previous_tax_id) = split(/--/, $form->{"previous_accno_$i"});
 
-  print qq|
-<body onLoad="fokus()">
+    if ($previous_accno &&
+        ($previous_accno eq $selected_accno) &&
+        ($previous_tax_id ne $selected_tax_id)) {
+      my $item = $taxcharts{$selected_tax_id};
+      $selected_taxchart = "$item->{id}--$item->{rate}";
+    }
 
-<form method=post name="gl" action=$form->{script}>
+    $selected_accno      = '' if ($init);
+    $selected_taxchart ||= $taxchart_init;
+
+    my $accno = qq|<td>| .
+      NTI($cgi->popup_menu('-name' => "accno_$i",
+                           '-id' => "accno_$i",
+                           '-onChange' => "setTaxkey($i)",
+                           '-style' => 'width:200px',
+                           '-values' => \@chart_values,
+                           '-labels' => \%chart_labels,
+                           '-default' => $selected_accno_full))
+      . $cgi->hidden('-name' => "previous_accno_$i",
+                     '-default' => $selected_accno_full)
+      . qq|</td>|;
+    my $tax_ddbox = qq|<td>| .
+      NTI($cgi->popup_menu('-name' => "taxchart_$i",
+                           '-id' => "taxchart_$i",
+                           '-style' => 'width:200px',
+                           '-values' => \@taxchart_values,
+                           '-labels' => \%taxchart_labels,
+                           '-default' => $selected_taxchart))
+      . qq|</td>|;
+
+    my ($fx_transaction, $checked);
+    if ($init) {
+      if ($form->{transfer}) {
+        $fx_transaction = qq|
+        <td><input name="fx_transaction_$i" class=checkbox type=checkbox value=1></td>
+    |;
+      }
 
-<input name=id type=hidden value=$form->{id}>
+    } else {
+      if ($form->{"debit_$i"} != 0) {
+        $form->{totaldebit} += $form->{"debit_$i"};
+        if (!$form->{taxincluded}) {
+          $form->{totaldebit} += $form->{"tax_$i"};
+        }
+      } else {
+        $form->{totalcredit} += $form->{"credit_$i"};
+        if (!$form->{taxincluded}) {
+          $form->{totalcredit} += $form->{"tax_$i"};
+        }
+      }
 
-<input type=hidden name=closedto value=$form->{closedto}>
-<input type=hidden name=locked value=$form->{locked}>
-<input type=hidden name=title value="$title">
-<input type=hidden name=taxchart value=|
-    . $form->escape($form->{taxchart}) . qq|>
-<input type=hidden name=chart value="$form->{chart}">
-<input type=hidden name=creditrowcount value="$form->{creditrowcount}">
-<input type=hidden name=debitrowcount value="$form->{debitrowcount}">
+      for (qw(debit credit tax)) {
+        $form->{"${_}_$i"} =
+          ($form->{"${_}_$i"})
+          ? $form->format_amount(\%myconfig, $form->{"${_}_$i"}, 2)
+          : "";
+      }
 
+      if ($i < $form->{rowcount}) {
+        if ($form->{transfer}) {
+          $checked = ($form->{"fx_transaction_$i"}) ? "1" : "";
+          my $x = ($checked) ? "x" : "";
+          $fx_transaction = qq|
+      <td><input type=hidden name="fx_transaction_$i" value="$checked">$x</td>
+    |;
+        }
+        $form->hide_form("accno_$i");
 
-<table width=100%>
-  <tr>
-    <th class=listtop>$form->{title}</th>
-  </tr>
-  <tr height="5"></tr>
-  <tr>
-    <td>
-      <table width=100%>
-       <tr>
-         <th align=right>| . $locale->text('Reference') . qq|</th>
-         <td><input name=reference size=20 value="$form->{reference}" tabindex="1" $readonly></td>
-         <td align=left>
-           <table width=100%>
-             <tr>
-               <th align=right nowrap>| . $locale->text('Date') . qq|</th>
-                $button1
-             </tr>
-           </table>
-         </td>
-       </tr>|;
-  if ($form->{id}) {
-    print qq|
-       <tr>
-         <th align=right>| . $locale->text('Belegnummer') . qq|</th>
-         <td><input name=id size=20 value="$form->{id}" $readonly></td>
-         <td align=left>
-         <table width=100%>
-             <tr>
-               <th align=right width=50%>| . $locale->text('Buchungsdatum') . qq|</th>
-               <td align=left><input name=gldate size=11 title="$myconfig{dateformat}" value=$form->{gldate} $readonly></td>
-             </tr>
-           </table>
-         </td>
-       </tr>|;
-  }
-  print qq|
-       $department|;
-  if ($form->{id}) {
-    print qq|
-       <tr>
-         <th align=right>| . $locale->text('Description') . qq|</th>
-         <td>$description</td>
-         <td align=left>
-           <table width=100%>
-             <tr>
-               <th align=right width=50%>| . $locale->text('Mitarbeiter') . qq|</th>
-               <td align=left><input name=employee size=11  value=$form->{employee} $readonly></td>
-             </tr>
-           </table>
-         </td>
-       </tr>|;
-  } else {
-    print qq|
-       <tr>
-         <th align=right>| . $locale->text('Description') . qq|</th>
-         <td colspan=3>$description</td>
-       </tr>|;
-  }
-  print qq|
-       <tr>
-         <th align=right>| . $locale->text('Betrag') . qq|</th>
-         <td>$amount</td>
-         <td align=left colspan=2>
-           <table>
-             <tr>
-               <th align=left>| . $locale->text('MwSt. inkl.') . qq|</th>
-               <td><input type=checkbox name=taxincluded value=1 tabindex="8" $taxincluded></td>
-             </tr>
-           </table>
-        </td>
-       </tr>|;
-  if ($form->{debit_splited}) {
-    print qq|
-       <tr>
-         <th align=right>| . $locale->text('Debit') . qq|</th>
-         <td>Betrag gesplittet</td>
-         <td><input  name=debit size=10 value="|
-      . $form->format_amount(\%myconfig, $form->{debit}, 2)
-      . qq|" readonly> EUR</td>
-          <td><input class=submit type=submit name=action value="|
-      . $locale->text('Split Debit')
-      . qq|"></td>
-          <input  name=debit_splited type=hidden size=10 value=$form->{debit_splited}>
-       </tr>
-        <tr>
-          <th align=right>| . $locale->text('Credit') . qq|</th>
-         <td><select name=creditchartselected tabindex="6">$form->{creditchart}</select></td>
-         <td><input name=credit size=10 value="|
-      . $form->format_amount(\%myconfig, $form->{credit}, 2)
-      . qq|" readonly > EUR</td>
-          <input  name=credit_splited type=hidden size=10 value=$form->{credit_splited}>
-        </tr>
-        |;
-  } elsif ($form->{credit_splited}) {
+      } else {
+        if ($form->{transfer}) {
+          $fx_transaction = qq|
+      <td><input name="fx_transaction_$i" class=checkbox type=checkbox value=1></td>
+    |;
+        }
+      }
+    }
+    my $debitreadonly  = "";
+    my $creditreadonly = "";
+    if ($i == $form->{rowcount}) {
+      if ($form->{debitlock}) {
+        $debitreadonly = "readonly";
+      } elsif ($form->{creditlock}) {
+        $creditreadonly = "readonly";
+      }
+    }
+
+    my $projectnumber =
+      NTI($cgi->popup_menu('-name' => "project_id_$i",
+                           '-values' => \@project_values,
+                           '-labels' => \%project_labels,
+                           '-default' => $form->{"project_id_$i"} ));
+    my $projectnumber_hidden = qq|
+    <input type="hidden" name="project_id_$i" value="$form->{"project_id_$i"}">|;
+
+    my $copy2credit = $i == 1 ? 'onkeyup="copy_debit_to_credit()"' : '';
+
+    print qq|<tr valign=top>
+    $accno
+    <td id="chart_balance_$i" align="right">&nbsp;</td>
+    $fx_transaction
+    <td><input name="debit_$i" size="8" value="$form->{"debit_$i"}" accesskey=$i $copy2credit $debitreadonly></td>
+    <td><input name="credit_$i" size=8 value="$form->{"credit_$i"}" $creditreadonly></td>
+    <td><input type="hidden" name="tax_$i" value="$form->{"tax_$i"}">$form->{"tax_$i"}</td>
+    $tax_ddbox|;
+
+    if ($form->{show_details}) {
+      print qq|
+    $source
+    $memo
+    <td>$projectnumber</td>
+|;
+    } else {
     print qq|
-          <tr>
-         <th align=right>| . $locale->text('Debit') . qq|</th>
-         <td><select name=debitchartselected tabindex="6">$form->{debitchart}</select></td>
-         <td><input  name=debit size=10 value="|
-      . $form->format_amount(\%myconfig, $form->{debit}, 2)
-      . qq|" readonly> EUR</td>
-          <input  name=debit_splited type=hidden size=10 value=$form->{debit_splited}>
-         </tr>
-          <tr>
-          <th align=right>| . $locale->text('Credit') . qq|</th>
-          <td>Betrag gesplittet</td>
-         <td><input name=credit size=10 value="|
-      . $form->format_amount(\%myconfig, $form->{credit}, 2)
-      . qq|" readonly > EUR</td>
-          <td><input class=submit type=submit name=action value="|
-      . $locale->text('Split Credit')
-      . qq|"></td>
-          <input  name=credit_splited type=hidden size=10 value=$form->{credit_splited}>
-          |;
-  } else {
+    $source_hidden
+    $memo_hidden
+    $projectnumber_hidden
+    |;
+    }
     print qq|
-          <tr>
-         <th align=right>| . $locale->text('Debit') . qq|</th>
-         <td><select name=debitchartselected tabindex="6">$form->{debitchart}</select></td>
-         <td><input  name=debit size=10 value="|
-      . $form->format_amount(\%myconfig, $form->{debit}, 2)
-      . qq|" readonly> EUR</td>
-          <td><input class=submit type=submit name=action value="|
-      . $locale->text('Split Debit')
-      . qq|"></td>
-          <input  name=debit_splited type=hidden size=10 value=$form->{debit_splited}>
-         </tr>
-          <tr>
-         <th align=right>| . $locale->text('Credit') . qq|</th>
-         <td><select name=creditchartselected tabindex="6">$form->{creditchart}</select></td>
-         <td><input name=credit size=10 value="|
-      . $form->format_amount(\%myconfig, $form->{credit}, 2)
-      . qq|" readonly > EUR</td>
-          <td><input class=submit type=submit name=action value="|
-      . $locale->text('Split Credit')
-      . qq|"></td>
-          <input  name=credit_splited type=hidden size=10 value=$form->{credit_splited}>
-         </tr>
-         <tr>
-         <th align=right>| . $locale->text('Tax') . qq|</th>
-         <td><select name=taxchartselected tabindex="7">$form->{taxchart}</select></td>
-         <td><input name=tax size=10 value="|
-      . $form->format_amount(\%myconfig, $form->{tax}, 2)
-      . qq|" readonly > EUR</td>
-          <td></td>
-         </tr>|;
-  }
-  print qq|
-       </tr>      </table>
-    </td>
-  </tr>
-  <tr>
-    <td><hr size=3 noshade></td>
   </tr>
-$jsscript
 |;
+  }
+
+  $form->hide_form(qw(rowcount selectaccno));
+
+  $main::lxdebug->leave_sub();
 
-  $lxdebug->leave_sub();
 }
 
-sub form_footer {
-  $lxdebug->enter_sub();
-  ($dec) = ($form->{totaldebit} =~ /\.(\d+)/);
-  $dec           = length $dec;
-  $decimalplaces = ($dec > 2) ? $dec : 2;
-  $taxrowcount   =
-    ($form->{creditrowcount} > $form->{debitrowcount})
-    ? $form->{creditrowcount}
-    : $form->{debitrowcount};
-  $radieren = ($form->current_date(\%myconfig) eq $form->{gldate}) ? 1 : 0;
-
-  map {
-    $form->{$_} =
-      $form->format_amount(\%myconfig, $form->{$_}, $decimalplaces, "&nbsp;")
-  } qw(totaldebit totalcredit);
+sub form_header {
+  $::lxdebug->enter_sub;
+  $::auth->assert('general_ledger');
 
-  print qq|
-</table>
-|;
-  for $i (2 .. $form->{creditrowcount}) {
-    print qq|
-    <input type=hidden name=creditchartselected_$i value="$form->{"creditchartselected_$i"}">
-    <input type=hidden name=credit_$i value="$form->{"credit_$i"}">
-    |;
-  }
-  for $i (2 .. $form->{debitrowcount}) {
-    print qq|
-    <input type=hidden name=debitchartselected_$i value="$form->{"debitchartselected_$i"}">
-    <input type=hidden name=debit_$i value="$form->{"debit_$i"}">
-    |;
-  }
-  if ($taxrowcount > 1) {
-    for $i (2 .. $taxrowcount) {
-      print qq|
-      <input type=hidden name=taxchartselected_$i value="$form->{"taxchartselected_$i"}">
-      <input type=hidden name=tax_$i value="$form->{"tax_$i"}">
-      |;
-    }
-  }
-  print qq|
-<input type=hidden name=path value=$form->{path}>
-<input type=hidden name=login value=$form->{login}>
-<input type=hidden name=password value=$form->{password}>
+  my ($init) = @_;
 
-<input name=callback type=hidden value="$form->{callback}">
-<br>
-|;
+  my @old_project_ids = grep { $_ } map{ $::form->{"project_id_$_"} } 1..$::form->{rowcount};
 
-  $transdate = $form->datetonum($form->{transdate}, \%myconfig);
-  $closedto  = $form->datetonum($form->{closedto},  \%myconfig);
+  $::form->get_lists("projects"  => { "key"       => "ALL_PROJECTS",
+                                    "all"       => 0,
+                                    "old_id"    => \@old_project_ids },
+                   "charts"    => { "key"       => "ALL_CHARTS",
+                                    "transdate" => $::form->{transdate} },
+                   "taxcharts" => "ALL_TAXCHARTS");
 
-  if ($form->{id}) {
+  GL->get_chart_balances('charts' => $::form->{ALL_CHARTS});
 
-    print qq|<input class=submit type=submit name=action value="|
-      . $locale->text('Storno') . qq|">|;
+  my $title      = $::form->{title};
+  $::form->{title} = $::locale->text("$title General Ledger Transaction");
+  # $locale->text('Add General Ledger Transaction')
+  # $locale->text('Edit General Ledger Transaction')
 
-    # Löschen und ändern von Buchungen nicht mehr möglich (GoB) nur am selben Tag möglich
+  map { $::form->{$_} =~ s/\"/&quot;/g }
+    qw(chart taxchart);
 
-    if (!$form->{locked} && $radieren) {
-      print qq|
-               <input class=submit type=submit name=action value="|
-        . $locale->text('Post')
-        . qq|" accesskey="b">
-               <input class=submit type=submit name=action value="|
-        . $locale->text('Delete') . qq|">|;
-    }
+  $::form->{selectdepartment} =~ s/ selected//;
+  $::form->{selectdepartment} =~
+    s/option>\Q$::form->{department}\E/option selected>$::form->{department}/;
 
-    #  if ($transdate > $closedto) {
-    #          print qq|
-    #          <input class=submit type=submit name=action value="|.$locale->text('Post as new').qq|">|;
-    #  }
+  if ($init) {
+    $::form->{fokus} = "gl.reference";
+    $::form->{taxincluded} = "1";
   } else {
-    if ($transdate > $closedto) {
-      print qq|<input class=submit type=submit name=action value="|
-        . $locale->text('Update') . qq|">
-                <input class=submit type=submit name=action value="|
-        . $locale->text('Post') . qq|">|;
-    }
+    $::form->{fokus} = qq|gl.accno_$::form->{rowcount}|;
   }
 
-  if ($form->{menubar}) {
-    require "$form->{path}/menu.pl";
-    &menubar;
+  $::form->{previous_id}     ||= "--";
+  $::form->{previous_gldate} ||= "--";
+
+  $::form->header;
+  print $::form->parse_html_template('gl/form_header', {
+    hide_title => $title,
+  });
+
+  $::lxdebug->leave_sub;
+
+}
+
+sub form_footer {
+  $::lxdebug->enter_sub;
+  $::auth->assert('general_ledger');
+
+  my ($follow_ups, $follow_ups_due);
+
+  if ($::form->{id}) {
+    $follow_ups     = FU->follow_ups('trans_id' => $::form->{id});
+    $follow_ups_due = sum map { $_->{due} * 1 } @{ $follow_ups || [] };
   }
 
-  print "
-  </form>
+  my $radieren = $::form->current_date(\%::myconfig) eq $::form->{gldate};
 
-</body>
-</html>
-";
+  print $::form->parse_html_template('gl/form_footer', {
+    radieren       => $radieren,
+    follow_ups     => $follow_ups,
+    follow_ups_due => $follow_ups_due,
+  });
 
-  $lxdebug->leave_sub();
+  $::lxdebug->leave_sub;
 }
 
 sub delete {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my $locale   = $main::locale;
 
   $form->header;
 
   print qq|
 <body>
 
-<form method=post action=$form->{script}>
+<form method=post action=gl.pl>
 |;
 
-  map { $form->{$_} =~ s/\"/&quot;/g } qw(reference description chart);
+  map { $form->{$_} =~ s/\"/&quot;/g } qw(reference description);
 
   delete $form->{header};
 
-  foreach $key (keys %$form) {
-    print qq|<input type=hidden name=$key value="$form->{$key}">\n|;
+  foreach my $key (keys %$form) {
+    next if (($key eq 'login') || ($key eq 'password') || ('' ne ref $form->{$key}));
+    print qq|<input type="hidden" name="$key" value="$form->{$key}">\n|;
   }
 
   print qq|
@@ -1374,122 +953,176 @@ sub delete {
     . $locale->text('Yes') . qq|">
 </form>
 |;
+  $main::lxdebug->leave_sub();
 
-  $lxdebug->leave_sub();
 }
 
 sub yes {
-  $lxdebug->enter_sub();
-
-  $form->redirect($locale->text('Transaction deleted!'))
-    if (GL->delete_transaction(\%myconfig, \%$form));
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $locale   = $main::locale;
+
+  if (GL->delete_transaction(\%myconfig, \%$form)){
+    # saving the history
+      if(!exists $form->{addition} && $form->{id} ne "") {
+        $form->{snumbers} = qq|ordnumber_| . $form->{ordnumber};
+        $form->{addition} = "DELETED";
+        $form->save_history;
+      }
+    # /saving the history
+    $form->redirect($locale->text('Transaction deleted!'))
+  }
   $form->error($locale->text('Cannot delete transaction!'));
+  $main::lxdebug->leave_sub();
 
-  $lxdebug->leave_sub();
 }
 
-sub post {
-  $lxdebug->enter_sub();
+sub post_transaction {
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $locale   = $main::locale;
 
   # check if there is something in reference and date
   $form->isblank("reference",   $locale->text('Reference missing!'));
   $form->isblank("transdate",   $locale->text('Transaction Date missing!'));
   $form->isblank("description", $locale->text('Description missing!'));
 
-  $transdate = $form->datetonum($form->{transdate}, \%myconfig);
-  $closedto  = $form->datetonum($form->{closedto},  \%myconfig);
+  my $transdate = $form->datetonum($form->{transdate}, \%myconfig);
+  my $closedto  = $form->datetonum($form->{closedto},  \%myconfig);
 
-  ($debitaccno,  $debittaxkey)  = split(/--/, $form->{debitchartselected});
-  ($creditaccno, $credittaxkey) = split(/--/, $form->{creditchartselected});
+  my @a           = ();
+  my $count       = 0;
+  my $debittax    = 0;
+  my $credittax   = 0;
+  my $debitcount  = 0;
+  my $creditcount = 0;
+  my $debitcredit;
+  my %split_safety = ();
 
-  $credit_save = $form->{credit};
-  $debit_save  = $form->{debit};
+  my @flds = qw(accno debit credit projectnumber fx_transaction source memo tax taxchart);
 
-  # check project
-  &check_project;
-  ($taxkey, $taxrate) = split(/--/, $form->{taxchartselected});
+  for my $i (1 .. $form->{rowcount}) {
+    next if $form->{"debit_$i"} eq "" && $form->{"credit_$i"} eq "";
 
-  if ($debittaxkey > 0) {
-    $form->{taxchart} = $form->unescape($form->{taxchart});
-    $form->{taxchart} =~ s/\"$debittaxkey--([^\"]*)\"/\"$debittaxkey--$1\"/;
+    for (qw(debit credit tax)) {
+      $form->{"${_}_$i"} = $form->parse_amount(\%myconfig, $form->{"${_}_$i"});
+    }
+
+    push @a, {};
+    $debitcredit = ($form->{"debit_$i"} == 0) ? "0" : "1";
 
-    $rate = ($form->{taxchart} =~ /selected/) ? $taxrate : $1;
-    $form->{taxkey} =
-      ($form->{taxchart} =~ /selected/) ? $taxkey : $debittaxkey;
+    $split_safety{   $form->{"debit_$i"}  <=> 0 }++;
+    $split_safety{ - $form->{"credit_$i"} <=> 0 }++;
 
-    if ($form->{storno}) {
-      $form->{debit}  = $form->parse_amount(\%myconfig, $form->{debit});
-      $form->{credit} = $form->parse_amount(\%myconfig, $form->{credit});
-      $form->{tax}    = $form->parse_amount(\%myconfig, $form->{tax});
+    if ($debitcredit) {
+      $debitcount++;
     } else {
+      $creditcount++;
+    }
+
+    if (($debitcount >= 2) && ($creditcount == 2)) {
+      $form->{"credit_$i"} = 0;
+      $form->{"tax_$i"}    = 0;
+      $creditcount--;
+      $form->{creditlock} = 1;
+    }
+    if (($creditcount >= 2) && ($debitcount == 2)) {
+      $form->{"debit_$i"} = 0;
+      $form->{"tax_$i"}   = 0;
+      $debitcount--;
+      $form->{debitlock} = 1;
+    }
+    if (($creditcount == 1) && ($debitcount == 2)) {
+      $form->{creditlock} = 1;
+    }
+    if (($creditcount == 2) && ($debitcount == 1)) {
+      $form->{debitlock} = 1;
+    }
+    if ($debitcredit && $credittax) {
+      $form->{"taxchart_$i"} = "0--0.00";
+    }
+    if (!$debitcredit && $debittax) {
+      $form->{"taxchart_$i"} = "0--0.00";
+    }
+    my $amount = ($form->{"debit_$i"} == 0)
+            ? $form->{"credit_$i"}
+            : $form->{"debit_$i"};
+    my $j = $#a;
+    if (($debitcredit && $credittax) || (!$debitcredit && $debittax)) {
+      $form->{"taxchart_$i"} = "0--0.00";
+      $form->{"tax_$i"}      = 0;
+    }
+    my ($taxkey, $rate) = split(/--/, $form->{"taxchart_$i"});
+    if ($taxkey > 1) {
+      if ($debitcredit) {
+        $debittax = 1;
+      } else {
+        $credittax = 1;
+      }
       if ($form->{taxincluded}) {
-        $form->{debit} =
-          $form->parse_amount(\%myconfig, $form->{amount}) / ($rate + 1);
-        $form->{credit} = $form->parse_amount(\%myconfig, $form->{amount}) * 1;
-        $form->{tax} =
-          $form->parse_amount(\%myconfig, $form->{amount}) / ($rate + 1) *
-          $rate;
+        $form->{"tax_$i"} = $amount / ($rate + 1) * $rate;
+        if ($debitcredit) {
+          $form->{"debit_$i"} = $form->{"debit_$i"} - $form->{"tax_$i"};
+        } else {
+          $form->{"credit_$i"} = $form->{"credit_$i"} - $form->{"tax_$i"};
+        }
       } else {
-        $form->{debit} = $form->parse_amount(\%myconfig, $form->{amount}) * 1;
-        $form->{credit} =
-          $form->parse_amount(\%myconfig, $form->{amount}) * ($rate + 1);
-        $form->{tax} =
-          $form->parse_amount(\%myconfig, $form->{amount}) * $rate;
+        $form->{"tax_$i"} = $amount * $rate;
       }
+    } else {
+      $form->{"tax_$i"} = 0;
     }
-    $form->{debittaxkey} = 1;
 
-  } else {
-    $form->{taxchart} = $form->unescape($form->{taxchart});
-    $form->{taxchart} =~ s/\"$credittaxkey--([^\"]*)\"/\"$credittaxkey--$1\"/;
+    for (@flds) { $a[$j]->{$_} = $form->{"${_}_$i"} }
+    $count++;
+  }
 
-    $rate = ($form->{taxchart} =~ /selected/) ? $taxrate : $1;
-    $form->{taxkey} =
-      ($form->{taxchart} =~ /selected/) ? $taxkey : $credittaxkey;
+  if ($split_safety{-1} > 1 && $split_safety{1} > 1) {
+    $::form->error($::locale->text("Split entry detected. The values you have entered will result in an entry with more than one position on both debit and credit. Due to known problems involving accounting software Lx-Office does not allow these."));
+  }
 
-    if ($form->{storno}) {
-      $form->{debit}  = $form->parse_amount(\%myconfig, $form->{debit});
-      $form->{credit} = $form->parse_amount(\%myconfig, $form->{credit});
-      $form->{tax}    = $form->parse_amount(\%myconfig, $form->{tax});
-    } else {
-      if ($form->{taxincluded}) {
-        $form->{debit} = $form->parse_amount(\%myconfig, $form->{amount}) * 1;
-        $form->{credit} =
-          $form->parse_amount(\%myconfig, $form->{amount}) / ($rate + 1);
-        $form->{tax} =
-          $form->parse_amount(\%myconfig, $form->{amount}) / ($rate + 1) *
-          $rate;
-      } else {
-        $form->{debit} =
-          $form->parse_amount(\%myconfig, $form->{amount}) * ($rate + 1);
-        $form->{credit} = $form->parse_amount(\%myconfig, $form->{amount}) * 1;
-        $form->{tax} =
-          $form->parse_amount(\%myconfig, $form->{amount}) * $rate;
-      }
-    }
-    $form->{debittaxkey} = 0;
+  for my $i (1 .. $count) {
+    my $j = $i - 1;
+    for (@flds) { $form->{"${_}_$i"} = $a[$j]->{$_} }
+  }
 
+  for my $i ($count + 1 .. $form->{rowcount}) {
+    for (@flds) { delete $form->{"${_}_$i"} }
   }
-  if ($form->{credit_splited}) {
-    $form->{debit}  = $form->parse_amount(\%myconfig, $form->{amount}) * 1;
-    $form->{credit} = $credit_save;
-    $form->{tax}    = 0;
-  } elsif ($form->{debit_splited}) {
-    $form->{credit} = $form->parse_amount(\%myconfig, $form->{amount}) * 1;
-    $form->{debit}  = $debit_save;
-    $form->{tax}    = 0;
+
+  my ($debit, $credit, $taxtotal);
+  for my $i (1 .. $form->{rowcount}) {
+    my $dr  = $form->{"debit_$i"};
+    my $cr  = $form->{"credit_$i"};
+    my $tax = $form->{"tax_$i"};
+    if ($dr && $cr) {
+      $form->error($locale->text('Cannot post transaction with a debit and credit entry for the same account!'));
+    }
+    $debit    += $dr + $tax if $dr;
+    $credit   += $cr + $tax if $cr;
+    $taxtotal += $tax if $form->{taxincluded}
   }
 
+  $form->{taxincluded} = 0 if !$taxtotal;
+
   # this is just for the wise guys
   $form->error($locale->text('Cannot post transaction for a closed period!'))
-    if ($transdate <= $closedto);
-  $form->error($locale->text('Soll- und Habenkonto sind gleich!'))
-    if ($debitaccno eq $creditaccno);
-  $form->error($locale->text('Keine Steuerautomatik möglich!'))
-    if ($debittaxkey && $credittaxkey && !($taxkey == 0));
+    if ($form->date_closed($form->{"transdate"}, \%myconfig));
+  if ($form->round_amount($debit, 2) != $form->round_amount($credit, 2)) {
+    $form->error($locale->text('Out of balance transaction!'));
+  }
+
+  if ($form->round_amount($debit, 2) + $form->round_amount($credit, 2) == 0) {
+    $form->error($locale->text('Empty transaction!'));
+  }
 
-  if (($errno = GL->post_transaction(\%myconfig, \%$form)) <= -1) {
+  if ((my $errno = GL->post_transaction(\%myconfig, \%$form)) <= -1) {
     $errno *= -1;
+    my @err;
     $err[1] = $locale->text('Cannot have a value in both Debit and Credit!');
     $err[2] = $locale->text('Debit and credit out of balance!');
     $err[3] = $locale->text('Cannot post a transaction without a value!');
@@ -1497,395 +1130,90 @@ sub post {
     $form->error($err[$errno]);
   }
   undef($form->{callback});
-  $form->redirect("Buchung gespeichert. Buchungsnummer = " . $form->{id});
-
-  $lxdebug->leave_sub();
-}
-
-sub post_as_new {
-  $lxdebug->enter_sub();
-
-  $form->{id} = 0;
-  &add;
-
-  $lxdebug->leave_sub();
-}
-
-sub storno {
-  $lxdebug->enter_sub();
-
-  $form->{id}     = 0;
-  $form->{storno} = 1;
-  &post;
-
-  $lxdebug->leave_sub();
-}
-
-sub split_debit {
-  $lxdebug->enter_sub();
-
-  # change callback
-  $form->{old_callback} = $form->escape($form->{callback}, 1);
-  $form->{callback} = $form->escape("$form->{script}?action=update", 1);
-
-  # delete action
-  delete $form->{action};
-
-  # save all other form variables in a previousform variable
-  foreach $key (keys %$form) {
-
-    # escape ampersands
-    $form->{$key} =~ s/&/%26/g;
-    $previousform .= qq|$key=$form->{$key}&|;
-  }
-  chop $previousform;
-  $previousform = $form->escape($previousform, 1);
-  if (!$form->{debitpost}) {
-    $form->{debitpost} = $form->{amount};
+  # saving the history
+  if(!exists $form->{addition} && $form->{id} ne "") {
+    $form->{snumbers} = qq|ordnumber_| . $form->{ordnumber};
+    $form->{addition} = "SAVED";
+    $form->{what_done} = $locale->text("Buchungsnummer") . " = " . $form->{id};
+    $form->save_history;
   }
-  $form->{previousform} = $previousform;
-  &display_split_debit();
+  # /saving the history
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
-sub split_credit {
-  $lxdebug->enter_sub();
-
-  # change callback
-  $form->{old_callback} = $form->escape($form->{callback}, 1);
-  $form->{callback} = $form->escape("$form->{script}?action=update", 1);
+sub post {
+  $main::lxdebug->enter_sub();
 
-  # delete action
-  delete $form->{action};
+  $main::auth->assert('general_ledger');
 
-  # save all other form variables in a previousform variable
-  foreach $key (keys %$form) {
+  my $form     = $main::form;
+  my $locale   = $main::locale;
 
-    # escape ampersands
-    $form->{$key} =~ s/&/%26/g;
-    $previousform .= qq|$key=$form->{$key}&|;
-  }
-  chop $previousform;
-  $previousform = $form->escape($previousform, 1);
-  if (!$form->{creditpost}) {
-    $form->{creditpost} = $form->{amount};
+  if ($::myconfig{mandatory_departments} && !$form->{department}) {
+    $form->{saved_message} = $::locale->text('You have to specify a department.');
+    update();
+    exit;
   }
-  $form->{previousform} = $previousform;
-  &display_split_credit();
-  $lxdebug->leave_sub();
-}
 
-sub display_split_credit {
-  $lxdebug->enter_sub();
-  $form->{taxchart} = $form->unescape($form->{taxchart});
+  $form->{title}  = $locale->text("$form->{title} General Ledger Transaction");
+  $form->{storno} = 0;
 
-  $form->header;
-
-  print qq|
-<body>
-<form method=post name=split_credit action=gl.pl>
-|
-    . $locale->text('Credit') . qq|: |
-    . $form->format_amount(\%myconfig, $form->{amount}, 2)
-    . qq| EUR<br>
-|
-    . $locale->text('Still to post')
-    . qq|:<input name=creditpost size=10 value="|
-    . $form->format_amount(\%myconfig, $form->{creditpost}, 2)
-    . qq|"> EUR<br>
-<script type="text/javascript">
-           function update_stilltopost (betrag){
-           remaining = parseFloat(document.split_credit.creditpost.value) - parseFloat(betrag);
-           document.split_credit.creditpost.value= remaining;
-           }
-</script>
-
-<table>|;
-  for $i (2 .. $form->{creditrowcount}) {
-    $form->{"creditchart_$i"} = $form->{chart};
-    $form->{"creditchart_$i"} =~
-      s/value=\"$form->{"creditchartselected_$i"}\"/value=\"$form->{"creditchartselected_$i"}\" selected/;
-
-    $form->{"taxchart_$i"} = $form->{taxchart};
-    $form->{"taxchart_$i"} =~
-      s/value=\"$form->{"taxchartselected_$i"}\"/value=\"$form->{"taxchartselected_$i"}\" selected/;
-    $position = $i - 1;
-    print qq|
-  <tr><td></td></tr>
-  <tr>
-    <th>Position $position</th>
-    <td><select name=creditchartselected_$i>$form->{"creditchart_$i"}</select></td>
-    <th align=right>| . $locale->text('Amount') . qq| $1</th>
-    <td><input name=credit_$i size=10 value="|
-      . $form->format_amount(\%myconfig, $form->{"credit_$i"}, 2)
-      . qq|" onBlur="update_stilltopost(this.value)"> EUR</td>
-  </tr>
-  <tr>
-    <th></th>
-    <td><select name=taxchartselected_$i>$form->{"taxchart_$i"}</select></td>
-    <th align=right>| . $locale->text('Tax') . qq|</th>
-    <td><input name=tax_$i size=10 value="|
-      . $form->format_amount(\%myconfig, $form->{"tax_$i"}, 2)
-      . qq|"> EUR</td>
-    <td><input type=checkbox name=tax_manual_$i value=1> Steuerkorrektur</td>
-  </tr>
-  <td></td>
-  <tr>
-  </tr>
-  <tr>
-    <td colspan=5><hr size=3 noshade></td>
-  </tr>
+  post_transaction();
 
-|;
-  }
-  print qq|
-</table>
-<input type=hidden name=previousform value="$form->{previousform}">
-
-<input type=hidden name=path value=$form->{path}>
-<input type=hidden name=login value=$form->{login}>
-<input type=hidden name=password value=$form->{password}>
-<input type=hidden name=callback value=$form->{callback}>
-<input type=hidden name=old_callback value=$form->{old_callback}>
-<input type=hidden name=amount value=$form->{amount}>
-<input type=hidden name=credit_splited value=1>
-<input type=hidden name=creditrowcount value="$form->{creditrowcount}">
-<input type=hidden name=chart value=| . $form->escape($form->{chart}) . qq|>
-<input type=hidden name=taxchart value=|
-    . $form->escape($form->{taxchart}) . qq|>
-<p>
-<input class=submit type=submit name=action value="|
-    . $locale->text('New Account') . qq|">
-<input class=submit type=submit name=action value="|
-    . $locale->text('Close') . qq|">
-</form>
+  remove_draft() if $form->{remove_draft};
 
-</body>
-</html>
-|;
+  $form->{callback} = build_std_url("action=add&DONT_LOAD_DRAFT=1", "show_details");
+  $form->redirect($form->{callback});
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
-sub display_split_debit {
-  $lxdebug->enter_sub();
-  $form->{taxchart} = $form->unescape($form->{taxchart});
-
-  $form->header;
+sub post_as_new {
+  $main::lxdebug->enter_sub();
 
-  print qq|
-<body>
-<form method=post name=split_debit action=gl.pl>
-|
-    . $locale->text('Debit') . qq|: |
-    . $form->format_amount(\%myconfig, $form->{amount}, 2)
-    . qq| EUR<br>
-|
-    . $locale->text('Still to post')
-    . qq|:<input name=debitpost size=10 value="|
-    . $form->format_amount(\%myconfig, $form->{debitpost}, 2)
-    . qq|"> EUR<br>
-<script type="text/javascript">
-           function update_stilltopost (betrag){
-           remaining = parseFloat(document.split_debit.debitpost.value) - parseFloat(betrag);
-           document.split_debit.debitpost.value= remaining;
-           }
-</script>
-
-<table>|;
-  for $i (2 .. $form->{debitrowcount}) {
-    $form->{"debitchart_$i"} = $form->{chart};
-    $form->{"debitchart_$i"} =~
-      s/value=\"$form->{"debitchartselected_$i"}\"/value=\"$form->{"debitchartselected_$i"}\" selected/;
-
-    $form->{"taxchart_$i"} = $form->{taxchart};
-    $form->{"taxchart_$i"} =~
-      s/value=\"$form->{"taxchartselected_$i"}\"/value=\"$form->{"taxchartselected_$i"}\" selected/;
-    $position = $i - 1;
-    print qq|
-  <tr><td></td></tr>
-  <tr>
-    <th>Position $position</th>
-    <td><select name=debitchartselected_$i>$form->{"debitchart_$i"}</select></td>
-    <th align=right>| . $locale->text('Amount') . qq| $1</th>
-    <td><input name=debit_$i size=10 value="|
-      . $form->format_amount(\%myconfig, $form->{"debit_$i"}, 2)
-      . qq|" onBlur="update_stilltopost(this.value)"> EUR</td>
-  </tr>
-  <tr>
-    <th></th>
-    <td><select name=taxchartselected_$i>$form->{"taxchart_$i"}</select></td>
-    <th align=right>| . $locale->text('Tax') . qq|</th>
-    <td><input name=tax_$i size=10 value="|
-      . $form->format_amount(\%myconfig, $form->{"tax_$i"}, 2)
-      . qq|"> EUR</td>
-    <td><input type=checkbox name=tax_manual_$i value=1> Steuerkorrektur</td>
-  </tr>
-  <td></td>
-  <tr>
-  </tr>
-  <tr>
-    <td colspan=5><hr size=3 noshade></td>
-  </tr>
+  $main::auth->assert('general_ledger');
 
-|;
-  }
-  print qq|
-</table>
-<input type=hidden name=previousform value="$form->{previousform}">
-
-<input type=hidden name=path value=$form->{path}>
-<input type=hidden name=login value=$form->{login}>
-<input type=hidden name=password value=$form->{password}>
-<input type=hidden name=callback value=$form->{callback}>
-<input type=hidden name=old_callback value=$form->{old_callback}>
-<input type=hidden name=amount value=$form->{amount}>
-<input type=hidden name=debit_splited value=1>
-<input type=hidden name=debitrowcount value="$form->{debitrowcount}">
-<input type=hidden name=chart value=| . $form->escape($form->{chart}) . qq|>
-<input type=hidden name=taxchart value=|
-    . $form->escape($form->{taxchart}) . qq|>
-<p>
-<input class=submit type=submit name=action value="|
-    . $locale->text('New Account') . qq|">
-<input class=submit type=submit name=action value="|
-    . $locale->text('Close') . qq|">
-</form>
+  my $form     = $main::form;
 
-</body>
-</html>
-|;
+  $form->{id} = 0;
+  &add;
+  $main::lxdebug->leave_sub();
 
-  $lxdebug->leave_sub();
 }
 
-sub new_account {
-  $lxdebug->enter_sub();
-
-  $form->{chart} = $form->unescape($form->{chart});
-
-  if ($form->{credit_splited}) {
-    $form->{creditpost} = $form->{amount};
-
-    for $i (2 .. $form->{creditrowcount}) {
-      $form->{"credit_$i"} =
-        $form->parse_amount(\%myconfig, $form->{"credit_$i"});
-      $form->{creditpost} -= $form->{"credit_$i"};
-      ($taxkey, $taxrate) = split(/--/, $form->{"taxchartselected_$i"});
-      if ($form->{"tax_manual_$i"}) {
-        $form->{"tax_$i"} = $form->parse_amount(\%myconfig, $form->{"tax_$i"});
-      } else {
-        $form->{"tax_$i"} = $form->{"credit_$i"} * $taxrate;
-      }
-      $form->{creditpost} -= $form->{"tax_$i"};
-
-    }
-    if ($form->{"credit_$form->{creditrowcount}"}) {
-      $form->{creditrowcount}++;
-    }
+sub storno {
+  $main::lxdebug->enter_sub();
 
-    &display_split_credit;
-  }
-  if ($form->{debit_splited}) {
-    $form->{debitpost} = $form->{amount};
-
-    for $i (2 .. $form->{debitrowcount}) {
-      $form->{"debit_$i"} =
-        $form->parse_amount(\%myconfig, $form->{"debit_$i"});
-      $form->{debitpost} -= $form->{"debit_$i"};
-      ($taxkey, $taxrate) = split(/--/, $form->{"taxchartselected_$i"});
-      if ($form->{"tax_manual_$i"}) {
-        $form->{"tax_$i"} = $form->parse_amount(\%myconfig, $form->{"tax_$i"});
-      } else {
-        $form->{"tax_$i"} = $form->{"debit_$i"} * $taxrate;
-      }
-      $form->{debitpost} -= $form->{"tax_$i"};
+  $main::auth->assert('general_ledger');
 
-    }
-    if ($form->{"debit_$form->{debitrowcount}"}) {
-      $form->{debitrowcount}++;
-    }
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $locale   = $main::locale;
 
-    &display_split_debit;
+  # don't cancel cancelled transactions
+  if (IS->has_storno(\%myconfig, $form, 'gl')) {
+    $form->{title} = $locale->text("Cancel Accounts Receivables Transaction");
+    $form->error($locale->text("Transaction has already been cancelled!"));
   }
-  $lxdebug->leave_sub();
-}
-
-sub close {
-  $lxdebug->enter_sub();
-
-  # save the new form variables before splitting previousform
-  map { $newform{$_} = $form->{$_} } keys %$form;
 
-  $previousform = $form->unescape($form->{previousform});
+  GL->storno($form, \%myconfig, $form->{id});
 
-  # don't trample on previous variables
-  map { delete $form->{$_} } keys %newform;
-
-  # now take it apart and restore original values
-  foreach $item (split /&/, $previousform) {
-    ($key, $value) = split /=/, $item, 2;
-    $value =~ s/%26/&/g;
-    $form->{$key} = $value;
+  # saving the history
+  if(!exists $form->{addition} && $form->{id} ne "") {
+    $form->{snumbers} = "ordnumber_$form->{ordnumber}";
+    $form->{addition} = "STORNO";
+    $form->save_history;
   }
-  if ($newform{credit_splited}) {
-    $form->{credit}         = 0;
-    $form->{credit_splited} = $newform{credit_splited};
-    $form->{creditrowcount} = $newform{creditrowcount};
-    for $i (2 .. $form->{creditrowcount}) {
-      $form->{"creditchartselected_$i"} = $newform{"creditchartselected_$i"};
-      $form->{"credit_$i"}              = $newform{"credit_$i"};
-      $form->{"credit_$i"}              =
-        $form->parse_amount(\%myconfig, $form->{"credit_$i"});
-      $form->{"taxchartselected_$i"} = $newform{"taxchartselected_$i"};
-      ($taxkey, $taxrate) = split(/--/, $form->{"taxchartselected_$i"});
-      if ($newform{"tax_manual_$i"}) {
-        $form->{"tax_$i"} =
-          $form->parse_amount(\%myconfig, $newform{"tax_$i"});
-      } else {
-        $form->{"tax_$i"} = $form->{"credit_$i"} * $taxrate;
-      }
-      $form->{credit} += $form->round_amount($form->{"credit_$i"}, 2);
-      $form->{credit} += $form->round_amount($form->{"tax_$i"},    2);
+  # /saving the history
 
-    }
-  } else {
-    $form->{debit}         = 0;
-    $form->{debit_splited} = $newform{debit_splited};
-    $form->{debitrowcount} = $newform{debitrowcount};
-    for $i (2 .. $form->{debitrowcount}) {
-      $form->{"debitchartselected_$i"} = $newform{"debitchartselected_$i"};
-      $form->{"debit_$i"}              = $newform{"debit_$i"};
-      $form->{"debit_$i"}              =
-        $form->parse_amount(\%myconfig, $form->{"debit_$i"});
-      $form->{"taxchartselected_$i"} = $newform{"taxchartselected_$i"};
-      ($taxkey, $taxrate) = split(/--/, $form->{"taxchartselected_$i"});
-      if ($newform{"tax_manual_$i"}) {
-        $form->{"tax_$i"} =
-          $form->parse_amount(\%myconfig, $newform{"tax_$i"});
-      } else {
-        $form->{"tax_$i"} = $form->{"debit_$i"} * $taxrate;
-      }
-      $form->{debit} += $form->round_amount($form->{"debit_$i"}, 2);
-      $form->{debit} += $form->round_amount($form->{"tax_$i"},   2);
-    }
-  }
-  delete $form->{action};
-  $callback = $form->unescape($form->{callback});
-  $form->{callback} = $form->unescape($form->{old_callback});
-  delete $form->{old_callback};
+  $form->redirect(sprintf $locale->text("Transaction %d cancelled."), $form->{storno_id});
 
-  # put callback together
-  foreach $key (keys %$form) {
-
-    # do single escape for Apache 2.0
-    $value = $form->escape($form->{$key}, 1);
-    $callback .= qq|&$key=$value|;
-  }
-  $form->{callback} = $callback;
+  $main::lxdebug->leave_sub();
+}
 
-  # redirect
-  $form->redirect;
-  $lxdebug->leave_sub();
+sub continue {
+  call_sub($main::form->{nextsub});
 }
+
+1;