[New Feature]Scan Item Barcode label to quick create/update records in items child table (#15731)

* Update transaction.js

* setup barcode scan

stock entry controller not inherited from transaction.js, need to call setup barcode scan from transaction.js

* fix bug of item_code change always reset qty to 0

when calling frappe.model.set_value(dt,dn,'item_code',xxx), even qty is set, system always reset qty to 0.

* Update transaction.js

* Update transaction.js

* Update transaction.js

* Update transaction.js

* Update transaction.js

* Update transaction.js

* clean up barcode logic for transactions

* call scan_barcode method for stock entry

* separate out logic for searching serial, batch or barcode number

* added scan barcode field in transactions doctype

* search barcode-serial-batch sequence, code rectify

* hide all barcode related field if disabled from settings

* remove print statement

* Update stock_entry.py
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index 504d45f..e6b2f5f 100755
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -1,5 +1,6 @@
 {
  "allow_copy": 0, 
+ "allow_events_in_timeline": 0,
  "allow_guest_to_view": 0, 
  "allow_import": 1, 
  "allow_rename": 0, 
@@ -1552,6 +1553,38 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "scan_barcode",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Scan Barcode",
+   "length": 0,
+   "no_copy": 0,
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
    "allow_bulk_edit": 1, 
    "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
@@ -4593,7 +4626,7 @@
  "istable": 0, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2018-09-11 14:44:31.220376", 
+ "modified": "2018-10-18 04:43:39.792967",
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Purchase Invoice", 
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index 4154d2e..59c7629 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -1,5 +1,6 @@
 {
  "allow_copy": 0, 
+ "allow_events_in_timeline": 0,
  "allow_guest_to_view": 0, 
  "allow_import": 1, 
  "allow_rename": 0, 
@@ -1652,6 +1653,38 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "scan_barcode",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Scan Barcode",
+   "length": 0,
+   "no_copy": 0,
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
    "allow_bulk_edit": 1, 
    "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
@@ -5546,7 +5579,7 @@
  "istable": 0, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2018-09-07 14:24:58.854289", 
+ "modified": "2018-10-18 04:43:08.998164",
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Sales Invoice", 
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index 601af69..3ffa534 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -1,5 +1,6 @@
 {
  "allow_copy": 0, 
+ "allow_events_in_timeline": 0,
  "allow_guest_to_view": 0, 
  "allow_import": 1, 
  "allow_rename": 0, 
@@ -1387,6 +1388,38 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "scan_barcode",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Scan Barcode",
+   "length": 0,
+   "no_copy": 0,
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
    "allow_bulk_edit": 1, 
    "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
@@ -3736,8 +3769,8 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2018-08-29 12:16:12.886021", 
- "modified_by": "nabinhait@gmail.com", 
+ "modified": "2018-10-18 04:40:58.392537",
+ "modified_by": "Administrator",
  "module": "Buying", 
  "name": "Purchase Order", 
  "owner": "Administrator", 
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 3e27d56..ca6eb44 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -253,6 +253,62 @@
 		this.set_dynamic_labels();
 		this.setup_sms();
 		this.setup_quality_inspection();
+		this.frm.fields_dict["scan_barcode"] && this.frm.fields_dict["scan_barcode"].set_value("");
+		this.frm.fields_dict["scan_barcode"] && this.frm.fields_dict["scan_barcode"].set_new_description("");
+	},
+
+	scan_barcode: function() {
+		let scan_barcode_field = this.frm.fields_dict["scan_barcode"];
+
+		let show_description = function(idx, item_code, exist=null) {
+			if(exist) {
+				scan_barcode_field.set_new_description(__('Row : ') + idx + ' ' +
+					item_code + __(' Qty increased by 1'));
+			} else {
+				scan_barcode_field.set_new_description(__('New row : ') + idx + ' ' +
+					item_code + __('  Created'));
+			}
+		}
+
+		if(this.frm.doc.scan_barcode) {
+			frappe.call({
+				method: "erpnext.selling.page.point_of_sale.point_of_sale.search_serial_or_batch_or_barcode_number",
+				args: { search_value: this.frm.doc.scan_barcode }
+			}).then(r => {
+
+				if(r && r.message && r.message.item_code) {
+					let child = "";
+					let add_row_index = -1;
+					let cur_grid= this.frm.fields_dict["items"].grid;
+
+					this.frm.doc.items.map(d => {
+						if(d.item_code==r.message.item_code){
+							add_row_index = d.idx;
+							return;
+						} else if(!d.item_code && add_row_index==-1) {
+							add_row_index = d.idx;
+						}
+					});
+
+					if(add_row_index == -1) {
+						child = frappe.model.add_child(this.frm.doc, cur_grid.doctype, "items", add_row_index);
+					} else {
+						child = cur_grid.get_grid_row(add_row_index-1).doc;
+					}
+					show_description(child.idx, r.message.item_code, child.item_code);
+
+					frappe.model.set_value(child.doctype, child.name, {
+						"item_code": r.message.item_code,
+						"qty": (child.qty || 0) + 1
+					});
+				}
+				else{
+					scan_barcode_field.set_new_description(this.frm.doc.scan_barcode +__(' does not exist!'));
+				}
+			});
+			scan_barcode_field.set_value("");
+		}
+		return false;
 	},
 
 	apply_default_taxes: function() {
diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json
index 22e5741..ee626df 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.json
+++ b/erpnext/selling/doctype/sales_order/sales_order.json
@@ -1,5 +1,6 @@
 {
  "allow_copy": 0, 
+ "allow_events_in_timeline": 0,
  "allow_guest_to_view": 0, 
  "allow_import": 1, 
  "allow_rename": 0, 
@@ -1205,6 +1206,38 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "scan_barcode",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Scan Barcode",
+   "length": 0,
+   "no_copy": 0,
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
    "allow_bulk_edit": 1, 
    "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
@@ -3918,7 +3951,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2018-08-21 14:44:44.011356", 
+ "modified": "2018-10-18 04:41:28.111144",
  "modified_by": "Administrator", 
  "module": "Selling", 
  "name": "Sales Order", 
diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py
index ed28204..daec5b5 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.py
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.py
@@ -11,12 +11,9 @@
 
 @frappe.whitelist()
 def get_items(start, page_length, price_list, item_group, search_value="", pos_profile=None):
-	serial_no = ""
-	batch_no = ""
-	barcode = ""
+	data = dict()
 	warehouse = ""
 	display_items_in_stock = 0
-	item_code = search_value
 
 	if pos_profile:
 		warehouse, display_items_in_stock = frappe.db.get_value('POS Profile', pos_profile, ['warehouse', 'display_items_in_stock'])
@@ -25,20 +22,12 @@
 		item_group = get_root_of('Item Group')
 
 	if search_value:
-		# search serial no
-		serial_no_data = frappe.db.get_value('Serial No', search_value, ['name', 'item_code'])
-		if serial_no_data:
-			serial_no, item_code = serial_no_data
+		data = search_serial_or_batch_or_barcode_number(search_value)
 
-		if not serial_no:
-			batch_no_data = frappe.db.get_value('Batch', search_value, ['name', 'item'])
-			if batch_no_data:
-				batch_no, item_code = batch_no_data
-
-		if not serial_no and not batch_no:
-			barcode_data = frappe.db.get_value('Item Barcode', {'barcode': search_value}, ['parent', 'barcode'])
-			if barcode_data:
-				item_code, barcode = barcode_data
+	item_code = data.get("item_code") if data.get("item_code") else search_value
+	serial_no = data.get("serial_no") if data.get("serial_no") else ""
+	batch_no = data.get("batch_no") if data.get("batch_no") else ""
+	barcode = data.get("barcode") if data.get("barcode") else ""
 
 	item_code, condition = get_conditions(item_code, serial_no, batch_no, barcode)
 
@@ -119,6 +108,23 @@
 
 	return res
 
+@frappe.whitelist()
+def search_serial_or_batch_or_barcode_number(search_value):
+	# search barcode no
+	barcode_data = frappe.db.get_value('Item Barcode', {'barcode': search_value}, ['barcode', 'parent as item_code'], as_dict=True)
+	if barcode_data:
+		return barcode_data
+
+	# search serial no
+	serial_no_data = frappe.db.get_value('Serial No', search_value, ['name as serial_no', 'item_code'], as_dict=True)
+	if serial_no_data:
+		return serial_no_data
+
+	# search batch no
+	batch_no_data = frappe.db.get_value('Batch', search_value, ['name as batch_no', 'item as item_code'], as_dict=True)
+	if batch_no_data:
+		return batch_no_data
+
 def get_conditions(item_code, serial_no, batch_no, barcode):
 	if serial_no or batch_no or barcode:
 		return frappe.db.escape(item_code), "i.name = %(item_code)s"
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json
index 765033a..14a766e 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.json
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.json
@@ -1,5 +1,6 @@
 {
  "allow_copy": 0,
+ "allow_events_in_timeline": 0,
  "allow_guest_to_view": 0,
  "allow_import": 1,
  "allow_rename": 0,
@@ -1368,6 +1369,38 @@
    "unique": 0
   },
   {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "scan_barcode",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Scan Barcode",
+   "length": 0,
+   "no_copy": 0,
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
    "allow_bulk_edit": 1,
    "allow_in_quick_entry": 0,
    "allow_on_submit": 0,
@@ -4168,7 +4201,7 @@
  "istable": 0,
  "max_attachments": 0,
  "menu_index": 0,
- "modified": "2018-10-06 14:25:15.326772",
+ "modified": "2018-10-18 04:38:25.217283",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Delivery Note",
diff --git a/erpnext/stock/doctype/material_request/material_request.json b/erpnext/stock/doctype/material_request/material_request.json
index c0285cb..8a53a27 100644
--- a/erpnext/stock/doctype/material_request/material_request.json
+++ b/erpnext/stock/doctype/material_request/material_request.json
@@ -1,5 +1,6 @@
 {
  "allow_copy": 0,
+ "allow_events_in_timeline": 0,
  "allow_guest_to_view": 0,
  "allow_import": 1,
  "allow_rename": 0,
@@ -313,6 +314,38 @@
    "unique": 0
   },
   {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "scan_barcode",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Scan Barcode",
+   "length": 0,
+   "no_copy": 0,
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
    "allow_bulk_edit": 1,
    "allow_in_quick_entry": 0,
    "allow_on_submit": 0,
@@ -826,7 +859,7 @@
  "istable": 0,
  "max_attachments": 0,
  "menu_index": 0,
- "modified": "2018-09-05 07:28:01.070112",
+ "modified": "2018-10-18 04:41:56.818108",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Material Request",
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 0356b0e..a26992a 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -594,6 +594,11 @@
 		erpnext.utils.add_item(this.frm);
 	},
 
+	scan_barcode: function() {
+		let transaction_controller= new erpnext.TransactionController({frm:this.frm});
+		transaction_controller.scan_barcode();
+	},
+
 	on_submit: function() {
 		this.clean_up();
 	},
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.json b/erpnext/stock/doctype/stock_entry/stock_entry.json
index 35f8c27..6a925ad 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.json
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.json
@@ -1,5 +1,6 @@
 {
  "allow_copy": 0,
+ "allow_events_in_timeline": 0,
  "allow_guest_to_view": 0,
  "allow_import": 1,
  "allow_rename": 0,
@@ -1051,6 +1052,38 @@
    "bold": 0,
    "collapsible": 0,
    "columns": 0,
+   "fieldname": "scan_barcode",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Scan Barcode",
+   "length": 0,
+   "no_copy": 0,
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 0
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
    "fieldname": "items",
    "fieldtype": "Table",
    "hidden": 0,
@@ -1965,7 +1998,7 @@
    "report_hide": 0,
    "reqd": 0,
    "search_index": 0,
-   "set_only_once": 0, 
+   "set_only_once": 0,
    "translatable": 0,
    "unique": 0
   },
@@ -2048,7 +2081,7 @@
  "issingle": 0,
  "istable": 0,
  "max_attachments": 0,
- "modified": "2018-09-05 06:27:59.630826",
+ "modified": "2018-10-18 04:42:41.452572",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Entry",
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index d4e7b95..d8e4656 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -634,19 +634,19 @@
 
 		ret = frappe._dict({
 			'uom'			      	: item.stock_uom,
-			'stock_uom'			  	: item.stock_uom,
+			'stock_uom'			: item.stock_uom,
 			'description'		  	: item.description,
-			'image'					: item.image,
+			'image'				: item.image,
 			'item_name' 		  	: item.item_name,
 			'expense_account'		: args.get("expense_account"),
 			'cost_center'			: get_default_cost_center(args, item, item_group_defaults),
-			'qty'					: 0,
-			'transfer_qty'			: 0,
+			'qty'				: args.get("qty"),
+			'transfer_qty'			: args.get('qty'),
 			'conversion_factor'		: 1,
-			'batch_no'				: '',
+			'batch_no'			: '',
 			'actual_qty'			: 0,
 			'basic_rate'			: 0,
-			'serial_no'				: '',
+			'serial_no'			: '',
 			'has_serial_no'			: item.has_serial_no,
 			'has_batch_no'			: item.has_batch_no,
 			'sample_quantity'		: item.sample_quantity
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.py b/erpnext/stock/doctype/stock_settings/stock_settings.py
index 97d24c6..65de2e5 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.py
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.py
@@ -26,8 +26,9 @@
 			frappe.msgprint (_("`Freeze Stocks Older Than` should be smaller than %d days.") %stock_frozen_limit)
 
 		# show/hide barcode field
-		frappe.make_property_setter({'fieldname': 'barcodes', 'property': 'hidden',
-			'value': 0 if self.show_barcode_field else 1})
+		for name in ["barcode", "barcodes", "scan_barcode"]:
+			frappe.make_property_setter({'fieldname': name, 'property': 'hidden',
+				'value': 0 if self.show_barcode_field else 1})
 
 		self.cant_change_valuation_method()
 		self.validate_clean_description_html()