Merge branch 'develop' into lcv_multicurrency
diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
index 41f9ce0..a3c29b6 100644
--- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
+++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
@@ -21,6 +21,7 @@
   "book_asset_depreciation_entry_automatically",
   "add_taxes_from_item_tax_template",
   "automatically_fetch_payment_terms",
+  "delete_linked_ledger_entries",
   "deferred_accounting_settings_section",
   "automatically_process_deferred_accounting_entry",
   "book_deferred_entries_based_on",
@@ -219,6 +220,12 @@
    "fieldtype": "Select",
    "label": "Book Deferred Entries Based On",
    "options": "Days\nMonths"
+  },
+  {
+   "default": "0",
+   "fieldname": "delete_linked_ledger_entries",
+   "fieldtype": "Check",
+   "label": "Delete Accounting and Stock Ledger Entries on deletion of Transaction"
   }
  ],
  "icon": "icon-cog",
@@ -226,7 +233,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2020-10-13 11:32:52.268826",
+ "modified": "2021-01-05 13:04:00.118892",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Accounts Settings",
@@ -254,4 +261,4 @@
  "sort_field": "modified",
  "sort_order": "ASC",
  "track_changes": 1
-}
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 4a952a3..06aa20b 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -275,8 +275,11 @@
 
 	supplier: function() {
 		var me = this;
-		if(this.frm.updating_party_details)
+
+		// Do not update if inter company reference is there as the details will already be updated
+		if(this.frm.updating_party_details || this.frm.doc.inter_company_invoice_reference)
 			return;
+
 		erpnext.utils.get_party_details(this.frm, "erpnext.accounts.party.get_party_details",
 			{
 				posting_date: this.frm.doc.posting_date,
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index c64ffd8..451c936 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -57,8 +57,8 @@
   "set_warehouse",
   "rejected_warehouse",
   "col_break_warehouse",
+  "set_from_warehouse",
   "is_subcontracted",
-  "supplier_warehouse",
   "items_section",
   "update_stock",
   "scan_barcode",
@@ -515,6 +515,7 @@
   },
   {
    "depends_on": "update_stock",
+   "description": "Sets 'Accepted Warehouse' in each row of the items table.",
    "fieldname": "set_warehouse",
    "fieldtype": "Link",
    "label": "Set Accepted Warehouse",
@@ -544,17 +545,6 @@
    "print_hide": 1
   },
   {
-   "depends_on": "eval:doc.is_subcontracted==\"Yes\"",
-   "fieldname": "supplier_warehouse",
-   "fieldtype": "Link",
-   "label": "Supplier Warehouse",
-   "no_copy": 1,
-   "options": "Warehouse",
-   "print_hide": 1,
-   "print_width": "50px",
-   "width": "50px"
-  },
-  {
    "fieldname": "items_section",
    "fieldtype": "Section Break",
    "oldfieldtype": "Section Break",
@@ -1232,7 +1222,9 @@
    "fieldname": "inter_company_invoice_reference",
    "fieldtype": "Link",
    "label": "Inter Company Invoice Reference",
+   "no_copy": 1,
    "options": "Sales Invoice",
+   "print_hide": 1,
    "read_only": 1
   },
   {
@@ -1356,13 +1348,25 @@
    "fieldtype": "Link",
    "label": "Represents Company",
    "options": "Company"
+  },
+  {
+   "depends_on": "eval:doc.update_stock && (doc.is_subcontracted==\"Yes\" || doc.is_internal_supplier)",
+   "description": "Sets 'From Warehouse' in each row of the items table.",
+   "fieldname": "set_from_warehouse",
+   "fieldtype": "Link",
+   "label": "Set From Warehouse",
+   "no_copy": 1,
+   "options": "Warehouse",
+   "print_hide": 1,
+   "print_width": "50px",
+   "width": "50px"
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 204,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-12-11 12:46:12.796378",
+ "modified": "2020-12-26 20:49:03.305063",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Purchase Invoice",
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 3c29561..dacd50a 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -480,7 +480,7 @@
 		grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
 
 		if grand_total and not self.is_internal_transfer():
-				# Didnot use base_grand_total to book rounding loss gle
+				# Did not use base_grand_total to book rounding loss gle
 				grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
 					self.precision("grand_total"))
 				gl_entries.append(
@@ -511,8 +511,8 @@
 		voucher_wise_stock_value = {}
 		if self.update_stock:
 			for d in frappe.get_all('Stock Ledger Entry',
-				fields = ["voucher_detail_no", "stock_value_difference"], filters={'voucher_no': self.name}):
-				voucher_wise_stock_value.setdefault(d.voucher_detail_no, d.stock_value_difference)
+				fields = ["voucher_detail_no", "stock_value_difference", "warehouse"], filters={'voucher_no': self.name}):
+				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")
 			if d.category in ('Valuation', 'Total and Valuation')
@@ -563,16 +563,17 @@
 							)
 
 					else:
-						gl_entries.append(
-							self.get_gl_dict({
-								"account": item.expense_account,
-								"against": self.supplier,
-								"debit": warehouse_debit_amount,
-								"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
-								"cost_center": item.cost_center,
-								"project": item.project or self.project
-							}, account_currency, item=item)
-						)
+						if not self.is_internal_transfer():
+							gl_entries.append(
+								self.get_gl_dict({
+									"account": item.expense_account,
+									"against": self.supplier,
+									"debit": warehouse_debit_amount,
+									"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
+									"cost_center": item.cost_center,
+									"project": item.project or self.project
+								}, account_currency, item=item)
+							)
 
 					# Amount added through landed-cost-voucher
 					if landed_cost_entries:
@@ -625,13 +626,14 @@
 							if expense_booked_in_pr:
 								expense_account = service_received_but_not_billed_account
 
-					gl_entries.append(self.get_gl_dict({
-							"account": expense_account,
-							"against": self.supplier,
-							"debit": amount,
-							"cost_center": item.cost_center,
-							"project": item.project or self.project
-						}, account_currency, item=item))
+					if not self.is_internal_transfer():
+						gl_entries.append(self.get_gl_dict({
+								"account": expense_account,
+								"against": self.supplier,
+								"debit": amount,
+								"cost_center": item.cost_center,
+								"project": item.project or self.project
+							}, account_currency, item=item))
 
 					# If asset is bought through this document and not linked to PR
 					if self.update_stock and item.landed_cost_voucher_amount:
@@ -796,10 +798,10 @@
 
 		# Stock ledger value is not matching with the warehouse amount
 		if (self.update_stock and voucher_wise_stock_value.get(item.name) and
-			warehouse_debit_amount != flt(voucher_wise_stock_value.get(item.name), net_amt_precision)):
+			warehouse_debit_amount != flt(voucher_wise_stock_value.get((item.name, item.warehouse)), net_amt_precision)):
 
 			cost_of_goods_sold_account = self.get_company_default("default_expense_account")
-			stock_amount = flt(voucher_wise_stock_value.get(item.name), net_amt_precision)
+			stock_amount = flt(voucher_wise_stock_value.get((item.name, item.warehouse)), net_amt_precision)
 			stock_adjustment_amt = warehouse_debit_amount - stock_amount
 
 			gl_entries.append(
diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
index f6d76e5..1f7853d 100644
--- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
+++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "autoname": "hash",
  "creation": "2013-05-22 12:43:10",
  "doctype": "DocType",
@@ -87,6 +88,7 @@
   "po_detail",
   "purchase_receipt",
   "pr_detail",
+  "sales_invoice_item",
   "item_weight_details",
   "weight_per_unit",
   "total_weight",
@@ -553,8 +555,8 @@
    "fieldtype": "Link",
    "hidden": 1,
    "label": "Brand",
-   "print_hide": 1,
-   "options": "Brand"
+   "options": "Brand",
+   "print_hide": 1
   },
   {
    "fetch_from": "item_code.item_group",
@@ -562,9 +564,9 @@
    "fieldname": "item_group",
    "fieldtype": "Link",
    "label": "Item Group",
+   "options": "Item Group",
    "print_hide": 1,
-   "read_only": 1,
-   "options": "Item Group"
+   "read_only": 1
   },
   {
    "description": "Tax detail table fetched from item master as a string and stored in this field.\nUsed for Taxes and Charges",
@@ -759,10 +761,11 @@
    "read_only": 1
   },
   {
+   "depends_on": "eval:parent.is_internal_supplier && parent.update_stock",
    "fieldname": "from_warehouse",
    "fieldtype": "Link",
    "ignore_user_permissions": 1,
-   "label": "Supplier Warehouse",
+   "label": "From Warehouse",
    "options": "Warehouse"
   },
   {
@@ -779,11 +782,20 @@
    "no_copy": 1,
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "fieldname": "sales_invoice_item",
+   "fieldtype": "Data",
+   "label": "Sales Invoice Item",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1
   }
  ],
  "idx": 1,
  "istable": 1,
- "modified": "2020-08-20 11:48:01.398356",
+ "links": [],
+ "modified": "2020-12-26 17:20:36.415791",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Purchase Invoice Item",
@@ -791,4 +803,4 @@
  "permissions": [],
  "sort_field": "modified",
  "sort_order": "DESC"
-}
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 72199a9..f2a62cd 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -130,16 +130,15 @@
 
 		this.set_default_print_format();
 		if (doc.docstatus == 1 && !doc.inter_company_invoice_reference) {
-			frappe.model.with_doc("Customer", me.frm.doc.customer, function() {
-				var customer = frappe.model.get_doc("Customer", me.frm.doc.customer);
-				var internal = customer.is_internal_customer;
-				var disabled = customer.disabled;
-				if (internal == 1 && disabled == 0) {
-					me.frm.add_custom_button("Inter Company Invoice", function() {
-						me.make_inter_company_invoice();
-					}, __('Create'));
-				}
-			});
+			let internal = me.frm.doc.is_internal_customer;
+			if (internal) {
+				let button_label = (me.frm.doc.company === me.frm.doc.represents_company) ? "Internal Purchase Invoice" :
+					"Inter Company Purchase Invoice";
+
+				me.frm.add_custom_button(button_label, function() {
+					me.make_inter_company_invoice();
+				}, __('Create'));
+			}
 		}
 	},
 
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index 6799fb9..447cee4 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -60,6 +60,8 @@
   "ignore_pricing_rule",
   "sec_warehouse",
   "set_warehouse",
+  "column_break_55",
+  "set_target_warehouse",
   "items_section",
   "update_stock",
   "scan_barcode",
@@ -1969,13 +1971,24 @@
    "label": "Represents Company",
    "options": "Company",
    "read_only": 1
+  },
+  {
+   "fieldname": "column_break_55",
+   "fieldtype": "Column Break"
+  },
+  {
+   "depends_on": "eval: doc.is_internal_customer && doc.update_stock",
+   "fieldname": "set_target_warehouse",
+   "fieldtype": "Link",
+   "label": "Set Target Warehouse",
+   "options": "Warehouse"
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 181,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-12-11 12:48:31.769958",
+ "modified": "2020-12-25 22:57:32.555067",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Sales Invoice",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 566734e..7116a6a 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -6,7 +6,7 @@
 import frappe.defaults
 from frappe.utils import cint, flt, getdate, add_days, cstr, nowdate, get_link_to_form, formatdate
 from frappe import _, msgprint, throw
-from erpnext.accounts.party import get_party_account, get_due_date
+from erpnext.accounts.party import get_party_account, get_due_date, get_party_details
 from frappe.model.mapper import get_mapped_doc
 from erpnext.controllers.selling_controller import SellingController
 from erpnext.accounts.utils import get_account_currency
@@ -21,6 +21,8 @@
 from erpnext.accounts.doctype.loyalty_program.loyalty_program import \
 	get_loyalty_program_details_with_points, get_loyalty_details, validate_loyalty_points
 from erpnext.accounts.deferred_revenue import validate_service_stop_date
+from frappe.model.utils import get_fetch_values
+from frappe.contacts.doctype.address.address import get_address_display
 
 from erpnext.healthcare.utils import manage_invoice_submit_cancel
 
@@ -1534,7 +1536,7 @@
 	details = get_inter_company_details(doc, doctype)
 	price_list = doc.selling_price_list if doctype in ["Sales Invoice", "Sales Order", "Delivery Note"] else doc.buying_price_list
 	valid_price_list = frappe.db.get_value("Price List", {"name": price_list, "buying": 1, "selling": 1})
-	if not valid_price_list:
+	if not valid_price_list and not doc.is_internal_transfer():
 		frappe.throw(_("Selected Price List should have buying and selling fields checked."))
 
 	party = details.get("party")
@@ -1557,6 +1559,7 @@
 	if doctype in ["Sales Invoice", "Sales Order"]:
 		source_doc = frappe.get_doc(doctype, source_name)
 		target_doctype = "Purchase Invoice" if doctype == "Sales Invoice" else "Purchase Order"
+		target_detail_field = "sales_invoice_item" if doctype == "Sales Invoice" else "sales_order_item"
 		source_document_warehouse_field = 'target_warehouse'
 		target_document_warehouse_field = 'from_warehouse'
 	else:
@@ -1570,6 +1573,7 @@
 
 	def set_missing_values(source, target):
 		target.run_method("set_missing_values")
+		set_purchase_references(target)
 
 	def update_details(source_doc, target_doc, source_parent):
 		target_doc.inter_company_invoice_reference = source_doc.name
@@ -1577,19 +1581,38 @@
 			currency = frappe.db.get_value('Supplier', details.get('party'), 'default_currency')
 			target_doc.company = details.get("company")
 			target_doc.supplier = details.get("party")
+			target_doc.is_internal_supplier = 1
+			target_doc.ignore_pricing_rule = 1
 			target_doc.buying_price_list = source_doc.selling_price_list
 
+			# Invert Addresses
+			update_address(target_doc, 'supplier_address', 'address_display', source_doc.company_address)
+			update_address(target_doc, 'shipping_address', 'shipping_address_display', source_doc.customer_address)
+
 			if currency:
 				target_doc.currency = currency
+
+			update_taxes(target_doc, party=target_doc.supplier, party_type='Supplier', company=target_doc.company,
+				doctype=target_doc.doctype, party_address=target_doc.supplier_address,
+				company_address=target_doc.shipping_address)
+
 		else:
 			currency = frappe.db.get_value('Customer', details.get('party'), 'default_currency')
 			target_doc.company = details.get("company")
 			target_doc.customer = details.get("party")
 			target_doc.selling_price_list = source_doc.buying_price_list
 
+			update_address(target_doc, 'company_address', 'company_address_display', source_doc.supplier_address)
+			update_address(target_doc, 'shipping_address_name', 'shipping_address', source_doc.shipping_address)
+			update_address(target_doc, 'customer_address', 'address_display', source_doc.shipping_address)
+
 			if currency:
 				target_doc.currency = currency
 
+			update_taxes(target_doc, party=target_doc.customer, party_type='Customer', company=target_doc.company,
+				doctype=target_doc.doctype, party_address=target_doc.customer_address,
+				company_address=target_doc.company_address, shipping_address_name=target_doc.shipping_address_name)
+
 	item_field_map = {
 		"doctype": target_doctype + " Item",
 		"field_no_map": [
@@ -1597,25 +1620,33 @@
 			"expense_account",
 			"cost_center",
 			"warehouse"
-		]
+		],
+		"field_map": {
+			'rate': 'rate',
+		}
 	}
 
-	if source_doc.get('update_stock'):
-		item_field_map.update({
-			'field_map': {
-				source_document_warehouse_field: target_document_warehouse_field,
-				'batch_no': 'batch_no',
-				'serial_no': 'serial_no'
-			}
+	if doctype in ["Sales Invoice", "Sales Order"]:
+		item_field_map["field_map"].update({
+			"name": target_detail_field,
 		})
 
+	if source_doc.get('update_stock'):
+		item_field_map["field_map"].update({
+			source_document_warehouse_field: target_document_warehouse_field,
+			'batch_no': 'batch_no',
+			'serial_no': 'serial_no'
+		})
 
 	doclist = get_mapped_doc(doctype, source_name,	{
 		doctype: {
 			"doctype": target_doctype,
 			"postprocess": update_details,
+			"set_target_warehouse": "set_from_warehouse",
 			"field_no_map": [
-				"taxes_and_charges"
+				"taxes_and_charges",
+				"set_warehouse",
+				"shipping_address"
 			]
 		},
 		doctype +" Item": item_field_map
@@ -1624,6 +1655,110 @@
 
 	return doclist
 
+def set_purchase_references(doc):
+	# add internal PO or PR links if any
+	if doc.is_internal_transfer():
+		if doc.doctype == 'Purchase Receipt':
+			so_item_map = get_delivery_note_details(doc.inter_company_invoice_reference)
+
+			if so_item_map:
+				pd_item_map, parent_child_map, warehouse_map = \
+					get_pd_details('Purchase Order Item', so_item_map, 'sales_order_item')
+
+				update_pr_items(doc, so_item_map, pd_item_map, parent_child_map, warehouse_map)
+
+		elif doc.doctype == 'Purchase Invoice':
+			dn_item_map, so_item_map = get_sales_invoice_details(doc.inter_company_invoice_reference)
+			# First check for Purchase receipt
+			if list(dn_item_map.values()):
+				pd_item_map, parent_child_map, warehouse_map = \
+					get_pd_details('Purchase Receipt Item', dn_item_map, 'delivery_note_item')
+
+				update_pi_items(doc, 'pr_detail', 'purchase_receipt',
+					dn_item_map, pd_item_map, parent_child_map, warehouse_map)
+
+			if list(so_item_map.values()):
+				pd_item_map, parent_child_map, warehouse_map = \
+					get_pd_details('Purchase Order Item', so_item_map, 'sales_order_item')
+
+				update_pi_items(doc, 'po_detail', 'purchase_order',
+					so_item_map, pd_item_map, parent_child_map, warehouse_map)
+
+def update_pi_items(doc, detail_field, parent_field, sales_item_map,
+	purchase_item_map, parent_child_map, warehouse_map):
+	for item in doc.get('items'):
+		item.set(detail_field, purchase_item_map.get(sales_item_map.get(item.sales_invoice_item)))
+		item.set(parent_field, parent_child_map.get(sales_item_map.get(item.sales_invoice_item)))
+		if doc.update_stock:
+			item.warehouse = warehouse_map.get(sales_item_map.get(item.sales_invoice_item))
+
+def update_pr_items(doc, sales_item_map, purchase_item_map, parent_child_map, warehouse_map):
+	for item in doc.get('items'):
+		item.purchase_order_item = purchase_item_map.get(sales_item_map.get(item.delivery_note_item))
+		item.warehouse = warehouse_map.get(sales_item_map.get(item.delivery_note_item))
+		item.purchase_order = parent_child_map.get(sales_item_map.get(item.delivery_note_item))
+
+def get_delivery_note_details(internal_reference):
+	so_item_map = {}
+
+	si_item_details = frappe.get_all('Delivery Note Item', fields=['name', 'so_detail'],
+		filters={'parent': internal_reference})
+
+	for d in si_item_details:
+		so_item_map.setdefault(d.name, d.so_detail)
+
+	return so_item_map
+
+def get_sales_invoice_details(internal_reference):
+	dn_item_map = {}
+	so_item_map = {}
+
+	si_item_details = frappe.get_all('Sales Invoice Item', fields=['name', 'so_detail',
+		'dn_detail'], filters={'parent': internal_reference})
+
+	for d in si_item_details:
+		if d.dn_detail:
+			dn_item_map.setdefault(d.name, d.dn_detail)
+		if d.so_detail:
+			so_item_map.setdefault(d.name, d.so_detail)
+
+	return dn_item_map, so_item_map
+
+def get_pd_details(doctype, sd_detail_map, sd_detail_field):
+	pd_item_map = {}
+	accepted_warehouse_map = {}
+	parent_child_map = {}
+
+	pd_item_details = frappe.get_all(doctype,
+		fields=[sd_detail_field, 'name', 'warehouse', 'parent'], filters={sd_detail_field: ('in', list(sd_detail_map.values()))})
+
+	for d in pd_item_details:
+		pd_item_map.setdefault(d.get(sd_detail_field), d.name)
+		parent_child_map.setdefault(d.get(sd_detail_field), d.parent)
+		accepted_warehouse_map.setdefault(d.get(sd_detail_field), d.warehouse)
+
+	return pd_item_map, parent_child_map, accepted_warehouse_map
+
+def update_taxes(doc, party=None, party_type=None, company=None, doctype=None, party_address=None,
+	company_address=None, shipping_address_name=None, master_doctype=None):
+	# Update Party Details
+	party_details = get_party_details(party=party, party_type=party_type, company=company,
+		doctype=doctype, party_address=party_address, company_address=company_address,
+		shipping_address=shipping_address_name)
+
+	# Update taxes and charges if any
+	doc.taxes_and_charges = party_details.get('taxes_and_charges')
+	doc.set('taxes', party_details.get('taxes'))
+
+def update_address(doc, address_field, address_display_field, address_name):
+	doc.set(address_field, address_name)
+	fetch_values = get_fetch_values(doc.doctype, address_field, address_name)
+
+	for key, value in fetch_values.items():
+		doc.set(key, value)
+
+	doc.set(address_display_field, get_address_display(doc.get(address_field)))
+
 @frappe.whitelist()
 def get_loyalty_programs(customer):
 	''' sets applicable loyalty program to the customer or returns a list of applicable programs '''
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 3a6dbeb..e94e2cd 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -22,6 +22,7 @@
 from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
 from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
 from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
+from erpnext.stock.utils import get_incoming_rate
 
 class TestSalesInvoice(unittest.TestCase):
 	def make(self):
@@ -688,7 +689,7 @@
 		self.assertTrue(gle)
 
 	def test_pos_gl_entry_with_perpetual_inventory(self):
-		make_pos_profile(company="_Test Company with perpetual inventory", income_account = "Sales - TCP1", 
+		make_pos_profile(company="_Test Company with perpetual inventory", income_account = "Sales - TCP1",
 			expense_account = "Cost of Goods Sold - TCP1", warehouse="Stores - TCP1", cost_center = "Main - TCP1", write_off_account="_Test Write Off - TCP1")
 
 		pr = make_purchase_receipt(company= "_Test Company with perpetual inventory", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
@@ -745,7 +746,7 @@
 		self.assertEqual(pos_return.get('payments')[0].amount, -1000)
 
 	def test_pos_change_amount(self):
-		make_pos_profile(company="_Test Company with perpetual inventory", income_account = "Sales - TCP1", 
+		make_pos_profile(company="_Test Company with perpetual inventory", income_account = "Sales - TCP1",
 			expense_account = "Cost of Goods Sold - TCP1", warehouse="Stores - TCP1", cost_center = "Main - TCP1", write_off_account="_Test Write Off - TCP1")
 
 		pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",
@@ -1770,59 +1771,82 @@
 		self.assertEqual(target_doc.company, "_Test Company 1")
 		self.assertEqual(target_doc.supplier, "_Test Internal Supplier")
 
-	# def test_internal_transfer_gl_entry(self):
-	# 	## Create internal transfer account
-	# 	account = create_account(account_name="Unrealized Profit",
-	# 		parent_account="Current Liabilities - TCP1", company="_Test Company with perpetual inventory")
+	def test_internal_transfer_gl_entry(self):
+		## Create internal transfer account
+		account = create_account(account_name="Unrealized Profit",
+			parent_account="Current Liabilities - TCP1", company="_Test Company with perpetual inventory")
 
-	# 	frappe.db.set_value('Company', '_Test Company with perpetual inventory',
-	# 		'unrealized_profit_loss_account', account)
+		frappe.db.set_value('Company', '_Test Company with perpetual inventory',
+			'unrealized_profit_loss_account', account)
 
-	# 	customer = create_internal_customer("_Test Internal Customer 2", "_Test Company with perpetual inventory",
-	# 		"_Test Company with perpetual inventory")
+		customer = create_internal_customer("_Test Internal Customer 2", "_Test Company with perpetual inventory",
+			"_Test Company with perpetual inventory")
 
-	# 	create_internal_supplier("_Test Internal Supplier 2", "_Test Company with perpetual inventory",
-	# 		"_Test Company with perpetual inventory")
+		create_internal_supplier("_Test Internal Supplier 2", "_Test Company with perpetual inventory",
+			"_Test Company with perpetual inventory")
 
-	# 	si = create_sales_invoice(
-	# 		company = "_Test Company with perpetual inventory",
-	# 		customer = customer,
-	# 		debit_to = "Debtors - TCP1",
-	# 		warehouse = "Stores - TCP1",
-	# 		income_account = "Sales - TCP1",
-	# 		expense_account = "Cost of Goods Sold - TCP1",
-	# 		cost_center = "Main - TCP1",
-	# 		currency = "INR",
-	# 		do_not_save = 1
-	# 	)
+		si = create_sales_invoice(
+			company = "_Test Company with perpetual inventory",
+			customer = customer,
+			debit_to = "Debtors - TCP1",
+			warehouse = "Stores - TCP1",
+			income_account = "Sales - TCP1",
+			expense_account = "Cost of Goods Sold - TCP1",
+			cost_center = "Main - TCP1",
+			currency = "INR",
+			do_not_save = 1
+		)
 
-	# 	si.selling_price_list = "_Test Price List Rest of the World"
-	# 	si.update_stock = 1
-	# 	si.items[0].target_warehouse = 'Work In Progress - TCP1'
-	# 	add_taxes(si)
-	# 	si.save()
-	# 	si.submit()
+		si.selling_price_list = "_Test Price List Rest of the World"
+		si.update_stock = 1
+		si.items[0].target_warehouse = 'Work In Progress - TCP1'
+		add_taxes(si)
+		si.save()
 
-	# 	target_doc = make_inter_company_transaction("Sales Invoice", si.name)
-	# 	target_doc.company = '_Test Company with perpetual inventory'
-	# 	target_doc.items[0].warehouse = 'Finished Goods - TCP1'
-	# 	add_taxes(target_doc)
-	# 	target_doc.save()
-	# 	target_doc.submit()
+		rate = 0.0
+		for d in si.get('items'):
+			rate = get_incoming_rate({
+				"item_code": d.item_code,
+				"warehouse": d.warehouse,
+				"posting_date": si.posting_date,
+				"posting_time": si.posting_time,
+				"qty": -1 * flt(d.get('stock_qty')),
+				"serial_no": d.serial_no,
+				"company": si.company,
+				"voucher_type": 'Sales Invoice',
+				"voucher_no": si.name,
+				"allow_zero_valuation": d.get("allow_zero_valuation")
+			}, raise_error_if_no_rate=False)
 
-	# 	si_gl_entries = [
-	# 		["_Test Account Excise Duty - TCP1", 0.0, 12.0, nowdate()],
-	# 		["Unrealized Profit - TCP1", 12.0, 0.0, nowdate()]
-	# 	]
+			rate = flt(rate, 2)
 
-	# 	check_gl_entries(self, si.name, si_gl_entries, add_days(nowdate(), -1))
+		si.submit()
 
-	# 	pi_gl_entries = [
-	# 		["_Test Account Excise Duty - TCP1", 12.0 , 0.0, nowdate()],
-	# 		["Unrealized Profit - TCP1", 0.0, 12.0, nowdate()]
-	# 	]
+		target_doc = make_inter_company_transaction("Sales Invoice", si.name)
+		target_doc.company = '_Test Company with perpetual inventory'
+		target_doc.items[0].warehouse = 'Finished Goods - TCP1'
+		add_taxes(target_doc)
+		target_doc.save()
+		target_doc.submit()
 
-	# 	check_gl_entries(self, target_doc.name, pi_gl_entries, add_days(nowdate(), -1))
+		tax_amount = flt(rate * (12/100), 2)
+		si_gl_entries = [
+			["_Test Account Excise Duty - TCP1", 0.0, tax_amount, nowdate()],
+			["Unrealized Profit - TCP1", tax_amount, 0.0, nowdate()]
+		]
+
+		check_gl_entries(self, si.name, si_gl_entries, add_days(nowdate(), -1))
+
+		pi_gl_entries = [
+			["_Test Account Excise Duty - TCP1", tax_amount , 0.0, nowdate()],
+			["Unrealized Profit - TCP1", 0.0, tax_amount, nowdate()]
+		]
+
+		# Sale and Purchase both should be at valuation rate
+		self.assertEqual(si.items[0].rate, rate)
+		self.assertEqual(target_doc.items[0].rate, rate)
+
+		check_gl_entries(self, target_doc.name, pi_gl_entries, add_days(nowdate(), -1))
 
 	def test_eway_bill_json(self):
 		si = make_sales_invoice_for_ewaybill()
diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
index 3695075..7a98aff 100644
--- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
+++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
@@ -565,11 +565,12 @@
    "print_hide": 1
   },
   {
+   "depends_on": "eval: parent.is_internal_customer && parent.update_stock",
    "fieldname": "target_warehouse",
    "fieldtype": "Link",
    "hidden": 1,
    "ignore_user_permissions": 1,
-   "label": "Customer Warehouse (Optional)",
+   "label": "Target Warehouse",
    "no_copy": 1,
    "options": "Warehouse",
    "print_hide": 1
@@ -815,7 +816,7 @@
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-09-23 19:59:04.879322",
+ "modified": "2020-12-26 17:25:04.090630",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Sales Invoice Item",
diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py
index b46de6c..429a9f3 100644
--- a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py
+++ b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py
@@ -34,6 +34,9 @@
 
 	validate_disabled(doc)
 
+	# Validate with existing taxes and charges template for unique tax category
+	validate_for_tax_category(doc)
+
 	for tax in doc.get("taxes"):
 		validate_taxes_and_charges(tax)
 		validate_inclusive_tax(tax, doc)
@@ -41,3 +44,7 @@
 def validate_disabled(doc):
 	if doc.is_default and doc.disabled:
 		frappe.throw(_("Disabled template must not be default template"))
+
+def validate_for_tax_category(doc):
+	if frappe.db.exists(doc.doctype, {"company": doc.company, "tax_category": doc.tax_category, "disabled": 0}):
+		frappe.throw(_("A template with tax category {0} already exists. Only one template is allowed with each tax category").format(frappe.bold(doc.tax_category)))
diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
index eeb5140..cb4d9b4 100644
--- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
+++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
@@ -49,7 +49,8 @@
 		elif d.po_detail:
 			purchase_receipt = ", ".join(po_pr_map.get(d.po_detail, []))
 
-		expense_account = d.expense_account or aii_account_map.get(d.company)
+		expense_account = d.unrealized_profit_loss_account or d.expense_account \
+			or aii_account_map.get(d.company)
 
 		row = {
 			'item_code': d.item_code,
@@ -315,6 +316,7 @@
 			`tabPurchase Invoice Item`.`name`, `tabPurchase Invoice Item`.`parent`,
 			`tabPurchase Invoice`.posting_date, `tabPurchase Invoice`.credit_to, `tabPurchase Invoice`.company,
 			`tabPurchase Invoice`.supplier, `tabPurchase Invoice`.remarks, `tabPurchase Invoice`.base_net_total,
+			`tabPurchase Invoice`.unrealized_profit_loss_account,
 			`tabPurchase Invoice Item`.`item_code`, `tabPurchase Invoice Item`.description,
 			`tabPurchase Invoice Item`.`item_name`, `tabPurchase Invoice Item`.`item_group`,
 			`tabPurchase Invoice Item`.`project`, `tabPurchase Invoice Item`.`purchase_order`,
diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
index f54ceb0..998003a 100644
--- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
+++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
@@ -76,7 +76,7 @@
 			'company': d.company,
 			'sales_order': d.sales_order,
 			'delivery_note': d.delivery_note,
-			'income_account': d.income_account,
+			'income_account': d.unrealized_profit_loss_account or d.income_account,
 			'cost_center': d.cost_center,
 			'stock_qty': d.stock_qty,
 			'stock_uom': d.stock_uom
@@ -379,6 +379,7 @@
 		select
 			`tabSales Invoice Item`.name, `tabSales Invoice Item`.parent,
 			`tabSales Invoice`.posting_date, `tabSales Invoice`.debit_to,
+			`tabSales Invoice`.unrealized_profit_loss_account,
 			`tabSales Invoice`.project, `tabSales Invoice`.customer, `tabSales Invoice`.remarks,
 			`tabSales Invoice`.territory, `tabSales Invoice`.company, `tabSales Invoice`.base_net_total,
 			`tabSales Invoice Item`.item_code, `tabSales Invoice Item`.description,
diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py
index 9399e70..8ac749d 100644
--- a/erpnext/accounts/report/purchase_register/purchase_register.py
+++ b/erpnext/accounts/report/purchase_register/purchase_register.py
@@ -14,13 +14,15 @@
 	if not filters: filters = {}
 
 	invoice_list = get_invoices(filters, additional_query_columns)
-	columns, expense_accounts, tax_accounts = get_columns(invoice_list, additional_table_columns)
+	columns, expense_accounts, tax_accounts, unrealized_profit_loss_accounts \
+		= get_columns(invoice_list, additional_table_columns)
 
 	if not invoice_list:
 		msgprint(_("No record found"))
 		return columns, invoice_list
 
 	invoice_expense_map = get_invoice_expense_map(invoice_list)
+	internal_invoice_map = get_internal_invoice_map(invoice_list)
 	invoice_expense_map, invoice_tax_map = get_invoice_tax_map(invoice_list,
 		invoice_expense_map, expense_accounts)
 	invoice_po_pr_map = get_invoice_po_pr_map(invoice_list)
@@ -52,10 +54,17 @@
 		# map expense values
 		base_net_total = 0
 		for expense_acc in expense_accounts:
-			expense_amount = flt(invoice_expense_map.get(inv.name, {}).get(expense_acc))
+			if inv.is_internal_supplier and inv.company == inv.represents_company:
+				expense_amount = 0
+			else:
+				expense_amount = flt(invoice_expense_map.get(inv.name, {}).get(expense_acc))
 			base_net_total += expense_amount
 			row.append(expense_amount)
 
+		# Add amount in unrealized account
+		for account in unrealized_profit_loss_accounts:
+			row.append(flt(internal_invoice_map.get((inv.name, account))))
+
 		# net total
 		row.append(base_net_total or inv.base_net_total)
 
@@ -96,7 +105,8 @@
 			"width": 80
 		}
 	]
-	expense_accounts = tax_accounts = expense_columns = tax_columns = []
+	expense_accounts = tax_accounts = expense_columns = tax_columns = unrealized_profit_loss_accounts = \
+		unrealized_profit_loss_account_columns = []
 
 	if invoice_list:
 		expense_accounts = frappe.db.sql_list("""select distinct expense_account
@@ -112,17 +122,25 @@
 			and parent in (%s) order by account_head""" %
 			', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]))
 
+		unrealized_profit_loss_accounts = frappe.db.sql_list("""SELECT distinct unrealized_profit_loss_account
+			from `tabPurchase Invoice` where docstatus = 1 and name in (%s)
+			and ifnull(unrealized_profit_loss_account, '') != ''
+			order by unrealized_profit_loss_account""" %
+			', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]))
 
 	expense_columns = [(account + ":Currency/currency:120") for account in expense_accounts]
+	unrealized_profit_loss_account_columns = [(account + ":Currency/currency:120") for account in unrealized_profit_loss_accounts]
+
 	for account in tax_accounts:
 		if account not in expense_accounts:
 			tax_columns.append(account + ":Currency/currency:120")
 
-	columns = columns + expense_columns + [_("Net Total") + ":Currency/currency:120"] + tax_columns + \
+	columns = columns + expense_columns + unrealized_profit_loss_account_columns + \
+		[_("Net Total") + ":Currency/currency:120"] + tax_columns + \
 		[_("Total Tax") + ":Currency/currency:120", _("Grand Total") + ":Currency/currency:120",
 			_("Rounded Total") + ":Currency/currency:120", _("Outstanding Amount") + ":Currency/currency:120"]
 
-	return columns, expense_accounts, tax_accounts
+	return columns, expense_accounts, tax_accounts, unrealized_profit_loss_accounts
 
 def get_conditions(filters):
 	conditions = ""
@@ -199,6 +217,19 @@
 
 	return invoice_expense_map
 
+def get_internal_invoice_map(invoice_list):
+	unrealized_amount_details = frappe.db.sql("""SELECT name, unrealized_profit_loss_account,
+		base_net_total as amount from `tabPurchase Invoice` where name in (%s)
+		and is_internal_supplier = 1 and company = represents_company""" %
+		', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
+
+	internal_invoice_map = {}
+	for d in unrealized_amount_details:
+		if d.unrealized_profit_loss_account:
+			internal_invoice_map.setdefault((d.name, d.unrealized_profit_loss_account), d.amount)
+
+	return internal_invoice_map
+
 def get_invoice_tax_map(invoice_list, invoice_expense_map, expense_accounts):
 	tax_details = frappe.db.sql("""
 		select parent, account_head, case add_deduct_tax when "Add" then sum(base_tax_amount_after_discount_amount)
diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py
index b6e61b1..cb2c98b 100644
--- a/erpnext/accounts/report/sales_register/sales_register.py
+++ b/erpnext/accounts/report/sales_register/sales_register.py
@@ -15,13 +15,14 @@
 	if not filters: filters = frappe._dict({})
 
 	invoice_list = get_invoices(filters, additional_query_columns)
-	columns, income_accounts, tax_accounts = get_columns(invoice_list, additional_table_columns)
+	columns, income_accounts, tax_accounts, unrealized_profit_loss_accounts = get_columns(invoice_list, additional_table_columns)
 
 	if not invoice_list:
 		msgprint(_("No record found"))
 		return columns, invoice_list
 
 	invoice_income_map = get_invoice_income_map(invoice_list)
+	internal_invoice_map = get_internal_invoice_map(invoice_list)
 	invoice_income_map, invoice_tax_map = get_invoice_tax_map(invoice_list,
 		invoice_income_map, income_accounts)
 	#Cost Center & Warehouse Map
@@ -70,12 +71,22 @@
 		# map income values
 		base_net_total = 0
 		for income_acc in income_accounts:
-			income_amount = flt(invoice_income_map.get(inv.name, {}).get(income_acc))
+			if inv.is_internal_customer and inv.company == inv.represents_company:
+				income_amount = 0
+			else:
+				income_amount = flt(invoice_income_map.get(inv.name, {}).get(income_acc))
+
 			base_net_total += income_amount
 			row.update({
 				frappe.scrub(income_acc): income_amount
 			})
 
+		# Add amount in unrealized account
+		for account in unrealized_profit_loss_accounts:
+			row.update({
+				frappe.scrub(account): flt(internal_invoice_map.get((inv.name, account)))
+			})
+
 		# net total
 		row.update({'net_total': base_net_total or inv.base_net_total})
 
@@ -230,6 +241,8 @@
 	tax_accounts = []
 	income_columns = []
 	tax_columns = []
+	unrealized_profit_loss_accounts = []
+	unrealized_profit_loss_account_columns = []
 
 	if invoice_list:
 		income_accounts = frappe.db.sql_list("""select distinct income_account
@@ -243,12 +256,18 @@
 			and parent in (%s) order by account_head""" %
 			', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]))
 
+		unrealized_profit_loss_accounts = frappe.db.sql_list("""SELECT distinct unrealized_profit_loss_account
+			from `tabSales Invoice` where docstatus = 1 and name in (%s)
+			and ifnull(unrealized_profit_loss_account, '') != ''
+			order by unrealized_profit_loss_account""" %
+			', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]))
+
 	for account in income_accounts:
 		income_columns.append({
 			"label": account,
 			"fieldname": frappe.scrub(account),
 			"fieldtype": "Currency",
-			"options": 'currency',
+			"options": "currency",
 			"width": 120
 		})
 
@@ -258,15 +277,24 @@
 				"label": account,
 				"fieldname": frappe.scrub(account),
 				"fieldtype": "Currency",
-				"options": 'currency',
+				"options": "currency",
 				"width": 120
 			})
 
+	for account in unrealized_profit_loss_accounts:
+		unrealized_profit_loss_account_columns.append({
+			"label": account,
+			"fieldname": frappe.scrub(account),
+			"fieldtype": "Currency",
+			"options": "currency",
+			"width": 120
+		})
+
 	net_total_column = [{
 		"label": _("Net Total"),
 		"fieldname": "net_total",
 		"fieldtype": "Currency",
-		"options": 'currency',
+		"options": "currency",
 		"width": 120
 	}]
 
@@ -301,9 +329,10 @@
 		}
 	]
 
-	columns = columns + income_columns + net_total_column + tax_columns + total_columns
+	columns = columns + income_columns + unrealized_profit_loss_account_columns + \
+		net_total_column + tax_columns + total_columns
 
-	return columns, income_accounts, tax_accounts
+	return columns, income_accounts, tax_accounts, unrealized_profit_loss_accounts
 
 def get_conditions(filters):
 	conditions = ""
@@ -368,7 +397,8 @@
 	return frappe.db.sql("""
 		select name, posting_date, debit_to, project, customer,
 		customer_name, owner, remarks, territory, tax_id, customer_group,
-		base_net_total, base_grand_total, base_rounded_total, outstanding_amount {0}
+		base_net_total, base_grand_total, base_rounded_total, outstanding_amount,
+		is_internal_customer, represents_company, company {0}
 		from `tabSales Invoice`
 		where docstatus = 1 %s order by posting_date desc, name desc""".format(additional_query_columns or '') %
 		conditions, filters, as_dict=1)
@@ -385,6 +415,19 @@
 
 	return invoice_income_map
 
+def get_internal_invoice_map(invoice_list):
+	unrealized_amount_details = frappe.db.sql("""SELECT name, unrealized_profit_loss_account,
+		base_net_total as amount from `tabSales Invoice` where name in (%s)
+		and is_internal_customer = 1 and company = represents_company""" %
+		', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
+
+	internal_invoice_map = {}
+	for d in unrealized_amount_details:
+		if d.unrealized_profit_loss_account:
+			internal_invoice_map.setdefault((d.name, d.unrealized_profit_loss_account), d.amount)
+
+	return internal_invoice_map
+
 def get_invoice_tax_map(invoice_list, invoice_income_map, income_accounts):
 	tax_details = frappe.db.sql("""select parent, account_head,
 		sum(base_tax_amount_after_discount_amount) as tax_amount
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index 14534ef..dd0f065 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -164,16 +164,16 @@
 
 					if (doc.docstatus === 1 && !doc.inter_company_order_reference) {
 						let me = this;
-						frappe.model.with_doc("Supplier", me.frm.doc.supplier, () => {
-							let supplier = frappe.model.get_doc("Supplier", me.frm.doc.supplier);
-							let internal = supplier.is_internal_supplier;
-							let disabled = supplier.disabled;
-							if (internal === 1 && disabled === 0) {
-								me.frm.add_custom_button("Inter Company Order", function() {
-									me.make_inter_company_order(me.frm);
-								}, __('Create'));
-							}
-						});
+						let internal = me.frm.doc.is_internal_supplier;
+						if (internal) {
+							let button_label = (me.frm.doc.company === me.frm.doc.represents_company) ? "Internal Sales Order" :
+								"Inter Company Sales Order";
+
+							me.frm.add_custom_button(button_label, function() {
+								me.make_inter_company_order(me.frm);
+							}, __('Create'));
+						}
+
 					}
 				}
 
@@ -381,7 +381,7 @@
 						material_request_type: "Purchase",
 						docstatus: 1,
 						status: ["!=", "Stopped"],
-						per_ordered: ["<", 99.99],
+						per_ordered: ["<", 100],
 						company: me.frm.doc.company
 					}
 				})
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index 75da71c..ee2beea 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -134,6 +134,8 @@
   "ref_sq",
   "column_break_74",
   "party_account_currency",
+  "is_internal_supplier",
+  "represents_company",
   "inter_company_order_reference"
  ],
  "fields": [
@@ -1101,13 +1103,28 @@
   {
    "fieldname": "items_col_break",
    "fieldtype": "Column Break"
+  },
+  {
+   "default": "0",
+   "fetch_from": "supplier.is_internal_supplier",
+   "fieldname": "is_internal_supplier",
+   "fieldtype": "Check",
+   "label": "Is Internal Supplier"
+  },
+  {
+   "fetch_from": "supplier.represents_company",
+   "fieldname": "represents_company",
+   "fieldtype": "Link",
+   "label": "Represents Company",
+   "options": "Company",
+   "read_only": 1
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 105,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-12-03 16:46:44.229351",
+ "modified": "2021-01-20 22:07:23.487138",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Purchase Order",
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
index e537771..b76c378 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
@@ -224,7 +224,7 @@
 							material_request_type: "Purchase",
 							docstatus: 1,
 							status: ["!=", "Stopped"],
-							per_ordered: ["<", 99.99],
+							per_ordered: ["<", 100],
 							company: me.frm.doc.company
 						}
 					})
@@ -280,7 +280,7 @@
 								material_request_type: "Purchase",
 								docstatus: 1,
 								status: ["!=", "Stopped"],
-								per_ordered: ["<", 99.99]
+								per_ordered: ["<", 100]
 							}
 						});
 						dialog.hide();
diff --git a/erpnext/buying/doctype/supplier/supplier.py b/erpnext/buying/doctype/supplier/supplier.py
index 0ee9d18..edeb135 100644
--- a/erpnext/buying/doctype/supplier/supplier.py
+++ b/erpnext/buying/doctype/supplier/supplier.py
@@ -52,7 +52,10 @@
 		self.validate_internal_supplier()
 
 	def validate_internal_supplier(self):
-		if self.is_internal_supplier and frappe.db.get_value("Supplier", {"represents_company": self.represents_company}, "name"):
+		internal_supplier = frappe.db.get_value("Supplier",
+			{"is_internal_supplier": 1, "represents_company": self.represents_company, "name": ("!=", self.name)}, "name")
+
+		if internal_supplier:
 			frappe.throw(_("Internal Supplier for company {0} already exists").format(
 				frappe.bold(self.represents_company)))
 
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
index a3b2085..a0187b0 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
@@ -44,7 +44,7 @@
 							material_request_type: "Purchase",
 							docstatus: 1,
 							status: ["!=", "Stopped"],
-							per_ordered: ["<", 99.99],
+							per_ordered: ["<", 100],
 							company: me.frm.doc.company
 						}
 					})
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 7ac4cfe..9d9d1b3 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -75,6 +75,9 @@
 		self.ensure_supplier_is_not_blocked()
 
 		self.validate_date_with_fiscal_year()
+		self.validate_inter_company_reference()
+
+		self.set_incoming_rate()
 
 		if self.meta.get_field("currency"):
 			self.calculate_taxes_and_totals()
@@ -118,6 +121,12 @@
 
 	def before_cancel(self):
 		validate_einvoice_fields(self)
+	
+	def on_trash(self):
+		# delete sl and gl entries on deletion of transaction
+		if frappe.db.get_single_value('Accounts Settings', 'delete_linked_ledger_entries'):
+			frappe.db.sql("delete from `tabGL Entry` where voucher_type=%s and voucher_no=%s", (self.doctype, self.name))
+			frappe.db.sql("delete from `tabStock Ledger Entry` where voucher_type=%s and voucher_no=%s", (self.doctype, self.name))
 
 	def validate_deferred_start_and_end_date(self):
 		for d in self.items:
@@ -206,6 +215,17 @@
 				validate_fiscal_year(self.get(date_field), self.fiscal_year, self.company,
 									 self.meta.get_label(date_field), self)
 
+	def validate_inter_company_reference(self):
+		if self.doctype not in ('Purchase Invoice', 'Purchase Receipt', 'Purchase Order'):
+			return
+
+		if self.is_internal_transfer():
+			if not (self.get('inter_company_reference') or self.get('inter_company_invoice_reference')
+				or self.get('inter_company_order_reference')):
+				msg = _("Internal Sale or Delivery Reference missing. ")
+				msg += _("Please create purchase from internal sale or delivery document itself")
+				frappe.throw(msg, title=_("Internal Sales Reference Missing"))
+
 	def validate_due_date(self):
 		if self.get('is_pos'): return
 
@@ -964,9 +984,9 @@
 			It will an internal transfer if its an internal customer and representation
 			company is same as billing company
 		"""
-		if self.doctype == 'Sales Invoice':
+		if self.doctype in ('Sales Invoice', 'Delivery Note', 'Sales Order'):
 			internal_party_field = 'is_internal_customer'
-		else:
+		elif self.doctype in ('Purchase Invoice', 'Purchase Receipt', 'Purchase Order'):
 			internal_party_field = 'is_internal_supplier'
 
 		if self.get(internal_party_field) and (self.represents_company == self.company):
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 4dee375..ab1f027 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -44,7 +44,6 @@
 		self.validate_items()
 		self.set_qty_as_per_stock_uom()
 		self.validate_stock_or_nonstock_items()
-		self.update_tax_category_for_internal_transfer()
 		self.validate_warehouse()
 		self.validate_from_warehouse()
 		self.set_supplier_address()
@@ -100,11 +99,6 @@
 			msg = _('Tax Category has been changed to "Total" because all the Items are non-stock items')
 			self.update_tax_category(msg)
 
-	def update_tax_category_for_internal_transfer(self):
-		if self.doctype == 'Purchase Invoice' and self.is_internal_transfer():
-			msg = _('Tax Category has been changed to "Total" as its an internal purchase.')
-			self.update_tax_category(msg)
-
 	def update_tax_category(self, msg):
 		tax_for_valuation = [d for d in self.get("taxes")
 				if d.category in ["Valuation", "Valuation and Total"]]
@@ -224,6 +218,48 @@
 			else:
 				item.valuation_rate = 0.0
 
+	def set_incoming_rate(self):
+		if self.doctype not in ("Purchase Receipt", "Purchase Invoice", "Purchase Order"):
+			return
+
+		ref_doctype_map = {
+			"Purchase Order": "Sales Order Item",
+			"Purchase Receipt": "Delivery Note Item",
+			"Purchase Invoice": "Sales Invoice Item",
+		}
+
+		ref_doctype = ref_doctype_map.get(self.doctype)
+		items = self.get("items")
+		for d in items:
+			if not cint(self.get("is_return")):
+				# Get outgoing rate based on original item cost based on valuation method
+
+				if not d.get(frappe.scrub(ref_doctype)):
+					outgoing_rate = get_incoming_rate({
+						"item_code": d.item_code,
+						"warehouse": d.get('from_warehouse'),
+						"posting_date": self.get('posting_date') or self.get('transation_date'),
+						"posting_time": self.get('posting_time'),
+						"qty": -1 * flt(d.get('stock_qty')),
+						"serial_no": d.get('serial_no'),
+						"company": self.company,
+						"voucher_type": self.doctype,
+						"voucher_no": self.name,
+						"allow_zero_valuation": d.get("allow_zero_valuation")
+					}, raise_error_if_no_rate=False)
+
+					rate = flt(outgoing_rate * d.conversion_factor, d.precision('rate'))
+				else:
+					rate = frappe.db.get_value(ref_doctype, d.get(frappe.scrub(ref_doctype)), 'rate')
+
+				if self.is_internal_transfer():
+					if rate != d.rate:
+						d.rate = rate
+						d.discount_percentage = 0
+						d.discount_amount = 0
+						frappe.msgprint(_("Row {0}: Item rate has been updated as per valuation rate since its an internal stock transfer")
+							.format(d.idx), alert=1)
+
 	def get_supplied_items_cost(self, item_row_id, reset_outgoing_rate=True):
 		supplied_items_cost = 0.0
 		for d in self.get("supplied_items"):
@@ -243,7 +279,7 @@
 
 				d.amount = flt(flt(d.consumed_qty) * flt(d.rate), d.precision("amount"))
 				supplied_items_cost += flt(d.amount)
-		
+
 		return supplied_items_cost
 
 	def validate_for_subcontracting(self):
@@ -559,6 +595,8 @@
 						from_warehouse_sle = self.get_sl_entries(d, {
 							"actual_qty": -1 * pr_qty,
 							"warehouse": d.from_warehouse,
+							"outgoing_rate": d.rate,
+							"recalculate_rate": 1,
 							"dependant_sle_voucher_detail_no": d.name
 						})
 
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index 812021f..e085048 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -3,7 +3,7 @@
 
 from __future__ import unicode_literals
 import frappe
-from frappe.utils import cint, flt, cstr, comma_or, get_link_to_form
+from frappe.utils import cint, flt, cstr, get_link_to_form, nowtime
 from frappe import _, throw
 from erpnext.stock.get_item_details import get_bin_details
 from erpnext.stock.utils import get_incoming_rate
@@ -49,7 +49,6 @@
 		self.set_customer_address()
 		self.validate_for_duplicate_items()
 		self.validate_target_warehouse()
-		self.set_incoming_rate()
 
 	def set_missing_values(self, for_validate=False):
 
@@ -191,7 +190,7 @@
 		for it in self.get("items"):
 			if not it.item_code:
 				continue
-			
+
 			last_purchase_rate, is_stock_item = frappe.get_cached_value("Item", it.item_code, ["last_purchase_rate", "is_stock_item"])
 			last_purchase_rate_in_sales_uom = last_purchase_rate * (it.conversion_factor or 1)
 			if flt(it.base_net_rate) < flt(last_purchase_rate_in_sales_uom):
@@ -312,7 +311,7 @@
 				sales_order.update_reserved_qty(so_item_rows)
 
 	def set_incoming_rate(self):
-		if self.doctype not in ("Delivery Note", "Sales Invoice"):
+		if self.doctype not in ("Delivery Note", "Sales Invoice", "Sales Order"):
 			return
 
 		items = self.get("items") + (self.get("packed_items") or [])
@@ -322,15 +321,26 @@
 				d.incoming_rate = get_incoming_rate({
 					"item_code": d.item_code,
 					"warehouse": d.warehouse,
-					"posting_date": self.posting_date,
-					"posting_time": self.posting_time,
-					"qty": -1*flt(d.qty),
-					"serial_no": d.serial_no,
+					"posting_date": self.get('posting_date') or self.get('transaction_date'),
+					"posting_time": self.get('posting_time') or nowtime(),
+					"qty": -1 * flt(d.get('stock_qty') or d.get('actual_qty')),
+					"serial_no": d.get('serial_no'),
 					"company": self.company,
 					"voucher_type": self.doctype,
 					"voucher_no": self.name,
 					"allow_zero_valuation": d.get("allow_zero_valuation")
 				}, raise_error_if_no_rate=False)
+
+				# For internal transfers use incoming rate as the valuation rate
+				if self.is_internal_transfer():
+					rate = flt(d.incoming_rate * d.conversion_factor, d.precision('rate'))
+					if d.rate != rate:
+						d.rate = rate
+						d.discount_percentage = 0
+						d.discount_amount = 0
+						frappe.msgprint(_("Row {0}: Item rate has been updated as per valuation rate since its an internal stock transfer")
+							.format(d.idx), alert=1)
+
 			elif self.get("return_against"):
 				# Get incoming rate of return entry from reference document
 				# based on original item cost as per valuation method
@@ -391,7 +401,7 @@
 				})
 				if item_row.warehouse:
 					sle.dependant_sle_voucher_detail_no = item_row.name
-			
+
 		return sle
 
 	def set_po_nos(self, for_validate=False):
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index e0fcf47..4b5e347 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -24,6 +24,7 @@
 			self.validate_inspection()
 		self.validate_serialized_batch()
 		self.validate_customer_provided_item()
+		self.validate_internal_transfer()
 		self.validate_putaway_capacity()
 
 	def make_gl_entries(self, gl_entries=None, from_repost=False):
@@ -74,6 +75,7 @@
 		warehouse_with_no_account = []
 		precision = frappe.get_precision("GL Entry", "debit_in_account_currency")
 		for item_row in voucher_details:
+
 			sle_list = sle_map.get(item_row.name)
 			if sle_list:
 				for sle in sle_list:
@@ -218,7 +220,7 @@
 		""", (self.doctype, self.name), as_dict=True)
 
 		for sle in stock_ledger_entries:
-				stock_ledger.setdefault(sle.voucher_detail_no, []).append(sle)
+			stock_ledger.setdefault(sle.voucher_detail_no, []).append(sle)
 		return stock_ledger
 
 	def make_batches(self, warehouse_field):
@@ -393,6 +395,32 @@
 			if frappe.db.get_value('Item', d.item_code, 'is_customer_provided_item'):
 				d.allow_zero_valuation_rate = 1
 
+	def validate_internal_transfer(self):
+		if self.doctype in ('Sales Invoice', 'Delivery Note', 'Purchase Invoice', 'Purchase Receipt') \
+			and self.is_internal_transfer():
+			self.validate_in_transit_warehouses()
+			self.validate_multi_currency()
+			self.validate_packed_items()
+
+	def validate_in_transit_warehouses(self):
+		if (self.doctype == 'Sales Invoice' and self.get('update_stock')) or self.doctype == 'Delivery Note':
+			for item in self.get('items'):
+				if not item.target_warehouse:
+					frappe.throw(_("Row {0}: Target Warehouse is mandatory for internal transfers").format(item.idx))
+
+		if (self.doctype == 'Purchase Invoice' and self.get('update_stock')) or self.doctype == 'Purchase Receipt':
+			for item in self.get('items'):
+				if not item.from_warehouse:
+					frappe.throw(_("Row {0}: From Warehouse is mandatory for internal transfers").format(item.idx))
+
+	def validate_multi_currency(self):
+		if self.currency != self.company_currency:
+			frappe.throw(_("Internal transfers can only be done in company's default currency"))
+
+	def validate_packed_items(self):
+		if self.doctype in ('Sales Invoice', 'Delivery Note Item') and self.get('packed_items'):
+			frappe.throw(_("Packed Items cannot be transferred internally"))
+
 	def validate_putaway_capacity(self):
 		# if over receipt is attempted while 'apply putaway rule' is disabled
 		# and if rule was applied on the transaction, validate it.
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 14377e1..1c20555 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -416,9 +416,6 @@
 	'Italy': {
 		'erpnext.controllers.taxes_and_totals.update_itemised_tax_data': 'erpnext.regional.italy.utils.update_itemised_tax_data',
 		'erpnext.controllers.accounts_controller.validate_regional': 'erpnext.regional.italy.utils.sales_invoice_validate',
-	},
-	'Germany': {
-		'erpnext.controllers.accounts_controller.validate_regional': 'erpnext.regional.germany.accounts_controller.validate_regional',
 	}
 }
 user_privacy_documents = [
diff --git a/erpnext/hr/doctype/shift_assignment/shift_assignment.py b/erpnext/hr/doctype/shift_assignment/shift_assignment.py
index 2c385e8..ab65260 100644
--- a/erpnext/hr/doctype/shift_assignment/shift_assignment.py
+++ b/erpnext/hr/doctype/shift_assignment/shift_assignment.py
@@ -88,7 +88,7 @@
 
 def add_assignments(events, start, end, conditions=None):
 	query = """select name, start_date, end_date, employee_name,
-		employee, docstatus
+		employee, docstatus, shift_type
 		from `tabShift Assignment` where
 		start_date >= %(start_date)s
 		or end_date <=  %(end_date)s
@@ -97,18 +97,40 @@
 	if conditions:
 		query += conditions
 
-	for d in frappe.db.sql(query, {"start_date":start, "end_date":end}, as_dict=True):
-		e = {
-			"name": d.name,
-			"doctype": "Shift Assignment",
-			"start_date": d.start_date,
-			"end_date": d.end_date if d.end_date else nowdate(),
-			"title": cstr(d.employee_name) + ": "+ \
-				cstr(d.shift_type),
-			"docstatus": d.docstatus
-		}
-		if e not in events:
-			events.append(e)
+	records = frappe.db.sql(query, {"start_date":start, "end_date":end}, as_dict=True)
+	shift_timing_map = get_shift_type_timing([d.shift_type for d in records])
+
+	for d in records:
+		daily_event_start = d.start_date
+		daily_event_end = d.end_date if d.end_date else getdate()
+		delta = timedelta(days=1)
+		while daily_event_start <= daily_event_end:
+			start_timing = frappe.utils.get_datetime(daily_event_start)+ shift_timing_map[d.shift_type]['start_time']
+			end_timing = frappe.utils.get_datetime(daily_event_start)+ shift_timing_map[d.shift_type]['end_time']
+			daily_event_start += delta
+			e = {
+				"name": d.name,
+				"doctype": "Shift Assignment",
+				"start_date": start_timing,
+				"end_date": end_timing,
+				"title": cstr(d.employee_name) + ": "+ \
+					cstr(d.shift_type),
+				"docstatus": d.docstatus,
+				"allDay": 0
+			}
+			if e not in events:
+				events.append(e)
+
+	return events
+
+def get_shift_type_timing(shift_types):
+	shift_timing_map = {}
+	data = frappe.get_all("Shift Type", filters = {"name": ("IN", shift_types)}, fields = ['name', 'start_time', 'end_time'])
+
+	for d in data:
+		shift_timing_map[d.name] = d
+
+	return shift_timing_map
 
 
 def get_employee_shift(employee, for_date=nowdate(), consider_default_shift=False, next_shift_direction=None):
diff --git a/erpnext/hr/doctype/shift_assignment/shift_assignment_calendar.js b/erpnext/hr/doctype/shift_assignment/shift_assignment_calendar.js
index 17a986d..bb692e1 100644
--- a/erpnext/hr/doctype/shift_assignment/shift_assignment_calendar.js
+++ b/erpnext/hr/doctype/shift_assignment/shift_assignment_calendar.js
@@ -6,14 +6,8 @@
 		"start": "start_date",
 		"end": "end_date",
 		"id": "name",
-		"docstatus": 1
-	},
-	options: {
-		header: {
-			left: 'prev,next today',
-			center: 'title',
-			right: 'month'
-		}
+		"docstatus": 1,
+		"allDay": "allDay",
 	},
 	get_events_method: "erpnext.hr.doctype.shift_assignment.shift_assignment.get_events"
 }
\ No newline at end of file
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 1d1f18b..9627600 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -105,10 +105,18 @@
 		frappe.ui.form.on(this.frm.doctype + " Item", {
 			items_add: function(frm, cdt, cdn) {
 				var item = frappe.get_doc(cdt, cdn);
-				if(!item.warehouse && frm.doc.set_warehouse) {
+				if (!item.warehouse && frm.doc.set_warehouse) {
 					item.warehouse = frm.doc.set_warehouse;
 				}
 
+				if (!item.target_warehouse && frm.doc.set_target_warehouse) {
+					item.target_warehouse = frm.doc.set_target_warehouse;
+				}
+
+				if (!item.from_warehouse && frm.doc.set_from_warehouse) {
+					item.from_warehouse = frm.doc.set_from_warehouse;
+				}
+
 				erpnext.accounts.dimensions.copy_dimension_from_first_row(frm, cdt, cdn, 'items');
 			}
 		});
@@ -227,6 +235,8 @@
 				}
 			};
 
+			this.frm.trigger('set_default_internal_warehouse');
+
 			return frappe.run_serially([
 				() => set_value('currency', currency),
 				() => set_value('price_list_currency', currency),
@@ -658,7 +668,7 @@
 				args: item_args
 			},
 			callback: function(r) {
-				frappe.model.set_value(item.doctype, item.name, 'rate', r.message);
+				frappe.model.set_value(item.doctype, item.name, 'rate', r.message * item.conversion_factor);
 			}
 		});
 	},
@@ -724,6 +734,31 @@
 		this.calculate_taxes_and_totals(false);
 	},
 
+	update_stock: function() {
+		this.frm.trigger('set_default_internal_warehouse');
+	},
+
+	set_default_internal_warehouse: function() {
+		let me = this;
+		if ((this.frm.doc.doctype === 'Sales Invoice' && me.frm.doc.update_stock)
+			|| this.frm.doc.doctype == 'Delivery Note') {
+			if (this.frm.doc.is_internal_customer && this.frm.doc.company === this.frm.doc.represents_company) {
+				frappe.db.get_value('Company', this.frm.doc.company, 'default_in_transit_warehouse', function(value) {
+					me.frm.set_value('set_target_warehouse', value.default_in_transit_warehouse);
+				});
+			}
+		}
+
+		if ((this.frm.doc.doctype === 'Purchase Invoice' && me.frm.doc.update_stock)
+			|| this.frm.doc.doctype == 'Purchase Receipt') {
+			if (this.frm.doc.is_internal_supplier && this.frm.doc.company === this.frm.doc.represents_company) {
+				frappe.db.get_value('Company', this.frm.doc.company, 'default_in_transit_warehouse', function(value) {
+					me.frm.set_value('set_from_warehouse', value.default_in_transit_warehouse);
+				});
+			}
+		}
+	},
+
 	company: function() {
 		var me = this;
 		var set_pricing = function() {
@@ -810,7 +845,7 @@
 			in_list(['Purchase Order', 'Purchase Receipt', 'Purchase Invoice'], this.frm.doctype)) {
 			erpnext.utils.get_shipping_address(this.frm, function(){
 				set_party_account(set_pricing);
-			})
+			});
 
 			// Get default company billing address in Purchase Invoice, Order and Receipt
 			frappe.call({
@@ -1977,6 +2012,14 @@
 		this.autofill_warehouse(this.frm.doc.items, "warehouse", this.frm.doc.set_warehouse);
 	},
 
+	set_target_warehouse: function() {
+		this.autofill_warehouse(this.frm.doc.items, "target_warehouse", this.frm.doc.set_target_warehouse);
+	},
+
+	set_from_warehouse: function() {
+		this.autofill_warehouse(this.frm.doc.items, "from_warehouse", this.frm.doc.set_from_warehouse);
+	},
+
 	autofill_warehouse : function (child_table, warehouse_field, warehouse) {
 		if (warehouse && child_table && child_table.length) {
 			let doctype = child_table[0].doctype;
diff --git a/erpnext/public/js/utils/party.js b/erpnext/public/js/utils/party.js
index 770704e..808dd5a 100644
--- a/erpnext/public/js/utils/party.js
+++ b/erpnext/public/js/utils/party.js
@@ -276,6 +276,12 @@
 
 erpnext.utils.get_shipping_address = function(frm, callback){
 	if (frm.doc.company) {
+		if (!(frm.doc.inter_com_order_reference || frm.doc.internal_invoice_reference ||
+			frm.doc.internal_order_reference)) {
+			if (callback) {
+				return callback();
+			}
+		}
 		frappe.call({
 			method: "erpnext.accounts.custom.address.get_shipping_address",
 			args: {
diff --git a/erpnext/regional/germany/accounts_controller.py b/erpnext/regional/germany/accounts_controller.py
deleted file mode 100644
index 7f76493..0000000
--- a/erpnext/regional/germany/accounts_controller.py
+++ /dev/null
@@ -1,53 +0,0 @@
-import frappe
-from frappe import _
-from frappe import msgprint
-
-
-REQUIRED_FIELDS = {
-	"Sales Invoice": [
-		{
-			"field_name": "company_address",
-			"regulation": "§ 14 Abs. 4 Nr. 1 UStG"
-		},
-		{
-			"field_name": "company_tax_id",
-			"regulation": "§ 14 Abs. 4 Nr. 2 UStG"
-		},
-		{
-			"field_name": "taxes",
-			"regulation": "§ 14 Abs. 4 Nr. 8 UStG"
-		},
-		{
-			"field_name": "customer_address",
-			"regulation": "§ 14 Abs. 4 Nr. 1 UStG",
-			"condition": "base_grand_total > 250"
-		}
-	]
-}
-
-
-def validate_regional(doc):
-	"""Check if required fields for this document are present."""
-	required_fields = REQUIRED_FIELDS.get(doc.doctype)
-	if not required_fields:
-		return
-
-	meta = frappe.get_meta(doc.doctype)
-	field_map = {field.fieldname: field.label for field in meta.fields}
-
-	for field in required_fields:
-		condition = field.get("condition")
-		if condition and not frappe.safe_eval(condition, doc.as_dict()):
-			continue
-
-		field_name = field.get("field_name")
-		regulation = field.get("regulation")
-		if field_name and not doc.get(field_name):
-			missing(field_map.get(field_name), regulation)
-
-
-def missing(field_label, regulation):
-	"""Notify the user that a required field is missing."""
-	translated_msg = _('Remember to set {field_label}. It is required by {regulation}.', context='Specific for Germany. Example: Remember to set Company Tax ID. It is required by § 14 Abs. 4 Nr. 2 UStG.') # noqa: E501
-	formatted_msg = translated_msg.format(field_label=frappe.bold(_(field_label)), regulation=regulation)
-	msgprint(formatted_msg)
diff --git a/erpnext/regional/germany/test_accounts_controller.py b/erpnext/regional/germany/test_accounts_controller.py
deleted file mode 100644
index 8bd378c..0000000
--- a/erpnext/regional/germany/test_accounts_controller.py
+++ /dev/null
@@ -1,12 +0,0 @@
-import frappe
-import unittest
-from erpnext.regional.germany.accounts_controller import validate_regional
-
-
-class TestAccountsController(unittest.TestCase):
-
-	def setUp(self):
-		self.sales_invoice = frappe.get_last_doc('Sales Invoice')
-
-	def test_validate_regional(self):
-		validate_regional(self.sales_invoice)
diff --git a/erpnext/regional/india/taxes.js b/erpnext/regional/india/taxes.js
index 87baece..f09d3d0 100644
--- a/erpnext/regional/india/taxes.js
+++ b/erpnext/regional/india/taxes.js
@@ -40,14 +40,12 @@
 				callback: function(r) {
 					if(r.message) {
 						frm.set_value('taxes_and_charges', r.message.taxes_and_charges);
+						frm.set_value('taxes', r.message.taxes);
 						frm.set_value('place_of_supply', r.message.place_of_supply);
-					} else if (frm.doc.is_internal_supplier || frm.doc.is_internal_customer) {
-						frm.set_value('taxes_and_charges', '');
-						frm.set_value('taxes', []);
 					}
 				}
 			});
 		}
 	});
-};
+}
 
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index 0d82638..e89885f 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -171,7 +171,7 @@
 
 	if is_internal_transfer(party_details, doctype):
 		party_details.taxes_and_charges = ''
-		party_details.taxes = ''
+		party_details.taxes = []
 		return party_details
 
 	if doctype in ("Sales Invoice", "Delivery Note", "Sales Order"):
diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py
index ad3de5f..96dc3f7 100644
--- a/erpnext/regional/report/gstr_1/gstr_1.py
+++ b/erpnext/regional/report/gstr_1/gstr_1.py
@@ -255,15 +255,16 @@
 
 						for item_code, tax_amounts in item_wise_tax_detail.items():
 							tax_rate = tax_amounts[0]
-							if cgst_or_sgst:
-								tax_rate *= 2
-								if parent not in self.cgst_sgst_invoices:
-									self.cgst_sgst_invoices.append(parent)
+							if tax_rate:
+								if cgst_or_sgst:
+									tax_rate *= 2
+									if parent not in self.cgst_sgst_invoices:
+										self.cgst_sgst_invoices.append(parent)
 
-							rate_based_dict = self.items_based_on_tax_rate\
-								.setdefault(parent, {}).setdefault(tax_rate, [])
-							if item_code not in rate_based_dict:
-								rate_based_dict.append(item_code)
+								rate_based_dict = self.items_based_on_tax_rate\
+									.setdefault(parent, {}).setdefault(tax_rate, [])
+								if item_code not in rate_based_dict:
+									rate_based_dict.append(item_code)
 					except ValueError:
 						continue
 		if unidentified_gst_accounts:
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index 29214ee..bf8b7fc 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -84,7 +84,10 @@
 				frappe.throw(_("{0} is not a company bank account").format(frappe.bold(self.default_bank_account)))
 
 	def validate_internal_customer(self):
-		if self.is_internal_customer and frappe.db.get_value('Customer', {"represents_company": self.represents_company}, "name"):
+		internal_customer = frappe.db.get_value("Customer",
+			{"is_internal_customer": 1, "represents_company": self.represents_company, "name": ("!=", self.name)}, "name")
+
+		if internal_customer:
 			frappe.throw(_("Internal Customer for company {0} already exists").format(
 				frappe.bold(self.represents_company)))
 
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index d4fb07c..78f9df9 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -171,8 +171,10 @@
 						this.frm.add_custom_button(__('Request for Raw Materials'), () => this.make_raw_material_request(), __('Create'));
 					}
 
-					// make purchase order
+					// Make Purchase Order
+					if (!this.frm.doc.is_internal_customer) {
 						this.frm.add_custom_button(__('Purchase Order'), () => this.make_purchase_order(), __('Create'));
+					}
 
 					// maintenance
 					if(flt(doc.per_delivered, 2) < 100 && (order_is_maintenance || order_is_a_custom_sale)) {
@@ -193,16 +195,15 @@
 
 					if (doc.docstatus === 1 && !doc.inter_company_order_reference) {
 						let me = this;
-						frappe.model.with_doc("Customer", me.frm.doc.customer, () => {
-							let customer = frappe.model.get_doc("Customer", me.frm.doc.customer);
-							let internal = customer.is_internal_customer;
-							let disabled = customer.disabled;
-							if (internal === 1 && disabled === 0) {
-								me.frm.add_custom_button("Inter Company Order", function() {
-									me.make_inter_company_order();
-								}, __('Create'));
-							}
-						});
+						let internal = me.frm.doc.is_internal_customer;
+						if (internal) {
+							let button_label = (me.frm.doc.company === me.frm.doc.represents_company) ? "Internal Purchase Order" :
+								"Inter Company Purchase Order";
+
+							me.frm.add_custom_button(button_label, function() {
+								me.make_inter_company_order();
+							}, __('Create'));
+						}
 					}
 				}
 				// payment request
diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json
index 3d64ac3..0a5c665 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.json
+++ b/erpnext/selling/doctype/sales_order/sales_order.json
@@ -107,6 +107,8 @@
   "tc_name",
   "terms",
   "more_info",
+  "is_internal_customer",
+  "represents_company",
   "inter_company_order_reference",
   "project",
   "party_account_currency",
@@ -1103,7 +1105,8 @@
    "hide_days": 1,
    "hide_seconds": 1,
    "label": "Inter Company Order Reference",
-   "options": "Purchase Order"
+   "options": "Purchase Order",
+   "read_only": 1
   },
   {
    "description": "Track this Sales Order against any Project",
@@ -1455,13 +1458,29 @@
    "hide_seconds": 1,
    "label": "Skip Delivery Note",
    "print_hide": 1
+  },
+  {
+   "default": "0",
+   "fetch_from": "customer.is_internal_customer",
+   "fieldname": "is_internal_customer",
+   "fieldtype": "Check",
+   "label": "Is Internal Customer",
+   "read_only": 1
+  },
+  {
+   "fetch_from": "customer.represents_company",
+   "fieldname": "represents_company",
+   "fieldtype": "Link",
+   "label": "Represents Company",
+   "options": "Company",
+   "read_only": 1
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 105,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-10-30 13:59:18.628077",
+ "modified": "2021-01-20 23:40:39.929296",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Sales Order",
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js
index ee18042..334bdea 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.js
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.js
@@ -95,13 +95,19 @@
 			frm.page.set_inner_btn_group_as_primary(__('Create'));
 		}
 
-		if (frm.doc.docstatus === 1 && frm.doc.is_internal_customer && !frm.doc.inter_company_reference) {
-			frm.add_custom_button(__('Purchase Receipt'), function() {
-				frappe.model.open_mapped_doc({
-					method: 'erpnext.stock.doctype.delivery_note.delivery_note.make_inter_company_purchase_receipt',
-					frm: frm,
-				})
-			}, __('Create'));
+		if (frm.doc.docstatus == 1 && !frm.doc.inter_company_reference) {
+			let internal = me.frm.doc.is_internal_customer;
+			if (internal) {
+				let button_label = (me.frm.doc.company === me.frm.doc.represents_company) ? "Internal Purchase Receipt" :
+					"Inter Company Purchase Receipt";
+
+				me.frm.add_custom_button(button_label, function() {
+					frappe.model.open_mapped_doc({
+						method: 'erpnext.stock.doctype.delivery_note.delivery_note.make_inter_company_purchase_receipt',
+						frm: frm,
+					});
+				}, __('Create'));
+			}
 		}
 	}
 });
@@ -297,15 +303,6 @@
 			}
 		})
 	},
-
-	to_warehouse: function() {
-		let packed_items_table = this.frm.doc["packed_items"];
-		this.autofill_warehouse(this.frm.doc["items"], "target_warehouse", this.frm.doc.to_warehouse);
-		if (packed_items_table && packed_items_table.length) {
-			this.autofill_warehouse(packed_items_table, "target_warehouse", this.frm.doc.to_warehouse);
-		}
-	}
-
 });
 
 $.extend(cur_frm.cscript, new erpnext.stock.DeliveryNoteController({frm: cur_frm}));
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json
index c9f8d08..f595aad 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.json
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.json
@@ -53,7 +53,7 @@
   "sec_warehouse",
   "set_warehouse",
   "col_break_warehouse",
-  "to_warehouse",
+  "set_target_warehouse",
   "items_section",
   "scan_barcode",
   "items",
@@ -117,6 +117,7 @@
   "source",
   "column_break5",
   "is_internal_customer",
+  "represents_company",
   "inter_company_reference",
   "per_billed",
   "customer_group",
@@ -503,18 +504,6 @@
    "fieldtype": "Column Break"
   },
   {
-   "description": "Required only for sample item.",
-   "fieldname": "to_warehouse",
-   "fieldtype": "Link",
-   "in_standard_filter": 1,
-   "label": "To Warehouse",
-   "no_copy": 1,
-   "oldfieldname": "to_warehouse",
-   "oldfieldtype": "Link",
-   "options": "Warehouse",
-   "print_hide": 1
-  },
-  {
    "fieldname": "items_section",
    "fieldtype": "Section Break",
    "oldfieldtype": "Section Break",
@@ -1261,13 +1250,34 @@
    "no_copy": 1,
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "depends_on": "eval: doc.is_internal_customer",
+   "fieldname": "set_target_warehouse",
+   "fieldtype": "Link",
+   "in_standard_filter": 1,
+   "label": "Set Target Warehouse",
+   "no_copy": 1,
+   "oldfieldname": "to_warehouse",
+   "oldfieldtype": "Link",
+   "options": "Warehouse",
+   "print_hide": 1
+  },
+  {
+   "description": "Company which internal customer represents.",
+   "fetch_from": "customer.represents_company",
+   "fieldname": "represents_company",
+   "fieldtype": "Link",
+   "label": "Represents Company",
+   "options": "Company",
+   "read_only": 1
   }
  ],
  "icon": "fa fa-truck",
  "idx": 146,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-11-30 12:54:45.407289",
+ "modified": "2020-12-26 17:07:59.194403",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Delivery Note",
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index a30cadf..fa5a7fb 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -664,7 +664,8 @@
 	return make_inter_company_transaction("Delivery Note", source_name, target_doc)
 
 def make_inter_company_transaction(doctype, source_name, target_doc=None):
-	from erpnext.accounts.doctype.sales_invoice.sales_invoice import validate_inter_company_transaction, get_inter_company_details
+	from erpnext.accounts.doctype.sales_invoice.sales_invoice import (validate_inter_company_transaction,
+		get_inter_company_details, update_address, update_taxes, set_purchase_references)
 
 	if doctype == 'Delivery Note':
 		source_doc = frappe.get_doc(doctype, source_name)
@@ -682,6 +683,7 @@
 
 	def set_missing_values(source, target):
 		target.run_method("set_missing_values")
+		set_purchase_references(target)
 
 		if target.doctype == 'Purchase Receipt':
 			master_doctype = 'Purchase Taxes and Charges Template'
@@ -697,21 +699,35 @@
 		if target_doc.doctype == 'Purchase Receipt':
 			target_doc.company = details.get("company")
 			target_doc.supplier = details.get("party")
-			target_doc.supplier_address = source_doc.company_address
-			target_doc.shipping_address = source_doc.shipping_address_name or source_doc.customer_address
 			target_doc.buying_price_list = source_doc.selling_price_list
 			target_doc.is_internal_supplier = 1
 			target_doc.inter_company_reference = source_doc.name
+
+			# Invert the address on target doc creation
+			update_address(target_doc, 'supplier_address', 'address_display', source_doc.company_address)
+			update_address(target_doc, 'shipping_address', 'shipping_address_display', source_doc.customer_address)
+
+			update_taxes(target_doc, party=target_doc.supplier, party_type='Supplier', company=target_doc.company,
+				doctype=target_doc.doctype, party_address=target_doc.supplier_address,
+				company_address=target_doc.shipping_address)
 		else:
 			target_doc.company = details.get("company")
 			target_doc.customer = details.get("party")
 			target_doc.company_address = source_doc.supplier_address
-			target_doc.shipping_address_name = source_doc.shipping_address
 			target_doc.selling_price_list = source_doc.buying_price_list
 			target_doc.is_internal_customer = 1
 			target_doc.inter_company_reference = source_doc.name
 
-	doclist = get_mapped_doc(doctype, source_name,	{
+			# Invert the address on target doc creation
+			update_address(target_doc, 'company_address', 'company_address_display', source_doc.supplier_address)
+			update_address(target_doc, 'shipping_address_name', 'shipping_address', source_doc.shipping_address)
+			update_address(target_doc, 'customer_address', 'address_display', source_doc.shipping_address)
+
+			update_taxes(target_doc, party=target_doc.customer, party_type='Customer', company=target_doc.company,
+				doctype=target_doc.doctype, party_address=target_doc.customer_address,
+				company_address=target_doc.company_address, shipping_address_name=target_doc.shipping_address_name)
+
+	doclist = get_mapped_doc(doctype, source_name, {
 		doctype: {
 			"doctype": target_doctype,
 			"postprocess": update_details,
@@ -722,7 +738,10 @@
 		doctype +" Item": {
 			"doctype": target_doctype + " Item",
 			"field_map": {
-				source_document_warehouse_field: target_document_warehouse_field
+				source_document_warehouse_field: target_document_warehouse_field,
+				'name': 'delivery_note_item',
+				'batch_no': 'batch_no',
+				'serial_no': 'serial_no'
 			},
 			"field_no_map": [
 				"warehouse"
diff --git a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
index 4bbf3de..9de088d 100644
--- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
+++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
@@ -458,7 +458,7 @@
    "fieldname": "warehouse",
    "fieldtype": "Link",
    "in_list_view": 1,
-   "label": "From Warehouse",
+   "label": "Warehouse",
    "oldfieldname": "warehouse",
    "oldfieldtype": "Link",
    "options": "Warehouse",
@@ -467,11 +467,12 @@
    "width": "100px"
   },
   {
+   "depends_on": "eval:parent.is_internal_customer",
    "fieldname": "target_warehouse",
    "fieldtype": "Link",
    "hidden": 1,
    "ignore_user_permissions": 1,
-   "label": "Customer Warehouse (Optional)",
+   "label": "Target Warehouse",
    "no_copy": 1,
    "options": "Warehouse",
    "print_hide": 1
@@ -748,7 +749,7 @@
  "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-12-07 19:59:27.119856",
+ "modified": "2020-12-26 17:31:27.029803",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Delivery Note Item",
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index d07b3dc..fcf7c26 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -106,9 +106,9 @@
   "item_tax_section_break",
   "taxes",
   "inspection_criteria",
+  "quality_inspection_template",
   "inspection_required_before_purchase",
   "inspection_required_before_delivery",
-  "quality_inspection_template",
   "manufacturing",
   "default_bom",
   "is_sub_contracted_item",
@@ -814,7 +814,6 @@
    "label": "Inspection Required before Delivery"
   },
   {
-   "depends_on": "eval:(doc.inspection_required_before_purchase || doc.inspection_required_before_delivery)",
    "fieldname": "quality_inspection_template",
    "fieldtype": "Link",
    "label": "Quality Inspection Template",
@@ -1069,7 +1068,7 @@
  "index_web_pages_for_search": 1,
  "links": [],
  "max_attachments": 1,
- "modified": "2020-08-07 14:24:58.384992",
+ "modified": "2021-01-25 20:49:50.222976",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Item",
@@ -1131,4 +1130,4 @@
  "sort_order": "DESC",
  "title_field": "item_name",
  "track_changes": 1
-}
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/material_request/material_request_list.js b/erpnext/stock/doctype/material_request/material_request_list.js
index 0d70958..de7a3d0 100644
--- a/erpnext/stock/doctype/material_request/material_request_list.js
+++ b/erpnext/stock/doctype/material_request/material_request_list.js
@@ -1,9 +1,10 @@
 frappe.listview_settings['Material Request'] = {
 	add_fields: ["material_request_type", "status", "per_ordered", "per_received", "transfer_status"],
 	get_indicator: function(doc) {
-		if(doc.status=="Stopped") {
+		var precision = frappe.defaults.get_default("float_precision");
+		if (doc.status=="Stopped") {
 			return [__("Stopped"), "red", "status,=,Stopped"];
-		} else if(doc.transfer_status && doc.docstatus != 2) {
+		} else if (doc.transfer_status && doc.docstatus != 2) {
 			if (doc.transfer_status == "Not Started") {
 				return [__("Not Started"), "orange"];
 			} else if (doc.transfer_status == "In Transit") {
@@ -11,14 +12,14 @@
 			} else if (doc.transfer_status == "Completed") {
 				return [__("Completed"), "green"];
 			}
-		} else if(doc.docstatus==1 && flt(doc.per_ordered, 2) == 0) {
+		} else if (doc.docstatus==1 && flt(doc.per_ordered, precision) == 0) {
 			return [__("Pending"), "orange", "per_ordered,=,0"];
-		}  else if(doc.docstatus==1 && flt(doc.per_ordered, 2) < 100) {
+		}  else if (doc.docstatus==1 && flt(doc.per_ordered, precision) < 100) {
 			return [__("Partially ordered"), "yellow", "per_ordered,<,100"];
-		} else if(doc.docstatus==1 && flt(doc.per_ordered, 2) == 100) {
-			if (doc.material_request_type == "Purchase" && flt(doc.per_received, 2) < 100 && flt(doc.per_received, 2) > 0) {
+		} else if (doc.docstatus==1 && flt(doc.per_ordered, precision) == 100) {
+			if (doc.material_request_type == "Purchase" && flt(doc.per_received, precision) < 100 && flt(doc.per_received, precision) > 0) {
 				return [__("Partially Received"), "yellow", "per_received,<,100"];
-			} else if (doc.material_request_type == "Purchase" && flt(doc.per_received, 2) == 100) {
+			} else if (doc.material_request_type == "Purchase" && flt(doc.per_received, precision) == 100) {
 				return [__("Received"), "green", "per_received,=,100"];
 			} else if (doc.material_request_type == "Purchase") {
 				return [__("Ordered"), "green", "per_ordered,=,100"];
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
index 55f0f0c..32d349f 100755
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
@@ -48,6 +48,7 @@
   "set_warehouse",
   "rejected_warehouse",
   "col_break_warehouse",
+  "set_from_warehouse",
   "is_subcontracted",
   "supplier_warehouse",
   "items_section",
@@ -115,6 +116,7 @@
   "per_returned",
   "is_internal_supplier",
   "inter_company_reference",
+  "represents_company",
   "subscription_detail",
   "auto_repeat",
   "printing_settings",
@@ -1087,7 +1089,9 @@
    "fieldname": "inter_company_reference",
    "fieldtype": "Link",
    "label": "Inter Company Reference",
+   "no_copy": 1,
    "options": "Delivery Note",
+   "print_hide": 1,
    "read_only": 1
   },
   {
@@ -1121,13 +1125,29 @@
    "no_copy": 1,
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "depends_on": "eval: doc.is_internal_supplier",
+   "description": "Sets 'From Warehouse' in each row of the items table.",
+   "fieldname": "set_from_warehouse",
+   "fieldtype": "Link",
+   "label": "Set From Warehouse",
+   "options": "Warehouse"
+  },
+  {
+   "fetch_from": "supplier.represents_company",
+   "fieldname": "represents_company",
+   "fieldtype": "Link",
+   "label": "Represents Company",
+   "options": "Company",
+   "read_only": 1
   }
  ],
  "icon": "fa fa-truck",
  "idx": 261,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-12-08 18:31:32.234503",
+ "modified": "2020-12-26 20:49:39.106049",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Purchase Receipt",
diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
index 662e50c..e991192 100644
--- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
+++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
@@ -76,6 +76,7 @@
   "purchase_order_item",
   "material_request_item",
   "purchase_receipt_item",
+  "delivery_note_item",
   "putaway_rule",
   "section_break_45",
   "allow_zero_valuation_rate",
@@ -819,11 +820,12 @@
    "read_only": 1
   },
   {
+   "depends_on": "eval:parent.is_internal_supplier",
    "fieldname": "from_warehouse",
    "fieldtype": "Link",
    "hidden": 1,
    "ignore_user_permissions": 1,
-   "label": "Supplier Warehouse",
+   "label": "From Warehouse",
    "options": "Warehouse"
   },
   {
@@ -871,12 +873,20 @@
    "fieldtype": "Float",
    "label": "Received Qty in Stock UOM",
    "print_hide": 1
+  },
+  {
+   "fieldname": "delivery_note_item",
+   "fieldtype": "Data",
+   "label": "Delivery Note Item",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1
   }
  ],
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-12-09 10:00:38.204294",
+ "modified": "2020-12-26 16:50:56.479347",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Purchase Receipt Item",
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 9aaa669..726118d 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -7,6 +7,14 @@
 
 frappe.ui.form.on('Stock Entry', {
 	setup: function(frm) {
+		frm.set_indicator_formatter('item_code', function(doc) {
+			if (!doc.s_warehouse) {
+				return 'blue';
+			} else {
+				return (doc.qty<=doc.actual_qty) ? 'green' : 'orange';
+			}
+		});
+
 		frm.set_query('work_order', function() {
 			return {
 				filters: [
@@ -782,15 +790,6 @@
 			}
 		}
 
-		this.frm.set_indicator_formatter('item_code',
-			function(doc) {
-				if (!doc.s_warehouse) {
-					return 'blue';
-				} else {
-					return (doc.qty<=doc.actual_qty) ? "green" : "orange"
-				}
-			})
-
 		this.frm.add_fetch("purchase_order", "supplier", "supplier");
 
 		frappe.dynamic_link = { doc: this.frm.doc, fieldname: 'supplier', doctype: 'Supplier' }
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index 5b9ada0..2b2a7a2 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -41,7 +41,7 @@
 
 			if sle.get("actual_qty") or sle.get("voucher_type")=="Stock Reconciliation":
 				sle_doc = make_entry(sle, allow_negative_stock, via_landed_cost_voucher)
-			
+
 			args = sle_doc.as_dict()
 			update_bin(args, allow_negative_stock, via_landed_cost_voucher)
 
@@ -65,7 +65,7 @@
 def repost_future_sle(args=None, voucher_type=None, voucher_no=None, allow_negative_stock=False, via_landed_cost_voucher=False):
 	if not args and voucher_type and voucher_no:
 		args = get_args_for_voucher(voucher_type, voucher_no)
-	
+
 	distinct_item_warehouses = [(d.item_code, d.warehouse) for d in args]
 
 	i = 0
@@ -80,7 +80,7 @@
 		for item_wh, new_sle in iteritems(obj.new_items):
 			if item_wh not in distinct_item_warehouses:
 				args.append(new_sle)
-		
+
 		i += 1
 
 def get_args_for_voucher(voucher_type, voucher_no):
@@ -127,7 +127,7 @@
 		self.initialize_previous_data(self.args)
 
 		self.build()
-	
+
 	def get_precision(self):
 		company_base_currency = frappe.get_cached_value('Company',  self.company,  "default_currency")
 		self.precision = get_field_precision(frappe.get_meta("Stock Ledger Entry").get_field("stock_value"),
@@ -213,13 +213,13 @@
 		# includes current entry!
 		args = self.data[self.args.warehouse].previous_sle \
 			or frappe._dict({"item_code": self.item_code, "warehouse": self.args.warehouse})
-		
+
 		return list(self.get_sle_after_datetime(args))
 
 	def get_dependent_entries_to_fix(self, entries_to_fix, sle):
 		dependant_sle = get_sle_by_voucher_detail_no(sle.dependant_sle_voucher_detail_no,
 			excluded_sle=sle.name)
-		
+
 		if not dependant_sle:
 			return
 		elif dependant_sle.item_code == self.item_code and dependant_sle.warehouse == self.args.warehouse:
@@ -251,7 +251,7 @@
 
 		# Get dynamic incoming/outgoing rate
 		self.get_dynamic_incoming_outgoing_rate(sle)
-		
+
 		if sle.serial_no:
 			self.get_serialized_values(sle)
 			self.wh_data.qty_after_transaction += flt(sle.actual_qty)
@@ -329,7 +329,7 @@
 				rate = get_rate_for_return(sle.voucher_type, sle.voucher_no, sle.item_code, voucher_detail_no=sle.voucher_detail_no)
 			else:
 				if sle.voucher_type in ("Purchase Receipt", "Purchase Invoice"):
-					rate_field = "valuation_rate" 
+					rate_field = "valuation_rate"
 				else:
 					rate_field = "incoming_rate"
 
@@ -344,7 +344,7 @@
 						ref_doctype = "Packed Item"
 					else:
 						ref_doctype = "Purchase Receipt Item Supplied"
-	
+
 					rate = frappe.db.get_value(ref_doctype, {"parent_detail_docname": sle.voucher_detail_no,
 						"item_code": sle.item_code}, rate_field)
 
@@ -374,7 +374,7 @@
 		stock_entry.db_update()
 		for d in stock_entry.items:
 			d.db_update()
-	
+
 	def update_rate_on_delivery_and_sales_return(self, sle, outgoing_rate):
 		# Update item's incoming rate on transaction
 		item_code = frappe.db.get_value(sle.voucher_type + " Item", sle.voucher_detail_no, "item_code")
@@ -487,7 +487,6 @@
 					self.wh_data.valuation_rate = new_stock_value / new_stock_qty
 				else:
 					self.wh_data.valuation_rate = sle.outgoing_rate
-
 		else:
 			if flt(self.wh_data.qty_after_transaction) >= 0 and sle.outgoing_rate:
 				self.wh_data.valuation_rate = sle.outgoing_rate
@@ -631,7 +630,7 @@
 				frappe.throw(message, NegativeStockError, title='Insufficient Stock')
 			else:
 				raise NegativeStockError(message)
-	
+
 	def update_bin(self):
 		# update bin for each warehouse
 		for warehouse, data in iteritems(self.data):
@@ -766,7 +765,7 @@
 	frappe.db.sql("""
 		update `tabStock Ledger Entry`
 		set qty_after_transaction = qty_after_transaction + {qty}
-		where 
+		where
 			item_code = %(item_code)s
 			and warehouse = %(warehouse)s
 			and voucher_no != %(voucher_no)s
@@ -794,7 +793,7 @@
 				frappe.get_desk_link('Warehouse', args.warehouse),
 				sle[0]["posting_date"], sle[0]["posting_time"],
 				frappe.get_desk_link(sle[0]["voucher_type"], sle[0]["voucher_no"]))
-						
+
 			frappe.throw(message, NegativeStockError, title='Insufficient Stock')
 
 def get_future_sle_with_negative_qty(args):
@@ -803,7 +802,7 @@
 			qty_after_transaction, posting_date, posting_time,
 			voucher_type, voucher_no
 		from `tabStock Ledger Entry`
-		where 
+		where
 			item_code = %(item_code)s
 			and warehouse = %(warehouse)s
 			and voucher_no != %(voucher_no)s
diff --git a/erpnext/templates/includes/macros.html b/erpnext/templates/includes/macros.html
index ea6b00f..5d8ee5c 100644
--- a/erpnext/templates/includes/macros.html
+++ b/erpnext/templates/includes/macros.html
@@ -40,7 +40,7 @@
 		<div class="col-md-{{ section.column_value }} mb-4">
 			<div class="card h-100 justify-content-between">
 				{% if card.image %}
-				<div class="website-image-lazy" data-class="card-img-top h-100" data-src="{{ card.image }}" data-alt="{{ card.title }}"></div>
+				<div class="website-image-lazy" data-class="card-img-top h-75" data-src="{{ card.image }}" data-alt="{{ card.title }}"></div>
 				{% endif %}
 				<div class="card-body">
 					<h5 class="card-title">{{ card.title }}</h5>