[enhancement] added reserved_qty_for_production in bin and updated item dashboard
diff --git a/erpnext/stock/doctype/bin/bin.js b/erpnext/stock/doctype/bin/bin.js
new file mode 100644
index 0000000..40411b6
--- /dev/null
+++ b/erpnext/stock/doctype/bin/bin.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Bin', {
+ refresh: function(frm) {
+
+ }
+});
diff --git a/erpnext/stock/doctype/bin/bin.json b/erpnext/stock/doctype/bin/bin.json
index 9eb3995..bb0de3f 100644
--- a/erpnext/stock/doctype/bin/bin.json
+++ b/erpnext/stock/doctype/bin/bin.json
@@ -16,6 +16,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 1,
"label": "Warehouse",
@@ -42,6 +43,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 1,
"label": "Item Code",
@@ -69,6 +71,7 @@
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Reserved Quantity",
@@ -95,6 +98,7 @@
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 1,
"label": "Actual Quantity",
@@ -121,6 +125,7 @@
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Ordered Quantity",
@@ -147,6 +152,7 @@
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Requested Quantity",
@@ -172,6 +178,7 @@
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Planned Qty",
@@ -197,6 +204,7 @@
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Projected Qty",
@@ -218,10 +226,36 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "fieldname": "reserved_qty_for_production",
+ "fieldtype": "Float",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Reserved Qty for Production",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
"fieldname": "ma_rate",
"fieldtype": "Float",
"hidden": 1,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Moving Average Rate",
@@ -247,6 +281,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "UOM",
@@ -273,6 +308,7 @@
"fieldtype": "Float",
"hidden": 1,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "FCFS Rate",
@@ -298,6 +334,7 @@
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Valuation Rate",
@@ -323,6 +360,7 @@
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Stock Value",
@@ -350,7 +388,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2016-02-10 02:39:45.738623",
+ "modified": "2016-04-18 08:12:57.341517",
"modified_by": "Administrator",
"module": "Stock",
"name": "Bin",
@@ -417,8 +455,10 @@
"write": 0
}
],
+ "quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"search_fields": "item_code,warehouse",
- "sort_order": "ASC"
+ "sort_order": "ASC",
+ "track_seen": 0
}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py
index ae7c6e7..a1580d5 100644
--- a/erpnext/stock/doctype/bin/bin.py
+++ b/erpnext/stock/doctype/bin/bin.py
@@ -65,12 +65,15 @@
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.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.save()
update_item_projected_qty(self.item_code)
+ def set_projected_qty(self):
+ self.projected_qty = (flt(self.actual_qty) + flt(self.ordered_qty)
+ + flt(self.indented_qty) + flt(self.planned_qty) - flt(self.reserved_qty)
+ - flt(self.reserved_qty_for_production))
+
def get_first_sle(self):
sle = frappe.db.sql("""
select * from `tabStock Ledger Entry`
@@ -81,8 +84,25 @@
""", (self.item_code, self.warehouse), as_dict=1)
return sle and sle[0] or None
+ def update_reserved_qty_for_production(self):
+ '''Update qty reserved for production from Production Item tables
+ in open production orders'''
+ self.reserved_qty_for_production = frappe.db.sql('''select sum(required_qty - transferred_qty)
+ from `tabProduction Order` pro, `tabProduction Order Item` item
+ where
+ item.item_code = %s
+ and item.parent = pro.name
+ and pro.docstatus = 1
+ and pro.source_warehouse = %s''', (self.item_code, self.warehouse))[0][0]
+
+ self.set_projected_qty()
+
+ self.db_set('reserved_qty_for_production', self.reserved_qty_for_production)
+ self.db_set('projected_qty', self.projected_qty)
+
+
def update_item_projected_qty(item_code):
- '''Set Item project qty'''
+ '''Set total_projected_qty in Item as sum of projected qty in all warehouses'''
frappe.db.sql('''update tabItem set
total_projected_qty = ifnull((select sum(projected_qty) from tabBin where item_code=%s), 0)
where name=%s''', (item_code, item_code))
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 900c40c..4a4de4c 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -16,12 +16,6 @@
},
- dashboard_update: function(frm) {
- if(frm.dashboard_data.stock_data && frm.dashboard_data.stock_data.length) {
- frm.dashboard.add_stats(frappe.render_template('item_dashboard', {data: frm.dashboard_data.stock_data}))
- }
- },
-
refresh: function(frm) {
if(frm.doc.is_stock_item) {
@@ -82,7 +76,25 @@
erpnext.item.toggle_attributes(frm);
- frm.dashboard.show_links();
+ frm.dashboard.show_dashboard();
+ },
+
+ dashboard_update: function(frm) {
+ if(frm.dashboard_data.stock_data && frm.dashboard_data.stock_data.length) {
+ var max_count = 0;
+ frm.dashboard_data.stock_data.forEach(function(d) {
+ d.actual_or_pending = d.projected_qty - d.reserved_qty;
+ d.pending_qty = 0;
+ if(d.actual_or_pending > d.actual_qty) {
+ d.pending_qty = d.actual_or_pending - d.actual_qty;
+ }
+
+ max_count = Math.max(d.actual_or_pending, d.actual_qty,
+ d.reserved_qty, max_count);
+ })
+ frm.dashboard.add_stats(frappe.render_template('item_dashboard',
+ {data: frm.dashboard_data.stock_data, max_count: max_count}));
+ }
},
validate: function(frm){
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index f0e5f29..649f97b 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -633,8 +633,8 @@
group by posting_date''', name))
def get_stock_data(name):
- return frappe.get_all('Bin', fields=['warehouse', 'actual_qty', 'projected_qty'],
- filters={'item_code': name})
+ return frappe.get_all('Bin', fields=['warehouse', 'actual_qty', 'projected_qty', 'reserved_qty'],
+ filters={'item_code': name}, order_by = 'warehouse asc')
def validate_end_of_life(item_code, end_of_life=None, disabled=None, verbose=1):
if (not end_of_life) or (disabled is None):
diff --git a/erpnext/stock/doctype/item/item_dashboard.html b/erpnext/stock/doctype/item/item_dashboard.html
index a002a50..cef209a 100644
--- a/erpnext/stock/doctype/item/item_dashboard.html
+++ b/erpnext/stock/doctype/item/item_dashboard.html
@@ -1,12 +1,39 @@
-<div style="padding-left: 15px;">
+<div style="padding-left: 15px; padding-right: 15px;">
<h5>Stock Levels</h5>
- <div class="row">
- <div class="col-md-6 col-xs-12">
- <ul class="list-unstyled">
- {% data.every(function(d) { %}
- <li class="small">{{ d.warehouse }}: {{ d.actual_qty }} ({{ d.projected_qty }})</li>
- {% }) %}
- </ul>
- </div>
- </div>
+ <ul class="list-group">
+ {% for(var i=0; i < data.length; i++) { var d = data[i]; %}
+ <li class="list-group-item" style="background-color: inherit;">
+ <div class="row">
+ <div class="col-sm-8 small" style="margin-top: 8px;">{{ d.warehouse }}</div>
+ <div class="col-sm-4 small">
+ <span class="inline-graph">
+ <span class="inline-graph-half" title="{{ __("Reserved Qty") }}">
+ <span class="inline-graph-count">{{ d.reserved_qty }}</span>
+ <span class="inline-graph-bar">
+ <span class="inline-graph-bar-inner"
+ style="width: {{ cint(Math.abs(d.reserved_qty)/max_count * 100) || 5 }}%">
+ </span>
+ </span>
+ </span>
+ <span class="inline-graph-half" title="{{ __("Acutal Qty {0} / Waiting Qty {1}", [d.actual_qty, d.pending_qty]) }}">
+ <span class="inline-graph-count">
+ {{ d.actual_qty }} {{ (d.pending_qty > 0) ? ("(" + d.pending_qty+ ")") : "" }}
+ </span>
+ <span class="inline-graph-bar">
+ <span class="inline-graph-bar-inner dark"
+ style="width: {{ cint(d.actual_qty/max_count * 100) }}%">
+ </span>
+ {% if(d.pending_qty > 0) { %}
+ <span class="inline-graph-bar-inner" title="{{ __("Projected Qty") }}"
+ style="width: {{ cint(d.pending_qty/max_count * 100) }}%">
+ </span>
+ {% } %}
+ </span>
+ </span>
+ </span>
+ </div>
+ </div>
+ </li>
+ {% } %}
+ </ul>
</div>
\ No newline at end of file
diff --git a/erpnext/stock/doctype/warehouse/test_records.json b/erpnext/stock/doctype/warehouse/test_records.json
index d5df175..e2162d2 100644
--- a/erpnext/stock/doctype/warehouse/test_records.json
+++ b/erpnext/stock/doctype/warehouse/test_records.json
@@ -13,6 +13,12 @@
},
{
"company": "_Test Company",
+ "create_account_under": "Fixed Assets - _TC",
+ "doctype": "Warehouse",
+ "warehouse_name": "_Test Warehouse 2"
+ },
+ {
+ "company": "_Test Company",
"create_account_under": "Stock Assets - _TC",
"doctype": "Warehouse",
"warehouse_name": "_Test Rejected Warehouse"
diff --git a/erpnext/stock/doctype/warehouse/warehouse.json b/erpnext/stock/doctype/warehouse/warehouse.json
index 00fe999..4e9dd07 100644
--- a/erpnext/stock/doctype/warehouse/warehouse.json
+++ b/erpnext/stock/doctype/warehouse/warehouse.json
@@ -91,6 +91,54 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
+ "fieldname": "disabled",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Disabled",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "column_break_4",
+ "fieldtype": "Column Break",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
"depends_on": "eval:sys_defaults.auto_accounting_for_stock",
"description": "Account for the warehouse (Perpetual Inventory) will be created under this Account.",
"fieldname": "create_account_under",
@@ -117,32 +165,8 @@
{
"allow_on_submit": 0,
"bold": 0,
- "collapsible": 0,
- "fieldname": "disabled",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 0,
- "label": "Disabled",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "description": "For Reference Only.",
+ "collapsible": 1,
+ "description": "",
"fieldname": "warehouse_contact_info",
"fieldtype": "Section Break",
"hidden": 0,
@@ -408,7 +432,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2016-03-30 03:31:43.954827",
+ "modified": "2016-04-18 05:44:24.837579",
"modified_by": "Administrator",
"module": "Stock",
"name": "Warehouse",
@@ -535,6 +559,7 @@
"write": 0
}
],
+ "quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"sort_order": "DESC",
diff --git a/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py b/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py
index b21b402..89963ab 100644
--- a/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py
+++ b/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py
@@ -14,7 +14,8 @@
return [_("Item Code") + ":Link/Item:140", _("Item Name") + "::100", _("Description") + "::200",
_("Item Group") + ":Link/Item Group:100", _("Brand") + ":Link/Brand:100", _("Warehouse") + ":Link/Warehouse:120",
_("UOM") + ":Link/UOM:100", _("Actual Qty") + ":Float:100", _("Planned Qty") + ":Float:100",
- _("Requested Qty") + ":Float:110", _("Ordered Qty") + ":Float:100", _("Reserved Qty") + ":Float:100",
+ _("Requested Qty") + ":Float:110", _("Ordered Qty") + ":Float:100",
+ _("Reserved Qty") + ":Float:100", _("Reserved Qty for Production") + ":Float:100",
_("Projected Qty") + ":Float:100", _("Reorder Level") + ":Float:100", _("Reorder Qty") + ":Float:100",
_("Shortage Qty") + ":Float:100"]
@@ -51,7 +52,7 @@
data.append([item.name, item.item_name, item.description, item.item_group, item.brand, bin.warehouse,
item.stock_uom, bin.actual_qty, bin.planned_qty, bin.indented_qty, bin.ordered_qty,
- bin.reserved_qty, bin.projected_qty, re_order_level, re_order_qty, shortage_qty])
+ bin.reserved_qty, bin.reserved_qty_for_production, bin.projected_qty, re_order_level, re_order_qty, shortage_qty])
return data
@@ -63,7 +64,8 @@
bin_filters.warehouse = filters.warehouse
bin_list = frappe.get_all("Bin", fields=["item_code", "warehouse",
- "actual_qty", "planned_qty", "indented_qty", "ordered_qty", "reserved_qty", "projected_qty"],
+ "actual_qty", "planned_qty", "indented_qty", "ordered_qty", "reserved_qty",
+ "reserved_qty_for_production", "projected_qty"],
filters=bin_filters, order_by="item_code, warehouse")
return bin_list
diff --git a/erpnext/stock/stock_balance.py b/erpnext/stock/stock_balance.py
index 7247d9e..7d92813 100644
--- a/erpnext/stock/stock_balance.py
+++ b/erpnext/stock/stock_balance.py
@@ -148,8 +148,9 @@
mismatch = True
if mismatch:
- bin.projected_qty = flt(bin.actual_qty) + flt(bin.ordered_qty) + \
+ bin.projected_qty = (flt(bin.actual_qty) + flt(bin.ordered_qty) +
flt(bin.indented_qty) + flt(bin.planned_qty) - flt(bin.reserved_qty)
+ - flt(bin.reserved_qty_for_production))
bin.save()