fix: Merge branch develop into dimensions
diff --git a/erpnext/accounts/doctype/accounting_dimension/__init__.py b/erpnext/accounts/doctype/accounting_dimension/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/accounting_dimension/__init__.py
diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js
new file mode 100644
index 0000000..34d17ec
--- /dev/null
+++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js
@@ -0,0 +1,22 @@
+// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Accounting Dimension', {
+
+	refresh: function(frm) {
+		frm.add_custom_button(__('Show {0} List', [frm.doc.document_type]), function () {
+			frappe.set_route("List", frm.doc.document_type);
+		});
+	},
+
+	document_type: function(frm) {
+		frm.set_value('label', frm.doc.document_type);
+		frm.set_value('fieldname', frappe.scrub(frm.doc.document_type))
+
+		frappe.db.get_value('Accounting Dimension', {'document_type': frm.doc.document_type}, 'document_type', (r) => {
+			if (r.document_type) {
+				frm.set_df_property('document_type', 'description', "Document type is already set as dimension");
+			}
+		});
+	},
+});
diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json
new file mode 100644
index 0000000..daa1004
--- /dev/null
+++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json
@@ -0,0 +1,69 @@
+{
+ "autoname": "field:label",
+ "creation": "2019-05-04 18:13:37.002352",
+ "doctype": "DocType",
+ "engine": "InnoDB",
+ "field_order": [
+  "document_type",
+  "label",
+  "fieldname",
+  "is_mandatory",
+  "disable"
+ ],
+ "fields": [
+  {
+   "fieldname": "label",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Label",
+   "unique": 1
+  },
+  {
+   "fieldname": "fieldname",
+   "fieldtype": "Data",
+   "label": "Fieldname"
+  },
+  {
+   "fieldname": "document_type",
+   "fieldtype": "Link",
+   "label": "Document Type",
+   "options": "DocType",
+   "reqd": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "is_mandatory",
+   "fieldtype": "Check",
+   "label": "Is Mandatory"
+  },
+  {
+   "default": "0",
+   "fieldname": "disable",
+   "fieldtype": "Check",
+   "label": "Disable"
+  }
+ ],
+ "modified": "2019-05-17 20:35:31.014495",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Accounting Dimension",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "share": 1,
+   "write": 1
+  }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "ASC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
new file mode 100644
index 0000000..565d243
--- /dev/null
+++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
@@ -0,0 +1,133 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+import json
+from frappe.model.document import Document
+from frappe.custom.doctype.custom_field.custom_field import create_custom_field
+from frappe import scrub
+from frappe.utils import cstr
+from frappe.utils.background_jobs import enqueue
+
+class AccountingDimension(Document):
+	def on_update(self):
+		frappe.enqueue(disable_dimension, doc=self)
+
+	def before_insert(self):
+		self.set_fieldname_and_label()
+		frappe.enqueue(make_dimension_in_accounting_doctypes, doc=self)
+
+	def on_trash(self):
+		frappe.enqueue(delete_accounting_dimension, doc=self)
+
+	def set_fieldname_and_label(self):
+		if not self.label:
+			self.label = cstr(self.document_type)
+
+		if not self.fieldname:
+			self.fieldname = scrub(self.label)
+
+def make_dimension_in_accounting_doctypes(doc):
+	doclist = get_doclist()
+
+	if doc.is_mandatory:
+		df.update({
+			"reqd": 1
+		})
+
+	for doctype in doclist:
+
+		df = {
+			"fieldname": doc.fieldname,
+			"label": doc.label,
+			"fieldtype": "Link",
+			"options": doc.document_type,
+			"insert_after": "cost_center"
+		}
+
+		if doctype == "Budget":
+			df.update({
+				"depends_on": "eval:doc.budget_against == '{0}'".format(doc.document_type)
+			})
+
+			create_custom_field(doctype, df)
+
+			property_setter = frappe.db.exists("Property Setter", "Budget-budget_against-options")
+
+			if property_setter:
+				property_setter_doc = frappe.get_doc("Property Setter", "Budget-budget_against-options")
+				property_setter_doc.value = property_setter_doc.value + "\n" + doc.document_type
+				property_setter_doc.save()
+
+				frappe.clear_cache(doctype='Budget')
+			else:
+				frappe.get_doc({
+					"doctype": "Property Setter",
+					"doctype_or_field": "DocField",
+					"doc_type": "Budget",
+					"field_name": "budget_against",
+					"property": "options",
+					"property_type": "Text",
+					"value": "\nCost Center\nProject\n" + doc.document_type
+				}).insert(ignore_permissions=True)
+			frappe.clear_cache(doctype=doctype)
+		else:
+			create_custom_field(doctype, df)
+			frappe.clear_cache(doctype=doctype)
+
+def delete_accounting_dimension(doc):
+	doclist = get_doclist()
+
+	frappe.db.sql("""
+		DELETE FROM `tabCustom Field`
+		WHERE  fieldname = %s
+		AND dt IN (%s)""" %
+		('%s', ', '.join(['%s']* len(doclist))), tuple([doc.fieldname] + doclist))
+
+	frappe.db.sql("""
+		DELETE FROM `tabProperty Setter`
+		WHERE  field_name = %s
+		AND doc_type IN (%s)""" %
+		('%s', ', '.join(['%s']* len(doclist))), tuple([doc.fieldname] + doclist))
+
+	budget_against_property = frappe.get_doc("Property Setter", "Budget-budget_against-options")
+	value_list = budget_against_property.value.split('\n')[3:]
+	value_list.remove(doc.document_type)
+
+	budget_against_property.value = "\nCost Center\nProject\n" + "\n".join(value_list)
+	budget_against_property.save()
+
+	for doctype in doclist:
+		frappe.clear_cache(doctype=doctype)
+
+def disable_dimension(doc):
+	if doc.disable:
+		df = {"read_only": 1}
+	else:
+		df = {"read_only": 0}
+
+	doclist = get_doclist()
+
+	for doctype in doclist:
+		field = frappe.db.get_value("Custom Field", {"dt": doctype, "fieldname": doc.fieldname})
+		if field:
+			custom_field = frappe.get_doc("Custom Field", field)
+			custom_field.update(df)
+			custom_field.save()
+
+		frappe.clear_cache(doctype=doctype)
+
+def get_doclist():
+	doclist = ["GL Entry", "Sales Invoice", "Purchase Invoice", "Payment Entry", "Asset",
+		"Expense Claim", "Stock Entry", "Budget", "Payroll Entry", "Delivery Note", "Sales Invoice Item", "Purchase Invoice Item",
+		"Purchase Order Item", "Journal Entry Account", "Material Request Item", "Delivery Note Item", "Purchase Receipt Item",
+		"Stock Entry Detail", "Payment Entry Deduction"]
+
+	return doclist
+
+def get_accounting_dimensions():
+	accounting_dimensions = frappe.get_all("Accounting Dimension", fields=["fieldname"])
+
+	return [d.fieldname for d in accounting_dimensions]
diff --git a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py
new file mode 100644
index 0000000..68ac707
--- /dev/null
+++ b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
+from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
+
+class TestAccountingDimension(unittest.TestCase):
+	def setUp(self):
+		frappe.set_user("Administrator")
+
+		if not frappe.db.exists("Accounting Dimension", {"document_type": "Department"}):
+			dimension = frappe.get_doc({
+				"doctype": "Accounting Dimension",
+				"document_type": "Department",
+			}).insert()
+
+	def test_dimension_against_sales_invoice(self):
+		si = create_sales_invoice(do_not_save=1)
+		si.append("items", {
+			"item_code": "_Test Item",
+			"warehouse": "_Test Warehouse - _TC",
+			"qty": 1,
+			"rate": 100,
+			"income_account": "Sales - _TC",
+			"expense_account": "Cost of Goods Sold - _TC",
+			"cost_center": "_Test Cost Center - _TC",
+			"department": "_Test Department - _TC"
+		})
+
+		si.save()
+		si.submit()
+
+		gle = frappe.get_doc("GL Entry", {"voucher_no": si.name, "account": "Sales - _TC"})
+
+		self.assertEqual(gle.department, "_Test Department - _TC")
+
+	def test_dimension_against_journal_entry(self):
+		je = make_journal_entry("Sales - _TC", "Sales Expenses - _TC", 500, save=False)
+		je.accounts[0].update({"department": "_Test Department - _TC"})
+		je.accounts[1].update({"department": "_Test Department - _TC"})
+
+		je.save()
+		je.submit()
+
+		gle = frappe.get_doc("GL Entry", {"voucher_no": je.name, "account": "Sales - _TC"})
+		gle1 = frappe.get_doc("GL Entry", {"voucher_no": je.name, "account": "Sales Expenses - _TC"})
+		self.assertEqual(gle.department, "_Test Department - _TC")
+		self.assertEqual(gle1.department, "_Test Department - _TC")
+
+
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 63f180d..26fbc23 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -509,7 +509,7 @@
 						"cost_center": d.cost_center,
 						"project": d.project,
 						"finance_book": self.finance_book
-					})
+					}, item=d)
 				)
 
 		if gl_map:
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index e224ee7..92803a6 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -507,7 +507,7 @@
 						"debit_in_account_currency": d.amount,
 						"debit": d.amount,
 						"cost_center": d.cost_center
-					})
+					}, item=d)
 				)
 
 	def update_advance_paid(self):
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 97ad0ea..9be61b7 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -456,7 +456,7 @@
 							"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
 							"cost_center": item.cost_center,
 							"project": item.project
-						}, account_currency)
+						}, account_currency, item=item)
 					)
 
 					# Amount added through landed-cost-voucher
@@ -468,7 +468,7 @@
 							"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
 							"credit": flt(item.landed_cost_voucher_amount),
 							"project": item.project
-						}))
+						}), item=item)
 
 					# sub-contracting warehouse
 					if flt(item.rm_supp_cost):
@@ -482,7 +482,7 @@
 							"cost_center": item.cost_center,
 							"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
 							"credit": flt(item.rm_supp_cost)
-						}, warehouse_account[self.supplier_warehouse]["account_currency"]))
+						}, warehouse_account[self.supplier_warehouse]["account_currency"], item=item))
 				elif not item.is_fixed_asset or (item.is_fixed_asset and is_cwip_accounting_disabled()):
 					gl_entries.append(
 						self.get_gl_dict({
@@ -494,7 +494,7 @@
 								else flt(item.net_amount, item.precision("net_amount"))),
 							"cost_center": item.cost_center,
 							"project": item.project
-						}, account_currency)
+						}, account_currency, item=item)
 					)
 
 			if self.auto_accounting_for_stock and self.is_opening == "No" and \
@@ -513,7 +513,7 @@
 									"debit": flt(item.item_tax_amount, item.precision("item_tax_amount")),
 									"remarks": self.remarks or "Accounting Entry for Stock",
 									"cost_center": self.cost_center
-								})
+								}, item=item)
 							)
 
 							self.negative_expense_to_be_booked += flt(item.item_tax_amount, \
@@ -542,7 +542,7 @@
 						"debit_in_account_currency": (base_asset_amount
 							if asset_rbnb_currency == self.company_currency else asset_amount),
 						"cost_center": item.cost_center
-					}))
+					}, item=item))
 
 					if item.item_tax_amount:
 						asset_eiiav_currency = get_account_currency(eiiav_account)
@@ -555,7 +555,7 @@
 							"credit_in_account_currency": (item.item_tax_amount
 								if asset_eiiav_currency == self.company_currency else
 									item.item_tax_amount / self.conversion_rate)
-						}))
+						}, item=item))
 				else:
 					cwip_account = get_asset_account("capital_work_in_progress_account",
 						item.asset, company = self.company)
@@ -569,7 +569,7 @@
 						"debit_in_account_currency": (base_asset_amount
 							if cwip_account_currency == self.company_currency else asset_amount),
 						"cost_center": self.cost_center
-					}))
+					}, item=item))
 
 					if item.item_tax_amount and not cint(erpnext.is_perpetual_inventory_enabled(self.company)):
 						asset_eiiav_currency = get_account_currency(eiiav_account)
@@ -582,7 +582,7 @@
 							"credit_in_account_currency": (item.item_tax_amount
 								if asset_eiiav_currency == self.company_currency else
 									item.item_tax_amount / self.conversion_rate)
-						}))
+						}, item=item))
 
 		return gl_entries
 
@@ -609,7 +609,7 @@
 					"remarks": self.get("remarks") or _("Stock Adjustment"),
 					"cost_center": item.cost_center,
 					"project": item.project
-				}, account_currency)
+				}, account_currency, item=item)
 			)
 
 			warehouse_debit_amount = stock_amount
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 20b5fb3..503f4f4 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -786,7 +786,7 @@
 								if account_currency==self.company_currency
 								else flt(item.net_amount, item.precision("net_amount"))),
 							"cost_center": item.cost_center
-						}, account_currency)
+						}, account_currency, item=item)
 					)
 
 		# expense account gl entries
diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py
index a661c03..e15dd2a 100644
--- a/erpnext/accounts/general_ledger.py
+++ b/erpnext/accounts/general_ledger.py
@@ -7,6 +7,7 @@
 from frappe import _
 from frappe.model.meta import get_field_precision
 from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget
+from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
 
 
 class StockAccountInvalidTransaction(frappe.ValidationError): pass
@@ -49,10 +50,11 @@
 
 def merge_similar_entries(gl_map):
 	merged_gl_map = []
+	accounting_dimensions = get_accounting_dimensions()
 	for entry in gl_map:
 		# if there is already an entry in this account then just add it
 		# to that entry
-		same_head = check_if_in_list(entry, merged_gl_map)
+		same_head = check_if_in_list(entry, merged_gl_map, accounting_dimensions)
 		if same_head:
 			same_head.debit	= flt(same_head.debit) + flt(entry.debit)
 			same_head.debit_in_account_currency	= \
@@ -69,16 +71,24 @@
 
 	return merged_gl_map
 
-def check_if_in_list(gle, gl_map):
+def check_if_in_list(gle, gl_map, dimensions=None):
+	account_head_fieldnames = ['party_type', 'party', 'against_voucher', 'against_voucher_type',
+		'cost_center', 'project']
+
+	if dimensions:
+		account_head_fieldnames = account_head_fieldnames + dimensions
+
 	for e in gl_map:
-		if e.account == gle.account \
-			and cstr(e.get('party_type'))==cstr(gle.get('party_type')) \
-			and cstr(e.get('party'))==cstr(gle.get('party')) \
-			and cstr(e.get('against_voucher'))==cstr(gle.get('against_voucher')) \
-			and cstr(e.get('against_voucher_type')) == cstr(gle.get('against_voucher_type')) \
-			and cstr(e.get('cost_center')) == cstr(gle.get('cost_center')) \
-			and cstr(e.get('project')) == cstr(gle.get('project')):
-				return e
+		same_head = True
+		if e.account != gle.account:
+			same_head = False
+
+		for fieldname in account_head_fieldnames:
+			if cstr(e.get(fieldname)) != cstr(gle.get(fieldname)):
+				same_head = False
+
+		if same_head:
+			return e
 
 def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False):
 	if not from_repost:
diff --git a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js
index cd9f9d9..b2072f0 100644
--- a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js
+++ b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js
@@ -62,3 +62,11 @@
 		},
 	]
 }
+
+let dimension_filters = erpnext.get_dimension_filters();
+
+dimension_filters.then((dimensions) => {
+	dimensions.forEach((dimension) => {
+		frappe.query_reports["Budget Variance Report"].filters[4].options.push(dimension["document_type"]);
+	});
+});
diff --git a/erpnext/accounts/report/budget_variance_report/budget_variance_report.py b/erpnext/accounts/report/budget_variance_report/budget_variance_report.py
index fe8de36..fb4f5d0 100644
--- a/erpnext/accounts/report/budget_variance_report/budget_variance_report.py
+++ b/erpnext/accounts/report/budget_variance_report/budget_variance_report.py
@@ -19,9 +19,12 @@
 	else:
 		cost_centers = get_cost_centers(filters)
 
+	print(cost_centers)
+
 	period_month_ranges = get_period_month_ranges(filters["period"], filters["from_fiscal_year"])
 	cam_map = get_cost_center_account_month_map(filters)
 
+	print(cam_map)
 	data = []
 	for cost_center in cost_centers:
 		cost_center_items = cam_map.get(cost_center)
@@ -45,8 +48,8 @@
 
 						if(filters.get("show_cumulative")):
 							last_total = period_data[0] - period_data[1]
-						
-						period_data[2] = period_data[0] - period_data[1] 
+
+						period_data[2] = period_data[0] - period_data[1]
 						row += period_data
 				totals[2] = totals[0] - totals[1]
 				if filters["period"] != "Yearly" :
@@ -56,7 +59,7 @@
 	return columns, data
 
 def validate_filters(filters):
-	if filters.get("budget_against")=="Project" and filters.get("cost_center"):
+	if filters.get("budget_against") != "Cost Center" and filters.get("cost_center"):
 		frappe.throw(_("Filter based on Cost Center is only applicable if Budget Against is selected as Cost Center"))
 
 def get_columns(filters):
@@ -92,8 +95,11 @@
 	if filters.get("budget_against") == "Cost Center":
 		cond = "order by lft"
 
-	return frappe.db.sql_list("""select name from `tab{tab}` where company=%s
-		{cond}""".format(tab=filters.get("budget_against"), cond=cond), filters.get("company"))
+	if filters.get("budget_against") in ["Cost Center", "Project"]:
+		return frappe.db.sql_list("""select name from `tab{tab}` where company=%s
+			{cond}""".format(tab=filters.get("budget_against"), cond=cond), filters.get("company"))
+	else:
+		return frappe.db.sql_list("""select name from `tab{tab}`""".format(tab=filters.get("budget_against")))
 
 #Get cost center & target details
 def get_cost_center_target_details(filters):
@@ -109,7 +115,7 @@
 		""".format(budget_against=filters.get("budget_against").replace(" ", "_").lower(), cond=cond),
 		(filters.from_fiscal_year,filters.to_fiscal_year,filters.budget_against, filters.company), as_dict=True)
 
-	
+
 
 #Get target distribution details of accounts of cost center
 def get_target_distribution_details(filters):
@@ -118,7 +124,7 @@
 		from `tabMonthly Distribution Percentage` mdp, `tabMonthly Distribution` md
 		where mdp.parent=md.name and md.fiscal_year between %s and %s order by md.fiscal_year""",(filters.from_fiscal_year, filters.to_fiscal_year), as_dict=1):
 			target_details.setdefault(d.name, {}).setdefault(d.month, flt(d.percentage_allocation))
-	
+
 	return target_details
 
 #Get actual details from gl entry
@@ -129,7 +135,7 @@
 	if filters.get("budget_against") == "Cost Center":
 		cc_lft, cc_rgt = frappe.db.get_value("Cost Center", name, ["lft", "rgt"])
 		cond = "lft>='{lft}' and rgt<='{rgt}'".format(lft = cc_lft, rgt=cc_rgt)
-	
+
 	ac_details = frappe.db.sql("""select gl.account, gl.debit, gl.credit,gl.fiscal_year,
 		MONTHNAME(gl.posting_date) as month_name, b.{budget_against} as budget_against
 		from `tabGL Entry` gl, `tabBudget Account` ba, `tabBudget` b
@@ -153,6 +159,7 @@
 def get_cost_center_account_month_map(filters):
 	import datetime
 	cost_center_target_details = get_cost_center_target_details(filters)
+	print(cost_center_target_details)
 	tdd = get_target_distribution_details(filters)
 
 	cam_map = {}
diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py
index 2140315..7f0cbaa 100644
--- a/erpnext/accounts/report/financial_statements.py
+++ b/erpnext/accounts/report/financial_statements.py
@@ -16,6 +16,7 @@
 from frappe.utils import (flt, getdate, get_first_day, add_months, add_days, formatdate)
 
 from six import itervalues
+from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
 
 def get_period_list(from_fiscal_year, to_fiscal_year, periodicity, accumulated_values=False,
 	company=None, reset_period_on_fy_change=True):
@@ -348,20 +349,23 @@
 	additional_conditions += " and account in ({})"\
 		.format(", ".join([frappe.db.escape(d) for d in accounts]))
 
+	gl_filters = {
+		"company": company,
+		"from_date": from_date,
+		"to_date": to_date,
+	}
+
+	for key, value in filters.items():
+		if value:
+			gl_filters.update({
+				key: value
+			})
+
 	gl_entries = frappe.db.sql("""select posting_date, account, debit, credit, is_opening, fiscal_year, debit_in_account_currency, credit_in_account_currency, account_currency from `tabGL Entry`
 		where company=%(company)s
 		{additional_conditions}
 		and posting_date <= %(to_date)s
-		order by account, posting_date""".format(additional_conditions=additional_conditions),
-		{
-			"company": company,
-			"from_date": from_date,
-			"to_date": to_date,
-			"cost_center": filters.cost_center,
-			"project": filters.project,
-			"finance_book": filters.get("finance_book")
-		},
-		as_dict=True)
+		order by account, posting_date""".format(additional_conditions=additional_conditions), gl_filters, as_dict=True)
 
 	if filters and filters.get('presentation_currency'):
 		convert_to_presentation_currency(gl_entries, get_currency(filters))
@@ -375,6 +379,8 @@
 def get_additional_conditions(from_date, ignore_closing_entries, filters):
 	additional_conditions = []
 
+	accounting_dimensions = get_accounting_dimensions()
+
 	if ignore_closing_entries:
 		additional_conditions.append("ifnull(voucher_type, '')!='Period Closing Voucher'")
 
@@ -395,6 +401,11 @@
 		if filters.get("finance_book"):
 			additional_conditions.append("ifnull(finance_book, '') in (%(finance_book)s, '')")
 
+	if accounting_dimensions:
+		for dimension in accounting_dimensions:
+			if filters.get(dimension):
+				additional_conditions.append("{0} in (%({0})s)".format(dimension))
+
 	return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else ""
 
 def get_cost_centers_with_children(cost_centers):
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js
index e74c16a..d999a1b 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.js
+++ b/erpnext/accounts/report/general_ledger/general_ledger.js
@@ -219,3 +219,17 @@
 		}
 	]
 }
+
+let dimension_filters = erpnext.get_dimension_filters();
+
+dimension_filters.then((dimensions) => {
+	dimensions.forEach((dimension) => {
+		frappe.query_reports["General Ledger"].filters.push({
+			"fieldname": dimension["fieldname"],
+			"label": __(dimension["label"]),
+			"fieldtype": "Link",
+			"options": dimension["document_type"]
+		});
+	});
+});
+
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py
index 1f1f738..492df4b 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/general_ledger.py
@@ -10,6 +10,7 @@
 from erpnext.accounts.utils import get_account_currency
 from erpnext.accounts.report.financial_statements import get_cost_centers_with_children
 from six import iteritems
+from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
 
 def execute(filters=None):
 	if not filters:
@@ -195,6 +196,13 @@
 	if match_conditions:
 		conditions.append(match_conditions)
 
+	accounting_dimensions = get_accounting_dimensions()
+
+	if accounting_dimensions:
+		for dimension in accounting_dimensions:
+			if filters.get(dimension):
+				conditions.append("{0} in (%({0})s)".format(dimension))
+
 	return "and {}".format(" and ".join(conditions)) if conditions else ""
 
 
diff --git a/erpnext/config/accounting.py b/erpnext/config/accounting.py
index 6664c4d..0ab1f52 100644
--- a/erpnext/config/accounting.py
+++ b/erpnext/config/accounting.py
@@ -174,6 +174,11 @@
 					"name": "Cheque Print Template",
 					"description": _("Setup cheque dimensions for printing")
 				},
+				{
+					"type": "doctype",
+					"name": "Accounting Dimension",
+					"description": _("Setup custom dimensions for accounting")
+				},
 			]
 		},
 		{
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 0672b2d..11c70b3 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -16,6 +16,7 @@
 from erpnext.accounts.doctype.pricing_rule.utils import validate_pricing_rules
 from erpnext.exceptions import InvalidCurrency
 from six import text_type
+from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
 
 force_item_fields = ("item_group", "brand", "stock_uom", "is_fixed_asset", "item_tax_rate", "pricing_rules")
 
@@ -338,7 +339,7 @@
 					frappe.throw(_("Row #{0}: Account {1} does not belong to company {2}")
 								 .format(d.idx, d.account_head, self.company))
 
-	def get_gl_dict(self, args, account_currency=None):
+	def get_gl_dict(self, args, account_currency=None, item=None):
 		"""this method populates the common properties of a gl entry record"""
 
 		posting_date = args.get('posting_date') or self.get('posting_date')
@@ -365,6 +366,16 @@
 			'party': None,
 			'project': self.get("project")
 		})
+
+		accounting_dimensions = get_accounting_dimensions()
+		dimension_dict = frappe._dict()
+
+		for dimension in accounting_dimensions:
+			dimension_dict[dimension] = self.get(dimension)
+			if item and item.get(dimension):
+				dimension_dict[dimension] = item.get(dimension)
+
+		gl_dict.update(dimension_dict)
 		gl_dict.update(args)
 
 		if not account_currency:
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index cee7e5a..7d6eb4a 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -81,7 +81,7 @@
 							"remarks": self.get("remarks") or "Accounting Entry for Stock",
 							"debit": flt(sle.stock_value_difference, 2),
 							"is_opening": item_row.get("is_opening"),
-						}, warehouse_account[sle.warehouse]["account_currency"]))
+						}, warehouse_account[sle.warehouse]["account_currency"], item=item_row))
 
 						# to target warehouse / expense account
 						gl_list.append(self.get_gl_dict({
@@ -92,7 +92,7 @@
 							"credit": flt(sle.stock_value_difference, 2),
 							"project": item_row.get("project") or self.get("project"),
 							"is_opening": item_row.get("is_opening")
-						}))
+						}, item=item_row))
 					elif sle.warehouse not in warehouse_with_no_account:
 						warehouse_with_no_account.append(sle.warehouse)
 
diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js
index 36746cd..2e4b8f2 100644
--- a/erpnext/public/js/financial_statements.js
+++ b/erpnext/public/js/financial_statements.js
@@ -63,7 +63,7 @@
 };
 
 function get_filters(){
-	return [
+	let filters = [
 		{
 			"fieldname":"company",
 			"label": __("Company"),
@@ -149,4 +149,21 @@
 			"options": erpnext.get_presentation_currency_list()
 		}
 	]
+
+	let dimension_filters = erpnext.get_dimension_filters()
+
+	dimension_filters.then((dimensions) => {
+		dimensions.forEach((dimension) => {
+			filters.push({
+				"fieldname": dimension["fieldname"],
+				"label": __(dimension["label"]),
+				"fieldtype": "Link",
+				"options": dimension["document_type"]
+			});
+		});
+	});
+
+	return filters;
 }
+
+
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index 6860d6a..540b5ea 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -62,6 +62,14 @@
 		$btn.on("click", function() {
 			me.show_serial_batch_selector(grid_row.frm, grid_row.doc);
 		});
+	},
+
+	get_dimension_filters: async function() {
+		let dimensions = await frappe.db.get_list('Accounting Dimension', {
+			fields: ['label', 'fieldname', 'document_type'],
+		});
+
+		return dimensions;
 	}
 });
 
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 54a414c..14cc1b3 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -221,7 +221,7 @@
 						"cost_center": d.cost_center,
 						"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
 						"debit": stock_value_diff
-					}, warehouse_account[d.warehouse]["account_currency"]))
+					}, warehouse_account[d.warehouse]["account_currency"], item=d))
 
 					# stock received but not billed
 					stock_rbnb_currency = get_account_currency(stock_rbnb)
@@ -233,7 +233,7 @@
 						"credit": flt(d.base_net_amount, d.precision("base_net_amount")),
 						"credit_in_account_currency": flt(d.base_net_amount, d.precision("base_net_amount")) \
 							if stock_rbnb_currency==self.company_currency else flt(d.net_amount, d.precision("net_amount"))
-					}, stock_rbnb_currency))
+					}, stock_rbnb_currency, item=d))
 
 					negative_expense_to_be_booked += flt(d.item_tax_amount)
 
@@ -246,7 +246,7 @@
 							"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
 							"credit": flt(d.landed_cost_voucher_amount),
 							"project": d.project
-						}))
+						}, item=d))
 
 					# sub-contracting warehouse
 					if flt(d.rm_supp_cost) and warehouse_account.get(self.supplier_warehouse):
@@ -256,7 +256,7 @@
 							"cost_center": d.cost_center,
 							"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
 							"credit": flt(d.rm_supp_cost)
-						}, warehouse_account[self.supplier_warehouse]["account_currency"]))
+						}, warehouse_account[self.supplier_warehouse]["account_currency"], item=d))
 
 					# divisional loss adjustment
 					valuation_amount_as_per_doc = flt(d.base_net_amount, d.precision("base_net_amount")) + \
@@ -278,7 +278,7 @@
 							"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
 							"debit": divisional_loss,
 							"project": d.project
-						}, stock_rbnb_currency))
+						}, stock_rbnb_currency, item=d))
 
 				elif d.warehouse not in warehouse_with_no_account or \
 					d.rejected_warehouse not in warehouse_with_no_account:
@@ -360,7 +360,7 @@
 					"debit": base_asset_amount,
 					"debit_in_account_currency": (base_asset_amount
 						if cwip_account_currency == self.company_currency else asset_amount)
-				}))
+				}, item=d))
 
 				# Asset received but not billed
 				asset_rbnb_currency = get_account_currency(arbnb_account)
@@ -372,7 +372,7 @@
 					"credit": base_asset_amount,
 					"credit_in_account_currency": (base_asset_amount
 						if asset_rbnb_currency == self.company_currency else asset_amount)
-				}))
+				}, item=d))
 
 		return gl_entries
 
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index d106ed1..c881d83 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -611,7 +611,7 @@
 					"cost_center": d.cost_center,
 					"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
 					"credit": additional_cost
-				}))
+				}, item=d))
 
 				gl_entries.append(self.get_gl_dict({
 					"account": d.expense_account,
@@ -619,7 +619,7 @@
 					"cost_center": d.cost_center,
 					"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
 					"credit": -1 * additional_cost # put it as negative credit instead of debit purposefully
-				}))
+				}, item=d))
 
 		return gl_entries