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