Merge branch 'frameless_w_fixed_header-div'
[kivitendo-erp.git] / bin / mozilla / gl.pl
index f88a0eb..fd67b5f 100644 (file)
 #
 #======================================================================
 
+use utf8;
+use strict;
 
+use POSIX qw(strftime);
+use List::Util qw(sum);
+
+use SL::FU;
 use SL::GL;
+use SL::IS;
 use SL::PE;
+use SL::ReportGenerator;
 
-use Data::Dumper;
-
-require "$form->{path}/arap.pl";
-
-1;
-# 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,1554 +75,1138 @@ require "$form->{path}/arap.pl";
 # $locale->text('Nov')
 # $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->{rowcount}  = 2;
 
-  $form->{debitchart} = $chart;
-  $form->{creditchart} = $chart;
-  $form->{taxchart} = $tax;
-  
-  $form->{debit} = 0;
+  $form->{debit}  = 0;
   $form->{credit} = 0;
-  $form->{tax} = 0;
-  
-  $form->{creditrowcount} = 2;
-  $form->{debitrowcount} = 2;
-  
+  $form->{tax}    = 0;
 
   # 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} });
+    map {
+      $form->{selectdepartment} .=
+        "<option>$_->{description}--$_->{id}\n"
+    } (@{ $form->{all_departments} || [] });
   }
-  &display_form;
-  
-  $lxdebug->leave_sub();
+
+  $form->{show_details} = $myconfig{show_form_details} unless defined $form->{show_details};
+
+  &display_form(1);
+  $main::lxdebug->leave_sub();
+
 }
 
+sub prepare_transaction {
+  $main::lxdebug->enter_sub();
 
-sub edit {
-  $lxdebug->enter_sub();
+  $main::auth->assert('general_ledger');
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
 
   GL->transaction(\%myconfig, \%$form);
 
-  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);
-  }
-  
-  $form->{amount}=$form->format_amount(\%myconfig, $form->{amount}, 2);
-  
+  $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} });
+    map {
+      $form->{selectdepartment} .=
+        "<option>$_->{description}--$_->{id}\n"
+    } (@{ $form->{all_departments} || [] });
   }
-  $form->{locked} = ($form->datetonum($form->{transdate}, \%myconfig) <= $form->datetonum($form->{closedto}, \%myconfig));
 
-  $form->{title} = "Edit";
-  
-  &form_header;
+  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};
+
+    } 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->{rowcount} = $i;
+  $form->{locked}   =
+    ($form->datetonum($form->{transdate}, \%myconfig) <=
+     $form->datetonum($form->{closedto}, \%myconfig));
 
-  &form_footer;
-  
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
+sub edit {
+  $main::lxdebug->enter_sub();
 
+  $main::auth->assert('general_ledger');
 
-sub search {
-  $lxdebug->enter_sub();
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
 
-  $form->{title} = $locale->text('Buchungsjournal');
-  
-  $form->all_departments(\%myconfig);
-  # departments
-  if (@{ $form->{all_departments} }) {
-    $form->{selectdepartment} = "<option>\n";
+  prepare_transaction();
 
-    map { $form->{selectdepartment} .= "<option>$_->{description}--$_->{id}\n" } (@{ $form->{all_departments} });
-  }
-  $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
-   {
-      # 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->{title} = "Edit";
 
-  $form->header;
+  $form->{show_details} = $myconfig{show_form_details} unless defined $form->{show_details};
 
-  print qq|
-<body>
+  form_header();
+  display_rows();
+  form_footer();
 
-<form method=post action=$form->{script}>
+  $main::lxdebug->leave_sub();
+}
 
-<input type=hidden name=sort value=transdate>
 
-<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>
+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 ]);
+
+  $::form->header;
+  print $::form->parse_html_template('gl/search', {
+    department_label => sub { ("$_[0]{description}--$_[0]{id}")x2 },
+    employee_label => sub { "$_[0]{id}--$_[0]{name}" },
+  });
+
+  $::lxdebug->leave_sub;
+}
 
-$jsscript
+sub create_subtotal_row {
+  $main::lxdebug->enter_sub();
 
-<input type=hidden name=nextsub value=generate_report>
+  my ($totals, $columns, $column_alignment, $subtotal_columns, $class) = @_;
 
-<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 $form     = $main::form;
+  my %myconfig = %main::myconfig;
 
-<br>
-<input class=submit type=submit name=action value="|.$locale->text('Continue').qq|">
-</form>
+  my $row = { map { $_ => { 'data' => '', 'class' => $class, 'align' => $column_alignment->{$_}, } } @{ $columns } };
 
-</body>
-</html>
-|;
-  $lxdebug->leave_sub();
-}
+  map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $totals->{$_}, 2) } @{ $subtotal_columns };
+
+  map { $totals->{$_} = 0 } @{ $subtotal_columns };
 
+  $main::lxdebug->leave_sub();
+
+  return $row;
+}
 
 sub generate_report {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  $main::auth->assert('general_ledger');
 
-  $form->{sort} = "transdate" unless $form->{sort};
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $locale   = $main::locale;
+
+  # 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
+
+  # <form method=post action=gl.pl>
+  # <input type=hidden name=sort value=datesort>    # form->{sort} setzen
+  # <input type=hidden name=nextsub value=generate_report>
+
+  # anhand von neuer Variable datesort wird jetzt $form->{sort} auf transdate oder gldate gesetzt
+  # damit ist die Hidden Variable "sort" wahrscheinlich sogar überflüssig
+
+  # ä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
+
+  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};
+  };
+
+  # was passiert hier?
+  report_generator_set_default_sort("$form->{datesort}", 1);
+#  report_generator_set_default_sort('transdate', 1);
 
   GL->all_transactions(\%myconfig, \%$form);
-  
-  $callback = "$form->{script}?action=generate_report&path=$form->{path}&login=$form->{login}&password=$form->{password}";
-
-  $href = $callback;
-  
-  %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('General Ledger');
-  
-  $ml = ($form->{ml} =~ /(A|E)/) ? -1 : 1;
-
-  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}";
+
+  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} });
   }
+
+  $form->{landscape} = 1;
+
+  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}) {
-    $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";
+    my ($department) = split /--/, $form->{department};
+    push @options, $locale->text('Department') . " : $department";
   }
 
-  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}";
-  }
-   
-  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 $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";
   }
 
+  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};
 
-  @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));
-
-  if ($form->{accno} || $form->{gifi_accno}) {
-    @columns = grep !/(accno|gifi_accno)/, @columns;
-    push @columns, "balance";
-    $form->{l_balance} = "Y";
- }
-  
-  $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";
-    }
-  }
+  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;
 
-  if ($form->{l_subtotal} eq 'Y') {
-    $callback .= "&l_subtotal=Y";
-    $href .= "&l_subtotal=Y";
-  }
+  my $report = SL::ReportGenerator->new(\%myconfig, $form);
 
-  $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>";
-  
-  $form->{landscape} = 1;
-  
-  $form->header;
+  $report->set_columns(%column_defs);
+  $report->set_column_order(@columns);
 
-  print qq|
-<body>
+  $report->set_export_options('generate_report', @hidden_variables, qw(sort sortdir));
 
-<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_sort_indicator($form->{sort} eq 'accno' ? 'debit_accno' : $form->{sort}, $form->{sortdir});
 
-map { print "$column_header{$_}\n" } @column_index;
+  $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';
 
-print "
-        </tr>
-        </thead>
-        </tfoot>
-        <tbody>
-";
-  
   # 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}};
-  }
-  
-  if (($form->{accno} || $form->{gifi_accno}) && $form->{balance}) {
+  $form->{callback} = "$callback&sort=" . E($form->{sort}) . "&sortdir=" . E($form->{sortdir});
 
-    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>
-|;
-  }
-    
-  foreach $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};
-    }
-    
-    $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);
-      }
-    }
-    
-    $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);
-      }      
-    }
-    
-    $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 @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 my $ref (@{ $form->{GL} }) {
+
+    my %rows;
+
+    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);
       }
     }
-    
-    $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);
-      }
+
+    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} }) ];
     }
-    
-    $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};
+
+    my $row = { };
+    map { $row->{$_} = { 'data' => '', 'align' => $column_alignment{$_} } } @columns;
+
+    my $sh = "";
+    if ($form->{balance} < 0) {
+      $sh = " S";
+      $ml = -1;
+    } elsif ($form->{balance} > 0) {
+      $sh = " H";
+      $ml = 1;
     }
-    
-    $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};
-    }    
-    
-    $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>";
-      }
+    my $data = $form->format_amount(\%myconfig, ($form->{balance} * $ml), 2);
+    $data .= $sh;
+
+    $row->{balance}->{data}        = $data;
+    $row->{projectnumbers}->{data} = join ", ", sort { lc($a) cmp lc($b) } keys %{ $ref->{projectnumbers} };
+
+    map { $row->{$_}->{data} = $ref->{$_} } qw(id reference description notes gldate employee);
+
+    map { $row->{$_}->{data} = \@{ $rows{$_} }; } qw(transdate debit credit debit_accno credit_accno debit_tax_accno credit_tax_accno source);
+
+    foreach my $col (qw(debit_accno credit_accno debit_tax_accno credit_tax_accno)) {
+      $row->{$col}->{link} = [ map { "${callback}&accno=" . E($_) } @{ $rows{$col} } ];
     }
-    
-    $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>";
-      }
-    }    
-#    $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');
+    $row->{reference}->{link} = build_std_url("script=$ref->{module}.pl", 'action=edit', 'id=' . E($ref->{id}), 'callback');
 
+    my $row_set = [ $row ];
 
-  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>";
-  
-  print qq|
-       <tr class=listtotal>
-|;
+    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');
+    }
 
-  map { print "$column_data{$_}\n" } @column_index;
+    $report->add_data($row_set);
 
-  print qq|
-        </tr>
-        </tbody>
-      </table>
-    </td>
-  </tr>
-  <tr>
-    <td><hr size=3 noshade></td>
-  </tr>
-</table>
+    $idx++;
+  }
 
-<br>
+  # = 0 for balanced ledger
+  my $balanced_ledger = $totals{debit} + $totals{debit_tax} - $totals{credit} - $totals{credit_tax};
 
-<form method=post action=$form->{script}>
+  my $row = create_subtotal_row(\%totals, \@columns, \%column_alignment, [ qw(debit credit debit_tax credit_tax) ], 'listtotal');
 
-<input name=callback type=hidden value="$form->{callback}">
+  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;
 
-<input type=hidden name=path value=$form->{path}>
-<input type=hidden name=login value=$form->{login}>
-<input type=hidden name=password value=$form->{password}>
+  $row->{balance}->{data}        = $data;
 
-<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|">|;
+  if ( !$form->{report_generator_csv_options_for_import} ) {
+    $report->add_separator();
+    $report->add_data($row);
+  }
 
+  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 update {
+  $main::lxdebug->enter_sub();
 
-sub gl_subtotal {
-  $lxdebug->enter_sub();
-      
-  $subtotaldebit = $form->format_amount(\%myconfig, $subtotaldebit, 2, "&nbsp;");
-  $subtotalcredit = $form->format_amount(\%myconfig, $subtotalcredit, 2, "&nbsp;");
-  
-  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>";
+  $main::auth->assert('general_ledger');
 
-  
-  print "<tr class=listsubtotal>";
-  map { print "$column_data{$_}\n" } @column_index;
-  print "</tr>";
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
 
-  $subtotaldebit = 0;
-  $subtotalcredit = 0;
+  $form->{oldtransdate} = $form->{transdate};
 
-  $sameitem = $ref->{$form->{sort}};
+  my @a           = ();
+  my $count       = 0;
+  my $debittax    = 0;
+  my $credittax   = 0;
+  my $debitcount  = 0;
+  my $creditcount = 0;
+  my ($debitcredit, $amount);
 
-  $lxdebug->leave_sub();
+  my @flds =
+    qw(accno debit credit projectnumber fx_transaction source memo tax taxchart);
 
-  return $sameitem;
-}
+  for my $i (1 .. $form->{rowcount}) {
 
+    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/;
-       
-       $form->{debitchart} = $form->{chart};
-       $form->{debitchart}  =~ s/value=\"$form->{debitchartselected}\"/value=\"$form->{debitchartselected}\" selected/;
+      push @a, {};
+      $debitcredit = ($form->{"debit_$i"} == 0) ? "0" : "1";
+      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";
+      }
+      $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++;
+    }
   }
-  ($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 ($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]->{$_} }
   }
-  &check_project;
+
+  for my $i ($count + 1 .. $form->{rowcount}) {
+    for (@flds) { delete $form->{"${_}_$i"} }
+  }
+
+  $form->{rowcount} = $count + 1;
 
   &display_form;
-  
-  $lxdebug->leave_sub();
-}
+  $main::lxdebug->leave_sub();
 
+}
 
 sub display_form {
-  $lxdebug->enter_sub();
+  my ($init) = @_;
+  $main::lxdebug->enter_sub();
 
+  $main::auth->assert('general_ledger');
 
-  &form_header;
-#   for $i (1 .. $form->{rowcount}) {
-#     $form->{totaldebit} += $form->parse_amount(\%myconfig, $form->{"debit_$i"});
-#     $form->{totalcredit} += $form->parse_amount(\%myconfig, $form->{"credit_$i"});
-#  
-#     &form_row($i);
-#   }
+  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"});
+  #     $form->{totalcredit} += $form->parse_amount(\%myconfig, $form->{"credit_$i"});
+  #
+  #     &form_row($i);
+  #   }
+  &display_rows($init);
   &form_footer;
+  $main::lxdebug->leave_sub();
 
-  $lxdebug->leave_sub();
 }
 
+sub display_rows {
+  my ($init) = @_;
+  $main::lxdebug->enter_sub();
 
+  $main::auth->assert('general_ledger');
 
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $cgi      = $::request->{cgi};
 
-sub form_header {
-  $lxdebug->enter_sub();
-
-  $title = $form->{title};
-  $form->{title} = $locale->text("$title General Ledger Transaction");
-  $readonly = ($form->{id}) ? "readonly" : "";
-  
-  $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}";
-# $locale->text('Add General Ledger Transaction')
-# $locale->text('Edit General Ledger Transaction')
-  map { $form->{$_} =~ s/\"/&quot;/g } qw(reference description chart);
-
-  $form->{selectdepartment} =~ s/ selected//;
-  $form->{taxchart} =~ s/ selected//;
-  $form->{selectdepartment} =~ s/option>\Q$form->{department}\E/option selected>$form->{department}/;
-
-  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>|;
-  }
-  
-  $taxincluded = ($form->{taxincluded}) ? "checked" : "";
-  
-  if (!$form->{id}) {
-       $taxincluded = "checked";
+  $form->{debit_1}     = 0 if !$form->{"debit_1"};
+  $form->{totaldebit}  = 0;
+  $form->{totalcredit} = 0;
+
+  my %project_labels = ();
+  my @project_values = ("");
+  foreach my $item (@{ $form->{"ALL_PROJECTS"} }) {
+    push(@project_values, $item->{"id"});
+    $project_labels{$item->{"id"}} = $item->{"projectnumber"};
   }
-  
-  $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
-   {
-      # without JavaScript Calendar
-      $button1 = qq|<td><input name=transdate id=transdate size=11 title="$myconfig{dateformat}" value=$form->{transdate} tabindex="2" $readonly></td>|;
+
+  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)
     }
-    
-  $form->header;
+    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;
+  }
 
-  
-  print qq|
-<body onLoad="fokus()">
+  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;
+  }
+
+  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">|;
+    }
 
-<form method=post name="gl" action=$form->{script}>
+    my $selected_accno_full;
+    my ($accno_row) = split(/--/, $form->{"accno_$i"});
+    my $item = $charts{$accno_row};
+    $selected_accno_full = "$item->{accno}--$item->{tax_id}";
 
-<input name=id type=hidden value=$form->{id}>
+    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"});
 
-<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}">
+    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}";
+    }
 
+    $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>
+    |;
+      }
 
-<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}) {
-          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 {
-          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>|;
+    } else {
+      if ($form->{"debit_$i"} != 0) {
+        $form->{totaldebit} += $form->{"debit_$i"};
+        if (!$form->{taxincluded}) {
+          $form->{totaldebit} += $form->{"tax_$i"};
         }
-        print qq|
-       </tr>      </table>
-    </td>
-  </tr>
-  <tr>
-    <td><hr size=3 noshade></td>
-  </tr>
-$jsscript
-|;
+      } else {
+        $form->{totalcredit} += $form->{"credit_$i"};
+        if (!$form->{taxincluded}) {
+          $form->{totalcredit} += $form->{"tax_$i"};
+        }
+      }
 
-  $lxdebug->leave_sub();
-}
+      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");
 
-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);
-  
-  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"}">
+      } else {
+        if ($form->{transfer}) {
+          $fx_transaction = qq|
+      <td><input name="fx_transaction_$i" class=checkbox type=checkbox value=1></td>
     |;
-  }
-  for $i (2 .. $form->{debitrowcount}) {
+        }
+      }
+    }
+    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|
-    <input type=hidden name=debitchartselected_$i value="$form->{"debitchartselected_$i"}">
-    <input type=hidden name=debit_$i value="$form->{"debit_$i"}">
+    $source_hidden
+    $memo_hidden
+    $projectnumber_hidden
     |;
-  }
-  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}>
-
-<input name=callback type=hidden value="$form->{callback}">
-<br>
+    print qq|
+  </tr>
 |;
+  }
+
+  $form->hide_form(qw(rowcount selectaccno));
+
+  $main::lxdebug->leave_sub();
+
+}
+
+sub form_header {
+  $::lxdebug->enter_sub;
+  $::auth->assert('general_ledger');
+
+  my ($init) = @_;
+
+  my @old_project_ids = grep { $_ } map{ $::form->{"project_id_$_"} } 1..$::form->{rowcount};
+
+  $::form->get_lists("projects"  => { "key"       => "ALL_PROJECTS",
+                                    "all"       => 0,
+                                    "old_id"    => \@old_project_ids },
+                   "charts"    => { "key"       => "ALL_CHARTS",
+                                    "transdate" => $::form->{transdate} },
+                   "taxcharts" => "ALL_TAXCHARTS");
 
-  $transdate = $form->datetonum($form->{transdate}, \%myconfig);
-  $closedto = $form->datetonum($form->{closedto}, \%myconfig);
-
-  if ($form->{id}) {
-  
-  print qq|<input class=submit type=submit name=action value="|.$locale->text('Storno').qq|">|;
-
-# Löschen und ändern von Buchungen nicht mehr möglich (GoB) nur am selben Tag möglich
-
-
-       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|">|;
-       }
-
-       
-#      if ($transdate > $closedto) {
-#              print qq|
-#              <input class=submit type=submit name=action value="|.$locale->text('Post as new').qq|">|;
-#      }
-   }  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|">|;
-       }
-   }
-
-  if ($form->{menubar}) {
-    require "$form->{path}/menu.pl";
-    &menubar;
+  GL->get_chart_balances('charts' => $::form->{ALL_CHARTS});
+
+  my $title      = $::form->{title};
+  $::form->{title} = $::locale->text("$title General Ledger Transaction");
+  # $locale->text('Add General Ledger Transaction')
+  # $locale->text('Edit General Ledger Transaction')
+
+  map { $::form->{$_} =~ s/\"/&quot;/g }
+    qw(chart taxchart);
+
+  $::form->{selectdepartment} =~ s/ selected//;
+  $::form->{selectdepartment} =~
+    s/option>\Q$::form->{department}\E/option selected>$::form->{department}/;
+
+  if ($init) {
+    $::form->{fokus} = "gl.reference";
+    $::form->{taxincluded} = "1";
+  } else {
+    $::form->{fokus} = qq|gl.accno_$::form->{rowcount}|;
   }
-  
-  print "
-  </form>
-
-</body>
-</html>
-";
-  
-  $lxdebug->leave_sub();
+
+  $::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 || [] };
+  }
+
+  my $radieren = $::form->current_date(\%::myconfig) eq $::form->{gldate};
+
+  print $::form->parse_html_template('gl/form_footer', {
+    radieren       => $radieren,
+    follow_ups     => $follow_ups,
+    follow_ups_due => $follow_ups_due,
+  });
+
+  $::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|
-<h2 class=confirm>|.$locale->text('Confirm!').qq|</h2>
+<h2 class=confirm>| . $locale->text('Confirm!') . qq|</h2>
 
-<h4>|.$locale->text('Are you sure you want to delete Transaction').qq| $form->{reference}</h4>
+<h4>|
+    . $locale->text('Are you sure you want to delete Transaction')
+    . qq| $form->{reference}</h4>
 
-<input name=action class=submit type=submit value="|.$locale->text('Yes').qq|">
+<input name=action class=submit type=submit value="|
+    . $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!'));
-  
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
+
 }
 
+sub post_transaction {
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $locale   = $main::locale;
 
-sub post {
-  $lxdebug->enter_sub();
   # 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("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);
-
-  ($debitaccno, $debittaxkey) = split(/--/, $form->{debitchartselected});  
-  ($creditaccno, $credittaxkey) = split(/--/, $form->{creditchartselected});
-  
-  $credit_save = $form->{credit};
-  $debit_save = $form->{debit};    
-
-  # check project
-  &check_project;
-  ($taxkey, $taxrate) = split(/--/, $form->{taxchartselected});    
-
-  if ($debittaxkey >0) { 
-       $form->{taxchart} = $form->unescape($form->{taxchart});
-       $form->{taxchart} =~ s/\"$debittaxkey--([^\"]*)\"/\"$debittaxkey--$1\"/;
-       
-       $rate = ($form->{taxchart} =~ /selected/) ? $taxrate : $1;
-       $form->{taxkey} = ($form->{taxchart} =~ /selected/) ? $taxkey : $debittaxkey;
-       
-       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}) / ($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;
-               }
-       }       
-       $form->{debittaxkey}=1;
-       
-  } else {
-               $form->{taxchart} = $form->unescape($form->{taxchart});
-               $form->{taxchart} =~ s/\"$credittaxkey--([^\"]*)\"/\"$credittaxkey--$1\"/;
-               
-
-               $rate = ($form->{taxchart} =~ /selected/) ? $taxrate : $1;
-               $form->{taxkey} = ($form->{taxchart} =~ /selected/) ? $taxkey : $credittaxkey;
-               
-               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;
-               
-       }
-  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 $transdate = $form->datetonum($form->{transdate}, \%myconfig);
+  my $closedto  = $form->datetonum($form->{closedto},  \%myconfig);
+
+  my @a           = ();
+  my $count       = 0;
+  my $debittax    = 0;
+  my $credittax   = 0;
+  my $debitcount  = 0;
+  my $creditcount = 0;
+  my $debitcredit;
+  my %split_safety = ();
+
+  my @flds = qw(accno debit credit projectnumber fx_transaction source memo tax taxchart);
+
+  for my $i (1 .. $form->{rowcount}) {
+    next if $form->{"debit_$i"} eq "" && $form->{"credit_$i"} eq "";
+
+    for (qw(debit credit tax)) {
+      $form->{"${_}_$i"} = $form->parse_amount(\%myconfig, $form->{"${_}_$i"});
+    }
+
+    push @a, {};
+    $debitcredit = ($form->{"debit_$i"} == 0) ? "0" : "1";
+
+    $split_safety{   $form->{"debit_$i"}  <=> 0 }++;
+    $split_safety{ - $form->{"credit_$i"} <=> 0 }++;
+
+    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->{"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->{"tax_$i"} = $amount * $rate;
+      }
+    } else {
+      $form->{"tax_$i"} = 0;
+    }
+
+    for (@flds) { $a[$j]->{$_} = $form->{"${_}_$i"} }
+    $count++;
+  }
+
+  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."));
   }
-   
+
+  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"} }
+  }
+
+  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 (($errno = GL->post_transaction(\%myconfig, \%$form)) <= -1) {
+  $form->error($locale->text('Cannot post transaction for a closed period!'))
+    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 ((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!');
-    
+
     $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;
+  # 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;
+  }
+  # /saving the history
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
-sub storno {
-  $lxdebug->enter_sub();
+sub post {
+  $main::lxdebug->enter_sub();
 
-  $form->{id} = 0;
-  $form->{storno} =1;
-  &post;
+  $main::auth->assert('general_ledger');
 
-  $lxdebug->leave_sub();
-}
+  my $form     = $main::form;
+  my $locale   = $main::locale;
 
-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}&|;
+  if ($::myconfig{mandatory_departments} && !$form->{department}) {
+    $form->{saved_message} = $::locale->text('You have to specify a department.');
+    update();
+    exit;
   }
-  chop $previousform;
-  $previousform = $form->escape($previousform, 1);
-  if (!$form->{debitpost}) {
-    $form->{debitpost} = $form->{amount};
-  } 
-  $form->{previousform} = $previousform;
-  &display_split_debit();
 
+  $form->{title}  = $locale->text("$form->{title} General Ledger Transaction");
+  $form->{storno} = 0;
 
-  $lxdebug->leave_sub();
-}
+  post_transaction();
 
-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);
-  # 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->{creditpost}) {
-    $form->{creditpost} = $form->{amount};
-  } 
-  $form->{previousform} = $previousform;
-  &display_split_credit();
-  $lxdebug->leave_sub();
-}
+  remove_draft() if $form->{remove_draft};
 
-sub display_split_credit {
-  $lxdebug->enter_sub();
-  $form->{taxchart} = $form->unescape($form->{taxchart});
-    
-  $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>
+  $form->{callback} = build_std_url("action=add&DONT_LOAD_DRAFT=1", "show_details");
+  $form->redirect($form->{callback});
 
-|;
+  $main::lxdebug->leave_sub();
 }
-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>
 
-</body>
-</html>
-|;
+sub post_as_new {
+  $main::lxdebug->enter_sub();
 
-  $lxdebug->leave_sub();
-}
+  $main::auth->assert('general_ledger');
 
-sub display_split_debit {
-  $lxdebug->enter_sub();
-  $form->{taxchart} = $form->unescape($form->{taxchart});
-    
-  $form->header;
+  my $form     = $main::form;
 
-  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>
+  $form->{id} = 0;
+  &add;
+  $main::lxdebug->leave_sub();
 
-|;
 }
-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>
 
-</body>
-</html>
-|;
+sub storno {
+  $main::lxdebug->enter_sub();
 
-  $lxdebug->leave_sub();
-}
+  $main::auth->assert('general_ledger');
 
-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"};
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $locale   = $main::locale;
 
-    }
-    if ($form->{"credit_$form->{creditrowcount}"}) {
-      $form->{creditrowcount}++;
-    }
-    
-    &display_split_credit;
+  # 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!"));
   }
-  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"};
 
-    }
-    if ($form->{"debit_$form->{debitrowcount}"}) {
-      $form->{debitrowcount}++;
-    }
-    
-    &display_split_debit;
-  }  
-  $lxdebug->leave_sub();
-}
+  GL->storno($form, \%myconfig, $form->{id});
 
-sub close {
-  $lxdebug->enter_sub();
-
-    # save the new form variables before splitting previousform
-    map { $newform{$_} = $form->{$_} } keys %$form;
-
-    $previousform = $form->unescape($form->{previousform});
+  # saving the history
+  if(!exists $form->{addition} && $form->{id} ne "") {
+    $form->{snumbers} = "ordnumber_$form->{ordnumber}";
+    $form->{addition} = "STORNO";
+    $form->save_history;
+  }
+  # /saving the history
 
-    # don't trample on previous variables
-    map { delete $form->{$_} } keys %newform;
+  $form->redirect(sprintf $locale->text("Transaction %d cancelled."), $form->{storno_id});
 
-    # now take it apart and restore original values
-    foreach $item (split /&/, $previousform) {
-      ($key, $value) = split /=/, $item, 2;
-      $value =~ s/%26/&/g;
-      $form->{$key} = $value;
-    }
-    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);;
-        
-      }
-    } 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};
-
-    # 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;