feat: Stock Quick Balance (#19123)
* feat: Stock Quick Balance
It will display the stock balance and stock value given the date and warehouse
Item code can be fed or barcode can be scanned to retrieve the values
* fix: Codacy fixes
* fix: Renamed to Quick Stock Balance and minor fixes
Refactored code , combined functions to make it DRY
Added permissions for Stock User and Manager
Added more context to naming
diff --git a/erpnext/stock/doctype/quick_stock_balance/__init__.py b/erpnext/stock/doctype/quick_stock_balance/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/stock/doctype/quick_stock_balance/__init__.py
diff --git a/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.js b/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.js
new file mode 100644
index 0000000..a6f7343
--- /dev/null
+++ b/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.js
@@ -0,0 +1,91 @@
+// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Quick Stock Balance', {
+
+ setup: (frm) => {
+ frm.set_query('item', () => {
+ if (!(frm.doc.warehouse && frm.doc.date)) {
+ frm.trigger('check_warehouse_and_date');
+ }
+ });
+ },
+
+ make_custom_stock_report_button: (frm) => {
+ if (frm.doc.item) {
+ frm.add_custom_button(__('Stock Balance Report'), () => {
+ frappe.set_route('query-report', 'Stock Balance',
+ { 'item_code': frm.doc.item, 'warehouse': frm.doc.warehouse });
+ }).addClass("btn-primary");
+ }
+ },
+
+ refresh: (frm) => {
+ frm.disable_save();
+ frm.trigger('make_custom_stock_report_button');
+ },
+
+ check_warehouse_and_date: (frm) => {
+ frappe.msgprint(__('Please enter Warehouse and Date'));
+ frm.doc.item = '';
+ frm.refresh();
+ },
+
+ warehouse: (frm) => {
+ if (frm.doc.item || frm.doc.item_barcode) {
+ frm.trigger('get_stock_and_item_details');
+ }
+ },
+
+ date: (frm) => {
+ if (frm.doc.item || frm.doc.item_barcode) {
+ frm.trigger('get_stock_and_item_details');
+ }
+ },
+
+ item: (frm) => {
+ frappe.flags.last_updated_element = 'item';
+ frm.trigger('get_stock_and_item_details');
+ frm.trigger('make_custom_stock_report_button');
+ },
+
+ item_barcode: (frm) => {
+ frappe.flags.last_updated_element = 'item_barcode';
+ frm.trigger('get_stock_and_item_details');
+ frm.trigger('make_custom_stock_report_button');
+ },
+
+ get_stock_and_item_details: (frm) => {
+ if (!(frm.doc.warehouse && frm.doc.date)) {
+ frm.trigger('check_warehouse_and_date');
+ }
+ else if (frm.doc.item || frm.doc.item_barcode) {
+ let filters = {
+ warehouse: frm.doc.warehouse,
+ date: frm.doc.date,
+ };
+ if (frappe.flags.last_updated_element === 'item') {
+ filters = { ...filters, ...{ item: frm.doc.item }};
+ }
+ else {
+ filters = { ...filters, ...{ barcode: frm.doc.item_barcode }};
+ }
+ frappe.call({
+ method: 'erpnext.stock.doctype.quick_stock_balance.quick_stock_balance.get_stock_item_details',
+ args: filters,
+ callback: (r) => {
+ if (r.message) {
+ let fields = ['item', 'qty', 'value', 'image'];
+ if (!r.message['barcodes'].includes(frm.doc.item_barcode)) {
+ frm.doc.item_barcode = '';
+ frm.refresh();
+ }
+ fields.forEach(function (field) {
+ frm.set_value(field, r.message[field]);
+ });
+ }
+ }
+ });
+ }
+ }
+});
diff --git a/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.json b/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.json
new file mode 100644
index 0000000..34ae7e6
--- /dev/null
+++ b/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.json
@@ -0,0 +1,137 @@
+{
+ "_comments": "[]",
+ "allow_copy": 1,
+ "creation": "2019-09-06 12:01:33.933063",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "warehouse",
+ "date",
+ "item_barcode",
+ "item",
+ "col_break",
+ "item_name",
+ "item_description",
+ "image",
+ "sec_break",
+ "qty",
+ "col_break2",
+ "value"
+ ],
+ "fields": [
+ {
+ "fieldname": "warehouse",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Warehouse",
+ "options": "Warehouse",
+ "reqd": 1
+ },
+ {
+ "fieldname": "item",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Item Code",
+ "options": "Item",
+ "reqd": 1
+ },
+ {
+ "fieldname": "col_break",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "item_barcode",
+ "fieldtype": "Data",
+ "label": "Item Barcode"
+ },
+ {
+ "fetch_from": "item.item_name",
+ "fieldname": "item_name",
+ "fieldtype": "Data",
+ "label": "Item Name",
+ "read_only": 1
+ },
+ {
+ "default": " ",
+ "fetch_from": "item.description",
+ "fieldname": "item_description",
+ "fieldtype": "Small Text",
+ "label": "Item Description",
+ "read_only": 1
+ },
+ {
+ "fieldname": "sec_break",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "qty",
+ "fieldtype": "Float",
+ "label": "Available Quantity",
+ "read_only": 1
+ },
+ {
+ "fieldname": "col_break2",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "value",
+ "fieldtype": "Currency",
+ "label": "Stock Value",
+ "read_only": 1
+ },
+ {
+ "fieldname": "image",
+ "fieldtype": "Image",
+ "label": "Image View",
+ "options": "image",
+ "print_hide": 1
+ },
+ {
+ "default": "Today",
+ "fieldname": "date",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "Date",
+ "reqd": 1
+ }
+ ],
+ "hide_toolbar": 1,
+ "issingle": 1,
+ "modified": "2019-10-04 21:59:48.597497",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Quick Stock Balance",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "read": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "read": 1,
+ "role": "Stock User",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "read": 1,
+ "role": "Stock Manager",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py b/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py
new file mode 100644
index 0000000..efa9519
--- /dev/null
+++ b/erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+from frappe.model.document import Document
+from erpnext.stock.utils import get_stock_balance, get_stock_value_on
+
+class QuickStockBalance(Document):
+ pass
+
+@frappe.whitelist()
+def get_stock_item_details(warehouse, date, item=None, barcode=None):
+ out = {}
+ if barcode:
+ out["item"] = frappe.db.get_value(
+ "Item Barcode", filters={"barcode": barcode}, fieldname=["parent"])
+ if not out["item"]:
+ frappe.throw(
+ _("Invalid Barcode. There is no Item attached to this barcode."))
+ else:
+ out["item"] = item
+
+ barcodes = frappe.db.get_values("Item Barcode", filters={"parent": out["item"]},
+ fieldname=["barcode"])
+
+ out["barcodes"] = [x[0] for x in barcodes]
+ out["qty"] = get_stock_balance(out["item"], warehouse, date)
+ out["value"] = get_stock_value_on(warehouse, date, out["item"])
+ out["image"] = frappe.db.get_value("Item",
+ filters={"name": out["item"]}, fieldname=["image"])
+ return out