Merge branch 'develop' into revert-bu-schluessel
diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
index 55ea571..9a35a24 100644
--- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
+++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
@@ -7,35 +7,30 @@
  "editable_grid": 1,
  "engine": "InnoDB",
  "field_order": [
-  "accounts_transactions_settings_section",
-  "over_billing_allowance",
-  "role_allowed_to_over_bill",
-  "credit_controller",
-  "make_payment_via_journal_entry",
-  "column_break_11",
-  "check_supplier_invoice_uniqueness",
+  "invoice_and_billing_tab",
+  "enable_features_section",
   "unlink_payment_on_cancellation_of_invoice",
-  "automatically_fetch_payment_terms",
-  "delete_linked_ledger_entries",
-  "book_asset_depreciation_entry_automatically",
   "unlink_advance_payment_on_cancelation_of_order",
+  "column_break_13",
+  "delete_linked_ledger_entries",
+  "invoicing_features_section",
+  "check_supplier_invoice_uniqueness",
+  "automatically_fetch_payment_terms",
+  "column_break_17",
   "enable_common_party_accounting",
-  "post_change_gl_entries",
   "enable_discount_accounting",
-  "tax_settings_section",
-  "determine_address_tax_category_from",
-  "column_break_19",
-  "add_taxes_from_item_tax_template",
-  "period_closing_settings_section",
-  "acc_frozen_upto",
-  "frozen_accounts_modifier",
-  "column_break_4",
+  "report_setting_section",
+  "use_custom_cash_flow",
   "deferred_accounting_settings_section",
   "book_deferred_entries_based_on",
   "column_break_18",
   "automatically_process_deferred_accounting_entry",
   "book_deferred_entries_via_journal_entry",
   "submit_journal_entries",
+  "tax_settings_section",
+  "determine_address_tax_category_from",
+  "column_break_19",
+  "add_taxes_from_item_tax_template",
   "print_settings",
   "show_inclusive_tax_in_print",
   "column_break_12",
@@ -43,8 +38,25 @@
   "currency_exchange_section",
   "allow_stale",
   "stale_days",
-  "report_settings_sb",
-  "use_custom_cash_flow"
+  "invoicing_settings_tab",
+  "accounts_transactions_settings_section",
+  "over_billing_allowance",
+  "column_break_11",
+  "role_allowed_to_over_bill",
+  "credit_controller",
+  "make_payment_via_journal_entry",
+  "pos_tab",
+  "pos_setting_section",
+  "post_change_gl_entries",
+  "assets_tab",
+  "asset_settings_section",
+  "book_asset_depreciation_entry_automatically",
+  "closing_settings_tab",
+  "period_closing_settings_section",
+  "acc_frozen_upto",
+  "column_break_25",
+  "frozen_accounts_modifier",
+  "report_settings_sb"
  ],
  "fields": [
   {
@@ -71,10 +83,6 @@
    "options": "Billing Address\nShipping Address"
   },
   {
-   "fieldname": "column_break_4",
-   "fieldtype": "Column Break"
-  },
-  {
    "fieldname": "credit_controller",
    "fieldtype": "Link",
    "in_list_view": 1,
@@ -83,6 +91,7 @@
   },
   {
    "default": "0",
+   "description": "Enabling ensure each Sales Invoice has a unique value in Supplier Invoice No. field",
    "fieldname": "check_supplier_invoice_uniqueness",
    "fieldtype": "Check",
    "label": "Check Supplier Invoice Number Uniqueness"
@@ -168,7 +177,7 @@
    "description": "Only select this if you have set up the Cash Flow Mapper documents",
    "fieldname": "use_custom_cash_flow",
    "fieldtype": "Check",
-   "label": "Use Custom Cash Flow Format"
+   "label": "Enable Custom Cash Flow Format"
   },
   {
    "default": "0",
@@ -241,7 +250,7 @@
   {
    "fieldname": "accounts_transactions_settings_section",
    "fieldtype": "Section Break",
-   "label": "Transactions Settings"
+   "label": "Credit Limit Settings"
   },
   {
    "fieldname": "column_break_11",
@@ -272,9 +281,72 @@
   },
   {
    "default": "0",
+   "description": "Learn about <a href=\"https://docs.erpnext.com/docs/v13/user/manual/en/accounts/articles/common_party_accounting#:~:text=Common%20Party%20Accounting%20in%20ERPNext,Invoice%20against%20a%20primary%20Supplier.\">Common Party</a>",
    "fieldname": "enable_common_party_accounting",
    "fieldtype": "Check",
    "label": "Enable Common Party Accounting"
+  },
+  {
+   "fieldname": "enable_features_section",
+   "fieldtype": "Section Break",
+   "label": "Invoice Cancellation"
+  },
+  {
+   "fieldname": "column_break_13",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "column_break_25",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "asset_settings_section",
+   "fieldtype": "Section Break",
+   "label": "Asset Settings"
+  },
+  {
+   "fieldname": "invoicing_settings_tab",
+   "fieldtype": "Tab Break",
+   "label": "Credit Limits"
+  },
+  {
+   "fieldname": "assets_tab",
+   "fieldtype": "Tab Break",
+   "label": "Assets"
+  },
+  {
+   "fieldname": "closing_settings_tab",
+   "fieldtype": "Tab Break",
+   "label": "Accounts Closing"
+  },
+  {
+   "fieldname": "pos_setting_section",
+   "fieldtype": "Section Break",
+   "label": "POS Setting"
+  },
+  {
+   "fieldname": "invoice_and_billing_tab",
+   "fieldtype": "Tab Break",
+   "label": "Invoice and Billing"
+  },
+  {
+   "fieldname": "invoicing_features_section",
+   "fieldtype": "Section Break",
+   "label": "Invoicing Features"
+  },
+  {
+   "fieldname": "column_break_17",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "pos_tab",
+   "fieldtype": "Tab Break",
+   "label": "POS"
+  },
+  {
+   "fieldname": "report_setting_section",
+   "fieldtype": "Section Break",
+   "label": "Report Setting"
   }
  ],
  "icon": "icon-cog",
@@ -282,7 +354,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2021-10-11 17:42:36.427699",
+ "modified": "2022-02-04 12:32:36.805652",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Accounts Settings",
@@ -309,5 +381,6 @@
  "quick_entry": 1,
  "sort_field": "modified",
  "sort_order": "ASC",
+ "states": [],
  "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/item_tax_template/item_tax_template.json b/erpnext/accounts/doctype/item_tax_template/item_tax_template.json
index 77c9e95..b42d712 100644
--- a/erpnext/accounts/doctype/item_tax_template/item_tax_template.json
+++ b/erpnext/accounts/doctype/item_tax_template/item_tax_template.json
@@ -2,7 +2,7 @@
  "actions": [],
  "allow_import": 1,
  "allow_rename": 1,
- "creation": "2018-11-22 22:45:00.370913",
+ "creation": "2022-01-19 01:09:13.297137",
  "doctype": "DocType",
  "document_type": "Setup",
  "editable_grid": 1,
@@ -10,6 +10,9 @@
  "field_order": [
   "title",
   "company",
+  "column_break_3",
+  "disabled",
+  "section_break_5",
   "taxes"
  ],
  "fields": [
@@ -36,10 +39,24 @@
    "label": "Company",
    "options": "Company",
    "reqd": 1
+  },
+  {
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break"
+  },
+  {
+   "default": "0",
+   "fieldname": "disabled",
+   "fieldtype": "Check",
+   "label": "Disabled"
+  },
+  {
+   "fieldname": "section_break_5",
+   "fieldtype": "Section Break"
   }
  ],
  "links": [],
- "modified": "2021-03-08 19:50:21.416513",
+ "modified": "2022-01-18 21:11:23.105589",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Item Tax Template",
@@ -82,6 +99,7 @@
  "show_name_in_global_search": 1,
  "sort_field": "modified",
  "sort_order": "DESC",
+ "states": [],
  "title_field": "title",
  "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.js b/erpnext/accounts/doctype/journal_entry/journal_entry.js
index 617b376..3cc28a3 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.js
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.js
@@ -8,6 +8,7 @@
 frappe.ui.form.on("Journal Entry", {
 	setup: function(frm) {
 		frm.add_fetch("bank_account", "account", "account");
+		frm.ignore_doctypes_on_cancel_all = ['Sales Invoice', 'Purchase Invoice'];
 	},
 
 	refresh: function(frm) {
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 279557a..76d9cc7 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -537,8 +537,11 @@
 
 		voucher_wise_stock_value = {}
 		if self.update_stock:
-			for d in frappe.get_all('Stock Ledger Entry',
-				fields = ["voucher_detail_no", "stock_value_difference", "warehouse"], filters={'voucher_no': self.name}):
+			stock_ledger_entries = frappe.get_all("Stock Ledger Entry",
+				fields = ["voucher_detail_no", "stock_value_difference", "warehouse"],
+				filters={"voucher_no": self.name, "voucher_type": self.doctype, "is_cancelled": 0}
+			)
+			for d in stock_ledger_entries:
 				voucher_wise_stock_value.setdefault((d.voucher_detail_no, d.warehouse), d.stock_value_difference)
 
 		valuation_tax_accounts = [d.account_head for d in self.get("taxes")
diff --git a/erpnext/accounts/doctype/tax_category/tax_category.json b/erpnext/accounts/doctype/tax_category/tax_category.json
index f7145af..44a339f 100644
--- a/erpnext/accounts/doctype/tax_category/tax_category.json
+++ b/erpnext/accounts/doctype/tax_category/tax_category.json
@@ -2,12 +2,13 @@
  "actions": [],
  "allow_rename": 1,
  "autoname": "field:title",
- "creation": "2018-11-22 23:38:39.668804",
+ "creation": "2022-01-19 01:09:28.920486",
  "doctype": "DocType",
  "editable_grid": 1,
  "engine": "InnoDB",
  "field_order": [
-  "title"
+  "title",
+  "disabled"
  ],
  "fields": [
   {
@@ -18,14 +19,21 @@
    "label": "Title",
    "reqd": 1,
    "unique": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "disabled",
+   "fieldtype": "Check",
+   "label": "Disabled"
   }
  ],
  "index_web_pages_for_search": 1,
  "links": [],
- "modified": "2021-03-03 11:50:38.748872",
+ "modified": "2022-01-18 21:13:41.161017",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Tax Category",
+ "naming_rule": "By fieldname",
  "owner": "Administrator",
  "permissions": [
   {
@@ -65,5 +73,6 @@
  "quick_entry": 1,
  "sort_field": "modified",
  "sort_order": "DESC",
+ "states": [],
  "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/accounts/report/balance_sheet/balance_sheet.py b/erpnext/accounts/report/balance_sheet/balance_sheet.py
index dc1f7aa..f10a5ea 100644
--- a/erpnext/accounts/report/balance_sheet/balance_sheet.py
+++ b/erpnext/accounts/report/balance_sheet/balance_sheet.py
@@ -120,11 +120,11 @@
 	opening_balance = 0
 	float_precision = cint(frappe.db.get_default("float_precision")) or 2
 	if asset:
-		opening_balance = flt(asset[0].get("opening_balance", 0), float_precision)
+		opening_balance = flt(asset[-1].get("opening_balance", 0), float_precision)
 	if liability:
-		opening_balance -= flt(liability[0].get("opening_balance", 0), float_precision)
+		opening_balance -= flt(liability[-1].get("opening_balance", 0), float_precision)
 	if equity:
-		opening_balance -= flt(equity[0].get("opening_balance", 0), float_precision)
+		opening_balance -= flt(equity[-1].get("opening_balance", 0), float_precision)
 
 	opening_balance = flt(opening_balance, float_precision)
 	if opening_balance:
diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py
index 03ae0ae..db28cdf 100644
--- a/erpnext/accounts/report/financial_statements.py
+++ b/erpnext/accounts/report/financial_statements.py
@@ -282,7 +282,8 @@
 	total_row = {
 		"account_name": _("Total {0} ({1})").format(_(root_type), _(balance_must_be)),
 		"account": _("Total {0} ({1})").format(_(root_type), _(balance_must_be)),
-		"currency": company_currency
+		"currency": company_currency,
+		"opening_balance": 0.0
 	}
 
 	for row in out:
@@ -294,6 +295,7 @@
 
 			total_row.setdefault("total", 0.0)
 			total_row["total"] += flt(row["total"])
+			total_row["opening_balance"] += row["opening_balance"]
 			row["total"] = ""
 
 	if "total" in total_row:
diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json
index b828a43..50321ba 100644
--- a/erpnext/buying/doctype/buying_settings/buying_settings.json
+++ b/erpnext/buying/doctype/buying_settings/buying_settings.json
@@ -6,14 +6,17 @@
  "document_type": "Other",
  "engine": "InnoDB",
  "field_order": [
+  "supplier_and_price_defaults_section",
   "supp_master_name",
   "supplier_group",
+  "column_break_4",
   "buying_price_list",
   "maintain_same_rate_action",
   "role_to_override_stop_action",
-  "column_break_3",
+  "transaction_settings_section",
   "po_required",
   "pr_required",
+  "column_break_12",
   "maintain_same_rate",
   "allow_multiple_items",
   "bill_for_rejected_quantity_in_purchase_invoice",
@@ -43,10 +46,6 @@
    "options": "Price List"
   },
   {
-   "fieldname": "column_break_3",
-   "fieldtype": "Column Break"
-  },
-  {
    "fieldname": "po_required",
    "fieldtype": "Select",
    "label": "Is Purchase Order Required for Purchase Invoice & Receipt Creation?",
@@ -73,7 +72,7 @@
   {
    "fieldname": "subcontract",
    "fieldtype": "Section Break",
-   "label": "Subcontract"
+   "label": "Subcontracting Settings"
   },
   {
    "default": "Material Transferred for Subcontract",
@@ -116,6 +115,24 @@
    "fieldname": "bill_for_rejected_quantity_in_purchase_invoice",
    "fieldtype": "Check",
    "label": "Bill for Rejected Quantity in Purchase Invoice"
+  },
+  {
+   "fieldname": "supplier_and_price_defaults_section",
+   "fieldtype": "Section Break",
+   "label": "Supplier and Price Defaults"
+  },
+  {
+   "fieldname": "column_break_4",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "transaction_settings_section",
+   "fieldtype": "Section Break",
+   "label": "Transaction Settings"
+  },
+  {
+   "fieldname": "column_break_12",
+   "fieldtype": "Column Break"
   }
  ],
  "icon": "fa fa-cog",
@@ -123,7 +140,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2021-09-08 19:26:23.548837",
+ "modified": "2022-01-27 17:57:58.367048",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Buying Settings",
@@ -141,5 +158,6 @@
  ],
  "sort_field": "modified",
  "sort_order": "DESC",
+ "states": [],
  "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index 902e115..dd9b45c 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -710,6 +710,7 @@
 
 	item_doc = frappe.get_cached_doc('Item', filters.get('item_code'))
 	item_group = filters.get('item_group')
+	company = filters.get('company')
 	taxes = item_doc.taxes or []
 
 	while item_group:
@@ -718,7 +719,7 @@
 		item_group = item_group_doc.parent_item_group
 
 	if not taxes:
-		return frappe.db.sql(""" SELECT name FROM `tabItem Tax Template` """)
+		return frappe.get_all('Item Tax Template', filters={'disabled': 0, 'company': company}, as_list=True)
 	else:
 		valid_from = filters.get('valid_from')
 		valid_from = valid_from[1] if isinstance(valid_from, list) else valid_from
@@ -727,7 +728,7 @@
 			'item_code': filters.get('item_code'),
 			'posting_date': valid_from,
 			'tax_category': filters.get('tax_category'),
-			'company': filters.get('company')
+			'company': company
 		}
 
 		taxes = _get_item_tax_template(args, taxes, for_validate=True)
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index 75fcaee..31b2209 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -74,7 +74,8 @@
 				doctype=self.doctype, company=self.company,
 				posting_date=self.get('posting_date'),
 				fetch_payment_terms_template=fetch_payment_terms_template,
-				party_address=self.customer_address, shipping_address=self.shipping_address_name)
+				party_address=self.customer_address, shipping_address=self.shipping_address_name,
+				company_address=self.get('company_address'))
 			if not self.meta.get_field("sales_team"):
 				party_details.pop("sales_team")
 			self.update_if_missing(party_details)
diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py
index 76a7cda..affde4a 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -400,6 +400,16 @@
 			ref_doc = frappe.get_doc(ref_dt, ref_dn)
 
 			ref_doc.db_set("per_billed", per_billed)
+
+			# set billling status
+			if hasattr(ref_doc, 'billing_status'):
+				if ref_doc.per_billed < 0.001:
+					ref_doc.db_set("billing_status", "Not Billed")
+				elif ref_doc.per_billed > 99.999999:
+					ref_doc.db_set("billing_status", "Fully Billed")
+				else:
+					ref_doc.db_set("billing_status", "Partly Billed")
+
 			ref_doc.set_status(update=True)
 
 def get_allowance_for(item_code, item_allowance=None, global_qty_allowance=None, global_amount_allowance=None, qty_or_amount="qty"):
diff --git a/erpnext/loan_management/doctype/loan/loan.js b/erpnext/loan_management/doctype/loan/loan.js
index f9c201a..940a1bb 100644
--- a/erpnext/loan_management/doctype/loan/loan.js
+++ b/erpnext/loan_management/doctype/loan/loan.js
@@ -46,7 +46,7 @@
 			});
 		});
 
-		$.each(["payment_account", "loan_account"], function (i, field) {
+		$.each(["payment_account", "loan_account", "disbursement_account"], function (i, field) {
 			frm.set_query(field, function () {
 				return {
 					"filters": {
@@ -88,6 +88,10 @@
 				frm.add_custom_button(__('Loan Write Off'), function() {
 					frm.trigger("make_loan_write_off_entry");
 				},__('Create'));
+
+				frm.add_custom_button(__('Loan Refund'), function() {
+					frm.trigger("make_loan_refund");
+				},__('Create'));
 			}
 		}
 		frm.trigger("toggle_fields");
@@ -155,6 +159,21 @@
 		})
 	},
 
+	make_loan_refund: function(frm) {
+		frappe.call({
+			args: {
+				"loan": frm.doc.name
+			},
+			method: "erpnext.loan_management.doctype.loan.loan.make_refund_jv",
+			callback: function (r) {
+				if (r.message) {
+					let doc = frappe.model.sync(r.message)[0];
+					frappe.set_route("Form", doc.doctype, doc.name);
+				}
+			}
+		})
+	},
+
 	request_loan_closure: function(frm) {
 		frappe.confirm(__("Do you really want to close this loan"),
 			function() {
diff --git a/erpnext/loan_management/doctype/loan/loan.json b/erpnext/loan_management/doctype/loan/loan.json
index af26f7b..196f36f 100644
--- a/erpnext/loan_management/doctype/loan/loan.json
+++ b/erpnext/loan_management/doctype/loan/loan.json
@@ -2,7 +2,7 @@
  "actions": [],
  "allow_import": 1,
  "autoname": "ACC-LOAN-.YYYY.-.#####",
- "creation": "2019-08-29 17:29:18.176786",
+ "creation": "2022-01-25 10:30:02.294967",
  "doctype": "DocType",
  "document_type": "Document",
  "editable_grid": 1,
@@ -34,6 +34,7 @@
   "is_term_loan",
   "account_info",
   "mode_of_payment",
+  "disbursement_account",
   "payment_account",
   "column_break_9",
   "loan_account",
@@ -356,12 +357,21 @@
    "fieldtype": "Date",
    "label": "Closure Date",
    "read_only": 1
+  },
+  {
+   "fetch_from": "loan_type.disbursement_account",
+   "fieldname": "disbursement_account",
+   "fieldtype": "Link",
+   "label": "Disbursement Account",
+   "options": "Account",
+   "read_only": 1,
+   "reqd": 1
   }
  ],
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2021-10-12 18:10:32.360818",
+ "modified": "2022-01-25 16:29:16.325501",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan",
@@ -391,5 +401,6 @@
  "search_fields": "posting_date",
  "sort_field": "creation",
  "sort_order": "DESC",
+ "states": [],
  "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/loan_management/doctype/loan/loan.py b/erpnext/loan_management/doctype/loan/loan.py
index f660a24..b798e08 100644
--- a/erpnext/loan_management/doctype/loan/loan.py
+++ b/erpnext/loan_management/doctype/loan/loan.py
@@ -10,6 +10,7 @@
 from frappe.utils import add_months, flt, get_last_day, getdate, now_datetime, nowdate
 
 import erpnext
+from erpnext.accounts.doctype.journal_entry.journal_entry import get_payment_entry
 from erpnext.controllers.accounts_controller import AccountsController
 from erpnext.loan_management.doctype.loan_repayment.loan_repayment import calculate_amounts
 from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import (
@@ -233,17 +234,15 @@
 	loan_type = frappe.get_value('Loan', loan, 'loan_type')
 	write_off_limit = frappe.get_value('Loan Type', loan_type, 'write_off_amount')
 
-	# checking greater than 0 as there may be some minor precision error
-	if not pending_amount:
-		frappe.db.set_value('Loan', loan, 'status', 'Loan Closure Requested')
-	elif pending_amount < write_off_limit:
+	if pending_amount and abs(pending_amount) < write_off_limit:
 		# Auto create loan write off and update status as loan closure requested
 		write_off = make_loan_write_off(loan)
 		write_off.submit()
-		frappe.db.set_value('Loan', loan, 'status', 'Loan Closure Requested')
-	else:
+	elif pending_amount > 0:
 		frappe.throw(_("Cannot close loan as there is an outstanding of {0}").format(pending_amount))
 
+	frappe.db.set_value('Loan', loan, 'status', 'Loan Closure Requested')
+
 @frappe.whitelist()
 def get_loan_application(loan_application):
 	loan = frappe.get_doc("Loan Application", loan_application)
@@ -400,4 +399,39 @@
 	if getdate(date) == get_last_day(date):
 		return get_last_day(add_months(date, 1))
 	else:
-		return add_months(date, 1)
\ No newline at end of file
+		return add_months(date, 1)
+
+@frappe.whitelist()
+def make_refund_jv(loan, amount=0, reference_number=None, reference_date=None, submit=0):
+	loan_details = frappe.db.get_value('Loan', loan, ['applicant_type', 'applicant',
+		'loan_account', 'payment_account', 'posting_date', 'company', 'name',
+		'total_payment', 'total_principal_paid'], as_dict=1)
+
+	loan_details.doctype = 'Loan'
+	loan_details[loan_details.applicant_type.lower()] = loan_details.applicant
+
+	if not amount:
+		amount = flt(loan_details.total_principal_paid - loan_details.total_payment)
+
+		if amount < 0:
+			frappe.throw(_('No excess amount pending for refund'))
+
+	refund_jv = get_payment_entry(loan_details, {
+		"party_type": loan_details.applicant_type,
+		"party_account": loan_details.loan_account,
+		"amount_field_party": 'debit_in_account_currency',
+		"amount_field_bank": 'credit_in_account_currency',
+		"amount": amount,
+		"bank_account": loan_details.payment_account
+	})
+
+	if reference_number:
+		refund_jv.cheque_no = reference_number
+
+	if reference_date:
+		refund_jv.cheque_date = reference_date
+
+	if submit:
+		refund_jv.submit()
+
+	return refund_jv
\ No newline at end of file
diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py
index 1676c21..5ebb2e1 100644
--- a/erpnext/loan_management/doctype/loan/test_loan.py
+++ b/erpnext/loan_management/doctype/loan/test_loan.py
@@ -42,16 +42,17 @@
 		create_loan_type("Personal Loan", 500000, 8.4,
 			is_term_loan=1,
 			mode_of_payment='Cash',
+			disbursement_account='Disbursement Account - _TC',
 			payment_account='Payment Account - _TC',
 			loan_account='Loan Account - _TC',
 			interest_income_account='Interest Income Account - _TC',
 			penalty_income_account='Penalty Income Account - _TC')
 
-		create_loan_type("Stock Loan", 2000000, 13.5, 25, 1, 5, 'Cash', 'Payment Account - _TC', 'Loan Account - _TC',
-			'Interest Income Account - _TC', 'Penalty Income Account - _TC')
+		create_loan_type("Stock Loan", 2000000, 13.5, 25, 1, 5, 'Cash', 'Disbursement Account - _TC',
+			'Payment Account - _TC', 'Loan Account - _TC', 'Interest Income Account - _TC', 'Penalty Income Account - _TC')
 
-		create_loan_type("Demand Loan", 2000000, 13.5, 25, 0, 5, 'Cash', 'Payment Account - _TC', 'Loan Account - _TC',
-			'Interest Income Account - _TC', 'Penalty Income Account - _TC')
+		create_loan_type("Demand Loan", 2000000, 13.5, 25, 0, 5, 'Cash', 'Disbursement Account - _TC',
+			'Payment Account - _TC', 'Loan Account - _TC', 'Interest Income Account - _TC', 'Penalty Income Account - _TC')
 
 		create_loan_security_type()
 		create_loan_security()
@@ -679,6 +680,29 @@
 		loan.load_from_db()
 		self.assertEqual(loan.status, "Loan Closure Requested")
 
+	def test_loan_repayment_against_partially_disbursed_loan(self):
+		pledge = [{
+			"loan_security": "Test Security 1",
+			"qty": 4000.00
+		}]
+
+		loan_application = create_loan_application('_Test Company', self.applicant2, 'Demand Loan', pledge)
+		create_pledge(loan_application)
+
+		loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
+		loan.submit()
+
+		first_date = '2019-10-01'
+		last_date = '2019-10-30'
+
+		make_loan_disbursement_entry(loan.name, loan.loan_amount/2, disbursement_date=first_date)
+
+		loan.load_from_db()
+
+		self.assertEqual(loan.status, "Partially Disbursed")
+		create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 5),
+			flt(loan.loan_amount/3))
+
 	def test_loan_amount_write_off(self):
 		pledge = [{
 			"loan_security": "Test Security 1",
@@ -790,6 +814,18 @@
 			"account_type": "Bank",
 		}).insert(ignore_permissions=True)
 
+	if not frappe.db.exists("Account", "Disbursement Account - _TC"):
+		frappe.get_doc({
+			"doctype": "Account",
+			"company": "_Test Company",
+			"account_name": "Disbursement Account",
+			"root_type": "Asset",
+			"report_type": "Balance Sheet",
+			"currency": "INR",
+			"parent_account": "Bank Accounts - _TC",
+			"account_type": "Bank",
+		}).insert(ignore_permissions=True)
+
 	if not frappe.db.exists("Account", "Interest Income Account - _TC"):
 		frappe.get_doc({
 			"doctype": "Account",
@@ -815,7 +851,7 @@
 		}).insert(ignore_permissions=True)
 
 def create_loan_type(loan_name, maximum_loan_amount, rate_of_interest, penalty_interest_rate=None, is_term_loan=None, grace_period_in_days=None,
-	mode_of_payment=None, payment_account=None, loan_account=None, interest_income_account=None, penalty_income_account=None,
+	mode_of_payment=None, disbursement_account=None, payment_account=None, loan_account=None, interest_income_account=None, penalty_income_account=None,
 	repayment_method=None, repayment_periods=None):
 
 	if not frappe.db.exists("Loan Type", loan_name):
@@ -829,6 +865,7 @@
 			"penalty_interest_rate": penalty_interest_rate,
 			"grace_period_in_days": grace_period_in_days,
 			"mode_of_payment": mode_of_payment,
+			"disbursement_account": disbursement_account,
 			"payment_account": payment_account,
 			"loan_account": loan_account,
 			"interest_income_account": interest_income_account,
diff --git a/erpnext/loan_management/doctype/loan_application/test_loan_application.py b/erpnext/loan_management/doctype/loan_application/test_loan_application.py
index d367e92..640709c 100644
--- a/erpnext/loan_management/doctype/loan_application/test_loan_application.py
+++ b/erpnext/loan_management/doctype/loan_application/test_loan_application.py
@@ -15,7 +15,7 @@
 class TestLoanApplication(unittest.TestCase):
 	def setUp(self):
 		create_loan_accounts()
-		create_loan_type("Home Loan", 500000, 9.2, 0, 1, 0, 'Cash', 'Payment Account - _TC', 'Loan Account - _TC',
+		create_loan_type("Home Loan", 500000, 9.2, 0, 1, 0, 'Cash', 'Disbursement Account - _TC', 'Payment Account - _TC', 'Loan Account - _TC',
 			'Interest Income Account - _TC', 'Penalty Income Account - _TC', 'Repay Over Number of Periods', 18)
 		self.applicant = make_employee("kate_loan@loan.com", "_Test Company")
 		make_salary_structure("Test Salary Structure Loan", "Monthly", employee=self.applicant, currency='INR')
diff --git a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
index e2d758b..df3aadf 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
+++ b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
@@ -122,7 +122,7 @@
 		gle_map.append(
 			self.get_gl_dict({
 				"account": loan_details.loan_account,
-				"against": loan_details.payment_account,
+				"against": loan_details.disbursement_account,
 				"debit": self.disbursed_amount,
 				"debit_in_account_currency": self.disbursed_amount,
 				"against_voucher_type": "Loan",
@@ -137,7 +137,7 @@
 
 		gle_map.append(
 			self.get_gl_dict({
-				"account": loan_details.payment_account,
+				"account": loan_details.disbursement_account,
 				"against": loan_details.loan_account,
 				"credit": self.disbursed_amount,
 				"credit_in_account_currency": self.disbursed_amount,
diff --git a/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py b/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py
index 94ec84e..10be750 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py
+++ b/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py
@@ -44,8 +44,8 @@
 	def setUp(self):
 		create_loan_accounts()
 
-		create_loan_type("Demand Loan", 2000000, 13.5, 25, 0, 5, 'Cash', 'Payment Account - _TC', 'Loan Account - _TC',
-			'Interest Income Account - _TC', 'Penalty Income Account - _TC')
+		create_loan_type("Demand Loan", 2000000, 13.5, 25, 0, 5, 'Cash', 'Disbursement Account - _TC',
+			'Payment Account - _TC', 'Loan Account - _TC', 'Interest Income Account - _TC', 'Penalty Income Account - _TC')
 
 		create_loan_security_type()
 		create_loan_security()
diff --git a/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py b/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py
index 46aaaad..e8c7750 100644
--- a/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py
+++ b/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py
@@ -30,8 +30,8 @@
 	def setUp(self):
 		create_loan_accounts()
 
-		create_loan_type("Demand Loan", 2000000, 13.5, 25, 0, 5, 'Cash', 'Payment Account - _TC', 'Loan Account - _TC',
-			'Interest Income Account - _TC', 'Penalty Income Account - _TC')
+		create_loan_type("Demand Loan", 2000000, 13.5, 25, 0, 5, 'Cash', 'Disbursement Account - _TC',
+			'Payment Account - _TC', 'Loan Account - _TC', 'Interest Income Account - _TC', 'Penalty Income Account - _TC')
 
 		create_loan_security_type()
 		create_loan_security()
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
index 7e997e8..acf3a65 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
@@ -125,7 +125,7 @@
 
 	def update_paid_amount(self):
 		loan = frappe.get_value("Loan", self.against_loan, ['total_amount_paid', 'total_principal_paid',
-			'status', 'is_secured_loan', 'total_payment', 'loan_amount', 'total_interest_payable',
+			'status', 'is_secured_loan', 'total_payment', 'loan_amount', 'disbursed_amount', 'total_interest_payable',
 			'written_off_amount'], as_dict=1)
 
 		loan.update({
@@ -153,7 +153,7 @@
 
 	def mark_as_unpaid(self):
 		loan = frappe.get_value("Loan", self.against_loan, ['total_amount_paid', 'total_principal_paid',
-			'status', 'is_secured_loan', 'total_payment', 'loan_amount', 'total_interest_payable',
+			'status', 'is_secured_loan', 'total_payment', 'loan_amount', 'disbursed_amount', 'total_interest_payable',
 			'written_off_amount'], as_dict=1)
 
 		no_of_repayments = len(self.repayment_details)
diff --git a/erpnext/loan_management/doctype/loan_type/loan_type.js b/erpnext/loan_management/doctype/loan_type/loan_type.js
index 04c89c4..9f9137c 100644
--- a/erpnext/loan_management/doctype/loan_type/loan_type.js
+++ b/erpnext/loan_management/doctype/loan_type/loan_type.js
@@ -15,7 +15,7 @@
 			});
 		});
 
-		$.each(["payment_account", "loan_account"], function (i, field) {
+		$.each(["payment_account", "loan_account", "disbursement_account"], function (i, field) {
 			frm.set_query(field, function () {
 				return {
 					"filters": {
diff --git a/erpnext/loan_management/doctype/loan_type/loan_type.json b/erpnext/loan_management/doctype/loan_type/loan_type.json
index c0a5d2c..00337e4 100644
--- a/erpnext/loan_management/doctype/loan_type/loan_type.json
+++ b/erpnext/loan_management/doctype/loan_type/loan_type.json
@@ -19,9 +19,10 @@
   "description",
   "account_details_section",
   "mode_of_payment",
+  "disbursement_account",
   "payment_account",
-  "loan_account",
   "column_break_12",
+  "loan_account",
   "interest_income_account",
   "penalty_income_account",
   "amended_from"
@@ -79,7 +80,7 @@
   {
    "fieldname": "payment_account",
    "fieldtype": "Link",
-   "label": "Payment Account",
+   "label": "Repayment Account",
    "options": "Account",
    "reqd": 1
   },
@@ -149,15 +150,23 @@
    "fieldtype": "Currency",
    "label": "Auto Write Off Amount ",
    "options": "Company:company:default_currency"
+  },
+  {
+   "fieldname": "disbursement_account",
+   "fieldtype": "Link",
+   "label": "Disbursement Account",
+   "options": "Account",
+   "reqd": 1
   }
  ],
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2021-04-19 18:10:57.368490",
+ "modified": "2022-01-25 16:23:57.009349",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Type",
+ "naming_rule": "By fieldname",
  "owner": "Administrator",
  "permissions": [
   {
@@ -181,5 +190,6 @@
   }
  ],
  "sort_field": "modified",
- "sort_order": "DESC"
+ "sort_order": "DESC",
+ "states": []
 }
\ No newline at end of file
diff --git a/erpnext/manufacturing/report/bom_stock_calculated/bom_stock_calculated.py b/erpnext/manufacturing/report/bom_stock_calculated/bom_stock_calculated.py
index 090a3e7..2693352 100644
--- a/erpnext/manufacturing/report/bom_stock_calculated/bom_stock_calculated.py
+++ b/erpnext/manufacturing/report/bom_stock_calculated/bom_stock_calculated.py
@@ -89,10 +89,10 @@
 			GROUP BY bom_item.item_code""".format(qty_field=qty_field, table=table, conditions=conditions, bom=bom), as_dict=1)
 
 def get_manufacturer_records():
-	details = frappe.get_all('Item Manufacturer', fields = ["manufacturer", "manufacturer_part_no", "parent"])
+	details = frappe.get_all('Item Manufacturer', fields = ["manufacturer", "manufacturer_part_no", "item_code"])
 	manufacture_details = frappe._dict()
 	for detail in details:
-		dic = manufacture_details.setdefault(detail.get('parent'), {})
+		dic = manufacture_details.setdefault(detail.get('item_code'), {})
 		dic.setdefault('manufacturer', []).append(detail.get('manufacturer'))
 		dic.setdefault('manufacturer_part', []).append(detail.get('manufacturer_part_no'))
 
diff --git a/erpnext/manufacturing/report/production_planning_report/production_planning_report.py b/erpnext/manufacturing/report/production_planning_report/production_planning_report.py
index 8368db6..e1e7225 100644
--- a/erpnext/manufacturing/report/production_planning_report/production_planning_report.py
+++ b/erpnext/manufacturing/report/production_planning_report/production_planning_report.py
@@ -172,10 +172,15 @@
 
 		self.purchase_details = {}
 
-		for d in frappe.get_all("Purchase Order Item",
+		purchased_items = frappe.get_all("Purchase Order Item",
 			fields=["item_code", "min(schedule_date) as arrival_date", "qty as arrival_qty", "warehouse"],
-			filters = {"item_code": ("in", self.item_codes), "warehouse": ("in", self.warehouses)},
-			group_by = "item_code, warehouse"):
+			filters={
+				"item_code": ("in", self.item_codes),
+				"warehouse": ("in", self.warehouses),
+				"docstatus": 1,
+			},
+			group_by = "item_code, warehouse")
+		for d in purchased_items:
 			key = (d.item_code, d.warehouse)
 			if key not in self.purchase_details:
 				self.purchase_details.setdefault(key, d)
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index eace7ca..feafecb 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -349,3 +349,4 @@
 erpnext.patches.v14_0.migrate_cost_center_allocations
 erpnext.patches.v13_0.convert_to_website_item_in_item_card_group_template
 erpnext.patches.v13_0.shopping_cart_to_ecommerce
+erpnext.patches.v13_0.update_disbursement_account
diff --git a/erpnext/patches/v13_0/update_disbursement_account.py b/erpnext/patches/v13_0/update_disbursement_account.py
new file mode 100644
index 0000000..c56fa8f
--- /dev/null
+++ b/erpnext/patches/v13_0/update_disbursement_account.py
@@ -0,0 +1,22 @@
+import frappe
+
+
+def execute():
+
+	frappe.reload_doc("loan_management", "doctype", "loan_type")
+	frappe.reload_doc("loan_management", "doctype", "loan")
+
+	loan_type = frappe.qb.DocType("Loan Type")
+	loan = frappe.qb.DocType("Loan")
+
+	frappe.qb.update(
+		loan_type
+	).set(
+		loan_type.disbursement_account, loan_type.payment_account
+	).run()
+
+	frappe.qb.update(
+		loan
+	).set(
+		loan.disbursement_account, loan.payment_account
+	).run()
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py
index 4f097fa..5f836db 100644
--- a/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py
+++ b/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py
@@ -214,6 +214,7 @@
 			create_loan_type("Car Loan", 500000, 8.4,
 				is_term_loan=1,
 				mode_of_payment='Cash',
+				disbursement_account='Disbursement Account - _TC',
 				payment_account='Payment Account - _TC',
 				loan_account='Loan Account - _TC',
 				interest_income_account='Interest Income Account - _TC',
diff --git a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
index 597fd5a..30b604b 100644
--- a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
@@ -370,6 +370,7 @@
 		create_loan_type("Car Loan", 500000, 8.4,
 			is_term_loan=1,
 			mode_of_payment='Cash',
+			disbursement_account='Disbursement Account - _TC',
 			payment_account='Payment Account - _TC',
 			loan_account='Loan Account - _TC',
 			interest_income_account='Interest Income Account - _TC',
diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
index d48cd67..cb79cf8 100644
--- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
+++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
@@ -295,6 +295,10 @@
 		inter_state_supply_details = {}
 
 		for inv, items_based_on_rate in self.items_based_on_tax_rate.items():
+			gst_category = self.invoice_detail_map.get(inv, {}).get('gst_category')
+			place_of_supply = self.invoice_detail_map.get(inv, {}).get('place_of_supply') or '00-Other Territory'
+			export_type = self.invoice_detail_map.get(inv, {}).get('export_type')
+
 			for rate, items in items_based_on_rate.items():
 				for item_code, taxable_value in self.invoice_items.get(inv).items():
 					if item_code in items:
@@ -302,9 +306,8 @@
 							self.report_dict['sup_details']['osup_nil_exmp']['txval'] += taxable_value
 						elif item_code in self.is_non_gst:
 							self.report_dict['sup_details']['osup_nongst']['txval'] += taxable_value
-						elif rate == 0:
+						elif rate == 0 or (gst_category == 'Overseas' and export_type == 'Without Payment of Tax'):
 							self.report_dict['sup_details']['osup_zero']['txval'] += taxable_value
-							#self.report_dict['sup_details']['osup_zero'][key] += tax_amount
 						else:
 							if inv in self.cgst_sgst_invoices:
 								tax_rate = rate/2
@@ -315,9 +318,6 @@
 								self.report_dict['sup_details']['osup_det']['iamt'] += (taxable_value * rate /100)
 								self.report_dict['sup_details']['osup_det']['txval'] += taxable_value
 
-								gst_category = self.invoice_detail_map.get(inv, {}).get('gst_category')
-								place_of_supply = self.invoice_detail_map.get(inv, {}).get('place_of_supply') or '00-Other Territory'
-
 								if gst_category in ['Unregistered', 'Registered Composition', 'UIN Holders'] and \
 								self.gst_details.get("gst_state") != place_of_supply.split("-")[1]:
 									inter_state_supply_details.setdefault((gst_category, place_of_supply), {
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index 42bc0b7..acf048e 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -1375,6 +1375,30 @@
 
 		automatically_fetch_payment_terms(enable=0)
 
+	def test_zero_amount_sales_order_billing_status(self):
+		from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
+
+		so = make_sales_order(uom="Nos", do_not_save=1)
+		so.items[0].rate = 0
+		so.save()
+		so.submit()
+
+		self.assertEqual(so.net_total, 0)
+		self.assertEqual(so.billing_status, 'Not Billed')
+
+		si = create_sales_invoice(qty=10, do_not_save=1)
+		si.price_list = '_Test Price List'
+		si.items[0].rate = 0
+		si.items[0].price_list_rate = 0
+		si.items[0].sales_order = so.name
+		si.items[0].so_detail = so.items[0].name
+		si.save()
+		si.submit()
+
+		self.assertEqual(si.net_total, 0)
+		so.load_from_db()
+		self.assertEqual(so.billing_status, 'Fully Billed')
+
 def automatically_fetch_payment_terms(enable=1):
 	accounts_settings = frappe.get_doc("Accounts Settings")
 	accounts_settings.automatically_fetch_payment_terms = enable
diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.json b/erpnext/selling/doctype/selling_settings/selling_settings.json
index 27bc541..7c4a3f6 100644
--- a/erpnext/selling/doctype/selling_settings/selling_settings.json
+++ b/erpnext/selling/doctype/selling_settings/selling_settings.json
@@ -80,7 +80,7 @@
    "description": "How often should Project and Company be updated based on Sales Transactions?",
    "fieldname": "sales_update_frequency",
    "fieldtype": "Select",
-   "label": "Sales Update Frequency",
+   "label": "Sales Update Frequency in Company and Project",
    "options": "Each Transaction\nDaily\nMonthly",
    "reqd": 1
   },
@@ -171,7 +171,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2021-09-13 12:32:17.004404",
+ "modified": "2022-02-04 15:41:59.939261",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Selling Settings",
@@ -189,5 +189,6 @@
  ],
  "sort_field": "modified",
  "sort_order": "DESC",
+ "states": [],
  "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
index 9204842..df8cadd 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
+++ b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
@@ -4,10 +4,11 @@
 
 
 import frappe
-from frappe.utils import flt
+from frappe.utils import add_to_date, flt, now
 
 from erpnext.accounts.doctype.account.test_account import create_account, get_inventory_account
 from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
+from erpnext.accounts.utils import update_gl_entries_after
 from erpnext.assets.doctype.asset.test_asset import create_asset_category, create_fixed_asset_item
 from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import (
 	get_gl_entries,
@@ -28,7 +29,8 @@
 				"voucher_type": pr.doctype,
 				"voucher_no": pr.name,
 				"item_code": "_Test Item",
-				"warehouse": "Stores - TCP1"
+				"warehouse": "Stores - TCP1",
+				"is_cancelled": 0,
 			},
 			fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
 
@@ -41,14 +43,39 @@
 				"voucher_type": pr.doctype,
 				"voucher_no": pr.name,
 				"item_code": "_Test Item",
-				"warehouse": "Stores - TCP1"
+				"warehouse": "Stores - TCP1",
+				"is_cancelled": 0,
 			},
 			fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
 
 		self.assertEqual(last_sle.qty_after_transaction, last_sle_after_landed_cost.qty_after_transaction)
-
 		self.assertEqual(last_sle_after_landed_cost.stock_value - last_sle.stock_value, 25.0)
 
+		# assert after submit
+		self.assertPurchaseReceiptLCVGLEntries(pr)
+
+		# Mess up cancelled SLE modified timestamp to check
+		# if they aren't effective in any business logic.
+		frappe.db.set_value("Stock Ledger Entry",
+			{
+				"is_cancelled": 1,
+				"voucher_type": pr.doctype,
+				"voucher_no": pr.name
+			},
+			"is_cancelled", 1,
+			modified=add_to_date(now(), hours=1, as_datetime=True, as_string=True)
+		)
+
+		items, warehouses = pr.get_items_and_warehouses()
+		update_gl_entries_after(pr.posting_date, pr.posting_time,
+			warehouses, items, company=pr.company)
+
+		# reassert after reposting
+		self.assertPurchaseReceiptLCVGLEntries(pr)
+
+
+	def assertPurchaseReceiptLCVGLEntries(self, pr):
+
 		gl_entries = get_gl_entries("Purchase Receipt", pr.name)
 
 		self.assertTrue(gl_entries)
@@ -74,8 +101,8 @@
 
 		for gle in gl_entries:
 			if not gle.get('is_cancelled'):
-				self.assertEqual(expected_values[gle.account][0], gle.debit)
-				self.assertEqual(expected_values[gle.account][1], gle.credit)
+				self.assertEqual(expected_values[gle.account][0], gle.debit, msg=f"incorrect debit for {gle.account}")
+				self.assertEqual(expected_values[gle.account][1], gle.credit, msg=f"incorrect credit for {gle.account}")
 
 
 	def test_landed_cost_voucher_against_purchase_invoice(self):
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 1257057..ffdf8c4 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -286,7 +286,7 @@
 				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, "warehouse": d.warehouse}, "stock_value_difference")
+						"voucher_detail_no": d.name, "warehouse": d.warehouse, "is_cancelled": 0}, "stock_value_difference")
 
 					if not stock_value_diff:
 						continue
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.json b/erpnext/stock/doctype/stock_entry/stock_entry.json
index 2f37778..c38dfaa 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.json
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.json
@@ -8,7 +8,6 @@
  "engine": "InnoDB",
  "field_order": [
   "items_section",
-  "title",
   "naming_series",
   "stock_entry_type",
   "outgoing_stock_entry",
@@ -84,14 +83,6 @@
    "oldfieldtype": "Section Break"
   },
   {
-   "fieldname": "title",
-   "fieldtype": "Data",
-   "hidden": 1,
-   "label": "Title",
-   "no_copy": 1,
-   "print_hide": 1
-  },
-  {
    "fieldname": "naming_series",
    "fieldtype": "Select",
    "label": "Series",
@@ -353,9 +344,9 @@
   },
   {
    "fieldname": "scan_barcode",
-   "options": "Barcode",
    "fieldtype": "Data",
-   "label": "Scan Barcode"
+   "label": "Scan Barcode",
+   "options": "Barcode"
   },
   {
    "allow_bulk_edit": 1,
@@ -628,10 +619,11 @@
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2021-08-20 19:19:31.514846",
+ "modified": "2022-02-07 12:55:14.614077",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Entry",
+ "naming_rule": "By \"Naming Series\" field",
  "owner": "Administrator",
  "permissions": [
   {
@@ -698,6 +690,7 @@
  "show_name_in_global_search": 1,
  "sort_field": "modified",
  "sort_order": "DESC",
- "title_field": "title",
+ "states": [],
+ "title_field": "stock_entry_type",
  "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index c51c9bc..a2ef7b4 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -76,7 +76,6 @@
 
 		self.validate_posting_time()
 		self.validate_purpose()
-		self.set_title()
 		self.validate_item()
 		self.validate_customer_provided_item()
 		self.validate_qty()
@@ -1835,14 +1834,6 @@
 
 		return sorted(list(set(get_serial_nos(self.pro_doc.serial_no)) - set(used_serial_nos)))
 
-	def set_title(self):
-		if frappe.flags.in_import and self.title:
-			# Allow updating title during data import/update
-			return
-
-		self.title = self.purpose
-
-
 @frappe.whitelist()
 def move_sample_to_retention_warehouse(company, items):
 	if isinstance(items, str):
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.json b/erpnext/stock/doctype/stock_settings/stock_settings.json
index 33d9a6c..438ec16 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.json
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.json
@@ -5,35 +5,41 @@
  "doctype": "DocType",
  "engine": "InnoDB",
  "field_order": [
+  "defaults_tab",
   "item_defaults_section",
   "item_naming_by",
   "item_group",
   "stock_uom",
-  "default_warehouse",
   "column_break_4",
-  "valuation_method",
+  "default_warehouse",
   "sample_retention_warehouse",
-  "use_naming_series",
-  "naming_series_prefix",
+  "valuation_method",
+  "price_list_defaults_section",
+  "auto_insert_price_list_rate_if_missing",
+  "column_break_12",
+  "update_existing_price_list_rate",
+  "stock_validations_tab",
   "section_break_9",
   "over_delivery_receipt_allowance",
-  "role_allowed_to_over_deliver_receive",
   "mr_qty_allowance",
-  "column_break_12",
-  "auto_insert_price_list_rate_if_missing",
-  "update_existing_price_list_rate",
+  "column_break_121",
+  "role_allowed_to_over_deliver_receive",
   "allow_negative_stock",
   "show_barcode_field",
   "clean_description_html",
   "quality_inspection_settings_section",
   "action_if_quality_inspection_is_not_submitted",
-  "column_break_21",
+  "column_break_23",
   "action_if_quality_inspection_is_rejected",
+  "serial_and_batch_item_settings_tab",
   "section_break_7",
   "automatically_set_serial_nos_based_on_fifo",
   "set_qty_in_transactions_based_on_serial_no_input",
   "column_break_10",
   "disable_serial_no_and_batch_selector",
+  "use_naming_series",
+  "naming_series_prefix",
+  "stock_planning_tab",
   "auto_material_request",
   "auto_indent",
   "column_break_27",
@@ -42,6 +48,7 @@
   "allow_from_dn",
   "column_break_31",
   "allow_from_pr",
+  "stock_closing_tab",
   "control_historical_stock_transactions_section",
   "stock_frozen_upto",
   "stock_frozen_upto_days",
@@ -122,7 +129,7 @@
   {
    "fieldname": "section_break_7",
    "fieldtype": "Section Break",
-   "label": "Serialised and Batch Setting"
+   "label": "Serial & Batch Item Settings"
   },
   {
    "default": "0",
@@ -276,10 +283,6 @@
    "label": "Quality Inspection Settings"
   },
   {
-   "fieldname": "column_break_21",
-   "fieldtype": "Column Break"
-  },
-  {
    "default": "Stop",
    "fieldname": "action_if_quality_inspection_is_rejected",
    "fieldtype": "Select",
@@ -298,6 +301,44 @@
    "fieldname": "update_existing_price_list_rate",
    "fieldtype": "Check",
    "label": "Update Existing Price List Rate"
+  },
+  {
+   "fieldname": "defaults_tab",
+   "fieldtype": "Tab Break",
+   "label": "Defaults"
+  },
+  {
+   "fieldname": "stock_validations_tab",
+   "fieldtype": "Tab Break",
+   "label": "Stock Validations"
+  },
+  {
+   "fieldname": "stock_planning_tab",
+   "fieldtype": "Tab Break",
+   "label": "Stock Planning"
+  },
+  {
+   "fieldname": "stock_closing_tab",
+   "fieldtype": "Tab Break",
+   "label": "Stock Closing"
+  },
+  {
+   "fieldname": "serial_and_batch_item_settings_tab",
+   "fieldtype": "Tab Break",
+   "label": "Serial & Batch Item"
+  },
+  {
+   "fieldname": "column_break_23",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "price_list_defaults_section",
+   "fieldtype": "Section Break",
+   "label": "Price List Defaults"
+  },
+  {
+   "fieldname": "column_break_121",
+   "fieldtype": "Column Break"
   }
  ],
  "icon": "icon-cog",
@@ -305,7 +346,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2021-11-06 19:40:02.183592",
+ "modified": "2022-02-04 15:33:43.692736",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Settings",
@@ -324,5 +365,6 @@
  "quick_entry": 1,
  "sort_field": "modified",
  "sort_order": "ASC",
+ "states": [],
  "track_changes": 1
 }
\ No newline at end of file