Merge branch 'develop' into fix-margin-for-filter
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/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 89c38c7..66b5f30 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")
 
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 efaeca0..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("""
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/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/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/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json
index 221044d..03703fd 100644
--- a/erpnext/setup/doctype/company/company.json
+++ b/erpnext/setup/doctype/company/company.json
@@ -242,7 +242,7 @@
   {
    "fieldname": "default_warehouse_for_sales_return",
    "fieldtype": "Link",
-   "label": "Default warehouse for Sales Return",
+   "label": "Default Warehouse for Sales Return",
    "options": "Warehouse"
   },
   {
@@ -801,4 +801,4 @@
  "sort_field": "modified",
  "sort_order": "ASC",
  "track_changes": 1
-}
\ No newline at end of file
+}
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/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/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 %}