Typos beim entfernen von setupPoints/setupDateFormat
[kivitendo-erp.git] / bin / mozilla / gl.pl
index 5069cef..d54dc70 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;
 
-require "bin/mozilla/arap.pl";
 require "bin/mozilla/common.pl";
+require "bin/mozilla/drafts.pl";
 require "bin/mozilla/reportgenerator.pl";
 
-1;
-
-# end of main
-
 # this is for our long dates
 # $locale->text('January')
 # $locale->text('February')
@@ -75,23 +76,23 @@ require "bin/mozilla/reportgenerator.pl";
 # $locale->text('Dec')
 
 sub add {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  $main::auth->assert('general_ledger');
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+
+  return $main::lxdebug->leave_sub() if (load_draft_maybe());
 
   $form->{title} = "Add";
 
-  $form->{callback} =
-    "$form->{script}?action=add&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 {
-    $tax .=
-      qq|<option value="$_->{id}--$_->{rate}">$_->{taxdescription}  |
-      . ($_->{rate} * 100) . qq| %|
-  } @{ $form->{TAX} };
-
   $form->{rowcount}  = 2;
 
   $form->{debit}  = 0;
@@ -100,51 +101,50 @@ sub add {
 
   # departments
   $form->all_departments(\%myconfig);
-  if (@{ $form->{all_departments} }) {
+  if (@{ $form->{all_departments} || [] }) {
     $form->{selectdepartment} = "<option>\n";
 
     map {
       $form->{selectdepartment} .=
         "<option>$_->{description}--$_->{id}\n"
-    } (@{ $form->{all_departments} });
+    } (@{ $form->{all_departments} || [] });
   }
 
   $form->{show_details} = $myconfig{show_form_details} unless defined $form->{show_details};
 
   &display_form(1);
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 
 }
 
 sub prepare_transaction {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
 
-  GL->transaction(\%myconfig, \%$form);
+  $main::auth->assert('general_ledger');
 
-  map {
-    $tax .=
-      qq|<option value="$_->{id}--$_->{rate}">$_->{taxdescription}  |
-      . ($_->{rate} * 100) . qq| %|
-  } @{ $form->{TAX} };
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+
+  GL->transaction(\%myconfig, \%$form);
 
   $form->{amount} = $form->format_amount(\%myconfig, $form->{amount}, 2);
 
   # departments
   $form->all_departments(\%myconfig);
-  if (@{ $form->{all_departments} }) {
+  if (@{ $form->{all_departments} || [] }) {
     $form->{selectdepartment} = "<option>\n";
 
     map {
       $form->{selectdepartment} .=
         "<option>$_->{description}--$_->{id}\n"
-    } (@{ $form->{all_departments} });
+    } (@{ $form->{all_departments} || [] });
   }
 
   my $i        = 1;
   my $tax      = 0;
   my $taxaccno = "";
-  foreach $ref (@{ $form->{GL} }) {
-    $j = $i - 1;
+  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};
@@ -185,11 +185,16 @@ sub prepare_transaction {
     ($form->datetonum($form->{transdate}, \%myconfig) <=
      $form->datetonum($form->{closedto}, \%myconfig));
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub edit {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  $main::auth->assert('general_ledger');
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
 
   prepare_transaction();
 
@@ -201,221 +206,80 @@ sub edit {
   display_rows();
   form_footer();
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 
 sub search {
-  $lxdebug->enter_sub();
-
-  $form->{title} = $locale->text('Journal');
-
-  $form->all_departments(\%myconfig);
-
-  # departments
-  if (@{ $form->{all_departments} }) {
-    $form->{selectdepartment} = "<option>\n";
-
-    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};
-
-  $form->get_lists("projects" => { "key" => "ALL_PROJECTS",
-                                   "all" => 1 });
-
-  my %project_labels = ();
-  my @project_values = ("");
-  foreach my $item (@{ $form->{"ALL_PROJECTS"} }) {
-    push(@project_values, $item->{"id"});
-    $project_labels{$item->{"id"}} = $item->{"projectnumber"};
-  }
-
-  my $projectnumber =
-    NTI($cgi->popup_menu('-name' => "project_id",
-                         '-values' => \@project_values,
-                         '-labels' => \%project_labels));
-
-  # use JavaScript Calendar or not
-  $form->{jsscript} = 1;
-  $jsscript = "";
-  if ($form->{jsscript}) {
-
-    # with JavaScript Calendar
-    $button1 = qq|
-       <td><input name=datefrom id=datefrom size=11 title="$myconfig{dateformat}" onBlur=\"check_right_date_format(this)\">
-       <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}" onBlur=\"check_right_date_format(this)\">
-       <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}" onBlur=\"check_right_date_format(this)\"></td>|;
-    $button2 =
-      qq|<td><input name=dateto id=dateto size=11 title="$myconfig{dateformat}" onBlur=\"check_right_date_format(this)\"></td>|;
-  }
-  $form->{javascript} .= qq|<script type="text/javascript" src="js/common.js"></script>|;
-  $form->header;
-  $onload = qq|focus()|;
-  $onload .= qq|;setupDateFormat('|. $myconfig{dateformat} .qq|', '|. $locale->text("Falsches Datumsformat!") .qq|')|;
-  $onload .= qq|;setupPoints('|. $myconfig{numberformat} .qq|', '|. $locale->text("wrongformat") .qq|')|;
-  print qq|
-<body onLoad="$onload">
-
-<form method=post action=$form->{script}>
-
-<input type=hidden name=sort value=transdate>
+  $::lxdebug->enter_sub;
+  $::auth->assert('general_ledger');
 
-<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('Project Number') . qq|</th>
-         <td colspan=3>$projectnumber</td>
-       </tr>
-       <tr>
-         <th align=right>| . $locale->text('From') . qq|</th>
-          $button1
-         <th align=right>| . $locale->text('To (time)') . qq|</th>
-          $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>
-                 </tr>
-                 <tr>
-                   <td align=right><input name="l_subtotal" class=checkbox type=checkbox value=Y></td>
-                   <td>| . $locale->text('Subtotal') . qq|</td>
-                   <td align=right><input name="l_projectnumbers" class=checkbox type=checkbox value=Y></td>
-                   <td>| . $locale->text('Project Number') . qq|</td>
-                 </tr>
-               </table>
-             </tr>
-           </table>
-       </tr>
-      </table>
-    </td>
-  </tr>
-  <tr>
-    <td><hr size=3 noshade></td>
-  </tr>
-</table>
-
-$jsscript
-
-<input type=hidden name=nextsub value=generate_report>
+  $::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 ]);
 
-<input type=hidden name=login value=$form->{login}>
-<input type=hidden name=password value=$form->{password}>
+  my $onload = "focus()";
 
-<br>
-<input class=submit type=submit name=action value="|
-    . $locale->text('Continue') . qq|">
-</form>
+  $::form->header;
+  print $::form->parse_html_template('gl/search', {
+    onload => $onload,
+    department_label => sub { ("$_[0]{description}--$_[0]{id}")x2 },
+    employee_label => sub { "$_[0]{id}--$_[0]{name}" },
+  });
 
-</body>
-</html>
-|;
-  $lxdebug->leave_sub();
+  $::lxdebug->leave_sub;
 }
 
 sub create_subtotal_row {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
 
   my ($totals, $columns, $column_alignment, $subtotal_columns, $class) = @_;
 
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+
   my $row = { map { $_ => { 'data' => '', 'class' => $class, 'align' => $column_alignment->{$_}, } } @{ $columns } };
 
   map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $totals->{$_}, 2) } @{ $subtotal_columns };
 
   map { $totals->{$_} = 0 } @{ $subtotal_columns };
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 
   return $row;
 }
 
 sub generate_report {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  $main::auth->assert('general_ledger');
+
+  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
 
-  $form->{sort} ||= "transdate";
+  # ä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);
 
@@ -436,59 +300,56 @@ sub generate_report {
   my $ml = ($form->{ml} =~ /(A|E|Q)/) ? -1 : 1;
 
   my @columns = qw(
-    transdate      id               reference      description
+    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
+    credit_tax     credit_tax_accno projectnumbers balance employee
   );
 
-  my @hidden_variables = qw(accno source reference department description notes project_id datefrom dateto category l_subtotal);
+  # 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);
 
-  my (@options, $date_option);
-  if ($form->{accno}) {
-    push @options, $locale->text('Account') . " : $form->{accno} $form->{account_description}";
-  }
-  if ($form->{source}) {
-    push @options, $locale->text('Source') . " : $form->{source}";
-  }
-  if ($form->{reference}) {
-    push @options, $locale->text('Reference') . " : $form->{reference}";
-  }
   if ($form->{department}) {
     my ($department) = split /--/, $form->{department};
     push @options, $locale->text('Department') . " : $department";
   }
-  if ($form->{description}) {
-    push @options, $locale->text('Description') . " : $form->{description}";
-  }
-  if ($form->{notes}) {
-    push @options, $locale->text('Notes') . " : $form->{notes}";
-  }
-  if ($form->{datefrom}) {
-    $date_option = $locale->text('From') . " " . $locale->date(\%myconfig, $form->{datefrom}, 1);
-  }
-  if ($form->{dateto}) {
-    if ($form->{datefrom}) {
-      $date_option .= " ";
-    }
-    $date_option .= $locale->text('Bis') . " " . $locale->date(\%myconfig, $form->{dateto}, 1);
-  }
-  push @options, $date_option if $date_option;
 
-  my $callback = build_std_url('action=generate_report', @hidden_variables);
+
+  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('Date'), },
+    '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'), },
@@ -503,25 +364,32 @@ sub generate_report {
     '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'), },
   );
 
-  map { $column_defs{$_}->{link}    = $callback . "&sort=${_}" }  qw(id transdate reference source description);
-  map { $column_defs{$_}->{link}    = $callback . "&sort=accno" } qw(debit_accno credit_accno debit_tax_accno credit_tax_accno debit_tax credit_tax);
+  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};
 
   my %column_alignment;
-  map { $column_alignment{$_} = 'right' }  qw(balance id debit credit debit_tax credit_tax);
-  map { $column_alignment{$_} = 'center' } qw(transdate reference description source notes debit_accno credit_accno debit_tax_accno credit_tax_accno);
+  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;
 
   my $report = SL::ReportGenerator->new(\%myconfig, $form);
 
   $report->set_columns(%column_defs);
   $report->set_column_order(@columns);
 
-  $report->set_export_options('generate_report', @hidden_variables);
+  $report->set_export_options('generate_report', @hidden_variables, qw(sort sortdir));
 
-  $report->set_sort_indicator($form->{sort}, 1);
+  $report->set_sort_indicator($form->{sort} eq 'accno' ? 'debit_accno' : $form->{sort}, $form->{sortdir});
 
   $report->set_options('top_info_text'        => join("\n", @options),
                        'output_format'        => 'HTML',
@@ -529,30 +397,18 @@ sub generate_report {
                        'attachment_basename'  => $locale->text('general_ledger_list') . strftime('_%Y%m%d', localtime time),
     );
   $report->set_options_from_form();
+  $locale->set_numberformat_wo_thousands_separator(\%myconfig) if lc($report->{options}->{output_format}) eq 'csv';
 
   # add sort to callback
-  $form->{callback} = "$callback&sort=" . E($form->{sort});
+  $form->{callback} = "$callback&sort=" . E($form->{sort}) . "&sortdir=" . E($form->{sortdir});
 
-  $form->{balance} *= $ml;
-
-  if ($form->{accno} && $form->{balance}) {
-    my $row = {
-      'balance' => {
-        'data'  => $form->format_amount(\%myconfig, $form->{balance}, 2),
-        'align' => 'right',
-      },
-    };
-
-    $report->add_data($row);
-  }
 
   my @totals_columns = qw(debit credit debit_tax credit_tax);
   my %subtotals      = map { $_ => 0 } @totals_columns;
   my %totals         = map { $_ => 0 } @totals_columns;
   my $idx            = 0;
 
-  foreach $ref (@{ $form->{GL} }) {
-    $form->{balance} *= $ml;
+  foreach my $ref (@{ $form->{GL} }) {
 
     my %rows;
 
@@ -562,12 +418,17 @@ sub generate_report {
         my $value         = $ref->{$key}->{$idx};
         $subtotals{$key} += $value;
         $totals{$key}    += $value;
-        $form->{balance}  = abs($form->{balance}) - abs($value);
+        if ($key =~ /debit.*/) {
+          $ml = -1;
+        } else {
+          $ml = 1;
+        }
+        $form->{balance}  = $form->{balance} + $value * $ml;
         push @{ $rows{$key} }, $form->format_amount(\%myconfig, $value, 2);
       }
     }
 
-    foreach my $key (qw(debit_accno credit_accno debit_tax_accno credit_tax_accno ac_transdate)) {
+    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} }) ];
     }
@@ -575,12 +436,23 @@ sub generate_report {
     my $row = { };
     map { $row->{$_} = { 'data' => '', 'align' => $column_alignment{$_} } } @columns;
 
-    $row->{balance}->{data}        = $form->format_amount(\%myconfig, $form->{balance}, 2);
+    my $sh = "";
+    if ($form->{balance} < 0) {
+      $sh = " S";
+      $ml = -1;
+    } elsif ($form->{balance} > 0) {
+      $sh = " H";
+      $ml = 1;
+    }
+    my $data = $form->format_amount(\%myconfig, ($form->{balance} * $ml), 2);
+    $data .= $sh;
+
+    $row->{balance}->{data}        = $data;
     $row->{projectnumbers}->{data} = join ", ", sort { lc($a) cmp lc($b) } keys %{ $ref->{projectnumbers} };
 
-    map { $row->{$_}->{data} = $ref->{$_} } qw(id reference description source notes);
+    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);
+    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} } ];
@@ -592,7 +464,7 @@ sub generate_report {
 
     my $row_set = [ $row ];
 
-    if (($form->{l_subtotal} eq 'Y')
+    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');
@@ -603,18 +475,28 @@ sub generate_report {
     $idx++;
   }
 
-  $report->add_separator();
-
   # = 0 for balanced ledger
   my $balanced_ledger = $totals{debit} + $totals{debit_tax} - $totals{credit} - $totals{credit_tax};
 
   my $row = create_subtotal_row(\%totals, \@columns, \%column_alignment, [ qw(debit credit debit_tax credit_tax) ], 'listtotal');
-  $row->{balance} = {
-    'data'  => $form->format_amount(\%myconfig, $form->{balance} * $ml, 2),
-    'align' => 'right',
-    'class' => 'listtotal',
-  };
-  $report->add_data($row);
+
+  my $sh = "";
+  if ($form->{balance} < 0) {
+    $sh = " S";
+    $ml = -1;
+  } elsif ($form->{balance} > 0) {
+    $sh = " H";
+    $ml = 1;
+  }
+  my $data = $form->format_amount(\%myconfig, ($form->{balance} * $ml), 2);
+  $data .= $sh;
+
+  $row->{balance}->{data}        = $data;
+
+  if ( !$form->{report_generator_csv_options_for_import} ) {
+    $report->add_separator();
+    $report->add_data($row);
+  }
 
   my $raw_bottom_info_text;
 
@@ -633,11 +515,16 @@ sub generate_report {
 
   $report->generate_with_headers();
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub update {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  $main::auth->assert('general_ledger');
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
 
   $form->{oldtransdate} = $form->{transdate};
 
@@ -647,8 +534,7 @@ sub update {
   my $credittax   = 0;
   my $debitcount  = 0;
   my $creditcount = 0;
-  $debitlock  = 0;
-  $creditlock = 0;
+  my ($debitcredit, $amount);
 
   my @flds =
     qw(accno debit credit projectnumber fx_transaction source memo tax taxchart);
@@ -673,19 +559,19 @@ sub update {
         $form->{"credit_$i"} = 0;
         $form->{"tax_$i"}    = 0;
         $creditcount--;
-        $creditlock = 1;
+        $form->{creditlock} = 1;
       }
       if (($creditcount >= 2) && ($debitcount == 2)) {
         $form->{"debit_$i"} = 0;
         $form->{"tax_$i"}   = 0;
         $debitcount--;
-        $debitlock = 1;
+        $form->{debitlock} = 1;
       }
       if (($creditcount == 1) && ($debitcount == 2)) {
-        $creditlock = 1;
+        $form->{creditlock} = 1;
       }
       if (($creditcount == 2) && ($debitcount == 1)) {
-        $debitlock = 1;
+        $form->{debitlock} = 1;
       }
       if ($debitcredit && $credittax) {
         $form->{"taxchart_$i"} = "0--0.00";
@@ -697,27 +583,25 @@ sub update {
         ($form->{"debit_$i"} == 0)
         ? $form->{"credit_$i"}
         : $form->{"debit_$i"};
-      $j = $#a;
+      my $j = $#a;
       if (($debitcredit && $credittax) || (!$debitcredit && $debittax)) {
         $form->{"taxchart_$i"} = "0--0.00";
         $form->{"tax_$i"}      = 0;
       }
-      if (!$form->{"korrektur_$i"}) {
-        ($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;
-          }
+      my ($taxkey, $rate) = split(/--/, $form->{"taxchart_$i"});
+      if ($taxkey > 1) {
+        if ($debitcredit) {
+          $debittax = 1;
         } else {
-          $form->{"tax_$i"} = 0;
+          $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"} }
@@ -725,25 +609,30 @@ sub update {
     }
   }
 
-  for $i (1 .. $count) {
-    $j = $i - 1;
+  for my $i (1 .. $count) {
+    my $j = $i - 1;
     for (@flds) { $form->{"${_}_$i"} = $a[$j]->{$_} }
   }
 
-  for $i ($count + 1 .. $form->{rowcount}) {
+  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 {
   my ($init) = @_;
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  $main::auth->assert('general_ledger');
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
 
   &form_header($init);
 
@@ -755,29 +644,24 @@ sub display_form {
   #   }
   &display_rows($init);
   &form_footer;
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 
 }
 
 sub display_rows {
   my ($init) = @_;
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  $main::auth->assert('general_ledger');
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $cgi      = $::request->{cgi};
 
   $form->{debit_1}     = 0 if !$form->{"debit_1"};
   $form->{totaldebit}  = 0;
   $form->{totalcredit} = 0;
 
-  my @old_project_ids = ();
-  map({ push(@old_project_ids, $form->{"project_id_$_"})
-          if ($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");
-
   my %project_labels = ();
   my @project_values = ("");
   foreach my $item (@{ $form->{"ALL_PROJECTS"} }) {
@@ -790,10 +674,13 @@ sub display_rows {
   my %charts = ();
   my $taxchart_init;
   foreach my $item (@{ $form->{ALL_CHARTS} }) {
-    my $key = Q($item->{accno}) . "--" . Q($item->{tax_id});
-    $taxchart_init = $item->{taxkey_id} unless (@chart_values);
+    if ($item->{charttype} eq 'H'){ #falls überschrift
+      next;                         #überspringen (Bug 1150)
+    }
+    my $key = $item->{accno} . "--" . $item->{tax_id};
+    $taxchart_init = $item->{tax_id} unless (@chart_values);
     push(@chart_values, $key);
-    $chart_labels{$key} = H($item->{accno}) . "--" . H($item->{description});
+    $chart_labels{$key} = $item->{accno} . "--" . $item->{description};
     $charts{$item->{accno}} = $item;
   }
 
@@ -801,20 +688,26 @@ sub display_rows {
   my @taxchart_values = ();
   my %taxcharts = ();
   foreach my $item (@{ $form->{ALL_TAXCHARTS} }) {
-    my $key = Q($item->{id}) . "--" . Q($item->{rate});
-    $taxchart_init = $key if ($taxchart_init eq $item->{taxkey});
+    my $key = $item->{id} . "--" . $item->{rate};
+    $taxchart_init = $key if ($taxchart_init == $item->{id});
     push(@taxchart_values, $key);
-    $taxchart_labels{$key} = H($item->{taxdescription}) . " " .
-      H($item->{rate} * 100) . ' %';
+    $taxchart_labels{$key} = $item->{taxdescription} . " " . $item->{rate} * 100 . ' %';
     $taxcharts{$item->{id}} = $item;
   }
 
-  for $i (1 .. $form->{rowcount}) {
-
-    $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>|;
+  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">|;
+    }
 
     my $selected_accno_full;
     my ($accno_row) = split(/--/, $form->{"accno_$i"});
@@ -832,13 +725,13 @@ sub display_rows {
       $selected_taxchart = "$item->{id}--$item->{rate}";
     }
 
-    $selected_accno = '' if ($init);
-    $selected_taxchart = $taxchart_init unless ($selected_taxchart ne "");
+    $selected_accno      = '' if ($init);
+    $selected_taxchart ||= $taxchart_init;
 
-    $accno = qq|<td>| .
+    my $accno = qq|<td>| .
       NTI($cgi->popup_menu('-name' => "accno_$i",
                            '-id' => "accno_$i",
-                           '-onChange' => "setTaxkey(this, $i)",
+                           '-onChange' => "setTaxkey($i)",
                            '-style' => 'width:200px',
                            '-values' => \@chart_values,
                            '-labels' => \%chart_labels,
@@ -846,7 +739,7 @@ sub display_rows {
       . $cgi->hidden('-name' => "previous_accno_$i",
                      '-default' => $selected_accno_full)
       . qq|</td>|;
-    $tax = qq|<td>| .
+    my $tax_ddbox = qq|<td>| .
       NTI($cgi->popup_menu('-name' => "taxchart_$i",
                            '-id' => "taxchart_$i",
                            '-style' => 'width:200px',
@@ -855,9 +748,8 @@ sub display_rows {
                            '-default' => $selected_taxchart))
       . qq|</td>|;
 
+    my ($fx_transaction, $checked);
     if ($init) {
-      $korrektur =
-        qq|<td><input type="checkbox" name="korrektur_$i" value="1"></td>|;
       if ($form->{transfer}) {
         $fx_transaction = qq|
         <td><input name="fx_transaction_$i" class=checkbox type=checkbox value=1></td>
@@ -887,19 +779,14 @@ sub display_rows {
       if ($i < $form->{rowcount}) {
         if ($form->{transfer}) {
           $checked = ($form->{"fx_transaction_$i"}) ? "1" : "";
-          $x = ($checked) ? "x" : "";
+          my $x = ($checked) ? "x" : "";
           $fx_transaction = qq|
       <td><input type=hidden name="fx_transaction_$i" value="$checked">$x</td>
     |;
         }
-        $checked = ($form->{"korrektur_$i"}) ? "checked" : "";
-        $korrektur =
-          qq|<td><input type="checkbox" name="korrektur_$i" value="1" $checked></td>|;
         $form->hide_form("accno_$i");
 
       } else {
-        $korrektur =
-          qq|<td><input type="checkbox" name="korrektur_$i" value="1"></td>|;
         if ($form->{transfer}) {
           $fx_transaction = qq|
       <td><input name="fx_transaction_$i" class=checkbox type=checkbox value=1></td>
@@ -910,9 +797,9 @@ sub display_rows {
     my $debitreadonly  = "";
     my $creditreadonly = "";
     if ($i == $form->{rowcount}) {
-      if ($debitlock) {
+      if ($form->{debitlock}) {
         $debitreadonly = "readonly";
-      } elsif ($creditlock) {
+      } elsif ($form->{creditlock}) {
         $creditreadonly = "readonly";
       }
     }
@@ -922,17 +809,19 @@ sub display_rows {
                            '-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 = 'onkeyup="copy_debit_to_credit()"' if $i == 1;
+    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 name="tax_$i" size=6 value="$form->{"tax_$i"}"></td>
-    $korrektur
-    $tax|;
+    <td><input type="hidden" name="tax_$i" value="$form->{"tax_$i"}">$form->{"tax_$i"}</td>
+    $tax_ddbox|;
 
     if ($form->{show_details}) {
       print qq|
@@ -940,6 +829,12 @@ sub display_rows {
     $memo
     <td>$projectnumber</td>
 |;
+    } else {
+    print qq|
+    $source_hidden
+    $memo_hidden
+    $projectnumber_hidden
+    |;
     }
     print qq|
   </tr>
@@ -948,326 +843,98 @@ sub display_rows {
 
   $form->hide_form(qw(rowcount selectaccno));
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 
 }
 
 sub form_header {
-  my ($init) = @_;
-  $lxdebug->enter_sub();
-  $title         = $form->{title};
-  $form->{title} = $locale->text("$title General Ledger Transaction");
-  $readonly      = ($form->{id}) ? "readonly" : "";
+  $::lxdebug->enter_sub;
+  $::auth->assert('general_ledger');
 
-  $show_details_checked = "checked" if $form->{show_details};
-
-  # $locale->text('Add General Ledger Transaction')
-  # $locale->text('Edit General Ledger Transaction')
-
-  map { $form->{$_} =~ s/\"/&quot;/g }
-    qw(reference description chart taxchart);
-
-  $form->{javascript} = qq|<script type="text/javascript">
-  <!--
-  function setTaxkey(accno, row) {
-    var taxkey = accno.options[accno.selectedIndex].value;
-    var reg = /--([0-9]*)/;
-    var found = reg.exec(taxkey);
-    var index = found[1];
-    index = parseInt(index);
-    var tax = 'taxchart_' + row;
-    for (var i = 0; i < document.getElementById(tax).options.length; ++i) {
-      var reg2 = new RegExp("^"+ index, "");
-      if (reg2.exec(document.getElementById(tax).options[i].value)) {
-        document.getElementById(tax).options[i].selected = true;
-        break;
-      }
-    }
-  };
+  my ($init) = @_;
 
-  function copy_debit_to_credit() {
-    var txt = document.getElementsByName('debit_1')[0].value;
-    document.getElementsByName('credit_2')[0].value = txt;
-  };
+  my @old_project_ids = grep { $_ } map{ $::form->{"project_id_$_"} } 1..$::form->{rowcount};
 
-  //-->
-  </script>|;
-  $form->{javascript} .= qq|<script type="text/javascript" src="js/show_form_details.js"></script>|;
+  $::form->get_lists("projects"  => { "key"       => "ALL_PROJECTS",
+                                    "all"       => 0,
+                                    "old_id"    => \@old_project_ids },
+                   "charts"    => { "key"       => "ALL_CHARTS",
+                                    "transdate" => $::form->{transdate} },
+                   "taxcharts" => "ALL_TAXCHARTS");
 
-  $form->{selectdepartment} =~ s/ selected//;
-  $form->{selectdepartment} =~
-    s/option>\Q$form->{department}\E/option selected>$form->{department}/;
+  GL->get_chart_balances('charts' => $::form->{ALL_CHARTS});
 
-  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}" $readonly>|;
-  }
+  my $title      = $::form->{title};
+  $::form->{title} = $::locale->text("$title General Ledger Transaction");
+  # $locale->text('Add General Ledger Transaction')
+  # $locale->text('Edit General Ledger Transaction')
 
-  $taxincluded = ($form->{taxincluded}) ? "checked" : "";
+  map { $::form->{$_} =~ s/\"/&quot;/g }
+    qw(chart taxchart);
 
-  if ($init) {
-    $taxincluded = "checked";
-  }
+  $::form->{selectdepartment} =~ s/ selected//;
+  $::form->{selectdepartment} =~
+    s/option>\Q$::form->{department}\E/option selected>$::form->{department}/;
 
-  $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};
   if ($init) {
-    $form->{fokus} = "gl.reference";
-  } else {
-    $form->{fokus} = qq|gl.accno_$form->{rowcount}|;
-  }
-
-  # use JavaScript Calendar or not
-  $form->{jsscript} = 1;
-  $jsscript = "";
-  if ($form->{jsscript}) {
-
-    # with JavaScript Calendar
-    $button1 = qq|
-       <td><input name=transdate id=transdate size=11 title="$myconfig{dateformat}" value="$form->{transdate}" $readonly onBlur=\"check_right_date_format(this)\">
-       <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}" $readonly onBlur=\"check_right_date_format(this)\"></td>|;
-  }
-
-  $form->{previous_id}     ||= "--";
-  $form->{previous_gldate} ||= "--";
-
-  $form->header;
-
-  print qq|
-<body onLoad="fokus()">
-
-<form method=post name="gl" action=$form->{script}>
-|;
-
-  $form->hide_form(qw(id closedto locked storno storno_id previous_id previous_gldate));
-
-  print qq|
-<input type=hidden name=title value="$title">
-
-
-<table width=100%>
-  <tr>
-    <th class=listtop>$form->{title}</th>
-  </tr>
-  <tr height="5"></tr>
-  <tr>
-    <td>
-      <table width=100%>
-        <tr>
-          <td colspan="6" align="left">|
-    . $locale->text("Previous transnumber text")
-    . " $form->{previous_id} "
-    . $locale->text("Previous transdate text")
-    . " $form->{previous_gldate}"
-    . qq|</td>
-        </tr>
-       <tr>
-         <th align=right>| . $locale->text('Reference') . qq|</th>
-         <td><input name=reference size=20 value="$form->{reference}" $readonly></td>
-         <td align=left>
-           <table>
-             <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>
-             <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 onBlur=\"check_right_date_format(this)\"></td>
-             </tr>
-           </table>
-         </td>
-       </tr>|;
-  }
-  print qq|    
-       $department|;
-  if ($form->{id}) {
-    print qq|
-       <tr>
-         <th align=right width=1%>| . $locale->text('Description') . qq|</th>
-         <td width=1%>$description</td>
-          <td>
-           <table>
-             <tr>
-               <th align=left>| . $locale->text('MwSt. inkl.') . qq|</th>
-               <td><input type=checkbox name=taxincluded value=1 $taxincluded></td>
-             </tr>
-           </table>
-        </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=20  value="| . H($form->{employee}) . qq|" readonly></td>
-             </tr>
-           </table>
-         </td>
-       </tr>|;
+    $::form->{fokus} = "gl.reference";
+    $::form->{taxincluded} = "1";
   } else {
-    print qq|
-       <tr>
-         <th align=left width=1%>| . $locale->text('Description') . qq|</th>
-         <td width=1%>$description</td>
-         <td>
-           <table>
-             <tr>
-               <th align=left>| . $locale->text('MwSt. inkl.') . qq|</th>
-               <td><input type=checkbox name=taxincluded value=1 $taxincluded></td>
-             </tr>
-           </table>
-        </td>
-       </tr>|;
+    $::form->{fokus} = qq|gl.accno_$::form->{rowcount}|;
   }
 
-  print qq|<tr>
-       <td width="1%" align="right" nowrap>| . $locale->text('Show details') . qq|</td>
-       <td width="1%"><input type="checkbox" onclick="show_form_details();" name="show_details" value="1" $show_details_checked></td>
-      </tr>|;
-
-  print qq|
-      <tr>
-      <td colspan=4>
-          <table width=100%>
-          <tr class=listheading>
-         <th class=listheading style="width:15%">|
-    . $locale->text('Account') . qq|</th>
-         <th class=listheading style="width:10%">|
-    . $locale->text('Debit') . qq|</th>
-         <th class=listheading style="width:10%">|
-    . $locale->text('Credit') . qq|</th>
-          <th class=listheading style="width:10%">|
-    . $locale->text('Tax') . qq|</th>
-          <th class=listheading style="width:5%">|
-    . $locale->text('Korrektur') . qq|</th>
-          <th class=listheading style="width:10%">|
-    . $locale->text('Taxkey') . qq|</th>|;
-
-  if ($form->{show_details}) {
-    print qq|
-         <th class=listheading style="width:20%">| . $locale->text('Source') . qq|</th>
-         <th class=listheading style="width:20%">| . $locale->text('Memo') . qq|</th>
-         <th class=listheading style="width:20%">| . $locale->text('Project Number') . qq|</th>
-|;
-  }
+  $::form->{previous_id}     ||= "--";
+  $::form->{previous_gldate} ||= "--";
 
-  print qq|
-       </tr>
+  $::form->header;
+  print $::form->parse_html_template('gl/form_header', {
+    hide_title => $title,
+  });
 
-$jsscript
-|;
-  $lxdebug->leave_sub();
+  $::lxdebug->leave_sub;
 
 }
 
 sub form_footer {
-  $lxdebug->enter_sub();
-  ($dec) = ($form->{totaldebit} =~ /\.(\d+)/);
-  $dec = length $dec;
-  $decimalplaces = ($dec > 2) ? $dec : 2;
-  $radieren = ($form->current_date(\%myconfig) eq $form->{gldate}) ? 1 : 0;
+  $::lxdebug->enter_sub;
+  $::auth->assert('general_ledger');
 
-  map {
-    $form->{$_} = $form->format_amount(\%myconfig, $form->{$_}, 2, "&nbsp;")
-  } qw(totaldebit totalcredit);
-
-  print qq|
-    <tr class=listtotal>
-    <td></td>
-    <th align=right class=listtotal> $form->{totaldebit}</th>
-    <th align=right class=listtotal> $form->{totalcredit}</th> 
-    <td colspan=6></td>
-    </tr>
-  </table>
-  </td>
-  </tr>
-</table>
+  my ($follow_ups, $follow_ups_due);
 
-<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>
-|;
-
-  $transdate = $form->datetonum($form->{transdate}, \%myconfig);
-  $closedto  = $form->datetonum($form->{closedto},  \%myconfig);
-
-  if ($form->{id}) {
-
-    if (!$form->{storno}) {
-      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|">|;
-    }
-
-  } else {
-    if ($transdate > $closedto) {
-      print qq|
-        <input class=submit type=submit name=action id=update_button value="| . $locale->text('Update') . qq|">
-        <input class=submit type=submit name=action value="| . $locale->text('Post') . qq|">|;
-    }
+  if ($::form->{id}) {
+    $follow_ups     = FU->follow_ups('trans_id' => $::form->{id});
+    $follow_ups_due = sum map { $_->{due} * 1 } @{ $follow_ups || [] };
   }
 
-  print "
-  </form>
+  my $radieren = $::form->current_date(\%::myconfig) eq $::form->{gldate};
 
-</body>
-</html>
-";
-  $lxdebug->leave_sub();
+  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);
 
   delete $form->{header};
 
-  foreach $key (keys %$form) {
+  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|;
   }
 
@@ -1282,37 +949,46 @@ sub delete {
     . $locale->text('Yes') . qq|">
 </form>
 |;
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 
 }
 
 sub yes {
-  $lxdebug->enter_sub();
+  $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($form->dbconnect(\%myconfig));
+        $form->{addition} = "DELETED";
+        $form->save_history;
       }
-    # /saving the 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 {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $locale   = $main::locale;
 
   # check if there is something in reference and date
   $form->isblank("reference",   $locale->text('Reference missing!'));
   $form->isblank("transdate",   $locale->text('Transaction Date missing!'));
   $form->isblank("description", $locale->text('Description missing!'));
 
-  $transdate = $form->datetonum($form->{transdate}, \%myconfig);
-  $closedto  = $form->datetonum($form->{closedto},  \%myconfig);
+  my $transdate = $form->datetonum($form->{transdate}, \%myconfig);
+  my $closedto  = $form->datetonum($form->{closedto},  \%myconfig);
 
   my @a           = ();
   my $count       = 0;
@@ -1320,8 +996,8 @@ sub post_transaction {
   my $credittax   = 0;
   my $debitcount  = 0;
   my $creditcount = 0;
-  $creditlock = 0;
-  $debitlock  = 0;
+  my $debitcredit;
+  my %split_safety = ();
 
   my @flds = qw(accno debit credit projectnumber fx_transaction source memo tax taxchart);
 
@@ -1335,6 +1011,9 @@ sub post_transaction {
     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 {
@@ -1345,19 +1024,19 @@ sub post_transaction {
       $form->{"credit_$i"} = 0;
       $form->{"tax_$i"}    = 0;
       $creditcount--;
-      $creditlock = 1;
+      $form->{creditlock} = 1;
     }
     if (($creditcount >= 2) && ($debitcount == 2)) {
       $form->{"debit_$i"} = 0;
       $form->{"tax_$i"}   = 0;
       $debitcount--;
-      $debitlock = 1;
+      $form->{debitlock} = 1;
     }
     if (($creditcount == 1) && ($debitcount == 2)) {
-      $creditlock = 1;
+      $form->{creditlock} = 1;
     }
     if (($creditcount == 2) && ($debitcount == 1)) {
-      $debitlock = 1;
+      $form->{debitlock} = 1;
     }
     if ($debitcredit && $credittax) {
       $form->{"taxchart_$i"} = "0--0.00";
@@ -1365,60 +1044,57 @@ sub post_transaction {
     if (!$debitcredit && $debittax) {
       $form->{"taxchart_$i"} = "0--0.00";
     }
-    $amount = ($form->{"debit_$i"} == 0)
+    my $amount = ($form->{"debit_$i"} == 0)
             ? $form->{"credit_$i"}
             : $form->{"debit_$i"};
-    $j = $#a;
+    my $j = $#a;
     if (($debitcredit && $credittax) || (!$debitcredit && $debittax)) {
       $form->{"taxchart_$i"} = "0--0.00";
       $form->{"tax_$i"}      = 0;
     }
-    if (!$form->{"korrektur_$i"}) {
-      ($taxkey, $rate) = split(/--/, $form->{"taxchart_$i"});
-      if ($taxkey > 1) {
+    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) {
-          $debittax = 1;
+          $form->{"debit_$i"} = $form->{"debit_$i"} - $form->{"tax_$i"};
         } else {
-          $credittax = 1;
+          $form->{"credit_$i"} = $form->{"credit_$i"} - $form->{"tax_$i"};
         }
-        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;
-      }
-    } elsif ($form->{taxincluded}) {
-      if ($debitcredit) {
-        $form->{"debit_$i"} = $form->{"debit_$i"} - $form->{"tax_$i"};
       } else {
-        $form->{"credit_$i"} = $form->{"credit_$i"} - $form->{"tax_$i"};
+        $form->{"tax_$i"} = $amount * $rate;
       }
+    } else {
+      $form->{"tax_$i"} = 0;
     }
 
     for (@flds) { $a[$j]->{$_} = $form->{"${_}_$i"} }
     $count++;
   }
 
-  for $i (1 .. $count) {
-    $j = $i - 1;
+  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 $i ($count + 1 .. $form->{rowcount}) {
+  for my $i ($count + 1 .. $form->{rowcount}) {
     for (@flds) { delete $form->{"${_}_$i"} }
   }
 
-  for $i (1 .. $form->{rowcount}) {
-    $dr  = $form->{"debit_$i"};
-    $cr  = $form->{"credit_$i"};
-    $tax = $form->{"tax_$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!'));
     }
@@ -1426,22 +1102,23 @@ sub post_transaction {
     $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);
+    if ($form->date_closed($form->{"transdate"}, \%myconfig));
   if ($form->round_amount($debit, 2) != $form->round_amount($credit, 2)) {
     $form->error($locale->text('Out of balance transaction!'));
   }
-  
+
   if ($form->round_amount($debit, 2) + $form->round_amount($credit, 2) == 0) {
     $form->error($locale->text('Empty transaction!'));
   }
-  
-  if (($errno = GL->post_transaction(\%myconfig, \%$form)) <= -1) {
+
+  if ((my $errno = GL->post_transaction(\%myconfig, \%$form)) <= -1) {
     $errno *= -1;
+    my @err;
     $err[1] = $locale->text('Cannot have a value in both Debit and Credit!');
     $err[2] = $locale->text('Debit and credit out of balance!');
     $err[3] = $locale->text('Cannot post a transaction without a value!');
@@ -1453,39 +1130,62 @@ sub post_transaction {
   if(!exists $form->{addition} && $form->{id} ne "") {
     $form->{snumbers} = qq|ordnumber_| . $form->{ordnumber};
     $form->{addition} = "SAVED";
-    $form->{what_done} = $locale->text("Buchungsnummer") . " = " . $form->{id}; 
-    $form->save_history($form->dbconnect(\%myconfig));
+    $form->{what_done} = $locale->text("Buchungsnummer") . " = " . $form->{id};
+    $form->save_history;
   }
-  # /saving the history 
+  # /saving the history
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub post {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  $main::auth->assert('general_ledger');
+
+  my $form     = $main::form;
+  my $locale   = $main::locale;
+
+  if ($::myconfig{mandatory_departments} && !$form->{department}) {
+    $form->{saved_message} = $::locale->text('You have to specify a department.');
+    update();
+    exit;
+  }
 
   $form->{title}  = $locale->text("$form->{title} General Ledger Transaction");
   $form->{storno} = 0;
 
   post_transaction();
 
-  $form->{callback} = build_std_url("action=add", "show_details");
+  remove_draft() if $form->{remove_draft};
+
+  $form->{callback} = build_std_url("action=add&DONT_LOAD_DRAFT=1", "show_details");
   $form->redirect($form->{callback});
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub post_as_new {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  $main::auth->assert('general_ledger');
+
+  my $form     = $main::form;
 
   $form->{id} = 0;
   &add;
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 
 }
 
 sub storno {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  $main::auth->assert('general_ledger');
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $locale   = $main::locale;
 
   # don't cancel cancelled transactions
   if (IS->has_storno(\%myconfig, $form, 'gl')) {
@@ -1499,12 +1199,17 @@ sub storno {
   if(!exists $form->{addition} && $form->{id} ne "") {
     $form->{snumbers} = "ordnumber_$form->{ordnumber}";
     $form->{addition} = "STORNO";
-    $form->save_history($form->dbconnect(\%myconfig));
+    $form->save_history;
   }
-  # /saving the history 
+  # /saving the history
 
-  $form->redirect(sprintf $locale->text("Transaction %d cancelled."), $form->{storno_id}); 
+  $form->redirect(sprintf $locale->text("Transaction %d cancelled."), $form->{storno_id});
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
+sub continue {
+  call_sub($main::form->{nextsub});
+}
+
+1;