Merge branch 'develop' of https://github.com/frappe/erpnext into lcv_multicurrency
diff --git a/.github/helper/documentation.py b/.github/helper/documentation.py
index b603ed5..9cc4663 100644
--- a/.github/helper/documentation.py
+++ b/.github/helper/documentation.py
@@ -21,8 +21,8 @@
 			if word.startswith('http') and uri_validator(word):
 				parsed_url = urlparse(word)
 				if parsed_url.netloc == "github.com":
-					_, org, repo, _type, ref = parsed_url.path.split('/')
-					if org == "frappe" and repo in docs_repos:
+					parts = parsed_url.path.split('/')
+					if len(parts) == 5 and parts[1] == "frappe" and parts[2] in docs_repos:
 						return True
 
 
diff --git a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py
index fd702c7..74ca62f 100644
--- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py
+++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py
@@ -13,8 +13,8 @@
 class AssetValueAdjustment(Document):
 	def validate(self):
 		self.validate_date()
-		self.set_difference_amount()
 		self.set_current_asset_value()
+		self.set_difference_amount()
 
 	def on_submit(self):
 		self.make_depreciation_entry()
@@ -25,7 +25,7 @@
 			frappe.throw(_("Cancel the journal entry {0} first").format(self.journal_entry))
 
 		self.reschedule_depreciations(self.current_asset_value)
-	
+
 	def validate_date(self):
 		asset_purchase_date = frappe.db.get_value('Asset', self.asset, 'purchase_date')
 		if getdate(self.date) < getdate(asset_purchase_date):
@@ -53,6 +53,7 @@
 		je.posting_date = self.date
 		je.company = self.company
 		je.remark = "Depreciation Entry against {0} worth {1}".format(self.asset, self.difference_amount)
+		je.finance_book = self.finance_book
 
 		credit_entry = {
 			"account": accumulated_depreciation_account,
@@ -78,7 +79,7 @@
 				debit_entry.update({
 					dimension['fieldname']: self.get(dimension['fieldname']) or dimension.get('default_dimension')
 				})
-		
+
 		je.append("accounts", credit_entry)
 		je.append("accounts", debit_entry)
 
diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py
index 2555edf..8c05134 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -254,22 +254,26 @@
 				if not args.get("second_source_extra_cond"):
 					args["second_source_extra_cond"] = ""
 
-				args['second_source_condition'] = """ + ifnull((select sum(%(second_source_field)s)
+				args['second_source_condition'] = frappe.db.sql(""" select ifnull((select sum(%(second_source_field)s)
 					from `tab%(second_source_dt)s`
 					where `%(second_join_field)s`="%(detail_id)s"
-					and (`tab%(second_source_dt)s`.docstatus=1) %(second_source_extra_cond)s FOR UPDATE), 0)""" % args
+					and (`tab%(second_source_dt)s`.docstatus=1)
+					%(second_source_extra_cond)s), 0) """ % args)[0][0]
 
 			if args['detail_id']:
 				if not args.get("extra_cond"): args["extra_cond"] = ""
 
-				frappe.db.sql("""update `tab%(target_dt)s`
-					set %(target_field)s = (
+				args["source_dt_value"] = frappe.db.sql("""
 						(select ifnull(sum(%(source_field)s), 0)
 							from `tab%(source_dt)s` where `%(join_field)s`="%(detail_id)s"
 							and (docstatus=1 %(cond)s) %(extra_cond)s)
-						%(second_source_condition)s
-					)
-					%(update_modified)s
+				""" % args)[0][0] or 0.0
+
+				if args['second_source_condition']:
+					args["source_dt_value"] += flt(args['second_source_condition'])
+
+				frappe.db.sql("""update `tab%(target_dt)s`
+					set %(target_field)s = %(source_dt_value)s %(update_modified)s
 					where name='%(detail_id)s'""" % args)
 
 	def _update_percent_field_in_targets(self, args, update_modified=True):
diff --git a/erpnext/erpnext_integrations/connectors/shopify_connection.py b/erpnext/erpnext_integrations/connectors/shopify_connection.py
index efbaa71..f0a05ed 100644
--- a/erpnext/erpnext_integrations/connectors/shopify_connection.py
+++ b/erpnext/erpnext_integrations/connectors/shopify_connection.py
@@ -260,6 +260,15 @@
 	"""Shipping lines represents the shipping details,
 		each such shipping detail consists of a list of tax_lines"""
 	for shipping_charge in shipping_lines:
+		if shipping_charge.get("price"):
+			taxes.append({
+				"charge_type": _("Actual"),
+				"account_head": get_tax_account_head(shipping_charge),
+				"description": shipping_charge["title"],
+				"tax_amount": shipping_charge["price"],
+				"cost_center": shopify_settings.cost_center
+			})
+
 		for tax in shipping_charge.get("tax_lines"):
 			taxes.append({
 				"charge_type": _("Actual"),
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.js b/erpnext/hr/doctype/employee_advance/employee_advance.js
index 7056adf..5037ceb 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.js
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.js
@@ -18,13 +18,18 @@
 			if (!frm.doc.employee) {
 				frappe.msgprint(__("Please select employee first"));
 			}
-			var company_currency = erpnext.get_currency(frm.doc.company);
+			let company_currency = erpnext.get_currency(frm.doc.company);
+			let currencies = [company_currency];
+			if (frm.doc.currency && (frm.doc.currency != company_currency)) {
+				currencies.push(frm.doc.currency);
+			}
+
 			return {
 				filters: {
 					"root_type": "Asset",
 					"is_group": 0,
 					"company": frm.doc.company,
-					"account_currency": ["in", [frm.doc.currency, company_currency]],
+					"account_currency": ["in", currencies],
 				}
 			};
 		});
@@ -181,21 +186,23 @@
 	},
 
 	currency: function(frm) {
-		var from_currency = frm.doc.currency;
-		var company_currency;
-		if (!frm.doc.company) {
-			company_currency = erpnext.get_currency(frappe.defaults.get_default("Company"));
-		} else {
-			company_currency = erpnext.get_currency(frm.doc.company);
+		if (frm.doc.currency) {
+			var from_currency = frm.doc.currency;
+			var company_currency;
+			if (!frm.doc.company) {
+				company_currency = erpnext.get_currency(frappe.defaults.get_default("Company"));
+			} else {
+				company_currency = erpnext.get_currency(frm.doc.company);
+			}
+			if (from_currency != company_currency) {
+				frm.events.set_exchange_rate(frm, from_currency, company_currency);
+			} else {
+				frm.set_value("exchange_rate", 1.0);
+				frm.set_df_property('exchange_rate', 'hidden', 1);
+				frm.set_df_property("exchange_rate", "description", "" );
+			}
+			frm.refresh_fields();
 		}
-		if (from_currency != company_currency) {
-			frm.events.set_exchange_rate(frm, from_currency, company_currency);
-		} else {
-			frm.set_value("exchange_rate", 1.0);
-			frm.set_df_property('exchange_rate', 'hidden', 1);
-			frm.set_df_property("exchange_rate", "description", "" );
-		}
-		frm.refresh_fields();
 	},
 
 	set_exchange_rate: function(frm, from_currency, company_currency) {
diff --git a/erpnext/manufacturing/doctype/job_card/job_card_calendar.js b/erpnext/manufacturing/doctype/job_card/job_card_calendar.js
index cf07698..f4877fd 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card_calendar.js
+++ b/erpnext/manufacturing/doctype/job_card/job_card_calendar.js
@@ -8,7 +8,17 @@
 		"allDay": "allDay",
 		"progress": "progress"
 	},
-	gantt: true,
+	gantt: {
+		field_map: {
+			"start": "started_time",
+			"end": "started_time",
+			"id": "name",
+			"title": "subject",
+			"color": "color",
+			"allDay": "allDay",
+			"progress": "progress"
+		}
+	},
 	filters: [
 		{
 			"fieldtype": "Link",
diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py
index e539279..2bf3fbf 100644
--- a/erpnext/manufacturing/doctype/work_order/test_work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py
@@ -491,6 +491,39 @@
 		work_order1.save()
 		self.assertEqual(work_order1.operations[0].time_in_mins, 40.0)
 
+	def test_partial_material_consumption(self):
+		frappe.db.set_value("Manufacturing Settings", None, "material_consumption", 1)
+		wo_order = make_wo_order_test_record(planned_start_date=now(), qty=4)
+
+		ste_cancel_list = []
+		ste1 = test_stock_entry.make_stock_entry(item_code="_Test Item",
+			target="_Test Warehouse - _TC", qty=20, basic_rate=5000.0)
+		ste2 = test_stock_entry.make_stock_entry(item_code="_Test Item Home Desktop 100",
+			target="_Test Warehouse - _TC", qty=20, basic_rate=1000.0)
+
+		ste_cancel_list.extend([ste1, ste2])
+
+		s = frappe.get_doc(make_stock_entry(wo_order.name, "Material Transfer for Manufacture", 4))
+		s.submit()
+		ste_cancel_list.append(s)
+
+		ste1 = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 2))
+		ste1.submit()
+		ste_cancel_list.append(ste1)
+
+		print(wo_order.name)
+		ste3 = frappe.get_doc(make_stock_entry(wo_order.name, "Material Consumption for Manufacture", 2))
+		self.assertEquals(ste3.fg_completed_qty, 2)
+
+		expected_qty = {"_Test Item": 2, "_Test Item Home Desktop 100": 4}
+		for row in ste3.items:
+			self.assertEquals(row.qty, expected_qty.get(row.item_code))
+
+		for ste_doc in ste_cancel_list:
+			ste_doc.cancel()
+
+		frappe.db.set_value("Manufacturing Settings", None, "material_consumption", 0)
+
 def get_scrap_item_details(bom_no):
 	scrap_items = {}
 	for item in frappe.db.sql("""select item_code, stock_qty from `tabBOM Scrap Item`
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js
index 9ce465c..a6086fb 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.js
+++ b/erpnext/manufacturing/doctype/work_order/work_order.js
@@ -545,7 +545,8 @@
 						var tbl = frm.doc.required_items || [];
 						var tbl_lenght = tbl.length;
 						for (var i = 0, len = tbl_lenght; i < len; i++) {
-							if (flt(frm.doc.required_items[i].required_qty) > flt(frm.doc.required_items[i].consumed_qty)) {
+							let wo_item_qty = frm.doc.required_items[i].transferred_qty || frm.doc.required_items[i].required_qty;
+							if (flt(wo_item_qty) > flt(frm.doc.required_items[i].consumed_qty)) {
 								counter += 1;
 							}
 						}
diff --git a/erpnext/non_profit/doctype/member/member.py b/erpnext/non_profit/doctype/member/member.py
index 44b975e..25d6b53 100644
--- a/erpnext/non_profit/doctype/member/member.py
+++ b/erpnext/non_profit/doctype/member/member.py
@@ -59,7 +59,7 @@
 			frappe.msgprint(_("A customer is already linked to this Member"))
 		cust = create_customer(frappe._dict({
 			'fullname': self.member_name,
-			'email': self.email_id or self.user,
+			'email': self.email_id or self.email,
 			'phone': None
 		}))
 
@@ -177,4 +177,4 @@
 			mobile=mobile
 		))
 
-		return member.name
\ No newline at end of file
+		return member.name
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 86ac613..9e33014 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -450,7 +450,6 @@
 erpnext.patches.v9_0.add_user_to_child_table_in_pos_profile
 erpnext.patches.v9_0.set_schedule_date_for_material_request_and_purchase_order
 erpnext.patches.v9_0.student_admission_childtable_migrate
-erpnext.patches.v9_0.fix_subscription_next_date #2017-10-23
 erpnext.patches.v9_0.add_healthcare_domain
 erpnext.patches.v9_0.set_variant_item_description
 erpnext.patches.v9_0.set_uoms_in_variant_field
diff --git a/erpnext/patches/v13_0/update_old_loans.py b/erpnext/patches/v13_0/update_old_loans.py
index 7723942..561e967 100644
--- a/erpnext/patches/v13_0/update_old_loans.py
+++ b/erpnext/patches/v13_0/update_old_loans.py
@@ -5,6 +5,8 @@
 from erpnext.accounts.doctype.account.test_account import create_account
 from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans
 from erpnext.loan_management.doctype.loan.loan import make_repayment_entry
+from erpnext.loan_management.doctype.loan_repayment.loan_repayment import get_accrued_interest_entries
+from frappe.model.naming import make_autoname
 
 def execute():
 
@@ -18,15 +20,29 @@
 	frappe.reload_doc('loan_management', 'doctype', 'loan_repayment_detail')
 	frappe.reload_doc('loan_management', 'doctype', 'loan_interest_accrual')
 	frappe.reload_doc('accounts', 'doctype', 'gl_entry')
+	frappe.reload_doc('accounts', 'doctype', 'journal_entry_account')
 
 	updated_loan_types = []
+	loans_to_close = []
+
+	# Update old loan status as closed
+	if frappe.db.has_column('Repayment Schedule', 'paid'):
+		loans_list = frappe.db.sql("""SELECT distinct parent from `tabRepayment Schedule`
+			where paid = 0 and docstatus = 1""", as_dict=1)
+
+		loans_to_close = [d.parent for d in loans_list]
+
+	if loans_to_close:
+		frappe.db.sql("UPDATE `tabLoan` set status = 'Closed' where name not in (%s)" % (', '.join(['%s'] * len(loans_to_close))), tuple(loans_to_close))
 
 	loans = frappe.get_all('Loan', fields=['name', 'loan_type', 'company', 'status', 'mode_of_payment',
-		'applicant_type', 'applicant', 'loan_account', 'payment_account', 'interest_income_account'])
+		'applicant_type', 'applicant', 'loan_account', 'payment_account', 'interest_income_account'],
+		filters={'docstatus': 1, 'status': ('!=', 'Closed')})
 
 	for loan in loans:
 		# Update details in Loan Types and Loan
 		loan_type_company = frappe.db.get_value('Loan Type', loan.loan_type, 'company')
+		loan_type = loan.loan_type
 
 		group_income_account = frappe.get_value('Account', {'company': loan.company,
 			'is_group': 1, 'root_type': 'Income', 'account_name': _('Indirect Income')})
@@ -38,7 +54,26 @@
 		penalty_account = create_account(company=loan.company, account_type='Income Account',
 			account_name='Penalty Account', parent_account=group_income_account)
 
-		if not loan_type_company:
+		# Same loan type used for multiple companies
+		if loan_type_company and loan_type_company != loan.company:
+			# get loan type for appropriate company
+			loan_type_name = frappe.get_value('Loan Type', {'company': loan.company,
+				'mode_of_payment': loan.mode_of_payment, 'loan_account': loan.loan_account,
+				'payment_account': loan.payment_account, 'interest_income_account': loan.interest_income_account,
+				'penalty_income_account': loan.penalty_income_account}, 'name')
+
+			if not loan_type_name:
+				loan_type_name = create_loan_type(loan, loan_type_name, penalty_account)
+
+			# update loan type in loan
+			frappe.db.sql("UPDATE `tabLoan` set loan_type = %s where name = %s", (loan_type_name,
+				loan.name))
+
+			loan_type = loan_type_name
+			if loan_type_name not in updated_loan_types:
+				updated_loan_types.append(loan_type_name)
+
+		elif not loan_type_company:
 			loan_type_doc = frappe.get_doc('Loan Type', loan.loan_type)
 			loan_type_doc.is_term_loan = 1
 			loan_type_doc.company = loan.company
@@ -49,8 +84,9 @@
 			loan_type_doc.penalty_income_account = penalty_account
 			loan_type_doc.submit()
 			updated_loan_types.append(loan.loan_type)
+			loan_type = loan.loan_type
 
-		if loan.loan_type in updated_loan_types:
+		if loan_type in updated_loan_types:
 			if loan.status == 'Fully Disbursed':
 				status = 'Disbursed'
 			elif loan.status == 'Repaid/Closed':
@@ -64,25 +100,48 @@
 				'status': status
 			})
 
-			process_loan_interest_accrual_for_term_loans(posting_date=nowdate(), loan_type=loan.loan_type,
+			process_loan_interest_accrual_for_term_loans(posting_date=nowdate(), loan_type=loan_type,
 				loan=loan.name)
 
-			payments = frappe.db.sql(''' SELECT j.name, a.debit, a.debit_in_account_currency, j.posting_date
-				FROM `tabJournal Entry` j, `tabJournal Entry Account` a
-				WHERE a.parent = j.name and a.reference_type='Loan' and a.reference_name = %s
-				and account = %s
-			''', (loan.name, loan.loan_account), as_dict=1)
 
-			for payment in payments:
-				repayment_entry = make_repayment_entry(loan.name, loan.loan_applicant_type, loan.applicant,
-					loan.loan_type, loan.company)
+			if frappe.db.has_column('Repayment Schedule', 'paid'):
+				total_principal, total_interest = frappe.db.get_value('Repayment Schedule', {'paid': 1, 'parent': loan.name},
+					['sum(principal_amount) as total_principal', 'sum(interest_amount) as total_interest'])
 
-				repayment_entry.amount_paid = payment.debit_in_account_currency
-				repayment_entry.posting_date = payment.posting_date
-				repayment_entry.save()
-				repayment_entry.submit()
+				accrued_entries = get_accrued_interest_entries(loan.name)
+				for entry in accrued_entries:
+					interest_paid = 0
+					principal_paid = 0
 
-				jv = frappe.get_doc('Journal Entry', payment.name)
-				jv.flags.ignore_links = True
-				jv.cancel()
+					if total_interest > entry.interest_amount:
+						interest_paid = entry.interest_amount
+					else:
+						interest_paid = total_interest
 
+					if total_principal > entry.payable_principal_amount:
+						principal_paid = entry.payable_principal_amount
+					else:
+						principal_paid = total_principal
+
+					frappe.db.sql(""" UPDATE `tabLoan Interest Accrual`
+						SET paid_principal_amount = `paid_principal_amount` + %s,
+							paid_interest_amount = `paid_interest_amount` + %s
+						WHERE name = %s""",
+						(principal_paid, interest_paid, entry.name))
+
+					total_principal -= principal_paid
+					total_interest -= interest_paid
+
+def create_loan_type(loan, loan_type_name, penalty_account):
+	loan_type_doc = frappe.new_doc('Loan Type')
+	loan_type_doc.loan_name = make_autoname("Loan Type-.####")
+	loan_type_doc.is_term_loan = 1
+	loan_type_doc.company = loan.company
+	loan_type_doc.mode_of_payment = loan.mode_of_payment
+	loan_type_doc.payment_account = loan.payment_account
+	loan_type_doc.loan_account = loan.loan_account
+	loan_type_doc.interest_income_account = loan.interest_income_account
+	loan_type_doc.penalty_income_account = penalty_account
+	loan_type_doc.submit()
+
+	return loan_type_doc.name
diff --git a/erpnext/patches/v9_0/fix_subscription_next_date.py b/erpnext/patches/v9_0/fix_subscription_next_date.py
deleted file mode 100644
index 4595c8d..0000000
--- a/erpnext/patches/v9_0/fix_subscription_next_date.py
+++ /dev/null
@@ -1,48 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import getdate
-from frappe.automation.doctype.auto_repeat.auto_repeat import get_next_schedule_date
-
-def execute():
-	frappe.reload_doc('accounts', 'doctype', 'subscription')
-	fields = ["name", "reference_doctype", "reference_document",
-			"start_date", "frequency", "repeat_on_day"]
-
-	for d in fields:
-		if not frappe.db.has_column('Subscription', d):
-			return
-
-	doctypes = ('Purchase Order', 'Sales Order', 'Purchase Invoice', 'Sales Invoice')
-	for data in frappe.get_all('Subscription',
-		fields = fields,
-		filters = {'reference_doctype': ('in', doctypes), 'docstatus': 1}):
-
-		recurring_id = frappe.db.get_value(data.reference_doctype, data.reference_document, "recurring_id")
-		if recurring_id:
-			frappe.db.sql("update `tab{0}` set subscription=%s where recurring_id=%s"
-				.format(data.reference_doctype), (data.name, recurring_id))
-
-		date_field = 'transaction_date'
-		if data.reference_doctype in ['Sales Invoice', 'Purchase Invoice']:
-			date_field = 'posting_date'
-
-		start_date = frappe.db.get_value(data.reference_doctype, data.reference_document, date_field)
-
-		if start_date and getdate(start_date) != getdate(data.start_date):
-			last_ref_date = frappe.db.sql("""
-				select {0}
-				from `tab{1}`
-				where subscription=%s and docstatus < 2
-				order by creation desc
-				limit 1
-			""".format(date_field, data.reference_doctype), data.name)[0][0]
-
-			next_schedule_date = get_next_schedule_date(last_ref_date, data.frequency, data.repeat_on_day)
-
-			frappe.db.set_value("Subscription", data.name, {
-				"start_date": start_date,
-				"next_schedule_date": next_schedule_date
-			}, None)
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/additional_salary/additional_salary.js b/erpnext/payroll/doctype/additional_salary/additional_salary.js
index 0784de9..7737e6c 100644
--- a/erpnext/payroll/doctype/additional_salary/additional_salary.js
+++ b/erpnext/payroll/doctype/additional_salary/additional_salary.js
@@ -12,14 +12,6 @@
 				}
 			};
 		});
-
-		if (!frm.doc.currency) return;
-		frm.set_query("salary_component", function() {
-			return {
-				query: "erpnext.payroll.doctype.salary_structure.salary_structure.get_earning_deduction_components",
-				filters: {currency: frm.doc.currency, company: frm.doc.company}
-			};
-		});
 	},
 
 	employee: function(frm) {
diff --git a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.json b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.json
index 9a5a463..4c45580 100644
--- a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.json
+++ b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.json
@@ -23,6 +23,7 @@
   "employee_benefits",
   "totals",
   "total_amount",
+  "column_break",
   "pro_rata_dispensed_amount"
  ],
  "fields": [
@@ -139,11 +140,15 @@
    "label": "Company",
    "options": "Company",
    "reqd": 1
+  },
+  {
+   "fieldname": "column_break",
+   "fieldtype": "Column Break"
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-11-25 11:49:05.095101",
+ "modified": "2020-12-14 15:52:08.566418",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Employee Benefit Application",
diff --git a/erpnext/payroll/doctype/employee_incentive/employee_incentive.js b/erpnext/payroll/doctype/employee_incentive/employee_incentive.js
index 85d1c54..182ce0f 100644
--- a/erpnext/payroll/doctype/employee_incentive/employee_incentive.js
+++ b/erpnext/payroll/doctype/employee_incentive/employee_incentive.js
@@ -11,11 +11,11 @@
 			};
 		});
 
-		if (!frm.doc.currency) return;
+		if (!frm.doc.company) return;
 		frm.set_query("salary_component", function() {
 			return {
 				query: "erpnext.payroll.doctype.salary_structure.salary_structure.get_earning_deduction_components",
-				filters: {type: "earning", currency: frm.doc.currency, company: frm.doc.company}
+				filters: {type: "earning", company: frm.doc.company}
 			};
 		});
 
diff --git a/erpnext/payroll/doctype/retention_bonus/retention_bonus.js b/erpnext/payroll/doctype/retention_bonus/retention_bonus.js
index 6fe8cca..f8bb40a 100644
--- a/erpnext/payroll/doctype/retention_bonus/retention_bonus.js
+++ b/erpnext/payroll/doctype/retention_bonus/retention_bonus.js
@@ -4,9 +4,13 @@
 frappe.ui.form.on('Retention Bonus', {
 	setup: function(frm) {
 		frm.set_query("employee", function() {
+			if (!frm.doc.company) {
+				frappe.msgprint(__("Please Select Company First"));
+			}
 			return {
 				filters: {
-					"status": "Active"
+					"status": "Active",
+					"company": frm.doc.company
 				}
 			};
 		});
diff --git a/erpnext/payroll/doctype/salary_structure/salary_structure.js b/erpnext/payroll/doctype/salary_structure/salary_structure.js
index 7daae49..ba824c5 100755
--- a/erpnext/payroll/doctype/salary_structure/salary_structure.js
+++ b/erpnext/payroll/doctype/salary_structure/salary_structure.js
@@ -55,17 +55,17 @@
 	},
 
 	set_earning_deduction_component: function(frm) {
-		if(!frm.doc.currency && !frm.doc.company) return;
+		if(!frm.doc.company) return;
 		frm.set_query("salary_component", "earnings", function() {
 			return {
 				query : "erpnext.payroll.doctype.salary_structure.salary_structure.get_earning_deduction_components",
-				filters: {type: "earning", currency: frm.doc.currency, company: frm.doc.company}
+				filters: {type: "earning", company: frm.doc.company}
 			};
 		});
 		frm.set_query("salary_component", "deductions", function() {
 			return {
 				query : "erpnext.payroll.doctype.salary_structure.salary_structure.get_earning_deduction_components",
-				filters: {type: "deduction", currency: frm.doc.currency, company: frm.doc.company}
+				filters: {type: "deduction", company: frm.doc.company}
 			};
 		});
 	},
@@ -74,7 +74,6 @@
 	currency: function(frm) {
 		calculate_totals(frm.doc);
 		frm.trigger("set_dynamic_labels")
-		frm.trigger('set_earning_deduction_component');
 		frm.refresh()
 	},
 
diff --git a/erpnext/payroll/doctype/salary_structure/salary_structure.py b/erpnext/payroll/doctype/salary_structure/salary_structure.py
index 877e41d..77914bb 100644
--- a/erpnext/payroll/doctype/salary_structure/salary_structure.py
+++ b/erpnext/payroll/doctype/salary_structure/salary_structure.py
@@ -210,7 +210,7 @@
 @frappe.whitelist()
 @frappe.validate_and_sanitize_search_inputs
 def get_earning_deduction_components(doctype, txt, searchfield, start, page_len, filters):
-	if len(filters) < 3:
+	if len(filters) < 2:
 		return {}
 
 	return frappe.db.sql("""
diff --git a/erpnext/public/js/telephony.js b/erpnext/public/js/telephony.js
index bd7f890..f9caade 100644
--- a/erpnext/public/js/telephony.js
+++ b/erpnext/public/js/telephony.js
@@ -20,4 +20,4 @@
 				});
 		}
 	}
-});
\ No newline at end of file
+});
diff --git a/erpnext/regional/india/taxes.js b/erpnext/regional/india/taxes.js
index b70b2ec..87baece 100644
--- a/erpnext/regional/india/taxes.js
+++ b/erpnext/regional/india/taxes.js
@@ -12,6 +12,9 @@
 		tax_category: function(frm) {
 			frm.trigger('get_tax_template');
 		},
+		customer_address: function(frm) {
+			frm.trigger('get_tax_template');
+		},
 		get_tax_template: function(frm) {
 			if (!frm.doc.company) return;
 
diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py
index 8379297..ad3de5f 100644
--- a/erpnext/regional/report/gstr_1/gstr_1.py
+++ b/erpnext/regional/report/gstr_1/gstr_1.py
@@ -151,6 +151,7 @@
 				{select_columns}
 			from `tab{doctype}`
 			where docstatus = 1 {where_conditions}
+			and is_opening = 'No'
 			order by posting_date desc
 			""".format(select_columns=self.select_columns, doctype=self.doctype,
 				where_conditions=conditions), self.filters, as_dict=1)
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index 04d85e5..9388e09 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -14,7 +14,6 @@
 from frappe.desk.notifications import clear_doctype_notifications
 from frappe.contacts.doctype.address.address import get_company_address
 from erpnext.controllers.selling_controller import SellingController
-from frappe.automation.doctype.auto_repeat.auto_repeat import get_next_schedule_date
 from erpnext.selling.doctype.customer.customer import check_credit_limit
 from erpnext.stock.doctype.item.item import get_item_defaults
 from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
@@ -418,8 +417,7 @@
 	def on_recurring(self, reference_doc, auto_repeat_doc):
 
 		def _get_delivery_date(ref_doc_delivery_date, red_doc_transaction_date, transaction_date):
-			delivery_date = get_next_schedule_date(ref_doc_delivery_date,
-				auto_repeat_doc.frequency, auto_repeat_doc.start_date, cint(auto_repeat_doc.repeat_on_day))
+			delivery_date = auto_repeat_doc.get_next_schedule_date(schedule_date=ref_doc_delivery_date)
 
 			if delivery_date <= transaction_date:
 				delivery_date_diff = frappe.utils.date_diff(ref_doc_delivery_date, red_doc_transaction_date)
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 9121758..27fcbb7 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -841,6 +841,10 @@
 		}
 	},
 
+	fg_completed_qty: function() {
+		this.get_items();
+	},
+
 	get_items: function() {
 		var me = this;
 		if(!this.frm.doc.fg_completed_qty || !this.frm.doc.bom_no)
@@ -850,6 +854,7 @@
 			// if work order / bom is mentioned, get items
 			return this.frm.call({
 				doc: me.frm.doc,
+				freeze: true,
 				method: "get_items",
 				callback: function(r) {
 					if(!r.exc) refresh_field("items");
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index e3159b9..32d7e6e 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -120,6 +120,7 @@
 		self.update_transferred_qty()
 		self.update_quality_inspection()
 		self.delete_auto_created_batches()
+		self.delete_linked_stock_entry()
 
 		if self.purpose == 'Material Transfer' and self.add_to_transit:
 			self.set_material_request_transfer_status('Not Started')
@@ -152,6 +153,12 @@
 			frappe.throw(_("For job card {0}, you can only make the 'Material Transfer for Manufacture' type stock entry")
 				.format(self.job_card))
 
+	def delete_linked_stock_entry(self):
+		if self.purpose == "Send to Warehouse":
+			for d in frappe.get_all("Stock Entry", filters={"docstatus": 0,
+				"outgoing_stock_entry": self.name, "purpose": "Receive at Warehouse"}):
+				frappe.delete_doc("Stock Entry", d.name)
+
 	def set_transfer_qty(self):
 		for item in self.get("items"):
 			if not flt(item.qty):
@@ -1033,26 +1040,22 @@
 		wo = frappe.get_doc("Work Order", self.work_order)
 		wo_items = frappe.get_all('Work Order Item',
 			filters={'parent': self.work_order},
-			fields=["item_code", "required_qty", "consumed_qty"]
+			fields=["item_code", "required_qty", "consumed_qty", "transferred_qty"]
 			)
 
+		work_order_qty = wo.material_transferred_for_manufacturing or wo.qty
 		for item in wo_items:
-			qty = item.required_qty
-
 			item_account_details = get_item_defaults(item.item_code, self.company)
 			# Take into account consumption if there are any.
-			if self.purpose == 'Manufacture':
-				req_qty_each = flt(item.required_qty / wo.qty)
-				if (flt(item.consumed_qty) != 0):
-					remaining_qty = flt(item.consumed_qty) - (flt(wo.produced_qty) * req_qty_each)
-					exhaust_qty = req_qty_each * wo.produced_qty
-					if remaining_qty > exhaust_qty :
-						if (remaining_qty/(req_qty_each * flt(self.fg_completed_qty))) >= 1:
-							qty =0
-						else:
-							qty = (req_qty_each * flt(self.fg_completed_qty)) - remaining_qty
-				else:
-					qty = req_qty_each * flt(self.fg_completed_qty)
+
+			wo_item_qty = item.transferred_qty or item.required_qty
+
+			req_qty_each = (
+				(flt(wo_item_qty) - flt(item.consumed_qty)) /
+					(flt(work_order_qty) - flt(wo.produced_qty))
+			)
+
+			qty = req_qty_each * flt(self.fg_completed_qty)
 
 			if qty > 0:
 				self.add_to_stock_entry_detail({
@@ -1134,13 +1137,15 @@
 					else:
 						qty = req_qty_each * flt(self.fg_completed_qty)
 
-
 			elif backflushed_materials.get(item.item_code):
 				for d in backflushed_materials.get(item.item_code):
 					if d.get(item.warehouse):
 						if (qty > req_qty):
 							qty = (qty/trans_qty) * flt(self.fg_completed_qty)
 
+						if consumed_qty:
+							qty -= consumed_qty
+
 			if cint(frappe.get_cached_value('UOM', item.stock_uom, 'must_be_whole_number')):
 				qty = frappe.utils.ceil(qty)
 
diff --git a/erpnext/telephony/doctype/voice_call_settings/__init__.py b/erpnext/telephony/doctype/voice_call_settings/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/telephony/doctype/voice_call_settings/__init__.py
diff --git a/erpnext/telephony/doctype/voice_call_settings/test_voice_call_settings.py b/erpnext/telephony/doctype/voice_call_settings/test_voice_call_settings.py
new file mode 100644
index 0000000..85d6add
--- /dev/null
+++ b/erpnext/telephony/doctype/voice_call_settings/test_voice_call_settings.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestVoiceCallSettings(unittest.TestCase):
+	pass
diff --git a/erpnext/telephony/doctype/voice_call_settings/voice_call_settings.js b/erpnext/telephony/doctype/voice_call_settings/voice_call_settings.js
new file mode 100644
index 0000000..4a61b61
--- /dev/null
+++ b/erpnext/telephony/doctype/voice_call_settings/voice_call_settings.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Voice Call Settings', {
+	// refresh: function(frm) {
+
+	// }
+});
diff --git a/erpnext/telephony/doctype/voice_call_settings/voice_call_settings.json b/erpnext/telephony/doctype/voice_call_settings/voice_call_settings.json
new file mode 100644
index 0000000..25e55a2
--- /dev/null
+++ b/erpnext/telephony/doctype/voice_call_settings/voice_call_settings.json
@@ -0,0 +1,124 @@
+{
+ "actions": [],
+ "autoname": "field:user",
+ "creation": "2020-12-08 16:52:40.590146",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "user",
+  "call_receiving_device",
+  "column_break_3",
+  "greeting_message",
+  "agent_busy_message",
+  "agent_unavailable_message"
+ ],
+ "fields": [
+  {
+   "fieldname": "user",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "User",
+   "options": "User",
+   "permlevel": 1,
+   "reqd": 1,
+   "unique": 1
+  },
+  {
+   "fieldname": "greeting_message",
+   "fieldtype": "Data",
+   "label": "Greeting Message"
+  },
+  {
+   "fieldname": "agent_busy_message",
+   "fieldtype": "Data",
+   "label": "Agent Busy Message"
+  },
+  {
+   "fieldname": "agent_unavailable_message",
+   "fieldtype": "Data",
+   "label": "Agent Unavailable Message"
+  },
+  {
+   "default": "Computer",
+   "fieldname": "call_receiving_device",
+   "fieldtype": "Select",
+   "label": "Call Receiving Device",
+   "options": "Computer\nPhone"
+  },
+  {
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break"
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "links": [],
+ "modified": "2020-12-14 18:49:34.600194",
+ "modified_by": "Administrator",
+ "module": "Telephony",
+ "name": "Voice Call Settings",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "All",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "permlevel": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "permlevel": 2,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "email": 1,
+   "export": 1,
+   "permlevel": 2,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "All",
+   "share": 1
+  }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/telephony/doctype/voice_call_settings/voice_call_settings.py b/erpnext/telephony/doctype/voice_call_settings/voice_call_settings.py
new file mode 100644
index 0000000..ad3bbf1
--- /dev/null
+++ b/erpnext/telephony/doctype/voice_call_settings/voice_call_settings.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, 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 VoiceCallSettings(Document):
+	pass