[Fix] total projected qty
diff --git a/erpnext/manufacturing/doctype/production_order/test_production_order.py b/erpnext/manufacturing/doctype/production_order/test_production_order.py
index d29544b..49db299 100644
--- a/erpnext/manufacturing/doctype/production_order/test_production_order.py
+++ b/erpnext/manufacturing/doctype/production_order/test_production_order.py
@@ -10,7 +10,9 @@
from erpnext.manufacturing.doctype.production_order.production_order \
import make_stock_entry, ItemHasVariantError
from erpnext.stock.doctype.stock_entry import test_stock_entry
+from erpnext.stock.doctype.item.test_item import get_total_projected_qty
from erpnext.stock.utils import get_bin
+from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
class TestProductionOrder(unittest.TestCase):
def setUp(self):
@@ -172,6 +174,28 @@
self.assertEqual(self.bin1_at_start.projected_qty,
cint(bin1_on_cancel.projected_qty))
+ def test_projected_qty_for_production_and_sales_order(self):
+ before_production_order = get_bin(self.item, self.warehouse)
+ before_production_order.update_reserved_qty_for_production()
+
+ self.pro_order = make_prod_order_test_record(item="_Test FG Item", qty=2,
+ source_warehouse=self.warehouse)
+
+ after_production_order = get_bin(self.item, self.warehouse)
+
+ sales_order = make_sales_order(item = self.item, qty = 2)
+ after_sales_order = get_bin(self.item, self.warehouse)
+
+ self.assertEqual(cint(before_production_order.reserved_qty_for_production) + 2,
+ cint(after_sales_order.reserved_qty_for_production))
+ self.assertEqual(cint(before_production_order.projected_qty),
+ cint(after_sales_order.projected_qty) + 2)
+
+ total_projected_qty = get_total_projected_qty(self.item)
+
+ item_doc = frappe.get_doc('Item', self.item)
+ self.assertEqual(total_projected_qty, item_doc.total_projected_qty)
+
def test_reserved_qty_for_production_on_stock_entry(self):
test_stock_entry.make_stock_entry(item_code="_Test Item",
target= self.warehouse, qty=100, basic_rate=100)
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index d9ef272..3caf714 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -320,3 +320,4 @@
erpnext.patches.v7_0.update_mode_of_payment_type
finally:erpnext.patches.v7_0.update_timesheet_communications
erpnext.patches.v7_0.update_status_of_zero_amount_sales_order
+erpnext.patches.v7_0.repost_bin_qty_and_item_projected_qty
diff --git a/erpnext/patches/v7_0/repost_bin_qty_and_item_projected_qty.py b/erpnext/patches/v7_0/repost_bin_qty_and_item_projected_qty.py
new file mode 100644
index 0000000..97af20a
--- /dev/null
+++ b/erpnext/patches/v7_0/repost_bin_qty_and_item_projected_qty.py
@@ -0,0 +1,28 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from erpnext.stock.doctype.bin.bin import update_item_projected_qty
+
+def execute():
+ repost_bin_qty()
+ repost_item_projected_qty()
+
+def repost_bin_qty():
+ for bin in frappe.db.sql(""" select name from `tabBin`
+ where (actual_qty + ordered_qty + indented_qty + planned_qty- reserved_qty - reserved_qty_for_production) != projected_qty """, as_dict=1):
+ bin_doc = frappe.get_doc('Bin', bin.name)
+ bin_doc.set_projected_qty()
+ bin_doc.db_set("projected_qty", bin_doc.projected_qty, update_modified = False)
+
+def repost_item_projected_qty():
+ for data in frappe.db.sql(""" select
+ `tabBin`.item_code as item_code,
+ sum(`tabBin`.projected_qty) as projected_qty,
+ `tabItem`.total_projected_qty as total_projected_qty
+ from
+ `tabBin`, `tabItem`
+ where `tabBin`.item_code = `tabItem`.name
+ group by `tabBin`.item_code having projected_qty <> total_projected_qty """, as_dict=1):
+ update_item_projected_qty(data.item_code)
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index f687868..41f4ecf 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -5,6 +5,7 @@
from frappe.utils import flt, add_days
import frappe.permissions
import unittest
+from erpnext.stock.doctype.item.test_item import get_total_projected_qty
from erpnext.selling.doctype.sales_order.sales_order \
import make_material_request, make_delivery_note, make_sales_invoice, WarehouseRequired
@@ -427,6 +428,13 @@
self.assertEquals(abs(flt(reserved_qty)), existing_reserved_qty_for_dn_item)
+ def test_total_projected_qty_against_sales_order(self):
+ so = make_sales_order(item = '_Test Item')
+ total_projected_qty = get_total_projected_qty('_Test Item')
+
+ item_doc = frappe.get_doc('Item', '_Test Item')
+ self.assertEqual(total_projected_qty, item_doc.total_projected_qty)
+
def test_reserved_qty_for_closing_so(self):
bin = frappe.get_all("Bin", filters={"item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC"},
fields=["reserved_qty"])
diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py
index 2378e3f..ece8220 100644
--- a/erpnext/stock/doctype/bin/bin.py
+++ b/erpnext/stock/doctype/bin/bin.py
@@ -14,18 +14,18 @@
self.stock_uom = frappe.db.get_value('Item', self.item_code, 'stock_uom')
self.validate_mandatory()
-
- self.projected_qty = flt(self.actual_qty) + flt(self.ordered_qty) + \
- flt(self.indented_qty) + flt(self.planned_qty) - flt(self.reserved_qty)
-
+ self.set_projected_qty()
self.block_transactions_against_group_warehouse()
+ def on_update(self):
+ update_item_projected_qty(self.item_code)
+
def validate_mandatory(self):
qf = ['actual_qty', 'reserved_qty', 'ordered_qty', 'indented_qty']
for f in qf:
if (not getattr(self, f, None)) or (not self.get(f)):
self.set(f, 0.0)
-
+
def block_transactions_against_group_warehouse(self):
from erpnext.stock.utils import is_group_warehouse
is_group_warehouse(self.warehouse)
@@ -72,9 +72,7 @@
self.indented_qty = flt(self.indented_qty) + flt(args.get("indented_qty"))
self.planned_qty = flt(self.planned_qty) + flt(args.get("planned_qty"))
- self.set_projected_qty()
self.save()
- update_item_projected_qty(self.item_code)
def set_projected_qty(self):
self.projected_qty = (flt(self.actual_qty) + flt(self.ordered_qty)
diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py
index bd617c6..aceefc0 100644
--- a/erpnext/stock/doctype/item/test_item.py
+++ b/erpnext/stock/doctype/item/test_item.py
@@ -177,4 +177,10 @@
variant.item_name = "_Test Variant Item-S"
variant.save()
+def get_total_projected_qty(item):
+ total_qty = frappe.db.sql(""" select sum(projected_qty) as projected_qty from tabBin
+ where item_code = %(item)s""", {'item': item}, as_dict=1)
+
+ return total_qty[0].projected_qty if total_qty else 0.0
+
test_records = frappe.get_test_records('Item')