From d83cf65be11c781cac7f1cb7b4a4a02993aaf3e4 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sun, 12 May 2019 18:34:23 +0530 Subject: [PATCH] fix: Added dimensions in financial reports and general ledger --- .../__init__.py | 0 .../accounting_dimension.js} | 2 +- .../accounting_dimension.json} | 13 +++++-- .../accounting_dimension.py} | 38 ++++++++++++------- .../test_accounting_dimension.py} | 2 +- .../accounts/report/financial_statements.py | 31 ++++++++++----- .../report/general_ledger/general_ledger.js | 21 ++++++++++ .../report/general_ledger/general_ledger.py | 8 ++++ erpnext/controllers/accounts_controller.py | 9 +++++ erpnext/public/js/financial_statements.js | 25 +++++++++++- 10 files changed, 119 insertions(+), 30 deletions(-) rename erpnext/accounts/doctype/{dimension => accounting_dimension}/__init__.py (100%) rename erpnext/accounts/doctype/{dimension/dimension.js => accounting_dimension/accounting_dimension.js} (78%) rename erpnext/accounts/doctype/{dimension/dimension.json => accounting_dimension/accounting_dimension.json} (76%) rename erpnext/accounts/doctype/{dimension/dimension.py => accounting_dimension/accounting_dimension.py} (57%) rename erpnext/accounts/doctype/{dimension/test_dimension.py => accounting_dimension/test_accounting_dimension.py} (79%) diff --git a/erpnext/accounts/doctype/dimension/__init__.py b/erpnext/accounts/doctype/accounting_dimension/__init__.py similarity index 100% rename from erpnext/accounts/doctype/dimension/__init__.py rename to erpnext/accounts/doctype/accounting_dimension/__init__.py diff --git a/erpnext/accounts/doctype/dimension/dimension.js b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js similarity index 78% rename from erpnext/accounts/doctype/dimension/dimension.js rename to erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js index 4926fff7da..0676731840 100644 --- a/erpnext/accounts/doctype/dimension/dimension.js +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js @@ -1,7 +1,7 @@ // Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors // For license information, please see license.txt -frappe.ui.form.on('Dimension', { +frappe.ui.form.on('Accounting Dimension', { // refresh: function(frm) { // } diff --git a/erpnext/accounts/doctype/dimension/dimension.json b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json similarity index 76% rename from erpnext/accounts/doctype/dimension/dimension.json rename to erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json index 4937e4d7a2..13902d6335 100644 --- a/erpnext/accounts/doctype/dimension/dimension.json +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json @@ -4,6 +4,7 @@ "doctype": "DocType", "engine": "InnoDB", "field_order": [ + "document_type", "label", "fieldname" ], @@ -13,19 +14,25 @@ "fieldtype": "Data", "in_list_view": 1, "label": "Label", - "reqd": 1, "unique": 1 }, { "fieldname": "fieldname", "fieldtype": "Data", "label": "Fieldname" + }, + { + "fieldname": "document_type", + "fieldtype": "Link", + "label": "Document Type", + "options": "DocType", + "reqd": 1 } ], - "modified": "2019-05-04 18:59:14.969008", + "modified": "2019-05-09 15:30:55.339917", "modified_by": "Administrator", "module": "Accounts", - "name": "Dimension", + "name": "Accounting Dimension", "owner": "Administrator", "permissions": [ { diff --git a/erpnext/accounts/doctype/dimension/dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py similarity index 57% rename from erpnext/accounts/doctype/dimension/dimension.py rename to erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py index 524b6acb00..93a25e7c0a 100644 --- a/erpnext/accounts/doctype/dimension/dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py @@ -8,22 +8,26 @@ from frappe.model.document import Document from frappe.custom.doctype.custom_field.custom_field import create_custom_fields from frappe.custom.doctype.custom_field.custom_field import create_custom_field from frappe import scrub +from frappe.utils import cstr -class Dimension(Document): +class AccountingDimension(Document): def before_insert(self): - self.set_fieldname() - self.make_dimension_in_accounting_doctypes() + self.set_fieldname_and_label() + self.make_accounting_dimension_in_accounting_doctypes() def on_trash(self): - self.delete_dimension() + self.delete_accounting_dimension() + + def set_fieldname_and_label(self): + if not self.label: + self.label = cstr(self.document_type) - def set_fieldname(self): if not self.fieldname: self.fieldname = scrub(self.label) - def make_dimension_in_accounting_doctypes(self): - last_created_dimension = get_last_created_dimension() + def make_accounting_dimension_in_accounting_doctypes(self): + last_created_accounting_dimension = get_last_created_accounting_dimension() doclist = ["GL Entry", "Sales Invoice", "Purchase Invoice", "Payment Entry", "BOM", "Sales Order", "Purchase Order", "Stock Entry", "Budget", "Payroll Entry", "Delivery Note"] @@ -31,14 +35,15 @@ class Dimension(Document): df = { "fieldname": self.fieldname, "label": self.label, - "fieldtype": "Data", - "insert_after": last_created_dimension if last_created_dimension else "project" + "fieldtype": "Link", + "options": self.document_type, + "insert_after": last_created_accounting_dimension if last_created_accounting_dimension else "project" } for doctype in doclist: create_custom_field(doctype, df) - def delete_dimension(self): + def delete_accounting_dimension(self): doclist = ["GL Entry", "Sales Invoice", "Purchase Invoice", "Payment Entry", "BOM", "Sales Order", "Purchase Order", "Stock Entry", "Budget", "Payroll Entry", "Delivery Note"] @@ -58,8 +63,13 @@ class Dimension(Document): frappe.clear_cache(doctype=doc) -def get_last_created_dimension(): - last_created_dimension = frappe.db.sql("select fieldname, max(creation) from `tabDimension`", as_dict=1) +def get_last_created_accounting_dimension(): + last_created_accounting_dimension = frappe.db.sql("select fieldname, max(creation) from `tabAccounting Dimension`", as_dict=1) - if last_created_dimension[0]: - return last_created_dimension[0].fieldname + if last_created_accounting_dimension[0]: + return last_created_accounting_dimension[0].fieldname + +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/dimension/test_dimension.py b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py similarity index 79% rename from erpnext/accounts/doctype/dimension/test_dimension.py rename to erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py index f726e9da66..b4368c4e61 100644 --- a/erpnext/accounts/doctype/dimension/test_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py @@ -6,5 +6,5 @@ from __future__ import unicode_literals # import frappe import unittest -class TestDimension(unittest.TestCase): +class TestAccountingDimension(unittest.TestCase): pass diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py index 214031582f..7f0cbaa263 100644 --- a/erpnext/accounts/report/financial_statements.py +++ b/erpnext/accounts/report/financial_statements.py @@ -16,6 +16,7 @@ from frappe import _ 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 @@ def set_gl_entries_by_account( 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 set_gl_entries_by_account( 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 @@ def get_additional_conditions(from_date, ignore_closing_entries, filters): 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 2826760dd8..7db8786c35 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.js +++ b/erpnext/accounts/report/general_ledger/general_ledger.js @@ -214,3 +214,24 @@ frappe.query_reports["General Ledger"] = { } ] } + +let dimension_filters = 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"] + }); + }); +}); + +async function get_dimension_filters() { + let dimensions = await frappe.db.get_list('Accounting Dimension', { + fields: ['label', 'fieldname', 'document_type'], + }); + + return dimensions; +} diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 44ca8d3549..033b9ba36a 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -10,6 +10,7 @@ from frappe import _, _dict 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 @@ def get_conditions(filters): 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/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 155a996a15..4f4084a2d7 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -16,6 +16,7 @@ from erpnext.accounts.party import get_party_account_currency, validate_party_fr 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") @@ -365,6 +366,14 @@ class AccountsController(TransactionBase): '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) + + gl_dict.update(dimension_dict) gl_dict.update(args) if not account_currency: diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js index 36746cddc3..77e67c49ed 100644 --- a/erpnext/public/js/financial_statements.js +++ b/erpnext/public/js/financial_statements.js @@ -63,7 +63,7 @@ erpnext.financial_statements = { }; function get_filters(){ - return [ + let filters = [ { "fieldname":"company", "label": __("Company"), @@ -149,4 +149,27 @@ function get_filters(){ "options": erpnext.get_presentation_currency_list() } ] + + let dimension_filters = 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; +} + +async function get_dimension_filters() { + let dimensions = await frappe.db.get_list('Accounting Dimension', { + fields: ['label', 'fieldname', 'document_type'], + }); + + return dimensions; }