Commit b9b14bc7 authored by Jérome Perrin's avatar Jérome Perrin

budget: use different cell ranges for consumption than definition

This way when "full consumption detail" is used, consumptions that are on a possible variation that was not selected in definition are part of the consumption cell range and are still reported under this variation.
parent 49c4caa4
...@@ -52,14 +52,21 @@ ...@@ -52,14 +52,21 @@
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>budget = context.getParentValue()\n <value> <string>budget = context.getParentValue()\n
budget_model = budget.getSpecialiseValue(portal_type=\'Budget Model\')\n budget_model = budget.getSpecialiseValue(portal_type=\'Budget Model\')\n
if budget_model is not None:\n if budget_model is None:\n
return []\n
\n
if base_id == \'cell\':\n
return budget_model.getCellRangeForBudgetLine(context, matrixbox=matrixbox)\n return budget_model.getCellRangeForBudgetLine(context, matrixbox=matrixbox)\n
return []\n if base_id in (\'engaged\', \'available\'):\n
return budget_model.getConsumptionCellRangeForBudgetLine(context, matrixbox=matrixbox, engaged_budget=True)\n
if base_id == \'consumed\':\n
return budget_model.getConsumptionCellRangeForBudgetLine(context, matrixbox=matrixbox, engaged_budget=False)\n
assert False, "Incorrect base_id %r" % (base_id, )\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>matrixbox=0, **kw</string> </value> <value> <string>base_id, matrixbox=0, **kw</string> </value>
</item> </item>
<item> <item>
<key> <string>_proxy_roles</string> </key> <key> <string>_proxy_roles</string> </key>
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
<key> <string>delegated_list</string> </key> <key> <string>delegated_list</string> </key>
<value> <value>
<list> <list>
<string>cell_base_id</string>
<string>cell_getter_method</string> <string>cell_getter_method</string>
<string>editable_attributes</string> <string>editable_attributes</string>
<string>global_attributes</string> <string>global_attributes</string>
...@@ -74,6 +75,10 @@ ...@@ -74,6 +75,10 @@
<key> <string>values</string> </key> <key> <string>values</string> </key>
<value> <value>
<dictionary> <dictionary>
<item>
<key> <string>cell_base_id</string> </key>
<value> <string>available</string> </value>
</item>
<item> <item>
<key> <string>cell_getter_method</string> </key> <key> <string>cell_getter_method</string> </key>
<value> <string>BudgetLine_getAvailableBudgetCell</string> </value> <value> <string>BudgetLine_getAvailableBudgetCell</string> </value>
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
<key> <string>delegated_list</string> </key> <key> <string>delegated_list</string> </key>
<value> <value>
<list> <list>
<string>cell_base_id</string>
<string>cell_getter_method</string> <string>cell_getter_method</string>
<string>editable_attributes</string> <string>editable_attributes</string>
<string>global_attributes</string> <string>global_attributes</string>
...@@ -74,6 +75,10 @@ ...@@ -74,6 +75,10 @@
<key> <string>values</string> </key> <key> <string>values</string> </key>
<value> <value>
<dictionary> <dictionary>
<item>
<key> <string>cell_base_id</string> </key>
<value> <string>consumed</string> </value>
</item>
<item> <item>
<key> <string>cell_getter_method</string> </key> <key> <string>cell_getter_method</string> </key>
<value> <string>BudgetLine_getConsumedBudgetCell</string> </value> <value> <string>BudgetLine_getConsumedBudgetCell</string> </value>
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
<key> <string>delegated_list</string> </key> <key> <string>delegated_list</string> </key>
<value> <value>
<list> <list>
<string>cell_base_id</string>
<string>cell_getter_method</string> <string>cell_getter_method</string>
<string>editable_attributes</string> <string>editable_attributes</string>
<string>global_attributes</string> <string>global_attributes</string>
...@@ -74,6 +75,10 @@ ...@@ -74,6 +75,10 @@
<key> <string>values</string> </key> <key> <string>values</string> </key>
<value> <value>
<dictionary> <dictionary>
<item>
<key> <string>cell_base_id</string> </key>
<value> <string>engaged</string> </value>
</item>
<item> <item>
<key> <string>cell_getter_method</string> </key> <key> <string>cell_getter_method</string> </key>
<value> <string>BudgetLine_getEngagedBudgetCell</string> </value> <value> <string>BudgetLine_getEngagedBudgetCell</string> </value>
......
...@@ -183,9 +183,10 @@ for budget in budget_list:\n ...@@ -183,9 +183,10 @@ for budget in budget_list:\n
consumed_budget_dict = budget_line.getConsumedBudgetDict()\n consumed_budget_dict = budget_line.getConsumedBudgetDict()\n
engaged_budget_dict = budget_line.getEngagedBudgetDict()\n engaged_budget_dict = budget_line.getEngagedBudgetDict()\n
\n \n
budget_line_cell_range = budget_line.BudgetLine_asCellRange()\n # We use \'engaged\' cell_id because we are supposed to have more engagements than consumptions\n
budget_line_cell_range = budget_line.BudgetLine_asCellRange(\'engaged\')\n
budget_line_as_cell_range_matrixbox =\\\n budget_line_as_cell_range_matrixbox =\\\n
budget_line.BudgetLine_asCellRange(matrixbox=1)\n budget_line.BudgetLine_asCellRange(\'engaged\', matrixbox=1)\n
\n \n
dependant_dimension_dict = budget_line.BudgetLine_getSummaryDimensionKeyDict()\n dependant_dimension_dict = budget_line.BudgetLine_getSummaryDimensionKeyDict()\n
\n \n
......
...@@ -99,6 +99,7 @@ ...@@ -99,6 +99,7 @@
<string>my_budget_variation</string> <string>my_budget_variation</string>
<string>my_variation_base_category</string> <string>my_variation_base_category</string>
<string>my_inventory_axis</string> <string>my_inventory_axis</string>
<string>my_full_consumption_detail</string>
</list> </list>
</value> </value>
</item> </item>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CheckBoxField" module="Products.Formulator.StandardFields"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>my_full_consumption_detail</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Detail Consumptions</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -111,6 +111,7 @@ ...@@ -111,6 +111,7 @@
<string>my_aggregate_title_list</string> <string>my_aggregate_title_list</string>
<string>my_include_virtual_none_node</string> <string>my_include_virtual_none_node</string>
<string>my_include_virtual_other_node</string> <string>my_include_virtual_other_node</string>
<string>my_full_consumption_detail</string>
</list> </list>
</value> </value>
</item> </item>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="CheckBoxField" module="Products.Formulator.StandardFields"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>my_full_consumption_detail</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>extra</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Detail Consumptions</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
367 371
\ No newline at end of file \ No newline at end of file
...@@ -33,7 +33,7 @@ from Products.ERP5Type import Permissions, PropertySheet ...@@ -33,7 +33,7 @@ from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.XMLMatrix import XMLMatrix from Products.ERP5Type.XMLMatrix import XMLMatrix
from Products.ERP5Type.Core.Predicate import Predicate from Products.ERP5Type.Core.Predicate import Predicate
from Products.ERP5.mixin.variated import VariatedMixin from Products.ERP5.mixin.variated import VariatedMixin
from Products.ERP5Type.Cache import transactional_cached
class BudgetLine(Predicate, XMLMatrix, VariatedMixin): class BudgetLine(Predicate, XMLMatrix, VariatedMixin):
""" A Line of budget, variated in budget cells. """ A Line of budget, variated in budget cells.
...@@ -103,6 +103,8 @@ class BudgetLine(Predicate, XMLMatrix, VariatedMixin): ...@@ -103,6 +103,8 @@ class BudgetLine(Predicate, XMLMatrix, VariatedMixin):
return budget_dict return budget_dict
@transactional_cached(key_method=lambda self, **kw:
(self.getRelativeUrl(), tuple(kw.items())))
def _getBudgetDict(self, simulation_period='Current', **kw): def _getBudgetDict(self, simulation_period='Current', **kw):
"""Use getCurrentInventoryList to compute all budget cell consumptions at """Use getCurrentInventoryList to compute all budget cell consumptions at
once, and returns them in a dict. once, and returns them in a dict.
......
...@@ -74,6 +74,26 @@ class BudgetModel(Predicate): ...@@ -74,6 +74,26 @@ class BudgetModel(Predicate):
cell_range.extend(variation_cell_range) cell_range.extend(variation_cell_range)
return cell_range return cell_range
def getConsumptionCellRangeForBudgetLine(self, budget_line, matrixbox=0, engaged_budget=False):
"""Return the cell range to use for the budget consumption.
It can be different from the cell range for definition when using full
consumption detail on budget variations.
"""
cell_range = []
for budget_variation in sorted(self.contentValues(
portal_type=self.getPortalBudgetVariationTypeList(),),
key=lambda x:x.getIntIndex()):
if not budget_variation.isMemberOf('budget_variation/budget_cell'):
continue
variation_cell_range = budget_variation.getConsumptionCellRangeForBudgetLine(
budget_line, matrixbox=matrixbox, engaged_budget=engaged_budget)
if variation_cell_range \
and variation_cell_range != [[]] \
and variation_cell_range not in cell_range:
cell_range.extend(variation_cell_range)
return cell_range
def getInventoryQueryDict(self, budget_cell): def getInventoryQueryDict(self, budget_cell):
"""Returns the query dict to pass to simulation query for a budget cell """Returns the query dict to pass to simulation query for a budget cell
""" """
......
...@@ -69,6 +69,38 @@ class CategoryBudgetVariation(BudgetVariation): ...@@ -69,6 +69,38 @@ class CategoryBudgetVariation(BudgetVariation):
return [[(i[1], i[0]) for i in item_list if i[1] in variation_category_list]] return [[(i[1], i[0]) for i in item_list if i[1] in variation_category_list]]
return [[i[1] for i in item_list if i[1] in variation_category_list]] return [[i[1] for i in item_list if i[1] in variation_category_list]]
def getConsumptionCellRangeForBudgetLine(self, budget_line, matrixbox=0, engaged_budget=False):
"""The cell range added by this variation for consumption
"""
cell_range = self.getCellRangeForBudgetLine(budget_line, matrixbox)
if not self.getProperty('full_consumption_detail'):
return cell_range
base_category = self.getProperty('variation_base_category')
prefix = ''
if base_category:
prefix = '%s/' % base_category
item_list = self.getBudgetLineVariationRangeCategoryList(budget_line)
if matrixbox:
used_node_item_set = set([item[0] for item in cell_range[0]])
else:
used_node_item_set = set([item for item in cell_range[0]])
if engaged_budget:
consumption_dict = budget_line.getConsumedBudgetDict()
else:
consumption_dict = budget_line.getEngagedBudgetDict()
for consumed_budget_key in consumption_dict.keys():
for item in consumed_budget_key:
if item.startswith(prefix):
used_node_item_set.add(item)
if matrixbox:
return [[(i[1], i[0]) for i in item_list if i[0] in used_node_item_set]]
return [[i[1] for i in item_list if i[1] in used_node_item_set]]
def getInventoryQueryDict(self, budget_cell): def getInventoryQueryDict(self, budget_cell):
""" Query dict to pass to simulation query """ Query dict to pass to simulation query
""" """
...@@ -141,9 +173,19 @@ class CategoryBudgetVariation(BudgetVariation): ...@@ -141,9 +173,19 @@ class CategoryBudgetVariation(BudgetVariation):
'mirror_section', 'mirror_node' ): 'mirror_section', 'mirror_node' ):
axis = '%s_uid' % axis axis = '%s_uid' % axis
if self.getProperty('full_consumption_detail'):
for title, category in self.getBudgetLineVariationRangeCategoryList(context):
if not category: continue
if axis.endswith('_uid'):
# XXX move out getattrs
category = self.getPortalObject().portal_categories\
.getCategoryUid(category)
query_dict.setdefault(axis, []).append(category)
return query_dict
found = False found = False
for category in context.getVariationCategoryList( for category in context.getVariationCategoryList(
base_category_list=(base_category,)): base_category_list=(base_category,)):
if axis.endswith('_uid'): if axis.endswith('_uid'):
category = self.getPortalObject().portal_categories\ category = self.getPortalObject().portal_categories\
.getCategoryUid(category) .getCategoryUid(category)
......
...@@ -103,6 +103,39 @@ class NodeBudgetVariation(BudgetVariation): ...@@ -103,6 +103,39 @@ class NodeBudgetVariation(BudgetVariation):
return [[i for i in node_item_list if i[0] in variation_category_list]] return [[i for i in node_item_list if i[0] in variation_category_list]]
return [[i[0] for i in node_item_list if i[0] in variation_category_list]] return [[i[0] for i in node_item_list if i[0] in variation_category_list]]
def getConsumptionCellRangeForBudgetLine(self, budget_line, matrixbox=0, engaged_budget=False):
"""The cell range added by this variation for consumption
"""
cell_range = self.getCellRangeForBudgetLine(budget_line, matrixbox)
if not self.getProperty('full_consumption_detail'):
return cell_range
base_category = self.getProperty('variation_base_category')
prefix = ''
if base_category:
prefix = '%s/' % base_category
node_item_list = [('%s%s' % (prefix, node.getRelativeUrl()),
self._getNodeTitle(node))
for node in self._getNodeList(budget_line)]
if matrixbox:
used_node_item_set = set([item[0] for item in cell_range[0]])
else:
used_node_item_set = set([item for item in cell_range[0]])
if engaged_budget:
consumption_dict = budget_line.getConsumedBudgetDict()
else:
consumption_dict = budget_line.getEngagedBudgetDict()
for consumed_budget_key in budget_line.getConsumedBudgetDict().keys():
for item in consumed_budget_key:
if item.startswith(prefix):
used_node_item_set.add(item)
if matrixbox:
return [[i for i in node_item_list if i[0] in used_node_item_set]]
return [[i[0] for i in node_item_list if i[0] in used_node_item_set]]
def getInventoryQueryDict(self, budget_cell): def getInventoryQueryDict(self, budget_cell):
""" Query dict to pass to simulation query """ Query dict to pass to simulation query
""" """
...@@ -223,10 +256,20 @@ class NodeBudgetVariation(BudgetVariation): ...@@ -223,10 +256,20 @@ class NodeBudgetVariation(BudgetVariation):
# if we have a virtual "all others" node, we don't set a criterion here. # if we have a virtual "all others" node, we don't set a criterion here.
if self.getProperty('include_virtual_other_node'): if self.getProperty('include_virtual_other_node'):
return query_dict return query_dict
if self.getProperty('full_consumption_detail'):
if self.isMemberOf('budget_variation/budget'):
category_list = [item[1] for item in
self.getBudgetVariationRangeCategoryList(context)]
else:
category_list = [item[1] for item in
self.getBudgetLineVariationRangeCategoryList(context)]
else:
category_list = context.getVariationCategoryList(
base_category_list=(base_category,))
found = False found = False
for node_url in context.getVariationCategoryList( for node_url in category_list:
base_category_list=(base_category,)):
if node_url != '%s/budget_special_node/none' % base_category: if node_url != '%s/budget_special_node/none' % base_category:
__traceback_info__ = (node_url, ) __traceback_info__ = (node_url, )
if uid_based_axis: if uid_based_axis:
......
This diff is collapsed.
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