Merge branch 'master' into develop
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 007afe4..3fbde29 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -323,7 +323,8 @@
 		}
 	}
 
-	item_fields_stock = ['serial_no', 'batch_no', 'actual_qty', 'expense_account', 'warehouse', 'expense_account', 'warehouse']
+	item_fields_stock = ['batch_no', 'actual_batch_qty', 'actual_qty', 'expense_account',
+		'warehouse', 'expense_account', 'quality_inspection']
 	cur_frm.fields_dict['items'].grid.set_column_disp(item_fields_stock,
 		(cint(doc.update_stock)==1 || cint(doc.is_return)==1 ? true : false));
 
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 6e3990a..f32cfcd 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -88,6 +88,8 @@
 		self.validate_c_form()
 		self.validate_time_sheets_are_submitted()
 		self.validate_multiple_billing("Delivery Note", "dn_detail", "amount", "items")
+		if not self.is_return:
+			self.validate_serial_numbers()
 		self.update_packing_list()
 		self.set_billing_hours_and_amount()
 		self.update_timesheet_billing_for_project()
@@ -125,6 +127,7 @@
 		if not self.is_return:
 			self.update_billing_status_for_zero_amount_refdoc("Sales Order")
 			self.check_credit_limit()
+			self.update_serial_no()
 
 		if not cint(self.is_pos) == 1 and not self.is_return:
 			self.update_against_document_in_jv()
@@ -155,6 +158,7 @@
 
 		if not self.is_return:
 			self.update_billing_status_for_zero_amount_refdoc("Sales Order")
+			self.update_serial_no(in_cancel=True)
 
 		self.validate_c_form_on_cancel()
 
@@ -781,6 +785,61 @@
 
 		self.due_date = None
 
+	def update_serial_no(self, in_cancel=False):
+		""" update Sales Invoice refrence in Serial No """
+
+		for item in self.items:
+			if not item.serial_no:
+				continue
+
+			serial_nos = ["'%s'"%serial_no for serial_no in item.serial_no.split("\n")]
+
+			frappe.db.sql(""" update `tabSerial No` set sales_invoice='{invoice}'
+				where name in ({serial_nos})""".format(
+					invoice='' if in_cancel else self.name,
+					serial_nos=",".join(serial_nos)
+				)
+			)
+
+	def validate_serial_numbers(self):
+		"""
+			validate serial number agains Delivery Note and Sales Invoice
+		"""
+		self.validate_serial_against_delivery_note()
+		self.validate_serial_against_sales_invoice()
+
+	def validate_serial_against_delivery_note(self):
+		""" 
+			validate if the serial numbers in Sales Invoice Items are same as in
+			Delivery Note Item
+		"""
+
+		for item in self.items:
+			if not item.delivery_note or not item.dn_detail:
+				continue
+
+			serial_nos = frappe.db.get_value("Delivery Note Item", item.dn_detail, "serial_no") or ""
+			dn_serial_nos = set(serial_nos.split("\n"))
+
+			serial_nos = item.serial_no or ""
+			si_serial_nos = set(serial_nos.split("\n"))
+
+			if si_serial_nos - dn_serial_nos:
+				frappe.throw(_("Serial Numbers in row {0} does not match with Delivery Note".format(item.idx)))
+
+	def validate_serial_against_sales_invoice(self):
+		""" check if serial number is already used in other sales invoice """
+		for item in self.items:
+			if not item.serial_no:
+				continue
+
+			for serial_no in item.serial_no.split("\n"):
+				sales_invoice = frappe.db.get_value("Serial No", serial_no, "sales_invoice")
+				if sales_invoice and self.name != sales_invoice:
+					frappe.throw(_("Serial Number: {0} is already referenced in Sales Invoice: {1}".format(
+						serial_no, sales_invoice
+					)))
+
 def get_list_context(context=None):
 	from erpnext.controllers.website_list_for_contact import get_list_context
 	list_context = get_list_context(context)
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 0ada847..8335879 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -737,6 +737,12 @@
 		self.assertFalse(frappe.db.get_value("Serial No", serial_nos[0], "warehouse"))
 		self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0],
 			"delivery_document_no"), si.name)
+		self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "sales_invoice"),
+			si.name)
+
+		# check if the serial number is already linked with any other Sales Invoice
+		_si = frappe.copy_doc(si.as_dict())
+		self.assertRaises(frappe.ValidationError, _si.insert)
 
 		return si
 
@@ -750,6 +756,7 @@
 		self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "warehouse"), "_Test Warehouse - _TC")
 		self.assertFalse(frappe.db.get_value("Serial No", serial_nos[0],
 			"delivery_document_no"))
+		self.assertFalse(frappe.db.get_value("Serial No", serial_nos[0], "sales_invoice"))
 
 	def test_serialize_status(self):
 		serial_no = frappe.get_doc({
@@ -768,6 +775,27 @@
 
 		self.assertRaises(SerialNoWarehouseError, si.submit)
 
+	def test_serial_numbers_against_delivery_note(self):
+		""" 
+			check if the sales invoice item serial numbers and the delivery note items
+			serial numbers are same
+		"""
+		from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
+		from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
+		from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
+		from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
+
+		se = make_serialized_item()
+		serial_nos = get_serial_nos(se.get("items")[0].serial_no)
+
+		dn = create_delivery_note(item=se.get("items")[0].item_code, serial_no=serial_nos[0])
+		dn.submit()
+
+		si = make_sales_invoice(dn.name)
+		si.save()
+
+		self.assertEquals(si.get("items")[0].serial_no, dn.get("items")[0].serial_no)
+
 	def test_invoice_due_date_against_customers_credit_days(self):
 		# set customer's credit days
 		frappe.db.set_value("Customer", "_Test Customer", "credit_days_based_on", "Fixed Days")
diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js
index 9261fa4..6a2e0cf 100644
--- a/erpnext/accounts/page/pos/pos.js
+++ b/erpnext/accounts/page/pos/pos.js
@@ -398,7 +398,7 @@
 		this.make_item_list();
 		this.make_discount_field()
 	},
-	
+
 	make_control: function() {
 		this.frm = {}
 		this.frm.doc = this.doc
@@ -543,7 +543,7 @@
 			me.toggle_totals_area();
 		});
 	},
-	
+
 	bind_numeric_keypad: function() {
 		var me = this;
 		$(this.numeric_keypad).find('.pos-operation').on('click', function(){
@@ -572,7 +572,7 @@
 				me.selected_field.closest('.pos-list-row').addClass('active');
 			}
 		})
-		
+
 		$(this.numeric_keypad).find('.numeric-del').click(function(){
 			me.selected_field = $(me.wrapper).find('.selected-item').find('.' + me.numeric_id)
 			me.numeric_val = cstr(flt(me.selected_field.val())).slice(0, -1);
@@ -580,7 +580,7 @@
 			me.selected_field.trigger("change")
 			// me.render_selected_item()
 		})
-		
+
 		$(this.numeric_keypad).find('.pos-pay').click(function(){
 			me.validate();
 			me.update_paid_amount_status(true);
@@ -988,7 +988,7 @@
 					})).tooltip().appendTo($wrap);
 				}
 			});
-			
+
 			$wrap.append(`
 				<div class="image-view-item btn-more text-muted text-center">
 					<div class="image-view-body">
@@ -1070,7 +1070,7 @@
 			});
 		}
 	},
-	
+
 	bind_items_event: function() {
 		var me = this;
 		$(this.wrapper).on('click', '.pos-bill-item', function() {
@@ -1107,7 +1107,7 @@
 			var qty = flt($(this).parents(".pos-bill-item").find('.pos-item-qty').val()) - 1;
 			me.update_qty(item_code, qty)
 		})
-		
+
 		$(this.wrapper).on("change", ".pos-item-disc", function () {
 			var item_code = $(this).parents(".pos-selected-item-action").attr("data-item-code");
 			var discount = $(this).val();
@@ -1763,10 +1763,14 @@
 	mandatory_batch_no: function () {
 		var me = this;
 		if (this.items[0].has_batch_no && !this.item_batch_no[this.items[0].item_code]) {
-			frappe.throw(__(repl("Error: Batch no is mandatory for item %(item)s", {
-				'item': this.items[0].item_code
-			})))
-		}
+			frappe.prompt([
+				{'fieldname': 'batch', 'fieldtype': 'Select', 'label': __('Batch No'), 'reqd': 1, 'options':this.batch_no_data[this.items[0].item_code]}
+				],
+				function(values){
+					me.item_batch_no[me.items[0].item_code] = values.batch;
+				},
+				__('Select Batch No'))
+			}
 	},
 
 	apply_pricing_rule: function () {
@@ -1788,7 +1792,7 @@
 				item.pricing_rule = null;
 				me.apply_pricing_rule_on_item(item)
 			}
-			
+
 			if(item.discount_percentage > 0) {
 				me.apply_pricing_rule_on_item(item)
 			}
diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py
index ccbb536..aafc128 100644
--- a/erpnext/crm/doctype/lead/lead.py
+++ b/erpnext/crm/doctype/lead/lead.py
@@ -4,7 +4,7 @@
 from __future__ import unicode_literals
 import frappe
 from frappe import _
-from frappe.utils import (cstr, validate_email_add, cint, comma_and, has_gravatar, now)
+from frappe.utils import (cstr, validate_email_add, cint, comma_and, has_gravatar, now, getdate, nowdate)
 from frappe.model.mapper import get_mapped_doc
 
 from erpnext.controllers.selling_controller import SellingController
@@ -46,7 +46,7 @@
 			if self.is_new() or not self.image:
 				self.image = has_gravatar(self.email_id)
 
-		if self.contact_date and self.contact_date < now():
+		if self.contact_date and getdate(self.contact_date) < getdate(nowdate()):
 			frappe.throw(_("Next Contact Date cannot be in the past"))
 
 	def on_update(self):
diff --git a/erpnext/docs/assets/img/setup/users/user-login-email.png b/erpnext/docs/assets/img/setup/users/user-login-email.png
new file mode 100644
index 0000000..71050af
--- /dev/null
+++ b/erpnext/docs/assets/img/setup/users/user-login-email.png
Binary files differ
diff --git a/erpnext/docs/assets/img/setup/users/user-login-mobile.png b/erpnext/docs/assets/img/setup/users/user-login-mobile.png
new file mode 100644
index 0000000..1d7af14
--- /dev/null
+++ b/erpnext/docs/assets/img/setup/users/user-login-mobile.png
Binary files differ
diff --git a/erpnext/docs/user/manual/en/setting-up/settings/system-settings.md b/erpnext/docs/user/manual/en/setting-up/settings/system-settings.md
index 053b4f1..b436b46 100644
--- a/erpnext/docs/user/manual/en/setting-up/settings/system-settings.md
+++ b/erpnext/docs/user/manual/en/setting-up/settings/system-settings.md
@@ -2,6 +2,8 @@
 
 You can localize ERPNext to use particular timezone, date, number or currency format and also set global session expiry via System Settings.
 
+By checking the 'Allow Login using Mobile Number' checkbox, you can login to ERPNext using a valid mobile number set in your User account. 
+
 To open System Settings, go to:
 
 > Setup > Settings > System Settings
diff --git a/erpnext/docs/user/manual/en/setting-up/users-and-permissions/adding-users.md b/erpnext/docs/user/manual/en/setting-up/users-and-permissions/adding-users.md
index 517c674..6fb64df 100644
--- a/erpnext/docs/user/manual/en/setting-up/users-and-permissions/adding-users.md
+++ b/erpnext/docs/user/manual/en/setting-up/users-and-permissions/adding-users.md
@@ -20,7 +20,10 @@
 
 Add user details such as First Name, Last Name, Email etc.
 
-The user's Email will become the user id.
+The user's Email will become the user id. Mobile No can also be used to log in if you check the Allow Login using Mobile No checkbox under the Security section in System Settings. While Mobile No will be unique, it will not be treated as a user id.
+
+<img class="screenshot" src="{{docs_base_url}}/assets/img/setup/users/user-login-email.png" alt="Email Login">
+<img class="screenshot" src="{{docs_base_url}}/assets/img/setup/users/user-login-mobile.png" alt="Mobile No Login">
 
 After adding these details, save the user.
 
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index ac91f60..0faf98e 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -396,3 +396,4 @@
 erpnext.patches.v8_0.rename_total_margin_to_rate_with_margin # 11-05-2017
 erpnext.patches.v8_0.fix_status_for_invoices_with_negative_outstanding
 erpnext.patches.v8_0.make_payments_table_blank_for_non_pos_invoice
+erpnext.patches.v8_0.set_sales_invoice_serial_number_from_delivery_note
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py b/erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py
new file mode 100644
index 0000000..2ae74cd
--- /dev/null
+++ b/erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py
@@ -0,0 +1,42 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from erpnext.stock.stock_balance import update_bin_qty, get_reserved_qty
+
+def execute():
+	""" Set the Serial Numbers in Sales Invoice Item from Delivery Note Item """
+
+	frappe.reload_doc("stock", "doctype", "serial_no")
+
+	frappe.db.sql(""" update `tabSales Invoice Item` sii inner join 
+		`tabDelivery Note Item` dni on sii.dn_detail=dni.name and  sii.qty=dni.qty
+		set sii.serial_no=dni.serial_no where sii.parent IN (select si.name 
+			from `tabSales Invoice` si where si.update_stock=0 and si.docstatus=1)""")
+
+	items = frappe.db.sql(""" select  sii.parent, sii.serial_no from  `tabSales Invoice Item` sii
+		left join `tabSales Invoice` si on sii.parent=si.name
+		where si.docstatus=1 and si.update_stock=0""", as_dict=True)
+
+	for item in items:
+		sales_invoice = item.get("parent", None)
+		serial_nos = item.get("serial_no", "")
+
+		if not sales_invoice or not serial_nos:
+			continue
+
+		serial_nos = ["'%s'"%no for no in serial_nos.split("\n")]
+
+		frappe.db.sql("""
+			UPDATE 
+				`tabSerial No`
+			SET 
+				sales_invoice='{sales_invoice}'
+			WHERE
+				name in ({serial_nos})
+			""".format(
+				sales_invoice=sales_invoice,
+				serial_nos=",".join(serial_nos)
+			)
+		)
\ No newline at end of file
diff --git a/erpnext/schools/doctype/course/course.js b/erpnext/schools/doctype/course/course.js
index f84c59f..c667eca 100644
--- a/erpnext/schools/doctype/course/course.js
+++ b/erpnext/schools/doctype/course/course.js
@@ -1,18 +1,30 @@
 frappe.ui.form.on("Course", "refresh", function(frm) {
 	if(!cur_frm.doc.__islocal) {
 		frm.add_custom_button(__("Program"), function() {
+			frappe.route_options = {
+				"Program Course.course": frm.doc.name
+			}
 			frappe.set_route("List", "Program");
 		});
 		
 		frm.add_custom_button(__("Student Group"), function() {
+			frappe.route_options = {
+				course: frm.doc.name
+			}
 			frappe.set_route("List", "Student Group");
 		});
 		
 		frm.add_custom_button(__("Course Schedule"), function() {
+			frappe.route_options = {
+				course: frm.doc.name
+			}
 			frappe.set_route("List", "Course Schedule");
 		});
 		
 		frm.add_custom_button(__("Assessment Plan"), function() {
+			frappe.route_options = {
+				course: frm.doc.name
+			}
 			frappe.set_route("List", "Assessment Plan");
 		});
 	}
diff --git a/erpnext/schools/doctype/program/program.js b/erpnext/schools/doctype/program/program.js
index cc09d0e..5146a19 100644
--- a/erpnext/schools/doctype/program/program.js
+++ b/erpnext/schools/doctype/program/program.js
@@ -6,22 +6,37 @@
 frappe.ui.form.on("Program", "refresh", function(frm) {
 	if(!frm.doc.__islocal) {
 		frm.add_custom_button(__("Student Applicant"), function() {
+			frappe.route_options = {
+				program: frm.doc.name
+			}
 			frappe.set_route("List", "Student Applicant");
 		});
 		
 		frm.add_custom_button(__("Program Enrollment"), function() {
+			frappe.route_options = {
+				program: frm.doc.name
+			}
 			frappe.set_route("List", "Program Enrollment");
 		});
 		
 		frm.add_custom_button(__("Student Group"), function() {
+			frappe.route_options = {
+				program: frm.doc.name
+			}
 			frappe.set_route("List", "Student Group");
 		});
 		
 		frm.add_custom_button(__("Fee Structure"), function() {
+			frappe.route_options = {
+				program: frm.doc.name
+			}
 			frappe.set_route("List", "Fee Structure");
 		});
 		
 		frm.add_custom_button(__("Fees"), function() {
+			frappe.route_options = {
+				program: frm.doc.name
+			}
 			frappe.set_route("List", "Fees");
 		});
 	}
diff --git a/erpnext/schools/doctype/student_attendance_tool/student_attendance_tool.js b/erpnext/schools/doctype/student_attendance_tool/student_attendance_tool.js
index 6f8c6cd..11a79e1 100644
--- a/erpnext/schools/doctype/student_attendance_tool/student_attendance_tool.js
+++ b/erpnext/schools/doctype/student_attendance_tool/student_attendance_tool.js
@@ -4,6 +4,12 @@
 
 frappe.ui.form.on('Student Attendance Tool', {
 	refresh: function(frm) {
+		if (frappe.route_options) {
+			frm.set_value("based_on", frappe.route_options.based_on);
+			frm.set_value("student_group", frappe.route_options.student_group);
+			frm.set_value("course_schedule", frappe.route_options.course_schedule);
+			frappe.route_options = null;
+		}
 		frm.disable_save();
 	},
 
diff --git a/erpnext/schools/doctype/student_group/student_group.js b/erpnext/schools/doctype/student_group/student_group.js
index ed94690..83fe094 100644
--- a/erpnext/schools/doctype/student_group/student_group.js
+++ b/erpnext/schools/doctype/student_group/student_group.js
@@ -13,11 +13,23 @@
 
 	refresh: function(frm) {
 		if (!frm.doc.__islocal) {
+			frm.add_custom_button(__("Attendance"), function() {
+				frappe.route_options = {
+					based_on: "Student Group",
+					student_group: frm.doc.name
+				}
+				frappe.set_route("List", "Student Attendance Tool");
+			});
 			frm.add_custom_button(__("Course Schedule"), function() {
+				frappe.route_options = {
+					student_group: frm.doc.name
+				}
 				frappe.set_route("List", "Course Schedule");
 			});
-
 			frm.add_custom_button(__("Assessment Plan"), function() {
+				frappe.route_options = {
+					student_group: frm.doc.name
+				}
 				frappe.set_route("List", "Assessment Plan");
 			});
 			frm.add_custom_button(__("Update Email Group"), function() {
@@ -30,6 +42,9 @@
 				});
 			});
 			frm.add_custom_button(__("Newsletter"), function() {
+				frappe.route_options = {
+					"Newsletter Email Group.email_group": frm.doc.name
+				}
 				frappe.set_route("List", "Newsletter");
 			});
 		}
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json
index c5efdf8..ed782ad 100644
--- a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json
+++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json
@@ -13,6 +13,7 @@
  "editable_grid": 0, 
  "fields": [
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -41,6 +42,67 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "column_break_2", 
+   "fieldtype": "Column Break", 
+   "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, 
+   "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, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "description": "Attachments can be shown without enabling the shopping cart", 
+   "fieldname": "show_attachments", 
+   "fieldtype": "Check", 
+   "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": "Show Public Attachments", 
+   "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, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -68,6 +130,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -97,6 +160,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -128,6 +192,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -157,6 +222,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -184,6 +250,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -214,6 +281,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -242,6 +310,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 1, 
@@ -272,6 +341,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -301,6 +371,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -333,6 +404,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -361,6 +433,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -402,7 +475,7 @@
  "issingle": 1, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2017-03-21 15:42:08.574497", 
+ "modified": "2017-05-19 09:31:38.078110", 
  "modified_by": "Administrator", 
  "module": "Shopping Cart", 
  "name": "Shopping Cart Settings", 
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py
index 4e24d2e..aa4f163 100644
--- a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py
+++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py
@@ -89,3 +89,7 @@
 	if not get_shopping_cart_settings().enabled:
 		frappe.throw(_("You need to enable Shopping Cart"), ShoppingCartSetupError)
 
+def show_attachments():
+        return get_shopping_cart_settings().show_attachments
+
+
diff --git a/erpnext/stock/doctype/serial_no/serial_no.json b/erpnext/stock/doctype/serial_no/serial_no.json
index 3b65ff8..b37713b 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.json
+++ b/erpnext/stock/doctype/serial_no/serial_no.json
@@ -1,5 +1,6 @@
 {
  "allow_copy": 0, 
+ "allow_guest_to_view": 0, 
  "allow_import": 1, 
  "allow_rename": 1, 
  "autoname": "field:serial_no", 
@@ -13,6 +14,7 @@
  "editable_grid": 0, 
  "fields": [
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -42,6 +44,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -69,6 +72,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -99,6 +103,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -130,6 +135,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -162,6 +168,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -189,6 +196,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -217,6 +225,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -248,6 +257,7 @@
    "width": "300px"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -280,6 +290,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -311,6 +322,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -339,6 +351,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -367,6 +380,7 @@
    "width": "50%"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -396,6 +410,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -425,6 +440,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -455,6 +471,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -483,6 +500,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -514,6 +532,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -542,6 +561,7 @@
    "width": "50%"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -571,6 +591,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 1, 
    "collapsible": 0, 
@@ -599,6 +620,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -628,6 +650,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -657,6 +680,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -686,6 +710,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -716,6 +741,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -744,6 +770,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -775,6 +802,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -803,6 +831,7 @@
    "width": "50%"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -834,6 +863,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 1, 
    "collapsible": 0, 
@@ -864,6 +894,68 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "invoice_details", 
+   "fieldtype": "Section Break", 
+   "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": "Invoice Details", 
+   "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, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "sales_invoice", 
+   "fieldtype": "Link", 
+   "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": "Sales Invoice", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Sales Invoice", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 1, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -892,6 +984,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -920,6 +1013,7 @@
    "width": "50%"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -952,6 +1046,7 @@
    "width": "150px"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -983,6 +1078,7 @@
    "width": "150px"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1011,6 +1107,7 @@
    "width": "50%"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1042,6 +1139,7 @@
    "width": "150px"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1073,6 +1171,7 @@
    "width": "150px"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1101,6 +1200,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1129,6 +1229,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1158,18 +1259,18 @@
    "unique": 0
   }
  ], 
+ "has_web_view": 0, 
  "hide_heading": 0, 
  "hide_toolbar": 0, 
  "icon": "fa fa-barcode", 
  "idx": 1, 
  "image_view": 0, 
  "in_create": 0, 
- "in_dialog": 0, 
  "is_submittable": 0, 
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2017-02-20 13:26:55.864960", 
+ "modified": "2017-05-15 18:22:23.685286", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Serial No", 
diff --git a/erpnext/templates/generators/item.html b/erpnext/templates/generators/item.html
index c0399a7..de54493 100644
--- a/erpnext/templates/generators/item.html
+++ b/erpnext/templates/generators/item.html
@@ -87,7 +87,7 @@
 				<table class="table borderless" style="width: 100%">
 				{% for d in website_specifications -%}
 					<tr>
-						<td class="uppercase text-muted" style="width: 30%;">{{ d.label }}</td>
+						<td class="text-muted" style="width: 30%;">{{ d.label }}</td>
 						<td>{{ d.description }}</td>
 					</tr>
 				{%- endfor %}
diff --git a/erpnext/templates/pages/order.html b/erpnext/templates/pages/order.html
index 7129178..da9eb33 100644
--- a/erpnext/templates/pages/order.html
+++ b/erpnext/templates/pages/order.html
@@ -86,6 +86,24 @@
 			{% endif %}
 		{% endif %}
 	</div>
+	
+{% if attachments %}
+<div class="order-item-table">
+	<div class="row order-items order-item-header text-muted">
+		<div class="col-sm-12 h6 text-uppercase">
+			{{ _("Attachments") }}
+		</div>
+	</div>
+	<div class="row order-items">
+		<div class="col-sm-12">
+			{% for attachment in attachments %}
+			<p class="small">
+				<a href="{{ attachment.file_url }}" target="blank"> {{ attachment.file_name }} </a>
+			</p>
+			{% endfor %}
+		</div>
+	</div>
 </div>
-
+{% endif %}
+</div>
 {% endblock %}
diff --git a/erpnext/templates/pages/order.py b/erpnext/templates/pages/order.py
index 296b907..b453c7e 100644
--- a/erpnext/templates/pages/order.py
+++ b/erpnext/templates/pages/order.py
@@ -5,6 +5,7 @@
 import frappe
 
 from frappe import _
+from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings import show_attachments
 
 def get_context(context):
 	context.no_cache = 1
@@ -13,6 +14,9 @@
 	if hasattr(context.doc, "set_indicator"):
 		context.doc.set_indicator()
 
+	if show_attachments():
+                context.attachments = get_attachments(frappe.form_dict.doctype, frappe.form_dict.name)
+
 	context.parents = frappe.form_dict.parents
 	context.payment_ref = frappe.db.get_value("Payment Request",
 		{"reference_name": frappe.form_dict.name}, "name")
@@ -21,3 +25,7 @@
 
 	if not frappe.has_website_permission(context.doc):
 		frappe.throw(_("Not Permitted"), frappe.PermissionError)
+
+def get_attachments(dt, dn):
+        return frappe.get_all("File", fields=["name", "file_name", "file_url", "is_private"],
+                              filters = {"attached_to_name": dn, "attached_to_doctype": dt, "is_private":0})