Merge branch 'develop' into version-12
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index fbf230a..ff08a72 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__ = '12.1.3'
+__version__ = '12.1.4'
 
 def get_default_company(user=None):
 	'''Get default company for user'''
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index a7279f7..8cbf845 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -446,6 +446,10 @@
 
 		row.age = (getdate(self.age_as_on) - getdate(entry_date)).days or 0
 		index = None
+
+		if not (self.filters.range1 and self.filters.range2 and self.filters.range3 and self.filters.range4):
+			self.filters.range1, self.filters.range2, self.filters.range3, self.filters.range4 = 30, 60, 90, 120
+
 		for i, days in enumerate([self.filters.range1, self.filters.range2, self.filters.range3, self.filters.range4]):
 			if row.age <= days:
 				index = i
diff --git a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py
index 7872dbe..2cb10b1 100644
--- a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py
+++ b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py
@@ -286,14 +286,14 @@
 
 			if parties and accounts:
 				if len(parties) == 1:
-					party = parties.keys()[0]
+					party = list(parties.keys())[0]
 					for account, amount in iteritems(accounts):
 						self.party_adjustment_accounts.add(account)
 						self.party_adjustment_details.setdefault(party, {})
 						self.party_adjustment_details[party].setdefault(account, 0)
 						self.party_adjustment_details[party][account] += amount
 				elif len(accounts) == 1 and not has_irrelevant_entry:
-					account = accounts.keys()[0]
+					account = list(accounts.keys())[0]
 					self.party_adjustment_accounts.add(account)
 					for party, amount in iteritems(parties):
 						self.party_adjustment_details.setdefault(party, {})
diff --git a/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py b/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py
index 24b5d87..57a1231 100644
--- a/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py
+++ b/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py
@@ -4,11 +4,14 @@
 from __future__ import unicode_literals
 import frappe
 from frappe import _
-from erpnext.accounts.report.accounts_receivable.accounts_receivable import get_ageing_data
+from erpnext.accounts.report.accounts_receivable.accounts_receivable import ReceivablePayableReport
 from frappe.utils import getdate, flt
 
+
 def execute(filters=None):
-	if not filters: filters = {}
+	if not filters:
+		filters = {}
+
 	validate_filters(filters)
 
 	columns = get_columns(filters)
@@ -19,18 +22,28 @@
 	for d in entries:
 		invoice = invoice_details.get(d.against_voucher) or frappe._dict()
 
-		if d.reference_type=="Purchase Invoice":
+		if d.reference_type == "Purchase Invoice":
 			payment_amount = flt(d.debit) or -1 * flt(d.credit)
 		else:
 			payment_amount = flt(d.credit) or -1 * flt(d.debit)
 
-		row = [d.voucher_type, d.voucher_no, d.party_type, d.party, d.posting_date, d.against_voucher,
-			invoice.posting_date, invoice.due_date, d.debit, d.credit, d.remarks]
+		d.update({
+			"range1": 0,
+			"range2": 0,
+			"range3": 0,
+			"range4": 0,
+			"outstanding": payment_amount
+		})
 
 		if d.against_voucher:
-			row += get_ageing_data(30, 60, 90, 120, d.posting_date, invoice.posting_date, payment_amount)
-		else:
-			row += ["", "", "", "", ""]
+			ReceivablePayableReport(filters).get_ageing_data(invoice.posting_date, d)
+
+		row = [
+			d.voucher_type, d.voucher_no, d.party_type, d.party, d.posting_date, d.against_voucher,
+			invoice.posting_date, invoice.due_date, d.debit, d.credit, d.remarks, 
+			d.age, d.range1, d.range2, d.range3, d.range4
+		]
+
 		if invoice.due_date:
 			row.append((getdate(d.posting_date) - getdate(invoice.due_date)).days or 0)
 
diff --git a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py
index 7551eae..ecb55dd 100644
--- a/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py
+++ b/erpnext/assets/doctype/asset_maintenance/asset_maintenance.py
@@ -57,7 +57,7 @@
 	if not start_date and not last_completion_date:
 		start_date = frappe.utils.now()
 
-	if last_completion_date and (last_completion_date > start_date or not start_date):
+	if last_completion_date and ((start_date and last_completion_date > start_date) or not start_date):
 		start_date = last_completion_date
 	if periodicity == 'Daily':
 		next_due_date = add_days(start_date, 1)
@@ -71,10 +71,11 @@
 		next_due_date = add_years(start_date, 2)
 	if periodicity == 'Quarterly':
 		next_due_date = add_months(start_date, 3)
-	if end_date and (start_date >= end_date or last_completion_date >= end_date or next_due_date):
+	if end_date and ((start_date and start_date >= end_date) or (last_completion_date and last_completion_date >= end_date) or next_due_date):
 		next_due_date = ""
 	return next_due_date
 
+
 def update_maintenance_log(asset_maintenance, item_code, item_name, task):
 	asset_maintenance_log = frappe.get_value("Asset Maintenance Log", {"asset_maintenance": asset_maintenance,
 		"task": task.maintenance_task, "maintenance_status": ('in',['Planned','Overdue'])})
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index b2a2f01..c5fa98d 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -10,7 +10,8 @@
 		frm.custom_make_buttons = {
 			'Purchase Receipt': 'Receipt',
 			'Purchase Invoice': 'Invoice',
-			'Stock Entry': 'Material to Supplier'
+			'Stock Entry': 'Material to Supplier',
+			'Payment Entry': 'Payment'
 		}
 
 		frm.set_query("reserve_warehouse", "supplied_items", function() {
@@ -196,10 +197,10 @@
 		if(items.length >= 1){
 			me.raw_material_data = [];
 			me.show_dialog = 1;
-			let title = "";
+			let title = __('Transfer Material to Supplier');
 			let fields = [
 			{fieldtype:'Section Break', label: __('Raw Materials')},
-			{fieldname: 'sub_con_rm_items', fieldtype: 'Table',
+			{fieldname: 'sub_con_rm_items', fieldtype: 'Table', label: __('Items'),
 				fields: [
 					{
 						fieldtype:'Data',
@@ -271,7 +272,7 @@
 						'item_code': item.main_item_code,
 						'rm_item_code': item.rm_item_code,
 						'item_name': item.rm_item_code,
-						'qty': item.required_qty,
+						'qty': item.required_qty - item.supplied_qty,
 						'warehouse':item.reserve_warehouse,
 						'rate':item.rate,
 						'amount':item.amount,
diff --git a/erpnext/hr/doctype/upload_attendance/upload_attendance.py b/erpnext/hr/doctype/upload_attendance/upload_attendance.py
index f452155..1707e35 100644
--- a/erpnext/hr/doctype/upload_attendance/upload_attendance.py
+++ b/erpnext/hr/doctype/upload_attendance/upload_attendance.py
@@ -60,8 +60,8 @@
 			existing_attendance = {}
 			if existing_attendance_records \
 				and tuple([getdate(date), employee.name]) in existing_attendance_records \
-				and getdate(employee.date_of_joining) >= getdate(date) \
-				and getdate(employee.relieving_date) <= getdate(date):
+				and getdate(employee.date_of_joining) <= getdate(date) \
+				and getdate(employee.relieving_date) >= getdate(date):
 					existing_attendance = existing_attendance_records[tuple([getdate(date), employee.name])]
 			row = [
 				existing_attendance and existing_attendance.name or "",
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 8eb4c9c..f82afb7 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -648,7 +648,7 @@
 			item_dict[item.item_code] = item
 
 	for item, item_details in item_dict.items():
-		for d in [["Account", "expense_account", "default_expense_account"],
+		for d in [["Account", "expense_account", "stock_adjustment_account"],
 			["Cost Center", "cost_center", "cost_center"], ["Warehouse", "default_warehouse", ""]]:
 				company_in_record = frappe.db.get_value(d[0], item_details.get(d[1]), "company")
 				if not item_details.get(d[1]) or (company_in_record and company != company_in_record):
diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py
index a8faa13..9d2e620 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.py
+++ b/erpnext/manufacturing/doctype/job_card/job_card.py
@@ -105,7 +105,6 @@
 		for_quantity, time_in_mins = 0, 0
 		from_time_list, to_time_list = [], []
 
-
 		for d in frappe.get_all('Job Card',
 			filters = {'docstatus': 1, 'operation_id': self.operation_id}):
 			doc = frappe.get_doc('Job Card', d.name)
@@ -125,8 +124,8 @@
 				if data.name == self.operation_id:
 					data.completed_qty = for_quantity
 					data.actual_operation_time = time_in_mins
-					data.actual_start_time = min(from_time_list)
-					data.actual_end_time = max(to_time_list)
+					data.actual_start_time = min(from_time_list) if from_time_list else None
+					data.actual_end_time = max(to_time_list) if to_time_list else None
 
 			wo.flags.ignore_validate_update_after_submit = True
 			wo.update_operation_status()
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index e86cadd..d6fd8a1 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -11,7 +11,8 @@
 			'Sales Invoice': 'Invoice',
 			'Material Request': 'Material Request',
 			'Purchase Order': 'Purchase Order',
-			'Project': 'Project'
+			'Project': 'Project',
+			'Payment Entry': "Payment"
 		}
 		frm.add_fetch('customer', 'tax_id', 'tax_id');
 
diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js
index 000d666..e508476 100644
--- a/erpnext/selling/sales_common.js
+++ b/erpnext/selling/sales_common.js
@@ -234,7 +234,7 @@
 					args: {
 						item_code: item.item_code,
 						warehouse: item.warehouse,
-						has_batch_no: has_batch_no,
+						has_batch_no: has_batch_no || 0,
 						stock_qty: item.stock_qty,
 						serial_no: item.serial_no || "",
 					},
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 35c0bb6..7c2e09e 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -808,7 +808,7 @@
 	return {'serial_no': serial_no}
 
 @frappe.whitelist()
-def get_bin_details_and_serial_nos(item_code, warehouse, has_batch_no, stock_qty=None, serial_no=None):
+def get_bin_details_and_serial_nos(item_code, warehouse, has_batch_no=None, stock_qty=None, serial_no=None):
 	bin_details_and_serial_nos = {}
 	bin_details_and_serial_nos.update(get_bin_details(item_code, warehouse))
 	if flt(stock_qty) > 0:
diff --git a/erpnext/stock/report/total_stock_summary/total_stock_summary.py b/erpnext/stock/report/total_stock_summary/total_stock_summary.py
index b25e096..41e2f86 100644
--- a/erpnext/stock/report/total_stock_summary/total_stock_summary.py
+++ b/erpnext/stock/report/total_stock_summary/total_stock_summary.py
@@ -15,8 +15,8 @@
 
 def get_columns():
 	columns = [
-		_("Company") + ":Link/Item:250",
-		_("Warehouse") + ":Link/Item:150",
+		_("Company") + ":Link/Company:250",
+		_("Warehouse") + ":Link/Warehouse:150",
 		_("Item") + ":Link/Item:150",
 		_("Description") + "::300",
 		_("Current Qty") + ":Float:100",
@@ -30,7 +30,7 @@
 
 	if filters.get("group_by") == "Warehouse":
 		if filters.get("company"):
-			conditions += " AND warehouse.company = %s" % frappe.db.escape(filters.get("company"), percent=False)
+			conditions += " AND warehouse.company = '%s'" % frappe.db.escape(filters.get("company"), percent=False)
 
 		conditions += " GROUP BY ledger.warehouse, item.item_code"
 		columns += "'' as company, ledger.warehouse"