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
This commit is contained in:
Marica 2019-10-09 15:24:58 +05:30 committed by Nabin Hait
parent 38ac7f7350
commit ccad0a4cf9
4 changed files with 262 additions and 0 deletions

View File

@ -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]);
});
}
}
});
}
}
});

View File

@ -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
}

View File

@ -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