Merge pull request #9750 from rohitwaghchaure/taxable_amount_issue

[Fix] Taxable amount in tax breakup showing wrong value for duplicate items in the invoice
diff --git a/.travis.yml b/.travis.yml
index 9f37374..0d8d2ff 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,12 @@
 language: python
 dist: trusty
-group: deprecated-2017Q2
+
+addons:
+  apt:
+    sources:
+      - google-chrome
+    packages:
+      - google-chrome-stable
 
 python:
   - "2.7"
@@ -8,43 +14,43 @@
 services:
   - mysql
 
-before_install:
-  - "export DISPLAY=:99.0"
-  - "sh -e /etc/init.d/xvfb start"
-
 install:
+  - sudo rm /etc/apt/sources.list.d/docker.list
   - sudo apt-get purge -y mysql-common mysql-server mysql-client
   - nvm install v7.10.0
-  # - wget https://raw.githubusercontent.com/frappe/bench/master/install_scripts/setup_frappe.sh
-  # - sudo bash setup_frappe.sh --skip-setup-bench --mysql-root-password travis --bench-branch develop
   - wget https://raw.githubusercontent.com/frappe/bench/master/playbooks/install.py
   - sudo python install.py --develop --user travis --without-bench-setup
   - sudo pip install -e ~/bench
 
-  # - sudo pip install --upgrade pip
   - rm $TRAVIS_BUILD_DIR/.git/shallow
   - bash $TRAVIS_BUILD_DIR/travis/bench_init.sh
   - cp -r $TRAVIS_BUILD_DIR/test_sites/test_site ~/frappe-bench/sites/
 
-script:
+before_script:
+  - wget http://chromedriver.storage.googleapis.com/2.27/chromedriver_linux64.zip
+  - unzip chromedriver_linux64.zip
+  - sudo apt-get install libnss3
+  - sudo apt-get --only-upgrade install google-chrome-stable
+  - sudo cp chromedriver /usr/local/bin/.
+  - sudo chmod +x /usr/local/bin/chromedriver
+  - export DISPLAY=:99.0
+  - sh -e /etc/init.d/xvfb start
+  - sleep 3
+  - mysql -u root -ptravis -e 'create database test_frappe'
+  - echo "USE mysql;\nCREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe';\nFLUSH PRIVILEGES;\n" | mysql -u root -ptravis
+  - echo "USE mysql;\nGRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost';\n" | mysql -u root -ptravis
+
   - cd ~/frappe-bench
   - bench get-app erpnext $TRAVIS_BUILD_DIR
   - bench use test_site
   - bench reinstall --yes
   - bench build
+  - bench scheduler disable
   - bench start &
   - sleep 10
-  - bench --verbose run-tests --driver Firefox
 
-before_script:
-  - mysql -u root -ptravis -e 'create database test_frappe'
-  - echo "USE mysql;\nCREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe';\nFLUSH PRIVILEGES;\n" | mysql -u root -ptravis
-  - echo "USE mysql;\nGRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost';\n" | mysql -u root -ptravis
-
-notifications:
-  webhooks:
-    urls:
-      - https://webhooks.gitter.im/e/92b3bea86d8c5397beef
-    on_success: always
-    on_failure: always
-    on_start: never
+script:
+  - set -e
+  - bench --verbose run-tests
+  - sleep 5
+  - bench --verbose run-tests --ui-tests
diff --git a/erpnext/accounts/doctype/budget/budget.py b/erpnext/accounts/doctype/budget/budget.py
index a6348f1..f99d0bb 100644
--- a/erpnext/accounts/doctype/budget/budget.py
+++ b/erpnext/accounts/doctype/budget/budget.py
@@ -83,7 +83,7 @@
 
 			budget_records = frappe.db.sql("""
 				select
-					b.{budget_against_field}, ba.budget_amount, b.monthly_distribution,
+					b.{budget_against_field} as budget_against, ba.budget_amount, b.monthly_distribution,
 					b.action_if_annual_budget_exceeded, 
 					b.action_if_accumulated_monthly_budget_exceeded
 				from 
@@ -111,15 +111,15 @@
 				args["month_end_date"] = get_last_day(args.posting_date)
 
 				compare_expense_with_budget(args, budget_amount, 
-					_("Accumulated Monthly"), monthly_action)
+					_("Accumulated Monthly"), monthly_action, budget.budget_against)
 
 			if yearly_action in ("Stop", "Warn") and monthly_action != "Stop" \
 				and yearly_action != monthly_action:
 				compare_expense_with_budget(args, flt(budget.budget_amount), 
-						_("Annual"), yearly_action)
+						_("Annual"), yearly_action, budget.budget_against)
 
 
-def compare_expense_with_budget(args, budget_amount, action_for, action):
+def compare_expense_with_budget(args, budget_amount, action_for, action, budget_against):
 	actual_expense = get_actual_expense(args)
 	if actual_expense > budget_amount:
 		diff = actual_expense - budget_amount
@@ -127,7 +127,7 @@
 
 		msg = _("{0} Budget for Account {1} against {2} {3} is {4}. It will exceed by {5}").format(
 				_(action_for), frappe.bold(args.account), args.budget_against_field, 
-				frappe.bold(args.budget_against), 
+				frappe.bold(budget_against),
 				frappe.bold(fmt_money(budget_amount, currency=currency)), 
 				frappe.bold(fmt_money(diff, currency=currency)))
 
diff --git a/erpnext/accounts/doctype/budget/test_budget.py b/erpnext/accounts/doctype/budget/test_budget.py
index 15895dc..f6849ba 100644
--- a/erpnext/accounts/doctype/budget/test_budget.py
+++ b/erpnext/accounts/doctype/budget/test_budget.py
@@ -140,6 +140,33 @@
 		budget.load_from_db()
 		budget.cancel()
 
+	def test_monthly_budget_against_parent_group_cost_center(self):
+		cost_center = "_Test Cost Center 3 - _TC"
+
+		if not frappe.db.exists("Cost Center", cost_center):
+			frappe.get_doc({
+				'doctype': 'Cost Center',
+				'cost_center_name': '_Test Cost Center 3',
+				'parent_cost_center': "_Test Company - _TC",
+				'company': '_Test Company',
+				'is_group': 0
+			}).insert(ignore_permissions=True)
+
+		budget = make_budget("Cost Center", cost_center)
+		frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
+
+		jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
+			"_Test Bank - _TC", 40000, cost_center)
+
+		self.assertRaises(BudgetError, jv.submit)
+
+		budget.load_from_db()
+		budget.cancel()
+		jv.cancel()
+
+		frappe.delete_doc('Journal Entry', jv.name)
+		frappe.delete_doc('Cost Center', cost_center)
+
 def set_total_expense_zero(posting_date, budget_against_field=None, budget_against_CC=None):
 	if budget_against_field == "Project":
 		budget_against = "_Test Project"
@@ -167,7 +194,8 @@
 	if budget_against == "Project":
 		budget_list = frappe.get_all("Budget", fields=["name"], filters = {"name": ("like", "_Test Project/_Test Fiscal Year 2013%")})
 	else:
-		budget_list = frappe.get_all("Budget", fields=["name"], filters = {"name": ("like", "_Test Cost Center - _TC/_Test Fiscal Year 2013%")})
+		cost_center_name = "{0}%".format(cost_center or "_Test Cost Center - _TC/_Test Fiscal Year 2013")
+		budget_list = frappe.get_all("Budget", fields=["name"], filters = {"name": ("like", cost_center_name)})
 	for d in budget_list:
 		frappe.db.sql("delete from `tabBudget` where name = %(name)s", d)
 		frappe.db.sql("delete from `tabBudget Account` where parent = %(name)s", d)
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index 5bfd4d9..63832fa 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -291,37 +291,39 @@
 
 	set_account_currency_and_balance: function(frm, account, currency_field,
 			balance_field, callback_function) {
-		frappe.call({
-			method: "erpnext.accounts.doctype.payment_entry.payment_entry.get_account_details",
-			args: {
-				"account": account,
-				"date": frm.doc.posting_date
-			},
-			callback: function(r, rt) {
-				if(r.message) {
-					frm.set_value(currency_field, r.message['account_currency']);
-					frm.set_value(balance_field, r.message['account_balance']);
+		if (frm.doc.posting_date) {
+			frappe.call({
+				method: "erpnext.accounts.doctype.payment_entry.payment_entry.get_account_details",
+				args: {
+					"account": account,
+					"date": frm.doc.posting_date
+				},
+				callback: function(r, rt) {
+					if(r.message) {
+						frm.set_value(currency_field, r.message['account_currency']);
+						frm.set_value(balance_field, r.message['account_balance']);
 
-					if(frm.doc.payment_type=="Receive" && currency_field=="paid_to_account_currency") {
-						frm.toggle_reqd(["reference_no", "reference_date"],
-							(r.message['account_type'] == "Bank" ? 1 : 0));
-						if(!frm.doc.received_amount && frm.doc.paid_amount)
-							frm.events.paid_amount(frm);
-					} else if(frm.doc.payment_type=="Pay" && currency_field=="paid_from_account_currency") {
-						frm.toggle_reqd(["reference_no", "reference_date"],
-							(r.message['account_type'] == "Bank" ? 1 : 0));
+						if(frm.doc.payment_type=="Receive" && currency_field=="paid_to_account_currency") {
+							frm.toggle_reqd(["reference_no", "reference_date"],
+								(r.message['account_type'] == "Bank" ? 1 : 0));
+							if(!frm.doc.received_amount && frm.doc.paid_amount)
+								frm.events.paid_amount(frm);
+						} else if(frm.doc.payment_type=="Pay" && currency_field=="paid_from_account_currency") {
+							frm.toggle_reqd(["reference_no", "reference_date"],
+								(r.message['account_type'] == "Bank" ? 1 : 0));
 
-						if(!frm.doc.paid_amount && frm.doc.received_amount)
-							frm.events.received_amount(frm);
+							if(!frm.doc.paid_amount && frm.doc.received_amount)
+								frm.events.received_amount(frm);
+						}
+
+						if(callback_function) callback_function(frm);
+
+						frm.events.hide_unhide_fields(frm);
+						frm.events.set_dynamic_labels(frm);
 					}
-
-					if(callback_function) callback_function(frm);
-
-					frm.events.hide_unhide_fields(frm);
-					frm.events.set_dynamic_labels(frm);
 				}
-			}
-		});
+			});			
+		}
 	},
 
 	paid_from_account_currency: function(frm) {
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index c6559f8..e9471b7 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -492,9 +492,13 @@
 	
 	for d in outstanding_invoices:
 		d["exchange_rate"] = 1
-		if party_account_currency != company_currency \
-			and d.voucher_type in ("Sales Invoice", "Purchase Invoice"):
+		if party_account_currency != company_currency:
+			if d.voucher_type in ("Sales Invoice", "Purchase Invoice"):
 				d["exchange_rate"] = frappe.db.get_value(d.voucher_type, d.voucher_no, "conversion_rate")
+			elif d.voucher_type == "Journal Entry":
+				d["exchange_rate"] = get_exchange_rate(
+					party_account_currency,	company_currency, d.posting_date
+				)
 
 	# Get all SO / PO which are not fully billed or aginst which full advance not paid
 	orders_to_be_billed =  get_orders_to_be_billed(args.get("posting_date"),args.get("party_type"), args.get("party"), 
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py
index bfe00ef..bc9d766 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py
@@ -11,8 +11,7 @@
 			'Sales Invoice': 'return_against'
 		},
 		'internal_links': {
-			'Sales Order': ['items', 'sales_order'],
-			'Delivery Note': ['items', 'delivery_note']
+			'Sales Order': ['items', 'sales_order']
 		},
 		'transactions': [
 			{
diff --git a/erpnext/crm/doctype/opportunity/opportunity.json b/erpnext/crm/doctype/opportunity/opportunity.json
index 18a97ac..6d9b514 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.json
+++ b/erpnext/crm/doctype/opportunity/opportunity.json
@@ -56,7 +56,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_global_search": 0, 
-   "in_list_view": 0, 
+   "in_list_view": 1, 
    "in_standard_filter": 0, 
    "label": "Series", 
    "length": 0, 
@@ -88,7 +88,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_global_search": 0, 
-   "in_list_view": 0, 
+   "in_list_view": 1, 
    "in_standard_filter": 0, 
    "label": "Opportunity From", 
    "length": 0, 
@@ -277,8 +277,8 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 1, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
    "label": "Opportunity Type", 
    "length": 0, 
    "no_copy": 0, 
@@ -310,7 +310,7 @@
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
    "in_global_search": 0, 
-   "in_list_view": 0, 
+   "in_list_view": 1, 
    "in_standard_filter": 1, 
    "label": "Status", 
    "length": 0, 
@@ -1189,7 +1189,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2017-06-13 14:29:07.077697", 
+ "modified": "2017-07-10 15:29:23.921967", 
  "modified_by": "Administrator", 
  "module": "CRM", 
  "name": "Opportunity", 
diff --git a/erpnext/docs/assets/img/setup/sms-setting2.jpg b/erpnext/docs/assets/img/setup/sms-settings2.jpg
similarity index 100%
rename from erpnext/docs/assets/img/setup/sms-setting2.jpg
rename to erpnext/docs/assets/img/setup/sms-settings2.jpg
Binary files differ
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index ec93f62..0966485 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -80,6 +80,13 @@
 			"parents": [{"title": _("Supplier Quotation"), "name": "quotations"}]
 		}
 	},
+	{"from_route": "/quotes", "to_route": "Quotation"},
+	{"from_route": "/quotes/<path:name>", "to_route": "order",
+		"defaults": {
+			"doctype": "Quotation",
+			"parents": [{"title": _("Quotes"), "name": "quotes"}]
+		}
+	},
 	{"from_route": "/shipments", "to_route": "Delivery Note"},
 	{"from_route": "/shipments/<path:name>", "to_route": "order",
 		"defaults": {
@@ -110,6 +117,7 @@
 	{"title": _("Projects"), "route": "/project", "reference_doctype": "Project"},
 	{"title": _("Request for Quotations"), "route": "/rfq", "reference_doctype": "Request for Quotation", "role": "Supplier"},
 	{"title": _("Supplier Quotation"), "route": "/quotations", "reference_doctype": "Supplier Quotation", "role": "Supplier"},
+	{"title": _("Quotes"), "route": "/quotes", "reference_doctype": "Quotation", "role":"Customer"},
 	{"title": _("Orders"), "route": "/orders", "reference_doctype": "Sales Order", "role":"Customer"},
 	{"title": _("Invoices"), "route": "/invoices", "reference_doctype": "Sales Invoice", "role":"Customer"},
 	{"title": _("Shipments"), "route": "/shipments", "reference_doctype": "Delivery Note", "role":"Customer"},
diff --git a/erpnext/hr/doctype/daily_work_summary/test_daily_work_summary.py b/erpnext/hr/doctype/daily_work_summary/test_daily_work_summary.py
index 81455f1..ad9d43f 100644
--- a/erpnext/hr/doctype/daily_work_summary/test_daily_work_summary.py
+++ b/erpnext/hr/doctype/daily_work_summary/test_daily_work_summary.py
@@ -12,32 +12,31 @@
 
 class TestDailyWorkSummary(unittest.TestCase):
 	def test_email_trigger(self):
-		settings, employees, emails = self.setup_and_prepare_test()
-
-		for d in employees:
+		self.setup_and_prepare_test()
+		for d in self.employees:
 			# check that email is sent to this employee
-			self.assertTrue(d.user_id in [d.recipient for d in emails
-				if settings.subject in d.message])
+			self.assertTrue(d.user_id in [d.recipient for d in self.emails
+				if self.settings.subject in d.message])
 
 	def test_email_trigger_failed(self):
 		hour = '00'
 		if frappe.utils.nowtime().split(':')[0]=='00':
 			hour = '01'
 
-		settings, employees, emails = self.setup_and_prepare_test(hour)
+		self.setup_and_prepare_test(hour)
 
-		for d in employees:
+		for d in self.employees:
 			# check that email is sent to this employee
-			self.assertFalse(d.user_id in [d.recipient for d in emails
-				if settings.subject in d.message])
+			self.assertFalse(d.user_id in [d.recipient for d in self.emails
+				if self.settings.subject in d.message])
 
 	def test_incoming(self):
-		settings, employees, emails = self.setup_and_prepare_test()
-
 		# get test mail with message-id as in-reply-to
+		self.setup_and_prepare_test()
+
 		with open(os.path.join(os.path.dirname(__file__), "test_data", "test-reply.raw"), "r") as f:
-			test_mails = [f.read().replace('{{ sender }}', employees[-1].user_id)\
-				.replace('{{ message_id }}', emails[-1].message_id)]
+			test_mails = [f.read().replace('{{ sender }}', self.employees[-1].user_id)\
+				.replace('{{ message_id }}', self.emails[-1].message_id)]
 
 		# pull the mail
 		email_account = frappe.get_doc("Email Account", "_Test Email Account 1")
@@ -52,30 +51,34 @@
 		self.assertTrue('I built Daily Work Summary!' in summary)
 
 	def setup_and_prepare_test(self, hour=None):
-		if not hour:
-			hour = frappe.utils.nowtime().split(':')[0]
 		frappe.db.sql('delete from `tabDaily Work Summary`')
 		frappe.db.sql('delete from `tabEmail Queue`')
 		frappe.db.sql('delete from `tabEmail Queue Recipient`')
 		frappe.db.sql('delete from `tabCommunication`')
 
-		# setup email to trigger at this our
-		settings = frappe.get_doc('Daily Work Summary Settings')
-		settings.companies = []
-
-		settings.append('companies', dict(company='_Test Company',
-			send_emails_at=hour + ':00'))
-		settings.test_subject = 'this is a subject for testing summary emails'
-		settings.save()
+		self.setup_settings(hour)
 
 		from erpnext.hr.doctype.daily_work_summary_settings.daily_work_summary_settings \
 			import trigger_emails
 		trigger_emails()
 
 		# check if emails are created
-		employees = frappe.get_all('Employee', fields = ['user_id'],
-			filters=dict(company='_Test Company', status='Active'))
+		self.employees = frappe.get_all('Employee', fields = ['user_id'],
+			filters=dict(company='_Test Company', status='Active', user_id=('!=', 'test@example.com')))
 
-		emails = frappe.db.sql("""select r.recipient, q.message, q.message_id from `tabEmail Queue` as q, `tabEmail Queue Recipient` as r where q.name = r.parent""", as_dict=1)
+		self.emails = frappe.db.sql("""select r.recipient, q.message, q.message_id from `tabEmail Queue` as q, `tabEmail Queue Recipient` as r where q.name = r.parent""", as_dict=1)
 
-		return settings, employees, emails
\ No newline at end of file
+		frappe.db.commit()
+
+	def setup_settings(self, hour=None):
+		# setup email to trigger at this our
+		if not hour:
+			hour = frappe.utils.nowtime().split(':')[0]
+		self.settings = frappe.get_doc('Daily Work Summary Settings')
+		self.settings.companies = []
+
+		self.settings.append('companies', dict(company='_Test Company',
+			send_emails_at=hour + ':00'))
+		self.settings.test_subject = 'this is a subject for testing summary emails'
+		self.settings.save()
+
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 7aef4fc..681b62f 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -365,9 +365,6 @@
 		base_total_rm_cost = 0
 
 		for d in self.get('items'):
-			if d.bom_no:
-				d.rate = self.get_bom_unitcost(d.bom_no)
-
 			d.base_rate = flt(d.rate) * flt(self.conversion_rate)
 			d.amount = flt(d.rate, self.precision("rate", d)) * flt(d.stock_qty, self.precision("stock_qty", d))
 			d.base_amount = d.amount * flt(self.conversion_rate)
diff --git a/erpnext/manufacturing/doctype/production_order/production_order.json b/erpnext/manufacturing/doctype/production_order/production_order.json
index ee033c4..e56e5a1 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order.json
+++ b/erpnext/manufacturing/doctype/production_order/production_order.json
@@ -1358,7 +1358,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2017-06-13 14:29:00.457874", 
+ "modified": "2017-07-10 14:29:00.457874", 
  "modified_by": "Administrator", 
  "module": "Manufacturing", 
  "name": "Production Order", 
diff --git a/erpnext/manufacturing/doctype/production_order_item/production_order_item.json b/erpnext/manufacturing/doctype/production_order_item/production_order_item.json
index 06a7876..00e3adf 100644
--- a/erpnext/manufacturing/doctype/production_order_item/production_order_item.json
+++ b/erpnext/manufacturing/doctype/production_order_item/production_order_item.json
@@ -353,7 +353,7 @@
  "issingle": 0, 
  "istable": 1, 
  "max_attachments": 0, 
- "modified": "2017-05-15 17:37:20.212361", 
+ "modified": "2017-07-10 17:37:20.212361", 
  "modified_by": "Administrator", 
  "module": "Manufacturing", 
  "name": "Production Order Item", 
diff --git a/erpnext/patches/v8_0/merge_student_batch_and_student_group.py b/erpnext/patches/v8_0/merge_student_batch_and_student_group.py
index 7cfdf60..c5654eb 100644
--- a/erpnext/patches/v8_0/merge_student_batch_and_student_group.py
+++ b/erpnext/patches/v8_0/merge_student_batch_and_student_group.py
@@ -9,8 +9,8 @@
 
 def execute():
 	# for converting student batch into student group
-	for doctype in ["Student Group", "Student Group Student", "Student Group Instructor", "Student Attendance"]:
-		frappe.reload_doc("schools", "doctype", doctype)
+	for doctype in ["Student Group", "Student Group Student", "Student Group Instructor", "Student Attendance", "Student"]:
+		frappe.reload_doc("schools", "doctype", frappe.scrub(doctype))
 
 	if frappe.db.table_exists("Student Batch"):
 		student_batches = frappe.db.sql('''select name as student_group_name, student_batch_name as batch,
diff --git a/erpnext/patches/v8_1/setup_gst_india.py b/erpnext/patches/v8_1/setup_gst_india.py
index ce27d37..5660693 100644
--- a/erpnext/patches/v8_1/setup_gst_india.py
+++ b/erpnext/patches/v8_1/setup_gst_india.py
@@ -5,6 +5,7 @@
 	frappe.reload_doc('regional', 'doctype', 'gst_settings')
 	frappe.reload_doc('regional', 'doctype', 'gst_hsn_code')
 	frappe.reload_doc('stock', 'doctype', 'item')
+	frappe.reload_doc("stock", "doctype", "customs_tariff_number")
 
 	for report_name in ('GST Sales Register', 'GST Purchase Register',
 		'GST Itemised Sales Register', 'GST Itemised Purchase Register'):
diff --git a/erpnext/schools/doctype/program_enrollment/program_enrollment.json b/erpnext/schools/doctype/program_enrollment/program_enrollment.json
index 0203b2c..f8a3b9e 100644
--- a/erpnext/schools/doctype/program_enrollment/program_enrollment.json
+++ b/erpnext/schools/doctype/program_enrollment/program_enrollment.json
@@ -143,9 +143,10 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "default": "Today", 
-   "fieldname": "enrollment_date", 
-   "fieldtype": "Date", 
+   "default": "0", 
+   "description": "Check this if the Student is residing at the Institute's Hostel.", 
+   "fieldname": "boarding_student", 
+   "fieldtype": "Check", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
@@ -153,9 +154,10 @@
    "in_global_search": 0, 
    "in_list_view": 0, 
    "in_standard_filter": 0, 
-   "label": "Enrollment Date", 
+   "label": "Boarding Student", 
    "length": 0, 
    "no_copy": 0, 
+   "options": "", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -163,7 +165,7 @@
    "read_only": 0, 
    "remember_last_selected_value": 0, 
    "report_hide": 0, 
-   "reqd": 1, 
+   "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
    "unique": 0
@@ -325,6 +327,37 @@
    "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "default": "Today", 
+   "fieldname": "enrollment_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": "Enrollment 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": 1, 
    "collapsible_depends_on": "vehicle_no", 
    "columns": 0, 
@@ -370,7 +403,7 @@
    "label": "Mode of Transportation", 
    "length": 0, 
    "no_copy": 0, 
-   "options": "\nSchool Bus\nPublic Transport\nSelf-Driving Vehicle\nPick/Drop by Guardian", 
+   "options": "\nWalking\nSchool Bus\nPublic Transport\nSelf-Driving Vehicle\nPick/Drop by Guardian", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -638,7 +671,7 @@
  "istable": 0, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2017-06-30 08:21:49.430996", 
+ "modified": "2017-07-10 18:16:15.810616", 
  "modified_by": "Administrator", 
  "module": "Schools", 
  "name": "Program Enrollment", 
diff --git a/erpnext/schools/doctype/student/student.json b/erpnext/schools/doctype/student/student.json
index fa6db0d..75cb758 100644
--- a/erpnext/schools/doctype/student/student.json
+++ b/erpnext/schools/doctype/student/student.json
@@ -595,67 +595,6 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fieldname": "section_break_18", 
-   "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": "Guardian Details", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "guardians", 
-   "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": "Guardians", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Student Guardian", 
-   "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_22", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -863,6 +802,67 @@
    "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "section_break_18", 
+   "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": "Guardian Details", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "guardians", 
+   "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": "Guardians", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Student Guardian", 
+   "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": 1, 
    "columns": 0, 
    "fieldname": "section_break_20", 
@@ -1114,7 +1114,7 @@
  "istable": 0, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2017-06-30 08:21:50.423784", 
+ "modified": "2017-07-07 16:30:08.930882", 
  "modified_by": "Administrator", 
  "module": "Schools", 
  "name": "Student", 
diff --git a/erpnext/schools/doctype/student/student_dashboard.py b/erpnext/schools/doctype/student/student_dashboard.py
index cd2314e..b36599c 100644
--- a/erpnext/schools/doctype/student/student_dashboard.py
+++ b/erpnext/schools/doctype/student/student_dashboard.py
@@ -7,10 +7,24 @@
 		'fieldname': 'student',
 		'transactions': [
 			{
-				'items': ['Student Log', 'Student Group', 'Program Enrollment']
+				'label': _('Admission'),
+				'items': ['Program Enrollment']
 			},
 			{
-				'items': ['Fees', 'Assessment Result', 'Student Attendance', 'Student Leave Application']
+				'label': _('Student Activity'),
+				'items': ['Student Log', 'Student Group', ]
+			},
+			{
+				'label': _('Assessment'),
+				'items': ['Assessment Result']
+			},
+			{
+				'label': _('Attendance'),
+				'items': ['Student Attendance', 'Student Leave Application']
+			},
+			{
+				'label': _('Fee'),
+				'items': ['Fees']
 			}
 		]
 	}
\ No newline at end of file
diff --git a/erpnext/schools/doctype/student_attendance_tool/student_attendance_tool.js b/erpnext/schools/doctype/student_attendance_tool/student_attendance_tool.js
index 93c83f3..c5ff917 100644
--- a/erpnext/schools/doctype/student_attendance_tool/student_attendance_tool.js
+++ b/erpnext/schools/doctype/student_attendance_tool/student_attendance_tool.js
@@ -135,22 +135,24 @@
 				frappe.confirm(__("Do you want to update attendance?<br>Present: {0}\
 					<br>Absent: {1}", [students_present.length, students_absent.length]),
 					function() {	//ifyes
-						frappe.call({
-							method: "erpnext.schools.api.mark_attendance",
-							freeze: true,
-							freeze_message: "Marking attendance",
-							args: {
-								"students_present": students_present,
-								"students_absent": students_absent,
-								"student_group": frm.doc.student_group,
-								"course_schedule": frm.doc.course_schedule,
-								"date": frm.doc.date
-							},
-							callback: function(r) {
-								$(me.wrapper.find(".btn-mark-att")).attr("disabled", false);
-								frm.trigger("student_group");
-							}
-						});
+						if(!frappe.request.ajax_count) {
+							frappe.call({
+								method: "erpnext.schools.api.mark_attendance",
+								freeze: true,
+								freeze_message: "Marking attendance",
+								args: {
+									"students_present": students_present,
+									"students_absent": students_absent,
+									"student_group": frm.doc.student_group,
+									"course_schedule": frm.doc.course_schedule,
+									"date": frm.doc.date
+								},
+								callback: function(r) {
+									$(me.wrapper.find(".btn-mark-att")).attr("disabled", false);
+									frm.trigger("student_group");
+								}
+							});
+						}
 					},
 					function() {	//ifno
 						$(me.wrapper.find(".btn-mark-att")).attr("disabled", false);
diff --git a/erpnext/schools/doctype/student_log/student_log.json b/erpnext/schools/doctype/student_log/student_log.json
index 43ac134..6c9d4b0 100644
--- a/erpnext/schools/doctype/student_log/student_log.json
+++ b/erpnext/schools/doctype/student_log/student_log.json
@@ -1,5 +1,6 @@
 {
  "allow_copy": 0, 
+ "allow_guest_to_view": 0, 
  "allow_import": 0, 
  "allow_rename": 0, 
  "autoname": "SLog.####", 
@@ -13,6 +14,7 @@
  "engine": "InnoDB", 
  "fields": [
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -43,64 +45,7 @@
    "unique": 0
   }, 
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "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": 1, 
-   "label": "Type", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "General\nAcademic\nMedical\nAchievement", 
-   "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_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, 
@@ -131,6 +76,38 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "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": 1, 
+   "label": "Type", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "General\nAcademic\nMedical\nAchievement", 
+   "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, 
@@ -160,6 +137,160 @@
    "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, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "academic_year", 
+   "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": "Academic Year", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Academic Year", 
+   "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": "academic_term", 
+   "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": "Academic Term", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Academic Term", 
+   "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": "program", 
+   "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": "Program", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Program", 
+   "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": "student_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": "Student Batch", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Student Batch Name", 
+   "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, 
@@ -188,6 +319,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -217,17 +349,17 @@
    "unique": 0
   }
  ], 
+ "has_web_view": 0, 
  "hide_heading": 0, 
  "hide_toolbar": 0, 
  "idx": 0, 
  "image_view": 0, 
  "in_create": 0, 
- "in_dialog": 0, 
  "is_submittable": 0, 
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2017-02-17 17:18:19.596892", 
+ "modified": "2017-07-06 12:42:05.777673", 
  "modified_by": "Administrator", 
  "module": "Schools", 
  "name": "Student Log", 
diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py
index b102e1d..a4d4bf9 100644
--- a/erpnext/selling/doctype/quotation/quotation.py
+++ b/erpnext/selling/doctype/quotation/quotation.py
@@ -86,6 +86,17 @@
 			print_lst.append(lst1)
 		return print_lst
 
+def get_list_context(context=None):
+	from erpnext.controllers.website_list_for_contact import get_list_context
+	list_context = get_list_context(context)
+	list_context.update({
+		'show_sidebar': True,
+		'show_search': True,
+		'no_breadcrumbs': True,
+		'title': _('Quotes'),
+	})
+
+	return list_context
 
 @frappe.whitelist()
 def make_sales_order(source_name, target_doc=None):
diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py
index adff615..2766ba0 100644
--- a/erpnext/setup/doctype/item_group/item_group.py
+++ b/erpnext/setup/doctype/item_group/item_group.py
@@ -69,7 +69,7 @@
 		context.update({
 			"items": get_product_list_for_group(product_group = self.name, start=start,
 				limit=context.page_length + 1, search=frappe.form_dict.get("search")),
-			"parent_groups": get_parent_item_groups(self.name),
+			"parents": get_parent_item_groups(self.parent_item_group),
 			"title": self.name,
 			"products_as_list": cint(frappe.db.get_single_value('Website Settings', 'products_as_list'))
 		})
@@ -136,7 +136,8 @@
 
 def get_parent_item_groups(item_group_name):
 	item_group = frappe.get_doc("Item Group", item_group_name)
-	return frappe.db.sql("""select name, route from `tabItem Group`
+	return 	[{"name": frappe._("Home"), "route":"/"}]+\
+		frappe.db.sql("""select name, route from `tabItem Group`
 		where lft <= %s and rgt >= %s
 		and show_in_website=1
 		order by lft asc""", (item_group.lft, item_group.rgt), as_dict=True)
@@ -146,6 +147,6 @@
 		item_group = doc.name
 
 	for d in get_parent_item_groups(item_group):
-		d = frappe.get_doc("Item Group", d.name)
-		if d.route:
-			clear_cache(d.route)
+		item_group_name = frappe.db.get_value("Item Group", d.get('name'))
+		if item_group_name:
+			clear_cache(frappe.db.get_value('Item Group', item_group_name, 'route'))
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 9328194..2c6aab5 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -146,10 +146,6 @@
 			return cstr(frappe.db.get_value('Item Group', self.item_group,
 				'route')) + '/' + self.scrub(self.item_name + '-' + random_string(5))
 
-	def get_parents(self, context):
-		item_group, route = frappe.db.get_value('Item Group', self.item_group, ['name', 'route'])
-		context.parents = [{'name': route, 'label': item_group}]
-
 	def validate_website_image(self):
 		"""Validate if the website image is a public file"""
 		auto_set_website_image = False
@@ -242,15 +238,12 @@
 		context.show_search=True
 		context.search_link = '/product_search'
 
-		context.parent_groups = get_parent_item_groups(self.item_group) + \
-			[{"name": self.name}]
+		context.parents = get_parent_item_groups(self.item_group)
 
 		self.set_variant_context(context)
 		self.set_attribute_context(context)
 		self.set_disabled_attributes(context)
 
-		self.get_parents(context)
-
 		return context
 
 	def set_variant_context(self, context):
diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
index 5f1e944..aca77a5 100755
--- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
+++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
@@ -1597,7 +1597,7 @@
    "collapsible": 0,
    "columns": 0,
    "default": ":Company",
-   "depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
+   "depends_on": "eval:cint(erpnext.is_perpetual_inventory_enabled(parent.company))",
    "fieldname": "cost_center",
    "fieldtype": "Link",
    "hidden": 0,
@@ -2044,7 +2044,7 @@
  "issingle": 0,
  "istable": 1,
  "max_attachments": 0,
- "modified": "2017-06-16 17:23:01.404744",
+ "modified": "2017-07-10 06:31:31.457497",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Purchase Receipt Item",
diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py
index 8420c9b..fe158c9 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.py
+++ b/erpnext/stock/doctype/serial_no/serial_no.py
@@ -85,6 +85,10 @@
 				self.supplier, self.supplier_name = \
 					frappe.db.get_value("Purchase Receipt", purchase_sle.voucher_no,
 						["supplier", "supplier_name"])
+
+			# If sales return entry
+			if self.purchase_document_type == 'Delivery Note':
+				self.sales_invoice = None
 		else:
 			for fieldname in ("purchase_document_type", "purchase_document_no",
 				"purchase_date", "purchase_time", "purchase_rate", "supplier", "supplier_name"):
diff --git a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
index ec14aab..6afb54e 100644
--- a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
+++ b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
@@ -960,7 +960,7 @@
    "bold": 0,
    "collapsible": 0,
    "columns": 0,
-   "depends_on": "eval:cint(frappe.sys_defaults.auto_accounting_for_stock)",
+   "depends_on": "eval:cint(erpnext.is_perpetual_inventory_enabled(parent.company))",
    "fieldname": "expense_account",
    "fieldtype": "Link",
    "hidden": 0,
@@ -1020,7 +1020,7 @@
    "collapsible": 0,
    "columns": 0,
    "default": ":Company",
-   "depends_on": "eval:cint(frappe.sys_defaults.auto_accounting_for_stock)",
+   "depends_on": "eval:cint(erpnext.is_perpetual_inventory_enabled(parent.company))",
    "fieldname": "cost_center",
    "fieldtype": "Link",
    "hidden": 0,
@@ -1266,7 +1266,7 @@
  "issingle": 0,
  "istable": 1,
  "max_attachments": 0,
- "modified": "2017-06-16 17:32:56.989049",
+ "modified": "2017-07-10 06:29:22.805345",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Entry Detail",
diff --git a/erpnext/tests/ui/test_fixtures.js b/erpnext/tests/ui/test_fixtures.js
index e4ee664..2ba5db5 100644
--- a/erpnext/tests/ui/test_fixtures.js
+++ b/erpnext/tests/ui/test_fixtures.js
@@ -1,48 +1,216 @@
 $.extend(frappe.test_data, {
-	'Customer': {
-		'Test Customer 1': [
-			{customer_name: 'Test Customer 1'}
+	"Customer": {
+		"Test Customer 1": [
+			{customer_name: "Test Customer 1"}
 		],
-		'Test Customer 2': [
-			{customer_name: 'Test Customer 2'}
+		"Test Customer 2": [
+			{customer_name: "Test Customer 2"}
 		],
-		'Test Customer 3': [
-			{customer_name: 'Test Customer 3'}
+		"Test Customer 3": [
+			{customer_name: "Test Customer 3"}
 		],
 	},
-	'Item': {
-		'Test Product 1': [
-			{item_code: 'Test Product 1'},
-			{item_group: 'Products'},
+	"Item": {
+		"Test Product 1": [
+			{item_code: "Test Product 1"},
+			{item_group: "Products"},
 			{is_stock_item: 1},
 			{standard_rate: 100},
 			{opening_stock: 100},
 		],
-		'Test Product 2': [
-			{item_code: 'Test Product 2'},
-			{item_group: 'Products'},
+		"Test Product 2": [
+			{item_code: "Test Product 2"},
+			{item_group: "Products"},
 			{is_stock_item: 1},
 			{standard_rate: 150},
 			{opening_stock: 200},
 		],
-		'Test Product 3': [
-			{item_code: 'Test Product 3'},
-			{item_group: 'Products'},
+		"Test Product 3": [
+			{item_code: "Test Product 3"},
+			{item_group: "Products"},
 			{is_stock_item: 1},
 			{standard_rate: 250},
 			{opening_stock: 100},
 		],
-		'Test Service 1': [
-			{item_code: 'Test Service 1'},
-			{item_group: 'Services'},
+		"Test Service 1": [
+			{item_code: "Test Service 1"},
+			{item_group: "Services"},
 			{is_stock_item: 0},
 			{standard_rate: 200}
 		],
-		'Test Service 2': [
-			{item_code: 'Test Service 2'},
-			{item_group: 'Services'},
+		"Test Service 2": [
+			{item_code: "Test Service 2"},
+			{item_group: "Services"},
 			{is_stock_item: 0},
 			{standard_rate: 300}
 		]
+	},
+	"Lead": {
+		"LEAD-00001": [
+			{lead_name: "Test Lead 1"}
+		],
+		"LEAD-00002": [
+			{lead_name: "Test Lead 2"}
+		],
+		"LEAD-00003": [
+			{lead_name: "Test Lead 3"}
+		]
+	},
+	"Address": {
+		"Test1-Billing": [
+			{address_title:"Test1"},
+			{address_type: "Billing"},
+			{address_line1: "Billing Street 1"},
+			{city: "Billing City 1"},
+			{links: [
+				[
+					{link_doctype: "Customer"},
+					{link_name: "Test Customer 1"}
+				]
+			]}
+		],
+		"Test1-Shipping": [
+			{address_title:"Test1"},
+			{address_type: "Shipping"},
+			{address_line1: "Shipping Street 1"},
+			{city: "Shipping City 1"},
+			{links: [
+				[
+					{link_doctype: "Customer"},
+					{link_name: "Test Customer 1"}
+				]
+			]}
+		],
+		"Test1-Warehouse": [
+			{address_title:"Test1"},
+			{address_type: "Warehouse"},
+			{address_line1: "Warehouse Street 1"},
+			{city: "Warehouse City 1"},
+			{links: [
+				[
+					{link_doctype: "Customer"},
+					{link_name: "Test Customer 1"}
+				]
+			]}
+		],
+		"Test2-Billing": [
+			{address_title:"Test2"},
+			{address_type: "Billing"},
+			{address_line1: "Billing Street 2"},
+			{city: "Billing City 2"},
+			{links: [
+				[
+					{link_doctype: "Customer"},
+					{link_name: "Test Customer 2"}
+				]
+			]}
+		],
+		"Test2-Shipping": [
+			{address_title:"Test2"},
+			{address_type: "Shipping"},
+			{address_line1: "Shipping Street 2"},
+			{city: "Shipping City 2"},
+			{links: [
+				[
+					{link_doctype: "Customer"},
+					{link_name: "Test Customer 2"}
+				]
+			]}
+		],
+		"Test2-Warehouse": [
+			{address_title:"Test2"},
+			{address_type: "Warehouse"},
+			{address_line1: "Warehouse Street 2"},
+			{city: "Warehouse City 2"},
+			{links: [
+				[
+					{link_doctype: "Customer"},
+					{link_name: "Test Customer 2"}
+				]
+			]}
+		]
+	},
+	"Contact": {
+		"Contact 1-Test Customer 1": [
+			{first_name: "Contact 1"},
+			{links: [
+				[
+					{link_doctype: "Customer"},
+					{link_name: "Test Customer 1"}
+				]
+			]}
+		],
+		"Contact 2-Test Customer 1": [
+			{first_name: "Contact 2"},
+			{links: [
+				[
+					{link_doctype: "Customer"},
+					{link_name: "Test Customer 1"}
+				]
+			]}
+		],
+		"Contact 1-Test Customer 2": [
+			{first_name: "Contact 1"},
+			{links: [
+				[
+					{link_doctype: "Customer"},
+					{link_name: "Test Customer 2"}
+				]
+			]}
+		],
+		"Contact 2-Test Customer 2": [
+			{first_name: "Contact 2"},
+			{links: [
+				[
+					{link_doctype: "Customer"},
+					{link_name: "Test Customer 2"}
+				]
+			]}
+		],
+	},
+	"Price List": {
+		"Test-Buying-USD": [
+			{price_list_name: "Test-Buying-USD"},
+			{currency: "USD"},
+			{buying: "1"}
+		],
+		"Test-Buying-EUR": [
+			{price_list_name: "Test-Buying-EUR"},
+			{currency: "EUR"},
+			{buying: "1"}
+		],
+		"Test-Selling-USD": [
+			{price_list_name: "Test-Selling-USD"},
+			{currency: "USD"},
+			{selling: "1"}
+		],
+		"Test-Selling-EUR": [
+			{price_list_name: "Test-Selling-EUR"},
+			{currency: "EUR"},
+			{selling: "1"}
+		],
+	},
+	"Terms and Conditions": {
+		"Test Term 1": [
+			{title: "Test Term 1"}
+		],
+		"Test Term 2": [
+			{title: "Test Term 2"}
+		]
+	},
+	"Sales Taxes and Charges Template": {
+		"TEST In State GST": [
+			{title: "TEST In State GST"},
+			{taxes:[
+				[
+					{charge_type:"On Net Total"},
+					{account_head:"CGST - "+frappe.get_abbr(frappe.defaults.get_default("Company")) }
+				],
+				[
+					{charge_type:"On Net Total"},
+					{account_head:"SGST - "+frappe.get_abbr(frappe.defaults.get_default("Company")) }
+				]
+			]}
+		]
 	}
-});
\ No newline at end of file
+});
diff --git a/erpnext/tests/ui/test_sellling.js b/erpnext/tests/ui/test_sellling.js
index 5543a67..f676152 100644
--- a/erpnext/tests/ui/test_sellling.js
+++ b/erpnext/tests/ui/test_sellling.js
@@ -1,29 +1,120 @@
-QUnit.module('sales');
+QUnit.module("sales");
 
-QUnit.test("test quotation", function(assert) {
-	assert.expect(2);
+QUnit.test("test: lead", function (assert) {
+	assert.expect(1);
+	let done = assert.async();
+	let random = frappe.utils.get_random(10);
+	frappe.run_serially([
+		() => frappe.tests.setup_doctype("Lead"),
+		() => frappe.set_route("List", "Lead"),
+		() => frappe.new_doc("Lead"),
+		() => cur_frm.set_value("lead_name", random),
+		() => cur_frm.save(),
+		() => {
+			assert.ok(cur_frm.doc.lead_name.includes(random));
+			return done();
+		}
+	]);
+});
+
+QUnit.test("test: opportunity", function (assert) {
+	assert.expect(1);
 	let done = assert.async();
 	frappe.run_serially([
-		() => frappe.tests.setup_doctype('Customer'),
-		() => frappe.tests.setup_doctype('Item'),
 		() => {
-			return frappe.tests.make('Quotation', [
-				{customer: 'Test Customer 1'},
-				{items: [
-					[
-						{'item_code': 'Test Product 1'},
-						{'qty': 5}
+			return frappe.tests.make("Opportunity", [{
+				enquiry_from: "Lead"
+			},
+			{
+				lead: "LEAD-00002"
+			}
+			]);
+		},
+		() => {
+			assert.ok(cur_frm.doc.lead === "LEAD-00002");
+			return done();
+		}
+	]);
+});
+
+QUnit.test("test: quotation", function (assert) {
+	assert.expect(18);
+	let done = assert.async();
+	frappe.run_serially([
+		() => frappe.tests.setup_doctype("Customer"),
+		() => frappe.tests.setup_doctype("Item"),
+		() => frappe.tests.setup_doctype("Address"),
+		() => frappe.tests.setup_doctype("Contact"),
+		() => frappe.tests.setup_doctype("Price List"),
+		() => frappe.tests.setup_doctype("Terms and Conditions"),
+		() => frappe.tests.setup_doctype("Sales Taxes and Charges Template"),
+		() => {
+			return frappe.tests.make("Quotation", [{
+				customer: "Test Customer 1"
+			},
+			{
+				items: [
+					[{
+						"item_code": "Test Product 1"
+					},
+					{
+						"qty": 5
+					}
 					]
-				]}
+				]
+			}
 			]);
 		},
 		() => {
 			// get_item_details
-			assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1');
+			assert.ok(cur_frm.doc.items[0].item_name == "Test Product 1", "Added Test Product 1");
 
 			// calculate_taxes_and_totals
-			assert.ok(cur_frm.doc.grand_total==500);
+			assert.ok(cur_frm.doc.grand_total === 500, "Total Amount is correct");
 		},
+		() => cur_frm.set_value("customer_address", "Test1-Billing"),
+		() => cur_frm.set_value("shipping_address_name", "Test1-Warehouse"),
+		() => cur_frm.set_value("contact_person", "Contact 1-Test Customer 1"),
+		() => cur_frm.set_value("currency", "USD"),
+		() => frappe.timeout(0.3),
+		() => cur_frm.set_value("selling_price_list", "Test-Selling-USD"),
+		() => frappe.timeout(0.5),
+		() => cur_frm.doc.items[0].rate = 200,
+		() => frappe.timeout(0.3),
+		() => cur_frm.set_value("tc_name", "Test Term 1"),
+		() => cur_frm.set_value("taxes_and_charges", "TEST In State GST"),
+		() => frappe.timeout(0.3),
+		() => cur_frm.save(),
+		() => {
+			// Check Address and Contact Info
+			assert.ok(cur_frm.doc.address_display.includes("Billing Street 1"), "Address Changed");
+			assert.ok(cur_frm.doc.shipping_address.includes("Warehouse Street 1"), "Address Changed");
+			assert.ok(cur_frm.doc.contact_display == "Contact 1", "Contact info changed");
+
+			// Check Currency
+			assert.ok(cur_frm.doc_currency == "USD", "Currency Changed");
+			assert.ok(cur_frm.doc.selling_price_list == "Test-Selling-USD", "Price List Changed");
+			assert.ok(cur_frm.doc.items[0].rate == 200, "Price Changed Manually");
+			assert.ok(cur_frm.doc.total == 1000, "New Total Calculated");
+
+			// Check Terms and Condtions
+			assert.ok(cur_frm.doc.tc_name == "Test Term 1", "Terms and Conditions Checked");
+
+			// Check Taxes
+			assert.ok(cur_frm.doc.taxes[0].account_head.includes("CGST"));
+			assert.ok(cur_frm.doc.taxes[1].account_head.includes("SGST"));
+			assert.ok(cur_frm.doc.grand_total == 1180, "Tax Amount Added to Total");
+			assert.ok(cur_frm.doc.taxes_and_charges == "TEST In State GST", "Tax Template Selected");
+		},
+		() => frappe.timeout(0.3),
+		() => cur_frm.print_doc(),
+		() => frappe.timeout(1),
+		() => assert.ok($('.btn-print-print').is(':visible'), "Print Format Available"),
+		() => assert.ok(RegExp(/QTN-\d\d\d\d\d/g).test($("#header-html small").text())),
+		() => assert.ok($(".important .text-right.value").text().includes("$ 1,180.00")),
+		() => assert.ok($(".section-break+ .section-break .column-break:nth-child(1) .data-field:nth-child(1) .value").text().includes("Billing Street 1"), "Print Preview Works As Expected"),
+		() => frappe.timeout(0.3),
+		() => cur_frm.print_doc(),
 		() => done()
 	]);
-});
+});
\ No newline at end of file