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:
parent
f6b784e39e
commit
49f9747385
@ -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) {
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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"""
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -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': {
|
||||
|
@ -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",
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user