Merge pull request #24921 from Anurag810/item-dashboard-fixes
fix: precision and formatted document for stock level in item dashboard.
This commit is contained in:
commit
c6b3766fb2
@ -1,14 +1,14 @@
|
|||||||
frappe.provide('erpnext.stock');
|
frappe.provide('erpnext.stock');
|
||||||
|
|
||||||
erpnext.stock.ItemDashboard = Class.extend({
|
erpnext.stock.ItemDashboard = Class.extend({
|
||||||
init: function(opts) {
|
init: function (opts) {
|
||||||
$.extend(this, opts);
|
$.extend(this, opts);
|
||||||
this.make();
|
this.make();
|
||||||
},
|
},
|
||||||
make: function() {
|
make: function () {
|
||||||
var me = this;
|
var me = this;
|
||||||
this.start = 0;
|
this.start = 0;
|
||||||
if(!this.sort_by) {
|
if (!this.sort_by) {
|
||||||
this.sort_by = 'projected_qty';
|
this.sort_by = 'projected_qty';
|
||||||
this.sort_order = 'asc';
|
this.sort_order = 'asc';
|
||||||
}
|
}
|
||||||
@ -16,22 +16,25 @@ erpnext.stock.ItemDashboard = Class.extend({
|
|||||||
this.content = $(frappe.render_template('item_dashboard')).appendTo(this.parent);
|
this.content = $(frappe.render_template('item_dashboard')).appendTo(this.parent);
|
||||||
this.result = this.content.find('.result');
|
this.result = this.content.find('.result');
|
||||||
|
|
||||||
this.content.on('click', '.btn-move', function() {
|
this.content.on('click', '.btn-move', function () {
|
||||||
handle_move_add($(this), "Move")
|
handle_move_add($(this), "Move");
|
||||||
});
|
});
|
||||||
|
|
||||||
this.content.on('click', '.btn-add', function() {
|
this.content.on('click', '.btn-add', function () {
|
||||||
handle_move_add($(this), "Add")
|
handle_move_add($(this), "Add");
|
||||||
});
|
});
|
||||||
|
|
||||||
this.content.on('click', '.btn-edit', function() {
|
this.content.on('click', '.btn-edit', function () {
|
||||||
let item = unescape($(this).attr('data-item'));
|
let item = unescape($(this).attr('data-item'));
|
||||||
let warehouse = unescape($(this).attr('data-warehouse'));
|
let warehouse = unescape($(this).attr('data-warehouse'));
|
||||||
let company = unescape($(this).attr('data-company'));
|
let company = unescape($(this).attr('data-company'));
|
||||||
frappe.db.get_value('Putaway Rule',
|
frappe.db.get_value('Putaway Rule', {
|
||||||
{'item_code': item, 'warehouse': warehouse, 'company': company}, 'name', (r) => {
|
'item_code': item,
|
||||||
frappe.set_route("Form", "Putaway Rule", r.name);
|
'warehouse': warehouse,
|
||||||
});
|
'company': company
|
||||||
|
}, 'name', (r) => {
|
||||||
|
frappe.set_route("Form", "Putaway Rule", r.name);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function handle_move_add(element, action) {
|
function handle_move_add(element, action) {
|
||||||
@ -39,23 +42,26 @@ erpnext.stock.ItemDashboard = Class.extend({
|
|||||||
let warehouse = unescape(element.attr('data-warehouse'));
|
let warehouse = unescape(element.attr('data-warehouse'));
|
||||||
let actual_qty = unescape(element.attr('data-actual_qty'));
|
let actual_qty = unescape(element.attr('data-actual_qty'));
|
||||||
let disable_quick_entry = Number(unescape(element.attr('data-disable_quick_entry')));
|
let disable_quick_entry = Number(unescape(element.attr('data-disable_quick_entry')));
|
||||||
let entry_type = action === "Move" ? "Material Transfer": null;
|
let entry_type = action === "Move" ? "Material Transfer" : null;
|
||||||
|
|
||||||
if (disable_quick_entry) {
|
if (disable_quick_entry) {
|
||||||
open_stock_entry(item, warehouse, entry_type);
|
open_stock_entry(item, warehouse, entry_type);
|
||||||
} else {
|
} else {
|
||||||
if (action === "Add") {
|
if (action === "Add") {
|
||||||
let rate = unescape($(this).attr('data-rate'));
|
let rate = unescape($(this).attr('data-rate'));
|
||||||
erpnext.stock.move_item(item, null, warehouse, actual_qty, rate, function() { me.refresh(); });
|
erpnext.stock.move_item(item, null, warehouse, actual_qty, rate, function () {
|
||||||
}
|
me.refresh();
|
||||||
else {
|
});
|
||||||
erpnext.stock.move_item(item, warehouse, null, actual_qty, null, function() { me.refresh(); });
|
} else {
|
||||||
|
erpnext.stock.move_item(item, warehouse, null, actual_qty, null, function () {
|
||||||
|
me.refresh();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function open_stock_entry(item, warehouse, entry_type) {
|
function open_stock_entry(item, warehouse, entry_type) {
|
||||||
frappe.model.with_doctype('Stock Entry', function() {
|
frappe.model.with_doctype('Stock Entry', function () {
|
||||||
var doc = frappe.model.get_new_doc('Stock Entry');
|
var doc = frappe.model.get_new_doc('Stock Entry');
|
||||||
if (entry_type) doc.stock_entry_type = entry_type;
|
if (entry_type) doc.stock_entry_type = entry_type;
|
||||||
|
|
||||||
@ -64,18 +70,18 @@ erpnext.stock.ItemDashboard = Class.extend({
|
|||||||
row.s_warehouse = warehouse;
|
row.s_warehouse = warehouse;
|
||||||
|
|
||||||
frappe.set_route('Form', doc.doctype, doc.name);
|
frappe.set_route('Form', doc.doctype, doc.name);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// more
|
// more
|
||||||
this.content.find('.btn-more').on('click', function() {
|
this.content.find('.btn-more').on('click', function () {
|
||||||
me.start += me.page_length;
|
me.start += me.page_length;
|
||||||
me.refresh();
|
me.refresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
refresh: function() {
|
refresh: function () {
|
||||||
if(this.before_refresh) {
|
if (this.before_refresh) {
|
||||||
this.before_refresh();
|
this.before_refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,13 +100,13 @@ erpnext.stock.ItemDashboard = Class.extend({
|
|||||||
frappe.call({
|
frappe.call({
|
||||||
method: this.method,
|
method: this.method,
|
||||||
args: args,
|
args: args,
|
||||||
callback: function(r) {
|
callback: function (r) {
|
||||||
me.render(r.message);
|
me.render(r.message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
render: function(data) {
|
render: function (data) {
|
||||||
if (this.start===0) {
|
if (this.start === 0) {
|
||||||
this.max_count = 0;
|
this.max_count = 0;
|
||||||
this.result.empty();
|
this.result.empty();
|
||||||
}
|
}
|
||||||
@ -115,7 +121,7 @@ erpnext.stock.ItemDashboard = Class.extend({
|
|||||||
this.max_count = this.max_count;
|
this.max_count = this.max_count;
|
||||||
|
|
||||||
// show more button
|
// show more button
|
||||||
if (data && data.length===(this.page_length + 1)) {
|
if (data && data.length === (this.page_length + 1)) {
|
||||||
this.content.find('.more').removeClass('hidden');
|
this.content.find('.more').removeClass('hidden');
|
||||||
|
|
||||||
// remove the last element
|
// remove the last element
|
||||||
@ -137,15 +143,15 @@ erpnext.stock.ItemDashboard = Class.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
get_item_dashboard_data: function(data, max_count, show_item) {
|
get_item_dashboard_data: function (data, max_count, show_item) {
|
||||||
if(!max_count) max_count = 0;
|
if (!max_count) max_count = 0;
|
||||||
if(!data) data = [];
|
if (!data) data = [];
|
||||||
|
|
||||||
data.forEach(function(d) {
|
data.forEach(function (d) {
|
||||||
d.actual_or_pending = d.projected_qty + d.reserved_qty + d.reserved_qty_for_production + d.reserved_qty_for_sub_contract;
|
d.actual_or_pending = d.projected_qty + d.reserved_qty + d.reserved_qty_for_production + d.reserved_qty_for_sub_contract;
|
||||||
d.pending_qty = 0;
|
d.pending_qty = 0;
|
||||||
d.total_reserved = d.reserved_qty + d.reserved_qty_for_production + d.reserved_qty_for_sub_contract;
|
d.total_reserved = d.reserved_qty + d.reserved_qty_for_production + d.reserved_qty_for_sub_contract;
|
||||||
if(d.actual_or_pending > d.actual_qty) {
|
if (d.actual_or_pending > d.actual_qty) {
|
||||||
d.pending_qty = d.actual_or_pending - d.actual_qty;
|
d.pending_qty = d.actual_or_pending - d.actual_qty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,16 +167,16 @@ erpnext.stock.ItemDashboard = Class.extend({
|
|||||||
return {
|
return {
|
||||||
data: data,
|
data: data,
|
||||||
max_count: max_count,
|
max_count: max_count,
|
||||||
can_write:can_write,
|
can_write: can_write,
|
||||||
show_item: show_item || false
|
show_item: show_item || false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
get_capacity_dashboard_data: function(data) {
|
get_capacity_dashboard_data: function (data) {
|
||||||
if (!data) data = [];
|
if (!data) data = [];
|
||||||
|
|
||||||
data.forEach(function(d) {
|
data.forEach(function (d) {
|
||||||
d.color = d.percent_occupied >=80 ? "#f8814f" : "#2490ef";
|
d.color = d.percent_occupied >= 80 ? "#f8814f" : "#2490ef";
|
||||||
});
|
});
|
||||||
|
|
||||||
let can_write = 0;
|
let can_write = 0;
|
||||||
@ -185,53 +191,77 @@ erpnext.stock.ItemDashboard = Class.extend({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
erpnext.stock.move_item = function(item, source, target, actual_qty, rate, callback) {
|
erpnext.stock.move_item = function (item, source, target, actual_qty, rate, callback) {
|
||||||
var dialog = new frappe.ui.Dialog({
|
var dialog = new frappe.ui.Dialog({
|
||||||
title: target ? __('Add Item') : __('Move Item'),
|
title: target ? __('Add Item') : __('Move Item'),
|
||||||
fields: [
|
fields: [{
|
||||||
{fieldname: 'item_code', label: __('Item'),
|
fieldname: 'item_code',
|
||||||
fieldtype: 'Link', options: 'Item', read_only: 1},
|
label: __('Item'),
|
||||||
{fieldname: 'source', label: __('Source Warehouse'),
|
fieldtype: 'Link',
|
||||||
fieldtype: 'Link', options: 'Warehouse', read_only: 1},
|
options: 'Item',
|
||||||
{fieldname: 'target', label: __('Target Warehouse'),
|
read_only: 1
|
||||||
fieldtype: 'Link', options: 'Warehouse', reqd: 1},
|
},
|
||||||
{fieldname: 'qty', label: __('Quantity'), reqd: 1,
|
{
|
||||||
fieldtype: 'Float', description: __('Available {0}', [actual_qty]) },
|
fieldname: 'source',
|
||||||
{fieldname: 'rate', label: __('Rate'), fieldtype: 'Currency', hidden: 1 },
|
label: __('Source Warehouse'),
|
||||||
|
fieldtype: 'Link',
|
||||||
|
options: 'Warehouse',
|
||||||
|
read_only: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname: 'target',
|
||||||
|
label: __('Target Warehouse'),
|
||||||
|
fieldtype: 'Link',
|
||||||
|
options: 'Warehouse',
|
||||||
|
reqd: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname: 'qty',
|
||||||
|
label: __('Quantity'),
|
||||||
|
reqd: 1,
|
||||||
|
fieldtype: 'Float',
|
||||||
|
description: __('Available {0}', [actual_qty])
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname: 'rate',
|
||||||
|
label: __('Rate'),
|
||||||
|
fieldtype: 'Currency',
|
||||||
|
hidden: 1
|
||||||
|
},
|
||||||
],
|
],
|
||||||
})
|
});
|
||||||
dialog.show();
|
dialog.show();
|
||||||
dialog.get_field('item_code').set_input(item);
|
dialog.get_field('item_code').set_input(item);
|
||||||
|
|
||||||
if(source) {
|
if (source) {
|
||||||
dialog.get_field('source').set_input(source);
|
dialog.get_field('source').set_input(source);
|
||||||
} else {
|
} else {
|
||||||
dialog.get_field('source').df.hidden = 1;
|
dialog.get_field('source').df.hidden = 1;
|
||||||
dialog.get_field('source').refresh();
|
dialog.get_field('source').refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(rate) {
|
if (rate) {
|
||||||
dialog.get_field('rate').set_value(rate);
|
dialog.get_field('rate').set_value(rate);
|
||||||
dialog.get_field('rate').df.hidden = 0;
|
dialog.get_field('rate').df.hidden = 0;
|
||||||
dialog.get_field('rate').refresh();
|
dialog.get_field('rate').refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(target) {
|
if (target) {
|
||||||
dialog.get_field('target').df.read_only = 1;
|
dialog.get_field('target').df.read_only = 1;
|
||||||
dialog.get_field('target').value = target;
|
dialog.get_field('target').value = target;
|
||||||
dialog.get_field('target').refresh();
|
dialog.get_field('target').refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.set_primary_action(__('Submit'), function() {
|
dialog.set_primary_action(__('Submit'), function () {
|
||||||
var values = dialog.get_values();
|
var values = dialog.get_values();
|
||||||
if(!values) {
|
if (!values) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(source && values.qty > actual_qty) {
|
if (source && values.qty > actual_qty) {
|
||||||
frappe.msgprint(__('Quantity must be less than or equal to {0}', [actual_qty]));
|
frappe.msgprint(__('Quantity must be less than or equal to {0}', [actual_qty]));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(values.source === values.target) {
|
if (values.source === values.target) {
|
||||||
frappe.msgprint(__('Source and target warehouse must be different'));
|
frappe.msgprint(__('Source and target warehouse must be different'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,21 +269,21 @@ erpnext.stock.move_item = function(item, source, target, actual_qty, rate, callb
|
|||||||
method: 'erpnext.stock.doctype.stock_entry.stock_entry_utils.make_stock_entry',
|
method: 'erpnext.stock.doctype.stock_entry.stock_entry_utils.make_stock_entry',
|
||||||
args: values,
|
args: values,
|
||||||
freeze: true,
|
freeze: true,
|
||||||
callback: function(r) {
|
callback: function (r) {
|
||||||
frappe.show_alert(__('Stock Entry {0} created',
|
frappe.show_alert(__('Stock Entry {0} created',
|
||||||
['<a href="/app/stock-entry/'+r.message.name+'">' + r.message.name+ '</a>']));
|
['<a href="/app/stock-entry/' + r.message.name + '">' + r.message.name + '</a>']));
|
||||||
dialog.hide();
|
dialog.hide();
|
||||||
callback(r);
|
callback(r);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$('<p style="margin-left: 10px;"><a class="link-open text-muted small">'
|
$('<p style="margin-left: 10px;"><a class="link-open text-muted small">' +
|
||||||
+ __("Add more items or open full form") + '</a></p>')
|
__("Add more items or open full form") + '</a></p>')
|
||||||
.appendTo(dialog.body)
|
.appendTo(dialog.body)
|
||||||
.find('.link-open')
|
.find('.link-open')
|
||||||
.on('click', function() {
|
.on('click', function () {
|
||||||
frappe.model.with_doctype('Stock Entry', function() {
|
frappe.model.with_doctype('Stock Entry', function () {
|
||||||
var doc = frappe.model.get_new_doc('Stock Entry');
|
var doc = frappe.model.get_new_doc('Stock Entry');
|
||||||
doc.from_warehouse = dialog.get_value('source');
|
doc.from_warehouse = dialog.get_value('source');
|
||||||
doc.to_warehouse = dialog.get_value('target');
|
doc.to_warehouse = dialog.get_value('target');
|
||||||
@ -266,6 +296,6 @@ erpnext.stock.move_item = function(item, source, target, actual_qty, rate, callb
|
|||||||
row.transfer_qty = dialog.get_value('qty');
|
row.transfer_qty = dialog.get_value('qty');
|
||||||
row.basic_rate = dialog.get_value('rate');
|
row.basic_rate = dialog.get_value('rate');
|
||||||
frappe.set_route('Form', doc.doctype, doc.name);
|
frappe.set_route('Form', doc.doctype, doc.name);
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
@ -2,6 +2,7 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.model.db_query import DatabaseQuery
|
from frappe.model.db_query import DatabaseQuery
|
||||||
|
from frappe.utils import flt, cint
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_data(item_code=None, warehouse=None, item_group=None,
|
def get_data(item_code=None, warehouse=None, item_group=None,
|
||||||
@ -42,11 +43,20 @@ def get_data(item_code=None, warehouse=None, item_group=None,
|
|||||||
limit_start=start,
|
limit_start=start,
|
||||||
limit_page_length='21')
|
limit_page_length='21')
|
||||||
|
|
||||||
|
precision = cint(frappe.db.get_single_value("System Settings", "float_precision"))
|
||||||
|
|
||||||
for item in items:
|
for item in items:
|
||||||
item.update({
|
item.update({
|
||||||
'item_name': frappe.get_cached_value("Item", item.item_code, 'item_name'),
|
'item_name': frappe.get_cached_value(
|
||||||
'disable_quick_entry': frappe.get_cached_value("Item", item.item_code, 'has_batch_no')
|
"Item", item.item_code, 'item_name'),
|
||||||
or frappe.get_cached_value("Item", item.item_code, 'has_serial_no'),
|
'disable_quick_entry': frappe.get_cached_value(
|
||||||
|
"Item", item.item_code, 'has_batch_no')
|
||||||
|
or frappe.get_cached_value(
|
||||||
|
"Item", item.item_code, 'has_serial_no'),
|
||||||
|
'projected_qty': flt(item.projected_qty, precision),
|
||||||
|
'reserved_qty': flt(item.reserved_qty, precision),
|
||||||
|
'reserved_qty_for_production': flt(item.reserved_qty_for_production, precision),
|
||||||
|
'reserved_qty_for_sub_contract': flt(item.reserved_qty_for_sub_contract, precision),
|
||||||
|
'actual_qty': flt(item.actual_qty, precision),
|
||||||
})
|
})
|
||||||
|
|
||||||
return items
|
return items
|
||||||
|
Loading…
x
Reference in New Issue
Block a user