diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js index 1cb68a6cda..0c6bcad721 100644 --- a/erpnext/public/js/controllers/buying.js +++ b/erpnext/public/js/controllers/buying.js @@ -516,27 +516,4 @@ erpnext.buying.get_items_from_product_bundle = function(frm) { }); dialog.show(); -} - -erpnext.apply_putaway_rule = (frm) => { - if (!frm.doc.company) { - frappe.throw({message:__("Please select a Company first."), title: __("Mandatory")}) - } - if (!frm.doc.items.length) return; - - frappe.call({ - method: "erpnext.stock.doctype.putaway_rule.putaway_rule.apply_putaway_rule", - args: { - items: frm.doc.items, - company: frm.doc.company - }, - callback: (result) => { - if(!result.exc) { - if(result.message) { - frm.doc.items = result.message; - frm.get_field("items").refresh(); - } - } - } - }); } \ No newline at end of file diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 7f08cd1359..31efb6aa34 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -2029,3 +2029,33 @@ erpnext.show_serial_batch_selector = function (frm, d, callback, on_close, show_ }, show_dialog); }); } + +erpnext.apply_putaway_rule = (frm) => { + if (!frm.doc.company) { + frappe.throw({message: __("Please select a Company first."), title: __("Mandatory")}); + } + if (!frm.doc.items.length) return; + + frappe.call({ + method: "erpnext.stock.doctype.putaway_rule.putaway_rule.apply_putaway_rule", + args: { + doctype: frm.doctype, + items: frm.doc.items, + company: frm.doc.company, + sync: true + }, + callback: (result) => { + if (!result.exc && result.message) { + frm.clear_table("items"); + + let items = result.message; + items.forEach((row) => { + delete row["name"]; + let child = frm.add_child("items"); + Object.assign(child, row); + }); + frm.get_field("items").grid.refresh(); + } + } + }); +}; \ No newline at end of file diff --git a/erpnext/stock/dashboard/item_dashboard.js b/erpnext/stock/dashboard/item_dashboard.js index abc286fcc6..070589b3dc 100644 --- a/erpnext/stock/dashboard/item_dashboard.js +++ b/erpnext/stock/dashboard/item_dashboard.js @@ -30,8 +30,8 @@ erpnext.stock.ItemDashboard = Class.extend({ let company = unescape($(this).attr('data-company')); frappe.db.get_value('Putaway Rule', {'item_code': item, 'warehouse': warehouse, 'company': company}, 'name', (r) => { - frappe.set_route("Form", "Putaway Rule", r.name); - }); + frappe.set_route("Form", "Putaway Rule", r.name); + }); }); function handle_move_add(element, action) { @@ -88,7 +88,7 @@ erpnext.stock.ItemDashboard = Class.extend({ start: this.start, sort_by: this.sort_by, sort_order: this.sort_order - } + }; var me = this; frappe.call({ @@ -104,10 +104,12 @@ erpnext.stock.ItemDashboard = Class.extend({ this.max_count = 0; this.result.empty(); } + + let context = ""; if (this.page_name === "warehouse-capacity-summary") { - var context = this.get_capacity_dashboard_data(data); + context = this.get_capacity_dashboard_data(data); } else { - var context = this.get_item_dashboard_data(data, this.max_count, true); + context = this.get_item_dashboard_data(data, this.max_count, true); } this.max_count = this.max_count; @@ -152,7 +154,7 @@ erpnext.stock.ItemDashboard = Class.extend({ }); let can_write = 0; - if(frappe.boot.user.can_write.indexOf("Stock Entry")>=0){ + if (frappe.boot.user.can_write.indexOf("Stock Entry") >= 0) { can_write = 1; } @@ -165,23 +167,23 @@ erpnext.stock.ItemDashboard = Class.extend({ }, get_capacity_dashboard_data: function(data) { - if(!data) data = []; + if (!data) data = []; data.forEach(function(d) { d.color = d.percent_occupied >=80 ? "#f8814f" : "#2490ef"; }); let can_write = 0; - if(frappe.boot.user.can_write.indexOf("Putaway Rule")>=0){ + if (frappe.boot.user.can_write.indexOf("Putaway Rule") >= 0) { can_write = 1; } return { data: data, can_write: can_write, - } + }; } -}) +}); erpnext.stock.move_item = function(item, source, target, actual_qty, rate, callback) { var dialog = new frappe.ui.Dialog({ diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js index 45eb646d4b..218fb9e121 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js @@ -214,7 +214,7 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend }, apply_putaway_rule: function() { - // if (this.frm.doc.apply_putaway_rule) erpnext.apply_putaway_rule(this.frm); + if (this.frm.doc.apply_putaway_rule) erpnext.apply_putaway_rule(this.frm); } }); diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index b1ad6103d3..4372bdcc59 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -87,7 +87,7 @@ class PurchaseReceipt(BuyingController): from erpnext.stock.doctype.putaway_rule.putaway_rule import apply_putaway_rule if self.get("items") and self.apply_putaway_rule: - self.items = apply_putaway_rule(self.doctype, self.get("items"), self.company) + apply_putaway_rule(self.doctype, self.get("items"), self.company) def validate(self): self.validate_posting_time() diff --git a/erpnext/stock/doctype/putaway_rule/putaway_rule.py b/erpnext/stock/doctype/putaway_rule/putaway_rule.py index 8838bb75f1..4ed4dafac7 100644 --- a/erpnext/stock/doctype/putaway_rule/putaway_rule.py +++ b/erpnext/stock/doctype/putaway_rule/putaway_rule.py @@ -64,7 +64,7 @@ def get_putaway_capacity(rule): return free_space if free_space > 0 else 0 @frappe.whitelist() -def apply_putaway_rule(doctype, items, company): +def apply_putaway_rule(doctype, items, company, sync=None): """ Applies Putaway Rule on line items. items: List of Purchase Receipt Item objects @@ -82,7 +82,7 @@ def apply_putaway_rule(doctype, items, company): source_warehouse = item.get("s_warehouse") serial_nos = get_serial_nos(item.get("serial_no")) - conversion = flt(item.conversion_factor) or 1 + item.conversion_factor = flt(item.conversion_factor) or 1 pending_qty, item_code = flt(item.qty), item.item_code pending_stock_qty = flt(item.transfer_qty) if doctype == "Stock Entry" else flt(item.stock_qty) if not pending_qty or not item_code: @@ -109,11 +109,11 @@ def apply_putaway_rule(doctype, items, company): for rule in item_wise_rules[item_code]: if pending_stock_qty > 0 and rule.free_space: stock_qty_to_allocate = flt(rule.free_space) if pending_stock_qty >= flt(rule.free_space) else pending_stock_qty - qty_to_allocate = stock_qty_to_allocate / (conversion) + qty_to_allocate = stock_qty_to_allocate / item.conversion_factor if uom_must_be_whole_number: qty_to_allocate = floor(qty_to_allocate) - stock_qty_to_allocate = qty_to_allocate * conversion + stock_qty_to_allocate = qty_to_allocate * item.conversion_factor if not qty_to_allocate: break @@ -124,17 +124,19 @@ def apply_putaway_rule(doctype, items, company): pending_qty -= qty_to_allocate rule["free_space"] -= stock_qty_to_allocate - if not pending_stock_qty: break + if not pending_stock_qty > 0: break # if pending qty after applying all rules, add row without warehouse if pending_stock_qty > 0: - # updated_table = add_row(item, pending_qty, '', updated_table, serial_nos=serial_nos) items_not_accomodated.append([item.item_code, pending_qty]) if items_not_accomodated: show_unassigned_items_message(items_not_accomodated) - return updated_table if updated_table else items + items[:] = updated_table if updated_table else items # modify items table + + if sync and json.loads(sync): # sync with client side + return items def get_ordered_putaway_rules(item_code, company, source_warehouse=None): """Returns an ordered list of putaway rules to apply on an item.""" @@ -174,12 +176,14 @@ def get_ordered_putaway_rules(item_code, company, source_warehouse=None): def add_row(item, to_allocate, warehouse, updated_table, rule=None, serial_nos=None): new_updated_table_row = copy.deepcopy(item) new_updated_table_row.idx = 1 if not updated_table else cint(updated_table[-1].idx) + 1 - new_updated_table_row.name = "New " + str(item.doctype) + " " + str(new_updated_table_row.idx) + new_updated_table_row.name = None new_updated_table_row.qty = to_allocate - new_updated_table_row.stock_qty = flt(to_allocate) * flt(new_updated_table_row.conversion_factor) + if item.doctype == "Stock Entry Detail": new_updated_table_row.t_warehouse = warehouse + new_updated_table_row.transfer_qty = flt(to_allocate) * flt(new_updated_table_row.conversion_factor) else: + new_updated_table_row.stock_qty = flt(to_allocate) * flt(new_updated_table_row.conversion_factor) new_updated_table_row.warehouse = warehouse new_updated_table_row.rejected_qty = 0 new_updated_table_row.received_qty = to_allocate diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index 2be70f37f2..fd920a585a 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -573,10 +573,10 @@ frappe.ui.form.on('Stock Entry', { } }, - apply_putaway_rule: function(frm) { - // if (frm.doc.apply_putaway_rule) erpnext.apply_putaway_rule(frm); + apply_putaway_rule: function (frm) { + if (frm.doc.apply_putaway_rule) erpnext.apply_putaway_rule(frm); } -}) +}); frappe.ui.form.on('Stock Entry Detail', { qty: function(frm, cdt, cdn) { diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index aa3425cbd8..f07039f564 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -47,7 +47,7 @@ class StockEntry(StockController): apply_rule = self.apply_putaway_rule and (self.purpose in ["Material Transfer", "Material Receipt"]) if self.get("items") and apply_rule: - self.items = apply_putaway_rule(self.doctype, self.get("items"), self.company) + apply_putaway_rule(self.doctype, self.get("items"), self.company) def validate(self): self.pro_doc = frappe._dict() diff --git a/erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary.js b/erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary.js index c3b3b5d8ec..b610e7dd58 100644 --- a/erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary.js +++ b/erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary.js @@ -10,8 +10,8 @@ frappe.pages['warehouse-capacity-summary'].on_page_load = function(wrapper) { page.company_field = page.add_field({ fieldname: 'company', label: __('Company'), - fieldtype:'Link', - options:'Company', + fieldtype: 'Link', + options: 'Company', reqd: 1, default: frappe.defaults.get_default("company"), change: function() { @@ -23,8 +23,8 @@ frappe.pages['warehouse-capacity-summary'].on_page_load = function(wrapper) { page.warehouse_field = page.add_field({ fieldname: 'warehouse', label: __('Warehouse'), - fieldtype:'Link', - options:'Warehouse', + fieldtype: 'Link', + options: 'Warehouse', change: function() { page.capacity_dashboard.start = 0; page.capacity_dashboard.refresh(); @@ -34,8 +34,8 @@ frappe.pages['warehouse-capacity-summary'].on_page_load = function(wrapper) { page.item_field = page.add_field({ fieldname: 'item_code', label: __('Item'), - fieldtype:'Link', - options:'Item', + fieldtype: 'Link', + options: 'Item', change: function() { page.capacity_dashboard.start = 0; page.capacity_dashboard.refresh(); @@ -45,8 +45,8 @@ frappe.pages['warehouse-capacity-summary'].on_page_load = function(wrapper) { page.parent_warehouse_field = page.add_field({ fieldname: 'parent_warehouse', label: __('Parent Warehouse'), - fieldtype:'Link', - options:'Warehouse', + fieldtype: 'Link', + options: 'Warehouse', get_query: function() { return { filters: { @@ -67,8 +67,8 @@ frappe.pages['warehouse-capacity-summary'].on_page_load = function(wrapper) { sort_order: 'desc', options: [ {fieldname: 'stock_capacity', label: __('Capacity (Stock UOM)')}, - {fieldname: 'percent_occupied', label:__('% Occupied')}, - {fieldname: 'actual_qty', label:__('Balance Qty (Stock ')} + {fieldname: 'percent_occupied', label: __('% Occupied')}, + {fieldname: 'actual_qty', label: __('Balance Qty (Stock ')} ] }, change: function(sort_by, sort_order) { @@ -90,14 +90,14 @@ frappe.pages['warehouse-capacity-summary'].on_page_load = function(wrapper) { sort_order: 'desc', method: 'erpnext.stock.dashboard.warehouse_capacity_dashboard.get_data', template: 'warehouse_capacity_summary' - }) + }); page.capacity_dashboard.before_refresh = function() { this.item_code = page.item_field.get_value(); this.warehouse = page.warehouse_field.get_value(); this.parent_warehouse = page.parent_warehouse_field.get_value(); this.company = page.company_field.get_value(); - } + }; page.capacity_dashboard.refresh(); @@ -105,16 +105,16 @@ frappe.pages['warehouse-capacity-summary'].on_page_load = function(wrapper) { page.main.on('click', 'a[data-type="'+ doctype.toLowerCase() +'"]', function() { var name = $(this).attr('data-name'); var field = page[doctype.toLowerCase() + '_field']; - if(field.get_value()===name) { - frappe.set_route('Form', doctype, name) + if (field.get_value()===name) { + frappe.set_route('Form', doctype, name); } else { field.set_input(name); page.capacity_dashboard.refresh(); } }); - } + }; setup_click('Item'); setup_click('Warehouse'); }); -} \ No newline at end of file +}; \ No newline at end of file