WH: fix: duplizierte Lagerjournalmengen bei produzierten Erzeugnissen
authorSven Schöling <s.schoeling@googlemail.com>
Fri, 21 May 2021 13:02:42 +0000 (15:02 +0200)
committerSven Schöling <s.schoeling@googlemail.com>
Fri, 21 May 2021 13:10:31 +0000 (15:10 +0200)
Analog zu odyn e7850d3d61 und b829d12400

Das Lagerjournal wurde ursprünglich in der Annahme gebaut dass eine
Transaktion maximal 2 Einträge hat. Eine Einlagerung und eine
Auslagerung.

Beim Produzieren von Erzeugnissen werden aber mittlerweile in einer
trans_id mehrere Lagerbewegungen zusammengefasst. Der Self-join auf
inventory für eine rechte und eine linke Seite funktioniert damit nicht
mehr.

Eigentlich müsste man das komplett umbauen, dieser Fix sorgt aber
erstmal dafür dass die Mengen stimmen, in dem der selfjoin exakt auf die
gleiche Zeile passiert. Rückbuchungen und Stornos sind damit auch
korrekt verbucht.

SL/WH.pm
t/wh/journal.t [new file with mode: 0644]

index 3efe8c0..2899aaf 100644 (file)
--- a/SL/WH.pm
+++ b/SL/WH.pm
@@ -548,26 +548,10 @@ sub get_warehouse_journal {
   $where_clause = defined($where_clause) ? $where_clause : '';
 
   my $query =
-  qq|SELECT * FROM (SELECT DISTINCT $select{trans}
-    FROM inventory i1
-    LEFT JOIN inventory i2 ON i1.trans_id = i2.trans_id
-    LEFT JOIN parts p ON i1.parts_id = p.id
-    LEFT JOIN bin b1 ON i1.bin_id = b1.id
-    LEFT JOIN bin b2 ON i2.bin_id = b2.id
-    LEFT JOIN warehouse w1 ON i1.warehouse_id = w1.id
-    LEFT JOIN warehouse w2 ON i2.warehouse_id = w2.id
-    LEFT JOIN transfer_type tt ON i1.trans_type_id = tt.id
-    LEFT JOIN project pr ON i1.project_id = pr.id
-    LEFT JOIN employee e ON i1.employee_id = e.id
-    WHERE $where_clause i2.qty = -i1.qty AND i2.qty > 0 AND
-          i1.trans_id IN ( SELECT i.trans_id FROM inventory i GROUP BY i.trans_id HAVING COUNT(i.trans_id) = 2 )
-    GROUP BY $group_clause
-
-    UNION
-
+  qq|SELECT * FROM (
     SELECT DISTINCT $select{out}
     FROM inventory i1
-    LEFT JOIN inventory i2 ON i1.trans_id = i2.trans_id
+    LEFT JOIN inventory i2 ON i1.trans_id = i2.trans_id AND i1.id = i2.id
     LEFT JOIN parts p ON i1.parts_id = p.id
     LEFT JOIN bin b1 ON i1.bin_id = b1.id
     LEFT JOIN bin b2 ON i2.bin_id = b2.id
@@ -576,7 +560,7 @@ sub get_warehouse_journal {
     LEFT JOIN transfer_type tt ON i1.trans_type_id = tt.id
     LEFT JOIN project pr ON i1.project_id = pr.id
     LEFT JOIN employee e ON i1.employee_id = e.id
-    WHERE $where_clause i1.qty < 0 AND
+    WHERE $where_clause i1.qty != 0 AND tt.direction = 'out' AND
           i1.trans_id IN ( SELECT i.trans_id FROM inventory i GROUP BY i.trans_id HAVING COUNT(i.trans_id) >= 1 )
     GROUP BY $group_clause
 
@@ -584,7 +568,7 @@ sub get_warehouse_journal {
 
     SELECT DISTINCT $select{in}
     FROM inventory i1
-    LEFT JOIN inventory i2 ON i1.trans_id = i2.trans_id
+    LEFT JOIN inventory i2 ON i1.trans_id = i2.trans_id AND i1.id = i2.id
     LEFT JOIN parts p ON i1.parts_id = p.id
     LEFT JOIN bin b1 ON i1.bin_id = b1.id
     LEFT JOIN bin b2 ON i2.bin_id = b2.id
@@ -593,12 +577,12 @@ sub get_warehouse_journal {
     LEFT JOIN transfer_type tt ON i1.trans_type_id = tt.id
     LEFT JOIN project pr ON i1.project_id = pr.id
     LEFT JOIN employee e ON i1.employee_id = e.id
-    WHERE $where_clause i1.qty > 0 AND
+    WHERE $where_clause i1.qty != 0 AND tt.direction = 'in' AND
           i1.trans_id IN ( SELECT i.trans_id FROM inventory i GROUP BY i.trans_id HAVING COUNT(i.trans_id) >= 1 )
     GROUP BY $group_clause
-    ORDER BY r_${sort_spec}) AS lines WHERE r_qty>0|;
+    ORDER BY r_${sort_spec}) AS lines WHERE r_qty != 0|;
 
-  my @all_vars = (@filter_vars,@filter_vars,@filter_vars);
+  my @all_vars = (@filter_vars,@filter_vars);
 
   if ($filter{limit}) {
     $query .= " LIMIT ?";
diff --git a/t/wh/journal.t b/t/wh/journal.t
new file mode 100644 (file)
index 0000000..e91bdb7
--- /dev/null
@@ -0,0 +1,75 @@
+use strict;
+use Test::More tests => 4;
+
+use lib 't';
+
+use SL::Dev::Part qw(new_part);
+use SL::Dev::Inventory qw(create_warehouse_and_bins);
+use SL::DB::Inventory;
+use Support::TestSetup;
+
+Support::TestSetup::login();
+
+use_ok("SL::WH");
+
+my ($wh, $bin, $part);
+
+sub init  {
+  ($wh, $bin) = create_warehouse_and_bins(
+    warehouse_description => 'Test warehouse',
+    bin_description       => 'Test bin',
+    number_of_bins        => 1,
+  );
+
+  $part = new_part()->save->load;
+
+  my $tt_used = SL::DB::Manager::TransferType->find_by(direction => 'out', description => 'used') or die;
+  my $tt_assembled = SL::DB::Manager::TransferType->find_by(direction => 'in', description => 'assembled') or die;
+
+  my %args = (
+    trans_id     => 1,
+    bin          => $bin,
+    warehouse    => $wh,
+    part         => $part,
+    qty          => 1,
+    employee     => SL::DB::Manager::Employee->current,
+    shippingdate => DateTime->now,
+  );
+
+  SL::DB::Inventory->new(%args, trans_type => $tt_used, qty => -1)->save;
+  SL::DB::Inventory->new(%args, trans_type => $tt_used, qty => -1)->save;
+  SL::DB::Inventory->new(%args, trans_type => $tt_assembled, qty => 1)->save;
+
+  qty                           => { type => 'numeric', precision => 25, scale => 5 },
+  shippingdate                  => { type => 'date', not_null => 1 },
+}
+
+sub reset_inventory {
+  SL::DB::Manager::Inventory->delete_all(all => 1);
+}
+
+reset_inventory();
+init();
+
+# l_date = Y
+# l_warehouse_from = Y
+# l_bin_from = Y
+# l_warehouse_to = Y
+# l_bin_to = Y
+# l_partnumber = Y
+# l_partdescription = Y
+# l_chargenumber = Y
+# l_trans_type = Y
+# l_qty = Y
+# l_oe_id = Y
+# l_projectnumber = Y
+# qty_op = dontcare
+
+
+my @contents = WH->get_warehouse_journal(sort => 'date');
+
+is $contents[0]{qty}, '1.00000', "produce assembly does not multiply qty (1)";
+is $contents[1]{qty}, '1.00000', "produce assembly does not multiply qty (2)";
+is $contents[2]{qty}, '1.00000', "produce assembly does not multiply qty (3)";
+
+1;