mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-08 15:42:52 +00:00
Report presentation currency (#12670)
* Add new Select to filters
* get the currencies from database rather than hardcoded
* label report columns:
- If presentation currency is available in filters, use it or
- If company is available in filters, use it or
- use default company currency
* add new function - get_currency
* tweak new function `get_currency`
* add new function `convert` to convert a value to another currency
* add new function `convert_to_presentation_currency`
* clean up `get_currency` first pass
* memoise the exchange rates
* limit fetched GL entries to to_date
* check if account type is p&l or not and use appropriate exchange rate based on that
* change EXCHANGE RATE to a dict, use for memoisation
* rename EXCHANGE_RATE
* cache exchange rates and use them as needed
* add docstrings
* add presentation currency logic to financial statement reports
* move new functions from `general_ledger.py` to new module
* clean up
* PEP 8 clean up
* move function to util.py
* PEP 8 clean up
* remove presentation currency option from cashflow
* adjust currency as needed
* allow users to save presentation currency in Accounts Settings
* add new function `get_presentation_currency_list`
* refactor query_report modules with no promises
* Revert "allow users to save presentation currency in Accounts Settings"
This reverts commit 3b58a6296c.
* show print page in correct currency
* Update utils.py
This commit is contained in:
@@ -3,10 +3,13 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from erpnext import get_company_currency, get_default_company
|
||||
from erpnext.accounts.report.utils import get_currency, convert_to_presentation_currency
|
||||
from frappe.utils import getdate, cstr, flt, fmt_money
|
||||
from frappe import _, _dict
|
||||
from erpnext.accounts.utils import get_account_currency
|
||||
|
||||
|
||||
def execute(filters=None):
|
||||
account_details = {}
|
||||
|
||||
@@ -29,6 +32,7 @@ def execute(filters=None):
|
||||
|
||||
return columns, res
|
||||
|
||||
|
||||
def validate_filters(filters, account_details):
|
||||
if not filters.get('company'):
|
||||
frappe.throw(_('{0} is mandatory').format(_('Company')))
|
||||
@@ -37,7 +41,7 @@ def validate_filters(filters, account_details):
|
||||
frappe.throw(_("Account {0} does not exists").format(filters.account))
|
||||
|
||||
if filters.get("account") and filters.get("group_by_account") \
|
||||
and account_details[filters.account].is_group == 0:
|
||||
and account_details[filters.account].is_group == 0:
|
||||
frappe.throw(_("Can not filter based on Account, if grouped by Account"))
|
||||
|
||||
if filters.get("voucher_no") and filters.get("group_by_voucher"):
|
||||
@@ -56,6 +60,7 @@ def validate_party(filters):
|
||||
elif not frappe.db.exists(party_type, party):
|
||||
frappe.throw(_("Invalid {0}: {1}").format(party_type, party))
|
||||
|
||||
|
||||
def set_account_currency(filters):
|
||||
if not (filters.get("account") or filters.get("party")):
|
||||
return filters
|
||||
@@ -66,8 +71,13 @@ def set_account_currency(filters):
|
||||
if filters.get("account"):
|
||||
account_currency = get_account_currency(filters.account)
|
||||
elif filters.get("party"):
|
||||
gle_currency = frappe.db.get_value("GL Entry", {"party_type": filters.party_type,
|
||||
"party": filters.party, "company": filters.company}, "account_currency")
|
||||
gle_currency = frappe.db.get_value(
|
||||
"GL Entry", {
|
||||
"party_type": filters.party_type, "party": filters.party, "company": filters.company
|
||||
},
|
||||
"account_currency"
|
||||
)
|
||||
|
||||
if gle_currency:
|
||||
account_currency = gle_currency
|
||||
else:
|
||||
@@ -90,29 +100,39 @@ def get_result(filters, account_details):
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def get_gl_entries(filters):
|
||||
currency_map = get_currency(filters)
|
||||
select_fields = """, sum(debit_in_account_currency) as debit_in_account_currency,
|
||||
sum(credit_in_account_currency) as credit_in_account_currency""" \
|
||||
if filters.get("show_in_account_currency") else ""
|
||||
|
||||
|
||||
group_by_condition = "group by voucher_type, voucher_no, account, cost_center" \
|
||||
if filters.get("group_by_voucher") else "group by name"
|
||||
|
||||
gl_entries = frappe.db.sql("""
|
||||
gl_entries = frappe.db.sql(
|
||||
"""
|
||||
select
|
||||
posting_date, account, party_type, party,
|
||||
sum(debit) as debit, sum(credit) as credit,
|
||||
voucher_type, voucher_no, cost_center, project,
|
||||
against_voucher_type, against_voucher,
|
||||
against_voucher_type, against_voucher, account_currency,
|
||||
remarks, against, is_opening {select_fields}
|
||||
from `tabGL Entry`
|
||||
where company=%(company)s {conditions}
|
||||
{group_by_condition}
|
||||
order by posting_date, account"""\
|
||||
.format(select_fields=select_fields, conditions=get_conditions(filters),
|
||||
group_by_condition=group_by_condition), filters, as_dict=1)
|
||||
order by posting_date, account
|
||||
""".format(
|
||||
select_fields=select_fields, conditions=get_conditions(filters),
|
||||
group_by_condition=group_by_condition
|
||||
),
|
||||
filters, as_dict=1)
|
||||
|
||||
if filters.get('presentation_currency'):
|
||||
return convert_to_presentation_currency(gl_entries, currency_map)
|
||||
else:
|
||||
return gl_entries
|
||||
|
||||
return gl_entries
|
||||
|
||||
def get_conditions(filters):
|
||||
conditions = []
|
||||
@@ -132,16 +152,20 @@ def get_conditions(filters):
|
||||
|
||||
if not (filters.get("account") or filters.get("party") or filters.get("group_by_account")):
|
||||
conditions.append("posting_date >=%(from_date)s")
|
||||
conditions.append("posting_date <=%(to_date)s")
|
||||
|
||||
if filters.get("project"):
|
||||
conditions.append("project=%(project)s")
|
||||
|
||||
from frappe.desk.reportview import build_match_conditions
|
||||
match_conditions = build_match_conditions("GL Entry")
|
||||
if match_conditions: conditions.append(match_conditions)
|
||||
|
||||
if match_conditions:
|
||||
conditions.append(match_conditions)
|
||||
|
||||
return "and {}".format(" and ".join(conditions)) if conditions else ""
|
||||
|
||||
|
||||
def get_data_with_opening_closing(filters, account_details, gl_entries):
|
||||
data = []
|
||||
gle_map = initialize_gle_map(gl_entries)
|
||||
@@ -178,14 +202,15 @@ def get_data_with_opening_closing(filters, account_details, gl_entries):
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def get_totals_dict():
|
||||
def _get_debit_credit_dict(label):
|
||||
return _dict(
|
||||
account = "'{0}'".format(label),
|
||||
debit = 0.0,
|
||||
credit = 0.0,
|
||||
debit_in_account_currency = 0.0,
|
||||
credit_in_account_currency = 0.0
|
||||
account="'{0}'".format(label),
|
||||
debit=0.0,
|
||||
credit=0.0,
|
||||
debit_in_account_currency=0.0,
|
||||
credit_in_account_currency=0.0
|
||||
)
|
||||
return _dict(
|
||||
opening = _get_debit_credit_dict(_('Opening')),
|
||||
@@ -193,12 +218,14 @@ def get_totals_dict():
|
||||
closing = _get_debit_credit_dict(_('Closing (Opening + Total)'))
|
||||
)
|
||||
|
||||
|
||||
def initialize_gle_map(gl_entries):
|
||||
gle_map = frappe._dict()
|
||||
for gle in gl_entries:
|
||||
gle_map.setdefault(gle.account, _dict(totals = get_totals_dict(), entries = []))
|
||||
gle_map.setdefault(gle.account, _dict(totals=get_totals_dict(), entries=[]))
|
||||
return gle_map
|
||||
|
||||
|
||||
def get_accountwise_gle(filters, gl_entries, gle_map):
|
||||
totals = get_totals_dict()
|
||||
entries = []
|
||||
@@ -210,13 +237,12 @@ def get_accountwise_gle(filters, gl_entries, gle_map):
|
||||
data[key].debit_in_account_currency += flt(gle.debit_in_account_currency)
|
||||
data[key].credit_in_account_currency += flt(gle.credit_in_account_currency)
|
||||
|
||||
|
||||
from_date, to_date = getdate(filters.from_date), getdate(filters.to_date)
|
||||
for gle in gl_entries:
|
||||
if gle.posting_date < from_date or cstr(gle.is_opening) == "Yes":
|
||||
update_value_in_dict(gle_map[gle.account].totals, 'opening', gle)
|
||||
update_value_in_dict(totals, 'opening', gle)
|
||||
|
||||
|
||||
update_value_in_dict(gle_map[gle.account].totals, 'closing', gle)
|
||||
update_value_in_dict(totals, 'closing', gle)
|
||||
|
||||
@@ -233,6 +259,7 @@ def get_accountwise_gle(filters, gl_entries, gle_map):
|
||||
|
||||
return totals, entries
|
||||
|
||||
|
||||
def get_result_as_list(data, filters):
|
||||
balance, balance_in_account_currency = 0, 0
|
||||
inv_details = get_supplier_invoice_details()
|
||||
@@ -272,6 +299,15 @@ def get_balance(row, balance, debit_field, credit_field):
|
||||
return balance
|
||||
|
||||
def get_columns(filters):
|
||||
if filters.get("presentation_currency"):
|
||||
currency = filters["presentation_currency"]
|
||||
else:
|
||||
if filters.get("company"):
|
||||
currency = get_company_currency(filters["company"])
|
||||
else:
|
||||
company = get_default_company()
|
||||
currency = get_company_currency(company)
|
||||
|
||||
columns = [
|
||||
{
|
||||
"label": _("Posting Date"),
|
||||
@@ -287,47 +323,25 @@ def get_columns(filters):
|
||||
"width": 180
|
||||
},
|
||||
{
|
||||
"label": _("Debit"),
|
||||
"label": _("Debit ({0})".format(currency)),
|
||||
"fieldname": "debit",
|
||||
"fieldtype": "Float",
|
||||
"width": 100
|
||||
},
|
||||
{
|
||||
"label": _("Credit"),
|
||||
"label": _("Credit ({0})".format(currency)),
|
||||
"fieldname": "credit",
|
||||
"fieldtype": "Float",
|
||||
"width": 100
|
||||
},
|
||||
{
|
||||
"label": _("Balance (Dr - Cr)"),
|
||||
"label": _("Balance ({0})".format(currency)),
|
||||
"fieldname": "balance",
|
||||
"fieldtype": "Float",
|
||||
"width": 130
|
||||
}
|
||||
]
|
||||
|
||||
if filters.get("show_in_account_currency"):
|
||||
columns.extend([
|
||||
{
|
||||
"label": _("Debit") + " (" + filters.account_currency + ")",
|
||||
"fieldname": "debit_in_account_currency",
|
||||
"fieldtype": "Float",
|
||||
"width": 100
|
||||
},
|
||||
{
|
||||
"label": _("Credit") + " (" + filters.account_currency + ")",
|
||||
"fieldname": "credit_in_account_currency",
|
||||
"fieldtype": "Float",
|
||||
"width": 100
|
||||
},
|
||||
{
|
||||
"label": _("Balance") + " (" + filters.account_currency + ")",
|
||||
"fieldname": "balance_in_account_currency",
|
||||
"fieldtype": "Data",
|
||||
"width": 100
|
||||
}
|
||||
])
|
||||
|
||||
columns.extend([
|
||||
{
|
||||
"label": _("Voucher Type"),
|
||||
|
||||
Reference in New Issue
Block a user