Verkaufsberichtsortierung um Land, Warengruppen, Kundentyp, Verkäufer und Monat erweitert
authorG. Richardson <information@lx-office-hosting.de>
Tue, 12 Jun 2012 13:08:34 +0000 (15:08 +0200)
committerG. Richardson <information@lx-office-hosting.de>
Tue, 12 Jun 2012 13:08:34 +0000 (15:08 +0200)
Hauptsortierung und Untersortierung sind jetzt nicht mehr auf Ware und Kunde
begrenzt, sondern man kann eine Kombinationen erstellen aus:

* Kunde
* Ware
* Land
* Warengruppe
* Kundentyp
* Verkäufer
* Monat

Es kann jetzt auch nach benutzerdefinierten Variablen gefiltert werden.

Der Verkaufsbericht spaltet sich mit seinen Optionen langsam in zwei
unterschiedliche Bereiche auf, den Artikelmodus, wo die einzelnen Zeilen aus
invoice angezeigt werden, und den Rechnungsmodus, wo nur die Zeilen der
Zwischensummen und Summen angezeigt werden, und die Detailinformationen
aus invoice nur stören.

Default ist Rechnungsmodus, den Artikelmodus kann man per Häkchen auswählen.

Je nachdem auf welcher Ebene man sich befindet machen dann auch Informationen
wie "Durchschnittsverkaufspreis" keinen Sinn mehr.

Bei Zuordnungen wo die Sortierung keinen Wert hat (z.B. Sortierung nach Land,
aber beim Kunden ist kein Land hinterlegt), erscheint als Überschrift "leer",
und alle leeren Werte werden als eine Gruppe zusammengefasst.

SL/VK.pm
bin/mozilla/vk.pl
locale/de/all
templates/webpages/vk/search_invoice.html

index ae3ff4d..63eecfd 100644 (file)
--- a/SL/VK.pm
+++ b/SL/VK.pm
@@ -51,37 +51,72 @@ sub invoice_transactions {
   my @values;
 
   my $query =
-    qq|SELECT cus.name,cus.customernumber,ar.invnumber,ar.id,ar.transdate,p.partnumber,i.parts_id,i.qty,i.price_factor,i.discount,i.description,i.lastcost,i.sellprice,i.fxsellprice,i.marge_total,i.marge_percent,i.unit | .
+    qq|SELECT ct.id as customerid, ct.name as customername,ct.customernumber,ct.country,ar.invnumber,ar.id,ar.transdate,p.partnumber,pg.partsgroup,i.parts_id,i.qty,i.price_factor,i.discount,i.description as description,i.lastcost,i.sellprice,i.marge_total,i.marge_percent,i.unit,b.description as business,e.name as employee,e2.name as salesman, to_char(ar.transdate,'Month') as month | .
     qq|FROM invoice i | .  
-    qq|join ar on (i.trans_id = ar.id) | .
-    qq|join parts p on (i.parts_id = p.id) | .
-    qq|join customer cus on (cus.id = ar.customer_id) |;
+    qq|JOIN ar on (i.trans_id = ar.id) | .
+    qq|JOIN parts p on (i.parts_id = p.id) | .
+    qq|LEFT JOIN partsgroup pg on (p.partsgroup_id = pg.id) | .
+    qq|LEFT JOIN customer ct on (ct.id = ar.customer_id) | .
+    qq|LEFT JOIN business b on (ct.business_id = b.id) | .
+    qq|LEFT JOIN employee e ON (ar.employee_id = e.id) | .
+    qq|LEFT JOIN employee e2 ON (ar.salesman_id = e2.id) |;
 
   my $where = "1 = 1";
 
+  # if employee can only see his own invoices, make sure this also holds for sales report
+  # limits by employees (Bearbeiter), not salesmen!
+  if (!$main::auth->assert('sales_all_edit', 1)) {
+    $where .= " AND ar.employee_id = (select id from employee where login= ?)";
+    push (@values, $form->{login});
+  }
+
   # Stornierte Rechnungen und Stornorechnungen in invoice rausfiltern
+  # was ist mit Gutschriften?
   $where .= " AND ar.storno is not true ";
 
   # Bestandteile von Erzeugnissen herausfiltern
   $where .= " AND i.assemblyitem is not true ";
 
-  my $sortorder = "cus.name,i.parts_id,ar.transdate";
-  if ($form->{sortby} eq 'artikelsort') {
-    $sortorder = "i.parts_id,cus.name,ar.transdate";
+  my $sortorder;
+  # sorting by month is a special case:
+  # Sorting by month, using salesman as an example:
+  # Sorting with month as mainsort: ORDER BY month,salesman,ar.transdate,ar.invnumber
+  # Sorting with month as subsort:  ORDER BY salesman,ar.transdate,month,ar.invnumber
+  if ($form->{mainsort} eq 'month') {
+    $sortorder .= "ar.transdate,month,"
+  } else {
+    $sortorder .= $form->{mainsort} . ",";
   };
+  if ($form->{subsort} eq 'month') {
+    $sortorder .= "ar.transdate,month,"
+  } else {
+    $sortorder .= $form->{subsort} . ",";
+  };
+  $sortorder .= 'ar.transdate,' unless $form->{subsort} eq 'month';
+  $sortorder .= 'ar.invnumber';
+
+#  $sortorder =~ s/month/ar.transdate/;
 
   if ($form->{customer_id}) {
     $where .= " AND ar.customer_id = ?";
     push(@values, $form->{customer_id});
   };
   if ($form->{customernumber}) {
-    $where .= qq| AND cus.customernumber = ? |;
+    $where .= qq| AND ct.customernumber = ? |;
     push(@values, $form->{customernumber});
   }
   if ($form->{partnumber}) {
     $where .= qq| AND (p.partnumber ILIKE ?)|;
     push(@values, '%' . $form->{partnumber} . '%');
   }
+  if ($form->{partsgroup_id}) {
+    $where .= qq| AND (pg.id = ?)|;
+    push(@values, $form->{partsgroup_id});
+  }
+  if ($form->{country}) {
+    $where .= qq| AND (ct.country ILIKE ?)|;
+    push(@values, '%' . $form->{country} . '%');
+  }
   # nimmt man description am Besten aus invoice oder parts?
   if ($form->{description}) {
     $where .= qq| AND (i.description ILIKE ?)|;
@@ -100,6 +135,15 @@ sub invoice_transactions {
     $where .= " AND ar.department_id = ?";
     push(@values, $department_id);
   }
+  if ($form->{employee_id}) {
+    $where .= " AND ar.employee_id = ?";
+    push @values, conv_i($form->{employee_id});
+  }
+
+  if ($form->{salesman_id}) {
+    $where .= " AND ar.salesman_id = ?";
+    push @values, conv_i($form->{salesman_id});
+  }
   if ($form->{project_id}) {
     $where .=
       qq|AND ((ar.globalproject_id = ?) OR EXISTS | .
@@ -107,8 +151,31 @@ sub invoice_transactions {
       qq|   WHERE i.project_id = ? AND i.trans_id = ar.id))|;
     push(@values, $form->{"project_id"}, $form->{"project_id"});
   }
+  if ($form->{business_id}) {
+    $where .= qq| AND ct.business_id = ? |; 
+    push(@values, $form->{"business_id"});
+  }
+
+  my ($cvar_where_ct, @cvar_values_ct) = CVar->build_filter_query('module'    => 'CT',
+                                                                  'trans_id_field' => 'ct.id',
+                                                                  'filter'         => $form);
+
+  if ($cvar_where_ct) {
+    $where .= qq| AND ($cvar_where_ct)|;
+    push @values, @cvar_values_ct;
+  }
+
 
-  $query .= " WHERE $where ORDER BY $sortorder";
+  my ($cvar_where_ic, @cvar_values_ic) = CVar->build_filter_query('module'         => 'IC',
+                                                                  'trans_id_field' => 'p.id',
+                                                                  'filter'         => $form);
+
+  if ($cvar_where_ic) {
+    $where .= qq| AND ($cvar_where_ic)|;
+    push @values, @cvar_values_ic;
+  }
+  
+  $query .= " WHERE $where ORDER BY $sortorder "; # LIMIT 5000";
 
   my @result = selectall_hashref_query($form, $dbh, $query, @values);
 
index b5c0931..ef99388 100644 (file)
@@ -46,7 +46,6 @@ require "bin/mozilla/reportgenerator.pl";
 
 use strict;
 
-
 sub search_invoice {
   $main::lxdebug->enter_sub();
   $main::auth->assert('general_ledger | invoice_edit');
@@ -63,11 +62,27 @@ sub search_invoice {
   $form->{title}    = $locale->text('Sales Report');
   $form->{jsscript} = 1;
 
-  $form->get_lists("projects"     => { "key" => "ALL_PROJECTS", "all" => 1 },
-                   "departments"  => "ALL_DEPARTMENTS",
-                   "customers"    => "ALL_VC");
-
+  $form->get_lists("projects"        => { "key" => "ALL_PROJECTS", "all" => 1 },
+                   "departments"     => "ALL_DEPARTMENTS",
+                   "business_types"  => "ALL_BUSINESS_TYPES",
+                   "salesmen"        => "ALL_SALESMEN",
+                   'employees'       => 'ALL_EMPLOYEES',
+                   'partsgroup'      => 'ALL_PARTSGROUPS',
+                   "customers"       => "ALL_VC");
+  $form->{CUSTOM_VARIABLES_IC}                  = CVar->get_configs('module' => 'IC');
+  ($form->{CUSTOM_VARIABLES_FILTER_CODE_IC},
+   $form->{CUSTOM_VARIABLES_INCLUSION_CODE_IC}) = CVar->render_search_options('variables'      => $form->{CUSTOM_VARIABLES_IC},
+                                                                           'include_prefix' => 'l_',
+                                                                           'include_value'  => 'Y');
+
+  $form->{CUSTOM_VARIABLES_CT}                  = CVar->get_configs('module' => 'CT');
+  ($form->{CUSTOM_VARIABLES_FILTER_CODE_CT},
+   $form->{CUSTOM_VARIABLES_INCLUSION_CODE_CT}) = CVar->render_search_options('variables'      => $form->{CUSTOM_VARIABLES_CT},
+                                                                           'include_prefix' => 'l_',
+                                                                           'include_value'  => 'Y');
   $form->{vc_keys}   = sub { "$_[0]->{name}--$_[0]->{id}" };
+  $form->{employee_labels} = sub { $_[0]->{"name"} || $_[0]->{"login"} };
+  $form->{salesman_labels} = $form->{employee_labels};
 
   $form->header;
   print $form->parse_html_template('vk/search_invoice', { %myconfig });
@@ -86,6 +101,9 @@ sub invoice_transactions {
 
   my ($callback, $href, @columns);
 
+  # can't currently be configured from report, empty line between main sortings
+  my $addemptylines = '1';
+
   if ( $form->{customer} =~ /--/ ) {
     # Felddaten kommen aus Dropdownbox
     ($form->{customername}, $form->{customer_id}) = split(/--/, $form->{customer});
@@ -108,28 +126,46 @@ sub invoice_transactions {
   # decimalplaces überprüfen oder auf Default 2 setzen
   $form->{decimalplaces} = 2 unless $form->{decimalplaces} > 0 && $form->{decimalplaces} < 6;
 
+  my $cvar_configs_ct = CVar->get_configs('module' => 'CT');
+  my $cvar_configs_ic = CVar->get_configs('module' => 'IC');
+
 #  report_generator_set_default_sort('transdate', 1);
 
   VK->invoice_transactions(\%myconfig, \%$form);
 
-  # anhand von radio button die Sortierreihenfolge festlegen
-  if ($form->{sortby} eq 'artikelsort') {
-    $form->{'mainsort'} = 'parts_id';
-    $form->{'subsort'}  = 'name';
-  } else {
-    $form->{'mainsort'} = 'name';
-    $form->{'subsort'}  = 'parts_id';
+  
+  if ( $form->{mainsort} eq 'month' or $form->{subsort} eq 'month' ) {
+
+    # Data already comes out of SELECT statement in correct month order, but
+    # remove whitespaces (month names are padded) and translate them as early
+    # as possible
+
+    foreach (@{ $form->{AR} }) {
+      $_->{month} =~ s/\s//g;
+      $_->{month} = $locale->text($_->{month});
+    };
   };
 
   $form->{title} = $locale->text('Sales Report');
 
   @columns =
-    qw(description invnumber transdate customernumber partnumber transdate qty unit sellprice sellprice_total discount lastcost lastcost_total marge_total marge_percent);
+    qw(description invnumber transdate customernumber customername partnumber partsgroup country business transdate qty unit sellprice sellprice_total discount lastcost lastcost_total marge_total marge_percent employee salesman);
+
+  my @includeable_custom_variables = grep { $_->{includeable} } @{ $cvar_configs_ic }, @{ $cvar_configs_ct };
+  my @searchable_custom_variables  = grep { $_->{searchable} }  @{ $cvar_configs_ic }, @{ $cvar_configs_ct };
+  my %column_defs_cvars            = map { +"cvar_$_->{name}" => { 'text' => $_->{description} } } @includeable_custom_variables;
+
+  push @columns, map { "cvar_$_->{name}" } @includeable_custom_variables;
+
 
   # hidden variables für pdf/csv export übergeben
   # einmal mit l_ um zu bestimmen welche Spalten ausgegeben werden sollen
   # einmal optionen für die Überschrift (z.B. transdatefrom, partnumber, ...)
-  my @hidden_variables  = (qw(l_headers l_subtotal l_total l_customernumber transdatefrom transdateto decimalplaces customer customername customer_id department partnumber description project_id customernumber), "$form->{db}number", map { "l_$_" } @columns);
+  my @hidden_variables  = (qw(l_headers_mainsort l_headers_subsort l_subtotal_mainsort l_subtotal_subsort l_total l_parts l_customername l_customernumber transdatefrom transdateto decimalplaces customer customername customer_id department partnumber partsgroup country business description project_id customernumber salesman employee salesman_id employee_id business_id partsgroup_id mainsort subsort), 
+      "$form->{db}number", 
+      map({ "cvar_$_->{name}" } @searchable_custom_variables),
+      map { "l_$_" } @columns
+      );
   my @hidden_nondefault = grep({ $form->{$_} } @hidden_variables);
   # Variablen werden dann als Hidden Variable mitgegeben, z.B.
   # <input type="hidden" name="report_generator_hidden_transdateto" value="21.05.2010">
@@ -140,6 +176,11 @@ sub invoice_transactions {
   my %column_defs = (
     'description'             => { 'text' => $locale->text('Description'), },
     'partnumber'              => { 'text' => $locale->text('Part Number'), },
+    'partsgroup'              => { 'text' => $locale->text('Group'), },
+    'country'                 => { 'text' => $locale->text('Country'), },
+    'business'                => { 'text' => $locale->text('Customer type'), },
+    'employee'                => { 'text' => $locale->text('Employee'), },
+    'salesman'                => { 'text' => $locale->text('Salesperson'), },
     'invnumber'               => { 'text' => $locale->text('Invoice Number'), },
     'transdate'               => { 'text' => $locale->text('Invoice Date'), },
     'qty'                     => { 'text' => $locale->text('Quantity'), },
@@ -152,15 +193,28 @@ sub invoice_transactions {
     'marge_total'             => { 'text' => $locale->text('Sales margin'), },
     'marge_percent'           => { 'text' => $locale->text('Sales margin %'), },
     'customernumber'          => { 'text' => $locale->text('Customer Number'), },
+    'customername'            => { 'text' => $locale->text('Customer Name'), },
+# add 3 more column_defs so we have a translation for top_info_text
+    'customer'                => { 'text' => $locale->text('Customer'), },
+    'part'                    => { 'text' => $locale->text('Part'), },
+    'month'                   => { 'text' => $locale->text('Month'), },
+    %column_defs_cvars,
   );
 
+  map { $column_defs{$_}->{visible} = $form->{"l_$_"} eq 'Y' } @columns;
+
   my %column_alignment = map { $_ => 'right' } qw(lastcost sellprice sellprice_total lastcost_total unit discount marge_total marge_percent qty);
 
-  $form->{"l_type"} = "Y";
+  
+  # so now the check-box "Description" is only used as switch for part description in invoice-mode
+  # always fill the column "Description" if we are in Zwischensummenmode
+  if (not defined $form->{"l_parts"}) {
+    $form->{"l_description"} = "Y";
+  };
   map { $column_defs{$_}->{visible} = $form->{"l_${_}"} ? 1 : 0 } @columns;
 
-
   my @options;
+
   if ($form->{description}) {
     push @options, $locale->text('Description') . " : $form->{description}";
   }
@@ -170,6 +224,7 @@ sub invoice_transactions {
   if ($form->{customernumber}) {
     push @options, $locale->text('Customer Number') . " : $form->{customernumber}";
   }
+# TODO: es wird nur id übergeben
   if ($form->{department}) {
     my ($department) = split /--/, $form->{department};
     push @options, $locale->text('Department') . " : $department";
@@ -183,6 +238,25 @@ sub invoice_transactions {
   if ($form->{partnumber}) {
     push @options, $locale->text('Part Number') . " : $form->{partnumber}";
   }
+  if ($form->{partsgroup_id}) {
+    my $partsgroup = SL::DB::PartsGroup->new(id => $form->{partsgroup_id})->load;
+    push @options, $locale->text('Group') . " : $partsgroup->{partsgroup}";
+  }
+  if ($form->{country}) {
+    push @options, $locale->text('Country') . " : $form->{country}";
+  }
+  if ($form->{employee_id}) {
+    my $employee = SL::DB::Employee->new(id => $form->{employee_id})->load;
+    push @options, $locale->text('Employee') . ' : ' . $employee->name;
+  }
+  if ($form->{salesman_id}) {
+    my $salesman = SL::DB::Employee->new(id => $form->{salesman_id})->load;
+    push @options, $locale->text('Salesman') . ' : ' . $salesman->name;
+  }
+  if ($form->{business_id}) {
+    my $business = SL::DB::Business->new(id => $form->{business_id})->load;
+    push @options, $locale->text('Customer type') . ' : ' . $business->description;
+  }
   if ($form->{ordnumber}) {
     push @options, $locale->text('Order Number') . " : $form->{ordnumber}";
   }
@@ -201,7 +275,7 @@ sub invoice_transactions {
 
   my $report = SL::ReportGenerator->new(\%myconfig, $form);
 
-  $report->set_options('top_info_text'        => join("\n", @options),
+  $report->set_options('top_info_text'        => join("\n", $locale->text('Main sorting') . ' : ' . $column_defs{$form->{mainsort}}->{text} , $locale->text('Secondary sorting') . ' : ' . $column_defs{$form->{'subsort'}}->{text}, @options),
                        'output_format'        => 'HTML',
                        'title'                => $form->{title},
                        'attachment_basename'  => $locale->text('Sales Report') . strftime('_%Y%m%d', localtime time),
@@ -216,6 +290,20 @@ sub invoice_transactions {
 
   $report->set_sort_indicator($form->{mainsort}, $form->{sortdir});
 
+  CVar->add_custom_variables_to_report('module'         => 'CT',
+      'trans_id_field' => 'customerid',
+      'configs'        => $cvar_configs_ct,
+      'column_defs'    => \%column_defs,
+      'data'           => $form->{AR}
+  );
+
+  CVar->add_custom_variables_to_report('module'         => 'IC',
+      'trans_id_field' => 'parts_id',
+      'configs'        => $cvar_configs_ic,
+      'column_defs'    => \%column_defs,
+      'data'           => $form->{AR}
+  );
+
   # add sort and escape callback, this one we use for the add sub
   $form->{callback} = $href .= "&sort=$form->{mainsort}";
 
@@ -241,23 +329,25 @@ sub invoice_transactions {
     # discount was already accounted for in db sellprice
     $ar->{sellprice} = $ar->{sellprice} / $ar->{price_factor};
     $ar->{lastcost} = $ar->{lastcost} / $ar->{price_factor};
-    $ar->{sellprice_total} = $ar->{qty} * ( $ar->{fxsellprice} * ( 1 - $ar->{discount} ) ) ;
+    $ar->{sellprice_total} = $ar->{qty} * $ar->{sellprice};
     $ar->{lastcost_total}  = $ar->{qty} * $ar->{lastcost};
     # marge_percent wird neu berechnet, da Wert in invoice leer ist (Bug)
-    $ar->{marge_percent} = $ar->{sellprice_total} ? (($ar->{sellprice_total}-$ar->{lastcost_total}) / $ar->{sellprice_total}) : 0;
+    $ar->{marge_percent} = $ar->{sellprice_total} ? (($ar->{sellprice_total}-$ar->{lastcost_total}) / $ar->{sellprice_total} * 100) : 0;
     # marge_total neu berechnen
     $ar->{marge_total} = $ar->{sellprice_total} ? $ar->{sellprice_total}-$ar->{lastcost_total}  : 0;
     $ar->{discount} *= 100;  # für Ausgabe formatieren, 10% stored as 0.1 in db
 
     # Anfangshauptüberschrift
-    if ( $form->{l_headers} eq "Y" && ( $idx == 0 or $ar->{ $form->{'mainsort'} } ne $form->{AR}->[$idx - 1]->{ $form->{'mainsort'} } )) {
-      my $name;
+    if ( $form->{l_headers_mainsort} eq "Y" && ( $idx == 0 or $ar->{ $form->{'mainsort'} } ne $form->{AR}->[$idx - 1]->{ $form->{'mainsort'} } )) {
       my $headerrow;
-      if ( $form->{mainsort} eq 'parts_id' ) {
-        $headerrow->{description}->{data} = "$ar->{description}";
+
+      # use $emptyname for mainsort header if mainsort is empty
+      if ( $ar->{$form->{'mainsort'}} ) {
+        $headerrow->{description}->{data} = $ar->{$form->{'mainsort'}};
       } else {
-        $headerrow->{description}->{data} = "$ar->{name}";
+        $headerrow->{description}->{data} = $locale->text('empty');
       };
+
       $headerrow->{description}->{class} = "listmainsortheader";
       my $headerrow_set = [ $headerrow ];
       $report->add_data($headerrow_set);
@@ -275,17 +365,17 @@ sub invoice_transactions {
       or $ar->{ $form->{'mainsort'} } ne $form->{AR}->[$idx - 1]->{ $form->{'mainsort'} }
     ) {
       my $headerrow;
-      my $name;
-      if ( $form->{subsort} eq 'parts_id' ) {
-        $name = 'description';
-        $headerrow->{description}->{data} = "$ar->{$name}";
+
+      # if subsort name is defined, use that name in header, otherwise use $emptyname
+      if ( $ar->{$form->{'subsort'}} ) {
+        $headerrow->{description}->{data} = $ar->{$form->{'subsort'}};
       } else {
-        $name = 'name';
-        $headerrow->{description}->{data} = "$ar->{$name}";
+        $headerrow->{description}->{data} = $locale->text('empty');
       };
       $headerrow->{description}->{class} = "listsubsortheader";
       my $headerrow_set = [ $headerrow ];
-      $report->add_data($headerrow_set) if $form->{l_headers} eq "Y";
+      # special case: subsort headers only makes (aesthetical) sense if we show individual parts
+      $report->add_data($headerrow_set) if $form->{l_headers_subsort} eq "Y" and $form->{l_parts};
     };
 
     map { $subtotals1{$_} += $ar->{$_};
@@ -318,12 +408,12 @@ sub invoice_transactions {
     };
 
     # Ertrag prozentual in den Summen: (summe VK - summe Ertrag) / summe VK
-    $subtotals1{marge_percent} = $subtotals1{sellprice_total} ? (($subtotals1{sellprice_total} - $subtotals1{lastcost_total}) / $subtotals1{sellprice_total}) : 0;
-    $subtotals2{marge_percent} = $subtotals2{sellprice_total} ? (($subtotals2{sellprice_total} - $subtotals2{lastcost_total}) / $subtotals2{sellprice_total}) : 0;
+    $subtotals1{marge_percent} = $subtotals1{sellprice_total} ? (($subtotals1{sellprice_total} - $subtotals1{lastcost_total}) / $subtotals1{sellprice_total}) * 100 : 0;
+    $subtotals2{marge_percent} = $subtotals2{sellprice_total} ? (($subtotals2{sellprice_total} - $subtotals2{lastcost_total}) / $subtotals2{sellprice_total}) *100 : 0;
 
     # Ertrag prozentual:  (Summe VK betrag - Summe EK betrag) / Summe VK betrag
     # wird laufend bei jeder Position neu berechnet
-    $totals{marge_percent}    = $totals{sellprice_total}    ? ( ($totals{sellprice_total} - $totals{lastcost_total}) / $totals{sellprice_total}   ) : 0;
+    $totals{marge_percent}    = $totals{sellprice_total}    ? ( ($totals{sellprice_total} - $totals{lastcost_total}) / $totals{sellprice_total}   ) * 100 : 0;
 
     map { $ar->{$_} = $form->format_amount(\%myconfig, $ar->{$_}, 2) } qw(marge_total marge_percent);
     map { $ar->{$_} = $form->format_amount(\%myconfig, $ar->{$_}, $form->{"decimalplaces"} )} qw(lastcost sellprice sellprice_total lastcost_total);
@@ -342,40 +432,34 @@ sub invoice_transactions {
     $row->{invnumber}->{link} = build_std_url("script=is.pl", 'action=edit')
       . "&id=" . E($ar->{id}) . "&callback=${callback}";
 
-    my $row_set = [ $row ];
+    # Einzelzeilen nur zeigen wenn l_parts gesetzt ist, nützlich, wenn man nur
+    # Subtotals und Totals sehen möchte
+    my $row_set = $form->{l_parts} ? [ $row ] : [ ];
 
-    if (($form->{l_subtotal} eq 'Y')
+    # hier wird bei l_subtotal nicht differenziert zwischen mainsort und subsort
+    # macht man l_subtotal_mainsort aus wird l_subtotal_subsort auch nicht ausgeführt
+    if (($form->{l_subtotal_mainsort} eq 'Y')
         && (($idx == (scalar @{ $form->{AR} } - 1))   # last element always has a subtotal
           || ($ar->{ $form->{'subsort'} } ne $form->{AR}->[$idx + 1]->{ $form->{'subsort'}   })
           || ($ar->{ $form->{'mainsort'} } ne $form->{AR}->[$idx + 1]->{ $form->{'mainsort'} })
           )) {   # if value that is sorted by changes, print subtotal
-      my $name;
-      if ( $form->{subsort} eq 'parts_id' ) {
-        $name = 'description';
-      } else {
-        $name = 'name';
-      };
 
-      if ($form->{l_subtotal} eq 'Y') {
-        push @{ $row_set }, create_subtotal_row_invoice(\%subtotals2, \@columns, \%column_alignment, \@subtotal_columns, 'listsubsortsubtotal', $ar->{$name}) ;
-        push @{ $row_set }, insert_empty_row();
+      if ($form->{l_subtotal_subsort} eq 'Y') {
+        push @{ $row_set }, create_subtotal_row_invoice(\%subtotals2, \@columns, \%column_alignment, \@subtotal_columns, 'listsubsortsubtotal', $ar->{ $form->{'subsort'} }) ;
+        push @{ $row_set }, insert_empty_row() if $form->{l_parts} and $addemptylines;
       };
     }
 
-    # if mainsort has changed, add mainsort subtotal and empty row
-    if (($form->{l_subtotal} eq 'Y')
+    # if last mainsort is reached or mainsort has changed, add mainsort subtotal and empty row
+    if (($form->{l_subtotal_mainsort} eq 'Y')
         && (($idx == (scalar @{ $form->{AR} } - 1))   # last element always has a subtotal
             || ($ar->{ $form->{'mainsort'} } ne $form->{AR}->[$idx + 1]->{ $form->{'mainsort'} })
             )) {   # if value that is sorted by changes, print subtotal
-      my $name;
-      if ( $form->{mainsort} eq 'parts_id' ) {
-        $name = 'description';
-      } else {
-        $name = 'name';
-      };
-      if ($form->{l_subtotal} eq 'Y' ) {
-        push @{ $row_set }, create_subtotal_row_invoice(\%subtotals1, \@columns, \%column_alignment, \@subtotal_columns, 'listmainsortsubtotal', $ar->{$name});
-        push @{ $row_set }, insert_empty_row();
+      if ($form->{l_subtotal_mainsort} eq 'Y' and $form->{mainsort} ne $form->{subsort} ) {
+        # subtotal is overriden if mainsort and subsort are equal, don't print
+        # subtotal line even if it is selected
+        push @{ $row_set }, create_subtotal_row_invoice(\%subtotals1, \@columns, \%column_alignment, \@subtotal_columns, 'listmainsortsubtotal', $ar->{$form->{mainsort}});
+        push @{ $row_set }, insert_empty_row() if $addemptylines; # insert empty row after mainsort
       };
     }
 
@@ -385,7 +469,7 @@ sub invoice_transactions {
   }
   if ( $form->{l_total} eq "Y" ) {
     $report->add_separator();
-    $report->add_data(create_subtotal_row_invoice(\%totals, \@columns, \%column_alignment, \@total_columns, 'listtotal'))
+    $report->add_data(create_subtotal_row_invoice(\%totals, \@columns, \%column_alignment, \@total_columns, 'listtotal', 'l_total'))
   };
 
   $report->generate_with_headers();
@@ -409,10 +493,19 @@ sub create_subtotal_row_invoice {
 
   my $form     = $main::form;
   my %myconfig = %main::myconfig;
+  my $locale   = $main::locale;
 
   my $row = { map { $_ => { 'data' => '', 'class' => $class, 'align' => $column_alignment->{$_}, } } @{ $columns } };
 
-  $row->{description}->{data} = "Summe " . $name;
+  # set name as "empty" if no value is given, except if we are dealing with the
+  # absolute total, then just write "Total sum"
+  # here we assume that no name will be called 'l_total'
+  $name = $locale->text('empty') unless $name;
+  if ( $name eq 'l_total' ) {
+    $row->{description}->{data} = $locale->text('Total sum');
+  } else {
+    $row->{description}->{data} = $locale->text('Total') . ' ' . $name;
+  };
 
   map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $totals->{$_}, 2) } qw(marge_total marge_percent);
   map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $totals->{$_}, 0) } qw(qty);
index 9e1d62a..6a5a58e 100644 (file)
@@ -488,6 +488,7 @@ $self->{texts} = {
   'Credit Tax'                  => 'Umsatzsteuer',
   'Credit Tax Account'          => 'Umsatzsteuerkonto',
   'Credit note (one letter abbreviation)' => 'G',
+  'Cumulated or averaged values' => 'Kumulierte oder gemittelte Werte',
   'Curr'                        => 'Währung',
   'Currencies'                  => 'W&auml;hrungen',
   'Currency'                    => 'Währung',
@@ -511,6 +512,7 @@ $self->{texts} = {
   'Customer not on file!'       => 'Kunde ist nicht in der Datenbank!',
   'Customer saved!'             => 'Kunde gespeichert!',
   'Customer type'               => 'Kundentyp',
+  'Customer variables'          => 'Kundenvariablen',
   'Customer/Vendor'             => 'Kunde/Lieferant',
   'Customer/Vendor (database ID)' => 'Kunde/Lieferant (Datenbank-ID)',
   'Customer/Vendor Name'        => 'Kunde/Lieferant',
@@ -839,6 +841,8 @@ $self->{texts} = {
   'Files created by kivitendo\'s &quot;Backup Dataset&quot; function are such files.' => 'Dateien, die von kivitendo\'s Funktion &quot;Datenbank sichern&quot; erstellt wurden, erf&uuml;llen diese Kriterien.',
   'Filter'                      => 'Filter',
   'Filter date by'              => 'Datum filtern nach',
+  'Filter for customer variables' => 'Filter für benutzerdefinierte Kundenvariablen',
+  'Filter for item variables'   => 'Filter für benutzerdefinierte Artikelvariablen',
   'Finish'                      => 'Abschlie&szlig;en',
   'Fix transaction'             => 'Buchung korrigieren',
   'Fix transactions'            => 'Buchungen korrigieren',
@@ -1012,7 +1016,10 @@ $self->{texts} = {
   'It may optionally be compressed with &quot;gzip&quot;.' => 'Sie darf optional mit &quot;gzip&quot; komprimiert sein.',
   'It will simply set the taxkey to 0 (meaning "no taxes") which is the correct value for such inventory transactions.' => 'Es wird einfach die Steuerschlüssel auf  0 setzen, was "keine Steuer" bedeutet und für solche Warenbestandsbuchungen der richtige Wert ist.',
   'Item deleted!'               => 'Artikel gelöscht!',
+  'Item mode'                   => 'Artikelmodus',
   'Item not on file!'           => 'Dieser Artikel ist nicht in der Datenbank!',
+  'Item values'                 => 'Artikelwerte',
+  'Item variables'              => 'Artikelvariablen',
   'Jahresverkehrszahlen neu'    => 'Jahresverkehrszahlen neu',
   'Jan'                         => 'Jan',
   'January'                     => 'Januar',
@@ -1154,6 +1161,7 @@ $self->{texts} = {
   'Module home page'            => 'Modul-Webseite',
   'Module name'                 => 'Modulname',
   'Monat'                       => 'Monat',
+  'Month'                       => 'Monat',
   'Monthly'                     => 'monatlich',
   'More than one #1 found matching, please be more specific.' => 'Mehr als ein #1 wurde gefunden, bitte geben Sie den Namen genauer an.',
   'More than one control file with the tag \'%s\' exist.' => 'Es gibt mehr als eine Kontrolldatei mit dem Tag \'%s\'.',
@@ -1261,6 +1269,7 @@ $self->{texts} = {
   'On Order'                    => 'Ist bestellt',
   'One or more Perl modules missing' => 'Ein oder mehr Perl-Module fehlen',
   'Only due follow-ups'         => 'Nur f&auml;llige Wiedervorlagen',
+  'Only shown in item mode'     => 'werden nur im Artikelmodus angezeigt',
   'Oops. No valid action found to dispatch. Please report this case to the Lx-Office team.' => 'Ups. Es wurde keine gültige Funktion zum Aufrufen gefunden. Bitte berichten Sie diesen Fall den Lx-Office-Entwicklern.',
   'Open'                        => 'Offen',
   'Open Amount'                 => 'Offener Betrag',
@@ -1587,6 +1596,7 @@ $self->{texts} = {
   'Search contacts'             => 'Ansprechpartnersuche',
   'Search term'                 => 'Suchbegriff',
   'Searchable'                  => 'Durchsuchbar',
+  'Secondary sorting'           => 'Untersortierung',
   'Select'                      => 'auswählen',
   'Select a Customer'           => 'Endkunde auswählen',
   'Select a customer'           => 'Einen Kunden ausw&auml;hlen',
@@ -1649,12 +1659,14 @@ $self->{texts} = {
   'Show details'                => 'Detailsanzeige',
   'Show follow ups...'          => 'Zeige Wiedervorlagen...',
   'Show help text'              => 'Hilfetext anzeigen',
+  'Show items from invoices individually' => 'Artikel aus Rechnungen anzeigen',
   'Show old dunnings'           => 'Alte Mahnungen anzeigen',
   'Show overdue sales quotations and requests for quotations...' => 'Überfällige Angebote und Preisanfragen anzeigen...',
   'Show your TODO list after loggin in' => 'Aufgabenliste nach dem Anmelden anzeigen',
   'Signature'                   => 'Unterschrift',
   'Since bin is not enforced in the parts data, please specify a bin where goods without a specified bin will be put.' => 'Da Lagerpl&auml;tze kein Pflichtfeld sind, geben Sie bitte einen Lagerplatz an, in dem Waren ohne spezifizierten Lagerplatz eingelagert werden sollen.',
   'Single quotes'               => 'Einfache Anführungszeichen',
+  'Single values in item mode, cumulated values in invoice mode' => 'Einzelwerte im Artikelmodus, kumulierte Werte im Rechnungsmodus',
   'Skip'                        => 'Überspringen',
   'Skonto'                      => 'Skonto',
   'Skonto Terms'                => 'Zahlungsziel Skonto',
@@ -1962,6 +1974,7 @@ $self->{texts} = {
   'Total'                       => 'Summe',
   'Total Fees'                  => 'Kumulierte Gebühren',
   'Total stock value'           => 'Gesamter Bestandswert',
+  'Total sum'                   => 'Gesamtsumme',
   'Totals'                      => 'Summen',
   'Trade Discount'              => 'Rabatt',
   'Trans Id'                    => 'Trans-ID',
@@ -2173,6 +2186,7 @@ $self->{texts} = {
   'ar_aging_list'               => 'liste_offene_forderungen',
   'as at'                       => 'zum Stand',
   'assembly_list'               => 'erzeugnisliste',
+  'averaged values, in invoice mode only useful when filtered by a part' => 'gemittelte Werte, im Rechnungsmodus nur sinnvoll wenn nach Artikel gefiltert wird',
   'back'                        => 'zurück',
   'balance'                     => 'Betriebsvermögensvergleich/Bilanzierung',
   'bank_collection_payment_list_#1' => 'bankeinzugszahlungsliste_#1',
@@ -2216,6 +2230,7 @@ $self->{texts} = {
   'eMail?'                      => 'eMail?',
   'ea'                          => 'St.',
   'emailed to'                  => 'gemailt an',
+  'empty'                       => 'leer',
   'executed'                    => 'ausgeführt',
   'female'                      => 'weiblich',
   'follow_up_list'              => 'wiedervorlageliste',
@@ -2229,6 +2244,7 @@ $self->{texts} = {
   'inactive'                    => 'inaktiv',
   'income'                      => 'Einnahmen-Überschuß-Rechnung',
   'invoice'                     => 'Rechnung',
+  'invoice mode or item mode'   => 'Rechnungsmodus oder Artikelmodus',
   'invoice_list'                => 'debitorenbuchungsliste',
   'kivitendo'                   => 'kivitendo',
   'kivitendo Homepage'          => 'Infos zu kivitendo',
index 098cd40..77f1d38 100644 (file)
@@ -3,24 +3,73 @@
 
  <form method=post name="search_invoice" action=[% script %]>
 
-  <table width=100%>
+  <table width=100% border="0">
   <tr><th class=listtop>[% title %]</th></tr>
   <tr height="5"></tr>
   <tr>
    <td>
-    <table>
+    <table border="0">
      <tr>
-       <td>[% 'Main sorting' | $T8 %]</td>
-       <td colspan="3">
-        <input name="sortby" id="artikelsort" class="radio" type="radio" value="artikelsort" checked>
-        <label for="artikelsort">[% 'Parts' | $T8 %]</label>
-        <input name="sortby" id="customersort" class="radio" type="radio" value="customersort">
-        <label for="customersort">[% 'Customer' | $T8 %]</label>
-       </td>
+     <td>
+      <table border="1">
+       <tr>
+        <th align=left nowrap>[% 'Configuration' | $T8 %]</th>
+        <td>
+         <table border="0">
+           <tr>
+             <td align="right">[% 'Main sorting' | $T8 %]</td>
+             <td>
+               <select name="mainsort" id="mainsort">
+               <option value="description">[% 'Part' | $T8 %]</option>
+               <option value="customername">[% 'Customer' | $T8 %]</option>
+               <option value="country">[% 'Country' | $T8 %]</option>
+               <option value="partsgroup">[% 'Group' | $T8 %]</option>
+               <option value="business">[% 'Customer type' | $T8 %]</option>
+               <option value="salesman" selected="selected">[% 'Salesman' | $T8 %]</option>
+               <option value="month">[% 'Month' | $T8 %]</option>
+               </select>
+             </td>
+             <td align=left><input name="l_headers_mainsort" class=checkbox type=checkbox value="Y" checked> [% 'Heading' | $T8 %]</td>
+             <td align=left><input name="l_subtotal_mainsort" class=checkbox type=checkbox value="Y" checked> [% 'Subtotal' | $T8 %]</td>
+             </tr>
+             <tr>
+               <td align="right">[% 'Secondary sorting' | $T8 %]</td>
+               <td>
+                 <select name="subsort" id="subsort">
+                 <option value="description">[% 'Part' | $T8 %]</option>
+                 <option value="customername">[% 'Customer' | $T8 %]</option>
+                 <option value="country">[% 'Country' | $T8 %]</option>
+                 <option value="partsgroup">[% 'Group' | $T8 %]</option>
+                 <option value="business">[% 'Customer type' | $T8 %]</option>
+                 <option value="salesman">[% 'Salesman' | $T8 %]</option>
+                 <option value="month" selected="selected">[% 'Month' | $T8 %]</option>
+                 </select>
+                 </td>
+               <td align=left><input name="l_headers_subsort" class=checkbox type=checkbox value=Y checked> [% 'Heading' | $T8 %]</td>
+               <td align=left><input name="l_subtotal_subsort" class=checkbox type=checkbox value=Y checked> [% 'Subtotal' | $T8 %]</td>
+             </tr>
+           <tr>
+           <th align="right">[% 'Item mode' | $T8 %]</th>
+           <td colspan="3" align=left><input name="l_parts" class=checkbox type=checkbox value="Y"> ([%'Show items from invoices individually' | $T8 %]) </td>
+          </tr>
+          <tr> 
+           <th align="right">
+             [% 'Total sum' | $T8 %]
+           </th>
+           <td colspan="1" align=left><input name="l_total" class=checkbox type=checkbox value="Y" checked></td>
+            <td align="right" nowrap>[% 'Decimalplaces' | $T8 %]: </td>
+            <td colspan="2"><input name="decimalplaces" size="2" value="2"></td>
+          </tr>
+    </table>
+    </td>
+       <tr>
+        <th align=left nowrap>[% 'Filter' | $T8 %]</th>
+        <td>
+         <table border="0">
+           <tr>
+      <tr>
+        <th align=left colspan="4"><br>[% 'Filter' | $T8 %]:</br></th>
       </tr>
-
-
-
      <tr>
       <th align=right>[% 'Customer' | $T8 %]</th>
       <td colspan=3>
      </tr>
       <tr>
        <th align="right" nowrap>[% 'Customer Number' | $T8 %]</th>
-       <td><input name="customernumber" size="20"></td>
+       <td colspan="3"><input name="customernumber" size="20"></td>
       </tr>
      <tr>
       <th align=right nowrap>[% 'Department' | $T8 %]</th>
-      <td>
+      <td colspan="3">
             [%- INCLUDE 'generic/multibox.html'
                  name          = 'department',
                  style         = 'width: 250px',
      </tr>
       <tr>
        <th align="right" nowrap>[% 'Part Number' | $T8 %]</th>
-       <td><input name="partnumber" size="20"></td>
+       <td colspan="3"><input name="partnumber" size="20"></td>
       </tr>
       <tr>
        <th align="right" nowrap>[% 'Part Description' | $T8 %]</th>
        <td colspan="3"><input name="description" size="40"></td>
       </tr>
      <tr>
-      <th align=right nowrap>[% 'From' | $T8 %]</th>
+      <th align="right">[% 'Group' | $T8 %]</th>
+      <td>
+             [%- INCLUDE 'generic/multibox.html'
+                  name          = 'partsgroup_id',
+                  style         = 'width: 250px',
+                  DATA          =  ALL_PARTSGROUPS,
+                  id_key        = 'id',
+                  label_key     = 'partsgroup',
+                  show_empty    = 1,
+                  allow_textbox = 0,
+             -%]
+      </td>
+     </tr>
+      <tr>
+       <td align="right" nowrap>[% 'Country' | $T8 %]</td>
+       <td colspan="3"><input name="country" size="20"></td>
+      </tr>
+     <tr>
+      <th align="right">[% 'Employee' | $T8 %]</th>
+      <td>
+             [%- INCLUDE 'generic/multibox.html'
+                  name          = 'employee_id',
+                  style         = 'width: 250px',
+                  DATA          =  ALL_EMPLOYEES,
+                  id_key        = 'id',
+                  label_sub     = 'employee_labels',
+                  limit         = vclimit,
+                  show_empty    = 1,
+                  allow_textbox = 0,
+                  default       = ' ',
+             -%]
+      </td>
+     </tr>
+    <tr>
+     <th align="right">[% 'Salesman' | $T8 %]</th>
+     <td>
+            [%- INCLUDE 'generic/multibox.html'
+                 name          = 'salesman_id',
+                 style         = 'width: 250px',
+                 DATA          =  ALL_SALESMEN,
+                 id_key        = 'id',
+                 label_sub     = 'salesman_labels',
+                 limit         = vclimit,
+                 show_empty    = 1,
+                 allow_textbox = 0,
+            -%]
+     </td>
+     </tr>
+     <tr>
+      <th align="right">[% 'Customer type' | $T8 %]</th>
+      <td colspan="3">
+            [%- INCLUDE 'generic/multibox.html'
+                 name          =  'business_id',
+                 style         = "width: 250px",
+                 DATA          =  ALL_BUSINESS_TYPES,
+                 id_key        = 'id',
+                 label_key     = 'description',
+                 limit         = vclimit,
+                 show_empty    = 1,
+                 allow_textbox = 0,
+            -%]
+      </td>
+     </tr>
+     <tr>
+      <th align=right nowrap>[% 'Invoice Date' | $T8 %] [% 'From' | $T8 %]</th>
       <td>
        <input name=transdatefrom id=transdatefrom size=11 title="[% dateformat | html %]" onBlur="check_right_date_format(this)">
        <input type=button name=transdatefrom id="trigger1" value=[% 'button' | $T8 %]>
       <input type=button name=transdateto name=transdateto id="trigger2" value=[% 'button' | $T8 %]>
      </td>
     </tr>
+    <tr>
+        <th align=left colspan="4"><br>[% 'Filter for customer variables' | $T8 %]:</br></th>
+    </tr>
+   [% CUSTOM_VARIABLES_FILTER_CODE_CT %]
+    <tr>
+        <th align=left colspan="4"><br>[% 'Filter for item variables' | $T8 %]:</br></th>
+    </tr>
+   [% CUSTOM_VARIABLES_FILTER_CODE_IC %]
    <input type=hidden name=sort value=transdate>
    </table>
+
     </td>
-    </tr>
-    <tr>
-     <td>
-      <table>
-       <tr>
+      <tr>
         <th align=right nowrap>[% 'Include in Report' | $T8 %]</th>
         <td>
-         <table width=100%>
+         <table border="0">
+          <td colspan="4">
+            [% 'Cumulated or averaged values' | $T8 %] ([% 'invoice mode or item mode' | $T8 %]):
+          </td>
           <tr>
-           <td align=right><input name="l_description" class=checkbox type=checkbox value=Y checked></td>
-           <td nowrap>[% 'Description' | $T8 %]</td>
-           <td align=right><input name="l_partnumber" class=checkbox type=checkbox value=Y></td>
-           <td nowrap>[% 'Part Number' | $T8 %]</td>
-           <td align=right><input name="l_invnumber" class=checkbox type=checkbox value=Y checked></td>
-           <td nowrap>[% 'Invnumber' | $T8 %]</td>
-           <td align=right><input name="l_transdate" class=checkbox type=checkbox value="Y" checked></td>
-           <td nowrap>[% 'Invdate' | $T8 %]</td>
+           <td align=left><input name="l_sellprice_total" class=checkbox type=checkbox value=Y checked>[% 'Sales price total' | $T8 %]</td>
+           <td align=left><input name="l_lastcost_total" class=checkbox type=checkbox value=Y checked>[% 'Purchase price total' | $T8 %]</td>
+           <td align=left><input name="l_marge_total" class=checkbox type=checkbox value=Y checked>[% 'Margetotal' | $T8 %]</td>
+           <td colspan="4"> ([% 'Single values in item mode, cumulated values in invoice mode' | $T8 %])
+           
           </tr>
           <tr>
-           <td align=right><input name="l_qty" class=checkbox type=checkbox value="Y" checked></td>
-           <td nowrap>[% 'Quantity' | $T8 %]</td>
-           <td align=right><input name="l_discount" class=checkbox type=checkbox value="Y"></td>
-           <td nowrap>[% 'Discount' | $T8 %]</td>
-           <td align=right><input name="l_unit" class=checkbox type=checkbox value="Y"></td>
-           <td nowrap>[% 'Unit' | $T8 %]</td>
+           <td align=left><input name="l_sellprice" class=checkbox type=checkbox value=Y checked>[% 'Sales price' | $T8 %]</td>
+           <td align=left><input name="l_lastcost" class=checkbox type=checkbox value=Y checked>[% 'Purchase price' | $T8 %]</td>
+           <td align=left><input name="l_marge_percent" class=checkbox type=checkbox value=Y checked>[% 'Margepercent' | $T8 %]</td>
+           <td colspan="4">([% 'averaged values, in invoice mode only useful when filtered by a part' | $T8 %])</td>
           </tr>
           <tr>
-           <td align=right><input name="l_sellprice" class=checkbox type=checkbox value=Y checked></td>
-           <td nowrap>[% 'Sales price' | $T8 %]</td>
-           <td align=right><input name="l_sellprice_total" class=checkbox type=checkbox value=Y checked></td>
-           <td nowrap>[% 'Sales price total' | $T8 %]</td>
-           <td align=right><input name="l_lastcost" class=checkbox type=checkbox value=Y checked></td>
-           <td nowrap>[% 'Purchase price' | $T8 %]</td>
-           <td align=right><input name="l_lastcost_total" class=checkbox type=checkbox value=Y checked></td>
-           <td nowrap>[% 'Purchase price total' | $T8 %]</td>
+           <td align=left><input name="l_qty" class=checkbox type=checkbox value="Y" checked>[% 'Quantity' | $T8 %]</td>
+           <td align=left><input name="l_discount" class=checkbox type=checkbox value="Y">[% 'Discount' | $T8 %]</td>
+           <td></td>
+           <td colspan="4">([% 'averaged values, in invoice mode only useful when filtered by a part' | $T8 %])</td>
           </tr>
+          <tr><td colspan="7">&nbsp;</td></tr>
+          <td colspan="4" align="left">
+          [% 'Item values' | $T8 %] ([% 'Only shown in item mode' | $T8 %])
+          </td>
           <tr>
-           <td align=right><input name="l_marge_total" class=checkbox type=checkbox value=Y checked></td>
-           <td nowrap>[% 'Margetotal' | $T8 %]</td>
-           <td align=right><input name="l_marge_percent" class=checkbox type=checkbox value=Y checked></td>
-           <td nowrap>[% 'Margepercent' | $T8 %]</td>
+           <td align=left><input name="l_description" class=checkbox type=checkbox value=Y checked>[% 'Description' | $T8 %]</td>
+           <td align=left><input name="l_partnumber" class=checkbox type=checkbox value=Y>[% 'Part Number' | $T8 %]</td>
+           <td align=left><input name="l_invnumber" class=checkbox type=checkbox value=Y>[% 'Invnumber' | $T8 %]</td>
+           <td align=left><input name="l_transdate" class=checkbox type=checkbox value="Y">[% 'Invdate' | $T8 %]</td>
           </tr>
           <tr>
-           <td align=right><input name="l_subtotal" class=checkbox type=checkbox value=Y checked></td>
-           <td nowrap>[% 'Subtotal' | $T8 %]</td>
-           <td align=right><input name="l_total" class=checkbox type=checkbox value="Y" checked></td>
-           <td nowrap>[% 'Total' | $T8 %]</td>
-           <td align=right><input name="l_headers" class=checkbox type=checkbox value="Y" checked></td>
-           <td nowrap>[% 'Headings' | $T8 %]</td>
+           <td align=left><input name="l_unit" class=checkbox type=checkbox value="Y">[% 'Unit' | $T8 %]</td>
+           <td align=left><input name="l_partsgroup" class=checkbox type=checkbox value=Y>[% 'Group' | $T8 %]</td>
+           <td align=left><input name="l_salesman" class=checkbox type=checkbox value=Y>[% 'Salesperson' | $T8 %]</td>
+           <td align=left><input name="l_employee" class=checkbox type=checkbox value=Y>[% 'Employee' | $T8 %]</td>
           </tr>
           <tr>
-           <td align=right><input name="l_customernumber" class=checkbox type=checkbox value=Y checked></td>
-           <td nowrap>[% 'Customer Number' | $T8 %]</td>
+           <td align=left><input name="l_customernumber" class=checkbox type=checkbox value=Y>[% 'Customer Number' | $T8 %]</td>
+           <td align=left><input name="l_customername" class=checkbox type=checkbox value=Y>[% 'Customer Name' | $T8 %]</td>
+           <td align=left><input name="l_country" class=checkbox type=checkbox value=Y>[% 'Country' | $T8 %]</td>
+           <td align=left><input name="l_business" class=checkbox type=checkbox value=Y>[% 'Customer type' | $T8 %]</td>
           </tr>
           <tr>
-            <th align="right" nowrap>[% 'Decimalplaces' | $T8 %]</th>
-            <td colspan="4"><input name="decimalplaces" size="2" value="2"></td>
           </tr>
+     <tr><td colspan="7">&nbsp;</td></tr>
+    <tr>
+    <th colspan="4" align="left">
+    [% 'Customer variables' | $T8 %] ([% 'Only shown in item mode' | $T8 %])
+    </th>
+    </tr>
+        [% CUSTOM_VARIABLES_INCLUSION_CODE_CT %]
+     <tr><td colspan="7">&nbsp;</td></tr>
+    <tr>
+    <th colspan="4" align="left">
+    [% 'Item variables' | $T8 %] ([% 'Only shown in item mode' | $T8 %])
+    </th>
+    </tr>
+      [% CUSTOM_VARIABLES_INCLUSION_CODE_IC %]
          </table>
         </td>
        </tr>
      </td>
     </tr>
     <tr>
-     <td><hr size=3 noshade></td>
     </tr>
    </table>
    <input type=hidden name=nextsub value=[% nextsub %]>