major(manufacturing): fixes to ux, material requests to purchase order based on default supplier etc (#15267)

* major(manufacturing): fixes to ux, material requests to purchase order based on default supplier etc

* fix: remove debug
This commit is contained in:
Rushabh Mehta 2018-08-30 18:50:48 +05:30 committed by Nabin Hait
parent f6b784e39e
commit 49f9747385
13 changed files with 298 additions and 273 deletions

View File

@ -497,15 +497,15 @@ cur_frm.fields_dict["items"].grid.get_field("cost_center").get_query = function(
}
cur_frm.cscript.income_account = function(doc, cdt, cdn) {
erpnext.utils.copy_value_in_all_row(doc, cdt, cdn, "items", "income_account");
erpnext.utils.copy_value_in_all_rows(doc, cdt, cdn, "items", "income_account");
}
cur_frm.cscript.expense_account = function(doc, cdt, cdn) {
erpnext.utils.copy_value_in_all_row(doc, cdt, cdn, "items", "expense_account");
erpnext.utils.copy_value_in_all_rows(doc, cdt, cdn, "items", "expense_account");
}
cur_frm.cscript.cost_center = function(doc, cdt, cdn) {
erpnext.utils.copy_value_in_all_row(doc, cdt, cdn, "items", "cost_center");
erpnext.utils.copy_value_in_all_rows(doc, cdt, cdn, "items", "cost_center");
}
cur_frm.set_query("debit_to", function(doc) {

View File

@ -64,7 +64,7 @@ frappe.ui.form.on("Purchase Order Item", {
var row = locals[cdt][cdn];
if (row.schedule_date) {
if(!frm.doc.schedule_date) {
erpnext.utils.copy_value_in_all_row(frm.doc, cdt, cdn, "items", "schedule_date");
erpnext.utils.copy_value_in_all_rows(frm.doc, cdt, cdn, "items", "schedule_date");
} else {
set_schedule_date(frm);
}
@ -309,6 +309,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
method: "erpnext.stock.doctype.material_request.material_request.make_purchase_order",
source_doctype: "Material Request",
target: me.frm,
args: args,
setters: {
company: me.frm.doc.company
},
@ -319,7 +320,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
per_ordered: ["<", 99.99],
}
})
}, __("Add items from"));
}, __("Get items from"));
this.frm.add_custom_button(__('Supplier Quotation'),
function() {
@ -335,7 +336,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
status: ["!=", "Stopped"],
}
})
}, __("Add items from"));
}, __("Get items from"));
this.frm.add_custom_button(__('Update rate as per last purchase'),
function() {
@ -364,7 +365,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
},
callback: function(r) {
if(r.exc) return;
var i = 0;
var item_length = me.frm.doc.items.length;
while (i < item_length) {
@ -379,17 +380,17 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
d.qty = d.qty - my_qty;
me.frm.doc.items[i].stock_qty = my_qty * me.frm.doc.items[i].conversion_factor;
me.frm.doc.items[i].qty = my_qty;
frappe.msgprint("Assigning " + d.mr_name + " to " + d.item_code + " (row " + me.frm.doc.items[i].idx + ")");
if (qty > 0) {
frappe.msgprint("Splitting " + qty + " units of " + d.item_code);
var new_row = frappe.model.add_child(me.frm.doc, me.frm.doc.items[i].doctype, "items");
item_length++;
for (var key in me.frm.doc.items[i]) {
new_row[key] = me.frm.doc.items[i][key];
}
new_row.idx = item_length;
new_row["stock_qty"] = new_row.conversion_factor * qty;
new_row["qty"] = qty;
@ -477,7 +478,7 @@ cur_frm.fields_dict['items'].grid.get_field('bom').get_query = function(doc, cdt
function set_schedule_date(frm) {
if(frm.doc.schedule_date){
erpnext.utils.copy_value_in_all_row(frm.doc, frm.doc.doctype, frm.doc.name, "items", "schedule_date");
erpnext.utils.copy_value_in_all_rows(frm.doc, frm.doc.doctype, frm.doc.name, "items", "schedule_date");
}
}

View File

@ -173,7 +173,7 @@ class BOM(WebsiteGenerator):
if not rate:
frappe.msgprint(_("{0} not found for Item {1}")
.format(self.rm_cost_as_per, arg["item_code"]))
.format(self.rm_cost_as_per, arg["item_code"]), alert=True)
return flt(rate)
@ -561,7 +561,6 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite
where
bom_item.docstatus < 2
and bom.name = %(bom)s
and is_stock_item = 1
{where_conditions}
group by item_code, stock_uom
order by idx"""

View File

@ -280,7 +280,7 @@ class ProductionPlan(Document):
item_dict[(d.item_code, d.sales_order, d.warehouse)] = item_details
return item_dict
def get_items_for_material_requests(self):
self.mr_items = []
@ -295,15 +295,15 @@ class ProductionPlan(Document):
bei.description, bei.stock_uom, item.min_order_qty, bei.source_warehouse,
item.default_material_request_type, item.min_order_qty, item_default.default_warehouse
from
`tabBOM Explosion Item` bei
`tabBOM Explosion Item` bei
JOIN `tabBOM` bom ON bom.name = bei.parent
JOIN `tabItem` item ON item.name = bei.item_code
LEFT JOIN `tabItem Default` item_default
ON item_default.parent = item.name and item_default.company=%s
where
bei.docstatus < 2
bei.docstatus < 2
and bom.name=%s and item.is_stock_item in (1, {0})
group by bei.item_code, bei.stock_uom""".format(self.include_non_stock_items),
group by bei.item_code, bei.stock_uom""".format(0 if self.include_non_stock_items else 1),
(self.company, data.bom_no), as_dict=1):
bom_wise_item_details.setdefault(d.item_code, d)
else:
@ -332,7 +332,7 @@ class ProductionPlan(Document):
bom.name = %(bom)s
and bom_item.docstatus < 2
and item.is_stock_item in (1, {0})
group by bom_item.item_code""".format(self.include_non_stock_items),{
group by bom_item.item_code""".format(0 if self.include_non_stock_items else 1),{
'bom': bom_no,
'parent_qty': parent_qty,
'company': self.company
@ -412,61 +412,60 @@ class ProductionPlan(Document):
pass
def make_material_request(self):
'''Create Material Requests grouped by Sales Order and Material Request Type'''
material_request_list = []
material_request_map = {}
item_details = self.get_itemwise_qty()
for item_code, rows in item_details.items():
item_doc = frappe.get_doc("Item", item_code)
for item in self.mr_items:
item_doc = frappe.get_cached_doc('Item', item.item_code)
# key for Sales Order:Material Request Type
key = '{}:{}'.format(item.sales_order, item_doc.default_material_request_type)
schedule_date = add_days(nowdate(), cint(item_doc.lead_time_days))
material_request = frappe.new_doc("Material Request")
material_request.update({
"transaction_date": nowdate(),
"status": "Draft",
"company": self.company,
"requested_by": frappe.session.user,
if not key in material_request_map:
# make a new MR for the combination
material_request_map[key] = frappe.new_doc("Material Request")
material_request = material_request_map[key]
material_request.update({
"transaction_date": nowdate(),
"status": "Draft",
"company": self.company,
"requested_by": frappe.session.user,
'material_request_type': item_doc.default_material_request_type
})
material_request_list.append(material_request)
else:
material_request = material_request_map[key]
# add item
material_request.append("items", {
"item_code": item.item_code,
"qty": item.quantity,
"schedule_date": schedule_date,
'material_request_type': item_doc.default_material_request_type
"warehouse": item.warehouse,
"sales_order": item.sales_order,
'production_plan': self.name,
'material_request_plan_item': item.name,
"project": frappe.db.get_value("Sales Order", item.sales_order, "project") \
if item.sales_order else None
})
for idx in rows:
child = self.mr_items[cint(idx)-1]
material_request.append("items", {
"item_code": item_code,
"qty": child.quantity,
"schedule_date": schedule_date,
"warehouse": child.warehouse,
"sales_order": child.sales_order,
'production_plan': self.name,
'material_request_plan_item': child.name,
"project": frappe.db.get_value("Sales Order", child.sales_order, "project") \
if child.sales_order else None
})
for material_request in material_request_list:
# submit
material_request.flags.ignore_permissions = 1
material_request.run_method("set_missing_values")
material_request.submit()
material_request_list.append(material_request.name)
frappe.flags.mute_messages = False
if material_request_list:
material_request_list = ["""<a href="#Form/Material Request/%s" target="_blank">%s</a>""" % \
(p, p) for p in material_request_list]
material_request_list = ["""<a href="#Form/Material Request/{0}">{1}</a>""".format(m.name, m.name) \
for m in material_request_list]
msgprint(_("{0} created").format(comma_and(material_request_list)))
else :
msgprint(_("No material request created"))
def get_itemwise_qty(self):
item_details = {}
for data in self.get('mr_items'):
if data.item_code in item_details:
item_details[data.item_code].append(data.idx)
else:
item_details.setdefault(data.item_code, [data.idx])
return item_details
def get_sales_orders(self):
so_filter = item_filter = ""
if self.from_date:
@ -516,7 +515,7 @@ def get_bin_details(row):
conditions = " and warehouse='{0}'".format(frappe.db.escape(warehouse))
item_projected_qty = frappe.db.sql(""" select ifnull(sum(projected_qty),0) as projected_qty,
ifnull(sum(actual_qty),0) as actual_qty from `tabBin`
ifnull(sum(actual_qty),0) as actual_qty from `tabBin`
where item_code = %(item_code)s {conditions}
""".format(conditions=conditions), { "item_code": row.item_code }, as_list=1)

View File

@ -118,7 +118,7 @@ $.extend(erpnext.utils, {
return dict[party_type];
},
copy_value_in_all_row: function(doc, dt, dn, table_fieldname, fieldname) {
copy_value_in_all_rows: function(doc, dt, dn, table_fieldname, fieldname) {
var d = locals[dt][dn];
if(d[fieldname]){
var cl = doc[table_fieldname] || [];
@ -487,6 +487,7 @@ erpnext.utils.map_current_doc = function(opts) {
"method": opts.method,
"source_names": opts.source_name,
"target_doc": cur_frm.doc,
'args': opts.args
},
callback: function(r) {
if(!r.exc) {

View File

@ -82,7 +82,7 @@ frappe.ui.form.on("Sales Order Item", {
},
delivery_date: function(frm, cdt, cdn) {
if(!frm.doc.delivery_date) {
erpnext.utils.copy_value_in_all_row(frm.doc, cdt, cdn, "items", "delivery_date");
erpnext.utils.copy_value_in_all_rows(frm.doc, cdt, cdn, "items", "delivery_date");
}
}
});

View File

@ -2,9 +2,6 @@ from frappe import _
def get_data():
return {
'heatmap': True,
'heatmap_message': _('This is based on transactions against this Company. See timeline below for details'),
'graph': True,
'graph_method': "frappe.utils.goal.get_monthly_goal_graph_data",
'graph_method_args': {

View File

@ -1841,7 +1841,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Defaults",
"label": "Sales, Purchase, Accounting Defaults",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@ -3951,7 +3951,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 1,
"modified": "2018-08-29 06:27:10.198002",
"modified": "2018-08-30 05:28:12.312880",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item",

View File

@ -1,6 +1,7 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
// eslint-disable-next-line
{% include 'erpnext/public/js/controllers/buying.js' %};
frappe.ui.form.on('Material Request', {
@ -11,24 +12,122 @@ frappe.ui.form.on('Material Request', {
'Request for Quotation': 'Request for Quotation',
'Supplier Quotation': 'Supplier Quotation',
'Work Order': 'Work Order'
}
};
// formatter for material request item
frm.set_indicator_formatter('item_code',
function(doc) { return (doc.qty<=doc.ordered_qty) ? "green" : "orange" })
function(doc) { return (doc.qty<=doc.ordered_qty) ? "green" : "orange"; });
frm.set_query("item_code", "items", function() {
return {
query: "erpnext.controllers.queries.item_query"
};
});
},
onload: function(frm) {
// add item, if previous view was item
erpnext.utils.add_item(frm);
//set schedule_date
// set schedule_date
set_schedule_date(frm);
frm.fields_dict["items"].grid.get_field("warehouse").get_query = function(doc, cdt, cdn){
return{
frm.fields_dict["items"].grid.get_field("warehouse").get_query = function(doc) {
return {
filters: {'company': doc.company}
};
};
},
refresh: function(frm) {
frm.events.make_custom_buttons(frm);
},
make_custom_buttons: function(frm) {
if (frm.doc.docstatus==0) {
frm.add_custom_button(__("Bill of Materials"),
() => frm.events.get_items_from_bom(frm), __("Get items from"));
}
if (frm.doc.docstatus == 1 && frm.doc.status != 'Stopped') {
if (flt(frm.doc.per_ordered, 2) < 100) {
// make
if (frm.doc.material_request_type === "Material Transfer") {
frm.add_custom_button(__("Transfer Material"),
() => frm.events.make_stock_entry(frm), __("Make"));
}
if (frm.doc.material_request_type === "Material Issue") {
frm.add_custom_button(__("Issue Material"),
() => frm.events.make_stock_entry(frm), __("Make"));
}
if (frm.doc.material_request_type === "Purchase") {
frm.add_custom_button(__('Purchase Order'),
() => frm.events.make_purchase_order(frm), __("Make"));
}
if (frm.doc.material_request_type === "Purchase") {
frm.add_custom_button(__("Request for Quotation"),
() => frm.events.make_request_for_quotation(frm), __("Make"));
}
if (frm.doc.material_request_type === "Purchase") {
frm.add_custom_button(__("Supplier Quotation"),
() => frm.events.make_supplier_quotation(frm), __("Make"));
}
if (frm.doc.material_request_type === "Manufacture") {
frm.add_custom_button(__("Work Order"),
() => frm.events.raise_work_orders(frm), __("Make"));
}
frm.page.set_inner_btn_group_as_primary(__("Make"));
// stop
frm.add_custom_button(__('Stop'),
() => frm.events.update_status(frm, 'Stop'));
}
}
if (frm.doc.docstatus===0) {
frm.add_custom_button(__('Sales Order'), () => frm.events.get_items_from_sales_order(frm),
__("Get items from"));
}
if (frm.doc.docstatus == 1 && frm.doc.status == 'Stopped') {
frm.add_custom_button(__('Re-open'), () => frm.events.update_status(frm, 'Submitted'));
}
},
update_status: function(frm, stop_status) {
frappe.call({
method: 'erpnext.stock.material_request.material_request.update_status',
args: { name: frm.doc.name, status: stop_status },
callback(r) {
if (!r.exc) {
frm.reload_doc();
}
}
});
},
get_items_from_sales_order: function(frm) {
erpnext.utils.map_current_doc({
method: "erpnext.selling.doctype.sales_order.sales_order.make_material_request",
source_doctype: "Sales Order",
target: frm,
setters: {
company: frm.doc.company
},
get_query_filters: {
docstatus: 1,
status: ["!=", "Closed"],
per_delivered: ["<", 99.99],
}
});
},
get_item_data: function(frm, item) {
frm.call({
method: "erpnext.stock.get_item_details.get_item_details",
@ -45,7 +144,6 @@ frappe.ui.form.on('Material Request', {
stock_qty: item.stock_qty,
company: frm.doc.company,
conversion_rate: 1,
name: frm.doc.name,
material_request_type: frm.doc.material_request_type,
plc_conversion_rate: 1,
rate: item.rate,
@ -62,133 +160,19 @@ frappe.ui.form.on('Material Request', {
}
});
},
});
frappe.ui.form.on("Material Request Item", {
qty: function (frm, doctype, name) {
var d = locals[doctype][name];
if (flt(d.qty) < flt(d.min_order_qty)) {
frappe.msgprint(__("Warning: Material Requested Qty is less than Minimum Order Qty"));
}
const item = locals[doctype][name];
frm.events.get_item_data(frm, item);
},
rate: function(frm, doctype, name) {
const item = locals[doctype][name];
frm.events.get_item_data(frm, item);
},
item_code: function(frm, doctype, name) {
const item = locals[doctype][name];
item.rate = 0
set_schedule_date(frm);
frm.events.get_item_data(frm, item);
},
schedule_date: function(frm, cdt, cdn) {
var row = locals[cdt][cdn];
if (row.schedule_date) {
if(!frm.doc.schedule_date) {
erpnext.utils.copy_value_in_all_row(frm.doc, cdt, cdn, "items", "schedule_date");
} else {
set_schedule_date(frm);
}
}
}
});
erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.extend({
onload: function(doc) {
this._super();
this.frm.set_query("item_code", "items", function() {
return {
query: "erpnext.controllers.queries.item_query"
}
});
},
refresh: function(doc) {
var me = this;
this._super();
if(doc.docstatus==0) {
cur_frm.add_custom_button(__("Get Items from BOM"),
cur_frm.cscript.get_items_from_bom, "fa fa-sitemap", "btn-default");
}
if(doc.docstatus == 1 && doc.status != 'Stopped') {
if(flt(doc.per_ordered, 2) < 100) {
// make
if(doc.material_request_type === "Material Transfer")
cur_frm.add_custom_button(__("Transfer Material"),
this.make_stock_entry, __("Make"));
if(doc.material_request_type === "Material Issue")
cur_frm.add_custom_button(__("Issue Material"),
this.make_stock_entry, __("Make"));
if(doc.material_request_type === "Purchase")
cur_frm.add_custom_button(__('Purchase Order'),
this.make_purchase_order, __("Make"));
if(doc.material_request_type === "Purchase")
cur_frm.add_custom_button(__("Request for Quotation"),
this.make_request_for_quotation, __("Make"));
if(doc.material_request_type === "Purchase")
cur_frm.add_custom_button(__("Supplier Quotation"),
this.make_supplier_quotation, __("Make"));
if(doc.material_request_type === "Manufacture")
cur_frm.add_custom_button(__("Work Order"),
function() { me.raise_work_orders() }, __("Make"));
cur_frm.page.set_inner_btn_group_as_primary(__("Make"));
// stop
me.frm.add_custom_button(__('Stop'),
me.frm.cscript['Stop Material Request']);
}
}
if (this.frm.doc.docstatus===0) {
this.frm.add_custom_button(__('Sales Order'),
function() {
erpnext.utils.map_current_doc({
method: "erpnext.selling.doctype.sales_order.sales_order.make_material_request",
source_doctype: "Sales Order",
target: me.frm,
setters: {
company: me.frm.doc.company
},
get_query_filters: {
docstatus: 1,
status: ["!=", "Closed"],
per_delivered: ["<", 99.99],
}
})
}, __("Get items from"));
}
if(doc.docstatus == 1 && doc.status == 'Stopped')
me.frm.add_custom_button(__('Re-open'),
me.frm.cscript['Unstop Material Request']);
},
get_items_from_bom: function() {
get_items_from_bom: function(frm) {
var d = new frappe.ui.Dialog({
title: __("Get Items from BOM"),
fields: [
{"fieldname":"bom", "fieldtype":"Link", "label":__("BOM"),
options:"BOM", reqd: 1, get_query: function(){
return {filters: { docstatus:1 }}
options:"BOM", reqd: 1, get_query: function() {
return {filters: { docstatus:1 }};
}},
{"fieldname":"warehouse", "fieldtype":"Link", "label":__("Warehouse"),
options:"Warehouse", reqd: 1},
{"fieldname":"qty", "fieldtype":"Float", "label":__("Quantity"),
reqd: 1, "default": 1},
{"fieldname":"fetch_exploded", "fieldtype":"Check",
"label":__("Fetch exploded BOM (including sub-assemblies)"), "default":1},
{fieldname:"fetch", "label":__("Get Items from BOM"), "fieldtype":"Button"}
@ -197,15 +181,15 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten
d.get_input("fetch").on("click", function() {
var values = d.get_values();
if(!values) return;
values["company"] = cur_frm.doc.company;
values["company"] = frm.doc.company;
frappe.call({
method: "erpnext.manufacturing.doctype.bom.bom.get_bom_items",
args: values,
callback: function(r) {
if(!r.message) {
frappe.throw(__("BOM does not contain any stock item"))
if (!r.message) {
frappe.throw(__("BOM does not contain any stock item"));
} else {
erpnext.utils.remove_empty_first_row(cur_frm, "items");
erpnext.utils.remove_empty_first_row(frm, "items");
$.each(r.message, function(i, item) {
var d = frappe.model.add_child(cur_frm.doc, "Material Request Item", "items");
d.item_code = item.item_code;
@ -226,6 +210,94 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten
d.show();
},
make_purchase_order: function(frm) {
frappe.prompt(
{fieldname:'default_supplier', label: __('For Default Supplier (optional)'), fieldtype: 'Link', options: 'Supplier'},
(values) => {
frappe.model.open_mapped_doc({
method: "erpnext.stock.doctype.material_request.material_request.make_purchase_order",
frm: frm,
args: { default_supplier: values.default_supplier },
run_link_triggers: true
});
}
)
},
make_request_for_quotation: function(frm) {
frappe.model.open_mapped_doc({
method: "erpnext.stock.doctype.material_request.material_request.make_request_for_quotation",
frm: frm,
run_link_triggers: true
});
},
make_supplier_quotation: function(frm) {
frappe.model.open_mapped_doc({
method: "erpnext.stock.doctype.material_request.material_request.make_supplier_quotation",
frm: frm
});
},
make_stock_entry: function(frm) {
frappe.model.open_mapped_doc({
method: "erpnext.stock.doctype.material_request.material_request.make_stock_entry",
frm: frm
});
},
raise_work_orders: function(frm) {
frappe.call({
method:"erpnext.stock.doctype.material_request.material_request.raise_work_orders",
args: {
"material_request": frm.doc.name
},
callback: function(r) {
if(r.message.length) {
frm.reload_doc();
}
}
});
},
});
frappe.ui.form.on("Material Request Item", {
qty: function (frm, doctype, name) {
var d = locals[doctype][name];
if (flt(d.qty) < flt(d.min_order_qty)) {
frappe.msgprint(__("Warning: Material Requested Qty is less than Minimum Order Qty"));
}
const item = locals[doctype][name];
frm.events.get_item_data(frm, item);
},
rate: function(frm, doctype, name) {
const item = locals[doctype][name];
frm.events.get_item_data(frm, item);
},
item_code: function(frm, doctype, name) {
const item = locals[doctype][name];
item.rate = 0;
set_schedule_date(frm);
frm.events.get_item_data(frm, item);
},
schedule_date: function(frm, cdt, cdn) {
var row = locals[cdt][cdn];
if (row.schedule_date) {
if(!frm.doc.schedule_date) {
erpnext.utils.copy_value_in_all_rows(frm.doc, cdt, cdn, "items", "schedule_date");
} else {
set_schedule_date(frm);
}
}
}
});
erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.extend({
tc_name: function() {
this.get_terms();
},
@ -234,7 +306,7 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten
// to override item code trigger from transaction.js
},
validate_company_and_party: function(party_field) {
validate_company_and_party: function() {
return true;
},
@ -242,51 +314,6 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten
return;
},
make_purchase_order: function() {
frappe.model.open_mapped_doc({
method: "erpnext.stock.doctype.material_request.material_request.make_purchase_order",
frm: cur_frm,
run_link_triggers: true
});
},
make_request_for_quotation: function(){
frappe.model.open_mapped_doc({
method: "erpnext.stock.doctype.material_request.material_request.make_request_for_quotation",
frm: cur_frm,
run_link_triggers: true
});
},
make_supplier_quotation: function() {
frappe.model.open_mapped_doc({
method: "erpnext.stock.doctype.material_request.material_request.make_supplier_quotation",
frm: cur_frm
});
},
make_stock_entry: function() {
frappe.model.open_mapped_doc({
method: "erpnext.stock.doctype.material_request.material_request.make_stock_entry",
frm: cur_frm
});
},
raise_work_orders: function() {
var me = this;
frappe.call({
method:"erpnext.stock.doctype.material_request.material_request.raise_work_orders",
args: {
"material_request": me.frm.doc.name
},
callback: function(r) {
if(r.message.length) {
me.frm.reload_doc();
}
}
});
},
validate: function() {
set_schedule_date(this.frm);
},
@ -313,22 +340,8 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten
// for backward compatibility: combine new and previous states
$.extend(cur_frm.cscript, new erpnext.buying.MaterialRequestController({frm: cur_frm}));
cur_frm.cscript['Stop Material Request'] = function() {
var doc = cur_frm.doc;
$c('runserverobj', {'method':'update_status', 'arg': 'Stopped', 'docs': doc}, function(r,rt) {
cur_frm.refresh();
});
};
cur_frm.cscript['Unstop Material Request'] = function(){
var doc = cur_frm.doc;
$c('runserverobj', {'method':'update_status', 'arg': 'Submitted','docs': doc}, function(r,rt) {
cur_frm.refresh();
});
};
function set_schedule_date(frm) {
if(frm.doc.schedule_date){
erpnext.utils.copy_value_in_all_row(frm.doc, frm.doc.doctype, frm.doc.name, "items", "schedule_date");
erpnext.utils.copy_value_in_all_rows(frm.doc, frm.doc.doctype, frm.doc.name, "items", "schedule_date");
}
}

View File

@ -59,7 +59,7 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Series",
"length": 0,
@ -793,7 +793,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2018-08-29 06:28:35.129352",
"modified": "2018-08-30 07:28:01.070112",
"modified_by": "Administrator",
"module": "Stock",
"name": "Material Request",

View File

@ -14,6 +14,7 @@ from erpnext.stock.stock_balance import update_bin_qty, get_indented_qty
from erpnext.controllers.buying_controller import BuyingController
from erpnext.manufacturing.doctype.work_order.work_order import get_item_details
from erpnext.buying.utils import check_for_closed_status, validate_for_items
from erpnext.stock.doctype.item.item import get_item_defaults
from six import string_types
@ -73,21 +74,16 @@ class MaterialRequest(BuyingController):
validate_for_items(self)
# self.set_title()
self.set_title()
# self.validate_qty_against_so()
# NOTE: Since Item BOM and FG quantities are combined, using current data, it cannot be validated
# Though the creation of Material Request from a Production Plan can be rethought to fix this
def set_title(self):
'''Set title as comma separated list of items'''
items = []
for d in self.items:
if d.item_code not in items:
items.append(d.item_code)
if(len(items)==4):
break
items = ', '.join([d.item_name for d in self.items][:4])
self.title = ', '.join(items)
self.title = _('{0} for {1}'.format(self.material_request_type, items))[:100]
def on_submit(self):
# frappe.db.set(self, 'status', 'Submitted')
@ -243,11 +239,30 @@ def update_item(obj, target, source_parent):
target.qty = flt(flt(obj.stock_qty) - flt(obj.ordered_qty))/ target.conversion_factor
target.stock_qty = (target.qty * target.conversion_factor)
@frappe.whitelist()
def update_status(name, status):
material_request = frappe.get_doc('Material Request', name)
material_request.check_permission('write')
material_request.update_status(status)
@frappe.whitelist()
def make_purchase_order(source_name, target_doc=None):
def postprocess(source, target_doc):
if frappe.flags.args and frappe.flags.args.default_supplier:
# items only for given default supplier
supplier_items = []
for d in target_doc.items:
default_supplier = get_item_defaults(d.item_code, target_doc.company).get('default_supplier')
if frappe.flags.args.default_supplier == default_supplier:
supplier_items.append(d)
target_doc.items = supplier_items
set_missing_values(source, target_doc)
def select_item(d):
return d.ordered_qty < d.stock_qty
doclist = get_mapped_doc("Material Request", source_name, {
"Material Request": {
"doctype": "Purchase Order",
@ -267,7 +282,7 @@ def make_purchase_order(source_name, target_doc=None):
["sales_order_item", "sales_order_item"]
],
"postprocess": update_item,
"condition": lambda doc: doc.ordered_qty < doc.stock_qty
"condition": select_item
}
}, target_doc, postprocess)
@ -334,8 +349,8 @@ def make_purchase_order_based_on_supplier(source_name, target_doc=None):
return target_doc
def get_material_requests_based_on_supplier(supplier):
supplier_items = [d[0] for d in frappe.db.get_values("Item",
{"default_supplier": supplier})]
supplier_items = [d.parent for d in frappe.db.get_all("Item Default",
{"default_supplier": supplier}, 'parent')]
if supplier_items:
material_requests = frappe.db.sql_list("""select distinct mr.name
from `tabMaterial Request` mr, `tabMaterial Request Item` mr_item

View File

@ -472,10 +472,10 @@ frappe.ui.form.on('Stock Entry Detail', {
}
},
expense_account: function(frm, cdt, cdn) {
erpnext.utils.copy_value_in_all_row(frm.doc, cdt, cdn, "items", "expense_account");
erpnext.utils.copy_value_in_all_rows(frm.doc, cdt, cdn, "items", "expense_account");
},
cost_center: function(frm, cdt, cdn) {
erpnext.utils.copy_value_in_all_row(frm.doc, cdt, cdn, "items", "cost_center");
erpnext.utils.copy_value_in_all_rows(frm.doc, cdt, cdn, "items", "cost_center");
},
sample_quantity: function(frm, cdt, cdn) {
validate_sample_quantity(frm, cdt, cdn);

View File

@ -333,13 +333,13 @@ def get_default_cost_center(args, item, item_group):
cost_center = None
if args.get('project'):
cost_center = frappe.db.get_value("Project", args.get("project"), "cost_center", cache=True)
if not cost_center:
if args.get('customer'):
cost_center = item.get('selling_cost_center') or item_group.get('selling_cost_center')
else:
cost_center = item.get('buying_cost_center') or item_group.get('buying_cost_center')
return cost_center or args.get("cost_center")
def get_default_supplier(args, item, item_group):
@ -401,7 +401,7 @@ def insert_item_price(args):
})
item_price.insert()
frappe.msgprint(_("Item Price added for {0} in Price List {1}").format(args.item_code,
args.price_list))
args.price_list), alert=True)
def get_item_price(args, item_code):
"""
@ -658,7 +658,7 @@ def get_serial_no_details(item_code, warehouse, stock_qty, serial_no):
def get_bin_details_and_serial_nos(item_code, warehouse, has_batch_no, stock_qty=None, serial_no=None):
bin_details_and_serial_nos = {}
bin_details_and_serial_nos.update(get_bin_details(item_code, warehouse))
if stock_qty > 0:
if flt(stock_qty) > 0:
if has_batch_no:
args = frappe._dict({"item_code":item_code, "warehouse":warehouse, "stock_qty":stock_qty})
serial_no = get_serial_no(args)