Commit 129d7dea authored by Vincent Pelletier's avatar Vincent Pelletier

AccountModule_getAccountListForTrialBalance: Improve performance.

- Correctly ignore parent_portal_type condition when all possible
  portal types are listed.
  This typically saves one stock-catalog join.
- Expand node_category_uid into lists of node_uids.
  This saves one very costly stock-catalog join, as nodes member of given
  category should typically be the minority, inciting MySQL query optimiser
  to use the index materialising this join, preventing use of actual stock
  indexes.
  As there should be few nodes involved in accounting reports, listing
  them all and passing them to queries should not matter much.

Also, add support for src__ parameter.
Also, assorted coding style improvements, changes and code factorisation.
parent d564f379
...@@ -2,35 +2,68 @@ from Products.ZSQLCatalog.SQLCatalog import Query ...@@ -2,35 +2,68 @@ from Products.ZSQLCatalog.SQLCatalog import Query
from Products.PythonScripts.standard import Object from Products.PythonScripts.standard import Object
from ZTUtils import LazyFilter from ZTUtils import LazyFilter
request = container.REQUEST
portal = context.getPortalObject() portal = context.getPortalObject()
getInventoryList = portal.portal_simulation.getInventoryList request = portal.REQUEST
traverse = context.getPortalObject().restrictedTraverse getInventoryList_ = portal.portal_simulation.getInventoryList
getObject = context.getPortalObject().portal_catalog.getObject traverse = portal.restrictedTraverse
portal_catalog = portal.portal_catalog
getObject = portal_catalog.getObject
Base_translateString = portal.Base_translateString Base_translateString = portal.Base_translateString
selected_gap = gap_root selected_gap = gap_root
traverseCategory = portal.portal_categories.restrictedTraverse
def getAccountUidListByCategory(category, strict_membership):
"""
Transform node_category* into node_uid list.
"""
if not category:
return []
kw = {
('strict_' if strict_membership else '') + 'account_type_uid': [
traverseCategory(x).getUid() for x in category
],
}
if node_uid:
kw['uid'] = node_uid
return [x.uid for x in portal_catalog(portal_type='Account', **kw)]
inventory_movement_type_list = portal.getPortalInventoryMovementTypeList() inventory_movement_type_list = portal.getPortalInventoryMovementTypeList()
# Balance Movement Type list is all movements that are both inventory movement # Balance Movement Type list is all movements that are both inventory movement
# and accounting movement # and accounting movement
balance_movement_type_list = [ t for t in balance_movement_type_list = [
portal.getPortalAccountingMovementTypeList() t for t in portal.getPortalAccountingMovementTypeList()
if t in inventory_movement_type_list ] if t in inventory_movement_type_list
]
accounting_movement_type_list = [ t for t in accounting_movement_type_list = [
portal.getPortalAccountingMovementTypeList() t for t in portal.getPortalAccountingMovementTypeList()
if t not in balance_movement_type_list ] if t not in balance_movement_type_list
]
inventory_params = dict(section_uid=section_uid,
simulation_state=simulation_state, src_list = []
precision=precision, def getInventoryList(node_uid=None, **kw):
group_by_resource=0) if not node_uid and node_uid is not None:
return []
for key, value in inventory_params.iteritems():
assert key not in kw, key
kw[key] = value
result = getInventoryList_(
section_uid=section_uid,
simulation_state=simulation_state,
precision=precision,
group_by_resource=0,
group_by_node=1,
node_uid=node_uid,
src__=src__,
**kw
)
if src__:
src_list.append(result)
return []
return result
inventory_params = {}
if group_analytic: if group_analytic:
inventory_params['group_by'] = group_analytic inventory_params['group_by'] = group_analytic
group_analytic = tuple(group_analytic) group_analytic = tuple(group_analytic)
if portal_type and set(portal_type) != set(portal.getPortalAccountingTransactionTypeList()):
if portal_type and portal_type != portal.getPortalAccountingTransactionTypeList():
inventory_params['parent_portal_type'] = portal_type inventory_params['parent_portal_type'] = portal_type
if function: if function:
if function == 'None': if function == 'None':
...@@ -58,33 +91,42 @@ if project: ...@@ -58,33 +91,42 @@ if project:
if mirror_section_category: if mirror_section_category:
inventory_params['mirror_section_category'] = mirror_section_category inventory_params['mirror_section_category'] = mirror_section_category
if node_uid:
inventory_params['node_uid'] = node_uid
MARKER = Object()
# a dictionary (node_relative_url, mirror_section_uid, payment_uid + analytic) # a dictionary (node_relative_url, mirror_section_uid, payment_uid + analytic)
# -> dict(debit=, credit=) # -> {'debit'=, 'credit'=}
line_per_account = {} line_per_account = {}
# a dictionnary node_relative_url -> boolean "do we have transactions for this account_used = set()
# account ?" def markNodeUsed(node):
account_used = {} account_used.add(node['node_relative_url'])
def getTotalPrice(node):
return node['total_price'] or 0
account_type = portal.portal_categories.account_type account_type = portal.portal_categories.account_type
balance_sheet_account_type_list = [c[0] for c in balance_sheet_account_type_list = [c[0] for c in
account_type.asset.getCategoryChildItemList(base=1, is_self_excluded=False, display_none_category=False ) + \ account_type.asset.getCategoryChildItemList(base=1, is_self_excluded=False, display_none_category=False) +
account_type.equity.getCategoryChildItemList(base=1, is_self_excluded=False, display_none_category=False) + \ account_type.equity.getCategoryChildItemList(base=1, is_self_excluded=False, display_none_category=False) +
account_type.liability.getCategoryChildItemList(base=1, is_self_excluded=False, display_none_category=False) ] account_type.liability.getCategoryChildItemList(base=1, is_self_excluded=False, display_none_category=False)
]
profit_and_loss_account_type = [
'account_type/expense', profit_and_loss_account_uid_list = getAccountUidListByCategory(
'account_type/income',] [
'account_type/expense',
account_type_to_group_by_payment = [ 'account_type/asset/cash/bank' ] 'account_type/income',
],
strict_membership=0,
)
account_type_to_group_by_payment = [
'account_type/asset/cash/bank'
]
node_uid_of_strict_account_type_to_group_by_payment = getAccountUidListByCategory(
account_type_to_group_by_payment,
strict_membership=1,
)
account_type_payable_receivable = [ account_type_payable_receivable = [
'account_type/asset/receivable', 'account_type/asset/receivable',
'account_type/liability/payable', ] 'account_type/liability/payable',
]
# For initial balance of third party accounts, we want the same bottom line figure for initial # For initial balance of third party accounts, we want the same bottom line figure for initial
...@@ -118,18 +160,23 @@ if expand_accounts: ...@@ -118,18 +160,23 @@ if expand_accounts:
account_type_to_group_by_mirror_section_previous_period = account_type_payable_receivable account_type_to_group_by_mirror_section_previous_period = account_type_payable_receivable
else: else:
account_type_to_group_by_mirror_section = [] account_type_to_group_by_mirror_section = []
account_type_to_group_by_mirror_section_previous_period = []
if show_detailed_balance_columns: if show_detailed_balance_columns:
account_type_to_group_by_mirror_section_previous_period = account_type_payable_receivable account_type_to_group_by_mirror_section_previous_period = account_type_payable_receivable
else:
account_type_to_group_by_mirror_section_previous_period = []
account_type_to_group_by_node = [at for at in balance_sheet_account_type_list node_uid_of_strict_account_type_to_group_by_mirror_section = getAccountUidListByCategory(
if at not in account_type_to_group_by_payment category=account_type_to_group_by_mirror_section,
and at not in account_type_to_group_by_mirror_section] strict_membership=1,
)
account_type_to_group_by_node_previous_period = [at for at in account_type_to_group_by_node
if at not in account_type_to_group_by_mirror_section_previous_period] account_type_to_group_by_node = [
x for x in balance_sheet_account_type_list
if x not in account_type_to_group_by_payment and x not in account_type_to_group_by_mirror_section
]
node_uid_of_strict_account_type_to_group_by_node = getAccountUidListByCategory(
category=account_type_to_group_by_node,
strict_membership=1,
)
total_debit = 0 total_debit = 0
total_credit = 0 total_credit = 0
...@@ -138,10 +185,9 @@ total_initial_credit_balance = 0 ...@@ -138,10 +185,9 @@ total_initial_credit_balance = 0
total_final_balance_if_debit = 0 total_final_balance_if_debit = 0
total_final_balance_if_credit = 0 total_final_balance_if_credit = 0
def getKey(brain, mirror_section=MARKER, payment=MARKER, all_empty=False): MARKER = Object()
key = (brain['node_relative_url'], def getAccountProps(brain, mirror_section=MARKER, payment=MARKER, all_empty=False):
mirror_section, key = (brain['node_relative_url'], mirror_section, payment)
payment)
for analytic in group_analytic: for analytic in group_analytic:
if all_empty: if all_empty:
key += (MARKER, ) key += (MARKER, )
...@@ -149,194 +195,111 @@ def getKey(brain, mirror_section=MARKER, payment=MARKER, all_empty=False): ...@@ -149,194 +195,111 @@ def getKey(brain, mirror_section=MARKER, payment=MARKER, all_empty=False):
key += (getattr(brain, analytic), ) key += (getattr(brain, analytic), )
else: else:
key += (brain.getObject().getProperty(analytic.replace('strict_', '', 1)), ) key += (brain.getObject().getProperty(analytic.replace('strict_', '', 1)), )
return key
analytic_title_dict = {None: '', }
def getAnalyticTitleFromUid(uid):
if uid is MARKER:
return ''
try: try:
return analytic_title_dict[uid] value = line_per_account[key]
except KeyError: except KeyError:
node = getObject(uid) line_per_account[key] = value = {'debit': 0, 'credit': 0}
title = node.getTranslatedTitle() return value
reference = node.getReference()
if reference:
title = '%s - %s' % (reference, title)
return analytic_title_dict.setdefault(uid, title)
section_price_currency_dict = {None: ''} def addAccountProps(entry_list, *args, **kw):
def getSectionPriceCurrencyFromSectionUid(uid): account_props = getAccountProps(*args, **kw)
if uid is MARKER: for key, value in entry_list:
return '' account_props[key] = account_props.get(key, 0) + value
try:
return section_price_currency_dict[uid]
except KeyError:
section = getObject(uid)
price_currency = ''
if section is not None:
price_currency = section.getProperty('price_currency_reference')
return section_price_currency_dict.setdefault(uid, price_currency)
# standards accounts {{{ # standards accounts {{{
for node in getInventoryList( local_inventory_params = {
node_category_strict_membership=account_type_to_group_by_node, 'node_uid': node_uid_of_strict_account_type_to_group_by_node,
group_by_node=1, 'from_date': from_date,
omit_asset_decrease=1, 'at_date': at_date,
from_date=from_date, 'portal_type': accounting_movement_type_list,
at_date=at_date, }
portal_type=accounting_movement_type_list, for node in getInventoryList(omit_asset_decrease=1, **local_inventory_params):
**inventory_params): markNodeUsed(node)
account_used[node['node_relative_url']] = 1 total_price = getTotalPrice(node)
account_props = line_per_account.setdefault(getKey(node), dict(debit=0, credit=0)) getAccountProps(node)['debit'] = total_price
total_price = node['total_price'] or 0
account_props['debit'] = total_price
total_debit += round(total_price, precision) total_debit += round(total_price, precision)
for node in getInventoryList(omit_asset_increase=1, **local_inventory_params):
for node in getInventoryList( markNodeUsed(node)
node_category_strict_membership=account_type_to_group_by_node, total_price = getTotalPrice(node)
group_by_node=1, getAccountProps(node)['credit'] = -total_price
omit_asset_increase=1,
from_date=from_date,
at_date=at_date,
portal_type=accounting_movement_type_list,
**inventory_params):
account_used[node['node_relative_url']] = 1
account_props = line_per_account.setdefault(getKey(node), dict(debit=0, credit=0))
total_price = node['total_price'] or 0
account_props['credit'] = -total_price
total_credit -= round(total_price, precision) total_credit -= round(total_price, precision)
# }}} # }}}
### profit & loss accounts {{{ ### profit & loss accounts {{{
for node in getInventoryList( local_inventory_params = {
node_category=profit_and_loss_account_type, 'node_uid': profit_and_loss_account_uid_list,
from_date=max(period_start_date, from_date), 'from_date': max(period_start_date, from_date),
group_by_node=1, 'at_date': at_date,
omit_asset_decrease=1, 'portal_type': accounting_movement_type_list,
at_date=at_date, }
portal_type=accounting_movement_type_list, for node in getInventoryList(omit_asset_decrease=1, **local_inventory_params):
**inventory_params): markNodeUsed(node)
account_used[node['node_relative_url']] = 1 total_price = getTotalPrice(node)
account_props = line_per_account.setdefault(getKey(node), dict(debit=0, credit=0)) getAccountProps(node)['debit'] = total_price
total_price = node['total_price'] or 0
account_props['debit'] = total_price
total_debit += round(total_price, precision) total_debit += round(total_price, precision)
for node in getInventoryList(omit_asset_increase=1, **local_inventory_params):
for node in getInventoryList( markNodeUsed(node)
node_category=profit_and_loss_account_type, total_price = getTotalPrice(node)
from_date=max(period_start_date, from_date), getAccountProps(node)['credit'] = -total_price
group_by_node=1,
omit_asset_increase=1,
at_date=at_date,
portal_type=accounting_movement_type_list,
**inventory_params):
account_used[node['node_relative_url']] = 1
account_props = line_per_account.setdefault(getKey(node), dict(debit=0, credit=0))
total_price = node['total_price'] or 0
account_props['credit'] = -total_price
total_credit -= round(total_price, precision) total_credit -= round(total_price, precision)
# }}} # }}}
# payable / receivable accounts {{{ # payable / receivable accounts {{{
if account_type_to_group_by_mirror_section: if node_uid_of_strict_account_type_to_group_by_mirror_section:
for node in getInventoryList( if src__:
node_category_strict_membership= src_list.append('-- payable / receivable accounts')
account_type_to_group_by_mirror_section, local_inventory_params = {
group_by_mirror_section=1, 'node_uid': node_uid_of_strict_account_type_to_group_by_mirror_section,
group_by_node=1, 'group_by_mirror_section': 1,
omit_asset_decrease=1, 'from_date': from_date,
from_date=from_date, 'at_date': at_date,
at_date=at_date, 'portal_type': accounting_movement_type_list,
portal_type=accounting_movement_type_list, }
**inventory_params): for node in getInventoryList(omit_asset_decrease=1, **local_inventory_params):
account_used[node['node_relative_url']] = 1 markNodeUsed(node)
account_props = line_per_account.setdefault( total_price = getTotalPrice(node)
getKey(node, mirror_section=node['mirror_section_uid']), getAccountProps(node, mirror_section=node['mirror_section_uid'])['debit'] = total_price
dict(debit=0, credit=0))
total_price = node['total_price'] or 0
account_props['debit'] = total_price
total_debit += round(total_price, precision) total_debit += round(total_price, precision)
for node in getInventoryList(omit_asset_increase=1, **local_inventory_params):
for node in getInventoryList( markNodeUsed(node)
node_category_strict_membership= total_price = getTotalPrice(node)
account_type_to_group_by_mirror_section, getAccountProps(node, mirror_section=node['mirror_section_uid'])['credit'] = -total_price
group_by_mirror_section=1,
group_by_node=1,
omit_asset_increase=1,
from_date=from_date,
at_date=at_date,
portal_type=accounting_movement_type_list,
**inventory_params):
account_used[node['node_relative_url']] = 1
account_props = line_per_account.setdefault(
getKey(node, mirror_section=node['mirror_section_uid']),
dict(debit=0, credit=0))
total_price = node['total_price'] or 0
account_props['credit'] = - total_price
total_credit -= round(total_price, precision) total_credit -= round(total_price, precision)
# }}} # }}}
# bank accounts {{{ # bank accounts {{{
if account_type_to_group_by_payment: if node_uid_of_strict_account_type_to_group_by_payment:
for node in getInventoryList( if src__:
node_category_strict_membership= src_list.append('-- bank accounts')
account_type_to_group_by_payment, local_inventory_params = {
group_by_payment=1, 'node_uid': node_uid_of_strict_account_type_to_group_by_payment,
group_by_node=1, 'group_by_payment': 1,
omit_asset_decrease=1, 'from_date': from_date,
from_date=from_date, 'at_date': at_date,
at_date=at_date, 'portal_type': accounting_movement_type_list,
portal_type=accounting_movement_type_list, }
**inventory_params): for node in getInventoryList(omit_asset_decrease=1, **local_inventory_params):
account_used[node['node_relative_url']] = 1 markNodeUsed(node)
account_props = line_per_account.setdefault( total_price = getTotalPrice(node)
getKey(node, payment=node['payment_uid']), getAccountProps(node, payment=node['payment_uid'])['debit'] = total_price
dict(debit=0, credit=0))
total_price = node['total_price'] or 0
account_props['debit'] = total_price
total_debit += round(total_price, precision) total_debit += round(total_price, precision)
for node in getInventoryList(omit_asset_increase=1, **local_inventory_params):
for node in getInventoryList( markNodeUsed(node)
node_category_strict_membership= total_price = getTotalPrice(node)
account_type_to_group_by_payment, getAccountProps(node, payment=node['payment_uid'])['credit'] = - total_price
group_by_payment=1,
group_by_node=1,
omit_asset_increase=1,
from_date=from_date,
at_date=at_date,
portal_type=accounting_movement_type_list,
**inventory_params):
account_used[node['node_relative_url']] = 1
account_props = line_per_account.setdefault(
getKey(node, payment=node['payment_uid']),
dict(debit=0, credit=0))
total_price = node['total_price'] or 0
account_props['credit'] = - total_price
total_credit -= round(total_price, precision) total_credit -= round(total_price, precision)
# }}} # }}}
node_title_and_id_cache = {}
def getNodeTitleAndId(node_relative_url):
try:
return node_title_and_id_cache[node_relative_url]
except KeyError:
node = traverse(node_relative_url)
return node_title_and_id_cache.setdefault(node_relative_url,
( node.getUid(),
node.getTranslatedTitle(),
node.Account_getGapId(gap_root=selected_gap),
node.getProperty('string_index'),
node))
# include all accounts, even those not selected before (no movements in the # include all accounts, even those not selected before (no movements in the
# period) # period)
for node in LazyFilter(context.account_module.contentValues(), skip=''): for node in LazyFilter(portal.account_module.contentValues(), skip=''): # XXX: context should already be account_module
if node.getRelativeUrl() not in account_used: if node.getRelativeUrl() not in account_used:
line_per_account.setdefault( getAccountProps(
getKey(dict(node_relative_url=node.getRelativeUrl()), all_empty=True), {
dict(debit=0, credit=0)) 'node_relative_url': node.getRelativeUrl(),
},
all_empty=True,
)
initial_balance_date = (from_date - 1).latestTime() initial_balance_date = (from_date - 1).latestTime()
...@@ -344,305 +307,306 @@ initial_balance_date = (from_date - 1).latestTime() ...@@ -344,305 +307,306 @@ initial_balance_date = (from_date - 1).latestTime()
# standards accounts {{{ # standards accounts {{{
# balance at period start date # balance at period start date
local_inventory_params = {
'node_uid': getAccountUidListByCategory(
[
x for x in account_type_to_group_by_node
if x not in account_type_to_group_by_mirror_section_previous_period
],
strict_membership=1,
),
}
for node in getInventoryList( for node in getInventoryList(
node_category_strict_membership= to_date=period_start_date,
account_type_to_group_by_node_previous_period, portal_type=accounting_movement_type_list + balance_movement_type_list,
group_by_node=1, **local_inventory_params
to_date=period_start_date, ):
portal_type=accounting_movement_type_list + total_price = getTotalPrice(node)
balance_movement_type_list, addAccountProps(
**inventory_params): (
account_props = line_per_account.setdefault(getKey(node), dict(debit=0, credit=0)) ('initial_balance', total_price),
total_price = node['total_price'] or 0 ('initial_debit_balance', max(total_price, 0)),
account_props['initial_balance'] = account_props.get( ('initial_credit_balance', max(-total_price, 0)),
'initial_balance', 0) + total_price ),
account_props['initial_debit_balance'] = account_props.get( node,
'initial_debit_balance', 0) + max(total_price, 0) )
account_props['initial_credit_balance'] = account_props.get(
'initial_credit_balance', 0) + max(- total_price, 0)
found_balance = False found_balance = False
# Balance Transaction # Balance Transaction
for node in getInventoryList( for node in getInventoryList(
node_category_strict_membership= from_date=from_date,
account_type_to_group_by_node_previous_period, at_date=from_date + 1,
group_by_node=1, portal_type=balance_movement_type_list,
from_date=from_date, **local_inventory_params
at_date=from_date + 1, ):
portal_type=balance_movement_type_list, total_price = getTotalPrice(node)
**inventory_params): addAccountProps(
account_props = line_per_account.setdefault(getKey(node), dict(debit=0, credit=0)) (
total_price = node['total_price'] or 0 ('initial_balance', total_price),
account_props['initial_balance'] = account_props.get( ('initial_debit_balance', max(total_price, 0)),
'initial_balance', 0) + total_price ('initial_credit_balance', max(-total_price, 0)),
account_props['initial_debit_balance'] = account_props.get( ),
'initial_debit_balance', 0) + max(total_price, 0) node,
account_props['initial_credit_balance'] = account_props.get( )
'initial_credit_balance', 0) + max(- total_price, 0)
found_balance = True found_balance = True
period_movement_type_list = accounting_movement_type_list period_movement_type_list = accounting_movement_type_list
if not found_balance: if not found_balance:
period_movement_type_list = accounting_movement_type_list +\ period_movement_type_list += balance_movement_type_list
balance_movement_type_list local_inventory_params = {
'node_uid': node_uid_of_strict_account_type_to_group_by_node,
for node in getInventoryList( 'from_date': period_start_date,
node_category_strict_membership= 'to_date': from_date,
account_type_to_group_by_node, 'portal_type': period_movement_type_list,
group_by_node=1, }
omit_asset_decrease=1, for node in getInventoryList(omit_asset_decrease=1, **local_inventory_params):
from_date=period_start_date, addAccountProps(
to_date=from_date, (
portal_type=period_movement_type_list, ('initial_debit_balance', getTotalPrice(node)),
**inventory_params): ),
account_props = line_per_account.setdefault(getKey(node), dict(debit=0, credit=0)) node,
total_price = node['total_price'] or 0 )
account_props['initial_debit_balance'] = account_props.get( for node in getInventoryList(omit_asset_increase=1, **local_inventory_params):
'initial_debit_balance', 0) + total_price addAccountProps(
(
for node in getInventoryList( ('initial_credit_balance', -(getTotalPrice(node))),
node_category_strict_membership= ),
account_type_to_group_by_node, node,
group_by_node=1, )
omit_asset_increase=1,
from_date=period_start_date,
to_date=from_date,
portal_type=period_movement_type_list,
**inventory_params):
account_props = line_per_account.setdefault(getKey(node), dict(debit=0, credit=0))
total_price = node['total_price'] or 0
account_props['initial_credit_balance'] = account_props.get(
'initial_credit_balance', 0) - total_price
# }}} # }}}
### profit & loss accounts {{{ ### profit & loss accounts {{{
for node in getInventoryList( local_inventory_params = {
node_category=profit_and_loss_account_type, 'node_uid': profit_and_loss_account_uid_list,
omit_asset_decrease=1, 'from_date': min(period_start_date, initial_balance_date),
from_date=min(period_start_date, 'at_date': initial_balance_date,
initial_balance_date), 'portal_type': accounting_movement_type_list,
at_date=initial_balance_date, }
group_by_node=1, for node in getInventoryList(omit_asset_decrease=1, **local_inventory_params):
portal_type=accounting_movement_type_list, addAccountProps(
**inventory_params): (
account_props = line_per_account.setdefault(getKey(node), dict(debit=0, credit=0)) ('initial_debit_balance', getTotalPrice(node)),
total_price = node['total_price'] or 0 ),
account_props['initial_debit_balance'] = account_props.get( node,
'initial_debit_balance', 0) + total_price )
for node in getInventoryList(omit_asset_increase=1, **local_inventory_params):
for node in getInventoryList( addAccountProps(
node_category=profit_and_loss_account_type, (
omit_asset_increase=1, ('initial_credit_balance', -(getTotalPrice(node))),
from_date=min(period_start_date, ),
initial_balance_date), node,
at_date=initial_balance_date, )
group_by_node=1,
portal_type=accounting_movement_type_list,
**inventory_params):
account_props = line_per_account.setdefault(getKey(node), dict(debit=0, credit=0))
total_price = node['total_price'] or 0
account_props['initial_credit_balance'] = account_props.get(
'initial_credit_balance', 0) - total_price
# }}} # }}}
# payable / receivable accounts {{{ # payable / receivable accounts {{{
# initial balance
if account_type_to_group_by_mirror_section_previous_period:
for node in getInventoryList(
node_category_strict_membership=account_type_to_group_by_mirror_section_previous_period,
group_by_mirror_section=1,
group_by_node=1,
to_date=period_start_date,
portal_type=accounting_movement_type_list +
balance_movement_type_list,
**inventory_params):
mirror_section_key = MARKER
if expand_accounts:
mirror_section_key = node['mirror_section_uid']
account_props = line_per_account.setdefault(
getKey(node, mirror_section=mirror_section_key),
dict(debit=0, credit=0))
total_price = node['total_price'] or 0
account_props['initial_debit_balance'] = account_props.get(
'initial_debit_balance', 0) + max(total_price, 0)
account_props['initial_credit_balance'] = account_props.get(
'initial_credit_balance', 0) + max(-total_price, 0)
found_balance=False found_balance=False
# Balance Transactions
if account_type_to_group_by_mirror_section_previous_period: if account_type_to_group_by_mirror_section_previous_period:
if src__:
src_list.append('-- payable / receivable accounts')
# initial balance
local_inventory_params = {
'node_uid': getAccountUidListByCategory(
category=account_type_to_group_by_mirror_section_previous_period,
strict_membership=1,
),
'group_by_mirror_section': 1,
}
for node in getInventoryList( for node in getInventoryList(
node_category_strict_membership=account_type_to_group_by_mirror_section_previous_period, to_date=period_start_date,
group_by_mirror_section=1, portal_type=accounting_movement_type_list + balance_movement_type_list,
group_by_node=1, **local_inventory_params
from_date=from_date, ):
at_date=from_date + 1, total_price = getTotalPrice(node)
portal_type=balance_movement_type_list, addAccountProps(
**inventory_params): (
mirror_section_key = MARKER ('initial_debit_balance', max(total_price, 0)),
if expand_accounts: ('initial_credit_balance', max(-total_price, 0)),
mirror_section_key = node['mirror_section_uid'] ),
account_props = line_per_account.setdefault( node,
getKey(node, mirror_section=mirror_section_key), mirror_section=node['mirror_section_uid'] if expand_accounts else MARKER,
dict(debit=0, credit=0)) )
total_price = node['total_price'] or 0 # Balance Transactions
account_props['initial_debit_balance'] = account_props.get( for node in getInventoryList(
'initial_debit_balance', 0) + max(total_price, 0) from_date=from_date,
account_props['initial_credit_balance'] = account_props.get( at_date=from_date + 1,
'initial_credit_balance', 0) + max(- total_price, 0) portal_type=balance_movement_type_list,
**local_inventory_params
):
total_price = getTotalPrice(node)
addAccountProps(
(
('initial_debit_balance', max(total_price, 0)),
('initial_credit_balance', max(-total_price, 0)),
),
node,
mirror_section=node['mirror_section_uid'] if expand_accounts else MARKER,
)
found_balance=True found_balance=True
period_movement_type_list = accounting_movement_type_list period_movement_type_list = accounting_movement_type_list
if not found_balance: if not found_balance:
period_movement_type_list = accounting_movement_type_list +\ period_movement_type_list += balance_movement_type_list
balance_movement_type_list
if expand_accounts: if expand_accounts:
for node in getInventoryList( if src__:
node_category_strict_membership= src_list.append('-- expand_accounts')
account_type_to_group_by_mirror_section, local_inventory_params = {
group_by_mirror_section=1, 'node_uid': node_uid_of_strict_account_type_to_group_by_mirror_section,
group_by_node=1, 'group_by_mirror_section': 1,
omit_asset_decrease=1, 'from_date': period_start_date,
from_date=period_start_date, 'to_date': from_date,
to_date=from_date, 'portal_type': period_movement_type_list,
portal_type=period_movement_type_list, }
**inventory_params): for node in getInventoryList(omit_asset_decrease=1, **local_inventory_params):
account_props = line_per_account.setdefault( addAccountProps(
getKey(node, mirror_section=node['mirror_section_uid']), (
dict(debit=0, credit=0)) ('initial_debit_balance', getTotalPrice(node)),
total_price = node['total_price'] or 0 ),
account_props['initial_debit_balance'] = account_props.get( node,
'initial_debit_balance', 0) + total_price mirror_section=node['mirror_section_uid'],
)
for node in getInventoryList( for node in getInventoryList(omit_asset_increase=1, **local_inventory_params):
node_category_strict_membership= addAccountProps(
account_type_to_group_by_mirror_section, (
group_by_mirror_section=1, ('initial_credit_balance', -(getTotalPrice(node))),
group_by_node=1, ),
omit_asset_increase=1, node,
from_date=period_start_date, mirror_section=node['mirror_section_uid'],
to_date=from_date, )
portal_type=period_movement_type_list,
**inventory_params):
account_props = line_per_account.setdefault(
getKey(node, mirror_section=node['mirror_section_uid']),
dict(debit=0, credit=0))
total_price = node['total_price'] or 0
account_props['initial_credit_balance'] = account_props.get(
'initial_credit_balance', 0) - total_price
# }}} # }}}
# bank accounts {{{ # bank accounts {{{
if account_type_to_group_by_payment: if node_uid_of_strict_account_type_to_group_by_payment:
if src__:
src_list.append('-- bank accounts')
# Initial balance # Initial balance
local_inventory_params = {
'node_uid': node_uid_of_strict_account_type_to_group_by_payment,
'group_by_payment': 1,
}
for node in getInventoryList( for node in getInventoryList(
node_category_strict_membership= to_date=period_start_date,
account_type_to_group_by_payment, portal_type=accounting_movement_type_list + balance_movement_type_list,
group_by_payment=1, **local_inventory_params
group_by_node=1, ):
to_date=period_start_date, total_price = getTotalPrice(node)
portal_type=accounting_movement_type_list + addAccountProps(
balance_movement_type_list, (
**inventory_params): ('initial_debit_balance', max(total_price, 0)),
account_props = line_per_account.setdefault( ('initial_credit_balance', max(-total_price, 0)),
getKey(node, payment=node['payment_uid']), ),
dict(debit=0, credit=0)) node,
total_price = node['total_price'] or 0 payment=node['payment_uid'],
account_props['initial_debit_balance'] = account_props.get( )
'initial_debit_balance', 0) + max(total_price, 0)
account_props['initial_credit_balance'] = account_props.get(
'initial_credit_balance', 0) + max(- total_price, 0)
found_balance = False found_balance = False
# Balance Transaction # Balance Transaction
for node in getInventoryList( for node in getInventoryList(
node_category_strict_membership= from_date=from_date,
account_type_to_group_by_payment, at_date=from_date + 1,
group_by_payment=1, portal_type=balance_movement_type_list,
group_by_node=1, **local_inventory_params
from_date=from_date, ):
at_date=from_date + 1, account_props = getAccountProps(node, payment=node['payment_uid'])
portal_type=balance_movement_type_list, total_price = (getTotalPrice(node)) + account_props.get('initial_debit_balance', 0) - account_props.get('initial_credit_balance', 0)
**inventory_params):
account_used[node['node_relative_url']] = 1
account_props = line_per_account.setdefault(
getKey(node, payment=node['payment_uid']),
dict(debit=0, credit=0))
total_price = node['total_price'] or 0
total_price += account_props.get('initial_debit_balance', 0)
total_price -= account_props.get('initial_credit_balance', 0)
account_props['initial_debit_balance'] = max(total_price, 0) account_props['initial_debit_balance'] = max(total_price, 0)
account_props['initial_credit_balance'] = max(- total_price, 0) account_props['initial_credit_balance'] = max(- total_price, 0)
found_balance = True found_balance = True
period_movement_type_list = accounting_movement_type_list period_movement_type_list = accounting_movement_type_list
if not found_balance: if not found_balance:
period_movement_type_list = accounting_movement_type_list +\ period_movement_type_list += balance_movement_type_list
balance_movement_type_list local_inventory_params = {
for node in getInventoryList( 'node_uid': node_uid_of_strict_account_type_to_group_by_payment,
node_category_strict_membership= 'group_by_payment': 1,
account_type_to_group_by_payment, 'from_date': period_start_date,
group_by_payment=1, 'to_date': from_date,
group_by_node=1, 'portal_type': period_movement_type_list,
omit_asset_decrease=1, }
from_date=period_start_date, for node in getInventoryList(omit_asset_decrease=1, **local_inventory_params):
to_date=from_date, addAccountProps(
portal_type=period_movement_type_list, (
**inventory_params): ('initial_debit_balance', getTotalPrice(node)),
account_used[node['node_relative_url']] = 1 ),
account_props = line_per_account.setdefault( node,
getKey(node, payment=node['payment_uid']), payment=node['payment_uid'],
dict(debit=0, credit=0)) )
total_price = node['total_price'] or 0 for node in getInventoryList(omit_asset_increase=1, **local_inventory_params):
account_props['initial_debit_balance'] = account_props.get( addAccountProps(
'initial_debit_balance', 0) + total_price (
('initial_credit_balance', -(getTotalPrice(node))),
),
node,
payment=node['payment_uid'],
)
# }}}
for node in getInventoryList( if src__:
node_category_strict_membership= return src_list
account_type_to_group_by_payment,
group_by_payment=1,
group_by_node=1,
omit_asset_increase=1,
from_date=period_start_date,
to_date=from_date,
portal_type=period_movement_type_list,
**inventory_params):
account_used[node['node_relative_url']] = 1
account_props = line_per_account.setdefault(
getKey(node, payment=node['payment_uid']),
dict(debit=0, credit=0))
total_price = node['total_price'] or 0
account_props['initial_credit_balance'] = account_props.get(
'initial_credit_balance', 0) - total_price
# }}}
node_title_and_id_cache = {}
def getNodeTitleAndId(node_relative_url):
try:
return node_title_and_id_cache[node_relative_url]
except KeyError:
node = traverse(node_relative_url)
return node_title_and_id_cache.setdefault(
node_relative_url,
(
node.getUid(),
node.getTranslatedTitle(),
node.Account_getGapId(gap_root=selected_gap),
node.getProperty('string_index'),
node,
)
)
section_price_currency_dict = {None: ''}
def getSectionPriceCurrencyFromSectionUid(uid):
if uid is MARKER:
return ''
try:
return section_price_currency_dict[uid]
except KeyError:
section = getObject(uid)
if section is None:
price_currency = ''
else:
price_currency = section.getProperty('price_currency_reference')
section_price_currency_dict[uid] = price_currency
return price_currency
analytic_title_dict = {None: ''}
def getAnalyticTitleFromUid(uid):
if uid is MARKER:
return ''
try:
return analytic_title_dict[uid]
except KeyError:
node = getObject(uid)
title = node.getTranslatedTitle()
reference = node.getReference()
if reference:
title = '%s - %s' % (reference, title)
analytic_title_dict[uid] = title
return title
TRANSLATED_NONE = Base_translateString('None')
line_list = [] line_list = []
for key, data in line_per_account.items(): for key, data in line_per_account.iteritems():
node_relative_url = key[0] node_relative_url = key[0]
mirror_section_uid = key[1] mirror_section_uid = key[1]
payment_uid = key[2] payment_uid = key[2]
analytic_key_list = key[3:] analytic_key_list = key[3:]
mirror_section_title = None
if expand_accounts and mirror_section_uid is not MARKER: if expand_accounts and mirror_section_uid is not MARKER:
mirror_section_title = getObject(mirror_section_uid).getTitle() mirror_section_title = getObject(mirror_section_uid).getTitle()
else:
mirror_section_title = None
node_uid, node_title, node_id, node_string_index, node =\ node_uid, node_title, node_id, node_string_index, node = getNodeTitleAndId(node_relative_url)
getNodeTitleAndId(node_relative_url)
if selected_gap and not node.isMemberOf(selected_gap): if selected_gap and not node.isMemberOf(selected_gap):
continue continue
if payment_uid is not MARKER: if payment_uid is not MARKER:
if payment_uid is None: node_title += " (%s)" % (
node_title = '%s (%s)' % ( node_title, Base_translateString('None')) TRANSLATED_NONE if payment_uid is None else getObject(payment_uid).getTitle(),
else: )
payment = getObject(payment_uid)
node_title = "%s (%s)" % ( node_title, payment.getTitle() )
if not node_string_index: if not node_string_index:
node_string_index = '%-10s' % node_id node_string_index = '%-10s' % node_id
...@@ -652,29 +616,29 @@ for key, data in line_per_account.items(): ...@@ -652,29 +616,29 @@ for key, data in line_per_account.items():
total_initial_debit_balance += round(initial_debit_balance, precision) total_initial_debit_balance += round(initial_debit_balance, precision)
total_initial_credit_balance += round(initial_credit_balance, precision) total_initial_credit_balance += round(initial_credit_balance, precision)
final_debit_balance = round(initial_debit_balance + data['debit'], final_debit_balance = round(initial_debit_balance + data['debit'], precision)
precision) final_credit_balance = round(initial_credit_balance + data['credit'], precision)
final_credit_balance = round(initial_credit_balance + data['credit'],
precision)
closing_balance = final_debit_balance - final_credit_balance closing_balance = final_debit_balance - final_credit_balance
total_final_balance_if_debit += round(max(closing_balance, 0), precision) total_final_balance_if_debit += round(max(closing_balance, 0), precision)
total_final_balance_if_credit += round(max(-closing_balance, 0) or 0, precision) total_final_balance_if_credit += round(max(-closing_balance, 0) or 0, precision)
line = Object(uid='new_', line = Object(
node_id=node_id, uid='new_',
node_title=node_title, node_id=node_id,
mirror_section_title=mirror_section_title, node_title=node_title,
node_relative_url=node_relative_url, mirror_section_title=mirror_section_title,
initial_balance=initial_debit_balance - initial_credit_balance, node_relative_url=node_relative_url,
initial_debit_balance=initial_debit_balance, initial_balance=initial_debit_balance - initial_credit_balance,
initial_credit_balance=initial_credit_balance, initial_debit_balance=initial_debit_balance,
debit=data['debit'], initial_credit_balance=initial_credit_balance,
credit=data['credit'], debit=data['debit'],
final_balance=final_debit_balance - final_credit_balance, credit=data['credit'],
final_debit_balance=final_debit_balance, final_balance=final_debit_balance - final_credit_balance,
final_credit_balance=final_credit_balance, final_debit_balance=final_debit_balance,
final_balance_if_debit=max(closing_balance, 0), final_credit_balance=final_credit_balance,
final_balance_if_credit=max(-closing_balance, 0) or 0,) final_balance_if_debit=max(closing_balance, 0),
final_balance_if_credit=max(-closing_balance, 0) or 0,
)
sort_key = (node_string_index, node_title, mirror_section_title) sort_key = (node_string_index, node_title, mirror_section_title)
analytic_dict = {} analytic_dict = {}
...@@ -686,94 +650,89 @@ for key, data in line_per_account.items(): ...@@ -686,94 +650,89 @@ for key, data in line_per_account.items():
# We sort on section title first # We sort on section title first
sort_key = (title, ) + sort_key sort_key = (title, ) + sort_key
sort_key += (title, ) sort_key += (title, )
analytic_dict['sort_key'] = sort_key analytic_dict['sort_key'] = sort_key
line.update(analytic_dict) line.update(analytic_dict)
line_list.append(line) line_list.append(line)
if not show_empty_accounts: if not show_empty_accounts:
line_list = [ line for line in line_list line_list = [
if line['debit'] or line for line in line_list
line['credit'] or if line['debit'] or
line['initial_credit_balance'] or line['credit'] or
line['initial_debit_balance'] ] line['initial_credit_balance'] or
line['initial_debit_balance']
line_list.sort(key=lambda obj:obj['sort_key']) ]
line_list.sort(key=lambda obj: obj['sort_key'])
# cache values for stat # cache values for stat
request.set('TrialBalance.total_initial_debit_balance', request.set('TrialBalance.total_initial_debit_balance', total_initial_debit_balance)
total_initial_debit_balance) request.set('TrialBalance.total_initial_credit_balance', total_initial_credit_balance)
request.set('TrialBalance.total_initial_credit_balance',
total_initial_credit_balance)
request.set('TrialBalance.debit', total_debit) request.set('TrialBalance.debit', total_debit)
request.set('TrialBalance.credit', total_credit) request.set('TrialBalance.credit', total_credit)
request.set('TrialBalance.final_balance_if_debit', total_final_balance_if_debit) request.set('TrialBalance.final_balance_if_debit', total_final_balance_if_debit)
request.set('TrialBalance.final_balance_if_credit', total_final_balance_if_credit) request.set('TrialBalance.final_balance_if_credit', total_final_balance_if_credit)
if not per_account_class_summary: if per_account_class_summary:
return line_list current_gap = selected_gap or portal.portal_preferences.getPreferredAccountingTransactionGap() or ''
if current_gap.startswith('gap/'):
current_gap = selected_gap or \ current_gap = current_gap[4:]
portal.portal_preferences.getPreferredAccountingTransactionGap() or '' def getAccountClass(account_relative_url):
if current_gap.startswith('gap/'): account = traverse(account_relative_url)
current_gap = current_gap[4:] for gap in account.getGapList():
def getAccountClass(account_relative_url): if gap.startswith(current_gap):
account = traverse(account_relative_url) gap_part_list = gap.split('/')
for gap in account.getGapList(): # country / accounting principle / ${class}
if gap.startswith(current_gap): if len(gap_part_list) > 2:
gap_part_list = gap.split('/') return gap_part_list[2]
# country / accounting principle / ${class} return None # this account has no class on the current GAP
if len(gap_part_list) > 2:
return gap_part_list[2] account_per_class = {}
return None # this account has no class on the current GAP for brain in line_list:
account_per_class.setdefault(getAccountClass(brain.node_relative_url), []).append(brain)
new_line_list = []
account_per_class = {} line_list = []
for brain in line_list: add_line = line_list.append
account_per_class.setdefault( for account_class in sorted(account_per_class):
getAccountClass(brain.node_relative_url), []).append(brain) initial_debit_balance = 0
debit = 0
account_class_list = account_per_class.keys() final_debit_balance = 0
account_class_list.sort() initial_credit_balance = 0
credit = 0
add_line = new_line_list.append final_credit_balance = 0
for account_class in account_class_list: final_balance_if_debit = 0
initial_debit_balance = 0 final_balance_if_credit = 0
debit = 0
final_debit_balance = 0 for account in account_per_class[account_class]:
initial_credit_balance = 0 initial_debit_balance += account.initial_debit_balance
credit = 0 debit += account.debit
final_credit_balance = 0 final_debit_balance += account.final_debit_balance
final_balance_if_debit = 0 initial_credit_balance += account.initial_credit_balance
final_balance_if_credit = 0 credit += account.credit
final_credit_balance += account.final_credit_balance
for account in account_per_class[account_class]: final_balance_if_debit += account.final_balance_if_debit
initial_debit_balance += account.initial_debit_balance final_balance_if_credit += account.final_balance_if_credit
debit += account.debit add_line(account)
final_debit_balance += account.final_debit_balance
initial_credit_balance += account.initial_credit_balance # summary
credit += account.credit add_line(Object(
final_credit_balance += account.final_credit_balance node_title=Base_translateString(
final_balance_if_debit += account.final_balance_if_debit 'Total for class ${account_class}',
final_balance_if_credit += account.final_balance_if_credit mapping={'account_class': account_class or '???'},
add_line(account) ),
initial_balance=round(initial_debit_balance - initial_credit_balance, precision),
# summary initial_debit_balance=round(initial_debit_balance, precision),
add_line(Object(node_title=Base_translateString('Total for class ${account_class}', debit=round(debit, precision),
mapping=dict(account_class=account_class or '???')), final_debit_balance=round(final_debit_balance, precision),
initial_balance=round(initial_debit_balance - initial_credit_balance, precision), initial_credit_balance=round(initial_credit_balance, precision),
initial_debit_balance=round(initial_debit_balance, precision), credit=round(credit, precision),
debit=round(debit, precision), final_credit_balance=round(final_credit_balance, precision),
final_debit_balance=round(final_debit_balance, precision), final_balance_if_debit=round(final_balance_if_debit, precision),
initial_credit_balance=round(initial_credit_balance, precision), final_balance_if_credit=round(final_balance_if_credit, precision),
credit=round(credit, precision), final_balance=round(final_debit_balance - final_credit_balance, precision),
final_credit_balance=round(final_credit_balance, precision), ))
final_balance_if_debit=round(final_balance_if_debit, precision),
final_balance_if_credit=round(final_balance_if_credit, precision), add_line(Object(node_title=' '))
final_balance=round(final_debit_balance - final_credit_balance, precision),))
return line_list
add_line(Object(node_title=' '))
return new_line_list
# vim: foldmethod=marker # vim: foldmethod=marker
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>show_empty_accounts, expand_accounts, at_date, from_date, period_start_date, section_uid, simulation_state, precision, node_uid, gap_root=None, per_account_class_summary=0, portal_type=None, function=None, funding=None, project=None, group_analytic=[], mirror_section_category=None, show_detailed_balance_columns=False, **kw</string> </value> <value> <string>show_empty_accounts, expand_accounts, at_date, from_date, period_start_date, section_uid, simulation_state, precision, node_uid, gap_root=None, per_account_class_summary=0, portal_type=None, function=None, funding=None, project=None, group_analytic=[], mirror_section_category=None, show_detailed_balance_columns=False, src__=False, **kw</string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment