Merge pull request #26506 from 18alantom/bp-fix-ig-portal-field-filter

fix: check if field_filters is None
diff --git a/.github/helper/semgrep_rules/frappe_correctness.yml b/.github/helper/semgrep_rules/frappe_correctness.yml
index faab334..d9603e8 100644
--- a/.github/helper/semgrep_rules/frappe_correctness.yml
+++ b/.github/helper/semgrep_rules/frappe_correctness.yml
@@ -98,8 +98,6 @@
   languages: [python]
   severity: WARNING
   paths:
-      exclude:
-        - test_*.py
       include:
         - "*/**/doctype/*"
 
diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml
index 389524e..e27b406 100644
--- a/.github/workflows/semgrep.yml
+++ b/.github/workflows/semgrep.yml
@@ -1,34 +1,18 @@
 name: Semgrep
 
 on:
-  pull_request:
-    branches:
-      - develop
-      - version-13-hotfix
-      - version-13-pre-release
+  pull_request: { }
+
 jobs:
   semgrep:
     name: Frappe Linter
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v2
-    - name: Setup python3
-      uses: actions/setup-python@v2
-      with:
-        python-version: 3.8
-
-    - name: Setup semgrep
-      run: |
-        python -m pip install -q semgrep
-        git fetch origin $GITHUB_BASE_REF:$GITHUB_BASE_REF -q
-
-    - name: Semgrep errors
-      run: |
-        files=$(git diff --name-only --diff-filter=d $GITHUB_BASE_REF)
-        [[ -d .github/helper/semgrep_rules ]] && semgrep --severity ERROR --config=.github/helper/semgrep_rules --quiet --error $files
-        semgrep --config="r/python.lang.correctness" --quiet --error $files
-
-    - name: Semgrep warnings
-      run: |
-        files=$(git diff --name-only --diff-filter=d $GITHUB_BASE_REF)
-        [[ -d .github/helper/semgrep_rules ]] && semgrep --severity WARNING --severity INFO --config=.github/helper/semgrep_rules --quiet $files
+      - uses: actions/checkout@v2
+      - uses: returntocorp/semgrep-action@v1
+        env:
+            SEMGREP_TIMEOUT: 120
+        with:
+            config: >-
+              r/python.lang.correctness
+              .github/helper/semgrep_rules
diff --git a/CODEOWNERS b/CODEOWNERS
index 7cf65a7..219b6bb 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -3,16 +3,33 @@
 # These owners will be the default owners for everything in
 # the repo. Unless a later match takes precedence,
 
-manufacturing/          @rohitwaghchaure @marination
-accounts/               @deepeshgarg007 @nextchamp-saqib
-loan_management/        @deepeshgarg007 @rohitwaghchaure
-pos*                    @nextchamp-saqib @rohitwaghchaure
-assets/                 @nextchamp-saqib @deepeshgarg007
-stock/                  @marination @rohitwaghchaure
-buying/                 @marination @deepeshgarg007
-hr/                     @Anurag810 @rohitwaghchaure
-projects/               @hrwX @nextchamp-saqib
-support/                @hrwX @marination
-healthcare/             @ruchamahabal @marination
-erpnext_integrations/   @Mangesh-Khairnar @nextchamp-saqib
-requirements.txt        @gavindsouza
+erpnext/accounts/               @nextchamp-saqib @deepeshgarg007
+erpnext/assets/                 @nextchamp-saqib @deepeshgarg007
+erpnext/erpnext_integrations/   @nextchamp-saqib
+erpnext/loan_management/        @nextchamp-saqib @deepeshgarg007
+erpnext/regional                @nextchamp-saqib @deepeshgarg007
+erpnext/selling                 @nextchamp-saqib @deepeshgarg007
+erpnext/support/                @nextchamp-saqib @deepeshgarg007
+pos*                            @nextchamp-saqib
+
+erpnext/buying/                 @marination @rohitwaghchaure @ankush
+erpnext/e_commerce/             @marination
+erpnext/maintenance/            @marination @rohitwaghchaure
+erpnext/manufacturing/          @marination @rohitwaghchaure @ankush
+erpnext/portal/                 @marination
+erpnext/quality_management/     @marination @rohitwaghchaure
+erpnext/shopping_cart/          @marination
+erpnext/stock/                  @marination @rohitwaghchaure @ankush
+
+erpnext/crm/                    @ruchamahabal
+erpnext/education/              @ruchamahabal
+erpnext/healthcare/             @ruchamahabal
+erpnext/hr/                     @ruchamahabal
+erpnext/non_profit/             @ruchamahabal
+erpnext/payroll                 @ruchamahabal
+erpnext/projects/               @ruchamahabal
+
+erpnext/controllers             @deepeshgarg007 @nextchamp-saqib @rohitwaghchaure @marination
+
+.github/                        @surajshetty3416 @ankush
+requirements.txt                @gavindsouza
diff --git a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
index 4fd8413..8456b49 100644
--- a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
+++ b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
@@ -391,5 +391,5 @@
 	})
 
 	company.save()
-	install_country_fixtures(company.name)
+	install_country_fixtures(company.name, company.country)
 	company.create_default_tax_template()
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json
index 51f18a5..6f362c1 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.json
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json
@@ -667,6 +667,7 @@
   {
    "fieldname": "base_paid_amount_after_tax",
    "fieldtype": "Currency",
+   "hidden": 1,
    "label": "Paid Amount After Tax (Company Currency)",
    "options": "Company:company:default_currency",
    "read_only": 1
@@ -693,21 +694,25 @@
    "depends_on": "eval:doc.received_amount && doc.payment_type != 'Internal Transfer'",
    "fieldname": "received_amount_after_tax",
    "fieldtype": "Currency",
+   "hidden": 1,
    "label": "Received Amount After Tax",
-   "options": "paid_to_account_currency"
+   "options": "paid_to_account_currency",
+   "read_only": 1
   },
   {
    "depends_on": "doc.received_amount",
    "fieldname": "base_received_amount_after_tax",
    "fieldtype": "Currency",
+   "hidden": 1,
    "label": "Received Amount After Tax (Company Currency)",
-   "options": "Company:company:default_currency"
+   "options": "Company:company:default_currency",
+   "read_only": 1
   }
  ],
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2021-06-22 20:37:06.154206",
+ "modified": "2021-07-09 08:58:15.008761",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Payment Entry",
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index ff00fde..46904f7 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -411,9 +411,15 @@
 		if not self.advance_tax_account:
 			frappe.throw(_("Advance TDS account is mandatory for advance TDS deduction"))
 
-		reference_doclist = []
 		net_total = self.paid_amount
-		included_in_paid_amount = 0
+
+		for reference in self.get("references"):
+			net_total_for_tds = 0
+			if reference.reference_doctype == 'Purchase Order':
+				net_total_for_tds += flt(frappe.db.get_value('Purchase Order', reference.reference_name, 'net_total'))
+		
+			if net_total_for_tds:
+				net_total = net_total_for_tds
 
 		# Adding args as purchase invoice to get TDS amount
 		args = frappe._dict({
@@ -430,7 +436,7 @@
 			return
 
 		tax_withholding_details.update({
-			'included_in_paid_amount': included_in_paid_amount,
+			'add_deduct_tax': 'Add',
 			'cost_center': self.cost_center or erpnext.get_default_cost_center(self.company)
 		})
 
@@ -519,16 +525,19 @@
 		self.unallocated_amount = 0
 		if self.party:
 			total_deductions = sum(flt(d.amount) for d in self.get("deductions"))
+			included_taxes = self.get_included_taxes()
 			if self.payment_type == "Receive" \
-				and self.base_total_allocated_amount < self.base_received_amount_after_tax + total_deductions \
-				and self.total_allocated_amount < self.paid_amount_after_tax + (total_deductions / self.source_exchange_rate):
-				self.unallocated_amount = (self.received_amount_after_tax + total_deductions -
+				and self.base_total_allocated_amount < self.base_received_amount + total_deductions \
+				and self.total_allocated_amount < self.paid_amount + (total_deductions / self.source_exchange_rate):
+				self.unallocated_amount = (self.received_amount + total_deductions -
 					self.base_total_allocated_amount) / self.source_exchange_rate
+				self.unallocated_amount -= included_taxes
 			elif self.payment_type == "Pay" \
-				and self.base_total_allocated_amount < (self.base_paid_amount_after_tax - total_deductions) \
-				and self.total_allocated_amount < self.received_amount_after_tax + (total_deductions / self.target_exchange_rate):
-				self.unallocated_amount = (self.base_paid_amount_after_tax - (total_deductions +
+				and self.base_total_allocated_amount < (self.base_paid_amount - total_deductions) \
+				and self.total_allocated_amount < self.received_amount + (total_deductions / self.target_exchange_rate):
+				self.unallocated_amount = (self.base_paid_amount - (total_deductions +
 					self.base_total_allocated_amount)) / self.target_exchange_rate
+				self.unallocated_amount -= included_taxes
 
 	def set_difference_amount(self):
 		base_unallocated_amount = flt(self.unallocated_amount) * (flt(self.source_exchange_rate)
@@ -537,17 +546,29 @@
 		base_party_amount = flt(self.base_total_allocated_amount) + flt(base_unallocated_amount)
 
 		if self.payment_type == "Receive":
-			self.difference_amount = base_party_amount - self.base_received_amount_after_tax
+			self.difference_amount = base_party_amount - self.base_received_amount
 		elif self.payment_type == "Pay":
-			self.difference_amount = self.base_paid_amount_after_tax - base_party_amount
+			self.difference_amount = self.base_paid_amount - base_party_amount
 		else:
-			self.difference_amount = self.base_paid_amount_after_tax - flt(self.base_received_amount_after_tax)
+			self.difference_amount = self.base_paid_amount - flt(self.base_received_amount)
 
 		total_deductions = sum(flt(d.amount) for d in self.get("deductions"))
+		included_taxes = self.get_included_taxes()
 
-		self.difference_amount = flt(self.difference_amount - total_deductions,
+		self.difference_amount = flt(self.difference_amount - total_deductions - included_taxes,
 			self.precision("difference_amount"))
 
+	def get_included_taxes(self):
+		included_taxes = 0
+		for tax in self.get('taxes'):
+			if tax.included_in_paid_amount:
+				if tax.add_deduct_tax == 'Add':
+					included_taxes += tax.base_tax_amount
+				else:
+					included_taxes -= tax.base_tax_amount
+
+		return included_taxes
+
 	# Paid amount is auto allocated in the reference document by default.
 	# Clear the reference document which doesn't have allocated amount on validate so that form can be loaded fast
 	def clear_unallocated_reference_document_rows(self):
@@ -690,8 +711,8 @@
 					"account": self.paid_from,
 					"account_currency": self.paid_from_account_currency,
 					"against": self.party if self.payment_type=="Pay" else self.paid_to,
-					"credit_in_account_currency": self.paid_amount_after_tax,
-					"credit": self.base_paid_amount_after_tax,
+					"credit_in_account_currency": self.paid_amount,
+					"credit": self.base_paid_amount,
 					"cost_center": self.cost_center
 				}, item=self)
 			)
@@ -701,8 +722,8 @@
 					"account": self.paid_to,
 					"account_currency": self.paid_to_account_currency,
 					"against": self.party if self.payment_type=="Receive" else self.paid_from,
-					"debit_in_account_currency": self.received_amount_after_tax,
-					"debit": self.base_received_amount_after_tax,
+					"debit_in_account_currency": self.received_amount,
+					"debit": self.base_received_amount,
 					"cost_center": self.cost_center
 				}, item=self)
 			)
@@ -715,35 +736,42 @@
 
 			if self.payment_type in ('Pay', 'Internal Transfer'):
 				dr_or_cr = "debit" if d.add_deduct_tax == "Add" else "credit"
+				against = self.party or self.paid_from
 			elif self.payment_type == 'Receive':
 				dr_or_cr = "credit" if d.add_deduct_tax == "Add" else "debit"
+				against = self.party or self.paid_to
 
 			payment_or_advance_account = self.get_party_account_for_taxes()
+			tax_amount = d.tax_amount
+			base_tax_amount = d.base_tax_amount
+
+			if self.advance_tax_account:
+				tax_amount = -1 * tax_amount
+				base_tax_amount = -1 * base_tax_amount
 
 			gl_entries.append(
 				self.get_gl_dict({
 					"account": d.account_head,
-					"against": self.party if self.payment_type=="Receive" else self.paid_from,
-					dr_or_cr: d.base_tax_amount,
-					dr_or_cr + "_in_account_currency": d.base_tax_amount
+					"against": against,
+					dr_or_cr: tax_amount,
+					dr_or_cr + "_in_account_currency": base_tax_amount
 					if account_currency==self.company_currency
 					else d.tax_amount,
 					"cost_center": d.cost_center
 				}, account_currency, item=d))
 
 			#Intentionally use -1 to get net values in party account
-			gl_entries.append(
-				self.get_gl_dict({
-					"account": payment_or_advance_account,
-					"against": self.party if self.payment_type=="Receive" else self.paid_from,
-					dr_or_cr: -1 * d.base_tax_amount,
-					dr_or_cr + "_in_account_currency": -1*d.base_tax_amount
-					if account_currency==self.company_currency
-					else d.tax_amount,
-					"cost_center": self.cost_center,
-					"party_type": self.party_type,
-					"party": self.party
-				}, account_currency, item=d))
+			if not d.included_in_paid_amount or self.advance_tax_account:
+				gl_entries.append(
+					self.get_gl_dict({
+						"account": payment_or_advance_account,
+						"against": against,
+						dr_or_cr: -1 * tax_amount,
+						dr_or_cr + "_in_account_currency": -1 * base_tax_amount
+						if account_currency==self.company_currency
+						else d.tax_amount,
+						"cost_center": self.cost_center,
+					}, account_currency, item=d))
 
 	def add_deductions_gl_entries(self, gl_entries):
 		for d in self.get("deductions"):
@@ -767,9 +795,9 @@
 		if self.advance_tax_account:
 			return self.advance_tax_account
 		elif self.payment_type == 'Receive':
-			return self.paid_from
-		elif self.payment_type in ('Pay', 'Internal Transfer'):
 			return self.paid_to
+		elif self.payment_type in ('Pay', 'Internal Transfer'):
+			return self.paid_from
 
 	def update_advance_paid(self):
 		if self.payment_type in ("Receive", "Pay") and self.party:
@@ -1648,12 +1676,6 @@
 			if dt == "Employee Advance":
 				paid_amount = received_amount * doc.get('exchange_rate', 1)
 
-	if dt == "Purchase Order" and doc.apply_tds:
-		if party_account_currency == bank.account_currency:
-			paid_amount = received_amount = doc.base_net_total
-		else:
-			paid_amount = received_amount = doc.base_net_total * doc.get('exchange_rate', 1)
-
 	return paid_amount, received_amount
 
 def apply_early_payment_discount(paid_amount, received_amount, doc):
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index a9860ed..4c313c4 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -818,11 +818,11 @@
 					account_currency = get_account_currency(tax.account_head)
 
 					if self.doctype == "Purchase Invoice":
-						dr_or_cr = "credit" if tax.add_deduct_tax == "Add" else "debit"
-						rev_dr_cr = "debit" if tax.add_deduct_tax == "Add" else "credit"
-					else:
 						dr_or_cr = "debit" if tax.add_deduct_tax == "Add" else "credit"
 						rev_dr_cr = "credit" if tax.add_deduct_tax == "Add" else "debit"
+					else:
+						dr_or_cr = "credit" if tax.add_deduct_tax == "Add" else "debit"
+						rev_dr_cr = "debit" if tax.add_deduct_tax == "Add" else "credit"
 
 					party = self.supplier if self.doctype == "Purchase Invoice" else self.customer
 					unallocated_amount = tax.tax_amount - tax.allocated_amount
diff --git a/erpnext/manufacturing/doctype/sub_operation/sub_operation.json b/erpnext/manufacturing/doctype/sub_operation/sub_operation.json
index f63d2b9..10cee32 100644
--- a/erpnext/manufacturing/doctype/sub_operation/sub_operation.json
+++ b/erpnext/manufacturing/doctype/sub_operation/sub_operation.json
@@ -19,6 +19,7 @@
    "options": "Operation"
   },
   {
+   "default": "0",
    "description": "Time in mins",
    "fieldname": "time_in_mins",
    "fieldtype": "Float",
@@ -38,7 +39,7 @@
  "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-12-07 18:09:18.005578",
+ "modified": "2021-07-15 16:39:41.635362",
  "modified_by": "Administrator",
  "module": "Manufacturing",
  "name": "Sub Operation",
diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py
index 68de0b2..bf1ccb7 100644
--- a/erpnext/manufacturing/doctype/work_order/test_work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py
@@ -513,6 +513,60 @@
 		work_order1.save()
 		self.assertEqual(work_order1.operations[0].time_in_mins, 40.0)
 
+	def test_batch_size_for_fg_item(self):
+		fg_item = "Test Batch Size Item For BOM 3"
+		rm1 = "Test Batch Size Item RM 1 For BOM 3"
+
+		frappe.db.set_value('Manufacturing Settings', None, 'make_serial_no_batch_from_work_order', 0)
+		for item in ["Test Batch Size Item For BOM 3", "Test Batch Size Item RM 1 For BOM 3"]:
+			item_args = {
+				"include_item_in_manufacturing": 1,
+				"is_stock_item": 1
+			}
+
+			if item == fg_item:
+				item_args['has_batch_no'] = 1
+				item_args['create_new_batch'] = 1
+				item_args['batch_number_series'] = 'TBSI3.#####'
+
+			make_item(item, item_args)
+
+		bom_name = frappe.db.get_value("BOM",
+			{"item": fg_item, "is_active": 1, "with_operations": 1}, "name")
+
+		if not bom_name:
+			bom = make_bom(item=fg_item, rate=1000, raw_materials = [rm1], do_not_save=True)
+			bom.save()
+			bom.submit()
+			bom_name = bom.name
+
+		work_order = make_wo_order_test_record(item=fg_item, skip_transfer=True, planned_start_date=now(), qty=1)
+		ste1 = frappe.get_doc(make_stock_entry(work_order.name, "Manufacture", 1))
+		for row in ste1.get('items'):
+			if row.is_finished_item:
+				self.assertEqual(row.item_code, fg_item)
+
+		work_order = make_wo_order_test_record(item=fg_item, skip_transfer=True, planned_start_date=now(), qty=1)
+		frappe.db.set_value('Manufacturing Settings', None, 'make_serial_no_batch_from_work_order', 1)
+		ste1 = frappe.get_doc(make_stock_entry(work_order.name, "Manufacture", 1))
+		for row in ste1.get('items'):
+			if row.is_finished_item:
+				self.assertEqual(row.item_code, fg_item)
+
+		work_order = make_wo_order_test_record(item=fg_item, skip_transfer=True, planned_start_date=now(),
+			qty=30, do_not_save = True)
+		work_order.batch_size = 10
+		work_order.insert()
+		work_order.submit()
+		self.assertEqual(work_order.has_batch_no, 1)
+		ste1 = frappe.get_doc(make_stock_entry(work_order.name, "Manufacture", 30))
+		for row in ste1.get('items'):
+			if row.is_finished_item:
+				self.assertEqual(row.item_code, fg_item)
+				self.assertEqual(row.qty, 10)
+
+		frappe.db.set_value('Manufacturing Settings', None, 'make_serial_no_batch_from_work_order', 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)
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index 779ae42..0a8e532 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -239,7 +239,7 @@
 		self.create_serial_no_batch_no()
 
 	def on_submit(self):
-		if not self.wip_warehouse:
+		if not self.wip_warehouse and not self.skip_transfer:
 			frappe.throw(_("Work-in-Progress Warehouse is required before Submit"))
 		if not self.fg_warehouse:
 			frappe.throw(_("For Warehouse is required before Submit"))
diff --git a/erpnext/non_profit/doctype/member/member.json b/erpnext/non_profit/doctype/member/member.json
index f190cfa..7c1baf1 100644
--- a/erpnext/non_profit/doctype/member/member.json
+++ b/erpnext/non_profit/doctype/member/member.json
@@ -26,7 +26,7 @@
   "razorpay_details_section",
   "subscription_id",
   "customer_id",
-  "subscription_activated",
+  "subscription_status",
   "column_break_21",
   "subscription_start",
   "subscription_end"
@@ -152,12 +152,6 @@
    "fieldtype": "Column Break"
   },
   {
-   "default": "0",
-   "fieldname": "subscription_activated",
-   "fieldtype": "Check",
-   "label": "Subscription Activated"
-  },
-  {
    "fieldname": "subscription_start",
    "fieldtype": "Date",
    "label": "Subscription Start "
@@ -166,11 +160,17 @@
    "fieldname": "subscription_end",
    "fieldtype": "Date",
    "label": "Subscription End"
+  },
+  {
+   "fieldname": "subscription_status",
+   "fieldtype": "Select",
+   "label": "Subscription Status",
+   "options": "\nActive\nHalted"
   }
  ],
  "image_field": "image",
  "links": [],
- "modified": "2020-11-09 12:12:10.174647",
+ "modified": "2021-07-11 14:27:26.368039",
  "modified_by": "Administrator",
  "module": "Non Profit",
  "name": "Member",
diff --git a/erpnext/non_profit/doctype/member/member.py b/erpnext/non_profit/doctype/member/member.py
index 30be585..67828d6 100644
--- a/erpnext/non_profit/doctype/member/member.py
+++ b/erpnext/non_profit/doctype/member/member.py
@@ -84,7 +84,9 @@
 		"email_id": user_details.email,
 		"pan_number": user_details.pan or None,
 		"membership_type": user_details.plan_id,
-		"subscription_id": user_details.subscription_id or None
+		"customer_id": user_details.customer_id or None,
+		"subscription_id": user_details.subscription_id or None,
+		"subscription_status": user_details.subscription_status or ""
 	})
 
 	member.insert(ignore_permissions=True)
diff --git a/erpnext/non_profit/doctype/membership/membership.py b/erpnext/non_profit/doctype/membership/membership.py
index e8ae618..b584116 100644
--- a/erpnext/non_profit/doctype/membership/membership.py
+++ b/erpnext/non_profit/doctype/membership/membership.py
@@ -196,11 +196,14 @@
 	return invoice
 
 
-def get_member_based_on_subscription(subscription_id, email):
-	members = frappe.get_all("Member", filters={
-					"subscription_id": subscription_id,
-					"email_id": email
-				}, order_by="creation desc")
+def get_member_based_on_subscription(subscription_id, email=None, customer_id=None):
+	filters = {"subscription_id": subscription_id}
+	if email:
+		filters.update({"email_id": email})
+	if customer_id:
+		filters.update({"customer_id": customer_id})
+
+	members = frappe.get_all("Member", filters=filters, order_by="creation desc")
 
 	try:
 		return frappe.get_doc("Member", members[0]["name"])
@@ -209,8 +212,6 @@
 
 
 def verify_signature(data, endpoint="Membership"):
-	if frappe.flags.in_test or os.environ.get("CI"):
-		return True
 	signature = frappe.request.headers.get("X-Razorpay-Signature")
 
 	settings = frappe.get_doc("Non Profit Settings")
@@ -225,16 +226,7 @@
 @frappe.whitelist(allow_guest=True)
 def trigger_razorpay_subscription(*args, **kwargs):
 	data = frappe.request.get_data(as_text=True)
-	try:
-		verify_signature(data)
-	except Exception as e:
-		log = frappe.log_error(e, "Membership Webhook Verification Error")
-		notify_failure(log)
-		return { "status": "Failed", "reason": e}
-
-	if isinstance(data, six.string_types):
-		data = json.loads(data)
-	data = frappe._dict(data)
+	data = process_request_data(data)
 
 	subscription = data.payload.get("subscription", {}).get("entity", {})
 	subscription = frappe._dict(subscription)
@@ -281,7 +273,7 @@
 		# Update membership values
 		member.subscription_start = datetime.fromtimestamp(subscription.start_at)
 		member.subscription_end = datetime.fromtimestamp(subscription.end_at)
-		member.subscription_activated = 1
+		member.subscription_status = "Active"
 		member.flags.ignore_mandatory = True
 		member.save()
 
@@ -294,9 +286,67 @@
 		message = "{0}\n\n{1}\n\n{2}: {3}".format(e, frappe.get_traceback(), _("Payment ID"), payment.id)
 		log = frappe.log_error(message, _("Error creating membership entry for {0}").format(member.name))
 		notify_failure(log)
-		return { "status": "Failed", "reason": e}
+		return {"status": "Failed", "reason": e}
 
-	return { "status": "Success" }
+	return {"status": "Success"}
+
+
+@frappe.whitelist(allow_guest=True)
+def update_halted_razorpay_subscription(*args, **kwargs):
+	"""
+	When all retries have been exhausted, Razorpay moves the subscription to the halted state.
+	The customer has to manually retry the charge or change the card linked to the subscription,
+	for the subscription to move back to the active state.
+	"""
+	if frappe.request:
+		data = frappe.request.get_data(as_text=True)
+		data = process_request_data(data)
+	elif frappe.flags.in_test:
+		data = kwargs.get("data")
+		data = frappe._dict(data)
+	else:
+		return
+
+	if not data.event == "subscription.halted":
+		return
+
+	subscription = data.payload.get("subscription", {}).get("entity", {})
+	subscription = frappe._dict(subscription)
+
+	try:
+		member = get_member_based_on_subscription(subscription.id, customer_id=subscription.customer_id)
+		if not member:
+			frappe.throw(_("Member with Razorpay Subscription ID {0} not found").format(subscription.id))
+
+		member.subscription_status = "Halted"
+		member.flags.ignore_mandatory = True
+		member.save()
+
+		if subscription.get("notes"):
+			member = get_additional_notes(member, subscription)
+
+	except Exception as e:
+		message = "{0}\n\n{1}".format(e, frappe.get_traceback())
+		log = frappe.log_error(message, _("Error updating halted status for member {0}").format(member.name))
+		notify_failure(log)
+		return {"status": "Failed", "reason": e}
+
+	return {"status": "Success"}
+
+
+def process_request_data(data):
+	try:
+		verify_signature(data)
+	except Exception as e:
+		log = frappe.log_error(e, "Membership Webhook Verification Error")
+		notify_failure(log)
+		return {"status": "Failed", "reason": e}
+
+	if isinstance(data, six.string_types):
+		data = json.loads(data)
+	data = frappe._dict(data)
+
+	return data
 
 
 def get_company_for_memberships():
@@ -362,4 +412,4 @@
 			`tabMembership` SET `status` = 'Expired'
 		WHERE
 			`status` not in ('Cancelled') AND `to_date` < %s
-		""", (nowdate()))
\ No newline at end of file
+		""", (nowdate()))
diff --git a/erpnext/non_profit/doctype/membership/test_membership.py b/erpnext/non_profit/doctype/membership/test_membership.py
index 31da792..0f5a9be 100644
--- a/erpnext/non_profit/doctype/membership/test_membership.py
+++ b/erpnext/non_profit/doctype/membership/test_membership.py
@@ -6,6 +6,7 @@
 import frappe
 import erpnext
 from erpnext.non_profit.doctype.member.member import create_member
+from erpnext.non_profit.doctype.membership.membership import update_halted_razorpay_subscription
 from frappe.utils import nowdate, add_months
 
 class TestMembership(unittest.TestCase):
@@ -13,11 +14,16 @@
 		plan = setup_membership()
 
 		# make test member
-		self.member_doc = create_member(frappe._dict({
-				'fullname': "_Test_Member",
-				'email': "_test_member_erpnext@example.com",
-				'plan_id': plan.name
-		}))
+		self.member_doc = create_member(
+			frappe._dict({
+				"fullname": "_Test_Member",
+				"email": "_test_member_erpnext@example.com",
+				"plan_id": plan.name,
+				"subscription_id": "sub_DEX6xcJ1HSW4CR",
+				"customer_id": "cust_C0WlbKhp3aLA7W",
+				"subscription_status": "Active"
+			})
+		)
 		self.member_doc.make_customer_and_link()
 		self.member = self.member_doc.name
 
@@ -51,6 +57,20 @@
 			"to_date": add_months(nowdate(), 3),
 		})
 
+	def test_halted_memberships(self):
+		make_membership(self.member, {
+			"from_date": add_months(nowdate(), 2),
+			"to_date": add_months(nowdate(), 3)
+		})
+
+		self.assertEqual(frappe.db.get_value("Member", self.member, "subscription_status"), "Active")
+		payload = get_subscription_payload()
+		update_halted_razorpay_subscription(data=payload)
+		self.assertEqual(frappe.db.get_value("Member", self.member, "subscription_status"), "Halted")
+
+	def tearDown(self):
+		frappe.db.rollback()
+
 def set_config(key, value):
 	frappe.db.set_value("Non Profit Settings", None, key, value)
 
@@ -115,4 +135,28 @@
 	else:
 		plan = frappe.get_doc("Membership Type", "_rzpy_test_milythm")
 
-	return plan
\ No newline at end of file
+	return plan
+
+def get_subscription_payload():
+	return {
+		"entity": "event",
+		"account_id": "acc_BFQ7uQEaa7j2z7",
+		"event": "subscription.halted",
+		"contains": [
+			"subscription"
+		],
+		"payload": {
+			"subscription": {
+				"entity": {
+					"id": "sub_DEX6xcJ1HSW4CR",
+					"entity": "subscription",
+					"plan_id": "_rzpy_test_milythm",
+					"customer_id": "cust_C0WlbKhp3aLA7W",
+					"status": "halted",
+					"notes": {
+						"Important": "Notes for Internal Reference"
+					},
+				}
+			}
+		}
+	}
\ No newline at end of file
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 29376f0..2a83635 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -291,3 +291,5 @@
 erpnext.patches.v13_0.bill_for_rejected_quantity_in_purchase_invoice
 erpnext.patches.v13_0.update_job_card_details
 erpnext.patches.v13_0.update_level_in_bom #1234sswef
+erpnext.patches.v13_0.add_missing_fg_item_for_stock_entry
+erpnext.patches.v13_0.update_subscription_status_in_memberships
diff --git a/erpnext/patches/v13_0/add_missing_fg_item_for_stock_entry.py b/erpnext/patches/v13_0/add_missing_fg_item_for_stock_entry.py
new file mode 100644
index 0000000..48999e6
--- /dev/null
+++ b/erpnext/patches/v13_0/add_missing_fg_item_for_stock_entry.py
@@ -0,0 +1,110 @@
+# Copyright (c) 2020, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+import frappe
+from frappe.utils import cstr, flt, cint
+from erpnext.stock.stock_ledger import make_sl_entries
+from erpnext.controllers.stock_controller import create_repost_item_valuation_entry
+
+def execute():
+	if not frappe.db.has_column('Work Order', 'has_batch_no'):
+		return
+
+	if cint(frappe.db.get_single_value('Manufacturing Settings', 'make_serial_no_batch_from_work_order')):
+		return
+
+	frappe.reload_doc('manufacturing', 'doctype', 'work_order')
+	filters = {
+		'docstatus': 1,
+		'produced_qty': ('>', 0),
+		'creation': ('>=', '2021-06-29 00:00:00'),
+		'has_batch_no': 1
+	}
+
+	fields = ['name', 'production_item']
+
+	work_orders = [d.name for d in frappe.get_all('Work Order', filters = filters, fields=fields)]
+
+	if not work_orders:
+		return
+
+	repost_stock_entries = []
+	stock_entries = frappe.db.sql_list('''
+		SELECT
+			se.name
+		FROM
+			`tabStock Entry` se
+		WHERE
+			se.purpose = 'Manufacture' and se.docstatus < 2 and se.work_order in {work_orders}
+			and not exists(
+				select name from `tabStock Entry Detail` sed where sed.parent = se.name and sed.is_finished_item = 1
+			)
+		Order BY
+			se.posting_date, se.posting_time
+	'''.format(work_orders=tuple(work_orders)))
+
+	if stock_entries:
+		print('Length of stock entries', len(stock_entries))
+
+	for stock_entry in stock_entries:
+		doc = frappe.get_doc('Stock Entry', stock_entry)
+		doc.set_work_order_details()
+		doc.load_items_from_bom()
+		doc.calculate_rate_and_amount()
+		set_expense_account(doc)
+		doc.make_batches('t_warehouse')
+
+		if doc.docstatus == 0:
+			doc.save()
+		else:
+			repost_stock_entry(doc)
+			repost_stock_entries.append(doc)
+
+	for repost_doc in repost_stock_entries:
+		repost_future_sle_and_gle(repost_doc)
+
+def set_expense_account(doc):
+	for row in doc.items:
+		if row.is_finished_item and not row.expense_account:
+			row.expense_account = frappe.get_cached_value('Company', doc.company, 'stock_adjustment_account')
+
+def repost_stock_entry(doc):
+	doc.db_update()
+	for child_row in doc.items:
+		if child_row.is_finished_item:
+			child_row.db_update()
+
+	sl_entries = []
+	finished_item_row = doc.get_finished_item_row()
+	get_sle_for_target_warehouse(doc, sl_entries, finished_item_row)
+
+	if sl_entries:
+		try:
+			make_sl_entries(sl_entries, True)
+		except Exception:
+			print(f'SLE entries not posted for the stock entry {doc.name}')
+			traceback = frappe.get_traceback()
+			frappe.log_error(traceback)
+
+def get_sle_for_target_warehouse(doc, sl_entries, finished_item_row):
+	for d in doc.get('items'):
+		if cstr(d.t_warehouse) and finished_item_row and d.name == finished_item_row.name:
+			sle = doc.get_sl_entries(d, {
+				"warehouse": cstr(d.t_warehouse),
+				"actual_qty": flt(d.transfer_qty),
+				"incoming_rate": flt(d.valuation_rate)
+			})
+
+			sle.recalculate_rate = 1
+			sl_entries.append(sle)
+
+def repost_future_sle_and_gle(doc):
+	args = frappe._dict({
+		"posting_date": doc.posting_date,
+		"posting_time": doc.posting_time,
+		"voucher_type": doc.doctype,
+		"voucher_no": doc.name,
+		"company": doc.company
+	})
+
+	create_repost_item_valuation_entry(args)
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/update_subscription_status_in_memberships.py b/erpnext/patches/v13_0/update_subscription_status_in_memberships.py
new file mode 100644
index 0000000..28e650e
--- /dev/null
+++ b/erpnext/patches/v13_0/update_subscription_status_in_memberships.py
@@ -0,0 +1,9 @@
+import frappe
+
+def execute():
+	if frappe.db.exists('DocType', 'Member'):
+		frappe.reload_doc('Non Profit', 'doctype', 'Member')
+
+		if frappe.db.has_column('Member', 'subscription_activated'):
+			frappe.db.sql('UPDATE `tabMember` SET subscription_status = "Active" WHERE subscription_activated = 1')
+			frappe.db.sql_ddl('ALTER table `tabMember` DROP COLUMN subscription_activated')
\ No newline at end of file
diff --git a/erpnext/public/js/utils/customer_quick_entry.js b/erpnext/public/js/utils/customer_quick_entry.js
index ebe6cd9..7bd21df 100644
--- a/erpnext/public/js/utils/customer_quick_entry.js
+++ b/erpnext/public/js/utils/customer_quick_entry.js
@@ -1,9 +1,9 @@
 frappe.provide('frappe.ui.form');
 
 frappe.ui.form.CustomerQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
-	init: function(doctype, after_insert) {
+	init: function(doctype, after_insert, init_callback, doc, force) {
+		this._super(doctype, after_insert, init_callback, doc, force);
 		this.skip_redirect_on_error = true;
-		this._super(doctype, after_insert);
 	},
 
 	render_dialog: function() {
diff --git a/erpnext/selling/page/point_of_sale/pos_item_cart.js b/erpnext/selling/page/point_of_sale/pos_item_cart.js
index f7b2c1d..6e36d28 100644
--- a/erpnext/selling/page/point_of_sale/pos_item_cart.js
+++ b/erpnext/selling/page/point_of_sale/pos_item_cart.js
@@ -367,15 +367,16 @@
 			`<div class="add-discount-field"></div>`
 		);
 		const me = this;
+		const frm = me.events.get_frm();
+		let discount = frm.doc.additional_discount_percentage;
 
 		this.discount_field = frappe.ui.form.make_control({
 			df: {
 				label: __('Discount'),
 				fieldtype: 'Data',
-				placeholder: __('Enter discount percentage.'),
+				placeholder: ( discount ? discount + '%' :  __('Enter discount percentage.') ),
 				input_class: 'input-xs',
 				onchange: function() {
-					const frm = me.events.get_frm();
 					if (flt(this.value) != 0) {
 						frappe.model.set_value(frm.doc.doctype, frm.doc.name, 'additional_discount_percentage', flt(this.value));
 						me.hide_discount_control(this.value);
diff --git a/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py b/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py
index ece9fb5..c3db27f 100644
--- a/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py
+++ b/erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py
@@ -12,10 +12,14 @@
 class TransactionDeletionRecord(Document):
 	def validate(self):
 		frappe.only_for('System Manager')
+		self.validate_doctypes_to_be_ignored()
+
+	def validate_doctypes_to_be_ignored(self):
 		doctypes_to_be_ignored_list = get_doctypes_to_be_ignored()
 		for doctype in self.doctypes_to_be_ignored:
 			if doctype.doctype_name not in doctypes_to_be_ignored_list:
-				frappe.throw(_("DocTypes should not be added manually to the 'Excluded DocTypes' table. You are only allowed to remove entries from it. "), title=_("Not Allowed"))
+				frappe.throw(_("DocTypes should not be added manually to the 'Excluded DocTypes' table. You are only allowed to remove entries from it."),
+					title=_("Not Allowed"))
 
 	def before_submit(self):
 		if not self.doctypes_to_be_ignored:
@@ -23,54 +27,9 @@
 
 		self.delete_bins()
 		self.delete_lead_addresses()
-		
-		company_obj = frappe.get_doc('Company', self.company)
-		# reset company values
-		company_obj.total_monthly_sales = 0
-		company_obj.sales_monthly_history = None
-		company_obj.save()
-		# Clear notification counts
+		self.reset_company_values()
 		clear_notifications()
-
-		singles = frappe.get_all('DocType', filters = {'issingle': 1}, pluck = 'name')
-		tables = frappe.get_all('DocType', filters = {'istable': 1}, pluck = 'name')
-		doctypes_to_be_ignored_list = singles
-		for doctype in self.doctypes_to_be_ignored:
-			doctypes_to_be_ignored_list.append(doctype.doctype_name)
-
-		docfields = frappe.get_all('DocField', 
-			filters = {
-				'fieldtype': 'Link', 
-				'options': 'Company',
-				'parent': ['not in', doctypes_to_be_ignored_list]},
-			fields=['parent', 'fieldname'])
-	
-		for docfield in docfields:
-			if docfield['parent'] != self.doctype:
-				no_of_docs = frappe.db.count(docfield['parent'], {
-							docfield['fieldname'] : self.company
-						})
-
-				if no_of_docs > 0:
-					self.delete_version_log(docfield['parent'], docfield['fieldname'])
-					self.delete_communications(docfield['parent'], docfield['fieldname'])
-
-					# populate DocTypes table
-					if docfield['parent'] not in tables:
-						self.append('doctypes', {
-							'doctype_name' : docfield['parent'],
-							'no_of_docs' : no_of_docs
-						})
-
-					# delete the docs linked with the specified company
-					frappe.db.delete(docfield['parent'], {
-						docfield['fieldname'] : self.company
-					})
-
-					naming_series = frappe.db.get_value('DocType', docfield['parent'], 'autoname')
-					if naming_series:
-						if '#' in naming_series:
-							self.update_naming_series(naming_series, docfield['parent'])	
+		self.delete_company_transactions()
 
 	def populate_doctypes_to_be_ignored_table(self):		
 		doctypes_to_be_ignored_list = get_doctypes_to_be_ignored()
@@ -79,6 +38,111 @@
 						'doctype_name' : doctype
 					})
 
+	def delete_bins(self):
+		frappe.db.sql("""delete from tabBin where warehouse in
+				(select name from tabWarehouse where company=%s)""", self.company)
+
+	def delete_lead_addresses(self):
+		"""Delete addresses to which leads are linked"""
+		leads = frappe.get_all('Lead', filters={'company': self.company})
+		leads = ["'%s'" % row.get("name") for row in leads]
+		addresses = []
+		if leads:
+			addresses = frappe.db.sql_list("""select parent from `tabDynamic Link` where link_name
+				in ({leads})""".format(leads=",".join(leads)))
+
+			if addresses:
+				addresses = ["%s" % frappe.db.escape(addr) for addr in addresses]
+
+				frappe.db.sql("""delete from tabAddress where name in ({addresses}) and
+					name not in (select distinct dl1.parent from `tabDynamic Link` dl1
+					inner join `tabDynamic Link` dl2 on dl1.parent=dl2.parent
+					and dl1.link_doctype<>dl2.link_doctype)""".format(addresses=",".join(addresses)))
+
+				frappe.db.sql("""delete from `tabDynamic Link` where link_doctype='Lead'
+					and parenttype='Address' and link_name in ({leads})""".format(leads=",".join(leads)))
+
+			frappe.db.sql("""update tabCustomer set lead_name=NULL where lead_name in ({leads})""".format(leads=",".join(leads)))
+
+	def reset_company_values(self):
+		company_obj = frappe.get_doc('Company', self.company)
+		company_obj.total_monthly_sales = 0
+		company_obj.sales_monthly_history = None
+		company_obj.save()
+
+	def delete_company_transactions(self):
+		doctypes_to_be_ignored_list = self.get_doctypes_to_be_ignored_list()
+		docfields = self.get_doctypes_with_company_field(doctypes_to_be_ignored_list)
+
+		tables = self.get_all_child_doctypes()	
+		for docfield in docfields:
+			if docfield['parent'] != self.doctype:
+				no_of_docs = self.get_number_of_docs_linked_with_specified_company(docfield['parent'], docfield['fieldname'])
+
+				if no_of_docs > 0:
+					self.delete_version_log(docfield['parent'], docfield['fieldname'])
+					self.delete_communications(docfield['parent'], docfield['fieldname'])
+					self.populate_doctypes_table(tables, docfield['parent'], no_of_docs)
+
+					self.delete_child_tables(docfield['parent'], docfield['fieldname'])
+					self.delete_docs_linked_with_specified_company(docfield['parent'], docfield['fieldname'])
+
+					naming_series = frappe.db.get_value('DocType', docfield['parent'], 'autoname')
+					if naming_series:
+						if '#' in naming_series:
+							self.update_naming_series(naming_series, docfield['parent'])	
+
+	def get_doctypes_to_be_ignored_list(self):
+		singles = frappe.get_all('DocType', filters = {'issingle': 1}, pluck = 'name')
+		doctypes_to_be_ignored_list = singles
+		for doctype in self.doctypes_to_be_ignored:
+			doctypes_to_be_ignored_list.append(doctype.doctype_name)
+
+		return doctypes_to_be_ignored_list
+
+	def get_doctypes_with_company_field(self, doctypes_to_be_ignored_list):
+		docfields = frappe.get_all('DocField', 
+			filters = {
+				'fieldtype': 'Link', 
+				'options': 'Company',
+				'parent': ['not in', doctypes_to_be_ignored_list]},
+			fields=['parent', 'fieldname'])
+
+		return docfields
+
+	def get_all_child_doctypes(self):
+		return frappe.get_all('DocType', filters = {'istable': 1}, pluck = 'name')
+
+	def get_number_of_docs_linked_with_specified_company(self, doctype, company_fieldname):
+		return frappe.db.count(doctype, {company_fieldname : self.company})
+
+	def populate_doctypes_table(self, tables, doctype, no_of_docs):
+		if doctype not in tables:
+			self.append('doctypes', {
+				'doctype_name' : doctype,
+				'no_of_docs' : no_of_docs
+			})		
+
+	def delete_child_tables(self, doctype, company_fieldname):
+		parent_docs_to_be_deleted = frappe.get_all(doctype, {
+			company_fieldname : self.company
+		}, pluck = 'name')
+
+		child_tables = frappe.get_all('DocField', filters = {
+			'fieldtype': 'Table', 
+			'parent': doctype
+		}, pluck = 'options')
+
+		for table in child_tables:
+			frappe.db.delete(table, {
+				'parent': ['in', parent_docs_to_be_deleted]
+			})
+
+	def delete_docs_linked_with_specified_company(self, doctype, company_fieldname):
+		frappe.db.delete(doctype, {
+			company_fieldname : self.company
+		})
+
 	def update_naming_series(self, naming_series, doctype_name):
 		if '.' in naming_series:
 			prefix, hashes = naming_series.rsplit('.', 1)
@@ -107,32 +171,6 @@
 
 		frappe.delete_doc('Communication', communication_names, ignore_permissions=True)
 
-	def delete_bins(self):
-		frappe.db.sql("""delete from tabBin where warehouse in
-				(select name from tabWarehouse where company=%s)""", self.company)
-
-	def delete_lead_addresses(self):
-		"""Delete addresses to which leads are linked"""
-		leads = frappe.get_all('Lead', filters={'company': self.company})
-		leads = ["'%s'" % row.get("name") for row in leads]
-		addresses = []
-		if leads:
-			addresses = frappe.db.sql_list("""select parent from `tabDynamic Link` where link_name
-				in ({leads})""".format(leads=",".join(leads)))
-
-			if addresses:
-				addresses = ["%s" % frappe.db.escape(addr) for addr in addresses]
-
-				frappe.db.sql("""delete from tabAddress where name in ({addresses}) and
-					name not in (select distinct dl1.parent from `tabDynamic Link` dl1
-					inner join `tabDynamic Link` dl2 on dl1.parent=dl2.parent
-					and dl1.link_doctype<>dl2.link_doctype)""".format(addresses=",".join(addresses)))
-
-				frappe.db.sql("""delete from `tabDynamic Link` where link_doctype='Lead'
-					and parenttype='Address' and link_name in ({leads})""".format(leads=",".join(leads)))
-
-			frappe.db.sql("""update tabCustomer set lead_name=NULL where lead_name in ({leads})""".format(leads=",".join(leads)))
-
 @frappe.whitelist()
 def get_doctypes_to_be_ignored():
 	doctypes_to_be_ignored_list = ['Account', 'Cost Center', 'Warehouse', 'Budget',
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index b55374b..264baea 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -100,10 +100,11 @@
 
 		frm.add_custom_button(__('Duplicate'), function() {
 			var new_item = frappe.model.copy_doc(frm.doc);
-			if(new_item.item_name===new_item.item_code) {
+			// Duplicate item could have different name, causing "copy paste" error.
+			if (new_item.item_name===new_item.item_code) {
 				new_item.item_name = null;
 			}
-			if(new_item.description===new_item.description) {
+			if (new_item.item_code===new_item.description || new_item.item_code===new_item.description) {
 				new_item.description = null;
 			}
 			frappe.set_route('Form', 'Item', new_item.name);
@@ -186,8 +187,6 @@
 	item_code: function(frm) {
 		if(!frm.doc.item_name)
 			frm.set_value("item_name", frm.doc.item_code);
-		if(!frm.doc.description)
-			frm.set_value("description", frm.doc.item_code);
 	},
 
 	is_stock_item: function(frm) {
diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
index 55f2ebb..5f31d9c 100644
--- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
+++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
@@ -133,6 +133,6 @@
 
 def get_repost_item_valuation_entries():
 	return frappe.db.sql(""" SELECT name from `tabRepost Item Valuation`
-		WHERE status != 'Completed' and creation <= %s and docstatus = 1
+		WHERE status in ('Queued', 'In Progress') and creation <= %s and docstatus = 1
 		ORDER BY timestamp(posting_date, posting_time) asc, creation asc
 	""", now(), as_dict=1)
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 90b81dd..872b1d0 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -719,6 +719,10 @@
 			frappe.throw(_("Multiple items cannot be marked as finished item"))
 
 		if self.purpose == "Manufacture":
+			if not finished_items:
+				frappe.throw(_('Finished Good has not set in the stock entry {0}')
+					.format(self.name))
+
 			allowance_percentage = flt(frappe.db.get_single_value("Manufacturing Settings",
 				"overproduction_percentage_for_work_order"))
 
@@ -1090,13 +1094,13 @@
 			"is_finished_item": 1
 		}
 
-		if self.work_order and self.pro_doc.has_batch_no:
+		if self.work_order and self.pro_doc.has_batch_no and cint(frappe.db.get_single_value('Manufacturing Settings',
+			'make_serial_no_batch_from_work_order', cache=True)):
 			self.set_batchwise_finished_goods(args, item)
 		else:
-			self.add_finisged_goods(args, item)
+			self.add_finished_goods(args, item)
 
 	def set_batchwise_finished_goods(self, args, item):
-		qty = flt(self.fg_completed_qty)
 		filters = {
 			"reference_name": self.pro_doc.name,
 			"reference_doctype": self.pro_doc.doctype,
@@ -1105,7 +1109,17 @@
 
 		fields = ["qty_to_produce as qty", "produced_qty", "name"]
 
-		for row in frappe.get_all("Batch", filters = filters, fields = fields, order_by="creation asc"):
+		data = frappe.get_all("Batch", filters = filters, fields = fields, order_by="creation asc")
+
+		if not data:
+			self.add_finished_goods(args, item)
+		else:
+			self.add_batchwise_finished_good(data, args, item)
+
+	def add_batchwise_finished_good(self, data, args, item):
+		qty = flt(self.fg_completed_qty)
+
+		for row in data:
 			batch_qty = flt(row.qty) - flt(row.produced_qty)
 			if not batch_qty:
 				continue
@@ -1121,9 +1135,9 @@
 			args["qty"] = fg_qty
 			args["batch_no"] = row.name
 
-			self.add_finisged_goods(args, item)
+			self.add_finished_goods(args, item)
 
-	def add_finisged_goods(self, args, item):
+	def add_finished_goods(self, args, item):
 		self.add_to_stock_entry_detail({
 			item.name: args
 		}, bom_no = self.bom_no)
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 4657700..cf52803 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -74,9 +74,8 @@
 
 	update_party_blanket_order(args, out)
 
-	if not doc or cint(doc.get('is_return')) == 0:
-		# get price list rate only if the invoice is not a credit or debit note
-		get_price_list_rate(args, item, out)
+	
+	get_price_list_rate(args, item, out)
 
 	if args.customer and cint(args.is_pos):
 		out.update(get_pos_profile_item_details(args.company, args, update_data=True))
diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py
index 8a6a3a3..b57b2aa 100644
--- a/erpnext/stock/utils.py
+++ b/erpnext/stock/utils.py
@@ -314,13 +314,16 @@
 	for row_idx, row in enumerate(result):
 		data = row.items() if is_dict_obj else enumerate(row)
 		for key, value in data:
-			if key not in convertible_columns or not conversion_factors[row_idx-1]:
+			if key not in convertible_columns:
 				continue
+			# If no conversion factor for the UOM, defaults to 1
+			if not conversion_factors[row_idx]:
+				conversion_factors[row_idx] = 1
 
 			if convertible_columns.get(key) == 'rate':
-				new_value = flt(value) * conversion_factors[row_idx-1]
+				new_value = flt(value) * conversion_factors[row_idx]
 			else:
-				new_value = flt(value) / conversion_factors[row_idx-1]
+				new_value = flt(value) / conversion_factors[row_idx]
 
 			if not is_dict_obj:
 				row.insert(key+1, new_value)
@@ -386,4 +389,4 @@
 	reposting_in_progress = frappe.db.exists("Repost Item Valuation",
 		{'docstatus': 1, 'status': ['in', ['Queued','In Progress']]})
 	if reposting_in_progress:
-		frappe.msgprint(_("Item valuation reposting in progress. Report might show incorrect item valuation."), alert=1)
\ No newline at end of file
+		frappe.msgprint(_("Item valuation reposting in progress. Report might show incorrect item valuation."), alert=1)