diff --git a/mis_builder/models/aep.py b/mis_builder/models/aep.py
index bc2f4021..500174ec 100644
--- a/mis_builder/models/aep.py
+++ b/mis_builder/models/aep.py
@@ -62,10 +62,9 @@ class AccountingExpressionProcessor(object):
# before done_parsing: {(domain, mode): set(account_codes)}
# after done_parsing: {(domain, mode): set(account_ids)}
self._map_account_ids = defaultdict(set)
- self._set_all_accounts = set() # set((domain, mode))
self._account_ids_by_code = defaultdict(set)
- def _load_account_codes(self, account_codes, account_domain):
+ def _load_account_codes(self, account_codes, root_account):
account_model = self.env['account.account']
# TODO: account_obj is necessary because _get_children_and_consol
# does not work in new API?
@@ -75,23 +74,35 @@ class AccountingExpressionProcessor(object):
for account_code in account_codes:
if account_code in self._account_ids_by_code:
continue
- if '%' in account_code:
+ if account_code is None:
+ # by convention the root account is keyed as
+ # None in _account_ids_by_code, so it is consistent
+ # with what _parse_match_object returns for an
+ # empty list of account codes, ie [None]
+ exact_codes.add(root_account.code)
+ elif '%' in account_code:
like_codes.add(account_code)
else:
exact_codes.add(account_code)
for account in account_model.\
- search([('code', 'in', list(exact_codes))] + account_domain):
+ search([('code', 'in', list(exact_codes)),
+ ('parent_id', 'child_of', root_account.id)]):
+ if account.code == root_account.code:
+ code = None
+ else:
+ code = account.code
if account.type in ('view', 'consolidation'):
- self._account_ids_by_code[account.code].update(
+ self._account_ids_by_code[code].update(
account_obj._get_children_and_consol(
self.env.cr, self.env.uid,
[account.id],
self.env.context))
else:
- self._account_ids_by_code[account.code].add(account.id)
+ self._account_ids_by_code[code].add(account.id)
for like_code in like_codes:
for account in account_model.\
- search([('code', 'like', like_code)] + account_domain):
+ search([('code', 'like', like_code),
+ ('parent_id', 'child_of', root_account.id)]):
if account.type in ('view', 'consolidation'):
self._account_ids_by_code[like_code].update(
account_obj._get_children_and_consol(
@@ -118,7 +129,7 @@ class AccountingExpressionProcessor(object):
if account_codes.strip():
account_codes = [a.strip() for a in account_codes.split(',')]
else:
- account_codes = None
+ account_codes = [None]
domain = domain or '[]'
domain = tuple(safe_eval(domain))
return field, mode, account_codes, domain
@@ -132,15 +143,12 @@ class AccountingExpressionProcessor(object):
for mo in self.ACC_RE.finditer(expr):
_, mode, account_codes, domain = self._parse_match_object(mo)
key = (domain, mode)
- if account_codes:
- self._map_account_ids[key].update(account_codes)
- else:
- self._set_all_accounts.add(key)
+ self._map_account_ids[key].update(account_codes)
- def done_parsing(self, account_domain):
+ def done_parsing(self, root_account):
# load account codes and replace account codes by account ids in _map
for key, account_codes in self._map_account_ids.items():
- self._load_account_codes(account_codes, account_domain)
+ self._load_account_codes(account_codes, root_account)
account_ids = set()
for account_code in account_codes:
account_ids.update(self._account_ids_by_code[account_code])
@@ -255,7 +263,7 @@ class AccountingExpressionProcessor(object):
if opening_period.date_start == period_from.date_start and \
mode == MODE_INITIAL:
# if the opening period has the same start date as
- # period_from, the we'll find the initial balance
+ # period_from, then we'll find the initial balance
# in the initial period and that's it
period_ids.append(opening_period[0].id)
continue
@@ -296,23 +304,6 @@ class AccountingExpressionProcessor(object):
for acc in accs:
self._data[key][acc['account_id'][0]] = \
(acc['debit'] or 0.0, acc['credit'] or 0.0)
- # fetch sum of debit/credit for expressions with no account
- for key in self._set_all_accounts:
- domain, mode = key
- if mode == MODE_VARIATION:
- domain = list(domain) + period_domain
- elif mode == MODE_INITIAL:
- domain = list(domain) + period_domain_i
- elif mode == MODE_END:
- domain = list(domain) + period_domain_e
- else:
- raise RuntimeError("unexpected mode %s" % (mode,))
- accs = aml_model.read_group(domain,
- ['debit', 'credit'],
- [])
- assert len(accs) == 1
- self._data[key][None] = \
- (accs[0]['debit'] or 0.0, accs[0]['credit'] or 0.0)
def replace_expr(self, expr):
"""Replace accounting variables in an expression by their amount.
@@ -326,11 +317,8 @@ class AccountingExpressionProcessor(object):
key = (domain, mode)
account_ids_data = self._data[key]
v = 0.0
- for account_code in account_codes or [None]:
- if account_code:
- account_ids = self._account_ids_by_code[account_code]
- else:
- account_ids = [None]
+ for account_code in account_codes:
+ account_ids = self._account_ids_by_code[account_code]
for account_id in account_ids:
debit, credit = \
account_ids_data.get(account_id, (0.0, 0.0))
diff --git a/mis_builder/models/mis_builder.py b/mis_builder/models/mis_builder.py
index 73932f15..767d40ca 100644
--- a/mis_builder/models/mis_builder.py
+++ b/mis_builder/models/mis_builder.py
@@ -483,13 +483,12 @@ class mis_report_instance_period(orm.Model):
'Period name should be unique by report'),
]
- def drilldown(self, cr, uid, id, expr, context=None):
- this = self.browse(cr, uid, id, context=context)[0]
+ def drilldown(self, cr, uid, _id, expr, context=None):
+ this = self.browse(cr, uid, _id, context=context)[0]
env = Environment(cr, uid, {})
aep = AccountingExpressionProcessor(env)
aep.parse_expr(expr)
- aep.done_parsing([('company_id', '=',
- this.report_instance_id.company_id.id)])
+ aep.done_parsing(this.report_instance_id.root_account)
domain = aep.get_aml_domain_for_expr(expr)
if domain:
# TODO: reuse compute_period_domain
@@ -680,6 +679,19 @@ class mis_report_instance(orm.Model):
context=context)
return res
+ def _get_root_account(self, cr, uid, ids, field_name, arg, context=None):
+ res = {}
+ account_obj = self.pool['account.account']
+ for r in self.browse(cr, uid, ids, context=context):
+ account_ids = account_obj.search(
+ cr, uid,
+ [('parent_id', '=', False),
+ ('company_id', '=', r.company_id.id)],
+ context=context)
+ if len(account_ids) == 1:
+ res[r.id] = account_ids[0]
+ return res
+
_name = 'mis.report.instance'
_columns = {
@@ -704,6 +716,9 @@ class mis_report_instance(orm.Model):
('all', 'All Entries'),
], 'Target Moves', required=True),
'company_id': fields.many2one('res.company', 'Company', required=True),
+ 'root_account': fields.function(_get_root_account,
+ type='many2one', obj='account.account',
+ string="Account chart"),
}
_defaults = {
@@ -754,13 +769,11 @@ class mis_report_instance(orm.Model):
tools.DEFAULT_SERVER_DATE_FORMAT),
tformat)
- def compute(self, cr, uid, _ids, context=None):
- assert isinstance(_ids, (int, long))
+ def compute(self, cr, uid, _id, context=None):
+ assert isinstance(_id, (int, long))
if context is None:
context = {}
- r = self.browse(cr, uid, _ids, context=context)
- context['state'] = r.target_move
-
+ r = self.browse(cr, uid, _id, context=context)
content = OrderedDict()
# empty line name for header
header = OrderedDict()
@@ -773,7 +786,7 @@ class mis_report_instance(orm.Model):
content[kpi.name] = {'kpi_name': kpi.description,
'cols': [],
'default_style': ''}
- aep.done_parsing([('company_id', '=', r.company_id.id)])
+ aep.done_parsing(r.root_account)
report_instance_period_obj = self.pool.get(
'mis.report.instance.period')
kpi_obj = self.pool.get('mis.report.kpi')
diff --git a/mis_builder/views/mis_builder.xml b/mis_builder/views/mis_builder.xml
index e4a34ae1..f7e09a83 100644
--- a/mis_builder/views/mis_builder.xml
+++ b/mis_builder/views/mis_builder.xml
@@ -139,6 +139,7 @@
+