Merge pull request #15976 from deepeshgarg007/summary

[Fix] Accounts receivable summary print format showing zero values
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index bb94383..92efe8e 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@
 from erpnext.hooks import regional_overrides
 from frappe.utils import getdate
 
-__version__ = '10.1.70'
+__version__ = '10.1.72'
 
 def get_default_company(user=None):
 	'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
index f5f832d..995efee 100644
--- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
@@ -11,11 +11,17 @@
 from frappe import MandatoryError
 
 class TestPricingRule(unittest.TestCase):
+	def setUp(self):
+		frappe.db.sql("delete from `tabPricing Rule`")
+
+	def tearDown(self):
+		frappe.db.sql("delete from `tabPricing Rule`")
+
 	def test_pricing_rule_for_discount(self):
 		from erpnext.stock.get_item_details import get_item_details
 		from frappe import MandatoryError
 
-		frappe.db.sql("delete from `tabPricing Rule`")
+
 
 		test_record = {
 			"doctype": "Pricing Rule",
@@ -89,14 +95,10 @@
 		details = get_item_details(args)
 		self.assertEqual(details.get("discount_percentage"), 15)
 
-		frappe.db.sql("delete from `tabPricing Rule`")
-
 	def test_pricing_rule_for_margin(self):
 		from erpnext.stock.get_item_details import get_item_details
 		from frappe import MandatoryError
 
-		frappe.db.sql("delete from `tabPricing Rule`")
-
 		test_record = {
 			"doctype": "Pricing Rule",
 			"title": "_Test Pricing Rule",
@@ -111,14 +113,14 @@
 			"company": "_Test Company"
 		}
 		frappe.get_doc(test_record.copy()).insert()
-		
+
 		item_price = frappe.get_doc({
 			"doctype": "Item Price",
 			"price_list": "_Test Price List 2",
 			"item_code": "_Test FG Item 2",
 			"price_list_rate": 100
 		})
-		
+
 		item_price.insert(ignore_permissions=True)
 
 		args = frappe._dict({
@@ -138,14 +140,10 @@
 		self.assertEqual(details.get("margin_type"), "Percentage")
 		self.assertEqual(details.get("margin_rate_or_amount"), 10)
 
-		frappe.db.sql("delete from `tabPricing Rule`")
-
 	def test_pricing_rule_for_variants(self):
 		from erpnext.stock.get_item_details import get_item_details
 		from frappe import MandatoryError
 
-		frappe.db.sql("delete from `tabPricing Rule`")
-
 		if not frappe.db.exists("Item", "Test Variant PRT"):
 			frappe.get_doc({
 				"doctype": "Item",
@@ -213,8 +211,6 @@
 		self.assertEqual(details.get("discount_percentage"), 17.5)
 
 	def test_pricing_rule_for_stock_qty(self):
-		frappe.db.sql("delete from `tabPricing Rule`")
-
 		test_record = {
 			"doctype": "Pricing Rule",
 			"title": "_Test Pricing Rule",
@@ -257,25 +253,19 @@
 		self.assertEqual(so.items[0].rate, 100)
 
 	def test_pricing_rule_with_margin_and_discount(self):
-		frappe.delete_doc_if_exists('Pricing Rule', '_Test Pricing Rule')
-		make_pricing_rule(selling=1, margin_type="Percentage", margin_rate_or_amount=10)
+		make_pricing_rule(selling=1, margin_type="Percentage", margin_rate_or_amount=10, discount_percentage=10)
 		si = create_sales_invoice(do_not_save=True)
 		si.items[0].price_list_rate = 1000
 		si.payment_schedule = []
 		si.insert(ignore_permissions=True)
 
 		item = si.items[0]
-		self.assertEqual(item.rate, 1100)
 		self.assertEqual(item.margin_rate_or_amount, 10)
-
-		# With discount
-		item.discount_percentage = 10
-		si.payment_schedule = []
-		si.save()
-		item = si.items[0]
-		self.assertEqual(item.rate, 990)
+		self.assertEqual(item.rate_with_margin, 1100)
 		self.assertEqual(item.discount_percentage, 10)
-		frappe.db.sql("delete from `tabPricing Rule`")
+		self.assertEqual(item.discount_amount, 110)
+		self.assertEqual(item.rate, 990)
+
 
 def make_pricing_rule(**args):
 	args = frappe._dict(args)
diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js
index 91a06f4..7b373f0 100644
--- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js
+++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js
@@ -43,6 +43,13 @@
 			"reqd": 1
 		},
 		{
+			"fieldname": "presentation_currency",
+			"label": __("Currency"),
+			"fieldtype": "Select",
+			"options": erpnext.get_presentation_currency_list(),
+			"default": frappe.defaults.get_user_default("Currency")
+		},
+		{
 			"fieldname":"accumulated_in_group_company",
 			"label": __("Accumulated Values in Group Company"),
 			"fieldtype": "Check",
diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
index 2d13469..b9aebd8 100644
--- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
+++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
@@ -5,6 +5,7 @@
 import frappe, erpnext
 from frappe import _
 from frappe.utils import flt, cint
+from erpnext.accounts.report.utils import get_currency, convert_to_presentation_currency
 from erpnext.accounts.report.financial_statements import get_fiscal_year_data, sort_accounts
 from erpnext.accounts.report.balance_sheet.balance_sheet import (get_provisional_profit_loss,
 	check_opening_balance, get_chart_data)
@@ -48,7 +49,7 @@
 	data.extend(liability or [])
 	data.extend(equity or [])
 
-	company_currency = frappe.db.get_value("Company", filters.company, "default_currency")
+	company_currency = get_company_currency(filters)
 	provisional_profit_loss, total_credit = get_provisional_profit_loss(asset, liability, equity,
 		companies, filters.get('company'), company_currency, True)
 
@@ -59,7 +60,7 @@
 			"account_name": "'" + _("Unclosed Fiscal Years Profit / Loss (Credit)") + "'",
 			"account": "'" + _("Unclosed Fiscal Years Profit / Loss (Credit)") + "'",
 			"warn_if_negative": True,
-			"currency": frappe.get_cached_value('Company',  filters.company,  "default_currency")
+			"currency": company_currency
 		}
 		for company in companies:
 			unclosed[company] = opening_balance
@@ -92,7 +93,7 @@
 	return data, None, chart
 
 def get_income_expense_data(companies, fiscal_year, filters):
-	company_currency = frappe.get_cached_value('Company',  filters.company,  "default_currency")
+	company_currency = get_company_currency(filters)
 	income = get_data(companies, "Income", "Credit", fiscal_year, filters, True)
 
 	expense = get_data(companies, "Expense", "Debit", fiscal_year, filters, True)
@@ -107,7 +108,7 @@
 	income, expense, net_profit_loss = get_income_expense_data(companies, fiscal_year, filters)
 
 	data = []
-	company_currency = frappe.get_cached_value('Company',  filters.company,  "default_currency")
+	company_currency = get_company_currency(filters)
 
 	for cash_flow_account in cash_flow_accounts:
 		section_data = []
@@ -185,6 +186,7 @@
 			"fieldname": company,
 			"label": company,
 			"fieldtype": "Currency",
+			"options": "currency",
 			"width": 150
 		})
 
@@ -216,7 +218,8 @@
 	return out
 
 def get_company_currency(filters=None):
-	return frappe.get_cached_value('Company',  filters.get('company'),  "default_currency")
+	return (filters.get('presentation_currency')
+		or frappe.get_cached_value('Company',  filters.company,  "default_currency"))
 
 def calculate_values(accounts_by_name, gl_entries_by_account, companies, fiscal_year, filters):
 	for entries in gl_entries_by_account.values():
@@ -328,28 +331,42 @@
 		filters.get('company'),  ["lft", "rgt"])
 
 	additional_conditions = get_additional_conditions(from_date, ignore_closing_entries, filters)
-
-	gl_entries = frappe.db.sql("""select gl.posting_date, gl.account, gl.debit, gl.credit, gl.is_opening, gl.company,
-		gl.fiscal_year, gl.debit_in_account_currency, gl.credit_in_account_currency, gl.account_currency,
-		acc.account_name, acc.account_number
-		from `tabGL Entry` gl, `tabAccount` acc where acc.name = gl.account and gl.company in 
-		(select name from `tabCompany` where lft >= %(company_lft)s and rgt <= %(company_rgt)s)
-		{additional_conditions} and gl.posting_date <= %(to_date)s and acc.lft >= %(lft)s and acc.rgt <= %(rgt)s
-		order by gl.account, gl.posting_date""".format(additional_conditions=additional_conditions),
-		{
-			"from_date": from_date,
-			"to_date": to_date,
-			"lft": root_lft,
-			"rgt": root_rgt,
+	companies = frappe.db.sql(""" select name, default_currency from `tabCompany`
+		where lft >= %(company_lft)s and rgt <= %(company_rgt)s""", {
 			"company_lft": company_lft,
 			"company_rgt": company_rgt,
-		},
-		as_dict=True)
+		}, as_dict=1)
 
-	for entry in gl_entries:
-		key = entry.account_number or entry.account_name
-		validate_entries(key, entry, accounts_by_name)
-		gl_entries_by_account.setdefault(key, []).append(entry)
+	currency_info = frappe._dict({
+		'report_date': to_date,
+		'presentation_currency': filters.get('presentation_currency')
+	})
+
+	for d in companies:
+		gl_entries = frappe.db.sql("""select gl.posting_date, gl.account, gl.debit, gl.credit, gl.is_opening, gl.company,
+			gl.fiscal_year, gl.debit_in_account_currency, gl.credit_in_account_currency, gl.account_currency,
+			acc.account_name, acc.account_number
+			from `tabGL Entry` gl, `tabAccount` acc where acc.name = gl.account and gl.company = %(company)s
+			{additional_conditions} and gl.posting_date <= %(to_date)s and acc.lft >= %(lft)s and acc.rgt <= %(rgt)s
+			order by gl.account, gl.posting_date""".format(additional_conditions=additional_conditions),
+			{
+				"from_date": from_date,
+				"to_date": to_date,
+				"lft": root_lft,
+				"rgt": root_rgt,
+				"company": d.name
+			},
+			as_dict=True)
+
+		if filters and filters.get('presentation_currency') != d.default_currency:
+			currency_info['company'] = d.name
+			currency_info['company_currency'] = d.default_currency
+			convert_to_presentation_currency(gl_entries, currency_info)
+
+		for entry in gl_entries:
+			key = entry.account_number or entry.account_name
+			validate_entries(key, entry, accounts_by_name)
+			gl_entries_by_account.setdefault(key, []).append(entry)
 
 	return gl_entries_by_account
 
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 6985c80..a441025 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -65,12 +65,13 @@
 
 				if item.doctype in ['Quotation Item', 'Sales Order Item', 'Delivery Note Item', 'Sales Invoice Item']:
 					item.rate_with_margin, item.base_rate_with_margin = self.calculate_margin(item)
-
-					item.rate = flt(item.rate_with_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))\
-						if item.rate_with_margin > 0 else item.rate
+					if flt(item.rate_with_margin) > 0:
+						item.rate = flt(item.rate_with_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))
+						item.discount_amount = item.rate_with_margin - item.rate
+				elif flt(item.price_list_rate) > 0:
+						item.discount_amount = item.price_list_rate - item.rate
 
 				item.net_rate = item.rate
-				item.discount_amount = item.price_list_rate - item.rate
 				item.amount = flt(item.rate * item.qty,	item.precision("amount"))
 				item.net_amount = item.amount
 
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 87b7942..6947c02 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -12,7 +12,7 @@
 source_link = "https://github.com/frappe/erpnext"
 
 develop_version = '12.x.x-develop'
-staging_version = '11.0.3-beta.20'
+staging_version = '11.0.3-beta.22'
 
 error_report_email = "support@erpnext.com"
 
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.py b/erpnext/hr/doctype/employee_advance/employee_advance.py
index 62355b8..1c8b5f9 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.py
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.py
@@ -13,7 +13,7 @@
 
 class EmployeeAdvance(Document):
 	def onload(self):
-		self.get("__onload").make_payment_via_journal_entry = frappe.db.get_single_value('Accounts Settings', 
+		self.get("__onload").make_payment_via_journal_entry = frappe.db.get_single_value('Accounts Settings',
 			'make_payment_via_journal_entry')
 
 	def validate(self):
@@ -47,7 +47,7 @@
 		paid_amount = frappe.db.sql("""
 			select ifnull(sum(debit_in_account_currency), 0) as paid_amount
 			from `tabGL Entry`
-			where against_voucher_type = 'Employee Advance' 
+			where against_voucher_type = 'Employee Advance'
 				and against_voucher = %s
 				and party_type = 'Employee'
 				and party = %s
@@ -67,7 +67,7 @@
 			select sum(ifnull(allocated_amount, 0))
 			from `tabExpense Claim Advance`
 			where employee_advance = %s and docstatus=1 and allocated_amount > 0
-		""", self.name)[0][0]
+		""", self.name)[0][0] or 0
 
 		if claimed_amount:
 			frappe.db.set_value("Employee Advance", self.name, "claimed_amount", flt(claimed_amount))
diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.js b/erpnext/hr/doctype/salary_structure/salary_structure.js
index 4a111e7..033938d 100755
--- a/erpnext/hr/doctype/salary_structure/salary_structure.js
+++ b/erpnext/hr/doctype/salary_structure/salary_structure.js
@@ -58,6 +58,9 @@
 				doc.company = frm.doc.company;
 				frappe.set_route('Form', 'Salary Structure Assignment', doc.name);
 			});
+			frm.add_custom_button(__("Assign to Employees"),function () {
+			frm.trigger('assign_to_employees')
+		})
 		}
 		let fields_read_only = ["is_tax_applicable", "is_flexible_benefit", "variable_based_on_taxable_salary"];
 		fields_read_only.forEach(function(field) {
@@ -65,6 +68,43 @@
 		});
 	},
 
+	assign_to_employees:function (frm) {
+		var d = new frappe.ui.Dialog({
+			title: __("Assign to Employees"),
+			fields: [
+				{fieldname: "sec_break", fieldtype: "Section Break", label: __("Filter Employees By (Optional)")},
+				{fieldname: "grade", fieldtype: "Link", options: "Employee Grade", label: __("Employee Grade")},
+				{fieldname:'department', fieldtype:'Link', options: 'Department', label: __('Department')},
+				{fieldname:'designation', fieldtype:'Link', options: 'Designation', label: __('Designation')},
+                {fieldname:"employee", fieldtype: "Link", options: "Employee", label: __("Employee")},
+				{fieldname:'base_variable', fieldtype:'Section Break'},
+				{fieldname:'from_date', fieldtype:'Date', label: __('From Date'), "reqd": 1},
+				{fieldname:'base_col_br', fieldtype:'Column Break'},
+				{fieldname:'base', fieldtype:'Currency', label: __('Base')},
+				{fieldname:'variable', fieldtype:'Currency', label: __('Variable')}
+			],
+			primary_action: function() {
+				var data = d.get_values();
+
+				frappe.call({
+					doc: frm.doc,
+					method: "assign_salary_structure",
+					args: data,
+					callback: function(r) {
+						if(!r.exc) {
+							d.hide();
+							frm.reload_doc();
+						}
+					}
+				});
+			},
+			primary_action_label: __('Assign')
+		});
+
+
+		d.show();
+	},
+
 	salary_slip_based_on_timesheet: function(frm) {
 		frm.trigger("toggle_fields")
 	},
diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.py b/erpnext/hr/doctype/salary_structure/salary_structure.py
index a36d820..7ead140 100644
--- a/erpnext/hr/doctype/salary_structure/salary_structure.py
+++ b/erpnext/hr/doctype/salary_structure/salary_structure.py
@@ -65,6 +65,76 @@
 		if not have_a_flexi and flt(self.max_benefits) > 0:
 			frappe.throw(_("Salary Structure should have flexible benefit component(s) to dispense benefit amount"))
 
+	def get_employees(self, **kwargs):
+		conditions, values = [], []
+		for field, value in kwargs.items():
+			if value:
+				conditions.append("{0}=%s".format(field))
+				values.append(value)
+
+		condition_str = " and " + " and ".join(conditions) if conditions else ""
+
+		employees = frappe.db.sql_list("select name from tabEmployee where status='Active' {condition}"
+			.format(condition=condition_str), tuple(values))
+
+		return employees
+
+	@frappe.whitelist()
+	def assign_salary_structure(self, grade=None, department=None, designation=None,employee=None,
+			from_date=None, base=None,variable=None):
+		employees = self.get_employees(grade= grade,department= department,designation= designation,name=employee)
+
+		if employees:
+			if len(employees) > 20:
+				frappe.enqueue(assign_salary_structure_for_employees, timeout=600,
+					employees=employees, salary_structure=self,from_date=from_date, base=base,variable=variable)
+			else:
+				assign_salary_structure_for_employees(employees, self,from_date=from_date, base=base,variable=variable)
+		else:
+			frappe.msgprint(_("No Employee Found"))
+
+
+
+def assign_salary_structure_for_employees(employees, salary_structure,from_date=None, base=None,variable=None):
+	salary_structures_assignments = []
+	existing_assignments_for = get_existing_assignments(employees, salary_structure.name,from_date)
+	count=0
+	for employee in employees:
+		if employee in existing_assignments_for:
+			continue
+		count +=1
+
+		salary_structures_assignment = create_salary_structures_assignment(employee, salary_structure, from_date, base, variable)
+		salary_structures_assignments.append(salary_structures_assignment)
+		frappe.publish_progress(count*100/len(set(employees) - set(existing_assignments_for)), title = _("Assigning Structures..."))
+
+	if salary_structures_assignments:
+		frappe.msgprint(_("Structures have been assigned successfully"))
+
+
+def create_salary_structures_assignment(employee, salary_structure, from_date, base, variable):
+	assignment = frappe.new_doc("Salary Structure Assignment")
+	assignment.employee = employee
+	assignment.salary_structure = salary_structure.name
+	assignment.from_date = from_date
+	assignment.base = base
+	assignment.variable = variable
+	assignment.save(ignore_permissions = True)
+	assignment.submit()
+	return assignment.name
+
+
+def get_existing_assignments(employees, salary_structure,from_date):
+	salary_structures_assignments = frappe.db.sql_list("""
+		select distinct employee from `tabSalary Structure Assignment` 
+		where salary_structure=%s and employee in (%s)
+		and from_date=%s and docstatus=1
+	""" % ('%s', ', '.join(['%s']*len(employees)),'%s'), [salary_structure] + employees+[from_date])
+	if salary_structures_assignments:
+		frappe.msgprint(_("Skipping Salary Structure Assignment for the following employees, as Salary Structure Assignment records already exists against them. {0}")
+			.format("\n".join(salary_structures_assignments)))
+	return salary_structures_assignments
+
 @frappe.whitelist()
 def make_salary_slip(source_name, target_doc = None, employee = None, as_print = False, print_format = None):
 	def postprocess(source, target):
diff --git a/erpnext/hr/doctype/salary_structure/test_salary_structure.py b/erpnext/hr/doctype/salary_structure/test_salary_structure.py
index 1a16db7..1a660d9 100644
--- a/erpnext/hr/doctype/salary_structure/test_salary_structure.py
+++ b/erpnext/hr/doctype/salary_structure/test_salary_structure.py
@@ -71,6 +71,19 @@
 		for row in salary_structure.deductions:
 			self.assertFalse(("\n" in row.formula) or ("\n" in row.condition))
 
+	def test_salary_structures_assignment(self):
+		salary_structure = make_salary_structure("Salary Structure Sample", "Monthly")
+		employee = "test_assign_stucture@salary.com"
+		employee_doc_name = make_employee(employee)
+		# clear the already assigned stuctures
+		frappe.db.sql('''delete from `tabSalary Structure Assignment` where employee=%s and salary_structure=%s ''',
+					  ("test_assign_stucture@salary.com",salary_structure.name))
+		#test structure_assignment
+		salary_structure.assign_salary_structure(employee=employee_doc_name,from_date='2013-01-01',base=5000,variable=200)
+		salary_structure_assignment = frappe.get_doc("Salary Structure Assignment",{'employee':employee_doc_name, 'from_date':'2013-01-01'})
+		self.assertEqual(salary_structure_assignment.docstatus, 1)
+		self.assertEqual(salary_structure_assignment.base, 5000)
+		self.assertEqual(salary_structure_assignment.variable, 200)
 
 def make_salary_structure(salary_structure, payroll_frequency, employee=None, dont_submit=False, other_details=None, test_tax=False):
 	if test_tax:
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 0eab982..d72f00a 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -108,7 +108,8 @@
 				"item_code": item.item_code,
 				"item_name": item.item_name,
 				"bom_no": item.bom_no,
-				"stock_qty": item.stock_qty
+				"stock_qty": item.stock_qty,
+				"allow_transfer_for_manufacture": item.allow_transfer_for_manufacture
 			})
 			for r in ret:
 				if not item.get(r):
@@ -127,6 +128,8 @@
 		self.validate_rm_item(item)
 
 		args['bom_no'] = args['bom_no'] or item and cstr(item[0]['default_bom']) or ''
+		args['transfer_for_manufacture'] = (cstr(args.get('allow_transfer_for_manufacture', '')) or
+			item and item[0].allow_transfer_for_manufacture or 0)
 		args.update(item[0])
 
 		rate = self.get_rm_rate(args)
@@ -142,7 +145,7 @@
 			 'qty'			: args.get("qty") or args.get("stock_qty") or 1,
 			 'stock_qty'	: args.get("qty") or args.get("stock_qty") or 1,
 			 'base_rate'	: rate,
-			 'allow_transfer_for_manufacture': item and args['allow_transfer_for_manufacture'] or 0
+			 'allow_transfer_for_manufacture': cint(args['transfer_for_manufacture']) or 0
 		}
 
 		return ret_item
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 1f231e6..f771181 100755
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -572,8 +572,10 @@
 execute:frappe.delete_doc("Page", "Purchase Analytics")
 execute:frappe.delete_doc("Page", "Stock Analytics")
 execute:frappe.delete_doc("Page", "Production Analytics")
-erpnext.patches.v11_0.ewaybill_fields_gst_india
+erpnext.patches.v11_0.ewaybill_fields_gst_india #2018-11-13
 erpnext.patches.v11_0.drop_column_max_days_allowed
 erpnext.patches.v11_0.change_healthcare_desktop_icons
 erpnext.patches.v10_0.update_user_image_in_employee
-erpnext.patches.v11_0.update_delivery_trip_status
\ No newline at end of file
+erpnext.patches.v11_0.update_delivery_trip_status
+erpnext.patches.v10_0.repost_gle_for_purchase_receipts_with_rejected_items
+erpnext.patches.v11_0.set_missing_gst_hsn_code
diff --git a/erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py b/erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py
new file mode 100644
index 0000000..68c06ef
--- /dev/null
+++ b/erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py
@@ -0,0 +1,32 @@
+# Copyright (c) 2017, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe, erpnext
+
+def execute():
+	for company in frappe.get_all("Company"):
+		if not erpnext.is_perpetual_inventory_enabled(company.name):
+			continue
+
+		acc_frozen_upto = frappe.db.get_value("Accounts Settings", None, "acc_frozen_upto") or "1900-01-01"
+		pr_with_rejected_warehouse = frappe.db.sql("""
+			select pr.name
+			from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pr_item
+			where pr.name = pr_item.parent
+				and pr.posting_date > %s
+				and pr.docstatus=1
+				and pr.company = %s
+				and pr_item.rejected_qty > 0
+		""", (acc_frozen_upto, company.name), as_dict=1)
+
+		for d in pr_with_rejected_warehouse:
+			doc = frappe.get_doc("Purchase Receipt", d.name)
+
+			doc.docstatus = 2
+			doc.make_gl_entries_on_cancel(repost_future_gle=False)
+
+
+			# update gl entries for submit state of PR
+			doc.docstatus = 1
+			doc.make_gl_entries(repost_future_gle=False)
diff --git a/erpnext/patches/v11_0/set_missing_gst_hsn_code.py b/erpnext/patches/v11_0/set_missing_gst_hsn_code.py
new file mode 100644
index 0000000..3c2cea2
--- /dev/null
+++ b/erpnext/patches/v11_0/set_missing_gst_hsn_code.py
@@ -0,0 +1,43 @@
+import frappe
+from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_html
+
+def execute():
+	company = frappe.db.sql_list("select name from tabCompany where country = 'India'")
+	if not company:
+		return
+
+	doctypes = ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice",
+		"Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice"]
+
+	for dt in doctypes:
+		date_field = "posting_date"
+		if dt in ["Quotation", "Sales Order", "Supplier Quotation", "Purchase Order"]:
+			date_field = "transaction_date"
+
+		transactions = frappe.db.sql("""
+			select dt.name, dt_item.name as child_name
+			from `tab{dt}` dt, `tab{dt} Item` dt_item
+			where dt.name = dt_item.parent
+				and dt.`{date_field}` > '2018-06-01'
+				and dt.docstatus = 1
+				and ifnull(dt_item.gst_hsn_code, '') = ''
+				and ifnull(dt_item.item_code, '') != ''
+				and dt.company in ({company})
+		""".format(dt=dt, date_field=date_field, company=", ".join(['%s']*len(company))), tuple(company), as_dict=1)
+
+		if not transactions:
+			continue
+
+		transaction_rows_name = [d.child_name for d in transactions]
+
+		frappe.db.sql("""
+			update `tab{dt} Item` dt_item
+			set dt_item.gst_hsn_code = (select gst_hsn_code from tabItem where name=dt_item.item_code)
+			where dt_item.name in ({rows_name})
+		""".format(dt=dt, rows_name=", ".join(['%s']*len(transaction_rows_name))), tuple(transaction_rows_name))
+
+		parent = set([d.name for d in transactions])
+		for t in list(parent):
+			trans_doc = frappe.get_doc(dt, t)
+			hsnwise_tax = get_itemised_tax_breakup_html(trans_doc)
+			frappe.db.set_value(dt, t, "other_charges_calculation", hsnwise_tax, update_modified=False)
\ No newline at end of file
diff --git a/erpnext/patches/v11_0/update_total_qty_field.py b/erpnext/patches/v11_0/update_total_qty_field.py
index 5c7663d..8f08699 100644
--- a/erpnext/patches/v11_0/update_total_qty_field.py
+++ b/erpnext/patches/v11_0/update_total_qty_field.py
@@ -9,12 +9,12 @@
 	frappe.reload_doc('stock', 'doctype', 'purchase_receipt')
 	frappe.reload_doc('accounts', 'doctype', 'sales_invoice')
 	frappe.reload_doc('accounts', 'doctype', 'purchase_invoice')
- 
+
 	doctypes = ["Sales Order", "Sales Invoice", "Delivery Note",\
 		"Purchase Order", "Purchase Invoice", "Purchase Receipt", "Quotation", "Supplier Quotation"]
 
 	for doctype in doctypes:
-		total_qty =	frappe.db.sql('''
+		total_qty = frappe.db.sql('''
 			SELECT
 				parent, SUM(qty) as qty
 			FROM
@@ -22,14 +22,25 @@
 			GROUP BY parent
 		''' % (doctype), as_dict = True)
 
-		when_then = []
-		for d in total_qty:
-			when_then.append("""
-				when dt.name = '{0}' then {1}
-			""".format(frappe.db.escape(d.get("parent")), d.get("qty")))
+		# Query to update total_qty might become too big, Update in batches
+		# batch_size is chosen arbitrarily, Don't try too hard to reason about it
+		batch_size = 100000
+		for i in range(0, len(total_qty), batch_size):
+			batch_transactions = total_qty[i:i + batch_size]
 
-		if when_then:
-			frappe.db.sql('''
-				UPDATE
-					`tab%s` dt SET dt.total_qty = CASE %s ELSE 0.0 END
-			''' % (doctype, " ".join(when_then)))
\ No newline at end of file
+			# UPDATE with CASE for some reason cannot use PRIMARY INDEX,
+			# causing all rows to be examined, leading to a very slow update
+
+			# UPDATE with WHERE clause uses PRIMARY INDEX, but will lead to too many queries
+
+			# INSERT with ON DUPLICATE KEY UPDATE uses PRIMARY INDEX
+			# and can perform multiple updates per query
+			# This is probably never used anywhere else as of now, but should be
+			values = []
+			for d in batch_transactions:
+				values.append("('{}', {})".format(d.parent, d.qty))
+			conditions = ",".join(values)
+			frappe.db.sql("""
+				INSERT INTO `tab{}` (name, total_qty) VALUES {}
+				ON DUPLICATE KEY UPDATE name = VALUES(name), total_qty = VALUES(total_qty)
+			""".format(doctype, conditions))
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index 21e02b7..a2d44c3 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -13,8 +13,8 @@
 				+ flt(effective_item_rate) * ( flt(item.margin_rate_or_amount) / 100);
 		} else {
 			item.rate_with_margin = flt(effective_item_rate) + flt(item.margin_rate_or_amount);
-			item.base_rate_with_margin = flt(item.rate_with_margin) * flt(this.frm.doc.conversion_rate);
 		}
+		item.base_rate_with_margin = flt(item.rate_with_margin) * flt(this.frm.doc.conversion_rate);
 
 		item.rate = flt(item.rate_with_margin , precision("rate", item));
 
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index f3c29fc..a33b87f 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -33,6 +33,7 @@
 				item.margin_rate_or_amount = 0;
 				item.rate_with_margin = 0;
 			}
+			item.base_rate_with_margin = item.rate_with_margin * flt(this.frm.doc.conversion_rate);
 
 			cur_frm.cscript.set_gross_profit(item);
 			cur_frm.cscript.calculate_taxes_and_totals();
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index c754121..d282f5c 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -85,7 +85,7 @@
 
 def make_custom_fields(update=True):
 	hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC',
-		fieldtype='Data', options='item_code.gst_hsn_code', insert_after='description',
+		fieldtype='Data', fetch_from='item_code.gst_hsn_code', insert_after='description',
 		allow_on_submit=1, print_hide=1)
 	invoice_gst_fields = [
 		dict(fieldname='gst_section', label='GST Details', fieldtype='Section Break',
diff --git a/erpnext/stock/doctype/item_barcode/item_barcode.json b/erpnext/stock/doctype/item_barcode/item_barcode.json
index c8a3a89..d89ca55 100644
--- a/erpnext/stock/doctype/item_barcode/item_barcode.json
+++ b/erpnext/stock/doctype/item_barcode/item_barcode.json
@@ -1,5 +1,6 @@
 {
  "allow_copy": 0, 
+ "allow_events_in_timeline": 0, 
  "allow_guest_to_view": 0, 
  "allow_import": 0, 
  "allow_rename": 0, 
@@ -15,6 +16,7 @@
  "fields": [
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -38,13 +40,15 @@
    "read_only": 0, 
    "remember_last_selected_value": 0, 
    "report_hide": 0, 
-   "reqd": 1, 
+   "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
+   "translatable": 0, 
    "unique": 1
   }, 
   {
    "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -72,6 +76,7 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
+   "translatable": 0, 
    "unique": 0
   }
  ], 
@@ -85,7 +90,7 @@
  "issingle": 0, 
  "istable": 1, 
  "max_attachments": 0, 
- "modified": "2017-12-10 20:55:23.814039", 
+ "modified": "2018-11-13 06:03:09.814357", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Item Barcode", 
@@ -99,5 +104,6 @@
  "sort_field": "modified", 
  "sort_order": "DESC", 
  "track_changes": 1, 
- "track_seen": 0
+ "track_seen": 0, 
+ "track_views": 0
 }
\ No newline at end of file
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index e482f58..f006d00 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -185,7 +185,8 @@
 				if warehouse_account.get(d.warehouse):
 					stock_value_diff = frappe.db.get_value("Stock Ledger Entry",
 						{"voucher_type": "Purchase Receipt", "voucher_no": self.name,
-						"voucher_detail_no": d.name}, "stock_value_difference")
+						"voucher_detail_no": d.name, "warehouse": d.warehouse}, "stock_value_difference")
+
 					if not stock_value_diff:
 						continue
 					gl_entries.append(self.get_gl_dict({