commit a33ef0ec2f31a94dd1e87384eaf41a2f7b25385f
Author: Jan Büren <jan@kivitendo-premium.de>
Date:   Sat Jul 22 10:51:55 2017 +0200

    Artikelbericht (IC.pm): Standardlager und Standardlagerplatz optional anzeigen

diff --git a/SL/IC.pm b/SL/IC.pm
index 8782aae8d..e36cc4fae 100644
--- a/SL/IC.pm
+++ b/SL/IC.pm
@@ -128,6 +128,7 @@ sub assembly_item {
 #
 # column flags:
 #   l_partnumber l_description l_listprice l_sellprice l_lastcost l_priceupdate l_weight l_unit l_rop l_image l_drawing l_microfiche l_partsgroup
+#   l_warehouse  l_bin
 #
 # exclusives:
 #   itemstatus  = active | onhand | short | obsolete | orphaned
@@ -136,6 +137,8 @@ sub assembly_item {
 # joining filters:
 #   make model                               - makemodel
 #   serialnumber transdatefrom transdateto   - invoice/orderitems
+#   warehouse                                - warehouse
+#   bin                                      - bin
 #
 # binary flags:
 #   bought sold onorder ordered rfq quoted   - aggreg joins with invoices/orders
@@ -151,6 +154,8 @@ sub assembly_item {
 #   onhand                                   - as above, but masking the simple itemstatus results (doh!)
 #   warehouse onhand
 #   search by overrides of description
+#   soldtotal drops option default warehouse and bin
+#   soldtotal can not work if there are no documents checked
 #
 # disabled sanity checks and changes:
 #  - searchitems = assembly will no longer disable bought
@@ -167,6 +172,9 @@ sub all_parts {
   my ($self, $myconfig, $form) = @_;
   my $dbh = $form->get_standard_dbh($myconfig);
 
+  # sanity backend check
+  croak "Cannot combine soldtotal with default bin or default warehouse" if ($form->{l_soldtotal} && ($form->{l_bin} || $form->{l_warehouse}));
+
   $form->{parts}     = +{ };
   $form->{soldtotal} = undef if $form->{l_soldtotal}; # security fix. top100 insists on putting strings in there...
 
@@ -178,6 +186,7 @@ sub all_parts {
   my @like_filters         = (@simple_filters, @invoice_oi_filters);
   my @all_columns          = (@simple_filters, @makemodel_filters, @apoe_filters, @project_filters, qw(serialnumber));
   my @simple_l_switches    = (@all_columns, qw(notes listprice sellprice lastcost priceupdate weight unit rop image shop insertdate));
+  my %no_simple_l_switches = (warehouse => 'wh.description as warehouse', bin => 'bin.description as bin');
   my @oe_flags             = qw(bought sold onorder ordered rfq quoted);
   my @qsooqr_flags         = qw(invnumber ordnumber quonumber trans_id name module qty);
   my @deliverydate_flags   = qw(deliverydate);
@@ -212,8 +221,10 @@ sub all_parts {
          ) AS cv ON cv.id = apoe.customer_id OR cv.id = apoe.vendor_id|,
     mv         => 'LEFT JOIN vendor AS mv ON mv.id = mm.make',
     project    => 'LEFT JOIN project AS pj ON pj.id = COALESCE(ioi.project_id, apoe.globalproject_id)',
+    warehouse  => 'LEFT JOIN warehouse AS wh ON wh.id = p.warehouse_id',
+    bin        => 'LEFT JOIN bin ON bin.id = p.bin_id',
   );
-  my @join_order = qw(partsgroup makemodel mv invoice_oi apoe cv pfac project);
+  my @join_order = qw(partsgroup makemodel mv invoice_oi apoe cv pfac project warehouse bin);
 
   my %table_prefix = (
      deliverydate => 'apoe.', serialnumber => 'ioi.',
@@ -442,6 +453,8 @@ sub all_parts {
   $joins_needed{cv}          = 1 if $bsooqr;
   $joins_needed{apoe}        = 1 if $joins_needed{project} || $joins_needed{cv}   || grep { $form->{$_} || $form->{"l_$_"} } @apoe_filters;
   $joins_needed{invoice_oi}  = 1 if $joins_needed{project} || $joins_needed{apoe} || grep { $form->{$_} || $form->{"l_$_"} } @invoice_oi_filters;
+  $joins_needed{bin}         = 1 if $form->{l_bin};
+  $joins_needed{warehouse}   = 1 if $form->{l_warehouse};
 
   # special case for description search.
   # up in the simple filter section the description filter got interpreted as something like: WHERE description ILIKE '%$form->{description}%'
@@ -478,6 +491,16 @@ sub all_parts {
   my $where_clause  = join ' AND ', map { "($_)" } @where_tokens;
   my $group_clause  = @group_tokens ? ' GROUP BY ' . join ', ',    map { $token_builder->($_) } @group_tokens : '';
 
+  # key of %no_simple_l_switch is the logical l_switch.
+  # the assigned value is the 'not so simple
+  # select token'
+  my $no_simple_select_clause;
+  foreach my $no_simple_l_switch (keys %no_simple_l_switches) {
+    next unless $form->{"l_${no_simple_l_switch}"};
+    $no_simple_select_clause .= ', '. $no_simple_l_switches{$no_simple_l_switch};
+  }
+  $select_clause .= $no_simple_select_clause;
+
   my %oe_flag_to_cvar = (
     bought   => 'invoice',
     sold     => 'invoice',
diff --git a/bin/mozilla/ic.pl b/bin/mozilla/ic.pl
index 24a275412..d4ad5f14f 100644
--- a/bin/mozilla/ic.pl
+++ b/bin/mozilla/ic.pl
@@ -167,7 +167,6 @@ sub generate_report {
   $form->{title} = $locale->text('Articles');
 
   my %column_defs = (
-    'bin'                => { 'text' => $locale->text('Bin'), },
     'deliverydate'       => { 'text' => $locale->text('deliverydate'), },
     'description'        => { 'text' => $locale->text('Part Description'), },
     'notes'              => { 'text' => $locale->text('Notes'), },
@@ -201,6 +200,8 @@ sub generate_report {
     'type_and_classific' => { 'text' => $locale->text('Type'), },
     'projectnumber'      => { 'text' => $locale->text('Project Number'), },
     'projectdescription' => { 'text' => $locale->text('Project Description'), },
+    'warehouse'          => { 'text' => $locale->text('Default Warehouse'), },
+    'bin'                => { 'text' => $locale->text('Default Bin'), },
   );
 
   $revers     = $form->{revers};
@@ -327,8 +328,8 @@ sub generate_report {
 
   if ($form->{l_service} && !$form->{l_assembly} && !$form->{l_part}) {
 
-    # remove bin, weight and rop from list
-    map { $form->{"l_$_"} = "" } qw(bin weight rop);
+    # remove warehouse, bin, weight and rop from list
+    map { $form->{"l_$_"} = "" } qw(bin weight rop warehouse);
 
     $form->{l_onhand} = "";
 
@@ -364,6 +365,10 @@ sub generate_report {
 
     flash('warning', $::locale->text('Soldtotal does not make sense without any bsooqr options'));
   }
+  if ($form->{l_soldtotal} && ($form->{l_warehouse} || $form->{l_bin})) {
+    delete $form->{"l_$_"} for  qw(bin warehouse);
+    flash('warning', $::locale->text('Sorry, I am too stupid to figure out the default warehouse/bin and the sold qty. I drop the default warehouse/bin option.'));
+  }
   if ($form->{l_name} && !$bsooqr_mode) {
     delete $form->{l_name};
 
@@ -372,7 +377,8 @@ sub generate_report {
   IC->all_parts(\%myconfig, \%$form);
 
   my @columns = qw(
-    partnumber type_and_classific description notes partsgroup bin onhand rop soldtotal unit listprice
+    partnumber type_and_classific description notes partsgroup warehouse bin
+    onhand rop soldtotal unit listprice
     linetotallistprice sellprice linetotalsellprice lastcost linetotallastcost
     priceupdate weight image drawing microfiche invnumber ordnumber quonumber
     transdate name serialnumber deliverydate ean projectnumber projectdescription
@@ -416,7 +422,7 @@ sub generate_report {
   my $callback         = build_std_url('action=generate_report', grep { $form->{$_} } @hidden_variables);
 
   my @sort_full        = qw(partnumber description onhand soldtotal deliverydate insertdate shop);
-  my @sort_no_revers   = qw(partsgroup bin priceupdate invnumber ordnumber quonumber name image drawing serialnumber);
+  my @sort_no_revers   = qw(partsgroup priceupdate invnumber ordnumber quonumber name image drawing serialnumber);
 
   foreach my $col (@sort_full) {
     $column_defs{$col}->{link} = join '&', $callback, "sort=$col", map { "$_=" . E($form->{$_}) } qw(revers lastsort);
diff --git a/doc/changelog b/doc/changelog
index eab5480be..b36292e7e 100644
--- a/doc/changelog
+++ b/doc/changelog
@@ -8,7 +8,7 @@ kleinere neue Features und Detailverbesserungen:
 
   - SEPA-XML: alle Sonderzeichen filtern
   - SEPA-Export: Export wieder rückgängig machen, falls noch Status offen
-
+  - Stammdaten -> Berichte -> Artikel: Standardlager und Lagerplatz optional anzeigen
 
 2017-07-17 - Release 3.5.0
 
diff --git a/locale/de/all b/locale/de/all
index 889ce2689..eaaa2eba4 100755
--- a/locale/de/all
+++ b/locale/de/all
@@ -2728,6 +2728,7 @@ $self->{texts} = {
   'Sold order items'            => 'Verkaufte Auftragsartikel',
   'Soldtotal does not make sense without any bsooqr options' => 'Option "Menge in gewählten Belegen" ohne gewählte Belege wird ignoriert.',
   'Solution'                    => 'Lösung',
+  'Sorry, I am too stupid to figure out the default warehouse/bin and the sold qty. I drop the default warehouse/bin option.' => 'Entschuldigung, ich bin nicht in der Lage Standard-Lager und die Menge in gewählten Belegen gleichzeitig anzuzeigen. Ich lass die Standard-Lager weg.',
   'Sort By'                     => 'Sortiert nach',
   'Source'                      => 'Beleg',
   'Source BIC'                  => 'Quell-BIC',
