Merge pull request #12885 from netchampfaris/setup-progress-deadlock-fix

[deadlock fix] Save if not set
diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py
index 63db16c..20eb14b 100644
--- a/erpnext/accounts/doctype/sales_invoice/pos.py
+++ b/erpnext/accounts/doctype/sales_invoice/pos.py
@@ -2,23 +2,30 @@
 # License: GNU General Public License v3. See license.txt
 
 from __future__ import unicode_literals
-import frappe, json
-from frappe import _
-from frappe.utils import nowdate
-from erpnext.setup.utils import get_exchange_rate
-from frappe.core.doctype.communication.email import make
-from erpnext.stock.get_item_details import get_pos_profile
+
+import json
+
+import frappe
 from erpnext.accounts.party import get_party_account_currency
 from erpnext.controllers.accounts_controller import get_taxes_and_charges
+from erpnext.setup.utils import get_exchange_rate
+from erpnext.stock.get_item_details import get_pos_profile
+from frappe import _
+from frappe.core.doctype.communication.email import make
+from frappe.utils import nowdate
+
 
 @frappe.whitelist()
 def get_pos_data():
 	doc = frappe.new_doc('Sales Invoice')
-	doc.is_pos = 1;
+	doc.is_pos = 1
 	pos_profile = get_pos_profile(doc.company) or {}
 	if not pos_profile:
 		frappe.throw(_("POS Profile is required to use Point-of-Sale"))
-	if not doc.company: doc.company = pos_profile.get('company')
+
+	if not doc.company:
+		doc.company = pos_profile.get('company')
+
 	doc.update_stock = pos_profile.get('update_stock')
 
 	if pos_profile.get('name'):
@@ -30,18 +37,20 @@
 	update_multi_mode_option(doc, pos_profile)
 	default_print_format = pos_profile.get('print_format') or "Point of Sale"
 	print_template = frappe.db.get_value('Print Format', default_print_format, 'html')
+	items_list = get_items_list(pos_profile)
 	customers = get_customers_list(pos_profile)
 
 	return {
 		'doc': doc,
 		'default_customer': pos_profile.get('customer'),
-		'items': get_items_list(pos_profile),
+		'items': items_list,
 		'item_groups': get_item_groups(pos_profile),
 		'customers': customers,
 		'address': get_customers_address(customers),
 		'contacts': get_contacts(customers),
 		'serial_no_data': get_serial_no_data(pos_profile, doc.company),
 		'batch_no_data': get_batch_no_data(),
+		'barcode_data': get_barcode_data(items_list),
 		'tax_data': get_item_tax_data(),
 		'price_list_data': get_price_list_data(doc.selling_price_list),
 		'bin_data': get_bin_data(pos_profile),
@@ -51,20 +60,23 @@
 		'meta': get_meta()
 	}
 
+
 def get_meta():
 	doctype_meta = {
 		'customer': frappe.get_meta('Customer'),
 		'invoice': frappe.get_meta('Sales Invoice')
 	}
 
-	for row in frappe.get_all('DocField', fields = ['fieldname', 'options'],
-		filters = {'parent': 'Sales Invoice', 'fieldtype': 'Table'}):
+	for row in frappe.get_all('DocField', fields=['fieldname', 'options'],
+            filters={'parent': 'Sales Invoice', 'fieldtype': 'Table'}):
 		doctype_meta[row.fieldname] = frappe.get_meta(row.options)
 
 	return doctype_meta
 
+
 def get_company_data(company):
-	return frappe.get_all('Company', fields = ["*"], filters= {'name': company})[0]
+	return frappe.get_all('Company', fields=["*"], filters={'name': company})[0]
+
 
 def update_pos_profile_data(doc, pos_profile, company_data):
 	doc.campaign = pos_profile.get('campaign')
@@ -96,12 +108,14 @@
 	doc.terms = frappe.db.get_value('Terms and Conditions', pos_profile.get('tc_name'), 'terms') or doc.terms or ''
 	doc.offline_pos_name = ''
 
+
 def get_root(table):
 	root = frappe.db.sql(""" select name from `tab%(table)s` having
-		min(lft)"""%{'table': table}, as_dict=1)
+		min(lft)""" % {'table': table}, as_dict=1)
 
 	return root[0].name
 
+
 def update_multi_mode_option(doc, pos_profile):
 	from frappe.model import default_fields
 
@@ -123,15 +137,18 @@
 
 		doc.append('payments', payment_mode)
 
+
 def get_mode_of_payment(doc):
-	return frappe.db.sql(""" select mpa.default_account, mpa.parent, mp.type as type from `tabMode of Payment Account` mpa,
-		 `tabMode of Payment` mp where mpa.parent = mp.name and mpa.company = %(company)s""", {'company': doc.company}, as_dict=1)
+	return frappe.db.sql(""" select mpa.default_account, mpa.parent, mp.type as type from `tabMode of Payment Account` mpa, \
+			`tabMode of Payment` mp where mpa.parent = mp.name and mpa.company = %(company)s""", {'company': doc.company}, as_dict=1)
+
 
 def update_tax_table(doc):
 	taxes = get_taxes_and_charges('Sales Taxes and Charges Template', doc.taxes_and_charges)
 	for tax in taxes:
 		doc.append('taxes', tax)
 
+
 def get_items_list(pos_profile):
 	cond = "1=1"
 	item_groups = []
@@ -139,19 +156,20 @@
 		# Get items based on the item groups defined in the POS profile
 		for d in pos_profile.get('item_groups'):
 			item_groups.extend([d.name for d in get_child_nodes('Item Group', d.item_group)])
-		cond = "item_group in (%s)"%(', '.join(['%s']*len(item_groups)))
+		cond = "item_group in (%s)" % (', '.join(['%s'] * len(item_groups)))
 
-	return frappe.db.sql(""" 
+	return frappe.db.sql("""
 		select
 			name, item_code, item_name, description, item_group, expense_account, has_batch_no,
-			has_serial_no, expense_account, selling_cost_center, stock_uom, image, 
-			default_warehouse, is_stock_item, barcode, brand
+			has_serial_no, expense_account, selling_cost_center, stock_uom, image,
+			default_warehouse, is_stock_item, brand
 		from
 			tabItem
 		where
 			disabled = 0 and has_variants = 0 and is_sales_item = 1 and {cond}
 		""".format(cond=cond), tuple(item_groups), as_dict=1)
 
+
 def get_item_groups(pos_profile):
 	item_group_dict = {}
 	item_groups = frappe.db.sql("""Select name,
@@ -161,6 +179,7 @@
 		item_group_dict[data.name] = [data.lft, data.rgt]
 	return item_group_dict
 
+
 def get_customers_list(pos_profile={}):
 	cond = "1=1"
 	customer_groups = []
@@ -168,12 +187,13 @@
 		# Get customers based on the customer groups defined in the POS profile
 		for d in pos_profile.get('customer_groups'):
 			customer_groups.extend([d.name for d in get_child_nodes('Customer Group', d.customer_group)])
-		cond = "customer_group in (%s)"%(', '.join(['%s']*len(customer_groups)))
+		cond = "customer_group in (%s)" % (', '.join(['%s'] * len(customer_groups)))
 
 	return frappe.db.sql(""" select name, customer_name, customer_group,
 		territory, customer_pos_id from tabCustomer where disabled = 0
 		and {cond}""".format(cond=cond), tuple(customer_groups), as_dict=1) or {}
 
+
 def get_customers_address(customers):
 	customer_address = {}
 	if isinstance(customers, basestring):
@@ -185,33 +205,37 @@
 			(select parent from `tabDynamic Link` where link_doctype = 'Customer' and link_name = %s
 			and parenttype = 'Address')""", data.name, as_dict=1)
 		address_data = {}
-		if address: address_data = address[0]
+		if address:
+			address_data = address[0]
 
 		address_data.update({'full_name': data.customer_name, 'customer_pos_id': data.customer_pos_id})
 		customer_address[data.name] = address_data
 
 	return customer_address
 
+
 def get_contacts(customers):
 	customer_contact = {}
 	if isinstance(customers, basestring):
 		customers = [frappe._dict({'name': customers})]
 
 	for data in customers:
-		contact = frappe.db.sql(""" select email_id, phone, mobile_no from `tabContact` 
+		contact = frappe.db.sql(""" select email_id, phone, mobile_no from `tabContact`
 			where is_primary_contact =1 and name in
 			(select parent from `tabDynamic Link` where link_doctype = 'Customer' and link_name = %s
 			and parenttype = 'Contact')""", data.name, as_dict=1)
-		if contact: 
+		if contact:
 			customer_contact[data.name] = contact[0]
 
 	return customer_contact
 
+
 def get_child_nodes(group_type, root):
 	lft, rgt = frappe.db.get_value(group_type, root, ["lft", "rgt"])
 	return frappe.db.sql(""" Select name, lft, rgt from `tab{tab}` where
 			lft >= {lft} and rgt <= {rgt} order by lft""".format(tab=group_type, lft=lft, rgt=rgt), as_dict=1)
 
+
 def get_serial_no_data(pos_profile, company):
 	# get itemwise serial no data
 	# example {'Nokia Lumia 1020': {'SN0001': 'Pune'}}
@@ -232,6 +256,7 @@
 
 	return itemwise_serial_no
 
+
 def get_batch_no_data():
 	# get itemwise batch no data
 	# exmaple: {'LED-GRE': [Batch001, Batch002]}
@@ -248,6 +273,26 @@
 
 	return itemwise_batch
 
+
+def get_barcode_data(items_list):
+	# get itemwise batch no data
+	# exmaple: {'LED-GRE': [Batch001, Batch002]}
+	# where LED-GRE is item code, SN0001 is serial no and Pune is warehouse
+
+	itemwise_barcode = {}
+	for item in items_list:
+		barcodes = frappe.db.sql("""
+		select barcode from `tabItem Barcode` where parent = '{0}'
+		""".format(item.item_code), as_dict=1)
+
+		for barcode in barcodes:
+			if item.item_code not in itemwise_barcode:
+				itemwise_barcode.setdefault(item.item_code, [])
+			itemwise_barcode[item.item_code].append(barcode)
+
+	return itemwise_barcode
+
+
 def get_item_tax_data():
 	# get default tax of an item
 	# example: {'Consulting Services': {'Excise 12 - TS': '12.000'}}
@@ -262,17 +307,19 @@
 
 	return itemwise_tax
 
+
 def get_price_list_data(selling_price_list):
 	itemwise_price_list = {}
 	price_lists = frappe.db.sql("""Select ifnull(price_list_rate, 0) as price_list_rate,
 		item_code from `tabItem Price` ip where price_list = %(price_list)s""",
-		{'price_list': selling_price_list}, as_dict=1)
+        {'price_list': selling_price_list}, as_dict=1)
 
 	for item in price_lists:
 		itemwise_price_list[item.item_code] = item.price_list_rate
 
 	return itemwise_price_list
 
+
 def get_bin_data(pos_profile):
 	itemwise_bin_data = {}
 	cond = "1=1"
@@ -289,6 +336,7 @@
 
 	return itemwise_bin_data
 
+
 def get_pricing_rule_data(doc):
 	pricing_rules = ""
 	if doc.ignore_pricing_rule == 0:
@@ -297,9 +345,10 @@
 						and ifnull(company, '') in (%(company)s, '') and disable = 0 and %(date)s
 						between ifnull(valid_from, '2000-01-01') and ifnull(valid_upto, '2500-12-31')
 						order by priority desc, name desc""",
-						{'company': doc.company, 'price_list': doc.selling_price_list, 'date': nowdate()}, as_dict=1)
+                        {'company': doc.company, 'price_list': doc.selling_price_list, 'date': nowdate()}, as_dict=1)
 	return pricing_rules
 
+
 @frappe.whitelist()
 def make_invoice(doc_list={}, email_queue_list={}, customers_list={}):
 	if isinstance(doc_list, basestring):
@@ -338,14 +387,15 @@
 		'synced_contacts': get_contacts(customers)
 	}
 
+
 def validate_records(doc):
 	validate_item(doc)
 
+
 def get_customer_id(doc, customer=None):
 	cust_id = None
 	if doc.get('customer_pos_id'):
-		cust_id = frappe.db.get_value('Customer',
-			{'customer_pos_id': doc.get('customer_pos_id')}, 'name')
+		cust_id = frappe.db.get_value('Customer',{'customer_pos_id': doc.get('customer_pos_id')}, 'name')
 
 	if not cust_id:
 		customer = customer or doc.get('customer')
@@ -356,6 +406,7 @@
 
 	return cust_id
 
+
 def make_customer_and_address(customers):
 	customers_list = []
 	for customer, data in customers.items():
@@ -372,6 +423,7 @@
 	frappe.db.commit()
 	return customers_list
 
+
 def add_customer(data):
 	customer_doc = frappe.new_doc('Customer')
 	customer_doc.customer_name = data.get('full_name') or data.get('customer')
@@ -380,28 +432,29 @@
 	customer_doc.customer_group = get_customer_group(data)
 	customer_doc.territory = get_territory(data)
 	customer_doc.flags.ignore_mandatory = True
-	customer_doc.save(ignore_permissions = True)
+	customer_doc.save(ignore_permissions=True)
 	frappe.db.commit()
 	return customer_doc.name
 
+
 def get_territory(data):
 	if data.get('territory'):
 		return data.get('territory')
 
-	return frappe.db.get_single_value('Selling Settings',
-		'territory') or _('All Territories')
+	return frappe.db.get_single_value('Selling Settings','territory') or _('All Territories')
+
 
 def get_customer_group(data):
 	if data.get('customer_group'):
 		return data.get('customer_group')
 
-	return frappe.db.get_single_value('Selling Settings',
-		'customer_group') or frappe.db.get_value('Customer Group', {'is_group': 0}, 'name')
+	return frappe.db.get_single_value('Selling Settings', 'customer_group') or frappe.db.get_value('Customer Group', {'is_group': 0}, 'name')
 
-def make_contact(args,customer):
+
+def make_contact(args, customer):
 	if args.get('email_id') or args.get('phone'):
 		name = frappe.db.get_value('Dynamic Link',
-			{'link_doctype': 'Customer', 'link_name': customer, 'parenttype': 'Contact'}, 'parent')
+            	{'link_doctype': 'Customer', 'link_name': customer, 'parenttype': 'Contact'}, 'parent')
 
 		args = {
 			'first_name': args.get('full_name'),
@@ -416,16 +469,18 @@
 		doc.update(args)
 		doc.is_primary_contact = 1
 		if not name:
-			doc.append('links',{
+			doc.append('links', {
 				'link_doctype': 'Customer',
 				'link_name': customer
 			})
 		doc.flags.ignore_mandatory = True
 		doc.save(ignore_permissions=True)
 
+
 def make_address(args, customer):
-	if not args.get('address_line1'): return
-	
+	if not args.get('address_line1'):
+		return
+
 	name = args.get('name')
 
 	if not name:
@@ -437,7 +492,7 @@
 	else:
 		address = frappe.new_doc('Address')
 		address.country = frappe.db.get_value('Company', args.get('company'), 'country')
-		address.append('links',{
+		address.append('links', {
 			'link_doctype': 'Customer',
 			'link_name': customer
 		})
@@ -446,7 +501,8 @@
 	address.is_shipping_address = 1
 	address.update(args)
 	address.flags.ignore_mandatory = True
-	address.save(ignore_permissions = True)
+	address.save(ignore_permissions=True)
+
 
 def make_email_queue(email_queue):
 	name_list = []
@@ -455,15 +511,16 @@
 		data = json.loads(data)
 		sender = frappe.session.user
 		print_format = "POS Invoice"
-		attachments = [frappe.attach_print('Sales Invoice', name, print_format= print_format)]
+		attachments = [frappe.attach_print('Sales Invoice', name, print_format=print_format)]
 
-		make(subject = data.get('subject'), content = data.get('content'), recipients = data.get('recipients'),
-			sender=sender,attachments = attachments, send_email=True,
-			doctype='Sales Invoice', name=name)
+		make(subject=data.get('subject'), content=data.get('content'), recipients=data.get('recipients'),
+                    sender=sender, attachments=attachments, send_email=True,
+                    doctype='Sales Invoice', name=name)
 		name_list.append(key)
 
 	return name_list
 
+
 def validate_item(doc):
 	for item in doc.get('items'):
 		if not frappe.db.exists('Item', item.get('item_code')):
@@ -486,13 +543,15 @@
 		frappe.db.commit()
 		name_list.append(name)
 	except Exception as e:
-		if frappe.message_log: frappe.message_log.pop()
+		if frappe.message_log:
+			frappe.message_log.pop()
 		frappe.db.rollback()
 		frappe.log_error(frappe.get_traceback())
 		name_list = save_invoice(doc, name, name_list)
 
 	return name_list
 
+
 def save_invoice(doc, name, name_list):
 	try:
 		if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js
index ab32d9f..ccb5553 100644
--- a/erpnext/accounts/page/pos/pos.js
+++ b/erpnext/accounts/page/pos/pos.js
@@ -301,6 +301,7 @@
 		this.customers = r.message.customers;
 		this.serial_no_data = r.message.serial_no_data;
 		this.batch_no_data = r.message.batch_no_data;
+		this.barcode_data = r.message.barcode_data;
 		this.tax_data = r.message.tax_data;
 		this.contacts = r.message.contacts;
 		this.address = r.message.address || {};
@@ -415,7 +416,7 @@
 		});
 
 		this.serach_item.make_input();
-		
+
 		this.serach_item.$input.on("keypress", function (event) {
 
 			clearTimeout(me.last_search_timeout);
@@ -423,7 +424,7 @@
 				if((me.serach_item.$input.val() != "") || (event.which == 13)) {
 					me.items = me.get_items();
 					me.make_item_list();
-				}				
+				}
 			}, 400);
 		});
 
@@ -1110,9 +1111,9 @@
 						search_status = false;
 						me.item_serial_no[item.item_code] = [me.serach_item.$input.val(), me.serial_no_data[item.item_code][me.serach_item.$input.val()]]
 						return true
-					} else if (item.barcode == me.serach_item.$input.val()) {
+					} else if (in_list(me.barcode_data[item.item_code], me.serach_item.$input.val())) {
 						search_status = false;
-						return item.barcode == me.serach_item.$input.val();
+						return true;
 					} else if (reg.test(item.item_code.toLowerCase()) || (item.description && reg.test(item.description.toLowerCase())) ||
 						reg.test(item.item_name.toLowerCase()) || reg.test(item.item_group.toLowerCase())) {
 						return true
@@ -1526,8 +1527,8 @@
 				me.print_document(html)
 			})
 		}
-		
-		if (this.frm.doc.docstatus == 1) {	
+
+		if (this.frm.doc.docstatus == 1) {
 			this.page.add_menu_item(__("Email"), function () {
 				me.email_prompt()
 			})
diff --git a/erpnext/accounts/report/balance_sheet/balance_sheet.js b/erpnext/accounts/report/balance_sheet/balance_sheet.js
index 760fa64..f22f3a1 100644
--- a/erpnext/accounts/report/balance_sheet/balance_sheet.js
+++ b/erpnext/accounts/report/balance_sheet/balance_sheet.js
@@ -11,5 +11,3 @@
 		"default": 1
 	});
 });
-
-
diff --git a/erpnext/accounts/report/cash_flow/cash_flow.js b/erpnext/accounts/report/cash_flow/cash_flow.js
index 455664f..391f57b 100644
--- a/erpnext/accounts/report/cash_flow/cash_flow.js
+++ b/erpnext/accounts/report/cash_flow/cash_flow.js
@@ -5,6 +5,11 @@
 	frappe.query_reports["Cash Flow"] = $.extend({},
 		erpnext.financial_statements);
 
+	// The last item in the array is the definition for Presentation Currency
+	// filter. It won't be used in cash flow for now so we pop it. Please take
+	// of this if you are working here.
+	frappe.query_reports["Cash Flow"]["filters"].pop();
+
 	frappe.query_reports["Cash Flow"]["filters"].push({
 		"fieldname": "accumulated_values",
 		"label": __("Accumulated Values"),
diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py
index b0c49df..5d2a35b 100644
--- a/erpnext/accounts/report/financial_statements.py
+++ b/erpnext/accounts/report/financial_statements.py
@@ -2,12 +2,14 @@
 # License: GNU General Public License v3. See license.txt
 
 from __future__ import unicode_literals
-import frappe
+
 import re
-from frappe import _
-from frappe.utils import (flt, getdate, get_first_day, get_last_day, date_diff,
-	add_months, add_days, formatdate, cint)
+
+import frappe
+from erpnext.accounts.report.utils import get_currency, convert_to_presentation_currency
 from erpnext.accounts.utils import get_fiscal_year
+from frappe import _
+from frappe.utils import (flt, getdate, get_first_day, add_months, add_days, formatdate)
 
 
 def get_period_list(from_fiscal_year, to_fiscal_year, periodicity, accumulated_values=False,
@@ -84,6 +86,7 @@
 
 	return period_list
 
+
 def get_fiscal_year_data(from_fiscal_year, to_fiscal_year):
 	fiscal_year = frappe.db.sql("""select min(year_start_date) as year_start_date,
 		max(year_end_date) as year_end_date from `tabFiscal Year` where
@@ -92,16 +95,19 @@
 
 	return fiscal_year[0] if fiscal_year else {}
 
+
 def validate_fiscal_year(fiscal_year, from_fiscal_year, to_fiscal_year):
 	if not fiscal_year.get('year_start_date') and not fiscal_year.get('year_end_date'):
 		frappe.throw(_("End Year cannot be before Start Year"))
 
+
 def get_months(start_date, end_date):
 	diff = (12 * end_date.year + end_date.month) - (12 * start_date.year + start_date.month)
 	return diff + 1
 
+
 def get_label(periodicity, from_date, to_date):
-	if periodicity=="Yearly":
+	if periodicity == "Yearly":
 		if formatdate(from_date, "YYYY") == formatdate(to_date, "YYYY"):
 			label = formatdate(from_date, "YYYY")
 		else:
@@ -111,28 +117,34 @@
 
 	return label
 
-def get_data(company, root_type, balance_must_be, period_list, filters=None,
+
+def get_data(
+		company, root_type, balance_must_be, period_list, filters=None,
 		accumulated_values=1, only_current_fiscal_year=True, ignore_closing_entries=False,
 		ignore_accumulated_values_for_fy=False):
+
 	accounts = get_accounts(company, root_type)
 	if not accounts:
 		return None
 
 	accounts, accounts_by_name, parent_children_map = filter_accounts(accounts)
 
-	company_currency = frappe.db.get_value("Company", company, "default_currency")
+	company_currency = get_appropriate_currency(company, filters)
 
 	gl_entries_by_account = {}
 	for root in frappe.db.sql("""select lft, rgt from tabAccount
 			where root_type=%s and ifnull(parent_account, '') = ''""", root_type, as_dict=1):
 
-		set_gl_entries_by_account(company,
+		set_gl_entries_by_account(
+			company,
 			period_list[0]["year_start_date"] if only_current_fiscal_year else None,
 			period_list[-1]["to_date"],
 			root.lft, root.rgt, filters,
-			gl_entries_by_account, ignore_closing_entries=ignore_closing_entries)
+			gl_entries_by_account, ignore_closing_entries=ignore_closing_entries
+		)
 
-	calculate_values(accounts_by_name, gl_entries_by_account, period_list, accumulated_values, ignore_accumulated_values_for_fy)
+	calculate_values(
+		accounts_by_name, gl_entries_by_account, period_list, accumulated_values, ignore_accumulated_values_for_fy)
 	accumulate_values_into_parents(accounts, accounts_by_name, period_list, accumulated_values)
 	out = prepare_data(accounts, balance_must_be, period_list, company_currency)
 	out = filter_out_zero_value_rows(out, parent_children_map)
@@ -143,7 +155,15 @@
 	return out
 
 
-def calculate_values(accounts_by_name, gl_entries_by_account, period_list, accumulated_values, ignore_accumulated_values_for_fy):
+def get_appropriate_currency(company, filters=None):
+	if filters and filters.get("presentation_currency"):
+		return filters["presentation_currency"]
+	else:
+		return frappe.db.get_value("Company", company, "default_currency")
+
+
+def calculate_values(
+		accounts_by_name, gl_entries_by_account, period_list, accumulated_values, ignore_accumulated_values_for_fy):
 	for entries in gl_entries_by_account.values():
 		for entry in entries:
 			d = accounts_by_name.get(entry.account)
@@ -164,6 +184,7 @@
 			if entry.posting_date < period_list[0].year_start_date:
 				d["opening_balance"] = d.get("opening_balance", 0.0) + flt(entry.debit) - flt(entry.credit)
 
+
 def accumulate_values_into_parents(accounts, accounts_by_name, period_list, accumulated_values):
 	"""accumulate children's values in parent accounts"""
 	for d in reversed(accounts):
@@ -175,6 +196,7 @@
 			accounts_by_name[d.parent_account]["opening_balance"] = \
 				accounts_by_name[d.parent_account].get("opening_balance", 0.0) + d.get("opening_balance", 0.0)
 
+
 def prepare_data(accounts, balance_must_be, period_list, company_currency):
 	data = []
 	year_start_date = period_list[0]["year_start_date"].strftime("%Y-%m-%d")
@@ -192,10 +214,10 @@
 			"year_start_date": year_start_date,
 			"year_end_date": year_end_date,
 			"currency": company_currency,
-			"opening_balance": d.get("opening_balance", 0.0) * (1 if balance_must_be=="Debit" else -1)
+			"opening_balance": d.get("opening_balance", 0.0) * (1 if balance_must_be == "Debit" else -1)
 		})
 		for period in period_list:
-			if d.get(period.key) and balance_must_be=="Credit":
+			if d.get(period.key) and balance_must_be == "Credit":
 				# change sign based on Debit or Credit, since calculation is done using (debit - credit)
 				d[period.key] *= -1
 
@@ -212,6 +234,7 @@
 
 	return data
 
+
 def filter_out_zero_value_rows(data, parent_children_map, show_zero_values=False):
 	data_with_value = []
 	for d in data:
@@ -228,6 +251,7 @@
 
 	return data_with_value
 
+
 def add_total_row(out, root_type, balance_must_be, period_list, company_currency):
 	total_row = {
 		"account_name": "'" + _("Total {0} ({1})").format(_(root_type), _(balance_must_be)) + "'",
@@ -246,16 +270,19 @@
 			total_row["total"] += flt(row["total"])
 			row["total"] = ""
 
-	if total_row.has_key("total"):
+	if "total" in total_row:
 		out.append(total_row)
 
 		# blank row after Total
 		out.append({})
 
+
 def get_accounts(company, root_type):
-	return frappe.db.sql("""select name, parent_account, lft, rgt, root_type, report_type, account_name from `tabAccount`
+	return frappe.db.sql(
+		"""select name, parent_account, lft, rgt, root_type, report_type, account_name from `tabAccount`
 		where company=%s and root_type=%s order by lft""", (company, root_type), as_dict=True)
 
+
 def filter_accounts(accounts, depth=10):
 	parent_children_map = {}
 	accounts_by_name = {}
@@ -280,6 +307,7 @@
 
 	return filtered_accounts, accounts_by_name, parent_children_map
 
+
 def sort_root_accounts(roots):
 	"""Sort root types as Asset, Liability, Equity, Income, Expense"""
 
@@ -299,13 +327,14 @@
 
 	roots.sort(compare_roots)
 
-def set_gl_entries_by_account(company, from_date, to_date, root_lft, root_rgt, filters, gl_entries_by_account,
-		ignore_closing_entries=False):
+
+def set_gl_entries_by_account(
+		company, from_date, to_date, root_lft, root_rgt, filters, gl_entries_by_account, ignore_closing_entries=False):
 	"""Returns a dict like { "account": [gl entries], ... }"""
 
 	additional_conditions = get_additional_conditions(from_date, ignore_closing_entries, filters)
 
-	gl_entries = frappe.db.sql("""select posting_date, account, debit, credit, is_opening, fiscal_year from `tabGL Entry`
+	gl_entries = frappe.db.sql("""select posting_date, account, debit, credit, is_opening, fiscal_year, debit_in_account_currency, credit_in_account_currency, account_currency from `tabGL Entry`
 		where company=%(company)s
 		{additional_conditions}
 		and posting_date <= %(to_date)s
@@ -321,11 +350,15 @@
 		},
 		as_dict=True)
 
+	if filters and filters.get('presentation_currency'):
+		convert_to_presentation_currency(gl_entries, get_currency(filters))
+
 	for entry in gl_entries:
 		gl_entries_by_account.setdefault(entry.account, []).append(entry)
 
 	return gl_entries_by_account
 
+
 def get_additional_conditions(from_date, ignore_closing_entries, filters):
 	additional_conditions = []
 
@@ -337,15 +370,17 @@
 
 	if filters:
 		if filters.get("project"):
-			additional_conditions.append("project = '%s'"%(frappe.db.escape(filters.get("project"))))
+			additional_conditions.append("project = '%s'" % (frappe.db.escape(filters.get("project"))))
 		if filters.get("cost_center"):
 			additional_conditions.append(get_cost_center_cond(filters.get("cost_center")))
 
 	return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else ""
 
+
 def get_cost_center_cond(cost_center):
 	lft, rgt = frappe.db.get_value("Cost Center", cost_center, ["lft", "rgt"])
-	return (""" cost_center in (select name from `tabCost Center` where lft >=%s and rgt <=%s)"""%(lft, rgt))
+	return """ cost_center in (select name from `tabCost Center` where lft >=%s and rgt <=%s)""" % (lft, rgt)
+
 
 def get_columns(periodicity, period_list, accumulated_values=1, company=None):
 	columns = [{
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.html b/erpnext/accounts/report/general_ledger/general_ledger.html
index 9e1b884..5cfdc9f 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.html
+++ b/erpnext/accounts/report/general_ledger/general_ledger.html
@@ -44,44 +44,24 @@
 						<br>{%= __("Supplier Invoice No") %}: {%= data[i].bill_no %}
 					{% } %}
 					</td>
-				{% if(filters.print_in_account_currency) { %}
 					<td style="text-align: right">
-						{%= format_currency(data[i].debit_in_account_currency, data[i].account_currency) %}
-					</td>
+						{%= format_currency(data[i].debit, filters.presentation_currency) %}</td>
 					<td style="text-align: right">
-						{%= format_currency(data[i].credit_in_account_currency, data[i].account_currency) %}
-					</td>
-				{% } else { %}
-					<td style="text-align: right">
-						{%= format_currency(data[i].debit) %}</td>
-					<td style="text-align: right">
-						{%= format_currency(data[i].credit) %}</td>
-				{% } %}
+						{%= format_currency(data[i].credit, filters.presentation_currency) %}</td>
 			{% } else { %}
 				<td></td>
 				<td></td>
 				<td><b>{%= frappe.format(data[i].account, {fieldtype: "Link"}) || "&nbsp;" %}</b></td>
-				{% if(filters.print_in_account_currency) { %}
-					<td style="text-align: right">
-						{%= data[i].account && format_currency(data[i].debit_in_account_currency, data[i].account_currency) %}</td>
-					<td style="text-align: right">
-						{%= data[i].account && format_currency(data[i].credit_in_account_currency, data[i].account_currency) %}</td>
-				{% } else { %}
-					<td style="text-align: right">
-						{%= data[i].account && format_currency(data[i].debit) %}
-					</td>
-					<td style="text-align: right">
-						{%= data[i].account && format_currency(data[i].credit) %}
-					</td>
-				{% } %}
-			{% } %}
-			{% if(filters.print_in_account_currency) { %}
 				<td style="text-align: right">
-					{%= format_currency(data[i].balance_in_account_currency, data[i].account_currency) %}
+					{%= data[i].account && format_currency(data[i].debit, filters.presentation_currency) %}
 				</td>
-			{% } else { %}
-				<td style="text-align: right">{%= format_currency(data[i].balance) %}</td>
-			{% } %}
+				<td style="text-align: right">
+					{%= data[i].account && format_currency(data[i].credit, filters.presentation_currency) %}
+				</td>
+			{% } %}			
+				<td style="text-align: right">
+					{%= format_currency(data[i].balance, filters.presentation_currency) %}
+				</td>
 			</tr>
 		{% } %}
 	</tbody>
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js
index adefadd..d6a2aec 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.js
+++ b/erpnext/accounts/report/general_ledger/general_ledger.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
 // License: GNU General Public License v3. See license.txt
 
 frappe.query_reports["General Ledger"] = {
@@ -107,9 +107,10 @@
 			"fieldtype": "Check",
 		},
 		{
-			"fieldname":"print_in_account_currency",
-			"label": __("Print in Account Currency"),
-			"fieldtype": "Check",
+			"fieldname": "presentation_currency",
+			"label": __("Currency"),
+			"fieldtype": "Select",
+			"options": erpnext.get_presentation_currency_list()
 		}
 	]
 }
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py
index 8e4259c..70ab67f 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/general_ledger.py
@@ -3,10 +3,13 @@
 
 from __future__ import unicode_literals
 import frappe
+from erpnext import get_company_currency, get_default_company
+from erpnext.accounts.report.utils import get_currency, convert_to_presentation_currency
 from frappe.utils import getdate, cstr, flt, fmt_money
 from frappe import _, _dict
 from erpnext.accounts.utils import get_account_currency
 
+
 def execute(filters=None):
 	account_details = {}
 
@@ -29,6 +32,7 @@
 
 	return columns, res
 
+
 def validate_filters(filters, account_details):
 	if not filters.get('company'):
 		frappe.throw(_('{0} is mandatory').format(_('Company')))
@@ -37,7 +41,7 @@
 		frappe.throw(_("Account {0} does not exists").format(filters.account))
 
 	if filters.get("account") and filters.get("group_by_account") \
-			and account_details[filters.account].is_group == 0:
+		and account_details[filters.account].is_group == 0:
 		frappe.throw(_("Can not filter based on Account, if grouped by Account"))
 
 	if filters.get("voucher_no") and filters.get("group_by_voucher"):
@@ -56,6 +60,7 @@
 		elif not frappe.db.exists(party_type, party):
 			frappe.throw(_("Invalid {0}: {1}").format(party_type, party))
 
+
 def set_account_currency(filters):
 	if not (filters.get("account") or filters.get("party")):
 		return filters
@@ -66,8 +71,13 @@
 		if filters.get("account"):
 			account_currency = get_account_currency(filters.account)
 		elif filters.get("party"):
-			gle_currency = frappe.db.get_value("GL Entry", {"party_type": filters.party_type,
-				"party": filters.party, "company": filters.company}, "account_currency")
+			gle_currency = frappe.db.get_value(
+				"GL Entry", {
+					"party_type": filters.party_type, "party": filters.party, "company": filters.company
+				},
+				"account_currency"
+			)
+
 			if gle_currency:
 				account_currency = gle_currency
 			else:
@@ -90,29 +100,39 @@
 
 	return result
 
+
 def get_gl_entries(filters):
+	currency_map = get_currency(filters)
 	select_fields = """, sum(debit_in_account_currency) as debit_in_account_currency,
 		sum(credit_in_account_currency) as credit_in_account_currency""" \
-		if filters.get("show_in_account_currency") else ""
+
 
 	group_by_condition = "group by voucher_type, voucher_no, account, cost_center" \
 		if filters.get("group_by_voucher") else "group by name"
 
-	gl_entries = frappe.db.sql("""
+	gl_entries = frappe.db.sql(
+		"""
 		select
 			posting_date, account, party_type, party,
 			sum(debit) as debit, sum(credit) as credit,
 			voucher_type, voucher_no, cost_center, project,
-			against_voucher_type, against_voucher,
+			against_voucher_type, against_voucher, account_currency,
 			remarks, against, is_opening {select_fields}
 		from `tabGL Entry`
 		where company=%(company)s {conditions}
 		{group_by_condition}
-		order by posting_date, account"""\
-		.format(select_fields=select_fields, conditions=get_conditions(filters),
-			group_by_condition=group_by_condition), filters, as_dict=1)
+		order by posting_date, account
+		""".format(
+			select_fields=select_fields, conditions=get_conditions(filters),
+			group_by_condition=group_by_condition
+		),
+		filters, as_dict=1)
 
-	return gl_entries
+	if filters.get('presentation_currency'):
+		return convert_to_presentation_currency(gl_entries, currency_map)
+	else:
+		return gl_entries
+
 
 def get_conditions(filters):
 	conditions = []
@@ -132,16 +152,20 @@
 
 	if not (filters.get("account") or filters.get("party") or filters.get("group_by_account")):
 		conditions.append("posting_date >=%(from_date)s")
+		conditions.append("posting_date <=%(to_date)s")
 
 	if filters.get("project"):
 		conditions.append("project=%(project)s")
 
 	from frappe.desk.reportview import build_match_conditions
 	match_conditions = build_match_conditions("GL Entry")
-	if match_conditions: conditions.append(match_conditions)
+
+	if match_conditions:
+		conditions.append(match_conditions)
 
 	return "and {}".format(" and ".join(conditions)) if conditions else ""
 
+
 def get_data_with_opening_closing(filters, account_details, gl_entries):
 	data = []
 	gle_map = initialize_gle_map(gl_entries)
@@ -178,14 +202,15 @@
 
 	return data
 
+
 def get_totals_dict():
 	def _get_debit_credit_dict(label):
 		return _dict(
-			account = "'{0}'".format(label),
-			debit = 0.0,
-			credit = 0.0,
-			debit_in_account_currency = 0.0,
-			credit_in_account_currency = 0.0
+			account="'{0}'".format(label),
+			debit=0.0,
+			credit=0.0,
+			debit_in_account_currency=0.0,
+			credit_in_account_currency=0.0
 		)
 	return _dict(
 		opening = _get_debit_credit_dict(_('Opening')),
@@ -193,12 +218,14 @@
 		closing = _get_debit_credit_dict(_('Closing (Opening + Total)'))
 	)
 
+
 def initialize_gle_map(gl_entries):
 	gle_map = frappe._dict()
 	for gle in gl_entries:
-		gle_map.setdefault(gle.account, _dict(totals = get_totals_dict(), entries = []))
+		gle_map.setdefault(gle.account, _dict(totals=get_totals_dict(), entries=[]))
 	return gle_map
 
+
 def get_accountwise_gle(filters, gl_entries, gle_map):
 	totals = get_totals_dict()
 	entries = []
@@ -210,13 +237,12 @@
 		data[key].debit_in_account_currency += flt(gle.debit_in_account_currency)
 		data[key].credit_in_account_currency += flt(gle.credit_in_account_currency)
 
-
 	from_date, to_date = getdate(filters.from_date), getdate(filters.to_date)
 	for gle in gl_entries:
 		if gle.posting_date < from_date or cstr(gle.is_opening) == "Yes":
 			update_value_in_dict(gle_map[gle.account].totals, 'opening', gle)
 			update_value_in_dict(totals, 'opening', gle)
-			
+
 			update_value_in_dict(gle_map[gle.account].totals, 'closing', gle)
 			update_value_in_dict(totals, 'closing', gle)
 
@@ -233,6 +259,7 @@
 
 	return totals, entries
 
+
 def get_result_as_list(data, filters):
 	balance, balance_in_account_currency = 0, 0
 	inv_details = get_supplier_invoice_details()
@@ -272,6 +299,15 @@
 	return balance
 
 def get_columns(filters):
+	if filters.get("presentation_currency"):
+		currency = filters["presentation_currency"]
+	else:
+		if filters.get("company"):
+			currency = get_company_currency(filters["company"])
+		else:
+			company = get_default_company()
+			currency = get_company_currency(company)
+
 	columns = [
 		{
 			"label": _("Posting Date"),
@@ -287,47 +323,25 @@
 			"width": 180
 		},
 		{
-			"label": _("Debit"),
+			"label": _("Debit ({0})".format(currency)),
 			"fieldname": "debit",
 			"fieldtype": "Float",
 			"width": 100
 		},
 		{
-			"label": _("Credit"),
+			"label": _("Credit ({0})".format(currency)),
 			"fieldname": "credit",
 			"fieldtype": "Float",
 			"width": 100
 		},
 		{
-			"label": _("Balance (Dr - Cr)"),
+			"label": _("Balance ({0})".format(currency)),
 			"fieldname": "balance",
 			"fieldtype": "Float",
 			"width": 130
 		}
 	]
 
-	if filters.get("show_in_account_currency"):
-		columns.extend([
-			{
-				"label": _("Debit") + " (" + filters.account_currency + ")",
-				"fieldname": "debit_in_account_currency",
-				"fieldtype": "Float",
-				"width": 100
-			},
-			{
-				"label": _("Credit") + " (" + filters.account_currency + ")",
-				"fieldname": "credit_in_account_currency",
-				"fieldtype": "Float",
-				"width": 100
-			},
-			{
-				"label": _("Balance") + " (" + filters.account_currency + ")",
-				"fieldname": "balance_in_account_currency",
-				"fieldtype": "Data",
-				"width": 100
-			}
-		])
-
 	columns.extend([
 		{
 			"label": _("Voucher Type"),
diff --git a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js
index bcac2df..a02c592 100644
--- a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js
+++ b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.js
@@ -1,6 +1,7 @@
 // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
 // License: GNU General Public License v3. See license.txt
 
+
 frappe.require("assets/erpnext/js/financial_statements.js", function() {
 	frappe.query_reports["Profit and Loss Statement"] = $.extend({},
 		erpnext.financial_statements);
@@ -24,4 +25,4 @@
 			"fieldtype": "Check"
 		}
 	);
-});
\ No newline at end of file
+});
diff --git a/erpnext/accounts/report/utils.py b/erpnext/accounts/report/utils.py
new file mode 100644
index 0000000..4490398
--- /dev/null
+++ b/erpnext/accounts/report/utils.py
@@ -0,0 +1,128 @@
+import frappe
+from erpnext import get_company_currency, get_default_company
+from erpnext.setup.utils import get_exchange_rate
+from frappe.utils import cint
+
+__exchange_rates = {}
+P_OR_L_ACCOUNTS = list(
+	sum(frappe.get_list('Account', fields=['name'], or_filters=[{'root_type': 'Income'}, {'root_type': 'Expense'}], as_list=True), ())
+)
+
+
+def get_currency(filters):
+	"""
+	Returns a dictionary containing currency information. The keys of the dict are
+	- company: The company for which we are fetching currency information. if no
+	company is specified, it will fallback to the default company.
+	- company currency: The functional currency of the said company.
+	- presentation currency: The presentation currency to use. Only currencies that
+	have been used for transactions will be allowed.
+	- report date: The report date.
+	:param filters: Report filters
+	:type filters: dict
+
+	:return: str - Currency
+	"""
+	company = get_appropriate_company(filters)
+	company_currency = get_company_currency(company)
+	presentation_currency = filters['presentation_currency'] if filters.get('presentation_currency') else company_currency
+	report_date = filters.get('to_date') or filters.get('to_fiscal_year')
+
+	currency_map = dict(company=company, company_currency=company_currency, presentation_currency=presentation_currency, report_date=report_date)
+
+	return currency_map
+
+
+def convert(value, from_, to, date):
+	"""
+	convert `value` from `from_` to `to` on `date`
+	:param value: Amount to be converted
+	:param from_: Currency of `value`
+	:param to: Currency to convert to
+	:param date: exchange rate as at this date
+	:return: Result of converting `value`
+	"""
+	rate = get_rate_as_at(date, from_, to)
+	converted_value = value / (rate or 1)
+	return converted_value
+
+
+def get_rate_as_at(date, from_currency, to_currency):
+	"""
+	Gets exchange rate as at `date` for `from_currency` - `to_currency` exchange rate.
+	This calls `get_exchange_rate` so that we can get the correct exchange rate as per
+	the user's Accounts Settings.
+	It is made efficient by memoising results to `__exchange_rates`
+	:param date: exchange rate as at this date
+	:param from_currency: Base currency
+	:param to_currency: Quote currency
+	:return: Retrieved exchange rate
+	"""
+	rate = __exchange_rates.get('{0}-{1}@{2}'.format(from_currency, to_currency, date))
+	if not rate:
+		rate = get_exchange_rate(from_currency, to_currency, date) or 1
+		__exchange_rates['{0}-{1}@{2}'.format(from_currency, to_currency, date)] = rate
+
+	return rate
+
+
+def is_p_or_l_account(account_name):
+	"""
+	Check if the given `account name` is an `Account` with `root_type` of either 'Income'
+	or 'Expense'.
+	:param account_name:
+	:return: Boolean
+	"""
+	return account_name in P_OR_L_ACCOUNTS
+
+
+def convert_to_presentation_currency(gl_entries, currency_info):
+	"""
+	Take a list of GL Entries and change the 'debit' and 'credit' values to currencies
+	in `currency_info`.
+	:param gl_entries:
+	:param currency_info:
+	:return:
+	"""
+	converted_gl_list = []
+	presentation_currency = currency_info['presentation_currency']
+	company_currency = currency_info['company_currency']
+
+	for entry in gl_entries:
+		account = entry['account']
+		debit = cint(entry['debit'])
+		credit = cint(entry['credit'])
+		debit_in_account_currency = cint(entry['debit_in_account_currency'])
+		credit_in_account_currency = cint(entry['credit_in_account_currency'])
+		account_currency = entry['account_currency']
+
+		if account_currency != presentation_currency or (account_currency == presentation_currency and not is_p_or_l_account(account)):
+			value = debit or credit
+
+			date = currency_info['report_date'] if not is_p_or_l_account(account) else entry['posting_date']
+
+			converted_value = convert(value, presentation_currency, company_currency, date)
+
+			if entry.get('debit'):
+				entry['debit'] = converted_value
+			else:
+				entry['credit'] = converted_value
+
+		elif account_currency == presentation_currency:
+			if entry.get('debit'):
+				entry['debit'] = debit_in_account_currency
+			else:
+				entry['credit'] = credit_in_account_currency
+
+		converted_gl_list.append(entry)
+
+	return converted_gl_list
+
+
+def get_appropriate_company(filters):
+	if filters.get('company'):
+		company = filters['company']
+	else:
+		company = get_default_company()
+
+	return company
diff --git a/erpnext/config/desktop.py b/erpnext/config/desktop.py
index 7556083..3c18844 100644
--- a/erpnext/config/desktop.py
+++ b/erpnext/config/desktop.py
@@ -360,6 +360,14 @@
 			"hidden": 1
 		},
 		{
+			"module_name": "Hotels",
+			"color": "#EA81E8",
+			"icon": "fa fa-bed",
+			"type": "module",
+			"label": _("Hotels"),
+			"hidden": 1
+		},
+		{
 			"module_name": "Agriculture",
 			"color": "#8BC34A",
 			"icon": "octicon octicon-globe",
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index b3672cb..b7017c1 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -12,7 +12,7 @@
 from erpnext.accounts.party import get_party_account_currency, validate_party_frozen_disabled
 from erpnext.exceptions import InvalidCurrency
 
-force_item_fields = ("item_group", "barcode", "brand", "stock_uom")
+force_item_fields = ("item_group", "brand", "stock_uom")
 
 class AccountsController(TransactionBase):
 	def __init__(self, *args, **kwargs):
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 4b7b43c..b141455 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -218,7 +218,7 @@
 			if not exists:
 				rm = self.append(raw_material_table, {})
 
-			required_qty = flt(flt(bom_item.qty_consumed_per_unit) * flt(item.qty) *
+			required_qty = flt(flt(bom_item.qty_consumed_per_unit) * (flt(item.qty) + getattr(item, 'rejected_qty', 0)) *
 				flt(item.conversion_factor), rm.precision("required_qty"))
 			rm.reference_name = item.name
 			rm.bom_detail_no = bom_item.name
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index fd7bdc7..9a93633 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -165,8 +165,8 @@
 			and (tabItem.`{key}` LIKE %(txt)s
 				or tabItem.item_group LIKE %(txt)s
 				or tabItem.item_name LIKE %(txt)s
-				or tabItem.barcode LIKE %(txt)s
 				or tabItem.description LIKE %(txt)s)
+                or tabItem.item_code IN (select parent from `tabItem Barcode` where barcode LIKE %(txt)s)
 			{fcond} {mcond}
 		order by
 			if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
@@ -270,13 +270,14 @@
 	}
 
 	if args.get('warehouse'):
-		batch_nos = frappe.db.sql("""select sle.batch_no, round(sum(sle.actual_qty),2), sle.stock_uom, batch.expiry_date
+		batch_nos = frappe.db.sql("""select sle.batch_no, round(sum(sle.actual_qty),2), sle.stock_uom, concat('MFG-',batch.manufacturing_date), concat('EXP-',batch.expiry_date)
 				from `tabStock Ledger Entry` sle
 				    INNER JOIN `tabBatch` batch on sle.batch_no = batch.name
 				where
 					sle.item_code = %(item_code)s
 					and sle.warehouse = %(warehouse)s
-					and sle.batch_no like %(txt)s
+					and (sle.batch_no like %(txt)s
+					or batch.manufacturing_date like %(txt)s)
 					and batch.docstatus < 2
 					{0}
 					{match_conditions}
@@ -287,9 +288,10 @@
 	if batch_nos:
 		return batch_nos
 	else:
-		return frappe.db.sql("""select name, expiry_date from `tabBatch` batch
+		return frappe.db.sql("""select name, concat('MFG-', manufacturing_date), concat('EXP-',expiry_date) from `tabBatch` batch
 			where item = %(item_code)s
-			and name like %(txt)s
+			and (name like %(txt)s
+			or manufacturing_date like %(txt)s)
 			and docstatus < 2
 			{0}
 			{match_conditions}
diff --git a/erpnext/demo/user/hr.py b/erpnext/demo/user/hr.py
index e59c3ee..d61aa4e 100644
--- a/erpnext/demo/user/hr.py
+++ b/erpnext/demo/user/hr.py
@@ -172,7 +172,6 @@
 				"from_date": frappe.flags.current_date,
 				"to_date": to_date,
 				"leave_type": allocated_leave.leave_type,
-				"status": "Approved"
 			})
 			try:
 				leave_application.insert()
@@ -191,8 +190,9 @@
 				"employee": employee.name,
 				"attendance_date": attendance_date
 			})
+
 			leave = frappe.db.sql("""select name from `tabLeave Application`
-				where employee = %s and %s between from_date and to_date and workflow_state = 'Approved'
+				where employee = %s and %s between from_date and to_date
 				and docstatus = 1""", (employee.name, attendance_date))
 
 			if leave:
diff --git a/erpnext/docs/assets/img/hotels/hotel-room.png b/erpnext/docs/assets/img/hotels/hotel-room.png
new file mode 100644
index 0000000..7aad227
--- /dev/null
+++ b/erpnext/docs/assets/img/hotels/hotel-room.png
Binary files differ
diff --git a/erpnext/docs/user/manual/en/hospitality/hotel-room.md b/erpnext/docs/user/manual/en/hospitality/hotel-room.md
new file mode 100644
index 0000000..b788d1b
--- /dev/null
+++ b/erpnext/docs/user/manual/en/hospitality/hotel-room.md
@@ -0,0 +1,5 @@
+# Hotel Room
+
+Hotel Room is a master to create hotel rooms for reservation
+
+<img class="screenshot" alt="Hotel Room" src="/docs/assets/img/hotels/hotel-room.png">
diff --git a/erpnext/docs/user/manual/en/hospitality/index.md b/erpnext/docs/user/manual/en/hospitality/index.md
index efd7377..dc6c743 100644
--- a/erpnext/docs/user/manual/en/hospitality/index.md
+++ b/erpnext/docs/user/manual/en/hospitality/index.md
@@ -6,4 +6,8 @@
 
 The Restaurant module in ERPNext will help you manage a chain of restaurants. You can create Restaurants, Menus, Tables, Reservations and a manage Order Entry and Billing.
 
+### Manage Hotels
+
+The Hotels module in ERPNext will help you manage creating Hotel Rooms, create Hotel Room Reservation. It will also help in creating Invoice from hotel room reservation
+
 {index}
\ No newline at end of file
diff --git a/erpnext/docs/user/manual/en/hospitality/index.txt b/erpnext/docs/user/manual/en/hospitality/index.txt
index cbe6da0..0c909d8 100644
--- a/erpnext/docs/user/manual/en/hospitality/index.txt
+++ b/erpnext/docs/user/manual/en/hospitality/index.txt
@@ -1,4 +1,5 @@
 restaurant
 restaurant-menu
 reservations
-order-entry
\ No newline at end of file
+order-entry
+hotel-room
diff --git a/erpnext/domains/hospitality.py b/erpnext/domains/hospitality.py
index bc55d9c..09b98c2 100644
--- a/erpnext/domains/hospitality.py
+++ b/erpnext/domains/hospitality.py
@@ -1,6 +1,7 @@
 data = {
 	'desktop_icons': [
 		'Restaurant',
+		'Hotels',
 		'Accounts',
 		'Buying',
 		'Stock',
@@ -9,7 +10,9 @@
 		'ToDo'
 	],
 	'restricted_roles': [
-		'Restaurant Manager'
+		'Restaurant Manager',
+		'Hotel Manager',
+		'Hotel Reservation User'
 	],
 	'custom_fields': {
 		'Sales Invoice': [
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
index 0a96820..90d4d0e 100755
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
@@ -103,7 +103,7 @@
 
 		# Check if He/She on Leave
 		leave_record = frappe.db.sql("""select half_day from `tabLeave Application`
-			where employee = %s and %s between from_date and to_date and status = 'Approved'
+			where employee = %s and %s between from_date and to_date
 			and docstatus = 1""", (employee, date), as_dict=True)
 		if leave_record:
 			if leave_record[0].half_day:
diff --git a/erpnext/hotels/__init__.py b/erpnext/hotels/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hotels/__init__.py
diff --git a/erpnext/hotels/doctype/__init__.py b/erpnext/hotels/doctype/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hotels/doctype/__init__.py
diff --git a/erpnext/hotels/doctype/hotel_room/__init__.py b/erpnext/hotels/doctype/hotel_room/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room/__init__.py
diff --git a/erpnext/hotels/doctype/hotel_room/hotel_room.js b/erpnext/hotels/doctype/hotel_room/hotel_room.js
new file mode 100644
index 0000000..76f22d5
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room/hotel_room.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Hotel Room', {
+	refresh: function(frm) {
+
+	}
+});
diff --git a/erpnext/hotels/doctype/hotel_room/hotel_room.json b/erpnext/hotels/doctype/hotel_room/hotel_room.json
new file mode 100644
index 0000000..2567c07
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room/hotel_room.json
@@ -0,0 +1,175 @@
+{
+ "allow_copy": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 1, 
+ "allow_rename": 1, 
+ "autoname": "prompt", 
+ "beta": 1, 
+ "creation": "2017-12-08 12:33:56.320420", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "Setup", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "hotel_room_type", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Hotel Room Type", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Hotel Room Type", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "capacity", 
+   "fieldtype": "Int", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Capacity", 
+   "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": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "extra_bed_capacity", 
+   "fieldtype": "Int", 
+   "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": "Extra Bed Capacity", 
+   "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
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 0, 
+ "max_attachments": 0, 
+ "modified": "2017-12-09 12:10:50.670113", 
+ "modified_by": "Administrator", 
+ "module": "Hotels", 
+ "name": "Hotel Room", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [
+  {
+   "amend": 0, 
+   "apply_user_permissions": 0, 
+   "cancel": 0, 
+   "create": 1, 
+   "delete": 1, 
+   "email": 1, 
+   "export": 1, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 1, 
+   "role": "System Manager", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
+   "write": 1
+  }, 
+  {
+   "amend": 0, 
+   "apply_user_permissions": 0, 
+   "cancel": 0, 
+   "create": 1, 
+   "delete": 1, 
+   "email": 1, 
+   "export": 1, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 1, 
+   "role": "Hotel Manager", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
+   "write": 1
+  }
+ ], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "restrict_to_domain": "Hospitality", 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 1, 
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/hotels/doctype/hotel_room/hotel_room.py b/erpnext/hotels/doctype/hotel_room/hotel_room.py
new file mode 100644
index 0000000..8471aee
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room/hotel_room.py
@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class HotelRoom(Document):
+	def validate(self):
+		if not self.capacity:
+			self.capacity, self.extra_bed_capacity = frappe.db.get_value('Hotel Room Type',
+					self.hotel_room_type, ['capacity', 'extra_bed_capacity'])
\ No newline at end of file
diff --git a/erpnext/hotels/doctype/hotel_room/test_hotel_room.js b/erpnext/hotels/doctype/hotel_room/test_hotel_room.js
new file mode 100644
index 0000000..8b2b833
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room/test_hotel_room.js
@@ -0,0 +1,23 @@
+/* eslint-disable */
+// rename this file from _test_[name] to test_[name] to activate
+// and remove above this line
+
+QUnit.test("test: Hotel Room", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Hotel Room
+		() => frappe.tests.make('Hotel Room', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/hotels/doctype/hotel_room/test_hotel_room.py b/erpnext/hotels/doctype/hotel_room/test_hotel_room.py
new file mode 100644
index 0000000..00d3aea
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room/test_hotel_room.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+test_records = [
+	dict(doctype="Hotel Room", name="1001",
+		hotel_room_type="Basic Room"),
+	dict(doctype="Hotel Room", name="1002",
+		hotel_room_type="Basic Room"),
+	dict(doctype="Hotel Room", name="1003",
+		hotel_room_type="Basic Room"),
+	dict(doctype="Hotel Room", name="1004",
+		hotel_room_type="Basic Room"),
+	dict(doctype="Hotel Room", name="1005",
+		hotel_room_type="Basic Room"),
+	dict(doctype="Hotel Room", name="1006",
+		hotel_room_type="Basic Room")
+]
+
+class TestHotelRoom(unittest.TestCase):
+	pass
diff --git a/erpnext/hotels/doctype/hotel_room_amenity/__init__.py b/erpnext/hotels/doctype/hotel_room_amenity/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_amenity/__init__.py
diff --git a/erpnext/hotels/doctype/hotel_room_amenity/hotel_room_amenity.json b/erpnext/hotels/doctype/hotel_room_amenity/hotel_room_amenity.json
new file mode 100644
index 0000000..29a0407
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_amenity/hotel_room_amenity.json
@@ -0,0 +1,103 @@
+{
+ "allow_copy": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
+ "beta": 0, 
+ "creation": "2017-12-08 12:35:36.572185", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "item", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Item", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Item", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "billable", 
+   "fieldtype": "Check", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Billable", 
+   "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
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 1, 
+ "max_attachments": 0, 
+ "modified": "2017-12-09 12:05:07.125687", 
+ "modified_by": "Administrator", 
+ "module": "Hotels", 
+ "name": "Hotel Room Amenity", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "restrict_to_domain": "Hospitality", 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 1, 
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/hotels/doctype/hotel_room_amenity/hotel_room_amenity.py b/erpnext/hotels/doctype/hotel_room_amenity/hotel_room_amenity.py
new file mode 100644
index 0000000..69da007
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_amenity/hotel_room_amenity.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class HotelRoomAmenity(Document):
+	pass
diff --git a/erpnext/hotels/doctype/hotel_room_package/__init__.py b/erpnext/hotels/doctype/hotel_room_package/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_package/__init__.py
diff --git a/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.js b/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.js
new file mode 100644
index 0000000..5b09ae5
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.js
@@ -0,0 +1,23 @@
+// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Hotel Room Package', {
+	hotel_room_type: function(frm) {
+		if (frm.doc.hotel_room_type) {
+			frappe.model.with_doc('Hotel Room Type', frm.doc.hotel_room_type, () => {
+				let hotel_room_type = frappe.get_doc('Hotel Room Type', frm.doc.hotel_room_type);
+
+				// reset the amenities
+				frm.doc.amenities = [];
+
+				for (let amenity of hotel_room_type.amenities) {
+					let d = frm.add_child('amenities');
+					d.item = amenity.item;
+					d.billable = amenity.billable;
+				}
+
+				frm.refresh();
+			});
+		}
+	}
+});
diff --git a/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.json b/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.json
new file mode 100644
index 0000000..57dad44
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.json
@@ -0,0 +1,215 @@
+{
+ "allow_copy": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
+ "autoname": "prompt", 
+ "beta": 1, 
+ "creation": "2017-12-08 12:43:17.211064", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "Setup", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "hotel_room_type", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Hotel Room Type", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Hotel Room Type", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "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, 
+   "fieldname": "item", 
+   "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": "Item", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Item", 
+   "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": "section_break_4", 
+   "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, 
+   "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": "amenities", 
+   "fieldtype": "Table", 
+   "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": "Amenities", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Hotel Room Amenity", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 0, 
+ "max_attachments": 0, 
+ "modified": "2017-12-09 12:10:31.111952", 
+ "modified_by": "Administrator", 
+ "module": "Hotels", 
+ "name": "Hotel Room Package", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [
+  {
+   "amend": 0, 
+   "apply_user_permissions": 0, 
+   "cancel": 0, 
+   "create": 1, 
+   "delete": 1, 
+   "email": 1, 
+   "export": 1, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 1, 
+   "role": "System Manager", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
+   "write": 1
+  }
+ ], 
+ "quick_entry": 0, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "restrict_to_domain": "Hospitality", 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 1, 
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.py b/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.py
new file mode 100644
index 0000000..8a62eea
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class HotelRoomPackage(Document):
+	def validate(self):
+		if not self.item:
+			item = frappe.get_doc(dict(
+				doctype = 'Item',
+				item_code = self.name,
+				item_group = 'Products',
+				is_stock_item = 0,
+				stock_uom = 'Unit'
+			))
+			item.insert()
+			self.item = item.name
diff --git a/erpnext/hotels/doctype/hotel_room_package/test_hotel_room_package.js b/erpnext/hotels/doctype/hotel_room_package/test_hotel_room_package.js
new file mode 100644
index 0000000..f1ebad4
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_package/test_hotel_room_package.js
@@ -0,0 +1,23 @@
+/* eslint-disable */
+// rename this file from _test_[name] to test_[name] to activate
+// and remove above this line
+
+QUnit.test("test: Hotel Room Package", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Hotel Room Package
+		() => frappe.tests.make('Hotel Room Package', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/hotels/doctype/hotel_room_package/test_hotel_room_package.py b/erpnext/hotels/doctype/hotel_room_package/test_hotel_room_package.py
new file mode 100644
index 0000000..ebf7f2b
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_package/test_hotel_room_package.py
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+test_records = [
+	dict(doctype='Item', item_code='Breakfast',
+		item_group='Products', is_stock_item=0),
+	dict(doctype='Item', item_code='Lunch',
+		item_group='Products', is_stock_item=0),
+	dict(doctype='Item', item_code='Dinner',
+		item_group='Products', is_stock_item=0),
+	dict(doctype='Item', item_code='WiFi',
+		item_group='Products', is_stock_item=0),
+	dict(doctype='Hotel Room Type', name="Delux Room",
+		capacity=4,
+		extra_bed_capacity=2,
+		amenities = [
+			dict(item='WiFi', billable=0)
+		]),
+	dict(doctype='Hotel Room Type', name="Basic Room",
+		capacity=4,
+		extra_bed_capacity=2,
+		amenities = [
+			dict(item='Breakfast', billable=0)
+		]),
+	dict(doctype="Hotel Room Package", name="Basic Room with Breakfast",
+		hotel_room_type="Basic Room",
+		amenities = [
+			dict(item="Breakfast", billable=0)
+		]),
+	dict(doctype="Hotel Room Package", name="Basic Room with Lunch",
+		hotel_room_type="Basic Room",
+		amenities = [
+			dict(item="Breakfast", billable=0),
+			dict(item="Lunch", billable=0)
+		]),
+	dict(doctype="Hotel Room Package", name="Basic Room with Dinner",
+		hotel_room_type="Basic Room",
+		amenities = [
+			dict(item="Breakfast", billable=0),
+			dict(item="Dinner", billable=0)
+		])
+]
+
+class TestHotelRoomPackage(unittest.TestCase):
+	pass
diff --git a/erpnext/hotels/doctype/hotel_room_pricing/__init__.py b/erpnext/hotels/doctype/hotel_room_pricing/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_pricing/__init__.py
diff --git a/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.js b/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.js
new file mode 100644
index 0000000..87bb192
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Hotel Room Pricing', {
+	refresh: function(frm) {
+
+	}
+});
diff --git a/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.json b/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.json
new file mode 100644
index 0000000..0f5a776
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.json
@@ -0,0 +1,266 @@
+{
+ "allow_copy": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 1, 
+ "allow_rename": 0, 
+ "autoname": "prompt", 
+ "beta": 1, 
+ "creation": "2017-12-08 12:51:47.088174", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "Setup", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "default": "1", 
+   "fieldname": "enabled", 
+   "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": "Enabled", 
+   "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": "currency", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Currency", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Currency", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "from_date", 
+   "fieldtype": "Date", 
+   "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": "From Date", 
+   "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": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "to_date", 
+   "fieldtype": "Date", 
+   "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": "To Date", 
+   "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": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "section_break_5", 
+   "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, 
+   "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": "items", 
+   "fieldtype": "Table", 
+   "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": "Items", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Hotel Room Pricing Item", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 0, 
+ "max_attachments": 0, 
+ "modified": "2017-12-09 12:10:41.559559", 
+ "modified_by": "Administrator", 
+ "module": "Hotels", 
+ "name": "Hotel Room Pricing", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [
+  {
+   "amend": 0, 
+   "apply_user_permissions": 0, 
+   "cancel": 0, 
+   "create": 1, 
+   "delete": 1, 
+   "email": 1, 
+   "export": 1, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 1, 
+   "role": "System Manager", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
+   "write": 1
+  }, 
+  {
+   "amend": 0, 
+   "apply_user_permissions": 0, 
+   "cancel": 0, 
+   "create": 1, 
+   "delete": 1, 
+   "email": 1, 
+   "export": 1, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 1, 
+   "role": "Hotel Manager", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
+   "write": 1
+  }
+ ], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "restrict_to_domain": "Hospitality", 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 1, 
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.py b/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.py
new file mode 100644
index 0000000..8eee0f2
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class HotelRoomPricing(Document):
+	pass
diff --git a/erpnext/hotels/doctype/hotel_room_pricing/test_hotel_room_pricing.js b/erpnext/hotels/doctype/hotel_room_pricing/test_hotel_room_pricing.js
new file mode 100644
index 0000000..ba0d1fd
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_pricing/test_hotel_room_pricing.js
@@ -0,0 +1,23 @@
+/* eslint-disable */
+// rename this file from _test_[name] to test_[name] to activate
+// and remove above this line
+
+QUnit.test("test: Hotel Room Pricing", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Hotel Room Pricing
+		() => frappe.tests.make('Hotel Room Pricing', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/hotels/doctype/hotel_room_pricing/test_hotel_room_pricing.py b/erpnext/hotels/doctype/hotel_room_pricing/test_hotel_room_pricing.py
new file mode 100644
index 0000000..2b7848b
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_pricing/test_hotel_room_pricing.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+test_records = [
+	dict(doctype="Hotel Room Pricing", enabled=1,
+		name="Winter 2017",
+		from_date="2017-01-01", to_date="2017-01-10",
+		items = [
+			dict(item="Basic Room with Breakfast", rate=10000),
+			dict(item="Basic Room with Lunch", rate=11000),
+			dict(item="Basic Room with Dinner", rate=12000)
+		])
+]
+
+class TestHotelRoomPricing(unittest.TestCase):
+	pass
diff --git a/erpnext/hotels/doctype/hotel_room_pricing_item/__init__.py b/erpnext/hotels/doctype/hotel_room_pricing_item/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_pricing_item/__init__.py
diff --git a/erpnext/hotels/doctype/hotel_room_pricing_item/hotel_room_pricing_item.json b/erpnext/hotels/doctype/hotel_room_pricing_item/hotel_room_pricing_item.json
new file mode 100644
index 0000000..d6cd826
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_pricing_item/hotel_room_pricing_item.json
@@ -0,0 +1,103 @@
+{
+ "allow_copy": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
+ "beta": 0, 
+ "creation": "2017-12-08 12:50:13.486090", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "item", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Item", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Item", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "rate", 
+   "fieldtype": "Currency", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Rate", 
+   "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": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 1, 
+ "max_attachments": 0, 
+ "modified": "2017-12-09 12:04:58.641703", 
+ "modified_by": "Administrator", 
+ "module": "Hotels", 
+ "name": "Hotel Room Pricing Item", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "restrict_to_domain": "Hospitality", 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 1, 
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/hotels/doctype/hotel_room_pricing_item/hotel_room_pricing_item.py b/erpnext/hotels/doctype/hotel_room_pricing_item/hotel_room_pricing_item.py
new file mode 100644
index 0000000..6bf01bf
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_pricing_item/hotel_room_pricing_item.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class HotelRoomPricingItem(Document):
+	pass
diff --git a/erpnext/hotels/doctype/hotel_room_pricing_package/__init__.py b/erpnext/hotels/doctype/hotel_room_pricing_package/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_pricing_package/__init__.py
diff --git a/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.js b/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.js
new file mode 100644
index 0000000..f6decd9
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Hotel Room Pricing Package', {
+	refresh: function(frm) {
+
+	}
+});
diff --git a/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.json b/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.json
new file mode 100644
index 0000000..92bd980
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.json
@@ -0,0 +1,162 @@
+{
+ "allow_copy": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
+ "beta": 0, 
+ "creation": "2017-12-08 12:50:13.486090", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "from_date", 
+   "fieldtype": "Date", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "From Date", 
+   "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": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "to_date", 
+   "fieldtype": "Date", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "To Date", 
+   "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": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "hotel_room_package", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Hotel Room Package", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Hotel Room Package", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "rate", 
+   "fieldtype": "Currency", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Rate", 
+   "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": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 1, 
+ "max_attachments": 0, 
+ "modified": "2017-12-08 12:52:01.743866", 
+ "modified_by": "Administrator", 
+ "module": "Hotels", 
+ "name": "Hotel Room Pricing Package", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 1, 
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.py b/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.py
new file mode 100644
index 0000000..9ae9fcf
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class HotelRoomPricingPackage(Document):
+	pass
diff --git a/erpnext/hotels/doctype/hotel_room_pricing_package/test_hotel_room_pricing_package.js b/erpnext/hotels/doctype/hotel_room_pricing_package/test_hotel_room_pricing_package.js
new file mode 100644
index 0000000..73a561c
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_pricing_package/test_hotel_room_pricing_package.js
@@ -0,0 +1,23 @@
+/* eslint-disable */
+// rename this file from _test_[name] to test_[name] to activate
+// and remove above this line
+
+QUnit.test("test: Hotel Room Pricing Package", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Hotel Room Pricing Package
+		() => frappe.tests.make('Hotel Room Pricing Package', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/hotels/doctype/hotel_room_pricing_package/test_hotel_room_pricing_package.py b/erpnext/hotels/doctype/hotel_room_pricing_package/test_hotel_room_pricing_package.py
new file mode 100644
index 0000000..fec1c86
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_pricing_package/test_hotel_room_pricing_package.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestHotelRoomPricingPackage(unittest.TestCase):
+	pass
diff --git a/erpnext/hotels/doctype/hotel_room_reservation/__init__.py b/erpnext/hotels/doctype/hotel_room_reservation/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_reservation/__init__.py
diff --git a/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.js b/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.js
new file mode 100644
index 0000000..2c9fd7b
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.js
@@ -0,0 +1,68 @@
+// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Hotel Room Reservation', {
+	refresh: function(frm) {
+		if(frm.doc.docstatus == 1){
+			frm.add_custom_button(__("Make Invoice"), ()=> {
+				frm.trigger("make_invoice");
+			});
+		}
+	},
+	from_date: function(frm) {
+		frm.trigger("recalculate_rates");
+	},
+	to_date: function(frm) {
+		frm.trigger("recalculate_rates");
+	},
+	recalculate_rates: function(frm) {
+		if (!frm.doc.from_date || !frm.doc.to_date
+			|| !frm.doc.items.length){
+			return;
+		}
+		frappe.call({
+			"method": "erpnext.hotels.doctype.hotel_room_reservation.hotel_room_reservation.get_room_rate",
+			"args": {"hotel_room_reservation": frm.doc}
+		}).done((r)=> {
+			for (var i = 0; i < r.message.items.length; i++) {
+				frm.doc.items[i].rate = r.message.items[i].rate;
+				frm.doc.items[i].amount = r.message.items[i].amount;
+			}
+			frappe.run_serially([
+				()=> frm.set_value("net_total", r.message.net_total),
+				()=> frm.refresh_field("items")
+			]);
+		});
+	},
+	make_invoice: function(frm) {
+		frappe.model.with_doc("Hotel Settings", "Hotel Settings", ()=>{
+			frappe.model.with_doctype("Sales Invoice", ()=>{
+				let hotel_settings = frappe.get_doc("Hotel Settings", "Hotel Settings");
+				let invoice = frappe.model.get_new_doc("Sales Invoice");
+				invoice.customer = frm.doc.customer || hotel_settings.default_customer;
+				if (hotel_settings.default_invoice_naming_series){
+					invoice.naming_series = hotel_settings.default_invoice_naming_series;
+				}
+				for (let d of frm.doc.items){
+					let invoice_item = frappe.model.add_child(invoice, "items")
+					invoice_item.item_code = d.item;
+					invoice_item.qty = d.qty;
+					invoice_item.rate = d.rate;
+				}
+				if (hotel_settings.default_taxes_and_charges){
+					invoice.taxes_and_charges = hotel_settings.default_taxes_and_charges;
+				}
+				frappe.set_route("Form", invoice.doctype, invoice.name);
+			});
+		});
+	}
+});
+
+frappe.ui.form.on('Hotel Room Reservation Item', {
+	item: function(frm, doctype, name) {
+		frm.trigger("recalculate_rates");
+	},
+	qty: function(frm) {
+		frm.trigger("recalculate_rates");
+	}
+});
diff --git a/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.json b/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.json
new file mode 100644
index 0000000..c65c4e1
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.json
@@ -0,0 +1,415 @@
+{
+ "allow_copy": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 1, 
+ "allow_rename": 0, 
+ "autoname": "HRES.#######", 
+ "beta": 1, 
+ "creation": "2017-12-08 13:01:34.829175", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "Document", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "guest_name", 
+   "fieldtype": "Data", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Guest Name", 
+   "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": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "customer", 
+   "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": "Customer", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Customer", 
+   "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": "from_date", 
+   "fieldtype": "Date", 
+   "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": "From Date", 
+   "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": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "to_date", 
+   "fieldtype": "Date", 
+   "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": "To Date", 
+   "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": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "late_checkin", 
+   "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": "Late Checkin", 
+   "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": "column_break_6", 
+   "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, 
+   "fieldname": "status", 
+   "fieldtype": "Select", 
+   "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": "Status", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Booked\nAdvance Paid\nInvoiced\nPaid\nCompleted\nCancelled", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "section_break_8", 
+   "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, 
+   "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": "items", 
+   "fieldtype": "Table", 
+   "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": "Items", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Hotel Room Reservation Item", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "net_total", 
+   "fieldtype": "Currency", 
+   "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": "Net Total", 
+   "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": "amended_from", 
+   "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": "Amended From", 
+   "length": 0, 
+   "no_copy": 1, 
+   "options": "Hotel Room Reservation", 
+   "permlevel": 0, 
+   "print_hide": 1, 
+   "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
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "is_submittable": 1, 
+ "issingle": 0, 
+ "istable": 0, 
+ "max_attachments": 0, 
+ "modified": "2017-12-09 12:11:26.395419", 
+ "modified_by": "Administrator", 
+ "module": "Hotels", 
+ "name": "Hotel Room Reservation", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [
+  {
+   "amend": 0, 
+   "apply_user_permissions": 0, 
+   "cancel": 0, 
+   "create": 1, 
+   "delete": 1, 
+   "email": 1, 
+   "export": 1, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 1, 
+   "role": "System Manager", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
+   "write": 1
+  }, 
+  {
+   "amend": 1, 
+   "apply_user_permissions": 0, 
+   "cancel": 1, 
+   "create": 1, 
+   "delete": 1, 
+   "email": 1, 
+   "export": 1, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 1, 
+   "role": "Hotel Reservation User", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 1, 
+   "write": 1
+  }
+ ], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "restrict_to_domain": "Hospitality", 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 1, 
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.py b/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.py
new file mode 100644
index 0000000..f3f76a9
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.py
@@ -0,0 +1,109 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe, json
+from frappe.model.document import Document
+from frappe import _
+from frappe.utils import date_diff, add_days, flt
+
+class HotelRoomUnavailableError(frappe.ValidationError): pass
+class HotelRoomPricingNotSetError(frappe.ValidationError): pass
+
+class HotelRoomReservation(Document):
+	def validate(self):
+		self.total_rooms = {}
+		self.set_rates()
+		self.validate_availability()
+
+	def validate_availability(self):
+		for i in xrange(date_diff(self.to_date, self.from_date)):
+			day = add_days(self.from_date, i)
+			self.rooms_booked = {}
+
+			for d in self.items:
+				if not d.item in self.rooms_booked:
+					self.rooms_booked[d.item] = 0
+
+				room_type = frappe.db.get_value("Hotel Room Package",
+					d.item, 'hotel_room_type')
+				rooms_booked = get_rooms_booked(room_type, day, exclude_reservation=self.name) \
+					+ d.qty + self.rooms_booked.get(d.item)
+				total_rooms = self.get_total_rooms(d.item)
+				if total_rooms < rooms_booked:
+					frappe.throw(_("Hotel Rooms of type {0} are unavailable on {1}".format(d.item,
+						frappe.format(day, dict(fieldtype="Date")))), exc=HotelRoomUnavailableError)
+
+				self.rooms_booked[d.item] += rooms_booked
+
+	def get_total_rooms(self, item):
+		if not item in self.total_rooms:
+			self.total_rooms[item] = frappe.db.sql("""
+				select count(*)
+				from
+					`tabHotel Room Package` package
+				inner join
+					`tabHotel Room` room on package.hotel_room_type = room.hotel_room_type
+				where
+					package.item = %s""", item)[0][0] or 0
+
+		return self.total_rooms[item]
+
+	def set_rates(self):
+		self.net_total = 0
+		for d in self.items:
+			net_rate = 0.0
+			for i in xrange(date_diff(self.to_date, self.from_date)):
+				day = add_days(self.from_date, i)
+				if not d.item:
+					continue
+				day_rate = frappe.db.sql("""
+					select 
+						item.rate 
+					from 
+						`tabHotel Room Pricing Item` item,
+						`tabHotel Room Pricing` pricing
+					where
+						item.parent = pricing.name
+						and item.item = %s
+						and %s between pricing.from_date 
+							and pricing.to_date""", (d.item, day))
+
+				if day_rate:
+					net_rate += day_rate[0][0]
+				else:
+					frappe.throw(
+						_("Please set Hotel Room Rate on {}".format(
+							frappe.format(day, dict(fieldtype="Date")))), exc=HotelRoomPricingNotSetError)
+			d.rate = net_rate
+			d.amount = net_rate * flt(d.qty)
+			self.net_total += d.amount
+
+@frappe.whitelist()
+def get_room_rate(hotel_room_reservation):
+	"""Calculate rate for each day as it may belong to different Hotel Room Pricing Item"""
+	doc = frappe.get_doc(json.loads(hotel_room_reservation))
+	doc.set_rates()
+	return doc.as_dict()
+
+def get_rooms_booked(room_type, day, exclude_reservation=None):
+	exclude_condition = ''
+	if exclude_reservation:
+		exclude_condition = 'and reservation.name != "{0}"'.format(frappe.db.escape(exclude_reservation))
+
+	return frappe.db.sql("""
+		select sum(item.qty)
+		from
+			`tabHotel Room Package` room_package,
+			`tabHotel Room Reservation Item` item,
+			`tabHotel Room Reservation` reservation
+		where
+			item.parent = reservation.name
+			and room_package.item = item.item
+			and room_package.hotel_room_type = %s
+			and reservation.docstatus = 1
+			{exclude_condition}
+			and %s between reservation.from_date
+				and reservation.to_date""".format(exclude_condition=exclude_condition), 
+				(room_type, day))[0][0] or 0
diff --git a/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation_calendar.js b/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation_calendar.js
new file mode 100644
index 0000000..7f7322c
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation_calendar.js
@@ -0,0 +1,9 @@
+frappe.views.calendar["Hotel Room Reservation"] = {
+	field_map: {
+		"start": "from_date",
+		"end": "to_date",
+		"id": "name",
+		"title": "guest_name",
+		"status": "status"
+	}
+}
\ No newline at end of file
diff --git a/erpnext/hotels/doctype/hotel_room_reservation/test_hotel_room_reservation.js b/erpnext/hotels/doctype/hotel_room_reservation/test_hotel_room_reservation.js
new file mode 100644
index 0000000..2897139
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_reservation/test_hotel_room_reservation.js
@@ -0,0 +1,23 @@
+/* eslint-disable */
+// rename this file from _test_[name] to test_[name] to activate
+// and remove above this line
+
+QUnit.test("test: Hotel Room Reservation", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Hotel Room Reservation
+		() => frappe.tests.make('Hotel Room Reservation', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/hotels/doctype/hotel_room_reservation/test_hotel_room_reservation.py b/erpnext/hotels/doctype/hotel_room_reservation/test_hotel_room_reservation.py
new file mode 100644
index 0000000..55c6311
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_reservation/test_hotel_room_reservation.py
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+from erpnext.hotels.doctype.hotel_room_reservation.hotel_room_reservation import HotelRoomPricingNotSetError, HotelRoomUnavailableError
+test_dependencies = ["Hotel Room Pricing", "Hotel Room"]
+
+class TestHotelRoomReservation(unittest.TestCase):
+	def setUp(self):
+		frappe.db.sql("delete from `tabHotel Room Reservation`")
+		frappe.db.sql("delete from `tabHotel Room Reservation Item`")
+
+	def test_reservation(self):
+		reservation = make_reservation(
+			from_date="2017-01-01",
+			to_date="2017-01-03",
+			items=[
+				dict(item="Basic Room with Dinner", qty=2)
+			]
+		)
+		reservation.insert()
+		self.assertEqual(reservation.net_total, 48000)
+
+	def test_price_not_set(self):
+		reservation = make_reservation(
+			from_date="2016-01-01",
+			to_date="2016-01-03",
+			items=[
+				dict(item="Basic Room with Dinner", qty=2)
+			]
+		)
+		self.assertRaises(HotelRoomPricingNotSetError, reservation.insert)
+
+	def test_room_unavailable(self):
+		reservation = make_reservation(
+			from_date="2017-01-01",
+			to_date="2017-01-03",
+			items=[
+				dict(item="Basic Room with Dinner", qty=2),
+			]
+		)
+		reservation.insert()
+
+		reservation = make_reservation(
+			from_date="2017-01-01",
+			to_date="2017-01-03",
+			items=[
+				dict(item="Basic Room with Dinner", qty=20),
+			]
+		)
+		self.assertRaises(HotelRoomUnavailableError, reservation.insert)
+
+def make_reservation(**kwargs):
+	kwargs["doctype"] = "Hotel Room Reservation"
+	if not "guest_name" in kwargs:
+		kwargs["guest_name"] = "Test Guest"
+	doc = frappe.get_doc(kwargs)
+	return doc
diff --git a/erpnext/hotels/doctype/hotel_room_reservation_item/__init__.py b/erpnext/hotels/doctype/hotel_room_reservation_item/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_reservation_item/__init__.py
diff --git a/erpnext/hotels/doctype/hotel_room_reservation_item/hotel_room_reservation_item.json b/erpnext/hotels/doctype/hotel_room_reservation_item/hotel_room_reservation_item.json
new file mode 100644
index 0000000..2b7931e
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_reservation_item/hotel_room_reservation_item.json
@@ -0,0 +1,195 @@
+{
+ "allow_copy": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
+ "autoname": "", 
+ "beta": 0, 
+ "creation": "2017-12-08 12:58:21.733330", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "item", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Item", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Item", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "qty", 
+   "fieldtype": "Int", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Qty", 
+   "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": "currency", 
+   "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": "Currency", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Currency", 
+   "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": "rate", 
+   "fieldtype": "Currency", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Rate", 
+   "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": "amount", 
+   "fieldtype": "Currency", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Amount", 
+   "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
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 1, 
+ "max_attachments": 0, 
+ "modified": "2017-12-09 12:04:34.562956", 
+ "modified_by": "Administrator", 
+ "module": "Hotels", 
+ "name": "Hotel Room Reservation Item", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "restrict_to_domain": "Hospitality", 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 1, 
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/hotels/doctype/hotel_room_reservation_item/hotel_room_reservation_item.py b/erpnext/hotels/doctype/hotel_room_reservation_item/hotel_room_reservation_item.py
new file mode 100644
index 0000000..3406fae
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_reservation_item/hotel_room_reservation_item.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class HotelRoomReservationItem(Document):
+	pass
diff --git a/erpnext/hotels/doctype/hotel_room_type/__init__.py b/erpnext/hotels/doctype/hotel_room_type/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_type/__init__.py
diff --git a/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.js b/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.js
new file mode 100644
index 0000000..d73835d
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Hotel Room Type', {
+	refresh: function(frm) {
+
+	}
+});
diff --git a/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.json b/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.json
new file mode 100644
index 0000000..3d26413
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.json
@@ -0,0 +1,204 @@
+{
+ "allow_copy": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 1, 
+ "allow_rename": 1, 
+ "autoname": "prompt", 
+ "beta": 1, 
+ "creation": "2017-12-08 12:38:29.485175", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "Setup", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "capacity", 
+   "fieldtype": "Int", 
+   "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": "Capacity", 
+   "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": "extra_bed_capacity", 
+   "fieldtype": "Int", 
+   "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": "Extra Bed Capacity", 
+   "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": "section_break_3", 
+   "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, 
+   "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": "amenities", 
+   "fieldtype": "Table", 
+   "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": "Amenities", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Hotel Room Amenity", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 0, 
+ "max_attachments": 0, 
+ "modified": "2017-12-09 12:10:23.355486", 
+ "modified_by": "Administrator", 
+ "module": "Hotels", 
+ "name": "Hotel Room Type", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [
+  {
+   "amend": 0, 
+   "apply_user_permissions": 0, 
+   "cancel": 0, 
+   "create": 1, 
+   "delete": 1, 
+   "email": 1, 
+   "export": 1, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 1, 
+   "role": "System Manager", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
+   "write": 1
+  }, 
+  {
+   "amend": 0, 
+   "apply_user_permissions": 0, 
+   "cancel": 0, 
+   "create": 1, 
+   "delete": 1, 
+   "email": 1, 
+   "export": 1, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 1, 
+   "role": "Hotel Manager", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
+   "write": 1
+  }
+ ], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "restrict_to_domain": "Hospitality", 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 1, 
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.py b/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.py
new file mode 100644
index 0000000..1fc1303
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class HotelRoomType(Document):
+	pass
diff --git a/erpnext/hotels/doctype/hotel_room_type/test_hotel_room_type.js b/erpnext/hotels/doctype/hotel_room_type/test_hotel_room_type.js
new file mode 100644
index 0000000..e2dd578
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_type/test_hotel_room_type.js
@@ -0,0 +1,23 @@
+/* eslint-disable */
+// rename this file from _test_[name] to test_[name] to activate
+// and remove above this line
+
+QUnit.test("test: Hotel Room Type", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Hotel Room Type
+		() => frappe.tests.make('Hotel Room Type', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/hotels/doctype/hotel_room_type/test_hotel_room_type.py b/erpnext/hotels/doctype/hotel_room_type/test_hotel_room_type.py
new file mode 100644
index 0000000..3b243e9
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_room_type/test_hotel_room_type.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestHotelRoomType(unittest.TestCase):
+	pass
diff --git a/erpnext/hotels/doctype/hotel_settings/__init__.py b/erpnext/hotels/doctype/hotel_settings/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_settings/__init__.py
diff --git a/erpnext/hotels/doctype/hotel_settings/hotel_settings.js b/erpnext/hotels/doctype/hotel_settings/hotel_settings.js
new file mode 100644
index 0000000..0b4a2c3
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_settings/hotel_settings.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Hotel Settings', {
+	refresh: function(frm) {
+
+	}
+});
diff --git a/erpnext/hotels/doctype/hotel_settings/hotel_settings.json b/erpnext/hotels/doctype/hotel_settings/hotel_settings.json
new file mode 100644
index 0000000..d9f5572
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_settings/hotel_settings.json
@@ -0,0 +1,175 @@
+{
+ "allow_copy": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
+ "beta": 1, 
+ "creation": "2017-12-08 17:50:24.523107", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "Setup", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "default_customer", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Default Customer", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Customer", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "default_taxes_and_charges", 
+   "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": "Default Taxes and Charges", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Sales Taxes and Charges Template", 
+   "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": "default_invoice_naming_series", 
+   "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": "Default Invoice Naming Series", 
+   "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
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 1, 
+ "istable": 0, 
+ "max_attachments": 0, 
+ "modified": "2017-12-09 12:11:12.857308", 
+ "modified_by": "Administrator", 
+ "module": "Hotels", 
+ "name": "Hotel Settings", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [
+  {
+   "amend": 0, 
+   "apply_user_permissions": 0, 
+   "cancel": 0, 
+   "create": 1, 
+   "delete": 1, 
+   "email": 1, 
+   "export": 0, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 0, 
+   "role": "System Manager", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
+   "write": 1
+  }, 
+  {
+   "amend": 0, 
+   "apply_user_permissions": 0, 
+   "cancel": 0, 
+   "create": 1, 
+   "delete": 1, 
+   "email": 1, 
+   "export": 0, 
+   "if_owner": 0, 
+   "import": 0, 
+   "permlevel": 0, 
+   "print": 1, 
+   "read": 1, 
+   "report": 0, 
+   "role": "Hotel Manager", 
+   "set_user_permissions": 0, 
+   "share": 1, 
+   "submit": 0, 
+   "write": 1
+  }
+ ], 
+ "quick_entry": 0, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "restrict_to_domain": "Hospitality", 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 1, 
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/hotels/doctype/hotel_settings/hotel_settings.py b/erpnext/hotels/doctype/hotel_settings/hotel_settings.py
new file mode 100644
index 0000000..d78bca1
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_settings/hotel_settings.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class HotelSettings(Document):
+	pass
diff --git a/erpnext/hotels/doctype/hotel_settings/test_hotel_settings.js b/erpnext/hotels/doctype/hotel_settings/test_hotel_settings.js
new file mode 100644
index 0000000..bc0b7f8
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_settings/test_hotel_settings.js
@@ -0,0 +1,23 @@
+/* eslint-disable */
+// rename this file from _test_[name] to test_[name] to activate
+// and remove above this line
+
+QUnit.test("test: Hotel Settings", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Hotel Settings
+		() => frappe.tests.make('Hotel Settings', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/hotels/doctype/hotel_settings/test_hotel_settings.py b/erpnext/hotels/doctype/hotel_settings/test_hotel_settings.py
new file mode 100644
index 0000000..a081acc
--- /dev/null
+++ b/erpnext/hotels/doctype/hotel_settings/test_hotel_settings.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestHotelSettings(unittest.TestCase):
+	pass
diff --git a/erpnext/hotels/report/__init__.py b/erpnext/hotels/report/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hotels/report/__init__.py
diff --git a/erpnext/hotels/report/hotel_room_occupancy/__init__.py b/erpnext/hotels/report/hotel_room_occupancy/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hotels/report/hotel_room_occupancy/__init__.py
diff --git a/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.js b/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.js
new file mode 100644
index 0000000..81efb2d
--- /dev/null
+++ b/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.js
@@ -0,0 +1,22 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Hotel Room Occupancy"] = {
+	"filters": [
+		{
+			"fieldname":"from_date",
+			"label": __("From Date"),
+			"fieldtype": "Date",
+			"default": frappe.datetime.now_date(),
+			"reqd":1
+		},
+		{
+			"fieldname":"to_date",
+			"label": __("To Date"),
+			"fieldtype": "Date",
+			"default": frappe.datetime.now_date(),
+			"reqd":1
+		}
+	]
+}
diff --git a/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.json b/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.json
new file mode 100644
index 0000000..782a48b
--- /dev/null
+++ b/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.json
@@ -0,0 +1,26 @@
+{
+ "add_total_row": 1, 
+ "apply_user_permissions": 1, 
+ "creation": "2017-12-09 14:31:26.306705", 
+ "disabled": 0, 
+ "docstatus": 0, 
+ "doctype": "Report", 
+ "idx": 0, 
+ "is_standard": "Yes", 
+ "modified": "2017-12-09 14:31:26.306705", 
+ "modified_by": "Administrator", 
+ "module": "Hotels", 
+ "name": "Hotel Room Occupancy", 
+ "owner": "Administrator", 
+ "ref_doctype": "Hotel Room Reservation", 
+ "report_name": "Hotel Room Occupancy", 
+ "report_type": "Script Report", 
+ "roles": [
+  {
+   "role": "System Manager"
+  }, 
+  {
+   "role": "Hotel Reservation User"
+  }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.py b/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.py
new file mode 100644
index 0000000..aebeb45
--- /dev/null
+++ b/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.py
@@ -0,0 +1,33 @@
+# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+from frappe.utils import add_days, date_diff
+
+from erpnext.hotels.doctype.hotel_room_reservation.hotel_room_reservation import get_rooms_booked
+
+def execute(filters=None):
+	columns = get_columns(filters)
+	data = get_data(filters)
+	return columns, data
+
+def get_columns(filters):
+	columns = [
+		dict(label=_("Room Type"), fieldname="room_type"),
+		dict(label=_("Rooms Booked"), fieldtype="Int")
+	]
+	return columns
+
+def get_data(filters):
+	out = []
+	for room_type in frappe.get_all('Hotel Room Type'):
+		total_booked = 0
+		for i in xrange(date_diff(filters.to_date, filters.from_date)):
+			day = add_days(filters.from_date, i)
+			total_booked += get_rooms_booked(room_type.name, day)
+
+		out.append([room_type.name, total_booked])
+
+	return out
\ No newline at end of file
diff --git a/erpnext/hr/doctype/attendance/attendance.py b/erpnext/hr/doctype/attendance/attendance.py
index fd7344a..7b04f7d 100644
--- a/erpnext/hr/doctype/attendance/attendance.py
+++ b/erpnext/hr/doctype/attendance/attendance.py
@@ -21,7 +21,7 @@
 
 	def check_leave_record(self):
 		leave_record = frappe.db.sql("""select leave_type, half_day from `tabLeave Application`
-			where employee = %s and %s between from_date and to_date and workflow_state = 'Approved'
+			where employee = %s and %s between from_date and to_date
 			and docstatus = 1""", (self.employee, self.attendance_date), as_dict=True)
 		if leave_record:
 			if leave_record[0].half_day:
diff --git a/erpnext/hr/doctype/leave_application/leave_application.js b/erpnext/hr/doctype/leave_application/leave_application.js
index c2d8326..2e6e451 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.js
+++ b/erpnext/hr/doctype/leave_application/leave_application.js
@@ -10,15 +10,6 @@
 			frm.set_value("posting_date", frappe.datetime.get_today());
 		}
 
-		frm.set_query("leave_approver", function() {
-			return {
-				query: "erpnext.hr.doctype.leave_application.leave_application.get_approvers",
-				filters: {
-					employee: frm.doc.employee
-				}
-			};
-		});
-
 		frm.set_query("employee", erpnext.queries.employee);
 
 	},
@@ -29,14 +20,11 @@
 
 	refresh: function(frm) {
 		if (frm.is_new()) {
-			frm.set_value("workflow_state", "Open");
 			frm.trigger("calculate_total_days");
 		}
-	},
-
-	leave_approver: function(frm) {
-		if(frm.doc.leave_approver){
-			frm.set_value("leave_approver_name", frappe.user.full_name(frm.doc.leave_approver));
+		cur_frm.set_intro("");
+		if(frm.doc.__islocal && !in_list(frappe.user_roles, "Employee")) {
+			frm.set_intro(__("Fill the form and save it"));
 		}
 	},
 
diff --git a/erpnext/hr/doctype/leave_application/leave_application.json b/erpnext/hr/doctype/leave_application/leave_application.json
index 88b5a55..2435d06 100644
--- a/erpnext/hr/doctype/leave_application/leave_application.json
+++ b/erpnext/hr/doctype/leave_application/leave_application.json
@@ -433,96 +433,6 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fieldname": "column_break_15", 
-   "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": "", 
-   "fieldname": "leave_approver", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 1, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 1, 
-   "label": "Leave Approver", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "User", 
-   "permlevel": 0, 
-   "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": "leave_approver_name", 
-   "fieldtype": "Read Only", 
-   "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": "Leave Approver Name", 
-   "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": "sb10", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -736,7 +646,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 3, 
- "modified": "2018-01-22 12:10:40.757274", 
+ "modified": "2018-02-12 13:10:05.766762", 
  "modified_by": "Administrator", 
  "module": "HR", 
  "name": "Leave Application", 
@@ -885,7 +795,7 @@
    "submit": 0, 
    "write": 1
   }
- ], 
+ ],
  "quick_entry": 0, 
  "read_only": 0, 
  "read_only_onload": 0, 
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index 5be44af..22fd0e5 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -21,17 +21,10 @@
 from frappe.model.document import Document
 class LeaveApplication(Document):
 	def get_feed(self):
-		return _("{0}: From {0} of type {1}").format(self.workflow_state, self.employee_name, self.leave_type)
+		return _("{0}: From {0} of type {1}").format(self.employee_name, self.leave_type)
 
 	def validate(self):
-		if self.get("__islocal"): self.workflow_state = 'Open'
-		if not getattr(self, "__islocal", None) and frappe.db.exists(self.doctype, self.name):
-			self.previous_doc = frappe.get_value(self.doctype, self.name, "leave_approver", as_dict=True)
-		else:
-			self.previous_doc = None
-
 		set_employee_name(self)
-
 		self.validate_dates()
 		self.validate_balance_leaves()
 		self.validate_leave_overlap()
@@ -39,22 +32,12 @@
 		self.show_block_day_warning()
 		self.validate_block_days()
 		self.validate_salary_processed_days()
-		self.validate_leave_approver()
 		self.validate_attendance()
 
-	def on_update(self):
-		if (not self.previous_doc and self.leave_approver) or (self.previous_doc and \
-				self.workflow_state == "Open" and self.previous_doc.leave_approver != self.leave_approver):
-			# notify leave approver about creation
-			self.notify_leave_approver()
-
 	def on_submit(self):
 
 		self.validate_back_dated_application()
 
-		# notify leave applier about approval
-		self.notify_employee(self.workflow_state)
-
 	def on_cancel(self):
 		# notify leave applier about cancellation
 		self.notify_employee("cancelled")
@@ -128,7 +111,7 @@
 		block_dates = get_applicable_block_dates(self.from_date, self.to_date,
 			self.employee, self.company)
 
-		if block_dates and self.workflow_state == "Approved":
+		if block_dates and self.docstatus == 1:
 			frappe.throw(_("You are not authorized to approve leaves on Block Dates"), LeaveDayBlockedError)
 
 	def validate_balance_leaves(self):
@@ -143,7 +126,7 @@
 				self.leave_balance = get_leave_balance_on(self.employee, self.leave_type, self.from_date,
 					consider_all_leaves_in_the_allocation_period=True)
 
-				if self.workflow_state != "Rejected" and self.leave_balance < self.total_leave_days:
+				if self.leave_balance < self.total_leave_days:
 					if frappe.db.get_value("Leave Type", self.leave_type, "allow_negative"):
 						frappe.msgprint(_("Note: There is not enough leave balance for Leave Type {0}")
 							.format(self.leave_type))
@@ -160,7 +143,7 @@
 			select
 				name, leave_type, posting_date, from_date, to_date, total_leave_days, half_day_date
 			from `tabLeave Application`
-			where employee = %(employee)s and docstatus < 2 and workflow_state in ("Open", "Approved")
+			where employee = %(employee)s and docstatus < 2
 			and to_date >= %(from_date)s and from_date <= %(to_date)s
 			and name != %(name)s""", {
 				"employee": self.employee,
@@ -190,7 +173,6 @@
 		leave_count_on_half_day_date = frappe.db.sql("""select count(name) from `tabLeave Application`
 			where employee = %(employee)s
 			and docstatus < 2
-			and workflow_state in ("Open", "Approved")
 			and half_day = 1
 			and half_day_date = %(half_day_date)s
 			and name != %(name)s""", {
@@ -206,23 +188,6 @@
 		if max_days and self.total_leave_days > cint(max_days):
 			frappe.throw(_("Leave of type {0} cannot be longer than {1}").format(self.leave_type, max_days))
 
-	def validate_leave_approver(self):
-		employee = frappe.get_doc("Employee", self.employee)
-		leave_approvers = [l.leave_approver for l in employee.get("leave_approvers")]
-
-		if len(leave_approvers) and self.leave_approver not in leave_approvers:
-			frappe.throw(_("Leave approver must be one of {0}")
-				.format(comma_or(leave_approvers)), InvalidLeaveApproverError)
-
-		elif self.leave_approver and not frappe.db.sql("""select name from `tabHas Role`
-			where parent=%s and role='Leave Approver'""", self.leave_approver):
-			frappe.throw(_("{0} ({1}) must have role 'Leave Approver'")\
-				.format(get_fullname(self.leave_approver), self.leave_approver), InvalidLeaveApproverError)
-
-		elif self.docstatus==1 and len(leave_approvers) and self.leave_approver != frappe.session.user:
-			frappe.throw(_("Only the selected Leave Approver can submit this Leave Application"),
-				LeaveApproverIdentityError)
-
 	def validate_attendance(self):
 		attendance = frappe.db.sql("""select name from `tabAttendance` where employee = %s and (attendance_date between %s and %s)
 					and status = "Present" and docstatus = 1""",
@@ -231,7 +196,7 @@
 			frappe.throw(_("Attendance for employee {0} is already marked for this day").format(self.employee),
 				AttendanceAlreadyMarkedError)
 
-	def notify_employee(self, workflow_state):
+	def notify_employee(self):
 		employee = frappe.get_doc("Employee", self.employee)
 		if not employee.user_id:
 			return
@@ -246,19 +211,15 @@
 			message += "Leave Type: {leave_type}".format(leave_type=self.leave_type)+"<br>"
 			message += "From Date: {from_date}".format(from_date=self.from_date)+"<br>"
 			message += "To Date: {to_date}".format(to_date=self.to_date)+"<br>"
-			message += "Status: {workflow_state}".format(workflow_state=_(workflow_state))
 			return message
 
 		self.notify({
 			# for post in messages
 			"message": _get_message(url=True),
 			"message_to": employee.user_id,
-			"subject": (_("Leave Application") + ": %s - %s") % (self.name, _(workflow_state))
+			"subject": (_("Leave Application") + ": %s - %s") % (self.name)
 		})
 
-	def notify_leave_approver(self):
-		employee = frappe.get_doc("Employee", self.employee)
-
 		def _get_message(url=False):
 			name = self.name
 			employee_name = cstr(employee.employee_name)
@@ -275,7 +236,6 @@
 		self.notify({
 			# for post in messages
 			"message": _get_message(url=True),
-			"message_to": self.leave_approver,
 
 			# for email
 			"subject": (_("New Leave Application") + ": %s - " + _("Employee") + ": %s") % (self.name, cstr(employee.employee_name))
@@ -321,23 +281,6 @@
 				pass
 
 @frappe.whitelist()
-def get_approvers(doctype, txt, searchfield, start, page_len, filters):
-	if not filters.get("employee"):
-		frappe.throw(_("Please select Employee Record first."))
-
-	employee_user = frappe.get_value("Employee", filters.get("employee"), "user_id")
-
-	approvers_list = frappe.db.sql("""select user.name, user.first_name, user.last_name from
-		tabUser user, `tabEmployee Leave Approver` approver where
-		approver.parent = %s
-		and user.name like %s
-		and approver.leave_approver=user.name""", (filters.get("employee"), "%" + txt + "%"))
-
-	if not approvers_list:
-		approvers_list = get_approver_list(employee_user)
-	return approvers_list
-
-@frappe.whitelist()
 def get_number_of_leave_days(employee, leave_type, from_date, to_date, half_day = None, half_day_date = None):
 	number_of_days = 0
 	if half_day == 1:
@@ -371,7 +314,7 @@
 		select employee, leave_type, from_date, to_date, total_leave_days
 		from `tabLeave Application`
 		where employee=%(employee)s and leave_type=%(leave_type)s
-			and workflow_state="Approved" and docstatus=1
+			and docstatus=1
 			and (from_date between %(from_date)s and %(to_date)s
 				or to_date between %(from_date)s and %(to_date)s
 				or (from_date < %(from_date)s and to_date > %(to_date)s))
@@ -471,11 +414,10 @@
 
 def add_leaves(events, start, end, match_conditions=None):
 	query = """select name, from_date, to_date, employee_name, half_day,
-		workflow_state, employee, docstatus
+		employee, docstatus
 		from `tabLeave Application` where
 		from_date <= %(end)s and to_date >= %(start)s <= to_date
-		and docstatus < 2
-		and workflow_state!="Rejected" """
+		and docstatus < 2"""
 	if match_conditions:
 		query += match_conditions
 
@@ -485,7 +427,6 @@
 			"doctype": "Leave Application",
 			"from_date": d.from_date,
 			"to_date": d.to_date,
-			"workflow_state": d.workflow_state,
 			"title": cstr(d.employee_name) + \
 				(d.half_day and _(" (Half Day)") or ""),
 			"docstatus": d.docstatus
diff --git a/erpnext/hr/doctype/leave_application/leave_application_calendar.js b/erpnext/hr/doctype/leave_application/leave_application_calendar.js
index b06b40f..0286f30 100644
--- a/erpnext/hr/doctype/leave_application/leave_application_calendar.js
+++ b/erpnext/hr/doctype/leave_application/leave_application_calendar.js
@@ -7,7 +7,7 @@
 		"end": "to_date",
 		"id": "name",
 		"title": "title",
-		"workflow_state": "workflow_state",
+		"docstatus": 1
 	},
 	options: {
 		header: {
diff --git a/erpnext/hr/doctype/leave_application/leave_application_list.js b/erpnext/hr/doctype/leave_application/leave_application_list.js
index 7798ae7..d7588da 100644
--- a/erpnext/hr/doctype/leave_application/leave_application_list.js
+++ b/erpnext/hr/doctype/leave_application/leave_application_list.js
@@ -1,7 +1,3 @@
 frappe.listview_settings['Leave Application'] = {
-	add_fields: ["workflow_state", "leave_type", "employee", "employee_name", "total_leave_days", "from_date", "to_date"],
-	get_indicator: function(doc) {
-		return [__(doc.workflow_state), frappe.utils.guess_colour(doc.workflow_state),
-			"workflow_state,=," + doc.workflow_state];
-	}
+	add_fields: ["leave_type", "employee", "employee_name", "total_leave_days", "from_date", "to_date"]
 };
diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.js b/erpnext/hr/doctype/leave_application/test_leave_application.js
index 6d51b71..6d7b6a7 100644
--- a/erpnext/hr/doctype/leave_application/test_leave_application.js
+++ b/erpnext/hr/doctype/leave_application/test_leave_application.js
@@ -16,7 +16,6 @@
 				{to_date: leave_date},
 				{half_day: 1},
 				{employee: employee.message.name},
-				{leave_approver: "Administrator"},
 				{follow_via_email: 0}
 			]);
 		},
@@ -36,8 +35,8 @@
 		() => frappe.set_route("List", "Leave Application", "List"),
 		() => frappe.timeout(1),
 		// // check approved application in list
-		() => assert.deepEqual(["Test Employee 1", "Approved"], [cur_list.data[0].employee_name, cur_list.data[0].workflow_state]),
-		// 	"leave for correct employee is approved"),
+		() => assert.deepEqual(["Test Employee 1", 1], [cur_list.data[0].employee_name, cur_list.data[0].docstatus]),
+		// 	"leave for correct employee is submitted"),
 		() => done()
 	]);
 });
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.py b/erpnext/hr/doctype/leave_application/test_leave_application.py
index b2f6054..520d7c9 100644
--- a/erpnext/hr/doctype/leave_application/test_leave_application.py
+++ b/erpnext/hr/doctype/leave_application/test_leave_application.py
@@ -103,7 +103,6 @@
 
 		application = self.get_application(_test_records[0])
 		application.insert()
-		application.workflow_state = "Approved"
 		self.assertRaises(LeaveDayBlockedError, application.submit)
 
 		frappe.set_user("test1@example.com")
@@ -127,11 +126,9 @@
 		make_allocation_record()
 
 		application = self.get_application(_test_records[0])
-		application.leave_approver = "test2@example.com"
 		application.insert()
 
 		application = self.get_application(_test_records[0])
-		application.leave_approver = "test2@example.com"
 		self.assertRaises(OverlapError, application.insert)
 
 	def test_overlap_with_half_day_1(self):
@@ -148,14 +145,12 @@
 
 		# leave from 1-5, half day on 3rd
 		application = self.get_application(_test_records[0])
-		application.leave_approver = "test2@example.com"
 		application.half_day = 1
 		application.half_day_date = "2013-01-03"
 		application.insert()
 
 		# Apply again for a half day leave on 3rd
 		application = self.get_application(_test_records[0])
-		application.leave_approver = "test2@example.com"
 		application.from_date = "2013-01-03"
 		application.to_date = "2013-01-03"
 		application.half_day = 1
@@ -164,7 +159,6 @@
 
 		# Apply again for a half day leave on 3rd
 		application = self.get_application(_test_records[0])
-		application.leave_approver = "test2@example.com"
 		application.from_date = "2013-01-03"
 		application.to_date = "2013-01-03"
 		application.half_day = 1
@@ -186,12 +180,10 @@
 
 		# leave from 1-5, no half day
 		application = self.get_application(_test_records[0])
-		application.leave_approver = "test2@example.com"
 		application.insert()
 
 		# Apply again for a half day leave on 1st
 		application = self.get_application(_test_records[0])
-		application.leave_approver = "test2@example.com"
 		application.half_day = 1
 		application.half_day_date = application.from_date
 
@@ -211,14 +203,12 @@
 
 		# leave from 1-5, half day on 5th
 		application = self.get_application(_test_records[0])
-		application.leave_approver = "test2@example.com"
 		application.half_day = 1
 		application.half_day_date = "2013-01-05"
 		application.insert()
 		
 		# Apply leave from 4-7, half day on 5th
 		application = self.get_application(_test_records[0])
-		application.leave_approver = "test2@example.com"
 		application.from_date = "2013-01-04"
 		application.to_date = "2013-01-07"
 		application.half_day = 1
@@ -228,7 +218,6 @@
 
 		# Apply leave from 5-7, half day on 5th
 		application = self.get_application(_test_records[0])
-		application.leave_approver = "test2@example.com"
 		application.from_date = "2013-01-05"
 		application.to_date = "2013-01-07"
 		application.half_day = 1
@@ -246,7 +235,6 @@
 		make_allocation_record(employee="_T-Employee-0002")
 
 		application = self.get_application(_test_records[1])
-		application.leave_approver = "test@example.com"
 
 		frappe.db.set_value("Leave Block List", "_Test Leave Block List",
 			"applies_to_all_departments", 1)
@@ -257,7 +245,6 @@
 		application.insert()
 
 		frappe.set_user("test@example.com")
-		application.workflow_state = "Approved"
 
 		# clear permlevel access cache on change user
 		del application._has_access_to
@@ -267,114 +254,6 @@
 		frappe.db.set_value("Leave Block List", "_Test Leave Block List",
 			"applies_to_all_departments", 0)
 
-	def test_leave_approval(self):
-		self._clear_roles()
-
-		from frappe.utils.user import add_role
-		add_role("test@example.com", "Employee")
-		add_role("test1@example.com", "HR User")
-		add_role("test1@example.com", "Leave Approver")
-		add_role("test2@example.com", "Leave Approver")
-
-		self._test_leave_approval_basic_case()
-		self._test_leave_approval_invalid_leave_approver_insert()
-		self._test_leave_approval_invalid_leave_approver_submit()
-		self._test_leave_approval_valid_leave_approver_insert()
-
-	def _test_leave_approval_basic_case(self):
-		self._clear_applications()
-
-		self._add_employee_leave_approver("_T-Employee-0001", "test1@example.com")
-
-		# create leave application as Employee
-		frappe.set_user("test@example.com")
-
-		make_allocation_record()
-
-		application = self.get_application(_test_records[0])
-		application.leave_approver = "test1@example.com"
-		application.insert()
-
-		# submit leave application by Leave Approver
-		frappe.set_user("test1@example.com")
-		application.workflow_state = "Approved"
-		del application._has_access_to
-		application.submit()
-		self.assertEqual(frappe.db.get_value("Leave Application", application.name,
-			"docstatus"), 1)
-
-	def _test_leave_approval_invalid_leave_approver_insert(self):
-		from erpnext.hr.doctype.leave_application.leave_application import InvalidLeaveApproverError
-
-		self._clear_applications()
-
-		# add a different leave approver in the employee's list
-		# should raise exception if not a valid leave approver
-		self._add_employee_leave_approver("_T-Employee-0001", "test2@example.com")
-		self._remove_employee_leave_approver("_T-Employee-0001", "test1@example.com")
-
-		make_allocation_record()
-
-		application = self.get_application(_test_records[0])
-		frappe.set_user("test@example.com")
-
-		application.leave_approver = "test1@example.com"
-		self.assertRaises(InvalidLeaveApproverError, application.insert)
-
-		frappe.db.sql("""delete from `tabEmployee Leave Approver` where parent=%s""",
-			"_T-Employee-0001")
-
-	def _test_leave_approval_invalid_leave_approver_submit(self):
-		self._clear_applications()
-		self._add_employee_leave_approver("_T-Employee-0001", "test2@example.com")
-
-		# create leave application as employee
-		# but submit as invalid leave approver - should raise exception
-		frappe.set_user("test@example.com")
-
-		make_allocation_record()
-
-		application = self.get_application(_test_records[0])
-		application.leave_approver = "test2@example.com"
-		application.insert()
-		frappe.set_user("test1@example.com")
-		del application._has_access_to
-		application.workflow_state = "Approved"
-
-		from erpnext.hr.doctype.leave_application.leave_application import LeaveApproverIdentityError
-		self.assertRaises(LeaveApproverIdentityError, application.submit)
-
-		frappe.db.sql("""delete from `tabEmployee Leave Approver` where parent=%s""",
-			"_T-Employee-0001")
-
-	def _test_leave_approval_valid_leave_approver_insert(self):
-		self._clear_applications()
-		self._add_employee_leave_approver("_T-Employee-0001", "test2@example.com")
-
-		original_department = frappe.db.get_value("Employee", "_T-Employee-0001", "department")
-		frappe.db.set_value("Employee", "_T-Employee-0001", "department", None)
-
-		frappe.set_user("test@example.com")
-
-		make_allocation_record()
-
-		application = self.get_application(_test_records[0])
-		application.leave_approver = "test2@example.com"
-		application.insert()
-
-		# change to valid leave approver and try to submit leave application
-		frappe.set_user("test2@example.com")
-		application.workflow_state = "Approved"
-		del application._has_access_to
-		application.submit()
-		self.assertEqual(frappe.db.get_value("Leave Application", application.name,
-			"docstatus"), 1)
-
-		frappe.db.sql("""delete from `tabEmployee Leave Approver` where parent=%s""",
-			"_T-Employee-0001")
-
-		frappe.db.set_value("Employee", "_T-Employee-0001", "department", original_department)
-
 def make_allocation_record(employee=None, leave_type=None):
 	frappe.db.sql("delete from `tabLeave Allocation`")
 
@@ -388,4 +267,4 @@
 	})
 
 	allocation.insert(ignore_permissions=True)
-	allocation.submit()
+	allocation.submit()
\ No newline at end of file
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py
index 878c6b4..da2598f 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.py
@@ -300,7 +300,6 @@
 				where t2.name = t1.leave_type
 				and t2.is_lwp = 1
 				and t1.docstatus = 1
-				and t1.workflow_state = 'Approved'
 				and t1.employee = %(employee)s
 				and CASE WHEN t2.include_holiday != 1 THEN %(dt)s not in ('{0}') and %(dt)s between from_date and to_date
 				WHEN t2.include_holiday THEN %(dt)s between from_date and to_date
diff --git a/erpnext/modules.txt b/erpnext/modules.txt
index 42f0f0b..d469145 100644
--- a/erpnext/modules.txt
+++ b/erpnext/modules.txt
@@ -20,4 +20,5 @@
 Restaurant
 Agriculture
 ERPNext Integrations
-Non Profit
\ No newline at end of file
+Non Profit
+Hotels
\ No newline at end of file
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 6f4c63e..69d8a47 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -489,7 +489,8 @@
 erpnext.patches.v10_0.update_assessment_plan
 erpnext.patches.v10_0.update_assessment_result
 erpnext.patches.v10_0.added_extra_gst_custom_field
-erpnext.patches.v10_0.workflow_leave_application #2018-01-24
+erpnext.patches.v10_0.workflow_leave_application #2018-01-24 #2018-02-02 #2018-02-08
 erpnext.patches.v10_0.set_default_payment_terms_based_on_company
 erpnext.patches.v10_0.update_sales_order_link_to_purchase_order
 erpnext.patches.v10_0.added_extra_gst_custom_field_in_gstr2
+erpnext.patches.v10_0.item_barcode_childtable_migrate
diff --git a/erpnext/patches/v10_0/item_barcode_childtable_migrate.py b/erpnext/patches/v10_0/item_barcode_childtable_migrate.py
new file mode 100644
index 0000000..d985bbf
--- /dev/null
+++ b/erpnext/patches/v10_0/item_barcode_childtable_migrate.py
@@ -0,0 +1,22 @@
+# Copyright (c) 2017, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+
+import frappe
+
+
+def execute():
+	items_barcode = frappe.db.sql("""SELECT name, barcode FROM tabItem
+		WHERE barcode IS NOT NULL and barcode != ''""", as_dict=1)
+
+	frappe.reload_doc("stock", "doctype", "item")
+	frappe.reload_doc("stock", "doctype", "item_barcode")
+
+	for item in items_barcode:
+		doc = frappe.get_doc("Item", item.get("name"))
+		if item.get("barcode"):
+			doc.append("barcodes", {"barcode": item.get("barcode")})
+			doc.flags.ignore_validate = True
+			doc.flags.ignore_mandatory = True
+			doc.save()
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/workflow_leave_application.py b/erpnext/patches/v10_0/workflow_leave_application.py
index 8a68f89..0d33402 100644
--- a/erpnext/patches/v10_0/workflow_leave_application.py
+++ b/erpnext/patches/v10_0/workflow_leave_application.py
@@ -3,11 +3,66 @@
 
 from __future__ import unicode_literals
 import frappe
-from erpnext.setup.install import leave_application_workflow
 
 def execute():
-	frappe.reload_doc("hr", "doctype", "leave_application")
-	frappe.reload_doc("workflow", "doctype", "workflow")
-	leave_application_workflow()
-	if frappe.db.has_column("Leave Application", "status"):
-		frappe.db.sql("""update `tabLeave Application` set workflow_state = status""")
+	if frappe.db.a_row_exists("Leave Application"):
+		frappe.reload_doc("hr", "doctype", "leave_application")
+		frappe.reload_doc("workflow", "doctype", "workflow")
+		states = {'Approved': 'Success', 'Rejected': 'Danger', 'Open': 'Warning'}
+
+		for state, style in states.items():
+			if not frappe.db.exists("Workflow State", state):
+				frappe.get_doc({
+					'doctype': 'Workflow State',
+					'workflow_state_name': state,
+					'style': style
+				}).insert(ignore_permissions=True)
+
+		for action in ['Approve', 'Reject']:
+			if not frappe.db.exists("Workflow Action", action):
+				frappe.get_doc({
+					'doctype': 'Workflow Action',
+					'workflow_action_name': action
+				}).insert(ignore_permissions=True)
+
+		if not frappe.db.exists("Workflow", "Leave Approval"):
+			frappe.get_doc({
+				'doctype': 'Workflow',
+				'workflow_name': 'Leave Approval',
+				'document_type': 'Leave Application',
+				'is_active': 1,
+				'workflow_state_field': 'workflow_state',
+				'states': [{
+					"state": 'Open',
+					"doc_status": 0,
+					"allow_edit": 'Employee'
+				}, {
+					"state": 'Approved',
+					"doc_status": 1,
+					"allow_edit": 'Leave Approver'
+				}, {
+					"state": 'Rejected',
+					"doc_status": 0,
+					"allow_edit": 'Leave Approver'
+				}],
+				'transitions': [{
+					"state": 'Open',
+					"action": 'Approve',
+					"next_state": 'Approved',
+					"allowed": 'Leave Approver'
+				},
+				{
+					"state": 'Open',
+					"action": 'Reject',
+					"next_state": 'Rejected',
+					"allowed": 'Leave Approver'
+				}]
+			}).insert(ignore_permissions=True)
+
+		if frappe.db.has_column("Leave Application", "status"):
+			frappe.db.sql("""update `tabLeave Application` set workflow_state = status""")
+
+		if frappe.db.has_column("Leave Application", "workflow_state"):
+			frappe.db.sql("""update `tabWorkflow Document State` set doc_status = 0 where parent = "Leave Approval" \
+			and state = "Rejected" and doc_status = 1""")
+			frappe.db.sql("""update `tabLeave Application` set docstatus = 0  where workflow_state = "Rejected" and docstatus = 1""")
diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js
index 1eeb896..29e3999 100644
--- a/erpnext/public/js/financial_statements.js
+++ b/erpnext/public/js/financial_statements.js
@@ -98,6 +98,16 @@
 			],
 			"default": "Monthly",
 			"reqd": 1
+		},
+		// Note:
+		// If you are modifying this array such that the presentation_currency object
+		// is no longer the last object, please make adjustments in cash_flow.js
+		// accordingly.
+		{
+			"fieldname": "presentation_currency",
+			"label": __("Currency"),
+			"fieldtype": "Select",
+			"options": erpnext.get_presentation_currency_list()
 		}
 	]
 }
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index 6841354..d50fa19 100644
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -13,6 +13,12 @@
 			return frappe.boot.sysdefaults.currency;
 	},
 
+	get_presentation_currency_list: () => {
+		const docs = frappe.boot.docs;
+		const currency_list = docs.filter(d => d.doctype === ":Currency").map(d => d.name);
+		return currency_list;
+	},
+
 	toggle_naming_series: function() {
 		if(cur_frm.fields_dict.naming_series) {
 			cur_frm.toggle_display("naming_series", cur_frm.doc.__islocal?true:false);
diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js
index a4d7265..0fb8730 100644
--- a/erpnext/public/js/utils/serial_no_batch_selector.js
+++ b/erpnext/public/js/utils/serial_no_batch_selector.js
@@ -215,7 +215,7 @@
 						in_list_view:1,
 						get_query: function() {
 							return {
-							    filters: {item_code: me.item_code },
+							    filters: {item: me.item_code },
 							    query: 'erpnext.controllers.queries.get_batch_numbers'
 					        };
 						},
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index fa0a448..c11337a 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -107,7 +107,7 @@
 		dict(fieldname='reason_for_issuing_document', label='Reason For Issuing document',
 			fieldtype='Select', insert_after='gst_col_break', print_hide=1,
 			depends_on='eval:doc.is_return==1', reqd=1,
-			options='\n01-Sales Return\n02-Post Sale Discount\n03-Deficiency in services\n04-Correction in Invoice\n05-Change in POS\n06-Finalization of Provisional assessment\n07-Others', default='01-Sales Return')
+			options='\n01-Sales Return\n02-Post Sale Discount\n03-Deficiency in services\n04-Correction in Invoice\n05-Change in POS\n06-Finalization of Provisional assessment\n07-Others')
 	]
 
 	purchase_invoice_gst_fields = [
diff --git a/erpnext/restaurant/doctype/restaurant/restaurant.json b/erpnext/restaurant/doctype/restaurant/restaurant.json
index f4ecba7..8572687 100644
--- a/erpnext/restaurant/doctype/restaurant/restaurant.json
+++ b/erpnext/restaurant/doctype/restaurant/restaurant.json
@@ -4,7 +4,7 @@
  "allow_import": 0, 
  "allow_rename": 0, 
  "autoname": "prompt", 
- "beta": 0, 
+ "beta": 1, 
  "creation": "2017-09-15 12:40:41.546933", 
  "custom": 0, 
  "docstatus": 0, 
@@ -269,7 +269,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2017-10-05 17:41:14.422242", 
+ "modified": "2017-12-09 12:13:10.185496", 
  "modified_by": "Administrator", 
  "module": "Restaurant", 
  "name": "Restaurant", 
diff --git a/erpnext/restaurant/doctype/restaurant_menu/restaurant_menu.json b/erpnext/restaurant/doctype/restaurant_menu/restaurant_menu.json
index 264634b..1b1610d 100644
--- a/erpnext/restaurant/doctype/restaurant_menu/restaurant_menu.json
+++ b/erpnext/restaurant/doctype/restaurant_menu/restaurant_menu.json
@@ -4,7 +4,7 @@
  "allow_import": 0, 
  "allow_rename": 0, 
  "autoname": "prompt", 
- "beta": 0, 
+ "beta": 1, 
  "creation": "2017-09-15 12:48:29.818715", 
  "custom": 0, 
  "docstatus": 0, 
@@ -207,7 +207,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2017-09-21 11:04:20.671542", 
+ "modified": "2017-12-09 12:13:13.684500", 
  "modified_by": "Administrator", 
  "module": "Restaurant", 
  "name": "Restaurant Menu", 
diff --git a/erpnext/restaurant/doctype/restaurant_reservation/restaurant_reservation.json b/erpnext/restaurant/doctype/restaurant_reservation/restaurant_reservation.json
index 6a2ffa1..0698758 100644
--- a/erpnext/restaurant/doctype/restaurant_reservation/restaurant_reservation.json
+++ b/erpnext/restaurant/doctype/restaurant_reservation/restaurant_reservation.json
@@ -4,7 +4,7 @@
  "allow_import": 0, 
  "allow_rename": 0, 
  "autoname": "REST.######", 
- "beta": 0, 
+ "beta": 1, 
  "creation": "2017-09-15 13:05:51.063661", 
  "custom": 0, 
  "docstatus": 0, 
@@ -297,7 +297,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2017-09-15 14:40:56.759315", 
+ "modified": "2017-12-09 12:13:20.027942", 
  "modified_by": "Administrator", 
  "module": "Restaurant", 
  "name": "Restaurant Reservation", 
diff --git a/erpnext/restaurant/doctype/restaurant_table/restaurant_table.json b/erpnext/restaurant/doctype/restaurant_table/restaurant_table.json
index da1bcde..5fc6e62 100644
--- a/erpnext/restaurant/doctype/restaurant_table/restaurant_table.json
+++ b/erpnext/restaurant/doctype/restaurant_table/restaurant_table.json
@@ -4,7 +4,7 @@
  "allow_import": 0, 
  "allow_rename": 0, 
  "autoname": "", 
- "beta": 0, 
+ "beta": 1, 
  "creation": "2017-09-15 12:45:24.717355", 
  "custom": 0, 
  "docstatus": 0, 
@@ -116,7 +116,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2017-09-15 13:18:05.254106", 
+ "modified": "2017-12-09 12:13:24.382345", 
  "modified_by": "Administrator", 
  "module": "Restaurant", 
  "name": "Restaurant Table", 
diff --git a/erpnext/selling/doctype/customer/customer.js b/erpnext/selling/doctype/customer/customer.js
index 92734cc..ed8e6c8 100644
--- a/erpnext/selling/doctype/customer/customer.js
+++ b/erpnext/selling/doctype/customer/customer.js
@@ -33,7 +33,38 @@
 				}
 			}
 		})
+		frm.set_query('customer_primary_address', function(doc) {
+			return {
+				query: "erpnext.selling.doctype.customer.customer.get_customer_primary_address",
+				filters: {
+					'customer': doc.name
+				}
+			}
+		})
 	},
+	customer_primary_address: function(frm){
+		if(frm.doc.customer_primary_address){
+			frappe.call({
+				method: 'frappe.contacts.doctype.address.address.get_address_display',
+				args: {
+					"address_dict": frm.doc.customer_primary_address
+				},
+				callback: function(r) {
+					frm.set_value("primary_address", r.message);
+				}
+			});
+		}
+		if(!frm.doc.customer_primary_address){
+			frm.set_value("primary_address", "");
+		}
+	},
+	customer_primary_contact: function(frm){
+		if(!frm.doc.customer_primary_contact){
+			frm.set_value("mobile_no", "");
+			frm.set_value("email_id", "");
+		}
+	},
+
 	refresh: function(frm) {
 		if(frappe.defaults.get_default("cust_master_name")!="Naming Series") {
 			frm.toggle_display("naming_series", false);
@@ -43,7 +74,7 @@
 
 		frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Customer'}
 
-		frm.toggle_display(['address_html','contact_html','primary_contact_detail'], !frm.doc.__islocal);
+		frm.toggle_display(['address_html','contact_html','primary_address_and_contact_detail'], !frm.doc.__islocal);
 
 		if(!frm.doc.__islocal) {
 			frappe.contacts.render_address_and_contact(frm);
@@ -72,4 +103,4 @@
 	validate: function(frm) {
 		if(frm.doc.lead_name) frappe.model.clear_doc("Lead", frm.doc.lead_name);
 	},
-});
+});
\ No newline at end of file
diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json
index b2577d5..d43de10 100644
--- a/erpnext/selling/doctype/customer/customer.json
+++ b/erpnext/selling/doctype/customer/customer.json
@@ -725,7 +725,8 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fieldname": "primary_contact_detail", 
+   "description": "Select, to make the customer searchable with these fields", 
+   "fieldname": "primary_address_and_contact_detail", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
@@ -734,7 +735,7 @@
    "in_global_search": 0, 
    "in_list_view": 0, 
    "in_standard_filter": 0, 
-   "label": "Primary Contact Detail", 
+   "label": "Primary Address and Contact Detail", 
    "length": 0, 
    "no_copy": 0, 
    "permlevel": 0, 
@@ -755,6 +756,7 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "description": "Reselect, if the chosen contact is edited after save", 
    "fieldname": "customer_primary_contact", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -786,6 +788,68 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fieldname": "mobile_no", 
+   "fieldtype": "Read Only", 
+   "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": "Mobile No", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "customer_primary_contact.mobile_no", 
+   "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": "email_id", 
+   "fieldtype": "Read Only", 
+   "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": "Email Id", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "customer_primary_contact.email_id", 
+   "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": "column_break_26", 
    "fieldtype": "Column Break", 
    "hidden": 0, 
@@ -815,8 +879,9 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fieldname": "mobile_no", 
-   "fieldtype": "Read Only", 
+   "description": "Reselect, if the chosen address is edited after save", 
+   "fieldname": "customer_primary_address", 
+   "fieldtype": "Link", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
@@ -824,10 +889,10 @@
    "in_global_search": 0, 
    "in_list_view": 0, 
    "in_standard_filter": 0, 
-   "label": "Mobile Number", 
+   "label": "Customer Primary Address", 
    "length": 0, 
    "no_copy": 0, 
-   "options": "customer_primary_contact.mobile_no", 
+   "options": "Address", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -846,7 +911,8 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fieldname": "email_id", 
+   "default": "", 
+   "fieldname": "primary_address", 
    "fieldtype": "Read Only", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
@@ -855,10 +921,10 @@
    "in_global_search": 0, 
    "in_list_view": 0, 
    "in_standard_filter": 0, 
-   "label": "Email Id", 
+   "label": "Primary Address", 
    "length": 0, 
    "no_copy": 0, 
-   "options": "customer_primary_contact.email_id", 
+   "options": "", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -1383,7 +1449,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2018-01-30 11:52:05.497363", 
+ "modified": "2018-02-09 10:44:35.801716", 
  "modified_by": "Administrator", 
  "module": "Selling", 
  "name": "Customer", 
@@ -1574,7 +1640,7 @@
  "quick_entry": 1, 
  "read_only": 0, 
  "read_only_onload": 0, 
- "search_fields": "customer_name,customer_group,territory, mobile_no", 
+ "search_fields": "customer_name,customer_group,territory, mobile_no,primary_address", 
  "show_name_in_global_search": 1, 
  "sort_order": "ASC", 
  "title_field": "customer_name", 
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index 2284f85..6f25bf7 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -309,3 +309,15 @@
 			'customer': customer,
 			'txt': '%%%s%%' % txt
 		})
+
+def get_customer_primary_address(doctype, txt, searchfield, start, page_len, filters):
+	customer = frappe.db.escape(filters.get('customer'))
+	return frappe.db.sql("""
+		select `tabAddress`.name from `tabAddress`, `tabDynamic Link`
+			where `tabAddress`.name = `tabDynamic Link`.parent and `tabDynamic Link`.link_name = %(customer)s
+			and `tabDynamic Link`.link_doctype = 'Customer' and `tabAddress`.is_primary_address = 1
+			and `tabAddress`.name like %(txt)s
+		""", {
+			'customer': customer,
+			'txt': '%%%s%%' % txt
+		})
\ No newline at end of file
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 4f0d250..666284f 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.py
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.py
@@ -29,7 +29,7 @@
 				batch_no, item_code = batch_no_data
 
 		if not serial_no and not batch_no:
-			barcode_data = frappe.db.get_value('Item', {'barcode': search_value}, ['name', 'barcode'])
+			barcode_data = frappe.db.get_value('Item Barcode', {'barcode': search_value}, ['parent', 'barcode'])
 			if barcode_data:
 				item_code, barcode = barcode_data
 
diff --git a/erpnext/setup/install.py b/erpnext/setup/install.py
index 2cc280f..81f909a 100644
--- a/erpnext/setup/install.py
+++ b/erpnext/setup/install.py
@@ -12,7 +12,6 @@
 	<a style="color: #888" href="http://erpnext.org">ERPNext</a></div>"""
 
 def after_install():
-	leave_application_workflow()
 	frappe.get_doc({'doctype': "Role", "role_name": "Analytics"}).insert()
 	set_single_defaults()
 	create_compact_item_print_custom_field()
@@ -20,58 +19,6 @@
 	add_all_roles_to("Administrator")
 	frappe.db.commit()
 
-def leave_application_workflow():
-	states = {'Approved': 'Success', 'Rejected': 'Danger', 'Open': 'Warning'}
-
-	for state, style in states.items():
-		if not frappe.db.exists("Workflow State", state):
-			frappe.get_doc({
-				'doctype': 'Workflow State',
-				'workflow_state_name': state,
-				'style': style
-			}).insert(ignore_permissions=True)
-
-	for action in ['Approve', 'Reject']:
-		if not frappe.db.exists("Workflow Action", action):
-			frappe.get_doc({
-				'doctype': 'Workflow Action',
-				'workflow_action_name': action
-			}).insert(ignore_permissions=True)
-
-	if not frappe.db.exists("Workflow", "Leave Approval"):
-		frappe.get_doc({
-			'doctype': 'Workflow',
-			'workflow_name': 'Leave Approval',
-			'document_type': 'Leave Application',
-			'is_active': 1,
-			'workflow_state_field': 'workflow_state',
-			'states': [{
-				"state": 'Open',
-				"doc_status": 0,
-				"allow_edit": 'Employee'
-			}, {
-				"state": 'Approved',
-				"doc_status": 1,
-				"allow_edit": 'Leave Approver'
-			}, {
-				"state": 'Rejected',
-				"doc_status": 1,
-				"allow_edit": 'Leave Approver'
-			}],
-			'transitions': [{
-				"state": 'Open',
-				"action": 'Approve',
-				"next_state": 'Approved',
-				"allowed": 'Leave Approver'
-			},
-			{
-				"state": 'Open',
-				"action": 'Reject',
-				"next_state": 'Rejected',
-				"allowed": 'Leave Approver'
-			}]
-		}).insert(ignore_permissions=True)
-
 def check_setup_wizard_not_completed():
 	if frappe.db.get_default('desktop:home_page') == 'desktop':
 		print()
diff --git a/erpnext/stock/doctype/batch/batch.js b/erpnext/stock/doctype/batch/batch.js
index 12aa0bd..e2ea7f9 100644
--- a/erpnext/stock/doctype/batch/batch.js
+++ b/erpnext/stock/doctype/batch/batch.js
@@ -25,9 +25,17 @@
 		}
 	},
 	item: (frm) => {
-		frappe.db.get_value('Item', {name: frm.doc.item}, 'has_expiry_date', (r) => {
-			frm.toggle_reqd('expiry_date', r.has_expiry_date);
-		});
+		// frappe.db.get_value('Item', {name: frm.doc.item}, 'has_expiry_date', (r) => {
+		// 	frm.toggle_reqd('expiry_date', r.has_expiry_date);
+		// });
+		frappe.db.get_value('Item', {name: frm.doc.item}, ['shelf_life_in_days', 'has_expiry_date'], (r) => {
+			if (r.has_expiry_date && r.shelf_life_in_days) {
+				// Calculate expiry date based on shelf_life_in_days
+				frm.set_value('expiry_date', frappe.datetime.add_days(frm.doc.manufacturing_date, r.shelf_life_in_days));
+			}else if(r.has_expiry_date){
+				frm.toggle_reqd('expiry_date', r.has_expiry_date);
+			}
+		})
 	},
 	make_dashboard: (frm) => {
 		if(!frm.is_new()) {
diff --git a/erpnext/stock/doctype/batch/batch.json b/erpnext/stock/doctype/batch/batch.json
index f60798b..cc1aac5 100644
--- a/erpnext/stock/doctype/batch/batch.json
+++ b/erpnext/stock/doctype/batch/batch.json
@@ -1,493 +1,494 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 1, 
- "allow_rename": 0, 
- "autoname": "", 
- "beta": 0, 
- "creation": "2013-03-05 14:50:38", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Setup", 
- "editable_grid": 0, 
- "engine": "InnoDB", 
+ "allow_copy": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 1,
+ "allow_rename": 0,
+ "autoname": "",
+ "beta": 0,
+ "creation": "2013-03-05 14:50:38",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "editable_grid": 0,
+ "engine": "InnoDB",
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "depends_on": "eval:doc.__islocal", 
-   "fieldname": "batch_id", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Batch ID", 
-   "length": 0, 
-   "no_copy": 1, 
-   "oldfieldname": "batch_id", 
-   "oldfieldtype": "Data", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "depends_on": "eval:doc.__islocal",
+   "fieldname": "batch_id",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Batch ID",
+   "length": 0,
+   "no_copy": 1,
+   "oldfieldname": "batch_id",
+   "oldfieldtype": "Data",
+   "permlevel": 0,
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 1,
+   "search_index": 0,
+   "set_only_once": 0,
    "unique": 0
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "item", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 1, 
-   "label": "Item", 
-   "length": 0, 
-   "no_copy": 0, 
-   "oldfieldname": "item", 
-   "oldfieldtype": "Link", 
-   "options": "Item", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "item",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 1,
+   "label": "Item",
+   "length": 0,
+   "no_copy": 0,
+   "oldfieldname": "item",
+   "oldfieldtype": "Link",
+   "options": "Item",
+   "permlevel": 0,
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 1,
+   "search_index": 0,
+   "set_only_once": 0,
    "unique": 0
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "image", 
-   "fieldtype": "Attach Image", 
-   "hidden": 1, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "image", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "image",
+   "fieldtype": "Attach Image",
+   "hidden": 1,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "image",
+   "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, 
-   "depends_on": "eval:doc.parent_batch", 
-   "fieldname": "parent_batch", 
-   "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": "Parent Batch", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Batch", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "depends_on": "eval:doc.parent_batch",
+   "fieldname": "parent_batch",
+   "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": "Parent Batch",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Batch",
+   "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, 
-   "columns": 0, 
-   "fieldname": "column_break_3", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "column_break_3",
+   "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, 
-   "fieldname": "manufacturing_date", 
-   "fieldtype": "Date", 
-   "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": "Manufacturing Date", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "default": "Today",
+   "fieldname": "manufacturing_date",
+   "fieldtype": "Date",
+   "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": "Manufacturing Date",
+   "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": "expiry_date", 
-   "fieldtype": "Date", 
-   "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": "Expiry Date", 
-   "length": 0, 
-   "no_copy": 0, 
-   "oldfieldname": "expiry_date", 
-   "oldfieldtype": "Date", 
-   "permlevel": 0, 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "expiry_date",
+   "fieldtype": "Date",
+   "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": "Expiry Date",
+   "length": 0,
+   "no_copy": 0,
+   "oldfieldname": "expiry_date",
+   "oldfieldtype": "Date",
+   "permlevel": 0,
+   "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": "source", 
-   "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": "Source", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "source",
+   "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": "Source",
+   "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": "supplier", 
-   "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": "Supplier", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Supplier", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "supplier",
+   "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": "Supplier",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Supplier",
+   "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, 
-   "columns": 0, 
-   "fieldname": "column_break_9", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "column_break_9",
+   "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, 
-   "fieldname": "reference_doctype", 
-   "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": "Source Document Type", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "DocType", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "reference_doctype",
+   "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": "Source Document Type",
+   "length": 0,
+   "no_copy": 0,
+   "options": "DocType",
+   "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, 
-   "columns": 0, 
-   "fieldname": "reference_name", 
-   "fieldtype": "Dynamic 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": "Source Document Name", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "reference_doctype", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "reference_name",
+   "fieldtype": "Dynamic 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": "Source Document Name",
+   "length": 0,
+   "no_copy": 0,
+   "options": "reference_doctype",
+   "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, 
-   "columns": 0, 
-   "fieldname": "section_break_7", 
-   "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, 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "section_break_7",
+   "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,
+   "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": "description", 
-   "fieldtype": "Small Text", 
-   "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": "Batch Description", 
-   "length": 0, 
-   "no_copy": 0, 
-   "oldfieldname": "description", 
-   "oldfieldtype": "Small Text", 
-   "permlevel": 0, 
-   "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": "description",
+   "fieldtype": "Small Text",
+   "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": "Batch Description",
+   "length": 0,
+   "no_copy": 0,
+   "oldfieldname": "description",
+   "oldfieldtype": "Small Text",
+   "permlevel": 0,
+   "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,
    "width": "300px"
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "icon": "fa fa-archive", 
- "idx": 1, 
- "image_field": "image", 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 5, 
- "modified": "2018-01-08 21:55:54.306693", 
- "modified_by": "Administrator", 
- "module": "Stock", 
- "name": "Batch", 
- "owner": "harshada@webnotestech.com", 
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "icon": "fa fa-archive",
+ "idx": 1,
+ "image_field": "image",
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 5,
+ "modified": "2018-01-23 17:41:06.862477",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Batch",
+ "owner": "harshada@webnotestech.com",
  "permissions": [
   {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Item Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "amend": 0,
+   "apply_user_permissions": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 0,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Item Manager",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
    "write": 1
   }
- ], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "sort_order": "DESC", 
- "title_field": "item", 
- "track_changes": 0, 
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_order": "DESC",
+ "title_field": "item",
+ "track_changes": 0,
  "track_seen": 0
-}
\ No newline at end of file
+}
diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py
index b5674d3..645ab1b 100644
--- a/erpnext/stock/doctype/batch/batch.py
+++ b/erpnext/stock/doctype/batch/batch.py
@@ -7,24 +7,13 @@
 from frappe.model.document import Document
 from frappe.model.naming import make_autoname, revert_series_if_last
 from frappe.utils import flt, cint
-
+from frappe.utils.jinja import render_template
+from frappe.utils.data import add_days
 
 class UnableToSelectBatchError(frappe.ValidationError):
 	pass
 
 
-def get_name_from_naming_series():
-	"""
-	Get a name generated for a Batch from the Batch's naming series.
-	:return: The string that was generated.
-	"""
-	naming_series_prefix = _get_batch_prefix()
-	key = _make_naming_series_key(naming_series_prefix)
-	name = make_autoname(key)
-
-	return name
-
-
 def get_name_from_hash():
 	"""
 	Get a name for a Batch by generating a unique hash.
@@ -99,7 +88,7 @@
 		if not self.batch_id:
 			if frappe.db.get_value('Item', self.item, 'create_new_batch'):
 				if batch_uses_naming_series():
-					self.batch_id = get_name_from_naming_series()
+					self.batch_id = self.get_name_from_naming_series()
 				else:
 					self.batch_id = get_name_from_hash()
 			else:
@@ -120,6 +109,28 @@
 		if frappe.db.get_value("Item", self.item, "has_batch_no") == 0:
 			frappe.throw(_("The selected item cannot have Batch"))
 
+	def before_save(self):
+		has_expiry_date, shelf_life_in_days = frappe.db.get_value('Item', self.item, ['has_expiry_date', 'shelf_life_in_days'])
+		if not self.expiry_date and has_expiry_date and shelf_life_in_days:
+			self.expiry_date = add_days(self.manufacturing_date, shelf_life_in_days)
+
+		if has_expiry_date and not self.expiry_date:
+			frappe.throw('Expiry date is mandatory for selected item')
+			frappe.msgprint('Set items shelf life in days, to set expiry based on manufacturing_date plus self life ')
+
+	def get_name_from_naming_series(self):
+		"""
+		Get a name generated for a Batch from the Batch's naming series.
+		:return: The string that was generated.
+		"""
+		naming_series_prefix = _get_batch_prefix()
+		# validate_template(naming_series_prefix)
+		naming_series_prefix = render_template(str(naming_series_prefix), self.__dict__)
+		key = _make_naming_series_key(naming_series_prefix)
+		name = make_autoname(key)
+
+		return name
+
 
 @frappe.whitelist()
 def get_batch_qty(batch_no=None, warehouse=None, item_code=None):
@@ -206,6 +217,7 @@
 					frappe.throw(_("Row #{0}: The batch {1} has only {2} qty. Please select another batch which has {3} qty available or split the row into multiple rows, to deliver/issue from multiple batches").format(d.idx, d.batch_no, batch_qty, qty))
 
 
+
 @frappe.whitelist()
 def get_batch_no(item_code, warehouse, qty=1, throw=False):
 	"""
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index 2b87069..f334973 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -178,35 +178,6 @@
    "bold": 0,
    "collapsible": 0,
    "columns": 0,
-   "fieldname": "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": "Barcode",
-   "length": 0,
-   "no_copy": 1,
-   "permlevel": 0,
-   "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": "",
    "fieldname": "item_group",
    "fieldtype": "Link",
@@ -702,6 +673,67 @@
    "unique": 0
   },
   {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "sb_barcodes", 
+   "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": "Barcodes", 
+   "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": "barcodes", 
+   "fieldtype": "Table", 
+   "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": "Barcodes", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Item Barcode", 
+   "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,
@@ -3484,7 +3516,7 @@
  "issingle": 0,
  "istable": 0,
  "max_attachments": 1,
- "modified": "2018-01-24 20:42:23.303090",
+ "modified": "2018-02-12 15:42:23.303090",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Item",
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index df90ad9..27f2c7b 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -2,30 +2,38 @@
 # License: GNU General Public License v3. See license.txt
 
 from __future__ import unicode_literals
-import frappe
-import erpnext
-import json
-import itertools
-from frappe import msgprint, _
-from frappe.utils import (cstr, flt, cint, getdate, now_datetime, formatdate,
-	strip, get_timestamp, random_string)
-from frappe.utils.html_utils import clean_html
-from frappe.website.website_generator import WebsiteGenerator
-from erpnext.setup.doctype.item_group.item_group import invalidate_cache_for, get_parent_item_groups
-from frappe.website.render import clear_cache
-from frappe.website.doctype.website_slideshow.website_slideshow import get_slideshow
-from erpnext.controllers.item_variant import (get_variant, copy_attributes_to_variant,
-	make_variant_item_code, validate_item_variant_attributes, ItemVariantExistsError)
 
-class DuplicateReorderRows(frappe.ValidationError): pass
-class StockExistsForTemplate(frappe.ValidationError): pass
+import itertools
+import json
+import erpnext
+import frappe
+from erpnext.controllers.item_variant import (ItemVariantExistsError,
+        copy_attributes_to_variant, get_variant, make_variant_item_code, validate_item_variant_attributes)
+from erpnext.setup.doctype.item_group.item_group import (get_parent_item_groups, invalidate_cache_for)
+from frappe import _, msgprint
+from frappe.utils import (cint, cstr, flt, formatdate, get_timestamp, getdate,
+                          now_datetime, random_string, strip)
+from frappe.utils.html_utils import clean_html
+from frappe.website.doctype.website_slideshow.website_slideshow import \
+	get_slideshow
+from frappe.website.render import clear_cache
+from frappe.website.website_generator import WebsiteGenerator
+
+
+class DuplicateReorderRows(frappe.ValidationError):
+	pass
+
+
+class StockExistsForTemplate(frappe.ValidationError):
+	pass
+
 
 class Item(WebsiteGenerator):
 	website = frappe._dict(
-		page_title_field = "item_name",
-		condition_field = "show_in_website",
-		template = "templates/generators/item.html",
-		no_cache = 1
+		page_title_field="item_name",
+		condition_field="show_in_website",
+		template="templates/generators/item.html",
+		no_cache=1
 	)
 
 	def onload(self):
@@ -37,14 +45,14 @@
 			self.set_onload("asset_exists", True if asset else False)
 
 	def autoname(self):
-		if frappe.db.get_default("item_naming_by")=="Naming Series":
+		if frappe.db.get_default("item_naming_by") == "Naming Series":
 			if self.variant_of:
 				if not self.item_code:
 					template_item_name = frappe.db.get_value("Item", self.variant_of, "item_name")
 					self.item_code = make_variant_item_code(self.variant_of, template_item_name, self)
 			else:
 				from frappe.model.naming import make_autoname
-				self.item_code = make_autoname(self.naming_series+'.#####')
+				self.item_code = make_autoname(self.naming_series + '.#####')
 		elif not self.item_code:
 			msgprint(_("Item Code is mandatory because Item is not automatically numbered"), raise_exception=1)
 
@@ -102,8 +110,8 @@
 		if not self.get("__islocal"):
 			self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group")
 			self.old_website_item_groups = frappe.db.sql_list("""select item_group
-				from `tabWebsite Item Group`
-				where parentfield='website_item_groups' and parenttype='Item' and parent=%s""", self.name)
+					from `tabWebsite Item Group`
+					where parentfield='website_item_groups' and parenttype='Item' and parent=%s""", self.name)
 
 	def on_update(self):
 		invalidate_cache_for_item(self)
@@ -121,7 +129,7 @@
 		'''Add a new price'''
 		if not price_list:
 			price_list = (frappe.db.get_single_value('Selling Settings', 'selling_price_list')
-				or frappe.db.get_value('Price List', _('Standard Selling')))
+                    	or frappe.db.get_value('Price List', _('Standard Selling')))
 		if price_list:
 			item_price = frappe.get_doc({
 				"doctype": "Item Price",
@@ -147,19 +155,19 @@
 
 		# default warehouse, or Stores
 		default_warehouse = (self.default_warehouse
-			or frappe.db.get_single_value('Stock Settings', 'default_warehouse')
-			or frappe.db.get_value('Warehouse', {'warehouse_name': _('Stores')}))
+        		or frappe.db.get_single_value('Stock Settings', 'default_warehouse')
+                or frappe.db.get_value('Warehouse', {'warehouse_name': _('Stores')}))
 
 		if default_warehouse:
 			stock_entry = make_stock_entry(item_code=self.name, target=default_warehouse,
-				qty=self.opening_stock, rate=self.valuation_rate)
+                                  qty=self.opening_stock, rate=self.valuation_rate)
 
 			stock_entry.add_comment("Comment", _("Opening Stock"))
 
 	def make_route(self):
 		if not self.route:
 			return cstr(frappe.db.get_value('Item Group', self.item_group,
-				'route')) + '/' + self.scrub((self.item_name if self.item_name else self.item_code) + '-' + random_string(5))
+                    'route')) + '/' + self.scrub((self.item_name if self.item_name else self.item_code) + '-' + random_string(5))
 
 	def validate_website_image(self):
 		"""Validate if the website image is a public file"""
@@ -176,14 +184,13 @@
 			"file_url": self.website_image
 		}, fields=["name", "is_private"], order_by="is_private asc", limit_page_length=1)
 
-
 		if file_doc:
 			file_doc = file_doc[0]
 
 		if not file_doc:
 			if not auto_set_website_image:
 				frappe.msgprint(_("Website Image {0} attached to Item {1} cannot be found")
-					.format(self.website_image, self.name))
+                                    .format(self.website_image, self.name))
 
 			self.website_image = None
 
@@ -219,7 +226,8 @@
 				self.website_image = None
 
 			except requests.exceptions.SSLError:
-				frappe.msgprint(_("Warning: Invalid SSL certificate on attachment {0}").format(self.website_image))
+				frappe.msgprint(
+					_("Warning: Invalid SSL certificate on attachment {0}").format(self.website_image))
 				self.website_image = None
 
 			# for CSV import
@@ -259,12 +267,13 @@
 
 	def validate_retain_sample(self):
 		if self.retain_sample and not frappe.db.get_single_value('Stock Settings', 'sample_retention_warehouse'):
-			frappe.throw(_("Please select Sample Retention Warehouse in Stock Settings first"));
+			frappe.throw(_("Please select Sample Retention Warehouse in Stock Settings first"))
 		if self.retain_sample and not self.has_batch_no:
-			frappe.throw(_(" {0} Retain Sample is based on batch, please check Has Batch No to retain sample of item").format(self.item_code))
+			frappe.throw(_(" {0} Retain Sample is based on batch, please check Has Batch No to retain sample of item").format(
+				self.item_code))
 
 	def get_context(self, context):
-		context.show_search=True
+		context.show_search = True
 		context.search_link = '/product_search'
 
 		context.parents = get_parent_item_groups(self.item_group)
@@ -282,8 +291,8 @@
 			# load variants
 			# also used in set_attribute_context
 			context.variants = frappe.get_all("Item",
-				filters={"variant_of": self.name, "show_variant_in_website": 1},
-				order_by="name asc")
+                                     filters={"variant_of": self.name, "show_variant_in_website": 1},
+                                     order_by="name asc")
 
 			variant = frappe.form_dict.variant
 			if not variant and context.variants:
@@ -294,7 +303,7 @@
 				context.variant = frappe.get_doc("Item", variant)
 
 				for fieldname in ("website_image", "web_long_description", "description",
-					"website_specifications"):
+                                        "website_specifications"):
 					if context.variant.get(fieldname):
 						value = context.variant.get(fieldname)
 						if isinstance(value, list):
@@ -317,14 +326,14 @@
 			# load attributes
 			for v in context.variants:
 				v.attributes = frappe.get_all("Item Variant Attribute",
-					fields=["attribute", "attribute_value"], filters={"parent": v.name})
+                                  fields=["attribute", "attribute_value"], filters={"parent": v.name})
 
 				for attr in v.attributes:
 					values = attribute_values_available.setdefault(attr.attribute, [])
 					if attr.attribute_value not in values:
 						values.append(attr.attribute_value)
 
-					if v.name==context.variant.name:
+					if v.name == context.variant.name:
 						context.selected_attributes[attr.attribute] = attr.attribute_value
 
 			# filter attributes, order based on attribute table
@@ -338,7 +347,7 @@
 				else:
 					# get list of values defined (for sequence)
 					for attr_value in frappe.db.get_all("Item Attribute Value",
-						fields=["attribute_value"], filters={"parent": attr.attribute}, order_by="idx asc"):
+                                         fields=["attribute_value"], filters={"parent": attr.attribute}, order_by="idx asc"):
 
 						if attr_value.attribute_value in attribute_values_available.get(attr.attribute, []):
 							values.append(attr_value.attribute_value)
@@ -373,7 +382,7 @@
 					return True
 
 		for i, attr in enumerate(self.attributes):
-			if i==0:
+			if i == 0:
 				continue
 
 			combination_source = []
@@ -414,7 +423,7 @@
 			for d in template.get("reorder_levels"):
 				n = {}
 				for k in ("warehouse", "warehouse_reorder_level",
-					"warehouse_reorder_qty", "material_request_type"):
+                                        "warehouse_reorder_qty", "material_request_type"):
 					n[k] = d.get(k)
 				self.append("reorder_levels", n)
 
@@ -422,12 +431,14 @@
 		check_list = []
 		for d in self.get('uoms'):
 			if cstr(d.uom) in check_list:
-				frappe.throw(_("Unit of Measure {0} has been entered more than once in Conversion Factor Table").format(d.uom))
+				frappe.throw(
+					_("Unit of Measure {0} has been entered more than once in Conversion Factor Table").format(d.uom))
 			else:
 				check_list.append(cstr(d.uom))
 
 			if d.uom and cstr(d.uom) == cstr(self.stock_uom) and flt(d.conversion_factor) != 1:
-				frappe.throw(_("Conversion factor for default Unit of Measure must be 1 in row {0}").format(d.idx))
+				frappe.throw(
+					_("Conversion factor for default Unit of Measure must be 1 in row {0}").format(d.idx))
 
 	def validate_item_type(self):
 		if self.has_serial_no == 1 and self.is_stock_item == 0:
@@ -436,29 +447,30 @@
 		if self.has_serial_no == 0 and self.serial_no_series:
 			self.serial_no_series = None
 
-
 	def check_for_active_boms(self):
 		if self.default_bom:
 			bom_item = frappe.db.get_value("BOM", self.default_bom, "item")
 			if bom_item not in (self.name, self.variant_of):
-				frappe.throw(_("Default BOM ({0}) must be active for this item or its template").format(bom_item))
+				frappe.throw(
+					_("Default BOM ({0}) must be active for this item or its template").format(bom_item))
 
 	def fill_customer_code(self):
 		""" Append all the customer codes and insert into "customer_code" field of item table """
-		cust_code=[]
+		cust_code = []
 		for d in self.get('customer_items'):
 			cust_code.append(d.ref_code)
-		self.customer_code=','.join(cust_code)
+		self.customer_code = ','.join(cust_code)
 
 	def check_item_tax(self):
 		"""Check whether Tax Rate is not entered twice for same Tax Type"""
-		check_list=[]
+		check_list = []
 		for d in self.get('taxes'):
 			if d.tax_type:
 				account_type = frappe.db.get_value("Account", d.tax_type, "account_type")
 
 				if account_type not in ['Tax', 'Chargeable', 'Income Account', 'Expense Account']:
-					frappe.throw(_("Item Tax Row {0} must have account of type Tax or Income or Expense or Chargeable").format(d.idx))
+					frappe.throw(
+						_("Item Tax Row {0} must have account of type Tax or Income or Expense or Chargeable").format(d.idx))
 				else:
 					if d.tax_type in check_list:
 						frappe.throw(_("{0} entered twice in Item Tax").format(d.tax_type))
@@ -466,12 +478,20 @@
 						check_list.append(d.tax_type)
 
 	def validate_barcode(self):
-		if self.barcode:
-			duplicate = frappe.db.sql("""select name from tabItem where barcode = %s
-				and name != %s""", (self.barcode, self.name))
-			if duplicate:
-				frappe.throw(_("Barcode {0} already used in Item {1}").format(self.barcode, duplicate[0][0]))
+		from stdnum import ean
+		if len(self.barcodes) > 0:
+			for item_barcode in self.barcodes:
+				if item_barcode.barcode:
+					duplicate = frappe.db.sql(
+						"""select parent from `tabItem Barcode` where barcode = %s and parent != %s""", (item_barcode.barcode, self.name))
+					if duplicate:
+						frappe.throw(_("Barcode {0} already used in Item {1}").format(
+							item_barcode.barcode, duplicate[0][0]))
 
+					if item_barcode.barcode_type:
+						if not ean.is_valid(item_barcode.barcode):
+							frappe.throw(_("Barcode {0} is not a valid {1} code").format(
+								item_barcode.barcode, item_barcode.barcode_type))
 
 	def validate_warehouse_for_reorder(self):
 		'''Validate Reorder level table for duplicate and conditional mandatory'''
@@ -483,7 +503,7 @@
 				warehouse += [d.get("warehouse")]
 			else:
 				frappe.throw(_("Row {0}: An Reorder entry already exists for this warehouse {1}")
-					.format(d.idx, d.warehouse), DuplicateReorderRows)
+                                    .format(d.idx, d.warehouse), DuplicateReorderRows)
 
 			if d.warehouse_reorder_level and not d.warehouse_reorder_qty:
 				frappe.throw(_("Row #{0}: Please set reorder quantity").format(d.idx))
@@ -497,12 +517,13 @@
 	def validate_name_with_item_group(self):
 		# causes problem with tree build
 		if frappe.db.exists("Item Group", self.name):
-			frappe.throw(_("An Item Group exists with same name, please change the item name or rename the item group"))
+			frappe.throw(
+				_("An Item Group exists with same name, please change the item name or rename the item group"))
 
 	def update_item_price(self):
 		frappe.db.sql("""update `tabItem Price` set item_name=%s,
 			item_description=%s, modified=NOW() where item_code=%s""",
-			(self.item_name, self.description, self.name))
+                    (self.item_name, self.description, self.name))
 
 	def on_trash(self):
 		super(Item, self).on_trash()
@@ -512,7 +533,7 @@
 			frappe.delete_doc("Item", variant_of.name)
 
 	def before_rename(self, old_name, new_name, merge=False):
-		if self.item_name==old_name:
+		if self.item_name == old_name:
 			frappe.db.set_value("Item", old_name, "item_name", new_name)
 
 		if merge:
@@ -524,7 +545,7 @@
 			new_properties = [cstr(d) for d in frappe.db.get_value("Item", new_name, field_list)]
 			if new_properties != [cstr(self.get(fld)) for fld in field_list]:
 				frappe.throw(_("To merge, following properties must be same for both items")
-					+ ": \n" + ", ".join([self.meta.get_label(fld) for fld in field_list]))
+                                    + ": \n" + ", ".join([self.meta.get_label(fld) for fld in field_list]))
 
 	def after_rename(self, old_name, new_name, merge):
 		if self.route:
@@ -547,7 +568,7 @@
 					item_wise_tax_detail.pop(old_name)
 
 					frappe.db.set_value(dt, d.name, "item_wise_tax_detail",
-						json.dumps(item_wise_tax_detail), update_modified=False)
+                                            json.dumps(item_wise_tax_detail), update_modified=False)
 
 	def set_last_purchase_rate(self, new_name):
 		last_purchase_rate = get_last_purchase_details(new_name).get("base_rate", 0)
@@ -575,13 +596,14 @@
 		self.set("website_specifications", [])
 		if self.item_group:
 			for label, desc in frappe.db.get_values("Item Website Specification",
-				{"parent": self.item_group}, ["label", "description"]):
-					row = self.append("website_specifications")
-					row.label = label
-					row.description = desc
+                                           {"parent": self.item_group}, ["label", "description"]):
+				row = self.append("website_specifications")
+				row.label = label
+				row.description = desc
 
 	def update_bom_item_desc(self):
-		if self.is_new(): return
+		if self.is_new():
+			return
 
 		if self.db_get('description') != self.description:
 			frappe.db.sql("""
@@ -620,11 +642,11 @@
 
 	def update_variants(self):
 		if self.flags.dont_update_variants or \
-			frappe.db.get_single_value('Item Variant Settings', 'do_not_update_variants'):
+                        frappe.db.get_single_value('Item Variant Settings', 'do_not_update_variants'):
 			return
 		if self.has_variants:
 			updated = []
-			variants = frappe.db.get_all("Item", fields=["item_code"], filters={"variant_of": self.name })
+			variants = frappe.db.get_all("Item", fields=["item_code"], filters={"variant_of": self.name})
 			for d in variants:
 				variant = frappe.get_doc("Item", d)
 				copy_attributes_to_variant(self, variant)
@@ -641,39 +663,41 @@
 	def validate_stock_exists_for_template_item(self):
 		if self.stock_ledger_created() and self._doc_before_save:
 			if (self._doc_before_save.has_variants != self.has_variants
-				or self._doc_before_save.variant_of != self.variant_of):
+                                or self._doc_before_save.variant_of != self.variant_of):
 				frappe.throw(_("Cannot change Variant properties after stock transction. You will have to make a new Item to do this.").format(self.name),
-					StockExistsForTemplate)
+                                    StockExistsForTemplate)
 
 			if self.has_variants or self.variant_of:
 				if not self.is_child_table_same('attributes'):
-					frappe.throw(_('Cannot change Attributes after stock transaction. Make a new Item and transfer stock to the new Item'))
+					frappe.throw(
+						_('Cannot change Attributes after stock transaction. Make a new Item and transfer stock to the new Item'))
 
 	def validate_uom(self):
 		if not self.get("__islocal"):
 			check_stock_uom_with_bin(self.name, self.stock_uom)
 		if self.has_variants:
-			for d in frappe.db.get_all("Item", filters= {"variant_of": self.name}):
+			for d in frappe.db.get_all("Item", filters={"variant_of": self.name}):
 				check_stock_uom_with_bin(d.name, self.stock_uom)
 		if self.variant_of:
 			template_uom = frappe.db.get_value("Item", self.variant_of, "stock_uom")
 			if template_uom != self.stock_uom:
 				frappe.throw(_("Default Unit of Measure for Variant '{0}' must be same as in Template '{1}'")
-					.format(self.stock_uom, template_uom))
+                                    .format(self.stock_uom, template_uom))
 
 	def validate_attributes(self):
-		if (self.has_variants or self.variant_of) and self.variant_based_on=='Item Attribute':
+		if (self.has_variants or self.variant_of) and self.variant_based_on == 'Item Attribute':
 			attributes = []
 			if not self.attributes:
 				frappe.throw(_("Attribute table is mandatory"))
 			for d in self.attributes:
 				if d.attribute in attributes:
-					frappe.throw(_("Attribute {0} selected multiple times in Attributes Table".format(d.attribute)))
+					frappe.throw(
+						_("Attribute {0} selected multiple times in Attributes Table".format(d.attribute)))
 				else:
 					attributes.append(d.attribute)
 
 	def validate_variant_attributes(self):
-		if self.variant_of and self.variant_based_on=='Item Attribute':
+		if self.variant_of and self.variant_based_on == 'Item Attribute':
 			args = {}
 			for d in self.attributes:
 				if not d.attribute_value:
@@ -683,10 +707,11 @@
 			variant = get_variant(self.variant_of, args, self.name)
 			if variant:
 				frappe.throw(_("Item variant {0} exists with same attributes")
-					.format(variant), ItemVariantExistsError)
+                                    .format(variant), ItemVariantExistsError)
 
 			validate_item_variant_attributes(self, args)
 
+
 def get_timeline_data(doctype, name):
 	'''returns timeline data based on stock ledger entry'''
 	out = {}
@@ -697,21 +722,23 @@
 
 	for date, count in items.iteritems():
 		timestamp = get_timestamp(date)
-		out.update({ timestamp: count })
+		out.update({timestamp: count})
 
 	return out
 
+
 def validate_end_of_life(item_code, end_of_life=None, disabled=None, verbose=1):
 	if (not end_of_life) or (disabled is None):
 		end_of_life, disabled = frappe.db.get_value("Item", item_code, ["end_of_life", "disabled"])
 
-	if end_of_life and end_of_life!="0000-00-00" and getdate(end_of_life) <= now_datetime().date():
+	if end_of_life and end_of_life != "0000-00-00" and getdate(end_of_life) <= now_datetime().date():
 		msg = _("Item {0} has reached its end of life on {1}").format(item_code, formatdate(end_of_life))
 		_msgprint(msg, verbose)
 
 	if disabled:
 		_msgprint(_("Item {0} is disabled").format(item_code), verbose)
 
+
 def validate_is_stock_item(item_code, is_stock_item=None, verbose=1):
 	if not is_stock_item:
 		is_stock_item = frappe.db.get_value("Item", item_code, "is_stock_item")
@@ -721,6 +748,7 @@
 
 		_msgprint(msg, verbose)
 
+
 def validate_cancelled_item(item_code, docstatus=None, verbose=1):
 	if docstatus is None:
 		docstatus = frappe.db.get_value("Item", item_code, "docstatus")
@@ -729,6 +757,7 @@
 		msg = _("Item {0} is cancelled").format(item_code)
 		_msgprint(msg, verbose)
 
+
 def _msgprint(msg, verbose):
 	if verbose:
 		msgprint(msg, raise_exception=True)
@@ -760,19 +789,19 @@
 		order by pr.posting_date desc, pr.posting_time desc, pr.name desc
 		limit 1""", (item_code, cstr(doc_name)), as_dict=1)
 
-	purchase_order_date = getdate(last_purchase_order and last_purchase_order[0].transaction_date \
-		or "1900-01-01")
-	purchase_receipt_date = getdate(last_purchase_receipt and \
-		last_purchase_receipt[0].posting_date or "1900-01-01")
+	purchase_order_date = getdate(last_purchase_order and last_purchase_order[0].transaction_date
+                               or "1900-01-01")
+	purchase_receipt_date = getdate(last_purchase_receipt and
+                                 last_purchase_receipt[0].posting_date or "1900-01-01")
 
 	if (purchase_order_date > purchase_receipt_date) or \
-			(last_purchase_order and not last_purchase_receipt):
+                (last_purchase_order and not last_purchase_receipt):
 		# use purchase order
 		last_purchase = last_purchase_order[0]
 		purchase_date = purchase_order_date
 
 	elif (purchase_receipt_date > purchase_order_date) or \
-			(last_purchase_receipt and not last_purchase_order):
+                (last_purchase_receipt and not last_purchase_order):
 		# use purchase receipt
 		last_purchase = last_purchase_receipt[0]
 		purchase_date = purchase_receipt_date
@@ -797,11 +826,12 @@
 
 	return out
 
+
 def invalidate_cache_for_item(doc):
 	invalidate_cache_for(doc, doc.item_group)
 
 	website_item_groups = list(set((doc.get("old_website_item_groups") or [])
-		+ [d.item_group for d in doc.get({"doctype":"Website Item Group"}) if d.item_group]))
+                                + [d.item_group for d in doc.get({"doctype": "Website Item Group"}) if d.item_group]))
 
 	for item_group in website_item_groups:
 		invalidate_cache_for(doc, item_group)
@@ -809,13 +839,14 @@
 	if doc.get("old_item_group") and doc.get("old_item_group") != doc.item_group:
 		invalidate_cache_for(doc, doc.old_item_group)
 
+
 def check_stock_uom_with_bin(item, stock_uom):
 	if stock_uom == frappe.db.get_value("Item", item, "stock_uom"):
 		return
 
-	matched=True
+	matched = True
 	ref_uom = frappe.db.get_value("Stock Ledger Entry",
-		{"item_code": item}, "stock_uom")
+                               {"item_code": item}, "stock_uom")
 
 	if ref_uom:
 		if cstr(ref_uom) != cstr(stock_uom):
@@ -823,13 +854,14 @@
 	else:
 		bin_list = frappe.db.sql("select * from tabBin where item_code=%s", item, as_dict=1)
 		for bin in bin_list:
-			if (bin.reserved_qty > 0 or bin.ordered_qty > 0 or bin.indented_qty > 0 \
-				or bin.planned_qty > 0) and cstr(bin.stock_uom) != cstr(stock_uom):
-					matched = False
-					break
+			if (bin.reserved_qty > 0 or bin.ordered_qty > 0 or bin.indented_qty > 0
+                                or bin.planned_qty > 0) and cstr(bin.stock_uom) != cstr(stock_uom):
+				matched = False
+				break
 
 		if matched and bin_list:
 			frappe.db.sql("""update tabBin set stock_uom=%s where item_code=%s""", (stock_uom, item))
 
 	if not matched:
-		frappe.throw(_("Default Unit of Measure for Item {0} cannot be changed directly because you have already made some transaction(s) with another UOM. You will need to create a new Item to use a different Default UOM.").format(item))
+		frappe.throw(
+			_("Default Unit of Measure for Item {0} cannot be changed directly because you have already made some transaction(s) with another UOM. You will need to create a new Item to use a different Default UOM.").format(item))
diff --git a/erpnext/stock/doctype/item_barcode/__init__.py b/erpnext/stock/doctype/item_barcode/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/stock/doctype/item_barcode/__init__.py
diff --git a/erpnext/stock/doctype/item_barcode/item_barcode.json b/erpnext/stock/doctype/item_barcode/item_barcode.json
new file mode 100644
index 0000000..c8a3a89
--- /dev/null
+++ b/erpnext/stock/doctype/item_barcode/item_barcode.json
@@ -0,0 +1,103 @@
+{
+ "allow_copy": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
+ "autoname": "field:barcode", 
+ "beta": 0, 
+ "creation": "2017-12-09 18:54:50.562438", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "barcode", 
+   "fieldtype": "Data", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 1, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Barcode", 
+   "length": 0, 
+   "no_copy": 1, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 1
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "barcode_type", 
+   "fieldtype": "Select", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Barcode Type", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "\nEAN\nUPC-A", 
+   "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
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 1, 
+ "max_attachments": 0, 
+ "modified": "2017-12-10 20:55:23.814039", 
+ "modified_by": "Administrator", 
+ "module": "Stock", 
+ "name": "Item Barcode", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 1, 
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/item_barcode/item_barcode.py b/erpnext/stock/doctype/item_barcode/item_barcode.py
new file mode 100644
index 0000000..e85f93b
--- /dev/null
+++ b/erpnext/stock/doctype/item_barcode/item_barcode.py
@@ -0,0 +1,11 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+
+from frappe.model.document import Document
+
+
+class ItemBarcode(Document):
+    pass
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.py b/erpnext/stock/doctype/stock_settings/stock_settings.py
index 89ece33..23a18f4 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.py
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.py
@@ -25,7 +25,7 @@
 			frappe.msgprint (_("`Freeze Stocks Older Than` should be smaller than %d days.") %stock_frozen_limit)
 
 		# show/hide barcode field
-		frappe.make_property_setter({'fieldname': 'barcode', 'property': 'hidden',
+		frappe.make_property_setter({'fieldname': 'barcodes', 'property': 'hidden',
 			'value': 0 if self.show_barcode_field else 1})
 
 		self.cant_change_valuation_method()
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 6b67233..01f5206 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -120,7 +120,7 @@
 @frappe.whitelist()
 def get_item_code(barcode=None, serial_no=None):
 	if barcode:
-		item_code = frappe.db.get_value("Item", {"barcode": barcode})
+		item_code = frappe.db.get_value("Item Barcode", {"barcode": barcode}, fieldname=["parent"])
 		if not item_code:
 			frappe.throw(_("No Item with Barcode {0}").format(barcode))
 	elif serial_no:
@@ -273,7 +273,7 @@
 			if not out[d[1]] or (company and args.company != company):
 				out[d[1]] = frappe.db.get_value("Company", args.company, d[2]) if d[2] else None
 
-	for fieldname in ("item_name", "item_group", "barcode", "brand", "stock_uom"):
+	for fieldname in ("item_name", "item_group", "barcodes", "brand", "stock_uom"):
 		out[fieldname] = item.get(fieldname)
 
 	return out
diff --git a/requirements.txt b/requirements.txt
index a6cfaf2..7b5d8da 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,3 +2,4 @@
 unidecode
 pygithub
 googlemaps
+python-stdnum