Merge branch 'develop' into barredterra-patch-1
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.js b/erpnext/accounts/doctype/pos_profile/pos_profile.js
index ef431d7..8ec6a53 100755
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.js
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.js
@@ -31,8 +31,7 @@
 		frm.set_query("print_format", function() {
 			return {
 				filters: [
-					['Print Format', 'doc_type', '=', 'Sales Invoice'],
-					['Print Format', 'print_format_type', '=', 'Jinja'],
+					['Print Format', 'doc_type', '=', 'POS Invoice']
 				]
 			};
 		});
@@ -45,10 +44,6 @@
 			};
 		});
 
-		frm.set_query("print_format", function() {
-			return { filters: { doc_type: "Sales Invoice", print_format_type: "JS"} };
-		});
-
 		frm.set_query('company_address', function(doc) {
 			if(!doc.company) {
 				frappe.throw(__('Please set Company'));
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/__init__.py b/erpnext/accounts/doctype/process_statement_of_accounts/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/__init__.py
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html
new file mode 100644
index 0000000..e1ddeff
--- /dev/null
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html
@@ -0,0 +1,89 @@
+<h1 class="text-center" style="page-break-before:always">{{ filters.party[0] }}</h1>
+<h3 class="text-center">{{ _("Statement of Accounts") }}</h3>
+
+<h5 class="text-center">
+    {{ frappe.format(filters.from_date, 'Date')}}
+	{{ _("to") }}
+	{{ frappe.format(filters.to_date, 'Date')}}
+</h5>
+
+<table class="table table-bordered">
+	<thead>
+		<tr>
+			<th style="width: 12%">{{ _("Date") }}</th>
+			<th style="width: 15%">{{ _("Ref") }}</th>
+			<th style="width: 25%">{{ _("Party") }}</th>
+			<th style="width: 15%">{{ _("Debit") }}</th>
+			<th style="width: 15%">{{ _("Credit") }}</th>
+			<th style="width: 18%">{{ _("Balance (Dr - Cr)") }}</th>
+		</tr>
+	</thead>
+	<tbody>
+        {% for row in data %}
+			<tr>
+			{% if(row.posting_date) %}
+				<td>{{ frappe.format(row.posting_date, 'Date') }}</td>
+				<td>{{ row.voucher_type }}
+					<br>{{ row.voucher_no }}</td>
+				<td>
+					{% if not (filters.party or filters.account)  %}
+						{{ row.party or row.account }}
+						<br>
+					{% endif %}
+
+					{{ _("Against") }}: {{ row.against }}
+					<br>{{ _("Remarks") }}: {{ row.remarks }}
+					{% if row.bill_no %}
+						<br>{{ _("Supplier Invoice No") }}: {{ row.bill_no }}
+					{% endif %}
+					</td>
+					<td style="text-align: right">
+						{{ frappe.utils.fmt_money(row.debit, filters.presentation_currency) }}</td>
+					<td style="text-align: right">
+						{{ frappe.utils.fmt_money(row.credit, filters.presentation_currency) }}</td>
+			{% else %}
+				<td></td>
+				<td></td>
+				<td><b>{{ frappe.format(row.account, {fieldtype: "Link"}) or "&nbsp;" }}</b></td>
+				<td style="text-align: right">
+					{{ row.account and frappe.utils.fmt_money(row.debit, filters.presentation_currency) }}
+				</td>
+				<td style="text-align: right">
+					{{ row.account and frappe.utils.fmt_money(row.credit, filters.presentation_currency) }}
+				</td>
+			{% endif %}
+				<td style="text-align: right">
+					{{ frappe.utils.fmt_money(row.balance, filters.presentation_currency) }}
+				</td>
+			</tr>
+		{% endfor %}
+		</tbody>
+</table>
+<br><br>
+{% if aging %}
+<h3 class="text-center">{{ _("Ageing Report Based On ") }} {{ aging.ageing_based_on }}</h3>
+<h5 class="text-center">
+	{{ _("Up to " ) }}  {{ frappe.format(filters.to_date, 'Date')}}
+</h5>
+<br>
+
+<table class="table table-bordered">
+	<thead>
+		<tr>
+			<th style="width: 12%">30 Days</th>
+			<th style="width: 15%">60 Days</th>
+			<th style="width: 25%">90 Days</th>
+			<th style="width: 15%">120 Days</th>
+		</tr>
+	</thead>
+	<tbody>
+		<tr>
+			<td>{{ aging.range1 }}</td>
+			<td>{{ aging.range2 }}</td>
+			<td>{{ aging.range3 }}</td>
+			<td>{{ aging.range4 }}</td>
+		</tr>
+	</tbody>
+</table>
+{% endif %}
+<p class="text-right text-muted">Printed On {{ frappe.format(frappe.utils.get_datetime(), 'Datetime') }}</p>
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js
new file mode 100644
index 0000000..7425132
--- /dev/null
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js
@@ -0,0 +1,132 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Process Statement Of Accounts', {
+	view_properties: function(frm) {
+		frappe.route_options = {doc_type: 'Customer'};
+		frappe.set_route("Form", "Customize Form");
+	},
+	refresh: function(frm){
+		if(!frm.doc.__islocal) {
+			frm.add_custom_button('Send Emails',function(){
+				frappe.call({
+					method: "erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.send_emails",
+					args: {
+						"document_name": frm.doc.name,
+					},
+					callback: function(r) {
+						if(r && r.message) {
+							frappe.show_alert({message: __('Emails Queued'), indicator: 'blue'});
+						}
+						else{
+							frappe.msgprint('No Records for these settings.')
+						}
+					}
+				});
+			});
+			frm.add_custom_button('Download',function(){
+				var url = frappe.urllib.get_full_url(
+					'/api/method/erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.download_statements?'
+					+ 'document_name='+encodeURIComponent(frm.doc.name))
+				$.ajax({
+					url: url,
+					type: 'GET',
+					success: function(result) {
+						if(jQuery.isEmptyObject(result)){
+							frappe.msgprint('No Records for these settings.');
+						}
+						else{
+							window.location = url;
+						}
+					}
+				});
+			});
+		}
+	},
+	onload: function(frm) {
+		frm.set_query('currency', function(){
+			return {
+				filters: {
+					'enabled': 1
+				}
+			}
+		});
+		if(frm.doc.__islocal){
+			frm.set_value('from_date', frappe.datetime.add_months(frappe.datetime.get_today(), -1));
+			frm.set_value('to_date', frappe.datetime.get_today());
+		}
+	},
+	customer_collection: function(frm){
+		frm.set_value('collection_name', '');
+		if(frm.doc.customer_collection){
+			frm.get_field('collection_name').set_label(frm.doc.customer_collection);
+		}
+	},
+	frequency: function(frm){
+		if(frm.doc.frequency != ''){
+			frm.set_value('start_date', frappe.datetime.get_today());
+		}
+		else{
+			frm.set_value('start_date', '');
+		}
+	},
+	fetch_customers: function(frm){
+		if(frm.doc.collection_name){
+			frappe.call({
+				method: "erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.fetch_customers",
+				args: {
+					'customer_collection': frm.doc.customer_collection,
+					'collection_name': frm.doc.collection_name,
+					'primary_mandatory': frm.doc.primary_mandatory
+				},
+				callback: function(r) {
+					if(!r.exc) {
+						if(r.message.length){
+							frm.clear_table('customers');
+							for (const customer of r.message){
+								var row = frm.add_child('customers');
+								row.customer = customer.name;
+								row.primary_email = customer.primary_email;
+								row.billing_email = customer.billing_email;
+							}
+							frm.refresh_field('customers');
+						}
+						else{
+							frappe.msgprint('No Customers found with selected options.');
+						}
+					}
+				}
+			});
+		}
+		else {
+			frappe.throw('Enter ' + frm.doc.customer_collection + ' name.');
+		}
+	}
+});
+
+frappe.ui.form.on('Process Statement Of Accounts Customer', {
+	customer: function(frm, cdt, cdn){
+		var row = locals[cdt][cdn];
+		if (!row.customer){
+			return;
+		}
+		frappe.call({
+			method: 'erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.get_customer_emails',
+			args: {
+				'customer_name': row.customer,
+				'primary_mandatory': frm.doc.primary_mandatory
+			},
+			callback: function(r){
+				if(!r.exe){
+					if(r.message.length){
+						frappe.model.set_value(cdt, cdn, "primary_email", r.message[0])
+						frappe.model.set_value(cdt, cdn, "billing_email", r.message[1])
+					}
+					else {
+						return
+					}
+				}
+			}
+		})
+	}
+});
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json
new file mode 100644
index 0000000..4be0e2e
--- /dev/null
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json
@@ -0,0 +1,310 @@
+{
+ "actions": [],
+ "allow_workflow": 1,
+ "autoname": "Prompt",
+ "creation": "2020-05-22 16:46:18.712954",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "section_break_11",
+  "from_date",
+  "company",
+  "account",
+  "group_by",
+  "cost_center",
+  "column_break_14",
+  "to_date",
+  "finance_book",
+  "currency",
+  "project",
+  "section_break_3",
+  "customer_collection",
+  "collection_name",
+  "fetch_customers",
+  "column_break_6",
+  "primary_mandatory",
+  "column_break_17",
+  "customers",
+  "preferences",
+  "orientation",
+  "section_break_14",
+  "include_ageing",
+  "ageing_based_on",
+  "section_break_1",
+  "enable_auto_email",
+  "section_break_18",
+  "frequency",
+  "filter_duration",
+  "column_break_21",
+  "start_date",
+  "section_break_33",
+  "subject",
+  "column_break_28",
+  "cc_to",
+  "section_break_30",
+  "body",
+  "help_text"
+ ],
+ "fields": [
+  {
+   "fieldname": "frequency",
+   "fieldtype": "Select",
+   "label": "Frequency",
+   "options": "Weekly\nMonthly\nQuarterly"
+  },
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1
+  },
+  {
+   "depends_on": "eval:doc.enable_auto_email == 0;",
+   "fieldname": "from_date",
+   "fieldtype": "Date",
+   "label": "From Date",
+   "mandatory_depends_on": "eval:doc.frequency == '';"
+  },
+  {
+   "depends_on": "eval:doc.enable_auto_email == 0;",
+   "fieldname": "to_date",
+   "fieldtype": "Date",
+   "label": "To Date",
+   "mandatory_depends_on": "eval:doc.frequency == '';"
+  },
+  {
+   "fieldname": "cost_center",
+   "fieldtype": "Table MultiSelect",
+   "label": "Cost Center",
+   "options": "PSOA Cost Center"
+  },
+  {
+   "fieldname": "project",
+   "fieldtype": "Table MultiSelect",
+   "label": "Project",
+   "options": "PSOA Project"
+  },
+  {
+   "fieldname": "section_break_3",
+   "fieldtype": "Section Break",
+   "label": "Customers"
+  },
+  {
+   "fieldname": "column_break_6",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "section_break_11",
+   "fieldtype": "Section Break",
+   "label": "General Ledger Filters"
+  },
+  {
+   "fieldname": "column_break_14",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "column_break_17",
+   "fieldtype": "Section Break",
+   "hide_border": 1
+  },
+  {
+   "fieldname": "customer_collection",
+   "fieldtype": "Select",
+   "label": "Select Customers By",
+   "options": "\nCustomer Group\nTerritory\nSales Partner\nSales Person"
+  },
+  {
+   "depends_on": "eval: doc.customer_collection !== ''",
+   "fieldname": "collection_name",
+   "fieldtype": "Dynamic Link",
+   "label": "Recipient",
+   "options": "customer_collection"
+  },
+  {
+   "fieldname": "section_break_1",
+   "fieldtype": "Section Break",
+   "label": "Email Settings"
+  },
+  {
+   "fieldname": "account",
+   "fieldtype": "Link",
+   "label": "Account",
+   "options": "Account"
+  },
+  {
+   "fieldname": "finance_book",
+   "fieldtype": "Link",
+   "label": "Finance Book",
+   "options": "Finance Book"
+  },
+  {
+   "fieldname": "preferences",
+   "fieldtype": "Section Break",
+   "label": "Print Preferences"
+  },
+  {
+   "fieldname": "orientation",
+   "fieldtype": "Select",
+   "label": "Orientation",
+   "options": "Landscape\nPortrait"
+  },
+  {
+   "default": "Today",
+   "fieldname": "start_date",
+   "fieldtype": "Date",
+   "label": "Start Date"
+  },
+  {
+   "default": "Group by Voucher (Consolidated)",
+   "fieldname": "group_by",
+   "fieldtype": "Select",
+   "label": "Group By",
+   "options": "\nGroup by Voucher\nGroup by Voucher (Consolidated)"
+  },
+  {
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "label": "Currency",
+   "options": "Currency"
+  },
+  {
+   "default": "0",
+   "fieldname": "include_ageing",
+   "fieldtype": "Check",
+   "in_list_view": 1,
+   "label": "Include Ageing Summary"
+  },
+  {
+   "default": "Due Date",
+   "depends_on": "eval:doc.include_ageing === 1",
+   "fieldname": "ageing_based_on",
+   "fieldtype": "Select",
+   "label": "Ageing Based On",
+   "options": "Due Date\nPosting Date"
+  },
+  {
+   "default": "0",
+   "fieldname": "enable_auto_email",
+   "fieldtype": "Check",
+   "in_list_view": 1,
+   "label": "Enable Auto Email"
+  },
+  {
+   "fieldname": "section_break_14",
+   "fieldtype": "Column Break",
+   "hide_border": 1
+  },
+  {
+   "depends_on": "eval: doc.enable_auto_email ==1",
+   "fieldname": "section_break_18",
+   "fieldtype": "Section Break",
+   "hide_border": 1
+  },
+  {
+   "fieldname": "column_break_21",
+   "fieldtype": "Column Break"
+  },
+  {
+   "depends_on": "eval: doc.customer_collection !== ''",
+   "fieldname": "fetch_customers",
+   "fieldtype": "Button",
+   "label": "Fetch Customers",
+   "options": "fetch_customers",
+   "print_hide": 1,
+   "report_hide": 1
+  },
+  {
+   "default": "1",
+   "fieldname": "primary_mandatory",
+   "fieldtype": "Check",
+   "label": "Send To Primary Contact"
+  },
+  {
+   "fieldname": "cc_to",
+   "fieldtype": "Link",
+   "label": "CC To",
+   "options": "User"
+  },
+  {
+   "default": "1",
+   "fieldname": "filter_duration",
+   "fieldtype": "Int",
+   "label": "Filter Duration (Months)"
+  },
+  {
+   "fieldname": "customers",
+   "fieldtype": "Table",
+   "label": "Customers",
+   "options": "Process Statement Of Accounts Customer",
+   "reqd": 1
+  },
+  {
+   "fieldname": "column_break_28",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "section_break_30",
+   "fieldtype": "Section Break",
+   "hide_border": 1
+  },
+  {
+   "fieldname": "section_break_33",
+   "fieldtype": "Section Break",
+   "hide_border": 1
+  },
+  {
+   "fieldname": "help_text",
+   "fieldtype": "HTML",
+   "label": "Help Text",
+   "options": "<br>\n<h4>Note</h4>\n<ul>\n<li>\nYou can use <a href=\"https://jinja.palletsprojects.com/en/2.11.x/\" target=\"_blank\">Jinja tags</a> in <b>Subject</b> and <b>Body</b> fields for dynamic values.\n</li><li>\n    All fields in this doctype are available under the <b>doc</b> object and all fields for the customer to whom the mail will go to is available under the  <b>customer</b> object.\n</li></ul>\n<h4> Examples</h4>\n<!-- {% raw %} -->\n<ul>\n    <li><b>Subject</b>:<br><br><pre><code>Statement Of Accounts for {{ customer.name }}</code></pre><br></li>\n    <li><b>Body</b>: <br><br>\n<pre><code>Hello {{ customer.name }},<br>PFA your Statement Of Accounts from {{ doc.from_date }} to {{ doc.to_date }}.</code> </pre></li>\n</ul>\n<!-- {% endraw %} -->"
+  },
+  {
+   "fieldname": "subject",
+   "fieldtype": "Data",
+   "label": "Subject"
+  },
+  {
+   "fieldname": "body",
+   "fieldtype": "Text Editor",
+   "label": "Body"
+  }
+ ],
+ "links": [],
+ "modified": "2020-08-08 08:47:09.185728",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Process Statement Of Accounts",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts User",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts Manager",
+   "share": 1,
+   "write": 1
+  }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
new file mode 100644
index 0000000..d50e4a8
--- /dev/null
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
@@ -0,0 +1,271 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+from erpnext.accounts.report.general_ledger.general_ledger import execute as get_soa
+from erpnext.accounts.report.accounts_receivable_summary.accounts_receivable_summary import execute as get_ageing
+from frappe.core.doctype.communication.email import make
+
+from frappe.utils.print_format import report_to_pdf
+from frappe.utils.pdf import get_pdf
+from frappe.utils import today, add_days, add_months, getdate, format_date
+from frappe.utils.jinja import validate_template
+
+import copy
+from datetime import timedelta
+from frappe.www.printview import get_print_style
+
+class ProcessStatementOfAccounts(Document):
+	def validate(self):
+		if not self.subject:
+			self.subject = 'Statement Of Accounts for {{ customer.name }}'
+		if not self.body:
+			self.body = 'Hello {{ customer.name }},<br>PFA your Statement Of Accounts from {{ doc.from_date }} to {{ doc.to_date }}.'
+
+		validate_template(self.subject)
+		validate_template(self.body)
+
+		if not self.customers:
+			frappe.throw(frappe._('Customers not selected.'))
+
+		if self.enable_auto_email:
+			self.to_date = self.start_date
+			self.from_date = add_months(self.to_date, -1 * self.filter_duration)
+
+
+def get_report_pdf(doc, consolidated=True):
+	statement_dict = {}
+	aging = ''
+	base_template_path = "frappe/www/printview.html"
+	template_path = "erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html"
+
+	for entry in doc.customers:
+		if doc.include_ageing:
+			ageing_filters = frappe._dict({
+				'company': doc.company,
+				'report_date': doc.to_date,
+				'ageing_based_on': doc.ageing_based_on,
+				'range1': 30,
+				'range2': 60,
+				'range3': 90,
+				'range4': 120,
+				'customer': entry.customer
+			})
+			col1, aging = get_ageing(ageing_filters)
+			aging[0]['ageing_based_on'] = doc.ageing_based_on
+
+		tax_id = frappe.get_doc('Customer', entry.customer).tax_id
+
+		filters= frappe._dict({
+			'from_date': doc.from_date,
+			'to_date': doc.to_date,
+			'company': doc.company,
+			'finance_book': doc.finance_book if doc.finance_book else None,
+			"account": doc.account if doc.account else None,
+			'party_type': 'Customer',
+			'party': [entry.customer],
+			'group_by': doc.group_by,
+			'currency': doc.currency,
+			'cost_center': [cc.cost_center_name for cc in doc.cost_center],
+			'project': [p.project_name for p in doc.project],
+			'show_opening_entries': 0,
+			'include_default_book_entries': 0,
+			'show_cancelled_entries': 1,
+			'tax_id': tax_id if tax_id else None
+		})
+		col, res = get_soa(filters)
+
+		for x in [0, -2, -1]:
+			res[x]['account'] = res[x]['account'].replace("'","")
+
+		if len(res) == 3:
+			continue
+		html = frappe.render_template(template_path, \
+			{"filters": filters, "data": res, "aging": aging[0] if doc.include_ageing else None})
+		html = frappe.render_template(base_template_path, {"body": html, \
+			"css": get_print_style(), "title": "Statement For " + entry.customer})
+		statement_dict[entry.customer] = html
+	if not bool(statement_dict):
+		return False
+	elif consolidated:
+		result = ''.join(list(statement_dict.values()))
+		return get_pdf(result, {'orientation': doc.orientation})
+	else:
+		for customer, statement_html in statement_dict.items():
+			statement_dict[customer]=get_pdf(statement_html, {'orientation': doc.orientation})
+		return statement_dict
+
+def get_customers_based_on_territory_or_customer_group(customer_collection, collection_name):
+	fields_dict = {
+		'Customer Group': 'customer_group',
+		'Territory': 'territory',
+	}
+	collection = frappe.get_doc(customer_collection, collection_name)
+	selected = [customer.name for customer in frappe.get_list(customer_collection, filters=[
+			['lft', '>=', collection.lft],
+			['rgt', '<=', collection.rgt]
+		],
+		fields=['name'],
+		order_by='lft asc, rgt desc'
+	)]
+	return frappe.get_list('Customer', fields=['name', 'email_id'], \
+		filters=[[fields_dict[customer_collection], 'IN', selected]])
+
+def get_customers_based_on_sales_person(sales_person):
+	lft, rgt = frappe.db.get_value("Sales Person",
+		sales_person, ["lft", "rgt"])
+	records = frappe.db.sql("""
+		select distinct parent, parenttype
+		from `tabSales Team` steam
+		where parenttype = 'Customer'
+			and exists(select name from `tabSales Person` where lft >= %s and rgt <= %s and name = steam.sales_person)
+	""", (lft, rgt), as_dict=1)
+	sales_person_records = frappe._dict()
+	for d in records:
+		sales_person_records.setdefault(d.parenttype, set()).add(d.parent)
+	customers = frappe.get_list('Customer', fields=['name', 'email_id'], \
+			filters=[['name', 'in', list(sales_person_records['Customer'])]])
+	return customers
+
+def get_recipients_and_cc(customer, doc):
+	recipients = []
+	for clist in doc.customers:
+		if clist.customer == customer:
+			recipients.append(clist.billing_email)
+			if doc.primary_mandatory and clist.primary_email:
+				recipients.append(clist.primary_email)
+	cc = []
+	if doc.cc_to != '':
+		try:
+			cc=[frappe.get_value('User', doc.cc_to, 'email')]
+		except:
+			pass
+
+	return recipients, cc
+
+def get_context(customer, doc):
+	template_doc = copy.deepcopy(doc)
+	del template_doc.customers
+	template_doc.from_date = format_date(template_doc.from_date)
+	template_doc.to_date = format_date(template_doc.to_date)
+	return {
+		'doc': template_doc,
+		'customer': frappe.get_doc('Customer', customer),
+		'frappe': frappe.utils
+	}
+
+@frappe.whitelist()
+def fetch_customers(customer_collection, collection_name, primary_mandatory):
+	customer_list = []
+	customers = []
+
+	if customer_collection == 'Sales Person':
+		customers = get_customers_based_on_sales_person(collection_name)
+		if not bool(customers):
+			frappe.throw('No Customers found with selected options.')
+	else:
+		if customer_collection == 'Sales Partner':
+			customers = frappe.get_list('Customer', fields=['name', 'email_id'], \
+				filters=[['default_sales_partner', '=', collection_name]])
+		else:
+			customers = get_customers_based_on_territory_or_customer_group(customer_collection, collection_name)
+
+	for customer in customers:
+		primary_email = customer.get('email_id') or ''
+		billing_email = get_customer_emails(customer.name, 1, billing_and_primary=False)
+
+		if billing_email == '' or (primary_email == '' and int(primary_mandatory)):
+			continue
+
+		customer_list.append({
+			'name': customer.name,
+			'primary_email': primary_email,
+			'billing_email': billing_email
+		})
+	return customer_list
+
+@frappe.whitelist()
+def get_customer_emails(customer_name, primary_mandatory, billing_and_primary=True):
+	billing_email = frappe.db.sql("""
+		SELECT c.email_id FROM `tabContact` AS c JOIN `tabDynamic Link` AS l ON c.name=l.parent \
+		WHERE l.link_doctype='Customer' and l.link_name='""" + customer_name + """' and \
+		c.is_billing_contact=1 \
+		order by c.creation desc""")
+
+	if len(billing_email) == 0 or (billing_email[0][0] is None):
+		if billing_and_primary:
+			frappe.throw('No billing email found for customer: '+ customer_name)
+		else:
+			return ''
+
+	if billing_and_primary:
+		primary_email =  frappe.get_value('Customer', customer_name, 'email_id')
+		if primary_email is None and int(primary_mandatory):
+			frappe.throw('No primary email found for customer: '+ customer_name)
+		return [primary_email or '', billing_email[0][0]]
+	else:
+		return billing_email[0][0] or ''
+
+@frappe.whitelist()
+def download_statements(document_name):
+	doc = frappe.get_doc('Process Statement Of Accounts', document_name)
+	report = get_report_pdf(doc)
+	if report:
+		frappe.local.response.filename = doc.name + '.pdf'
+		frappe.local.response.filecontent = report
+		frappe.local.response.type = "download"
+
+@frappe.whitelist()
+def send_emails(document_name, from_scheduler=False):
+	doc = frappe.get_doc('Process Statement Of Accounts', document_name)
+	report = get_report_pdf(doc, consolidated=False)
+
+	if report:
+		for customer, report_pdf in report.items():
+			attachments = [{
+				'fname': customer + '.pdf',
+				'fcontent': report_pdf
+			}]
+
+			recipients, cc = get_recipients_and_cc(customer, doc)
+			context = get_context(customer, doc)
+			subject = frappe.render_template(doc.subject, context)
+			message = frappe.render_template(doc.body, context)
+
+			frappe.enqueue(
+				queue='short',
+				method=frappe.sendmail,
+				recipients=recipients,
+				sender=frappe.session.user,
+				cc=cc,
+				subject=subject,
+				message=message,
+				now=True,
+				reference_doctype='Process Statement Of Accounts',
+				reference_name=document_name,
+				attachments=attachments
+			)
+
+		if doc.enable_auto_email and from_scheduler:
+			new_to_date = getdate(today())
+			if doc.frequency == 'Weekly':
+				new_to_date = add_days(new_to_date, 7)
+			else:
+				new_to_date = add_months(new_to_date, 1 if doc.frequency == 'Monthly' else 3)
+			new_from_date = add_months(new_to_date, -1 * doc.filter_duration)
+			doc.add_comment('Comment', 'Emails sent on: ' + frappe.utils.format_datetime(frappe.utils.now()))
+			doc.db_set('to_date', new_to_date, commit=True)
+			doc.db_set('from_date', new_from_date, commit=True)
+		return True
+	else:
+		return False
+
+@frappe.whitelist()
+def send_auto_email():
+	selected = frappe.get_list('Process Statement Of Accounts', filters={'to_date': format_date(today()), 'enable_auto_email': 1})
+	for entry in selected:
+		send_emails(entry.name, from_scheduler=True)
+	return True
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py
new file mode 100644
index 0000000..30efbb3
--- /dev/null
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestProcessStatementOfAccounts(unittest.TestCase):
+	pass
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts_customer/__init__.py b/erpnext/accounts/doctype/process_statement_of_accounts_customer/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/process_statement_of_accounts_customer/__init__.py
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.json b/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.json
new file mode 100644
index 0000000..dd04dc1
--- /dev/null
+++ b/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.json
@@ -0,0 +1,47 @@
+{
+ "actions": [],
+ "allow_workflow": 1,
+ "creation": "2020-08-03 16:35:21.852178",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "customer",
+  "billing_email",
+  "primary_email"
+ ],
+ "fields": [
+  {
+   "fieldname": "customer",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Customer",
+   "options": "Customer",
+   "reqd": 1
+  },
+  {
+   "fieldname": "primary_email",
+   "fieldtype": "Read Only",
+   "in_list_view": 1,
+   "label": "Primary Contact Email"
+  },
+  {
+   "fieldname": "billing_email",
+   "fieldtype": "Read Only",
+   "in_list_view": 1,
+   "label": "Billing Email"
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-08-03 22:55:38.875601",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Process Statement Of Accounts Customer",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.py b/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.py
new file mode 100644
index 0000000..1a76010
--- /dev/null
+++ b/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class ProcessStatementOfAccountsCustomer(Document):
+	pass
diff --git a/erpnext/accounts/doctype/psoa_cost_center/__init__.py b/erpnext/accounts/doctype/psoa_cost_center/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/psoa_cost_center/__init__.py
diff --git a/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.json b/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.json
new file mode 100644
index 0000000..e292b60
--- /dev/null
+++ b/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.json
@@ -0,0 +1,30 @@
+{
+ "actions": [],
+ "creation": "2020-08-03 16:56:45.744905",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "cost_center_name"
+ ],
+ "fields": [
+  {
+   "fieldname": "cost_center_name",
+   "fieldtype": "Link",
+   "label": "Cost Center",
+   "options": "Cost Center"
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-08-03 16:56:45.744905",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "PSOA Cost Center",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.py b/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.py
new file mode 100644
index 0000000..0aeef3e
--- /dev/null
+++ b/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class PSOACostCenter(Document):
+	pass
diff --git a/erpnext/accounts/doctype/psoa_project/__init__.py b/erpnext/accounts/doctype/psoa_project/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/psoa_project/__init__.py
diff --git a/erpnext/accounts/doctype/psoa_project/psoa_project.json b/erpnext/accounts/doctype/psoa_project/psoa_project.json
new file mode 100644
index 0000000..20a03ee
--- /dev/null
+++ b/erpnext/accounts/doctype/psoa_project/psoa_project.json
@@ -0,0 +1,30 @@
+{
+ "actions": [],
+ "creation": "2020-08-03 16:52:14.731978",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "project_name"
+ ],
+ "fields": [
+  {
+   "fieldname": "project_name",
+   "fieldtype": "Link",
+   "label": "Project",
+   "options": "Project"
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-08-03 16:53:39.219736",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "PSOA Project",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/psoa_project/psoa_project.py b/erpnext/accounts/doctype/psoa_project/psoa_project.py
new file mode 100644
index 0000000..f4a5dee
--- /dev/null
+++ b/erpnext/accounts/doctype/psoa_project/psoa_project.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class PSOAProject(Document):
+	pass
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index 2e91c8e..d62e73b 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -180,7 +180,7 @@
    "no_copy": 1,
    "oldfieldname": "naming_series",
    "oldfieldtype": "Select",
-   "options": "ACC-PINV-.YYYY.-",
+   "options": "ACC-PINV-.YYYY.-\nACC-PINV-RET-.YYYY.-",
    "print_hide": 1,
    "reqd": 1,
    "set_only_once": 1
@@ -1334,7 +1334,7 @@
  "idx": 204,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-08-03 12:46:01.411074",
+ "modified": "2020-08-03 23:20:04.466153",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Purchase Invoice",
@@ -1396,4 +1396,4 @@
  "timeline_field": "supplier",
  "title_field": "title",
  "track_changes": 1
-}
\ No newline at end of file
+}
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index 4dc81e9..31613e5 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -1,7 +1,6 @@
 {
  "actions": [],
  "allow_import": 1,
- "allow_workflow": 1,
  "autoname": "naming_series:",
  "creation": "2013-05-24 19:29:05",
  "doctype": "DocType",
@@ -217,7 +216,7 @@
    "no_copy": 1,
    "oldfieldname": "naming_series",
    "oldfieldtype": "Select",
-   "options": "ACC-SINV-.YYYY.-",
+   "options": "ACC-SINV-.YYYY.-\nACC-SINV-RET-.YYYY.-",
    "print_hide": 1,
    "reqd": 1,
    "set_only_once": 1
@@ -1947,7 +1946,7 @@
  "idx": 181,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-07-18 05:07:16.725974",
+ "modified": "2020-08-03 23:31:12.675040",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Sales Invoice",
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 964566a..9660c95 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -206,10 +206,19 @@
 			"rate": 14,
 			'included_in_print_rate': 1
 		})
+		si.append("taxes", {
+			"charge_type": "On Item Quantity",
+			"account_head": "_Test Account Education Cess - _TC",
+			"cost_center": "_Test Cost Center - _TC",
+			"description": "CESS",
+			"rate": 5,
+			'included_in_print_rate': 1
+		})
 		si.insert()
 
 		# with inclusive tax
-		self.assertEqual(si.net_total, 4385.96)
+		self.assertEqual(si.items[0].net_amount, 3947.368421052631)
+		self.assertEqual(si.net_total, 3947.37)
 		self.assertEqual(si.grand_total, 5000)
 
 		si.reload()
@@ -222,8 +231,8 @@
 		si.save()
 
 		# with inclusive tax and additional discount
-		self.assertEqual(si.net_total, 4285.96)
-		self.assertEqual(si.grand_total, 4885.99)
+		self.assertEqual(si.net_total, 3847.37)
+		self.assertEqual(si.grand_total, 4886)
 
 		si.reload()
 
@@ -235,7 +244,7 @@
 		si.save()
 
 		# with inclusive tax and additional discount
-		self.assertEqual(si.net_total, 4298.25)
+		self.assertEqual(si.net_total, 3859.65)
 		self.assertEqual(si.grand_total, 4900.00)
 
 	def test_sales_invoice_discount_amount(self):
diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template_dashboard.py b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template_dashboard.py
index 0e9c808..d825c6f 100644
--- a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template_dashboard.py
+++ b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template_dashboard.py
@@ -8,7 +8,7 @@
 		'fieldname': 'taxes_and_charges',
 		'non_standard_fieldnames': {
 			'Tax Rule': 'sales_tax_template',
-			'Subscription': 'tax_template',
+			'Subscription': 'sales_tax_template',
 			'Restaurant': 'default_tax_template'
 		},
 		'transactions': [
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index 28a6519..2f800bb 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -611,7 +611,7 @@
 			cond = "posting_date <= '{0}'".format(posting_date)
 
 	if company:
-		cond += "and company = '{0}'".format(company)
+		cond += "and company = {0}".format(frappe.db.escape(company))
 
 	data = frappe.db.sql(""" SELECT party, sum({0}) as amount
 		FROM `tabGL Entry`
diff --git a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py
index 148357f..34facd8 100644
--- a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py
+++ b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py
@@ -11,7 +11,7 @@
 
 class AssetMaintenanceLog(Document):
 	def validate(self):
-		if getdate(self.due_date) < getdate(nowdate()):
+		if getdate(self.due_date) < getdate(nowdate()) and self.maintenance_status not in ["Completed", "Cancelled"]:
 			self.maintenance_status = "Overdue"
 
 		if self.maintenance_status == "Completed" and not self.completion_date:
diff --git a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log_list.js b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log_list.js
index b854413..23000e6 100644
--- a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log_list.js
+++ b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log_list.js
@@ -1,14 +1,15 @@
 frappe.listview_settings['Asset Maintenance Log'] = {
 	add_fields: ["maintenance_status"],
+	has_indicator_for_draft: 1,
 	get_indicator: function(doc) {
-		if(doc.maintenance_status=="Pending") {
-			return [__("Pending"), "orange"];
-		} else if(doc.maintenance_status=="Completed") {
-			return [__("Completed"), "green"];
-		} else if(doc.maintenance_status=="Cancelled") {
-			return [__("Cancelled"), "red"];
-		} else if(doc.maintenance_status=="Overdue") {
-			return [__("Overdue"), "red"];
+		if (doc.maintenance_status=="Planned") {
+			return [__(doc.maintenance_status), "orange", "status,=," + doc.maintenance_status];
+		} else if (doc.maintenance_status=="Completed") {
+			return [__(doc.maintenance_status), "green", "status,=," + doc.maintenance_status];
+		} else if (doc.maintenance_status=="Cancelled") {
+			return [__(doc.maintenance_status), "red", "status,=," + doc.maintenance_status];
+		} else if (doc.maintenance_status=="Overdue") {
+			return [__(doc.maintenance_status), "red", "status,=," + doc.maintenance_status];
 		}
 	}
 };
diff --git a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py
index 155597e..fd702c7 100644
--- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py
+++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py
@@ -8,6 +8,7 @@
 from frappe.utils import flt, getdate, cint, date_diff, formatdate
 from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts
 from frappe.model.document import Document
+from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_checks_for_pl_and_bs_accounts
 
 class AssetValueAdjustment(Document):
 	def validate(self):
@@ -53,17 +54,33 @@
 		je.company = self.company
 		je.remark = "Depreciation Entry against {0} worth {1}".format(self.asset, self.difference_amount)
 
-		je.append("accounts", {
+		credit_entry = {
 			"account": accumulated_depreciation_account,
 			"credit_in_account_currency": self.difference_amount,
 			"cost_center": depreciation_cost_center or self.cost_center
-		})
+		}
 
-		je.append("accounts", {
+		debit_entry = {
 			"account": depreciation_expense_account,
 			"debit_in_account_currency": self.difference_amount,
 			"cost_center": depreciation_cost_center or self.cost_center
-		})
+		}
+
+		accounting_dimensions = get_checks_for_pl_and_bs_accounts()
+
+		for dimension in accounting_dimensions:
+			if dimension.get('mandatory_for_bs'):
+				credit_entry.update({
+					dimension['fieldname']: self.get(dimension['fieldname']) or dimension.get('default_dimension')
+				})
+
+			if dimension.get('mandatory_for_pl'):
+				debit_entry.update({
+					dimension['fieldname']: self.get(dimension['fieldname']) or dimension.get('default_dimension')
+				})
+		
+		je.append("accounts", credit_entry)
+		je.append("accounts", debit_entry)
 
 		je.flags.ignore_permissions = True
 		je.submit()
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index 25065ab..9f2b971 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -94,7 +94,7 @@
 				if(this.frm.doc.status !== 'Closed' && flt(this.frm.doc.per_received) < 100 && flt(this.frm.doc.per_billed) < 100) {
 					this.frm.add_custom_button(__('Update Items'), () => {
 						erpnext.utils.update_child_items({
-							frm: frm,
+							frm: this.frm,
 							child_docname: "items",
 							child_doctype: "Purchase Order Detail",
 							cannot_add_row: false,
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 89c38c7..3091193 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -479,7 +479,11 @@
 			if d.against_order:
 				allocated_amount = flt(d.amount)
 			else:
-				amount = self.rounded_total or self.grand_total
+				if self.get('party_account_currency') == self.company_currency:
+					amount = self.get('base_rounded_total') or self.base_grand_total
+				else:
+					amount = self.get('rounded_total') or self.grand_total
+
 				allocated_amount = min(amount - advance_allocated, d.amount)
 			advance_allocated += flt(allocated_amount)
 
@@ -802,10 +806,22 @@
 			self.payment_terms_template = ''
 			return
 
+		party_account_currency = self.get('party_account_currency')
+		if not party_account_currency:
+			party_type, party = self.get_party()
+
+			if party_type and party:
+				party_account_currency = get_party_account_currency(party_type, party, self.company)
+
 		posting_date = self.get("bill_date") or self.get("posting_date") or self.get("transaction_date")
 		date = self.get("due_date")
 		due_date = date or posting_date
-		grand_total = self.get("rounded_total") or self.grand_total
+
+		if party_account_currency == self.company_currency:
+			grand_total = self.get("base_rounded_total") or self.base_grand_total
+		else:
+			grand_total = self.get("rounded_total") or self.grand_total
+
 		if self.doctype in ("Sales Invoice", "Purchase Invoice"):
 			grand_total = grand_total - flt(self.write_off_amount)
 
@@ -850,13 +866,25 @@
 	def validate_payment_schedule_amount(self):
 		if self.doctype == 'Sales Invoice' and self.is_pos: return
 
+		party_account_currency = self.get('party_account_currency')
+		if not party_account_currency:
+			party_type, party = self.get_party()
+
+			if party_type and party:
+				party_account_currency = get_party_account_currency(party_type, party, self.company)
+
 		if self.get("payment_schedule"):
 			total = 0
 			for d in self.get("payment_schedule"):
 				total += flt(d.payment_amount)
-			total = flt(total, self.precision("grand_total"))
 
-			grand_total = flt(self.get("rounded_total") or self.grand_total, self.precision('grand_total'))
+			if party_account_currency == self.company_currency:
+				total = flt(total, self.precision("base_grand_total"))
+				grand_total = flt(self.get("base_rounded_total") or self.base_grand_total, self.precision('base_grand_total'))
+			else:
+				total = flt(total, self.precision("grand_total"))
+				grand_total = flt(self.get("rounded_total") or self.grand_total, self.precision('grand_total'))
+
 			if self.get("total_advance"):
 				grand_total -= self.get("total_advance")
 
@@ -957,7 +985,7 @@
 			# all rows about the reffered tax should be inclusive
 			_on_previous_row_error("1 - %d" % (tax.row_id,))
 		elif tax.get("category") == "Valuation":
-			frappe.throw(_("Valuation type charges can not marked as Inclusive"))
+			frappe.throw(_("Valuation type charges can not be marked as Inclusive"))
 
 
 def set_balance_in_account_currency(gl_dict, account_currency=None, conversion_rate=None, company_currency=None):
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index babc5bd..37b7e31 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -613,9 +613,12 @@
 	if not taxes:
 		return frappe.db.sql(""" SELECT name FROM `tabItem Tax Template` """)
 	else:
+		valid_from = filters.get('valid_from')
+		valid_from = valid_from[1] if isinstance(valid_from, list) else valid_from
+
 		args = {
 			'item_code': filters.get('item_code'),
-			'posting_date': filters.get('valid_from'),
+			'posting_date': valid_from,
 			'tax_category': filters.get('tax_category'),
 			'company': filters.get('company')
 		}
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 572e1ca..8f86dce 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -161,8 +161,9 @@
 		for item in self.doc.get("items"):
 			item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
 			cumulated_tax_fraction = 0
+			total_inclusive_tax_amount_per_qty = 0
 			for i, tax in enumerate(self.doc.get("taxes")):
-				tax.tax_fraction_for_current_item = self.get_current_tax_fraction(tax, item_tax_map)
+				tax.tax_fraction_for_current_item, inclusive_tax_amount_per_qty = self.get_current_tax_fraction(tax, item_tax_map)
 
 				if i==0:
 					tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item
@@ -172,9 +173,12 @@
 						+ tax.tax_fraction_for_current_item
 
 				cumulated_tax_fraction += tax.tax_fraction_for_current_item
+				total_inclusive_tax_amount_per_qty += inclusive_tax_amount_per_qty * flt(item.stock_qty)
 
-			if cumulated_tax_fraction and not self.discount_amount_applied and item.qty:
-				item.net_amount = flt(item.amount / (1 + cumulated_tax_fraction))
+			if not self.discount_amount_applied and item.qty and (cumulated_tax_fraction or total_inclusive_tax_amount_per_qty):
+				amount = flt(item.amount) - total_inclusive_tax_amount_per_qty
+
+				item.net_amount = flt(amount / (1 + cumulated_tax_fraction))
 				item.net_rate = flt(item.net_amount / item.qty, item.precision("net_rate"))
 				item.discount_percentage = flt(item.discount_percentage,
 					item.precision("discount_percentage"))
@@ -190,6 +194,7 @@
 			from tax inclusive amount
 		"""
 		current_tax_fraction = 0
+		inclusive_tax_amount_per_qty = 0
 
 		if cint(tax.included_in_print_rate):
 			tax_rate = self._get_tax_rate(tax, item_tax_map)
@@ -204,10 +209,15 @@
 			elif tax.charge_type == "On Previous Row Total":
 				current_tax_fraction = (tax_rate / 100.0) * \
 					self.doc.get("taxes")[cint(tax.row_id) - 1].grand_total_fraction_for_current_item
+			
+			elif tax.charge_type == "On Item Quantity":
+				inclusive_tax_amount_per_qty = flt(tax_rate)
 
-		if getattr(tax, "add_deduct_tax", None):
-			current_tax_fraction *= -1.0 if (tax.add_deduct_tax == "Deduct") else 1.0
-		return current_tax_fraction
+		if getattr(tax, "add_deduct_tax", None) and tax.add_deduct_tax == "Deduct":
+			current_tax_fraction *= -1.0
+			inclusive_tax_amount_per_qty *= -1.0
+
+		return current_tax_fraction, inclusive_tax_amount_per_qty
 
 	def _get_tax_rate(self, tax, item_tax_map):
 		if tax.account_head in item_tax_map:
@@ -321,7 +331,7 @@
 			current_tax_amount = (tax_rate / 100.0) * \
 				self.doc.get("taxes")[cint(tax.row_id) - 1].grand_total_for_current_item
 		elif tax.charge_type == "On Item Quantity":
-			current_tax_amount = tax_rate * item.stock_qty
+			current_tax_amount = tax_rate * item.qty
 
 		self.set_item_wise_tax(item, tax, tax_rate, current_tax_amount)
 
@@ -472,7 +482,7 @@
 			actual_taxes_dict = {}
 
 			for tax in self.doc.get("taxes"):
-				if tax.charge_type == "Actual":
+				if tax.charge_type in ["Actual", "On Item Quantity"]:
 					tax_amount = self.get_tax_amount_if_for_valuation_or_deduction(tax.tax_amount, tax)
 					actual_taxes_dict.setdefault(tax.idx, tax_amount)
 				elif tax.row_id in actual_taxes_dict:
diff --git a/erpnext/crm/doctype/opportunity/opportunity.json b/erpnext/crm/doctype/opportunity/opportunity.json
index 545e232..5cd5233 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.json
+++ b/erpnext/crm/doctype/opportunity/opportunity.json
@@ -16,6 +16,7 @@
   "opportunity_from",
   "party_name",
   "customer_name",
+  "source",
   "column_break0",
   "title",
   "opportunity_type",
@@ -49,10 +50,9 @@
   "contact_email",
   "contact_mobile",
   "more_info",
-  "source",
+  "company",
   "campaign",
   "column_break1",
-  "company",
   "transaction_date",
   "amended_from",
   "lost_reasons"
@@ -344,7 +344,7 @@
    "collapsible": 1,
    "fieldname": "more_info",
    "fieldtype": "Section Break",
-   "label": "Source",
+   "label": "More Information",
    "oldfieldtype": "Section Break",
    "options": "fa fa-file-text"
   },
@@ -424,7 +424,7 @@
  "icon": "fa fa-info-sign",
  "idx": 195,
  "links": [],
- "modified": "2020-07-14 16:49:15.888503",
+ "modified": "2020-08-11 17:34:35.066961",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Opportunity",
diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py
index 1b071ea..e152850 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.py
+++ b/erpnext/crm/doctype/opportunity/opportunity.py
@@ -119,11 +119,19 @@
 				and q.status not in ('Lost', 'Closed')""", self.name)
 
 	def has_ordered_quotation(self):
-		return frappe.db.sql("""
-			select q.name
-			from `tabQuotation` q, `tabQuotation Item` qi
-			where q.name = qi.parent and q.docstatus=1 and qi.prevdoc_docname =%s
-			and q.status = 'Ordered'""", self.name)
+		if not self.with_items:
+			return frappe.get_all('Quotation',
+				{
+					'opportunity': self.name,
+					'status': 'Ordered',
+					'docstatus': 1
+				}, 'name')
+		else:
+			return frappe.db.sql("""
+				select q.name
+				from `tabQuotation` q, `tabQuotation Item` qi
+				where q.name = qi.parent and q.docstatus=1 and qi.prevdoc_docname =%s
+				and q.status = 'Ordered'""", self.name)
 
 	def has_lost_quotation(self):
 		lost_quotation = frappe.db.sql("""
@@ -330,7 +338,7 @@
 	opportunity = frappe.get_doc({
 		"doctype": "Opportunity",
 		"opportunity_from": opportunity_from,
-		"lead": lead
+		"party_name": lead
 	}).insert(ignore_permissions=True)
 
 	link_communication_to_document(doc, "Opportunity", opportunity.name, ignore_communication_links)
diff --git a/erpnext/education/doctype/fees/test_fees.py b/erpnext/education/doctype/fees/test_fees.py
index b182992..eedc2ae 100644
--- a/erpnext/education/doctype/fees/test_fees.py
+++ b/erpnext/education/doctype/fees/test_fees.py
@@ -7,7 +7,7 @@
 import unittest
 from frappe.utils import nowdate
 from frappe.utils.make_random import get_random
-
+from erpnext.education.doctype.program.test_program import make_program_and_linked_courses
 
 # test_records = frappe.get_test_records('Fees')
 
@@ -15,6 +15,7 @@
 
 	def test_fees(self):
 		student = get_random("Student")
+		program = make_program_and_linked_courses("_Test Program 1", ["_Test Course 1", "_Test Course 2"])
 		fee = frappe.new_doc("Fees")
 		fee.posting_date = nowdate()
 		fee.due_date = nowdate()
@@ -23,6 +24,7 @@
 		fee.income_account = "Sales - _TC"
 		fee.cost_center = "_Test Cost Center - _TC"
 		fee.company = "_Test Company"
+		fee.program = program.name
 
 		fee.extend("components", [
 			{
diff --git a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.js b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.js
index 971e166..60f0f9d 100644
--- a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.js
+++ b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.js
@@ -134,7 +134,7 @@
 			{fieldtype: 'Link', label: 'Leave From', fieldname: 'leave_from', options: 'Healthcare Service Unit', reqd: 1, read_only:1},
 			{fieldtype: 'Link', label: 'Service Unit Type', fieldname: 'service_unit_type', options: 'Healthcare Service Unit Type'},
 			{fieldtype: 'Link', label: 'Transfer To', fieldname: 'service_unit', options: 'Healthcare Service Unit', reqd: 1},
-			{fieldtype: 'Datetime', label: 'Check In', fieldname: 'check_in', reqd: 1}
+			{fieldtype: 'Datetime', label: 'Check In', fieldname: 'check_in', reqd: 1, default: frappe.datetime.now_datetime()}
 		],
 		primary_action_label: __('Transfer'),
 		primary_action : function() {
@@ -147,7 +147,12 @@
 			if(dialog.get_value('service_unit')){
 				service_unit = dialog.get_value('service_unit');
 			}
-			if(!check_in){
+			if(check_in > frappe.datetime.now_datetime()){
+				frappe.msgprint({
+					title: __('Not Allowed'),
+					message: __('Check-in time cannot be greater than the current time'),
+					indicator: 'red'
+				});
 				return;
 			}
 			frappe.call({
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 95a836f..463ad6c 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -322,7 +322,8 @@
 		"erpnext.crm.doctype.email_campaign.email_campaign.set_email_campaign_status",
 		"erpnext.selling.doctype.quotation.quotation.set_expired_status",
 		"erpnext.healthcare.doctype.patient_appointment.patient_appointment.update_appointment_status",
-		"erpnext.buying.doctype.supplier_quotation.supplier_quotation.set_expired_status"
+		"erpnext.buying.doctype.supplier_quotation.supplier_quotation.set_expired_status",
+		"erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.send_auto_email"
 	],
 	"daily_long": [
 		"erpnext.setup.doctype.email_digest.email_digest.send",
diff --git a/erpnext/hr/desk_page/hr/hr.json b/erpnext/hr/desk_page/hr/hr.json
index 0fed8d3..895cf72 100644
--- a/erpnext/hr/desk_page/hr/hr.json
+++ b/erpnext/hr/desk_page/hr/hr.json
@@ -78,7 +78,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "HR",
- "modified": "2020-06-16 19:20:50.976045",
+ "modified": "2020-08-11 17:04:38.655417",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "HR",
@@ -88,7 +88,7 @@
  "pin_to_top": 0,
  "shortcuts": [
   {
-   "color": "#9deca2",
+   "color": "#cef6d1",
    "format": "{} Active",
    "label": "Employee",
    "link_to": "Employee",
@@ -96,12 +96,7 @@
    "type": "DocType"
   },
   {
-   "label": "Attendance",
-   "link_to": "Attendance",
-   "stats_filter": "",
-   "type": "DocType"
-  },
-  {
+   "color": "#ffe8cd",
    "format": "{} Open",
    "label": "Leave Application",
    "link_to": "Leave Application",
@@ -109,6 +104,12 @@
    "type": "DocType"
   },
   {
+   "label": "Attendance",
+   "link_to": "Attendance",
+   "stats_filter": "",
+   "type": "DocType"
+  },
+  {
    "label": "Job Applicant",
    "link_to": "Job Applicant",
    "type": "DocType"
diff --git a/erpnext/manufacturing/report/downtime_analysis/downtime_analysis.js b/erpnext/manufacturing/report/downtime_analysis/downtime_analysis.js
index ff32dbe..f648674 100644
--- a/erpnext/manufacturing/report/downtime_analysis/downtime_analysis.js
+++ b/erpnext/manufacturing/report/downtime_analysis/downtime_analysis.js
@@ -8,7 +8,7 @@
 			label: __("From Date"),
 			fieldname:"from_date",
 			fieldtype: "Datetime",
-			default: frappe.datetime.add_months(frappe.datetime.now_datetime(), -1),
+			default: frappe.datetime.convert_to_system_tz(frappe.datetime.add_months(frappe.datetime.now_datetime(), -1)),
 			reqd: 1
 		},
 		{
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 49af0ba..6777497 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -718,3 +718,5 @@
 erpnext.patches.v12_0.update_item_tax_template_company
 erpnext.patches.v13_0.move_branch_code_to_bank_account
 erpnext.patches.v13_0.healthcare_lab_module_rename_doctypes
+erpnext.patches.v13_0.stock_entry_enhancements
+erpnext.patches.v12_0.update_state_code_for_daman_and_diu
diff --git a/erpnext/patches/v12_0/stock_entry_enhancements.py b/erpnext/patches/v12_0/stock_entry_enhancements.py
index d04b3d3..847d928 100644
--- a/erpnext/patches/v12_0/stock_entry_enhancements.py
+++ b/erpnext/patches/v12_0/stock_entry_enhancements.py
@@ -19,7 +19,7 @@
 
 	for purpose in ["Material Issue", "Material Receipt", "Material Transfer",
 		"Material Transfer for Manufacture", "Material Consumption for Manufacture", "Manufacture",
-		"Repack", "Send to Subcontractor", "Send to Warehouse", "Receive at Warehouse"]:
+		"Repack", "Send to Subcontractor"]:
 
 		ste_type = frappe.get_doc({
 			'doctype': 'Stock Entry Type',
diff --git a/erpnext/patches/v12_0/update_state_code_for_daman_and_diu.py b/erpnext/patches/v12_0/update_state_code_for_daman_and_diu.py
new file mode 100644
index 0000000..7450e9c
--- /dev/null
+++ b/erpnext/patches/v12_0/update_state_code_for_daman_and_diu.py
@@ -0,0 +1,22 @@
+import frappe
+from erpnext.regional.india import states
+
+def execute():
+
+	company = frappe.get_all('Company', filters = {'country': 'India'})
+	if not company:
+		return
+
+	# Update options in gst_state custom field
+	gst_state = frappe.get_doc('Custom Field', 'Address-gst_state')
+	gst_state.options = '\n'.join(states)
+	gst_state.save()
+
+	# Update gst_state and state code in existing address
+	frappe.db.sql("""
+		UPDATE `tabAddress`
+		SET
+			gst_state = 'Dadra and Nagar Haveli and Daman and Diu',
+			gst_state_number = 26
+		WHERE gst_state = 'Daman and Diu'
+	""")
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/stock_entry_enhancements.py b/erpnext/patches/v13_0/stock_entry_enhancements.py
new file mode 100644
index 0000000..dcc4f95
--- /dev/null
+++ b/erpnext/patches/v13_0/stock_entry_enhancements.py
@@ -0,0 +1,27 @@
+# Copyright(c) 2020, Frappe Technologies Pvt.Ltd.and Contributors
+# License: GNU General Public License v3.See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+    frappe.reload_doc("stock", "doctype", "stock_entry")
+    if frappe.db.has_column("Stock Entry", "add_to_transit"):
+        frappe.db.sql("""
+            UPDATE `tabStock Entry` SET 
+            stock_entry_type = 'Material Transfer',
+            purpose = 'Material Transfer',
+            add_to_transit = 1 WHERE stock_entry_type = 'Send to Warehouse'
+            """)
+
+        frappe.db.sql("""UPDATE `tabStock Entry` SET 
+            stock_entry_type = 'Material Transfer',
+            purpose = 'Material Transfer'
+            WHERE stock_entry_type = 'Receive at Warehouse'
+            """)
+        
+        frappe.reload_doc("stock", "doctype", "warehouse_type")
+        if not frappe.db.exists('Warehouse Type', 'Transit'):
+            doc = frappe.new_doc('Warehouse Type')
+            doc.name = 'Transit'
+            doc.insert()
\ No newline at end of file
diff --git a/erpnext/payroll/desk_page/payroll/payroll.json b/erpnext/payroll/desk_page/payroll/payroll.json
index b5eac46..285e3b3 100644
--- a/erpnext/payroll/desk_page/payroll/payroll.json
+++ b/erpnext/payroll/desk_page/payroll/payroll.json
@@ -8,7 +8,7 @@
   {
    "hidden": 0,
    "label": "Taxation",
-   "links": "[\n    {\n        \"label\": \"Payroll Period\",\n        \"name\": \"Payroll Period\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Income Tax Slab\",\n        \"name\": \"Income Tax Slab\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Declaration\",\n        \"name\": \"Employee Tax Exemption Declaration\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Proof Submission\",\n        \"name\": \"Employee Tax Exemption Proof Submission\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Category\",\n        \"name\": \"Employee Tax Exemption Category\",\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Sub Category\",\n        \"name\": \"Employee Tax Exemption Sub Category\",\n        \"type\": \"doctype\"\n        \n    }\n]"
+   "links": "[\n    {\n        \"label\": \"Payroll Period\",\n        \"name\": \"Payroll Period\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Income Tax Slab\",\n        \"name\": \"Income Tax Slab\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Other Income\",\n        \"name\": \"Employee Other Income\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Declaration\",\n        \"name\": \"Employee Tax Exemption Declaration\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Proof Submission\",\n        \"name\": \"Employee Tax Exemption Proof Submission\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Category\",\n        \"name\": \"Employee Tax Exemption Category\",\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Sub Category\",\n        \"name\": \"Employee Tax Exemption Sub Category\",\n        \"type\": \"doctype\"\n        \n    }\n]"
   },
   {
    "hidden": 0,
@@ -38,7 +38,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "Payroll",
- "modified": "2020-06-19 12:23:06.034046",
+ "modified": "2020-08-10 19:38:45.976209",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Payroll",
diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
index 554484f..30ea432 100644
--- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
+++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
@@ -90,7 +90,7 @@
 		cond = ''
 		for f in ['company', 'branch', 'department', 'designation']:
 			if self.get(f):
-				cond += " and t1." + f + " = '" + self.get(f).replace("'", "\'") + "'"
+				cond += " and t1." + f + " = " + frappe.db.escape(self.get(f))
 
 		return cond
 
diff --git a/erpnext/public/js/communication.js b/erpnext/public/js/communication.js
index 5316eb4..9432d42 100644
--- a/erpnext/public/js/communication.js
+++ b/erpnext/public/js/communication.js
@@ -13,7 +13,7 @@
 				frappe.confirm(__(confirm_msg, [__("Issue")]), () => {
 					frm.trigger('make_issue_from_communication');
 				})
-			}, "Make");
+			}, "Create");
 		}
 
 		if(!in_list(["Lead", "Opportunity"], frm.doc.reference_doctype)) {
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index 405a33c..6951539 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -163,9 +163,11 @@
 		$.each(me.frm.doc["items"] || [], function(n, item) {
 			var item_tax_map = me._load_item_tax_rate(item.item_tax_rate);
 			var cumulated_tax_fraction = 0.0;
-
+			var total_inclusive_tax_amount_per_qty = 0;
 			$.each(me.frm.doc["taxes"] || [], function(i, tax) {
-				tax.tax_fraction_for_current_item = me.get_current_tax_fraction(tax, item_tax_map);
+				var current_tax_fraction = me.get_current_tax_fraction(tax, item_tax_map);
+				tax.tax_fraction_for_current_item = current_tax_fraction[0];
+				var inclusive_tax_amount_per_qty = current_tax_fraction[1];
 
 				if(i==0) {
 					tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item;
@@ -176,10 +178,12 @@
 				}
 
 				cumulated_tax_fraction += tax.tax_fraction_for_current_item;
+				total_inclusive_tax_amount_per_qty += inclusive_tax_amount_per_qty * flt(item.qty);
 			});
 
-			if(cumulated_tax_fraction && !me.discount_amount_applied) {
-				item.net_amount = flt(item.amount / (1 + cumulated_tax_fraction));
+			if(!me.discount_amount_applied && item.qty && (total_inclusive_tax_amount_per_qty || cumulated_tax_fraction)) {
+				var amount = flt(item.amount) - total_inclusive_tax_amount_per_qty;
+				item.net_amount = flt(amount / (1 + cumulated_tax_fraction));
 				item.net_rate = item.qty ? flt(item.net_amount / item.qty, precision("net_rate", item)) : 0;
 
 				me.set_in_company_currency(item, ["net_rate", "net_amount"]);
@@ -191,6 +195,7 @@
 		// Get tax fraction for calculating tax exclusive amount
 		// from tax inclusive amount
 		var current_tax_fraction = 0.0;
+		var inclusive_tax_amount_per_qty = 0;
 
 		if(cint(tax.included_in_print_rate)) {
 			var tax_rate = this._get_tax_rate(tax, item_tax_map);
@@ -205,13 +210,16 @@
 			} else if(tax.charge_type == "On Previous Row Total") {
 				current_tax_fraction = (tax_rate / 100.0) *
 					this.frm.doc["taxes"][cint(tax.row_id) - 1].grand_total_fraction_for_current_item;
+			} else if (tax.charge_type == "On Item Quantity") {
+				inclusive_tax_amount_per_qty = flt(tax_rate);
 			}
 		}
 
-		if(tax.add_deduct_tax) {
-			current_tax_fraction *= (tax.add_deduct_tax == "Deduct") ? -1.0 : 1.0;
+		if(tax.add_deduct_tax && tax.add_deduct_tax == "Deduct") {
+			current_tax_fraction *= -1;
+			inclusive_tax_amount_per_qty *= -1;
 		}
-		return current_tax_fraction;
+		return [current_tax_fraction, inclusive_tax_amount_per_qty];
 	},
 
 	_get_tax_rate: function(tax, item_tax_map) {
@@ -360,8 +368,9 @@
 		} else if(tax.charge_type == "On Previous Row Total") {
 			current_tax_amount = (tax_rate / 100.0) *
 				this.frm.doc["taxes"][cint(tax.row_id) - 1].grand_total_for_current_item;
+		} else if (tax.charge_type == "On Item Quantity") {
+			current_tax_amount = tax_rate * item.qty;
 		}
-
 		this.set_item_wise_tax(item, tax, tax_rate, current_tax_amount);
 
 		return current_tax_amount;
@@ -573,7 +582,7 @@
 			var actual_taxes_dict = {};
 
 			$.each(this.frm.doc["taxes"] || [], function(i, tax) {
-				if (tax.charge_type == "Actual") {
+				if (in_list(["Actual", "On Item Quantity"], tax.charge_type)) {
 					var tax_amount = (tax.category == "Valuation") ? 0.0 : tax.tax_amount;
 					tax_amount *= (tax.add_deduct_tax == "Deduct") ? -1.0 : 1.0;
 					actual_taxes_dict[tax.idx] = tax_amount;
@@ -586,7 +595,7 @@
 			$.each(actual_taxes_dict, function(key, value) {
 				if (value) total_actual_tax += value;
 			});
-
+			
 			return flt(this.frm.doc.grand_total - total_actual_tax, precision("grand_total"));
 		}
 	},
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 4e50f3d..436a232 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -1821,7 +1821,6 @@
 	},
 
 	set_query_for_item_tax_template: function(doc, cdt, cdn) {
-
 		var item = frappe.get_doc(cdt, cdn);
 		if(!item.item_code) {
 			frappe.throw(__("Please enter Item Code to get item taxes"));
@@ -1829,7 +1828,7 @@
 
 			let filters = {
 				'item_code': item.item_code,
-				'valid_from': doc.transaction_date || doc.bill_date || doc.posting_date,
+				'valid_from': ["<=", doc.transaction_date || doc.bill_date || doc.posting_date],
 				'item_group': item.item_group,
 			}
 
diff --git a/erpnext/public/less/website.less b/erpnext/public/less/website.less
index 57a0a33..ac878de 100644
--- a/erpnext/public/less/website.less
+++ b/erpnext/public/less/website.less
@@ -297,6 +297,10 @@
 	margin-top: 30px;
 }
 
+.item-group-slideshow {
+	margin-bottom: 1rem;
+}
+
 .product-image-img {
 	border: 1px solid @light-border-color;
 	border-radius: 3px;
diff --git a/erpnext/regional/india/__init__.py b/erpnext/regional/india/__init__.py
index 0ed98b7..d6221a8 100644
--- a/erpnext/regional/india/__init__.py
+++ b/erpnext/regional/india/__init__.py
@@ -10,8 +10,7 @@
  'Bihar',
  'Chandigarh',
  'Chhattisgarh',
- 'Dadra and Nagar Haveli',
- 'Daman and Diu',
+ 'Dadra and Nagar Haveli and Daman and Diu',
  'Delhi',
  'Goa',
  'Gujarat',
@@ -50,8 +49,7 @@
  "Bihar": "10",
  "Chandigarh": "04",
  "Chhattisgarh": "22",
- "Dadra and Nagar Haveli": "26",
- "Daman and Diu": "25",
+ "Dadra and Nagar Haveli and Daman and Diu": "26",
  "Delhi": "07",
  "Goa": "30",
  "Gujarat": "24",
diff --git a/erpnext/regional/india/gst_state_code_data.json b/erpnext/regional/india/gst_state_code_data.json
index 6dab81d..ff88e0f 100644
--- a/erpnext/regional/india/gst_state_code_data.json
+++ b/erpnext/regional/india/gst_state_code_data.json
@@ -135,14 +135,9 @@
   "state_name": "Delhi"
  },
  {
-  "state_number": "25",
-  "state_code": "DD",
-  "state_name": "Daman and Diu"
- },
- {
   "state_number": "26",
   "state_code": "DN",
-  "state_name": "Dadra and Nagar Haveli"
+  "state_name": "Dadra and Nagar Haveli and Daman and Diu"
  },
  {
   "state_number": "22",
diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py
index 8885b88..282efe4 100644
--- a/erpnext/regional/report/gstr_1/gstr_1.py
+++ b/erpnext/regional/report/gstr_1/gstr_1.py
@@ -131,6 +131,9 @@
 					taxable_value += abs(net_amount)
 				elif tax_rate:
 					taxable_value += abs(net_amount)
+				elif not tax_rate and self.filters.get('type_of_business') == 'EXPORT' \
+					and invoice_details.get('export_type') == "Without Payment of Tax":
+					taxable_value += abs(net_amount)
 
 		row += [tax_rate or 0, taxable_value]
 
diff --git a/erpnext/selling/doctype/customer/customer_dashboard.py b/erpnext/selling/doctype/customer/customer_dashboard.py
index 22e30e3..09e474d 100644
--- a/erpnext/selling/doctype/customer/customer_dashboard.py
+++ b/erpnext/selling/doctype/customer/customer_dashboard.py
@@ -12,7 +12,8 @@
 			'Payment Entry': 'party',
 			'Quotation': 'party_name',
 			'Opportunity': 'party_name',
-			'Bank Account': 'party'
+			'Bank Account': 'party',
+			'Subscription': 'party'
 		},
 		'dynamic_links': {
 			'party_name': ['Customer', 'quotation_to']
diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js
index 483ef78..ae5471b 100644
--- a/erpnext/selling/page/point_of_sale/pos_controller.js
+++ b/erpnext/selling/page/point_of_sale/pos_controller.js
@@ -35,7 +35,8 @@
 	create_opening_voucher() {
 		const table_fields = [
 			{ fieldname: "mode_of_payment", fieldtype: "Link", in_list_view: 1, label: "Mode of Payment", options: "Mode of Payment", reqd: 1 },
-			{ fieldname: "opening_amount", fieldtype: "Currency", in_list_view: 1, label: "Opening Amount", options: "company:company_currency", reqd: 1 }
+			{ fieldname: "opening_amount", fieldtype: "Currency", default: 0, in_list_view: 1, label: "Opening Amount", 
+				options: "company:company_currency", reqd: 1 }
 		];
 
 		const dialog = new frappe.ui.Dialog({
@@ -66,7 +67,7 @@
 							frappe.db.get_doc("POS Closing Entry", pos_closing_entry.name).then(({ payment_reconciliation }) => {
 								dialog.fields_dict.balance_details.df.data = [];
 								payment_reconciliation.forEach(pay => {
-									const { mode_of_payment, closing_amount } = pay;
+									const { mode_of_payment } = pay;
 									dialog.fields_dict.balance_details.df.data.push({
 										mode_of_payment: mode_of_payment
 									});
@@ -152,7 +153,7 @@
 			},
 			() => this.make_new_invoice(),
 			() => frappe.dom.unfreeze(),
-			() => this.page.set_title(__('Point of Sale Beta')),
+			() => this.page.set_title(__('Point of Sale')),
 		]);
 	}
 
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index 7ae5385..f882db6 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -34,6 +34,16 @@
 		frm.set_query("default_buying_terms", function() {
 			return { filters: { buying: 1 } };
 		});
+
+		frm.set_query("default_in_transit_warehouse", function() {
+			return {
+				filters:{
+					'warehouse_type' : 'Transit',
+					'is_group': 0,
+					'company': frm.doc.company
+				}
+			};
+		});
 	},
 
 	company_name: function(frm) {
diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json
index 221044d..4a26a71 100644
--- a/erpnext/setup/doctype/company/company.json
+++ b/erpnext/setup/doctype/company/company.json
@@ -25,6 +25,7 @@
   "default_selling_terms",
   "default_buying_terms",
   "default_warehouse_for_sales_return",
+  "default_in_transit_warehouse",
   "column_break_10",
   "country",
   "create_chart_of_accounts_based_on",
@@ -242,7 +243,7 @@
   {
    "fieldname": "default_warehouse_for_sales_return",
    "fieldtype": "Link",
-   "label": "Default warehouse for Sales Return",
+   "label": "Default Warehouse for Sales Return",
    "options": "Warehouse"
   },
   {
@@ -733,6 +734,12 @@
    "fieldname": "enable_perpetual_inventory_for_non_stock_items",
    "fieldtype": "Check",
    "label": "Enable Perpetual Inventory For Non Stock Items"
+  },
+  {
+   "fieldname": "default_in_transit_warehouse",
+   "fieldtype": "Link",
+   "label": "Default In Transit Warehouse",
+   "options": "Warehouse"
   }
  ],
  "icon": "fa fa-building",
@@ -740,7 +747,7 @@
  "image_field": "company_logo",
  "is_tree": 1,
  "links": [],
- "modified": "2020-06-24 12:45:31.462195",
+ "modified": "2020-08-06 00:38:08.311216",
  "modified_by": "Administrator",
  "module": "Setup",
  "name": "Company",
@@ -801,4 +808,4 @@
  "sort_field": "modified",
  "sort_order": "ASC",
  "track_changes": 1
-}
\ No newline at end of file
+}
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index 47b41a9..8e707fe 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -140,7 +140,8 @@
 			{"warehouse_name": _("All Warehouses"), "is_group": 1},
 			{"warehouse_name": _("Stores"), "is_group": 0},
 			{"warehouse_name": _("Work In Progress"), "is_group": 0},
-			{"warehouse_name": _("Finished Goods"), "is_group": 0}]:
+			{"warehouse_name": _("Finished Goods"), "is_group": 0},
+			{"warehouse_name": _("Goods In Transit"), "is_group": 0, "warehouse_type": "Transit"}]:
 
 			if not frappe.db.exists("Warehouse", "{0} - {1}".format(wh_detail["warehouse_name"], self.abbr)):
 				warehouse = frappe.get_doc({
@@ -149,7 +150,8 @@
 					"is_group": wh_detail["is_group"],
 					"company": self.name,
 					"parent_warehouse": "{0} - {1}".format(_("All Warehouses"), self.abbr) \
-						if not wh_detail["is_group"] else ""
+						if not wh_detail["is_group"] else "",
+					"warehouse_type" : wh_detail["warehouse_type"] if "warehouse_type" in wh_detail else None
 				})
 				warehouse.flags.ignore_permissions = True
 				warehouse.flags.ignore_mandatory = True
diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py
index ad063cf..72ed002 100644
--- a/erpnext/setup/setup_wizard/operations/install_fixtures.py
+++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py
@@ -95,8 +95,6 @@
 		{'doctype': 'Stock Entry Type', 'name': 'Send to Subcontractor', 'purpose': 'Send to Subcontractor'},
 		{'doctype': 'Stock Entry Type', 'name': 'Material Transfer for Manufacture', 'purpose': 'Material Transfer for Manufacture'},
 		{'doctype': 'Stock Entry Type', 'name': 'Material Consumption for Manufacture', 'purpose': 'Material Consumption for Manufacture'},
-		{'doctype': 'Stock Entry Type', 'name': 'Send to Warehouse', 'purpose': 'Send to Warehouse'},
-		{'doctype': 'Stock Entry Type', 'name': 'Receive at Warehouse', 'purpose': 'Receive at Warehouse'},
 
 		# Designation
 		{'doctype': 'Designation', 'designation_name': _('CEO')},
@@ -244,7 +242,10 @@
 		{"doctype": "Sales Stage", "stage_name": _("Identifying Decision Makers")},
 		{"doctype": "Sales Stage", "stage_name": _("Perception Analysis")},
 		{"doctype": "Sales Stage", "stage_name": _("Proposal/Price Quote")},
-		{"doctype": "Sales Stage", "stage_name": _("Negotiation/Review")}
+		{"doctype": "Sales Stage", "stage_name": _("Negotiation/Review")},
+
+		# Warehouse Type
+		{'doctype': 'Warehouse Type', 'name': 'Transit'},
 	]
 
 	from erpnext.setup.setup_wizard.data.industry_type import get_industry_types
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json
index 66efcf8..ea385c8 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.json
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.json
@@ -175,7 +175,7 @@
    "no_copy": 1,
    "oldfieldname": "naming_series",
    "oldfieldtype": "Select",
-   "options": "MAT-DN-.YYYY.-",
+   "options": "MAT-DN-.YYYY.-\nMAT-DN-RET-.YYYY.-",
    "print_hide": 1,
    "reqd": 1,
    "set_only_once": 1
@@ -1255,7 +1255,7 @@
  "idx": 146,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-07-18 05:13:55.580420",
+ "modified": "2020-08-03 23:18:47.739997",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Delivery Note",
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index 45526a3..d07b3dc 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -123,6 +123,7 @@
   "weightage",
   "slideshow",
   "website_image",
+  "website_image_alt",
   "thumbnail",
   "cb72",
   "website_warehouse",
@@ -1054,15 +1055,21 @@
    "fieldtype": "Data",
    "label": "Default Manufacturer Part No",
    "read_only": 1
+  },
+  {
+   "fieldname": "website_image_alt",
+   "fieldtype": "Data",
+   "label": "Image Description"
   }
  ],
  "has_web_view": 1,
  "icon": "fa fa-tag",
  "idx": 2,
  "image_field": "image",
+ "index_web_pages_for_search": 1,
  "links": [],
  "max_attachments": 1,
- "modified": "2020-07-31 21:21:10.956453",
+ "modified": "2020-08-07 14:24:58.384992",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Item",
@@ -1124,4 +1131,4 @@
  "sort_order": "DESC",
  "title_field": "item_name",
  "track_changes": 1
-}
\ No newline at end of file
+}
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index d7b43bf..d209f48 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -343,7 +343,7 @@
 			if variant:
 				context.variant = frappe.get_doc("Item", variant)
 
-				for fieldname in ("website_image", "web_long_description", "description",
+				for fieldname in ("website_image", "website_image_alt", "web_long_description", "description",
 										"website_specifications"):
 					if context.variant.get(fieldname):
 						value = context.variant.get(fieldname)
diff --git a/erpnext/stock/doctype/material_request/material_request.json b/erpnext/stock/doctype/material_request/material_request.json
index d1f29e3..44503d2 100644
--- a/erpnext/stock/doctype/material_request/material_request.json
+++ b/erpnext/stock/doctype/material_request/material_request.json
@@ -11,6 +11,7 @@
   "naming_series",
   "title",
   "material_request_type",
+  "transfer_status",
   "customer",
   "column_break_2",
   "schedule_date",
@@ -303,13 +304,22 @@
    "fieldtype": "Link",
    "label": "Set From Warehouse",
    "options": "Warehouse"
+  },
+  {
+   "allow_on_submit": 1,
+   "depends_on": "eval:doc.add_to_transit == 1",
+   "fieldname": "transfer_status",
+   "fieldtype": "Select",
+   "label": "Transfer Status",
+   "options": "\nNot Started\nIn Transit\nCompleted",
+   "read_only": 1
   }
  ],
  "icon": "fa fa-ticket",
  "idx": 70,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-05-01 20:21:09.990867",
+ "modified": "2020-08-10 13:27:54.891058",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Material Request",
diff --git a/erpnext/stock/doctype/material_request/material_request_list.js b/erpnext/stock/doctype/material_request/material_request_list.js
index 614ecb8..0d70958 100644
--- a/erpnext/stock/doctype/material_request/material_request_list.js
+++ b/erpnext/stock/doctype/material_request/material_request_list.js
@@ -1,8 +1,16 @@
 frappe.listview_settings['Material Request'] = {
-	add_fields: ["material_request_type", "status", "per_ordered", "per_received"],
+	add_fields: ["material_request_type", "status", "per_ordered", "per_received", "transfer_status"],
 	get_indicator: function(doc) {
 		if(doc.status=="Stopped") {
 			return [__("Stopped"), "red", "status,=,Stopped"];
+		} 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") {
+				return [__("In Transit"), "yellow"];
+			} else if (doc.transfer_status == "Completed") {
+				return [__("Completed"), "green"];
+			}
 		} else if(doc.docstatus==1 && flt(doc.per_ordered, 2) == 0) {
 			return [__("Pending"), "orange", "per_ordered,=,0"];
 		}  else if(doc.docstatus==1 && flt(doc.per_ordered, 2) < 100) {
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
index 92e33ca..ce54fc8 100755
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
@@ -1,7 +1,6 @@
 {
  "actions": [],
  "allow_import": 1,
- "allow_workflow": 1,
  "autoname": "naming_series:",
  "creation": "2013-05-21 16:16:39",
  "doctype": "DocType",
@@ -160,7 +159,7 @@
    "no_copy": 1,
    "oldfieldname": "naming_series",
    "oldfieldtype": "Select",
-   "options": "MAT-PRE-.YYYY.-",
+   "options": "MAT-PRE-.YYYY.-\nMAT-PR-RET-.YYYY.-",
    "print_hide": 1,
    "reqd": 1,
    "set_only_once": 1
@@ -1110,7 +1109,7 @@
  "idx": 261,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-07-18 05:19:12.148115",
+ "modified": "2020-08-03 23:20:26.381024",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Purchase Receipt",
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 53b986c..9845bc2 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -19,7 +19,6 @@
 				filters: [
 					['Stock Entry', 'docstatus', '=', 1],
 					['Stock Entry', 'per_transferred', '<','100'],
-					['Stock Entry', 'purpose', '=', 'Send to Warehouse']
 				]
 			}
 		});
@@ -171,9 +170,9 @@
 			}
 		}
 
-		if (frm.doc.docstatus === 1 && frm.doc.purpose == 'Send to Warehouse') {
-			if (frm.doc.per_transferred < 100) {
-				frm.add_custom_button(__('Receive at Warehouse Entry'), function() {
+		if (frm.doc.docstatus === 1) {
+			if (frm.doc.add_to_transit && frm.doc.purpose=='Material Transfer' && frm.doc.per_transferred < 100) {
+				frm.add_custom_button('End Transit', function() {
 					frappe.model.open_mapped_doc({
 						method: "erpnext.stock.doctype.stock_entry.stock_entry.make_stock_in_entry",
 						frm: frm
@@ -266,6 +265,7 @@
 	stock_entry_type: function(frm){
 		frm.remove_custom_button('Bill of Materials', "Get items from");
 		frm.events.show_bom_custom_button(frm);
+		frm.trigger('add_to_transit');
 	},
 
 	purpose: function(frm) {
@@ -532,6 +532,26 @@
 
 	target_warehouse_address: function(frm) {
 		erpnext.utils.get_address_display(frm, 'target_warehouse_address', 'target_address_display', false);
+	},
+
+	add_to_transit: function(frm) {
+		if(frm.doc.add_to_transit && frm.doc.purpose=='Material Transfer') {
+			frm.set_value('stock_entry_type', 'Material Transfer');
+			frm.fields_dict.to_warehouse.get_query = function() {
+				return {
+					filters:{
+						'warehouse_type' : 'Transit',
+						'is_group': 0,
+						'company': frm.doc.company
+					}
+				};
+			};
+			frappe.db.get_value('Company', frm.doc.company, 'default_in_transit_warehouse', (r) => {
+				if (r.default_in_transit_warehouse) {
+					frm.set_value('to_warehouse', r.default_in_transit_warehouse);
+				}
+			});
+		}
 	}
 })
 
@@ -754,6 +774,7 @@
 		}
 		erpnext.hide_company();
 		erpnext.utils.add_item(this.frm);
+		this.frm.trigger('add_to_transit');
 	},
 
 	scan_barcode: function() {
@@ -919,8 +940,6 @@
 			doc.purpose!='Material Issue');
 
 		this.frm.fields_dict["items"].grid.set_column_disp("additional_cost", doc.purpose!='Material Issue');
-		this.frm.toggle_reqd("outgoing_stock_entry",
-			doc.purpose == 'Receive at Warehouse' ? 1: 0);
 	},
 
 	supplier: function(doc) {
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.json b/erpnext/stock/doctype/stock_entry/stock_entry.json
index 704ae41..61e0df6 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.json
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.json
@@ -13,6 +13,7 @@
   "stock_entry_type",
   "outgoing_stock_entry",
   "purpose",
+  "add_to_transit",
   "work_order",
   "purchase_order",
   "delivery_note_no",
@@ -116,11 +117,12 @@
    "reqd": 1
   },
   {
-   "depends_on": "eval:doc.purpose == 'Receive at Warehouse'",
+   "depends_on": "eval:doc.purpose == 'Material Transfer'",
    "fieldname": "outgoing_stock_entry",
    "fieldtype": "Link",
    "label": "Stock Entry (Outward GIT)",
-   "options": "Stock Entry"
+   "options": "Stock Entry",
+   "read_only": 1
   },
   {
    "bold": 1,
@@ -132,7 +134,7 @@
    "label": "Purpose",
    "oldfieldname": "purpose",
    "oldfieldtype": "Select",
-   "options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor\nSend to Warehouse\nReceive at Warehouse",
+   "options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor",
    "read_only": 1
   },
   {
@@ -630,13 +632,21 @@
   {
    "fieldname": "print_settings_col_break",
    "fieldtype": "Column Break"
+  },
+  {
+   "default": "0",
+   "depends_on": "eval: doc.purpose=='Material Transfer' && !doc.outgoing_stock_entry",
+   "fieldname": "add_to_transit",
+   "fieldtype": "Check",
+   "label": "Add to Transit",
+   "no_copy": 1
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-23 12:56:52.881752",
+ "modified": "2020-08-11 19:10:07.954981",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Entry",
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 229cf02..30bcccd 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -96,6 +96,11 @@
 		self.update_quality_inspection()
 		if self.work_order and self.purpose == "Manufacture":
 			self.update_so_in_serial_number()
+		
+		if self.purpose == 'Material Transfer' and self.add_to_transit:
+			self.set_material_request_transfer_status('In Transit')
+		if self.purpose == 'Material Transfer' and self.outgoing_stock_entry:
+			self.set_material_request_transfer_status('Completed')
 
 	def on_cancel(self):
 
@@ -116,6 +121,11 @@
 		self.update_quality_inspection()
 		self.delete_auto_created_batches()
 
+		if self.purpose == 'Material Transfer' and self.add_to_transit:
+			self.set_material_request_transfer_status('Not Started')
+		if self.purpose == 'Material Transfer' and self.outgoing_stock_entry:
+			self.set_material_request_transfer_status('In Transit')
+
 	def set_job_card_data(self):
 		if self.job_card and not self.work_order:
 			data = frappe.db.get_value('Job Card',
@@ -133,7 +143,7 @@
 	def validate_purpose(self):
 		valid_purposes = ["Material Issue", "Material Receipt", "Material Transfer",
 			"Material Transfer for Manufacture", "Manufacture", "Repack", "Send to Subcontractor",
-			"Material Consumption for Manufacture", "Send to Warehouse", "Receive at Warehouse"]
+			"Material Consumption for Manufacture"]
 
 		if self.purpose not in valid_purposes:
 			frappe.throw(_("Purpose must be one of {0}").format(comma_or(valid_purposes)))
@@ -199,7 +209,8 @@
 						item.set(f, item_details.get(f))
 
 			if not item.transfer_qty and item.qty:
-				item.transfer_qty = item.qty * item.conversion_factor
+				item.transfer_qty = flt(flt(item.qty) * flt(item.conversion_factor),
+				self.precision("transfer_qty", item))
 
 			if (self.purpose in ("Material Transfer", "Material Transfer for Manufacture")
 				and not item.serial_no
@@ -258,10 +269,10 @@
 		"""perform various (sometimes conditional) validations on warehouse"""
 
 		source_mandatory = ["Material Issue", "Material Transfer", "Send to Subcontractor", "Material Transfer for Manufacture",
-			"Material Consumption for Manufacture", "Send to Warehouse", "Receive at Warehouse"]
+			"Material Consumption for Manufacture"]
 
 		target_mandatory = ["Material Receipt", "Material Transfer", "Send to Subcontractor",
-			"Material Transfer for Manufacture", "Send to Warehouse", "Receive at Warehouse"]
+			"Material Transfer for Manufacture"]
 
 		validate_for_manufacture = any([d.bom_no for d in self.get("items")])
 
@@ -809,7 +820,7 @@
 	def set_items_for_stock_in(self):
 		self.items = []
 
-		if self.outgoing_stock_entry and self.purpose == 'Receive at Warehouse':
+		if self.outgoing_stock_entry and self.purpose == 'Material Transfer':
 			doc = frappe.get_doc('Stock Entry', self.outgoing_stock_entry)
 
 			if doc.per_transferred == 100:
@@ -1210,13 +1221,25 @@
 
 	def validate_with_material_request(self):
 		for item in self.get("items"):
-			if item.material_request:
+			material_request = item.material_request or None
+			material_request_item = item.material_request_item or None
+			if self.purpose == 'Material Transfer' and self.outgoing_stock_entry:
+				parent_se = frappe.get_value("Stock Entry Detail", item.ste_detail, ['material_request','material_request_item'],as_dict=True)
+				if parent_se:
+					material_request = parent_se.material_request
+					material_request_item = parent_se.material_request_item
+
+			if material_request:
 				mreq_item = frappe.db.get_value("Material Request Item",
-					{"name": item.material_request_item, "parent": item.material_request},
+					{"name": material_request_item, "parent": material_request},
 					["item_code", "warehouse", "idx"], as_dict=True)
-				if mreq_item.item_code != item.item_code or \
-				mreq_item.warehouse != (item.s_warehouse if self.purpose== "Material Issue" else item.t_warehouse):
-					frappe.throw(_("Item or Warehouse for row {0} does not match Material Request").format(item.idx),
+				if mreq_item.item_code != item.item_code:
+					frappe.throw(_("Item for row {0} does not match Material Request").format(item.idx),
+						frappe.MappingMismatchError)
+				elif self.purpose == "Material Transfer" and self.add_to_transit:
+					continue
+				elif mreq_item.warehouse != (item.s_warehouse if self.purpose == "Material Issue" else item.t_warehouse):
+					frappe.throw(_("Warehouse for row {0} does not match Material Request").format(item.idx),
 						frappe.MappingMismatchError)
 
 	def validate_batch(self):
@@ -1284,7 +1307,7 @@
 						 to fullfill Sales Order {2}.").format(item.item_code, sr, sales_order))
 
 	def update_transferred_qty(self):
-		if self.purpose == 'Receive at Warehouse':
+		if self.purpose == 'Material Transfer' and self.outgoing_stock_entry:
 			stock_entries = {}
 			stock_entries_child_list = []
 			for d in self.items:
@@ -1342,6 +1365,20 @@
 						'reference_type': reference_type,
 						'reference_name': reference_name
 					})
+	def set_material_request_transfer_status(self, status):
+		material_requests = []
+		if self.outgoing_stock_entry:
+			parent_se = frappe.get_value("Stock Entry", self.outgoing_stock_entry, 'add_to_transit')
+
+		for item in self.items: 
+			material_request = item.material_request or None
+			if self.purpose == "Material Transfer" and material_request not in material_requests:
+				if self.outgoing_stock_entry and parent_se:
+					material_request = frappe.get_value("Stock Entry Detail", item.ste_detail, 'material_request')
+
+			if material_request and material_request not in material_requests:
+				material_requests.append(material_request)
+				frappe.db.set_value('Material Request', material_request, 'transfer_status', status)
 
 @frappe.whitelist()
 def move_sample_to_retention_warehouse(company, items):
@@ -1381,12 +1418,19 @@
 
 @frappe.whitelist()
 def make_stock_in_entry(source_name, target_doc=None):
+
 	def set_missing_values(source, target):
-		target.purpose = 'Receive at Warehouse'
 		target.set_stock_entry_type()
 
 	def update_item(source_doc, target_doc, source_parent):
 		target_doc.t_warehouse = ''
+
+		if source_doc.material_request_item and source_doc.material_request :
+			add_to_transit = frappe.db.get_value('Stock Entry', source_name, 'add_to_transit')
+			if add_to_transit:
+				warehouse = frappe.get_value('Material Request Item', source_doc.material_request_item, 'warehouse')
+				target_doc.t_warehouse = warehouse
+		
 		target_doc.s_warehouse = source_doc.t_warehouse
 		target_doc.qty = source_doc.qty - source_doc.transferred_qty
 
diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
index 8e25804..d98870d 100644
--- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
@@ -737,34 +737,6 @@
 		self.assertEqual(se.get("items")[0].allow_zero_valuation_rate, 1)
 		self.assertEqual(se.get("items")[0].amount, 0)
 
-	def test_goods_in_transit(self):
-		from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
-		warehouse = "_Test Warehouse FG 1 - _TC"
-
-		if not frappe.db.exists('Warehouse', warehouse):
-			create_warehouse("_Test Warehouse FG 1")
-
-		outward_entry = make_stock_entry(item_code="_Test Item",
-			purpose="Send to Warehouse",
-			source="_Test Warehouse - _TC",
-			target="_Test Warehouse 1 - _TC", qty=50, basic_rate=100)
-
-		inward_entry1 = make_stock_in_entry(outward_entry.name)
-		inward_entry1.items[0].t_warehouse = warehouse
-		inward_entry1.items[0].qty = 25
-		inward_entry1.submit()
-
-		doc = frappe.get_doc('Stock Entry', outward_entry.name)
-		self.assertEqual(doc.per_transferred, 50)
-
-		inward_entry2 = make_stock_in_entry(outward_entry.name)
-		inward_entry2.items[0].t_warehouse = warehouse
-		inward_entry2.items[0].qty = 25
-		inward_entry2.submit()
-
-		doc = frappe.get_doc('Stock Entry', outward_entry.name)
-		self.assertEqual(doc.per_transferred, 100)
-
 	def test_gle_for_opening_stock_entry(self):
 		mr = make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company="_Test Company with perpetual inventory",qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1", is_opening="Yes", do_not_save=True)
 
diff --git a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.json b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.json
index edee3c7..0f2b55e 100644
--- a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.json
+++ b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.json
@@ -1,156 +1,83 @@
 {
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
+ "actions": [],
  "autoname": "Prompt",
- "beta": 0,
  "creation": "2019-03-13 16:23:46.636769",
- "custom": 0,
- "docstatus": 0,
  "doctype": "DocType",
- "document_type": "",
  "editable_grid": 1,
  "engine": "InnoDB",
+ "field_order": [
+  "purpose"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "default": "Material Issue",
-   "fetch_if_empty": 0,
    "fieldname": "purpose",
    "fieldtype": "Select",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
    "in_list_view": 1,
-   "in_standard_filter": 0,
    "label": "Purpose",
-   "length": 0,
-   "no_copy": 0,
-   "options": "\nMaterial Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor\nSend to Warehouse\nReceive at Warehouse",
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
+   "options": "\nMaterial Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor",
    "reqd": 1,
-   "search_index": 0,
-   "set_only_once": 1,
-   "translatable": 0,
-   "unique": 0
+   "set_only_once": 1
   }
  ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2019-03-26 12:02:42.144377",
+ "links": [],
+ "modified": "2020-08-10 23:24:37.160817",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Entry Type",
- "name_case": "",
  "owner": "Administrator",
  "permissions": [
   {
-   "amend": 0,
-   "cancel": 0,
    "create": 1,
    "delete": 1,
    "email": 1,
    "export": 1,
-   "if_owner": 0,
-   "import": 0,
-   "permlevel": 0,
    "print": 1,
    "read": 1,
    "report": 1,
    "role": "System Manager",
-   "set_user_permissions": 0,
    "share": 1,
-   "submit": 0,
    "write": 1
   },
   {
-   "amend": 0,
-   "cancel": 0,
    "create": 1,
    "delete": 1,
    "email": 1,
    "export": 1,
-   "if_owner": 0,
-   "import": 0,
-   "permlevel": 0,
    "print": 1,
    "read": 1,
    "report": 1,
    "role": "Manufacturing Manager",
-   "set_user_permissions": 0,
    "share": 1,
-   "submit": 0,
    "write": 1
   },
   {
-   "amend": 0,
-   "cancel": 0,
    "create": 1,
    "delete": 1,
    "email": 1,
    "export": 1,
-   "if_owner": 0,
-   "import": 0,
-   "permlevel": 0,
    "print": 1,
    "read": 1,
    "report": 1,
    "role": "Stock Manager",
-   "set_user_permissions": 0,
    "share": 1,
-   "submit": 0,
    "write": 1
   },
   {
-   "amend": 0,
-   "cancel": 0,
    "create": 1,
    "delete": 1,
    "email": 1,
    "export": 1,
-   "if_owner": 0,
-   "import": 0,
-   "permlevel": 0,
    "print": 1,
    "read": 1,
    "report": 1,
    "role": "Stock User",
-   "set_user_permissions": 0,
    "share": 1,
-   "submit": 0,
    "write": 1
   }
  ],
  "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
  "sort_field": "modified",
  "sort_order": "ASC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/templates/generators/item/item_image.html b/erpnext/templates/generators/item/item_image.html
index 0dd4c35..5d46a45 100644
--- a/erpnext/templates/generators/item/item_image.html
+++ b/erpnext/templates/generators/item/item_image.html
@@ -23,7 +23,7 @@
 	})
 </script>
 {% else %}
-{{ product_image(website_image or image or 'no-image.jpg') }}
+{{ product_image(website_image or image or 'no-image.jpg', alt=website_image_alt or item_name) }}
 {% endif %}
 
 <!-- Simple image preview -->
diff --git a/erpnext/templates/generators/item_group.html b/erpnext/templates/generators/item_group.html
index 3f98453..40a064f 100644
--- a/erpnext/templates/generators/item_group.html
+++ b/erpnext/templates/generators/item_group.html
@@ -4,7 +4,7 @@
 
 {% block page_content %}
 <div class="item-group-content" itemscope itemtype="http://schema.org/Product">
-	<div>
+	<div class="item-group-slideshow">
 		{% if slideshow %}<!-- slideshow -->
 		{% include "templates/includes/slideshow.html" %}
 		{% endif %}
diff --git a/erpnext/templates/includes/macros.html b/erpnext/templates/includes/macros.html
index 3c82e90..ea6b00f 100644
--- a/erpnext/templates/includes/macros.html
+++ b/erpnext/templates/includes/macros.html
@@ -7,9 +7,9 @@
 </div>
 {% endmacro %}
 
-{% macro product_image(website_image, css_class="") %}
+{% macro product_image(website_image, css_class="", alt="") %}
     <div class="border text-center rounded h-100 {{ css_class }}" style="overflow: hidden;">
-		<img itemprop="image" class="website-image h-100 w-100" src="{{ frappe.utils.quoted(website_image or 'no-image.jpg') | abs_url }}">
+		<img itemprop="image" class="website-image h-100 w-100" alt="{{ alt }}" src="{{ frappe.utils.quoted(website_image or 'no-image.jpg') | abs_url }}">
     </div>
 {% endmacro %}