Merge branch 'develop' into datev_fixes
diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml
index 824b74e..84ecfb1 100644
--- a/.github/workflows/ci-tests.yml
+++ b/.github/workflows/ci-tests.yml
@@ -80,14 +80,29 @@
         env:
           TYPE: ${{ matrix.TYPE }}
 
-      - name: Coverage
-        if: matrix.TYPE == 'server'
+      - name: Coverage - Pull Request
+        if: matrix.TYPE == 'server' && github.event_name == 'pull_request'
         run: |
           cp ~/frappe-bench/sites/.coverage ${GITHUB_WORKSPACE}
           cd ${GITHUB_WORKSPACE}
-          pip install coveralls==3.0.1
-          pip install coverage==5.5
+          pip install coveralls==2.2.0
+          pip install coverage==4.5.4
           coveralls --service=github
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
           COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
+          COVERALLS_SERVICE_NAME: github
+          
+      - name: Coverage - Push
+        if: matrix.TYPE == 'server' && github.event_name == 'push'
+        run: |
+          cp ~/frappe-bench/sites/.coverage ${GITHUB_WORKSPACE}
+          cd ${GITHUB_WORKSPACE}
+          pip install coveralls==2.2.0
+          pip install coverage==4.5.4
+          coveralls --service=github-actions
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
+          COVERALLS_SERVICE_NAME: github-actions
+
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 4da0605..ea83d08 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@
 from erpnext.hooks import regional_overrides
 from frappe.utils import getdate
 
-__version__ = '13.1.0'
+__version__ = '13.1.1'
 
 def get_default_company(user=None):
 	'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index 830a7f2..b80e8ad 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -561,7 +561,7 @@
 			flt(frm.doc.received_amount) * flt(frm.doc.target_exchange_rate));
 
 		if(frm.doc.payment_type == "Pay")
-			frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.received_amount);
+			frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.received_amount, 1);
 		else
 			frm.events.set_unallocated_amount(frm);
 
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
index 08103184..d1523cd 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
@@ -234,7 +234,7 @@
 		});
 
 		if (invoices) {
-			this.frm.fields_dict.payment.grid.update_docfield_property(
+			this.frm.fields_dict.payments.grid.update_docfield_property(
 				'invoice_number', 'options', "\n" + invoices.join("\n")
 			);
 
diff --git a/erpnext/accounts/doctype/payment_schedule/payment_schedule.json b/erpnext/accounts/doctype/payment_schedule/payment_schedule.json
index e362566..6ed7a31 100644
--- a/erpnext/accounts/doctype/payment_schedule/payment_schedule.json
+++ b/erpnext/accounts/doctype/payment_schedule/payment_schedule.json
@@ -20,10 +20,11 @@
   "discount",
   "section_break_9",
   "payment_amount",
+  "outstanding",
+  "paid_amount",
   "discounted_amount",
   "column_break_3",
-  "outstanding",
-  "paid_amount"
+  "base_payment_amount"
  ],
  "fields": [
   {
@@ -78,7 +79,8 @@
    "depends_on": "paid_amount",
    "fieldname": "paid_amount",
    "fieldtype": "Currency",
-   "label": "Paid Amount"
+   "label": "Paid Amount",
+   "options": "currency"
   },
   {
    "fieldname": "column_break_3",
@@ -97,6 +99,7 @@
    "fieldname": "outstanding",
    "fieldtype": "Currency",
    "label": "Outstanding",
+   "options": "currency",
    "read_only": 1
   },
   {
@@ -145,12 +148,18 @@
   {
    "fieldname": "section_break_4",
    "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "base_payment_amount",
+   "fieldtype": "Currency",
+   "label": "Payment Amount (Company Currency)",
+   "options": "Company:company:default_currency"
   }
  ],
  "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2021-02-15 21:03:12.540546",
+ "modified": "2021-04-28 05:41:35.084233",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Payment Schedule",
diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py
index 6d2cffc..4d5472d 100644
--- a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py
+++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py
@@ -235,11 +235,11 @@
 
 	return pos_invoice_customer_map
 
-def consolidate_pos_invoices(pos_invoices=[], closing_entry={}):
-	invoices = pos_invoices or closing_entry.get('pos_transactions') or get_all_unconsolidated_invoices()
+def consolidate_pos_invoices(pos_invoices=None, closing_entry=None):
+	invoices = pos_invoices or (closing_entry and closing_entry.get('pos_transactions')) or get_all_unconsolidated_invoices()
 	invoice_by_customer = get_invoice_customer_map(invoices)
 
-	if len(invoices) >= 5 and closing_entry:
+	if len(invoices) >= 1 and closing_entry:
 		closing_entry.set_status(update=True, status='Queued')
 		enqueue_job(create_merge_logs, invoice_by_customer=invoice_by_customer, closing_entry=closing_entry)
 	else:
@@ -252,18 +252,18 @@
 		pluck='name'
 	)
 
-	if len(merge_logs) >= 5:
+	if len(merge_logs) >= 1:
 		closing_entry.set_status(update=True, status='Queued')
 		enqueue_job(cancel_merge_logs, merge_logs=merge_logs, closing_entry=closing_entry)
 	else:
 		cancel_merge_logs(merge_logs, closing_entry)
 
-def create_merge_logs(invoice_by_customer, closing_entry={}):
+def create_merge_logs(invoice_by_customer, closing_entry=None):
 	for customer, invoices in iteritems(invoice_by_customer):
 		merge_log = frappe.new_doc('POS Invoice Merge Log')
-		merge_log.posting_date = getdate(closing_entry.get('posting_date'))
+		merge_log.posting_date = getdate(closing_entry.get('posting_date')) if closing_entry else nowdate()
 		merge_log.customer = customer
-		merge_log.pos_closing_entry = closing_entry.get('name', None)
+		merge_log.pos_closing_entry = closing_entry.get('name') if closing_entry else None
 
 		merge_log.set('pos_invoices', invoices)
 		merge_log.save(ignore_permissions=True)
@@ -273,7 +273,7 @@
 		closing_entry.set_status(update=True, status='Submitted')
 		closing_entry.update_opening_entry()
 
-def cancel_merge_logs(merge_logs, closing_entry={}):
+def cancel_merge_logs(merge_logs, closing_entry=None):
 	for log in merge_logs:
 		merge_log = frappe.get_doc('POS Invoice Merge Log', log)
 		merge_log.flags.ignore_permissions = True
@@ -283,20 +283,20 @@
 		closing_entry.set_status(update=True, status='Cancelled')
 		closing_entry.update_opening_entry(for_cancel=True)
 
-def enqueue_job(job, merge_logs=None, invoice_by_customer=None, closing_entry=None):
+def enqueue_job(job, **kwargs):
 	check_scheduler_status()
 
+	closing_entry = kwargs.get('closing_entry') or {}
+
 	job_name = closing_entry.get("name")
 	if not job_already_enqueued(job_name):
 		enqueue(
 			job,
+			**kwargs,
 			queue="long",
 			timeout=10000,
 			event="processing_merge_logs",
 			job_name=job_name,
-			closing_entry=closing_entry,
-			invoice_by_customer=invoice_by_customer,
-			merge_logs=merge_logs,
 			now=frappe.conf.developer_mode or frappe.flags.in_test
 		)
 
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
index b623898..f61aacb 100644
--- 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
@@ -60,8 +60,8 @@
 		</tbody>
 </table>
 <br><br>
-{% if aging %}
-<h3 class="text-center">{{ _("Ageing Report Based On ") }} {{ aging.ageing_based_on }}</h3>
+{% if ageing %}
+<h3 class="text-center">{{ _("Ageing Report Based On ") }} {{ ageing.ageing_based_on }}</h3>
 <h5 class="text-center">
 	{{ _("Up to " ) }}  {{ frappe.format(filters.to_date, 'Date')}}
 </h5>
@@ -78,10 +78,10 @@
 	</thead>
 	<tbody>
 		<tr>
-			<td>{{ frappe.utils.fmt_money(aging.range1, currency=filters.presentation_currency) }}</td>
-			<td>{{ frappe.utils.fmt_money(aging.range2, currency=filters.presentation_currency) }}</td>
-			<td>{{ frappe.utils.fmt_money(aging.range3, currency=filters.presentation_currency) }}</td>
-			<td>{{ frappe.utils.fmt_money(aging.range4, currency=filters.presentation_currency) }}</td>
+			<td>{{ frappe.utils.fmt_money(ageing.range1, currency=filters.presentation_currency) }}</td>
+			<td>{{ frappe.utils.fmt_money(ageing.range2, currency=filters.presentation_currency) }}</td>
+			<td>{{ frappe.utils.fmt_money(ageing.range3, currency=filters.presentation_currency) }}</td>
+			<td>{{ frappe.utils.fmt_money(ageing.range4, currency=filters.presentation_currency) }}</td>
 		</tr>
 	</tbody>
 </table>
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
index b6149e8..62090c0 100644
--- 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
@@ -40,7 +40,7 @@
 
 def get_report_pdf(doc, consolidated=True):
 	statement_dict = {}
-	aging = ''
+	ageing = ''
 	base_template_path = "frappe/www/printview.html"
 	template_path = "erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html"
 
@@ -56,8 +56,10 @@
 				'range4': 120,
 				'customer': entry.customer
 			})
-			col1, aging = get_ageing(ageing_filters)
-			aging[0]['ageing_based_on'] = doc.ageing_based_on
+			col1, ageing = get_ageing(ageing_filters)
+
+			if ageing:
+				ageing[0]['ageing_based_on'] = doc.ageing_based_on
 
 		tax_id = frappe.get_doc('Customer', entry.customer).tax_id
 		presentation_currency =  get_party_account_currency('Customer', entry.customer, doc.company) \
@@ -87,11 +89,14 @@
 
 		if len(res) == 3:
 			continue
+
 		html = frappe.render_template(template_path, \
-			{"filters": filters, "data": res, "aging": aging[0] if doc.include_ageing else None})
+			{"filters": filters, "data": res, "ageing": ageing[0] if (doc.include_ageing and 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:
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 50492f5..66be11f 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -397,7 +397,7 @@
 
 		pi.update({
 			"payment_schedule": get_payment_terms("_Test Payment Term Template",
-				pi.posting_date, pi.grand_total)
+				pi.posting_date, pi.grand_total, pi.base_grand_total)
 		})
 
 		pi.save()
diff --git a/erpnext/accounts/doctype/subscription/subscription.json b/erpnext/accounts/doctype/subscription/subscription.json
index e80df2a..c4e4be7 100644
--- a/erpnext/accounts/doctype/subscription/subscription.json
+++ b/erpnext/accounts/doctype/subscription/subscription.json
@@ -36,6 +36,7 @@
   "additional_discount_percentage",
   "additional_discount_amount",
   "sb_3",
+  "submit_invoice",
   "invoices",
   "accounting_dimensions_section",
   "cost_center",
@@ -45,9 +46,7 @@
   {
    "allow_on_submit": 1,
    "fieldname": "cb_1",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "status",
@@ -55,97 +54,73 @@
    "label": "Status",
    "no_copy": 1,
    "options": "\nTrialling\nActive\nPast Due Date\nCancelled\nUnpaid\nCompleted",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "subscription_period",
    "fieldtype": "Section Break",
-   "label": "Subscription Period",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Subscription Period"
   },
   {
    "fieldname": "cancelation_date",
    "fieldtype": "Date",
    "label": "Cancelation Date",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "allow_on_submit": 1,
    "fieldname": "trial_period_start",
    "fieldtype": "Date",
    "label": "Trial Period Start Date",
-   "set_only_once": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "set_only_once": 1
   },
   {
    "depends_on": "eval:doc.trial_period_start",
    "fieldname": "trial_period_end",
    "fieldtype": "Date",
    "label": "Trial Period End Date",
-   "set_only_once": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "set_only_once": 1
   },
   {
    "fieldname": "column_break_11",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "current_invoice_start",
    "fieldtype": "Date",
    "label": "Current Invoice Start Date",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "current_invoice_end",
    "fieldtype": "Date",
    "label": "Current Invoice End Date",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "default": "0",
    "description": "Number of days that the subscriber has to pay invoices generated by this subscription",
    "fieldname": "days_until_due",
    "fieldtype": "Int",
-   "label": "Days Until Due",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Days Until Due"
   },
   {
    "default": "0",
    "fieldname": "cancel_at_period_end",
    "fieldtype": "Check",
-   "label": "Cancel At End Of Period",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Cancel At End Of Period"
   },
   {
    "default": "0",
    "fieldname": "generate_invoice_at_period_start",
    "fieldtype": "Check",
-   "label": "Generate Invoice At Beginning Of Period",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Generate Invoice At Beginning Of Period"
   },
   {
    "allow_on_submit": 1,
    "fieldname": "sb_4",
    "fieldtype": "Section Break",
-   "label": "Plans",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Plans"
   },
   {
    "allow_on_submit": 1,
@@ -153,84 +128,62 @@
    "fieldtype": "Table",
    "label": "Plans",
    "options": "Subscription Plan Detail",
-   "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "reqd": 1
   },
   {
    "depends_on": "eval:['Customer', 'Supplier'].includes(doc.party_type)",
    "fieldname": "sb_1",
    "fieldtype": "Section Break",
-   "label": "Taxes",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Taxes"
   },
   {
    "fieldname": "sb_2",
    "fieldtype": "Section Break",
-   "label": "Discounts",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Discounts"
   },
   {
    "fieldname": "apply_additional_discount",
    "fieldtype": "Select",
    "label": "Apply Additional Discount On",
-   "options": "\nGrand Total\nNet Total",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "\nGrand Total\nNet Total"
   },
   {
    "fieldname": "cb_2",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "additional_discount_percentage",
    "fieldtype": "Percent",
-   "label": "Additional DIscount Percentage",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Additional DIscount Percentage"
   },
   {
    "collapsible": 1,
    "fieldname": "additional_discount_amount",
    "fieldtype": "Currency",
-   "label": "Additional DIscount Amount",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Additional DIscount Amount"
   },
   {
    "depends_on": "eval:doc.invoices",
    "fieldname": "sb_3",
    "fieldtype": "Section Break",
-   "label": "Invoices",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Invoices"
   },
   {
    "collapsible": 1,
    "fieldname": "invoices",
    "fieldtype": "Table",
    "label": "Invoices",
-   "options": "Subscription Invoice",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Subscription Invoice"
   },
   {
    "collapsible": 1,
    "fieldname": "accounting_dimensions_section",
    "fieldtype": "Section Break",
-   "label": "Accounting Dimensions",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Accounting Dimensions"
   },
   {
    "fieldname": "dimension_col_break",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "party_type",
@@ -238,9 +191,7 @@
    "label": "Party Type",
    "options": "DocType",
    "reqd": 1,
-   "set_only_once": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "set_only_once": 1
   },
   {
    "fieldname": "party",
@@ -249,27 +200,21 @@
    "label": "Party",
    "options": "party_type",
    "reqd": 1,
-   "set_only_once": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "set_only_once": 1
   },
   {
    "depends_on": "eval:doc.party_type === 'Customer'",
    "fieldname": "sales_tax_template",
    "fieldtype": "Link",
    "label": "Sales Taxes and Charges Template",
-   "options": "Sales Taxes and Charges Template",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Sales Taxes and Charges Template"
   },
   {
    "depends_on": "eval:doc.party_type === 'Supplier'",
    "fieldname": "purchase_tax_template",
    "fieldtype": "Link",
    "label": "Purchase Taxes and Charges Template",
-   "options": "Purchase Taxes and Charges Template",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Purchase Taxes and Charges Template"
   },
   {
    "default": "0",
@@ -277,55 +222,49 @@
    "fieldname": "follow_calendar_months",
    "fieldtype": "Check",
    "label": "Follow Calendar Months",
-   "set_only_once": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "set_only_once": 1
   },
   {
    "default": "0",
    "description": "New invoices will be generated as per schedule even if current invoices are unpaid or past due date",
    "fieldname": "generate_new_invoices_past_due_date",
    "fieldtype": "Check",
-   "label": "Generate New Invoices Past Due Date",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Generate New Invoices Past Due Date"
   },
   {
    "fieldname": "end_date",
    "fieldtype": "Date",
    "label": "Subscription End Date",
-   "set_only_once": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "set_only_once": 1
   },
   {
    "fieldname": "start_date",
    "fieldtype": "Date",
    "label": "Subscription Start Date",
-   "set_only_once": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "set_only_once": 1
   },
   {
    "fieldname": "cost_center",
    "fieldtype": "Link",
    "label": "Cost Center",
-   "options": "Cost Center",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Cost Center"
   },
   {
    "fieldname": "company",
    "fieldtype": "Link",
    "label": "Company",
-   "options": "Company",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Company"
+  },
+  {
+   "default": "1",
+   "fieldname": "submit_invoice",
+   "fieldtype": "Check",
+   "label": "Submit Invoice Automatically"
   }
  ],
  "index_web_pages_for_search": 1,
  "links": [],
- "modified": "2021-02-09 15:44:20.024789",
+ "modified": "2021-04-19 15:24:27.550797",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Subscription",
diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py
index 826044a..7c4ff73 100644
--- a/erpnext/accounts/doctype/subscription/subscription.py
+++ b/erpnext/accounts/doctype/subscription/subscription.py
@@ -276,7 +276,7 @@
 				frappe.throw(_('Subscription End Date is mandatory to follow calendar months'))
 
 			if billing_info[0]['billing_interval'] != 'Month':
-				frappe.throw('Billing Interval in Subscription Plan must be Month to follow calendar months')
+				frappe.throw(_('Billing Interval in Subscription Plan must be Month to follow calendar months'))
 
 	def after_insert(self):
 		# todo: deal with users who collect prepayments. Maybe a new Subscription Invoice doctype?
@@ -383,7 +383,9 @@
 
 		invoice.flags.ignore_mandatory = True
 		invoice.save()
-		invoice.submit()
+
+		if self.submit_invoice:
+			invoice.submit()
 
 		return invoice
 
diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py
index 85bff10..f1717c5 100644
--- a/erpnext/accounts/general_ledger.py
+++ b/erpnext/accounts/general_ledger.py
@@ -171,7 +171,7 @@
 	else:
 		allowance = .5
 
-	if abs(debit_credit_diff) >= allowance:
+	if abs(debit_credit_diff) > allowance:
 		frappe.throw(_("Debit and Credit not equal for {0} #{1}. Difference is {2}.")
 			.format(gl_map[0].voucher_type, gl_map[0].voucher_no, debit_credit_diff))
 
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 97bcb00..c409850 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -923,29 +923,34 @@
 		date = self.get("due_date")
 		due_date = date or posting_date
 
-		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
+		base_grand_total = self.get("base_rounded_total") or self.base_grand_total
+		grand_total = self.get("rounded_total") or self.grand_total
 
 		if self.doctype in ("Sales Invoice", "Purchase Invoice"):
+			base_grand_total = base_grand_total - flt(self.base_write_off_amount)
 			grand_total = grand_total - flt(self.write_off_amount)
 
 		if self.get("total_advance"):
-			grand_total -= self.get("total_advance")
+			if party_account_currency == self.company_currency:
+				base_grand_total -= self.get("total_advance")
+				grand_total = flt(base_grand_total / self.get("conversion_rate"), self.precision("grand_total"))
+			else:
+				grand_total -= self.get("total_advance")
+				base_grand_total = flt(grand_total * self.get("conversion_rate"), self.precision("base_grand_total"))
 
 		if not self.get("payment_schedule"):
 			if self.get("payment_terms_template"):
-				data = get_payment_terms(self.payment_terms_template, posting_date, grand_total)
+				data = get_payment_terms(self.payment_terms_template, posting_date, grand_total, base_grand_total)
 				for item in data:
 					self.append("payment_schedule", item)
 			else:
-				data = dict(due_date=due_date, invoice_portion=100, payment_amount=grand_total)
+				data = dict(due_date=due_date, invoice_portion=100, payment_amount=grand_total, base_payment_amount=base_grand_total)
 				self.append("payment_schedule", data)
 		else:
 			for d in self.get("payment_schedule"):
 				if d.invoice_portion:
 					d.payment_amount = flt(grand_total * flt(d.invoice_portion / 100), d.precision('payment_amount'))
+					d.base_payment_amount = flt(base_grand_total * flt(d.invoice_portion / 100), d.precision('payment_amount'))
 					d.outstanding = d.payment_amount
 
 	def set_due_date(self):
@@ -982,22 +987,28 @@
 
 		if self.get("payment_schedule"):
 			total = 0
+			base_total = 0
 			for d in self.get("payment_schedule"):
 				total += flt(d.payment_amount)
+				base_total += flt(d.base_payment_amount)
 
-			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")
+			base_grand_total = self.get("base_rounded_total") or self.base_grand_total
+			grand_total = self.get("rounded_total") or self.grand_total
 
 			if self.doctype in ("Sales Invoice", "Purchase Invoice"):
+				base_grand_total = base_grand_total - flt(self.base_write_off_amount)
 				grand_total = grand_total - flt(self.write_off_amount)
-			if total != flt(grand_total, self.precision("grand_total")):
+
+			if self.get("total_advance"):
+				if party_account_currency == self.company_currency:
+					base_grand_total -= self.get("total_advance")
+					grand_total = flt(base_grand_total / self.get("conversion_rate"), self.precision("grand_total"))
+				else:
+					grand_total -= self.get("total_advance")
+					base_grand_total = flt(grand_total * self.get("conversion_rate"), self.precision("base_grand_total"))
+			print(grand_total, base_grand_total)
+			if total != flt(grand_total, self.precision("grand_total")) or \
+				base_total != flt(base_grand_total, self.precision("base_grand_total")):
 				frappe.throw(_("Total Payment Amount in Payment Schedule must be equal to Grand / Rounded Total"))
 
 	def is_rounded_total_disabled(self):
@@ -1237,7 +1248,7 @@
 
 
 @frappe.whitelist()
-def get_payment_terms(terms_template, posting_date=None, grand_total=None, bill_date=None):
+def get_payment_terms(terms_template, posting_date=None, grand_total=None, base_grand_total=None, bill_date=None):
 	if not terms_template:
 		return
 
@@ -1245,14 +1256,14 @@
 
 	schedule = []
 	for d in terms_doc.get("terms"):
-		term_details = get_payment_term_details(d, posting_date, grand_total, bill_date)
+		term_details = get_payment_term_details(d, posting_date, grand_total, base_grand_total, bill_date)
 		schedule.append(term_details)
 
 	return schedule
 
 
 @frappe.whitelist()
-def get_payment_term_details(term, posting_date=None, grand_total=None, bill_date=None):
+def get_payment_term_details(term, posting_date=None, grand_total=None, base_grand_total=None, bill_date=None):
 	term_details = frappe._dict()
 	if isinstance(term, text_type):
 		term = frappe.get_doc("Payment Term", term)
@@ -1261,9 +1272,9 @@
 	term_details.description = term.description
 	term_details.invoice_portion = term.invoice_portion
 	term_details.payment_amount = flt(term.invoice_portion) * flt(grand_total) / 100
+	term_details.base_payment_amount = flt(term.invoice_portion) * flt(base_grand_total) / 100
 	term_details.discount_type = term.discount_type
 	term_details.discount = term.discount
-	# term_details.discounted_amount = flt(grand_total) * (term.discount / 100) if term.discount_type == 'Percentage' else discount
 	term_details.outstanding = term_details.payment_amount
 	term_details.mode_of_payment = term.mode_of_payment
 
diff --git a/erpnext/loan_management/doctype/loan/loan.py b/erpnext/loan_management/doctype/loan/loan.py
index 83a813f..20b44a1 100644
--- a/erpnext/loan_management/doctype/loan/loan.py
+++ b/erpnext/loan_management/doctype/loan/loan.py
@@ -44,6 +44,7 @@
 
 	def on_cancel(self):
 		self.unlink_loan_security_pledge()
+		self.ignore_linked_doctypes = ['GL Entry']
 
 	def set_missing_fields(self):
 		if not self.company:
@@ -359,4 +360,4 @@
 	return {
 		"value": len(applicants),
 		"fieldtype": "Int"
-	}
\ No newline at end of file
+	}
diff --git a/erpnext/payroll/doctype/salary_structure/salary_structure.js b/erpnext/payroll/doctype/salary_structure/salary_structure.js
index e00bd87..d5c20dc 100755
--- a/erpnext/payroll/doctype/salary_structure/salary_structure.js
+++ b/erpnext/payroll/doctype/salary_structure/salary_structure.js
@@ -16,11 +16,11 @@
 	onload: function(frm) {
 
 		let help_button = $(`<a class = 'control-label'>
-			Condition and Formula Help
+			${__("Condition and Formula Help")}
 		</a>`).click(()=>{
 
 			let d = new frappe.ui.Dialog({
-				title: 'Condition and Formula Help',
+				title: __('Condition and Formula Help'),
 				fields: [
 					{
 						fieldname: 'msg_wrapper',
diff --git a/erpnext/projects/report/project_summary/project_summary.py b/erpnext/projects/report/project_summary/project_summary.py
index ea7f1ab..2c7bb49 100644
--- a/erpnext/projects/report/project_summary/project_summary.py
+++ b/erpnext/projects/report/project_summary/project_summary.py
@@ -131,25 +131,25 @@
 		{
 			"value": avg_completion,
 			"indicator": "Green" if avg_completion > 50 else "Red",
-			"label": "Average Completion",
+			"label": _("Average Completion"),
 			"datatype": "Percent",
 		},
 		{
 			"value": total,
 			"indicator": "Blue",
-			"label": "Total Tasks",
+			"label": _("Total Tasks"),
 			"datatype": "Int",
 		},
 		{
 			"value": completed,
 			"indicator": "Green",
-			"label": "Completed Tasks",
+			"label": _("Completed Tasks"),
 			"datatype": "Int",
 		},
 		{
 			"value": total_overdue,
 			"indicator": "Green" if total_overdue == 0 else "Red",
-			"label": "Overdue Tasks",
+			"label": _("Overdue Tasks"),
 			"datatype": "Int",
 		}
 	]
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index a0398e7..a2b95cb 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -640,6 +640,10 @@
 										let key = item.name;
 										me.apply_rule_on_other_items({key: item});
 									}
+								},
+								() => {
+									var company_currency = me.get_company_currency();
+									me.update_item_grid_labels(company_currency);
 								}
 							]);
 						}
@@ -1321,11 +1325,9 @@
 	change_grid_labels: function(company_currency) {
 		var me = this;
 
-		this.frm.set_currency_labels(["base_rate", "base_net_rate", "base_price_list_rate", "base_amount", "base_net_amount", "base_rate_with_margin"],
-			company_currency, "items");
+		this.update_item_grid_labels(company_currency);
 
-		this.frm.set_currency_labels(["rate", "net_rate", "price_list_rate", "amount", "net_amount", "stock_uom_rate", "rate_with_margin"],
-			this.frm.doc.currency, "items");
+		this.toggle_item_grid_columns(company_currency);
 
 		if(this.frm.fields_dict["operations"]) {
 			this.frm.set_currency_labels(["operating_cost", "hour_rate"], this.frm.doc.currency, "operations");
@@ -1360,6 +1362,39 @@
 				this.frm.doc.party_account_currency, "advances");
 		}
 
+		this.update_payment_schedule_grid_labels(company_currency);
+	},
+
+	update_item_grid_labels: function(company_currency) {
+		this.frm.set_currency_labels([
+			"base_rate", "base_net_rate", "base_price_list_rate",
+			"base_amount", "base_net_amount", "base_rate_with_margin"
+		], company_currency, "items");
+
+		this.frm.set_currency_labels([
+			"rate", "net_rate", "price_list_rate", "amount",
+			"net_amount", "stock_uom_rate", "rate_with_margin"
+		], this.frm.doc.currency, "items");
+	},
+
+	update_payment_schedule_grid_labels: function(company_currency) {
+		const me = this;
+		if (this.frm.fields_dict["payment_schedule"]) {
+			this.frm.set_currency_labels(["base_payment_amount", "base_outstanding", "base_paid_amount"],
+				company_currency, "payment_schedule");
+			this.frm.set_currency_labels(["payment_amount", "outstanding", "paid_amount"],
+				this.frm.doc.currency, "payment_schedule");
+			
+			var schedule_grid = this.frm.fields_dict["payment_schedule"].grid;
+			$.each(["base_payment_amount", "base_outstanding", "base_paid_amount"], function(i, fname) {
+				if (frappe.meta.get_docfield(schedule_grid.doctype, fname))
+					schedule_grid.set_column_disp(fname, me.frm.doc.currency != company_currency);
+			});
+		}
+	},
+
+	toggle_item_grid_columns: function(company_currency) {
+		const me = this;
 		// toggle columns
 		var item_grid = this.frm.fields_dict["items"].grid;
 		$.each(["base_rate", "base_price_list_rate", "base_amount", "base_rate_with_margin"], function(i, fname) {
@@ -1379,9 +1414,6 @@
 			if(frappe.meta.get_docfield(item_grid.doctype, fname))
 				item_grid.set_column_disp(fname, (show && (me.frm.doc.currency != company_currency)));
 		});
-
-		// set labels
-		var $wrapper = $(this.frm.wrapper);
 	},
 
 	recalculate: function() {
@@ -1995,11 +2027,14 @@
 					terms_template: doc.payment_terms_template,
 					posting_date: posting_date,
 					grand_total: doc.rounded_total || doc.grand_total,
+					base_grand_total: doc.base_rounded_total || doc.base_grand_total,
 					bill_date: doc.bill_date
 				},
 				callback: function(r) {
 					if(r.message && !r.exc) {
 						me.frm.set_value("payment_schedule", r.message);
+						const company_currency = me.get_company_currency();
+						this.update_payment_schedule_grid_labels(company_currency);
 					}
 				}
 			})
@@ -2007,6 +2042,7 @@
 	},
 
 	payment_term: function(doc, cdt, cdn) {
+		const me = this;
 		var row = locals[cdt][cdn];
 		if(row.payment_term) {
 			frappe.call({
@@ -2015,12 +2051,15 @@
 					term: row.payment_term,
 					bill_date: this.frm.doc.bill_date,
 					posting_date: this.frm.doc.posting_date || this.frm.doc.transaction_date,
-					grand_total: this.frm.doc.rounded_total || this.frm.doc.grand_total
+					grand_total: this.frm.doc.rounded_total || this.frm.doc.grand_total,
+					base_grand_total: this.frm.doc.base_rounded_total || this.frm.doc.base_grand_total
 				},
 				callback: function(r) {
 					if(r.message && !r.exc) {
 						for (var d in r.message) {
 							frappe.model.set_value(cdt, cdn, d, r.message[d]);
+							const company_currency = me.get_company_currency();
+							me.update_payment_schedule_grid_labels(company_currency);
 						}
 					}
 				}
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 2079cf8..8aec893 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -46,9 +46,6 @@
 			}, __("View"));
 		}
 
-		if (!frm.doc.is_fixed_asset) {
-			erpnext.item.make_dashboard(frm);
-		}
 
 		if (frm.doc.is_fixed_asset) {
 			frm.trigger('is_fixed_asset');
@@ -96,6 +93,10 @@
 
 		erpnext.item.edit_prices_button(frm);
 		erpnext.item.toggle_attributes(frm);
+		
+		if (!frm.doc.is_fixed_asset) {
+			erpnext.item.make_dashboard(frm);
+		}
 
 		frm.add_custom_button(__('Duplicate'), function() {
 			var new_item = frappe.model.copy_doc(frm.doc);
@@ -473,11 +474,15 @@
 								me.multiple_variant_dialog.get_primary_btn().html(__('Create Variants'));
 								me.multiple_variant_dialog.disable_primary_action();
 							} else {
+
 								let no_of_combinations = lengths.reduce((a, b) => a * b, 1);
-								me.multiple_variant_dialog.get_primary_btn()
-									.html(__(
-										`Make ${no_of_combinations} Variant${no_of_combinations === 1 ? '' : 's'}`
-									));
+								let msg;
+								if (no_of_combinations === 1) {
+									msg = __("Make {0} Variant", [no_of_combinations]);
+								} else {
+									msg = __("Make {0} Variants", [no_of_combinations]);
+								}
+								me.multiple_variant_dialog.get_primary_btn().html(msg);
 								me.multiple_variant_dialog.enable_primary_action();
 							}
 						}
diff --git a/requirements.txt b/requirements.txt
index 377fd7d..f1ffeb8 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,4 @@
-frappe
+# frappe   # https://github.com/frappe/frappe is installed during bench-init
 gocardless-pro~=1.22.0
 googlemaps  # used in ERPNext, but dependency is defined in Frappe
 pandas~=1.1.5