feat: add pending qty section to batch/serial selector dialog (#25519)

* feat: add pending qty section to batch/serial selector dialog

* fix: call attach in setup and refresh, fix conditional

* refactor: camel to snake casing
This commit is contained in:
Alan 2021-05-14 12:36:41 +05:30 committed by GitHub
parent 2aa401826e
commit 55c2fec683
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 96 additions and 1 deletions

View File

@ -74,9 +74,10 @@ erpnext.SerialNoBatchSelector = Class.extend({
fieldname: 'qty',
fieldtype:'Float',
read_only: me.has_batch && !me.has_serial_no,
label: __(me.has_batch && !me.has_serial_no ? 'Total Qty' : 'Qty'),
label: __(me.has_batch && !me.has_serial_no ? 'Selected Qty' : 'Qty'),
default: flt(me.item.stock_qty),
},
...get_pending_qty_fields(me),
{
fieldname: 'uom',
read_only: 1,
@ -181,6 +182,7 @@ erpnext.SerialNoBatchSelector = Class.extend({
if (this.has_batch && !this.has_serial_no) {
this.update_total_qty();
this.update_pending_qtys();
}
this.dialog.show();
@ -321,7 +323,21 @@ erpnext.SerialNoBatchSelector = Class.extend({
qty_field.set_input(total_qty);
},
update_pending_qtys: function() {
const pending_qty_field = this.dialog.fields_dict.pending_qty;
const total_selected_qty_field = this.dialog.fields_dict.total_selected_qty;
if (!pending_qty_field || !total_selected_qty_field) return;
const me = this;
const required_qty = this.dialog.fields_dict.required_qty.value;
const selected_qty = this.dialog.fields_dict.qty.value;
const total_selected_qty = selected_qty + calc_total_selected_qty(me);
const pending_qty = required_qty - total_selected_qty;
pending_qty_field.set_input(pending_qty);
total_selected_qty_field.set_input(total_selected_qty);
},
get_batch_fields: function() {
var me = this;
@ -423,6 +439,7 @@ erpnext.SerialNoBatchSelector = Class.extend({
}
me.update_total_qty();
me.update_pending_qtys();
}
},
],
@ -519,3 +536,60 @@ erpnext.SerialNoBatchSelector = Class.extend({
];
}
});
function get_pending_qty_fields(me) {
if (!check_can_calculate_pending_qty(me)) return [];
const { frm: { doc: { fg_completed_qty }}, item: { item_code, stock_qty }} = me;
const { qty_consumed_per_unit } = erpnext.stock.bom.items[item_code];
const total_selected_qty = calc_total_selected_qty(me);
const required_qty = flt(fg_completed_qty) * flt(qty_consumed_per_unit);
const pending_qty = required_qty - (flt(stock_qty) + total_selected_qty);
const pending_qty_fields = [
{ fieldtype: 'Section Break', label: __('Pending Quantity') },
{
fieldname: 'required_qty',
read_only: 1,
fieldtype: 'Float',
label: __('Required Qty'),
default: required_qty
},
{ fieldtype: 'Column Break' },
{
fieldname: 'total_selected_qty',
read_only: 1,
fieldtype: 'Float',
label: __('Total Selected Qty'),
default: total_selected_qty
},
{ fieldtype: 'Column Break' },
{
fieldname: 'pending_qty',
read_only: 1,
fieldtype: 'Float',
label: __('Pending Qty'),
default: pending_qty
},
];
return pending_qty_fields;
}
function calc_total_selected_qty(me) {
const { frm: { doc: { items }}, item: { name, item_code }} = me;
const totalSelectedQty = items
.filter( item => ( item.name !== name ) && ( item.item_code === item_code ) )
.map( item => flt(item.qty) )
.reduce( (i, j) => i + j, 0);
return totalSelectedQty;
}
function check_can_calculate_pending_qty(me) {
const { frm: { doc }, item } = me;
const docChecks = doc.bom_no
&& doc.fg_completed_qty
&& erpnext.stock.bom
&& erpnext.stock.bom.name === doc.bom_no;
const itemChecks = !!item;
return docChecks && itemChecks;
}

View File

@ -107,6 +107,7 @@ frappe.ui.form.on('Stock Entry', {
frappe.flags.hide_serial_batch_dialog = true;
}
});
attach_bom_items(frm.doc.bom_no);
},
setup_quality_inspection: function(frm) {
@ -311,6 +312,7 @@ frappe.ui.form.on('Stock Entry', {
}
frm.trigger("setup_quality_inspection");
attach_bom_items(frm.doc.bom_no)
},
stock_entry_type: function(frm){
@ -919,6 +921,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
method: "get_items",
callback: function(r) {
if(!r.exc) refresh_field("items");
if(me.frm.doc.bom_no) attach_bom_items(me.frm.doc.bom_no)
}
});
}
@ -1064,4 +1067,22 @@ erpnext.stock.select_batch_and_serial_no = (frm, item) => {
}
function attach_bom_items(bom_no) {
if (check_should_not_attach_bom_items(bom_no)) return
frappe.db.get_doc("BOM",bom_no).then(bom => {
const {name, items} = bom
erpnext.stock.bom = {name, items:{}}
items.forEach(item => {
erpnext.stock.bom.items[item.item_code] = item;
});
});
}
function check_should_not_attach_bom_items(bom_no) {
return (
bom_no === undefined ||
(erpnext.stock.bom && erpnext.stock.bom.name === bom_no)
);
}
$.extend(cur_frm.cscript, new erpnext.stock.StockEntry({frm: cur_frm}));