Historien Suchmaschine: Stacküberlauf vermeiden
[kivitendo-erp.git] / bin / mozilla / ar.pl
index 25ef7ce..dc7074c 100644 (file)
@@ -24,7 +24,8 @@
 # GNU General Public License for more details.
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1335, USA.
 #======================================================================
 #
 # Accounts Receivables
 
 use POSIX qw(strftime);
 use List::Util qw(sum first max);
+use List::UtilsBy qw(sort_by);
 
 use SL::AR;
 use SL::FU;
+use SL::GL;
 use SL::IS;
-use SL::PE;
 use SL::DB::Default;
+use SL::DB::Invoice;
 use SL::ReportGenerator;
 
 require "bin/mozilla/arap.pl";
 require "bin/mozilla/common.pl";
-require "bin/mozilla/drafts.pl";
 require "bin/mozilla/reportgenerator.pl";
 
 use strict;
@@ -80,13 +82,11 @@ use strict;
 sub add {
   $main::lxdebug->enter_sub();
 
-  $main::auth->assert('general_ledger');
+  $main::auth->assert('ar_transactions');
 
   my $form     = $main::form;
   my %myconfig = %main::myconfig;
 
-  return $main::lxdebug->leave_sub() if (load_draft_maybe());
-
   # saving the history
   if(!exists $form->{addition} && ($form->{id} ne "")) {
     $form->{snumbers} = qq|invnumber_| . $form->{invnumber};
@@ -96,12 +96,18 @@ sub add {
   # /saving the history
 
   $form->{title}    = "Add";
-  $form->{callback} = "ar.pl?action=add&DONT_LOAD_DRAFT=1" unless $form->{callback};
+  $form->{callback} = "ar.pl?action=add" unless $form->{callback};
 
   AR->get_transdate(\%myconfig, $form);
   $form->{initial_transdate} = $form->{transdate};
   create_links(dont_save => 1);
   $form->{transdate} = $form->{initial_transdate};
+
+  if ($form->{customer_id}) {
+    my $last_used_ar_chart = SL::DB::Customer->load_cached($form->{customer_id})->last_used_ar_chart;
+    $form->{"AR_amount_chart_id_1"} = $last_used_ar_chart->id if $last_used_ar_chart;
+  }
+
   &display_form;
   $main::lxdebug->leave_sub();
 }
@@ -109,7 +115,7 @@ sub add {
 sub edit {
   $main::lxdebug->enter_sub();
 
-  $main::auth->assert('general_ledger');
+  $main::auth->assert('ar_transactions');
 
   my $form     = $main::form;
 
@@ -128,7 +134,7 @@ sub edit {
 sub display_form {
   $main::lxdebug->enter_sub();
 
-  $main::auth->assert('general_ledger');
+  $main::auth->assert('ar_transactions');
 
   my $form     = $main::form;
 
@@ -138,21 +144,29 @@ sub display_form {
   $main::lxdebug->leave_sub();
 }
 
+sub _retrieve_invoice_object {
+  return undef if !$::form->{id};
+  return $::form->{invoice_obj} if $::form->{invoice_obj} && $::form->{invoice_obj}->id == $::form->{id};
+  return SL::DB::Invoice->new(id => $::form->{id})->load;
+}
+
 sub create_links {
   $main::lxdebug->enter_sub();
 
-  $main::auth->assert('general_ledger');
+  $main::auth->assert('ar_transactions');
 
   my %params   = @_;
   my $form     = $main::form;
   my %myconfig = %main::myconfig;
 
   $form->create_links("AR", \%myconfig, "customer");
+  $form->{invoice_obj} = _retrieve_invoice_object();
 
   my %saved;
   if (!$params{dont_save}) {
     %saved = map { ($_ => $form->{$_}) } qw(direct_debit id taxincluded);
     $saved{duedate} = $form->{duedate} if $form->{duedate};
+    $saved{currency} = $form->{currency} if $form->{currency};
   }
 
   IS->get_customer(\%myconfig, \%$form);
@@ -160,10 +174,12 @@ sub create_links {
   $form->{$_}          = $saved{$_} for keys %saved;
   $form->{oldcustomer} = "$form->{customer}--$form->{customer_id}";
   $form->{rowcount}    = 1;
+  $form->{AR_chart_id} = $form->{acc_trans} && $form->{acc_trans}->{AR} ? $form->{acc_trans}->{AR}->[0]->{chart_id} : $form->{AR_links}->{AR}->[0]->{chart_id};
 
   # currencies
   $form->{defaultcurrency} = $form->get_default_currency(\%myconfig);
 
+  $form->{selectcurrency} = "";
   map { $form->{selectcurrency} .= "<option>$_\n" } $form->get_all_currencies(\%myconfig);
 
   # customers
@@ -173,16 +189,7 @@ sub create_links {
       (@{ $form->{all_customer} });
   }
 
-  # departments
-  if (@{ $form->{all_departments} || [] }) {
-    $form->{selectdepartment} = "<option>\n";
-    $form->{department}       = "$form->{department}--$form->{department_id}";
-
-    map {
-      $form->{selectdepartment} .=
-        "<option>$_->{description}--$_->{id}\n"
-    } (@{ $form->{all_departments} || [] });
-  }
+  $form->{ALL_DEPARTMENTS} = SL::DB::Manager::Department->get_all;
 
   $form->{employee} = "$form->{employee}--$form->{employee_id}";
 
@@ -208,45 +215,25 @@ sub create_links {
 sub form_header {
   $main::lxdebug->enter_sub();
 
-  $main::auth->assert('general_ledger');
+  $main::auth->assert('ar_transactions');
 
   my $form     = $main::form;
   my %myconfig = %main::myconfig;
   my $locale   = $main::locale;
   my $cgi      = $::request->{cgi};
 
+  $form->{invoice_obj} = _retrieve_invoice_object();
+
   my ($title, $readonly, $exchangerate, $rows);
-  my ($notes, $department, $customer, $employee, $amount, $project);
-  my ($ARselected);
+  my ($notes, $customer, $employee, $amount, $project);
 
+  $form->{initial_focus} = !($form->{amount_1} * 1) ? 'customer' : 'row_' . $form->{rowcount};
 
   $title = $form->{title};
   # $locale->text('Add Accounts Receivables Transaction')
   # $locale->text('Edit Accounts Receivables Transaction')
   $form->{title} = $locale->text("$title Accounts Receivables Transaction");
 
-  $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;
-      }
-    }
-  };
-  //-->
-  </script>|;
-  # show history button js
-  $form->{javascript} .= qq|<script type="text/javascript" src="js/show_history.js"></script>|;
-  #/show history button js
   $readonly = ($form->{id}) ? "readonly" : "";
 
   $form->{radier} = ($::instance_conf->get_ar_changeable == 2)
@@ -255,7 +242,7 @@ sub form_header {
   $readonly = ($form->{radier}) ? "" : $readonly;
 
   # set option selected
-  foreach my $item (qw(customer currency department employee)) {
+  foreach my $item (qw(customer currency employee)) {
     $form->{"select$item"} =~ s/ selected//;
     $form->{"select$item"} =~ s/option>\Q$form->{$item}\E/option selected>$form->{$item}/;
   }
@@ -263,6 +250,9 @@ sub form_header {
   $form->{forex}        = $form->check_exchangerate( \%myconfig, $form->{currency}, $form->{transdate}, 'buy');
   $form->{exchangerate} = $form->{forex} if $form->{forex};
 
+  # format exchangerate
+  $form->{exchangerate}    = $form->{exchangerate} ? $form->format_amount(\%myconfig, $form->{exchangerate}) : '';
+
   $rows = max 2, $form->numtextrows($form->{notes}, 50);
 
   my @old_project_ids = grep { $_ } map { $form->{"project_id_$_"} } 1..$form->{rowcount};
@@ -275,56 +265,33 @@ sub form_header {
                    "taxcharts" => { "key"       => "ALL_TAXCHARTS",
                                     "module"    => "AR" },);
 
+  $form->{ALL_DEPARTMENTS} = SL::DB::Manager::Department->get_all;
+
   $_->{link_split} = { map { $_ => 1 } split/:/, $_->{link} } for @{ $form->{ALL_CHARTS} };
 
   my %project_labels = map { $_->{id} => $_->{projectnumber} } @{ $form->{"ALL_PROJECTS"} };
 
-  my (@AR_amount_values);
-  my (@AR_values);
-  my (@AR_paid_values);
-  my %chart_labels;
-  my %charts;
-  my $taxchart_init;
+  my (@AR_paid_values, %AR_paid_labels);
+  my $default_ar_amount_chart_id;
 
   foreach my $item (@{ $form->{ALL_CHARTS} }) {
     if ($item->{link_split}{AR_amount}) {
-      $taxchart_init = $item->{tax_id} if ($taxchart_init eq "");
-      my $key = "$item->{accno}--$item->{tax_id}";
-      push(@AR_amount_values, $key);
-    } elsif ($item->{link_split}{AR}) {
-      push(@AR_values, $item->{accno});
+      $default_ar_amount_chart_id //= $item->{id};
+
     } elsif ($item->{link_split}{AR_paid}) {
       push(@AR_paid_values, $item->{accno});
+      $AR_paid_labels{$item->{accno}} = "$item->{accno}--$item->{description}";
     }
-
-    # weirdness for AR_amount
-    $chart_labels{$item->{accno}} = "$item->{accno}--$item->{description}";
-    $chart_labels{"$item->{accno}--$item->{tax_id}"} = "$item->{accno}--$item->{description}";
-
-    $charts{$item->{accno}} = $item;
-  }
-
-  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 eq $item->{id});
-    push(@taxchart_values, $key);
-    $taxchart_labels{$key} = "$item->{taxdescription} " . ($item->{rate} * 100) . ' %';
-    $taxcharts{$item->{id}} = $item;
   }
 
   my $follow_up_vc         =  $form->{customer};
   $follow_up_vc            =~ s/--.*?//;
   my $follow_up_trans_info =  "$form->{invnumber} ($follow_up_vc)";
 
-  $form->{javascript} .=
-    qq|<script type="text/javascript" src="js/show_vc_details.js"></script>| .
-    qq|<script type="text/javascript" src="js/follow_up.js"></script>|;
+  $::request->layout->add_javascripts("autocomplete_chart.js", "show_vc_details.js", "show_history.js", "follow_up.js", "kivi.Draft.js", "kivi.GL.js");
 
-#  $amount  = $locale->text('Amount');
-#  $project = $locale->text('Project');
+  my $transdate = $::form->{transdate} ? DateTime->from_kivitendo($::form->{transdate}) : DateTime->today_local;
+  my $first_taxchart;
 
   my @transactions;
   for my $i (1 .. $form->{rowcount}) {
@@ -334,40 +301,26 @@ sub form_header {
       project_id => ($i==$form->{rowcount}) ? $form->{globalproject_id} : $form->{"project_id_$i"},
     };
 
-    my $selected_accno_full;
-    my ($accno_row) = split(/--/, $form->{"AR_amount_$i"});
-    my $item = $charts{$accno_row};
-    $selected_accno_full = "$item->{accno}--$item->{tax_id}";
+    my (%taxchart_labels, @taxchart_values, $default_taxchart, $taxchart_to_use);
+    my $amount_chart_id   = $form->{"AR_amount_chart_id_$i"} // $default_ar_amount_chart_id;
+    my $chart_has_changed = $::form->{"previous_AR_amount_chart_id_$i"} && ($amount_chart_id != $::form->{"previous_AR_amount_chart_id_$i"});
 
-    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_AR_amount_$i"});
+    foreach my $item ( GL->get_active_taxes_for_chart($amount_chart_id, $transdate) ) {
+      my $key             = $item->id . "--" . $item->rate;
+      $first_taxchart   //= $item;
+      $default_taxchart   = $item if $item->{is_default};
+      $taxchart_to_use    = $item if $key eq $form->{"taxchart_$i"};
 
-    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}";
+      push(@taxchart_values, $key);
+      $taxchart_labels{$key} = $item->taxdescription . " " . $item->rate * 100 . ' %';
     }
 
-    if (!$form->{"taxchart_$i"}) {
-      if ($form->{"AR_amount_$i"} =~ m/.--./) {
-        $selected_taxchart = join '--', map { ($_->{id}, $_->{rate}) } first { $_->{id} == $item->{tax_id} } @{ $form->{ALL_TAXCHARTS} };
-      } else {
-        $selected_taxchart = $taxchart_init;
-      }
-    }
+    $taxchart_to_use      = $default_taxchart // $first_taxchart if $chart_has_changed || !$taxchart_to_use;
+    my $selected_taxchart = $taxchart_to_use->id . '--' . $taxchart_to_use->rate;
 
     $transaction->{selectAR_amount} =
-      NTI($cgi->popup_menu('-name' => "AR_amount_$i",
-                           '-id' => "AR_amount_$i",
-                           '-style' => 'width:400px',
-                           '-onChange' => "setTaxkey(this, $i)",
-                           '-values' => \@AR_amount_values,
-                           '-labels' => \%chart_labels,
-                           '-default' => $selected_accno_full))
-      . $cgi->hidden('-name' => "previous_AR_amount_$i",
-                     '-default' => $selected_accno_full);
+        $::request->presenter->chart_picker("AR_amount_chart_id_$i", $amount_chart_id, style => "width: 400px", type => "AR_amount", class => ($form->{initial_focus} eq "row_$i" ? "initial_focus" : ""))
+      . $::request->presenter->hidden_tag("previous_AR_amount_chart_id_$i", $amount_chart_id);
 
     $transaction->{taxchart} =
       NTI($cgi->popup_menu('-name' => "taxchart_$i",
@@ -382,13 +335,6 @@ sub form_header {
 
   $form->{invtotal_unformatted} = $form->{invtotal};
 
-  $ARselected =
-    NTI($cgi->popup_menu('-name' => "ARselected", '-id' => "ARselected",
-                         '-style' => 'width:400px',
-                         '-values' => \@AR_values, '-labels' => \%chart_labels,
-                         '-default' => $form->{ARselected}));
-
-
   $form->{paidaccounts}++ if ($form->{"paid_$form->{paidaccounts}"});
 
   my $now = $form->current_date(\%myconfig);
@@ -409,14 +355,14 @@ sub form_header {
       gldate           => $form->{"gldate_$i"},
     };
 
-  # default account for current assets (i.e. 1801 - SKR04) if no account is selected
-  $form->{accno_arap} = IS->get_standard_accno_current_assets(\%myconfig, \%$form);
+    # default account for current assets (i.e. 1801 - SKR04) if no account is selected
+    $form->{accno_arap} = IS->get_standard_accno_current_assets(\%myconfig, \%$form);
 
     $payment->{selectAR_paid} =
       NTI($cgi->popup_menu('-name' => "AR_paid_$i",
                            '-id' => "AR_paid_$i",
                            '-values' => \@AR_paid_values,
-                           '-labels' => \%chart_labels,
+                           '-labels' => \%AR_paid_labels,
                            '-default' => $payment->{AR_paid} || $form->{accno_arap}));
 
 
@@ -426,9 +372,20 @@ sub form_header {
       : SL::DB::Default->get->payments_changeable == 2 ? $payment->{gldate} eq '' || $payment->{gldate} eq $now
       :                                                           1;
 
+    #deaktivieren von gebuchten Zahlungen ausserhalb der Bücherkontrolle, vorher prüfen ob heute eingegeben
+    if ($form->date_closed($payment->{"gldate_$i"})) {
+        $payment->{changeable} = 0;
+    }
+
     push @payments, $payment;
   }
 
+  my @empty = grep { $_->{paid} eq '' } @payments;
+  @payments = (
+    (sort_by { DateTime->from_kivitendo($_->{datepaid}) } grep { $_->{paid} ne '' } @payments),
+    @empty,
+  );
+
   $form->{totalpaid} = sum map { $_->{paid} } @payments;
 
   $form->header;
@@ -439,9 +396,10 @@ sub form_header {
     transactions         => \@transactions,
     project_labels       => \%project_labels,
     rows                 => $rows,
-    ARselected           => $ARselected,
+    AR_chart_id          => $form->{AR_chart_id},
     title_str            => $title,
     follow_up_trans_info => $follow_up_trans_info,
+    today                => DateTime->today,
   });
 
   $main::lxdebug->leave_sub();
@@ -450,7 +408,7 @@ sub form_header {
 sub form_footer {
   $main::lxdebug->enter_sub();
 
-  $main::auth->assert('general_ledger');
+  $main::auth->assert('ar_transactions');
 
   my $form     = $main::form;
   my %myconfig = %main::myconfig;
@@ -458,7 +416,7 @@ sub form_footer {
   my $cgi      = $::request->{cgi};
 
   if ( $form->{id} ) {
-    my $follow_ups = FU->follow_ups('trans_id' => $form->{id});
+    my $follow_ups = FU->follow_ups('trans_id' => $form->{id}, 'not_done' => 1);
     if ( @{ $follow_ups} ) {
       $form->{follow_up_length} = scalar(@{$follow_ups});
       $form->{follow_up_due_length} = sum(map({ $_->{due} * 1 } @{ $follow_ups }));
@@ -485,22 +443,23 @@ sub form_footer {
 }
 
 sub mark_as_paid {
-  $main::lxdebug->enter_sub();
+  $::auth->assert('ar_transactions');
 
-  $main::auth->assert('general_ledger');
-
-  my $form     = $main::form;
-  my %myconfig = %main::myconfig;
+  SL::DB::Invoice->new(id => $::form->{id})->load->mark_as_paid;
 
-  &mark_as_paid_common(\%myconfig,"ar");
+  $::form->redirect($::locale->text("Marked as paid"));
+}
 
-  $main::lxdebug->leave_sub();
+sub show_draft {
+  $::form->{transdate} = DateTime->today_local->to_kivitendo if !$::form->{transdate};
+  $::form->{gldate}    = $::form->{transdate} if !$::form->{gldate};
+  update();
 }
 
 sub update {
   $main::lxdebug->enter_sub();
 
-  $main::auth->assert('general_ledger');
+  $main::auth->assert('ar_transactions');
 
   my $form     = $main::form;
   my %myconfig = %main::myconfig;
@@ -545,19 +504,8 @@ sub update {
 
   $form->{invdate} = $form->{transdate};
 
-  $form->{invdate} = $form->{transdate};
-
-  my %saved_variables = map +( $_ => $form->{$_} ), qw(AR AR_amount_1 taxchart_1 customer_id notes);
-
   &check_name("customer");
 
-  $form->{AR} = $saved_variables{AR};
-  if ($saved_variables{AR_amount_1} =~ m/.--./) {
-    map { $form->{$_} = $saved_variables{$_} } qw(AR_amount_1 taxchart_1);
-  } else {
-    delete $form->{taxchart_1};
-  }
-
   $form->{invtotal} =
     ($form->{taxincluded}) ? $form->{invtotal} : $form->{invtotal} + $totaltax;
 
@@ -592,12 +540,13 @@ sub update {
 sub post_payment {
   $main::lxdebug->enter_sub();
 
-  $main::auth->assert('general_ledger');
+  $main::auth->assert('ar_transactions');
 
   my $form     = $main::form;
   my %myconfig = %main::myconfig;
   my $locale   = $main::locale;
 
+  $form->mtime_ischanged('ar');
   $form->{defaultcurrency} = $form->get_default_currency(\%myconfig);
 
   my $invdate = $form->datetonum($form->{transdate}, \%myconfig);
@@ -609,7 +558,13 @@ sub post_payment {
 
       $form->isblank("datepaid_$i", $locale->text('Payment date missing!'));
 
-      $form->error($locale->text('Cannot post payment for a closed period!')) if ($form->date_closed($form->{"datepaid_$i"}, \%myconfig));
+      $form->error($locale->text('Cannot post transaction above the maximum future booking date!'))
+        if ($form->date_max_future($form->{"datepaid_$i"}, \%myconfig));
+
+      #Zusätzlich noch das Buchungsdatum in die Bücherkontrolle einbeziehen
+      # (Dient zur Prüfung ob ZE oder ZA geprüft werden soll)
+      $form->error($locale->text('Cannot post payment for a closed period!'))
+        if ($form->date_closed($form->{"datepaid_$i"})  && !$form->date_closed($form->{"gldate_$i"}, \%myconfig));
 
       if ($form->{defaultcurrency} && ($form->{currency} ne $form->{defaultcurrency})) {
 #        $form->{"exchangerate_$i"} = $form->{exchangerate} if ($invdate == $datepaid);
@@ -635,7 +590,7 @@ sub post_payment {
 
 sub _post {
 
-  $main::auth->assert('general_ledger');
+  $main::auth->assert('ar_transactions');
 
   my $form     = $main::form;
 
@@ -646,7 +601,7 @@ sub _post {
 sub post {
   $main::lxdebug->enter_sub();
 
-  $main::auth->assert('general_ledger');
+  $main::auth->assert('ar_transactions');
 
   my $form     = $main::form;
   my %myconfig = %main::myconfig;
@@ -654,6 +609,8 @@ sub post {
 
   my ($inline) = @_;
 
+  $form->mtime_ischanged('ar');
+
   my ($datepaid);
 
   # check if there is an invoice number, invoice and due date
@@ -661,7 +618,7 @@ sub post {
   $form->isblank("duedate",   $locale->text('Due Date missing!'));
   $form->isblank("customer",  $locale->text('Customer missing!'));
 
-  if ($myconfig{mandatory_departments} && !$form->{department}) {
+  if ($myconfig{mandatory_departments} && !$form->{department_id}) {
     $form->{saved_message} = $::locale->text('You have to specify a department.');
     update();
     exit;
@@ -672,6 +629,7 @@ sub post {
 
   $form->error($locale->text('Cannot post transaction above the maximum future booking date!'))
     if ($form->date_max_future($transdate, \%myconfig));
+
   $form->error($locale->text('Cannot post transaction for a closed period!')) if ($form->date_closed($form->{"transdate"}, \%myconfig));
 
   $form->error($locale->text('Zero amount posting!'))
@@ -688,8 +646,13 @@ sub post {
 
       $form->isblank("datepaid_$i", $locale->text('Payment date missing!'));
 
+      $form->error($locale->text('Cannot post transaction above the maximum future booking date!'))
+        if ($form->date_max_future($form->{"datepaid_$i"}, \%myconfig));
+
+      #Zusätzlich noch das Buchungsdatum in die Bücherkontrolle einbeziehen
+      # (Dient zur Prüfung ob ZE oder ZA geprüft werden soll)
       $form->error($locale->text('Cannot post payment for a closed period!'))
-        if ($form->date_closed($form->{"datepaid_$i"}, \%myconfig));
+        if ($form->date_closed($form->{"datepaid_$i"})  && !$form->date_closed($form->{"gldate_$i"}, \%myconfig));
 
       if ($form->{defaultcurrency} && ($form->{currency} ne $form->{defaultcurrency})) {
         $form->{"exchangerate_$i"} = $form->{exchangerate} if ($transdate == $datepaid);
@@ -702,7 +665,7 @@ sub post {
   my ($customer) = split /--/, $form->{customer};
   if ($form->{oldcustomer} ne "$customer--$form->{customer_id}") {
     update();
-    ::end_of_request();
+    $::dispatcher->end_request;
   }
 
   $form->{AR}{receivables} = $form->{ARselected};
@@ -713,12 +676,12 @@ sub post {
 
   # saving the history
   if(!exists $form->{addition} && $form->{id} ne "") {
-    $form->{snumbers} = "invnumber_$form->{invnumber}";
-    $form->{addition} = "POSTED";
+    $form->{snumbers}  = "invnumber_$form->{invnumber}";
+    $form->{what_done} = "invoice";
+    $form->{addition}  = "POSTED";
     $form->save_history;
   }
   # /saving the history
-  remove_draft() if $form->{remove_draft};
 
   $form->redirect($locale->text('Transaction posted!')) unless $inline;
 
@@ -728,7 +691,7 @@ sub post {
 sub post_as_new {
   $main::lxdebug->enter_sub();
 
-  $main::auth->assert('general_ledger');
+  $main::auth->assert('ar_transactions');
 
   my $form     = $main::form;
   my %myconfig = %main::myconfig;
@@ -736,8 +699,9 @@ sub post_as_new {
   $form->{postasnew} = 1;
   # saving the history
   if(!exists $form->{addition} && $form->{id} ne "") {
-    $form->{snumbers} = qq|invnumber_| . $form->{invnumber};
-    $form->{addition} = "POSTED AS NEW";
+    $form->{snumbers}  = qq|invnumber_| . $form->{invnumber};
+    $form->{what_done} = "invoice";
+    $form->{addition}  = "POSTED AS NEW";
     $form->save_history;
   }
   # /saving the history
@@ -749,7 +713,7 @@ sub post_as_new {
 sub use_as_new {
   $main::lxdebug->enter_sub();
 
-  $main::auth->assert('general_ledger');
+  $main::auth->assert('ar_transactions');
 
   my $form     = $main::form;
   my %myconfig = %main::myconfig;
@@ -766,7 +730,7 @@ sub use_as_new {
 sub delete {
   $main::lxdebug->enter_sub();
 
-  $main::auth->assert('general_ledger');
+  $main::auth->assert('ar_transactions');
 
   my $form     = $main::form;
   my $locale   = $main::locale;
@@ -805,7 +769,7 @@ sub delete {
 sub yes {
   $main::lxdebug->enter_sub();
 
-  $main::auth->assert('general_ledger');
+  $main::auth->assert('ar_transactions');
 
   my $form     = $main::form;
   my %myconfig = %main::myconfig;
@@ -814,8 +778,9 @@ sub yes {
   if (AR->delete_transaction(\%myconfig, \%$form)) {
     # saving the history
     if(!exists $form->{addition}) {
-      $form->{snumbers} = qq|invnumber_| . $form->{invnumber};
-      $form->{addition} = "DELETED";
+      $form->{snumbers}  = qq|invnumber_| . $form->{invnumber};
+      $form->{what_done} = "invoice";
+      $form->{addition}  = "DELETED";
       $form->save_history;
     }
     # /saving the history
@@ -843,10 +808,10 @@ sub search {
 
   # Auch in Rechnungsübersicht nach Kundentyp filtern - jan
   $form->get_lists("projects"       => { "key" => "ALL_PROJECTS", "all" => 1 },
-                   "departments"    => "ALL_DEPARTMENTS",
                    "customers"      => "ALL_VC",
                    "business_types" => "ALL_BUSINESS_TYPES");
   $form->{ALL_EMPLOYEES} = SL::DB::Manager::Employee->get_all_sorted(query => [ deleted => 0 ]);
+  $form->{ALL_DEPARTMENTS} = SL::DB::Manager::Department->get_all;
   $form->{SHOW_BUSINESS_TYPES} = scalar @{ $form->{ALL_BUSINESS_TYPES} } > 0;
 
   $form->{CT_CUSTOM_VARIABLES}                  = CVar->get_configs('module' => 'CT');
@@ -907,9 +872,10 @@ sub ar_transactions {
   my $report = SL::ReportGenerator->new(\%myconfig, $form);
 
   @columns =
-    qw(transdate id type invnumber ordnumber cusordnumber name netamount tax amount paid
+    qw(ids transdate id type invnumber ordnumber cusordnumber name netamount tax amount paid
        datepaid due duedate transaction_description notes salesman employee shippingpoint shipvia
-       marge_total marge_percent globalprojectnumber customernumber country ustid taxzone payment_terms charts customertype);
+       marge_total marge_percent globalprojectnumber customernumber country ustid taxzone
+       payment_terms charts customertype direct_debit dunning_description department);
 
   my $ct_cvar_configs                 = CVar->get_configs('module' => 'CT');
   my @ct_includeable_custom_variables = grep { $_->{includeable} } @{ $ct_cvar_configs };
@@ -919,12 +885,14 @@ sub ar_transactions {
   push @columns, map { "cvar_$_->{name}" } @ct_includeable_custom_variables;
 
   my @hidden_variables = map { "l_${_}" } @columns;
-  push @hidden_variables, "l_subtotal", qw(open closed customer invnumber ordnumber cusordnumber transaction_description notes project_id transdatefrom transdateto employee_id salesman_id business_id);
+  push @hidden_variables, "l_subtotal", qw(open closed customer invnumber ordnumber cusordnumber transaction_description notes project_id transdatefrom transdateto duedatefrom duedateto
+                                           employee_id salesman_id business_id parts_partnumber parts_description department_id);
   push @hidden_variables, map { "cvar_$_->{name}" } @ct_searchable_custom_variables;
 
   $href = build_std_url('action=ar_transactions', grep { $form->{$_} } @hidden_variables);
 
   my %column_defs = (
+    'ids'                     => { raw_header_data => $::request->presenter->checkbox_tag("", id => "check_all", checkall => "[data-checkall=1]"), align => 'center' },
     'transdate'               => { 'text' => $locale->text('Date'), },
     'id'                      => { 'text' => $locale->text('ID'), },
     'type'                    => { 'text' => $locale->text('Type'), },
@@ -955,10 +923,13 @@ sub ar_transactions {
     'payment_terms'           => { 'text' => $locale->text('Payment Terms'), },
     'charts'                  => { 'text' => $locale->text('Buchungskonto'), },
     'customertype'            => { 'text' => $locale->text('Customer type'), },
+    'direct_debit'            => { 'text' => $locale->text('direct debit'), },
+    'department'              => { 'text' => $locale->text('Department'), },
+    dunning_description       => { 'text' => $locale->text('Dunning level'), },
     %column_defs_cvars,
   );
 
-  foreach my $name (qw(id transdate duedate invnumber ordnumber cusordnumber name datepaid employee shippingpoint shipvia transaction_description)) {
+  foreach my $name (qw(id transdate duedate invnumber ordnumber cusordnumber name datepaid employee shippingpoint shipvia transaction_description direct_debit)) {
     my $sortdir                 = $form->{sort} eq $name ? 1 - $form->{sortdir} : $form->{sortdir};
     $column_defs{$name}->{link} = $href . "&sort=$name&sortdir=$sortdir";
   }
@@ -968,6 +939,8 @@ sub ar_transactions {
   $form->{"l_type"} = "Y";
   map { $column_defs{$_}->{visible} = $form->{"l_${_}"} ? 1 : 0 } @columns;
 
+  $column_defs{ids}->{visible} = 'HTML';
+
   $report->set_columns(%column_defs);
   $report->set_column_order(@columns);
 
@@ -988,12 +961,10 @@ sub ar_transactions {
   if ($form->{cp_name}) {
     push @options, $locale->text('Contact Person') . " : $form->{cp_name}";
   }
-  if ($form->{department}) {
-    my ($department) = split /--/, $form->{department};
-    push @options, $locale->text('Department') . " : $department";
-  }
+
   if ($form->{department_id}) {
-    push @options, $locale->text('Department Id') . " : $form->{department_id}";
+    my $department = SL::DB::Manager::Department->find_by( id => $form->{department_id} );
+    push @options, $locale->text('Department') . " : " . $department->description;
   }
   if ($form->{invnumber}) {
     push @options, $locale->text('Invoice Number') . " : $form->{invnumber}";
@@ -1010,6 +981,12 @@ sub ar_transactions {
   if ($form->{transaction_description}) {
     push @options, $locale->text('Transaction description') . " : $form->{transaction_description}";
   }
+  if ($form->{parts_partnumber}) {
+    push @options, $locale->text('Part Number') . " : $form->{parts_partnumber}";
+  }
+  if ($form->{parts_description}) {
+    push @options, $locale->text('Part Description') . " : $form->{parts_description}";
+  }
   if ($form->{transdatefrom}) {
     push @options, $locale->text('From') . " " . $locale->date(\%myconfig, $form->{transdatefrom}, 1);
   }
@@ -1031,7 +1008,10 @@ sub ar_transactions {
     push @options, $locale->text('Closed');
   }
 
+  $form->{ALL_PRINTERS} = SL::DB::Manager::Printer->get_all_sorted;
+
   $report->set_options('top_info_text'        => join("\n", @options),
+                       'raw_top_info_text'    => $form->parse_html_template('ar/ar_transactions_header'),
                        'raw_bottom_info_text' => $form->parse_html_template('ar/ar_transactions_bottom'),
                        'output_format'        => 'HTML',
                        'title'                => $form->{title},
@@ -1063,8 +1043,6 @@ sub ar_transactions {
     $subtotals{marge_percent} = $subtotals{netamount} ? ($subtotals{marge_total} * 100 / $subtotals{netamount}) : 0;
     $totals{marge_percent}    = $totals{netamount}    ? ($totals{marge_total}    * 100 / $totals{netamount}   ) : 0;
 
-    map { $ar->{$_} = $form->format_amount(\%myconfig, $ar->{$_}, 2) } qw(netamount tax amount paid due marge_total marge_percent);
-
     my $is_storno  = $ar->{storno} &&  $ar->{storno_id};
     my $has_storno = $ar->{storno} && !$ar->{storno_id};
 
@@ -1075,6 +1053,10 @@ sub ar_transactions {
       $ar->{invoice}    ? $locale->text("Invoice (one letter abbreviation)") :
                           $locale->text("AR Transaction (abbreviation)");
 
+    map { $ar->{$_} = $form->format_amount(\%myconfig, $ar->{$_}, 2) } qw(netamount tax amount paid due marge_total marge_percent);
+
+    $ar->{direct_debit} = $ar->{direct_debit} ? $::locale->text('yes') : $::locale->text('no');
+
     my $row = { };
 
     foreach my $column (@columns) {
@@ -1087,6 +1069,12 @@ sub ar_transactions {
     $row->{invnumber}->{link} = build_std_url("script=" . ($ar->{invoice} ? 'is.pl' : 'ar.pl'), 'action=edit')
       . "&id=" . E($ar->{id}) . "&callback=${callback}";
 
+    $row->{ids} = {
+      raw_data =>  $::request->presenter->checkbox_tag("id[]", value => $ar->{id}, "data-checkall" => 1),
+      valign   => 'center',
+      align    => 'center',
+    };
+
     my $row_set = [ $row ];
 
     if (($form->{l_subtotal} eq 'Y')
@@ -1111,7 +1099,7 @@ sub ar_transactions {
 sub storno {
   $main::lxdebug->enter_sub();
 
-  $main::auth->assert('general_ledger');
+  $main::auth->assert('ar_transactions');
 
   my $form     = $main::form;
   my %myconfig = %main::myconfig;
@@ -1127,8 +1115,9 @@ sub storno {
 
   # saving the history
   if(!exists $form->{addition} && $form->{id} ne "") {
-    $form->{snumbers} = qq|invnumber_| . $form->{invnumber};
-    $form->{addition} = "STORNO";
+    $form->{snumbers}  = qq|invnumber_| . $form->{invnumber};
+    $form->{addition}  = "STORNO";
+    $form->{what_done} = "invoice";
     $form->save_history;
   }
   # /saving the history