Merge pull request #2390 from ankitjavalkarwork/fix2314

Add selectable BOM field for Subcontracted Item
diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.js b/erpnext/buying/doctype/purchase_common/purchase_common.js
index 75eb028..2f7af71 100644
--- a/erpnext/buying/doctype/purchase_common/purchase_common.js
+++ b/erpnext/buying/doctype/purchase_common/purchase_common.js
@@ -389,5 +389,22 @@
 	}
 });
 cur_frm.add_fetch('project_name', 'cost_center', 'cost_center');
-var tname = cur_frm.cscript.tname;
-var fname = cur_frm.cscript.fname;
+
+erpnext.buying.get_default_bom = function(frm) {
+	$.each(frm.doc[frm.cscript.fname] || [], function(i, d) {
+		if (d.item_code && d.bom === "") {
+			return frappe.call({
+				type: "GET",
+				method: "erpnext.stock.get_item_details.get_default_bom",
+				args: {
+					"item_code": d.item_code,
+				},
+				callback: function(r) {
+					if(r) {
+						frappe.model.set_value(d.doctype, d.name, "bom", r.message);
+					}
+				}
+			})
+		}
+	});
+}
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index aab48a2..e712995 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -109,7 +109,6 @@
 		var row = frappe.get_doc(cdt, cdn);
 		this.frm.script_manager.copy_from_first_row("po_details", row, ["schedule_date"]);
 	}
-
 });
 
 // for backward compatibility: combine new and previous states
@@ -135,6 +134,17 @@
 	}
 }
 
+cur_frm.fields_dict['po_details'].grid.get_field('bom').get_query = function(doc, cdt, cdn) {
+	var d = locals[cdt][cdn]
+	return {
+		filters: [
+			['BOM', 'item', '=', d.item_code],
+			['BOM', 'is_active', '=', '1'],
+			['BOM', 'docstatus', '=', '1']
+		]
+	}
+}
+
 cur_frm.cscript.get_last_purchase_rate = function(doc, cdt, cdn){
 	return $c_obj(doc, 'get_last_purchase_rate', '', function(r, rt) {
 		refresh_field(cur_frm.cscript.fname);
@@ -219,3 +229,11 @@
 cur_frm.cscript.schedule_date = function(doc, cdt, cdn) {
 	cur_frm.cscript.copy_account_in_all_row(doc, cdt, cdn, "schedule_date");
 }
+
+frappe.provide("erpnext.buying");
+
+frappe.ui.form.on("Purchase Order", "is_subcontracted", function(frm) {
+	if (frm.doc.is_subcontracted === "Yes") {
+		erpnext.buying.get_default_bom(frm);
+	}
+});
diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
index 0adc981..23fd162 100755
--- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
+++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
@@ -381,6 +381,16 @@
    "read_only": 1
   }, 
   {
+   "fieldname": "bom", 
+   "fieldtype": "Link", 
+   "label": "BOM", 
+   "no_copy": 1, 
+   "options": "BOM", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1
+  }, 
+  {
    "fieldname": "stock_qty", 
    "fieldtype": "Float", 
    "hidden": 0, 
@@ -445,7 +455,7 @@
  ], 
  "idx": 1, 
  "istable": 1, 
- "modified": "2014-09-09 05:35:36.346557", 
+ "modified": "2014-11-07 15:09:45.530230", 
  "modified_by": "Administrator", 
  "module": "Buying", 
  "name": "Purchase Order Item", 
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 09a9c3e..0f7e2ba 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -212,10 +212,19 @@
 		if not self.is_subcontracted and self.sub_contracted_items:
 			frappe.throw(_("Please enter 'Is Subcontracted' as Yes or No"))
 
-		if self.doctype == "Purchase Receipt" and self.is_subcontracted=="Yes" \
-			and not self.supplier_warehouse:
+		if self.is_subcontracted == "Yes":
+			if self.doctype == "Purchase Receipt" and not self.supplier_warehouse:
 				frappe.throw(_("Supplier Warehouse mandatory for sub-contracted Purchase Receipt"))
 
+			for item in self.get(self.fname):
+				if item in self.sub_contracted_items and not item.bom:
+					frappe.throw(_("Please select BOM in BOM field for Item {0}").format(item.item_code))
+
+		else:
+			for item in self.get(self.fname):
+				if item.bom:
+					item.bom = None
+
 	def create_raw_materials_supplied(self, raw_material_table):
 		if self.is_subcontracted=="Yes":
 			parent_items = []
@@ -236,7 +245,7 @@
 				item.rm_supp_cost = 0.0
 
 	def update_raw_materials_supplied(self, item, raw_material_table, rm_supplied_idx):
-		bom_items = self.get_items_from_default_bom(item.item_code)
+		bom_items = self.get_items_from_bom(item.item_code, item.bom)
 		raw_materials_cost = 0
 
 		for bom_item in bom_items:
@@ -309,15 +318,16 @@
 				if d not in delete_list:
 					self.append(raw_material_table, d)
 
-	def get_items_from_default_bom(self, item_code):
+	def get_items_from_bom(self, item_code, bom):
 		bom_items = frappe.db.sql("""select t2.item_code,
 			ifnull(t2.qty, 0) / ifnull(t1.quantity, 1) as qty_consumed_per_unit,
 			t2.rate, t2.stock_uom, t2.name, t2.description
 			from `tabBOM` t1, `tabBOM Item` t2
-			where t2.parent = t1.name and t1.item = %s and t1.is_default = 1
-			and t1.docstatus = 1 and t1.is_active = 1""", item_code, as_dict=1)
+			where t2.parent = t1.name and t1.item = %s
+			and t1.docstatus = 1 and t1.is_active = 1 and t1.name = %s""", (item_code, bom), as_dict=1)
+
 		if not bom_items:
-			msgprint(_("No default BOM exists for Item {0}").format(item_code), raise_exception=1)
+			msgprint(_("Specified BOM {0} does not exist for Item {1}").format(bom, item_code), raise_exception=1)
 
 		return bom_items
 
@@ -358,3 +368,4 @@
 				if not d.conversion_factor:
 					frappe.throw(_("Row {0}: Conversion Factor is mandatory"))
 				d.stock_qty = flt(d.qty) * flt(d.conversion_factor)
+
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index 632d42c..fc2d1b3 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -161,6 +161,17 @@
 	}
 }
 
+cur_frm.fields_dict['purchase_receipt_details'].grid.get_field('bom').get_query = function(doc, cdt, cdn) {
+	var d = locals[cdt][cdn]
+	return {
+		filters: [
+			['BOM', 'item', '=', d.item_code],
+			['BOM', 'is_active', '=', '1'],
+			['BOM', 'docstatus', '=', '1']
+		]
+	}
+}
+
 cur_frm.cscript.on_submit = function(doc, cdt, cdn) {
 	if(cint(frappe.boot.notification_settings.purchase_receipt))
 		cur_frm.email_doc(frappe.boot.notification_settings.purchase_receipt_message);
@@ -171,3 +182,10 @@
 	var sms_man = new SMSManager(cur_frm.doc);
 }
 
+frappe.provide("erpnext.buying");
+
+frappe.ui.form.on("Purchase Receipt", "is_subcontracted", function(frm) {
+	if (frm.doc.is_subcontracted === "Yes") {
+		erpnext.buying.get_default_bom(frm);
+	}
+});
diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
index da237ad..c13f34c 100755
--- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
+++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
@@ -400,6 +400,16 @@
    "permlevel": 0
   }, 
   {
+   "fieldname": "bom", 
+   "fieldtype": "Link", 
+   "label": "BOM", 
+   "no_copy": 1, 
+   "options": "BOM", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1
+  }, 
+  {
    "fieldname": "serial_no", 
    "fieldtype": "Text", 
    "in_filter": 1, 
@@ -549,7 +559,7 @@
  ], 
  "idx": 1, 
  "istable": 1, 
- "modified": "2014-09-09 05:35:38.908372", 
+ "modified": "2014-11-07 15:54:08.266918", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Purchase Receipt Item", 
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 0789a33..5fe8b14 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -68,6 +68,9 @@
 		out.schedule_date = out.lead_time_date = add_days(args.transaction_date,
 			item.lead_time_days)
 
+	if args.get("is_subcontracted") == "Yes":
+		out.bom = get_default_bom(args.item_code)
+
 	return out
 
 def process_args(args):
@@ -381,3 +384,12 @@
 		"price_list_currency": price_list_currency,
 		"plc_conversion_rate": plc_conversion_rate
 	}
+
+@frappe.whitelist()
+def get_default_bom(item_code=None):
+	if item_code:
+		bom = frappe.db.get_value("BOM", {"docstatus": 1, "is_default": 1, "is_active": 1, "item": item_code})
+		if bom:
+			return bom
+		else:
+			frappe.throw(_("No default BOM exists for Item {0}").format(item_code))