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 @@
<key> <string>_body</string> </key>
<value> <string>budget = context.getParentValue()\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 []\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>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>matrixbox=0, **kw</string> </value>
<value> <string>base_id, matrixbox=0, **kw</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
......
......@@ -10,6 +10,7 @@
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>cell_base_id</string>
<string>cell_getter_method</string>
<string>editable_attributes</string>
<string>global_attributes</string>
......@@ -74,6 +75,10 @@
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>cell_base_id</string> </key>
<value> <string>available</string> </value>
</item>
<item>
<key> <string>cell_getter_method</string> </key>
<value> <string>BudgetLine_getAvailableBudgetCell</string> </value>
......
......@@ -10,6 +10,7 @@
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>cell_base_id</string>
<string>cell_getter_method</string>
<string>editable_attributes</string>
<string>global_attributes</string>
......@@ -74,6 +75,10 @@
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>cell_base_id</string> </key>
<value> <string>consumed</string> </value>
</item>
<item>
<key> <string>cell_getter_method</string> </key>
<value> <string>BudgetLine_getConsumedBudgetCell</string> </value>
......
......@@ -10,6 +10,7 @@
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>cell_base_id</string>
<string>cell_getter_method</string>
<string>editable_attributes</string>
<string>global_attributes</string>
......@@ -74,6 +75,10 @@
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>cell_base_id</string> </key>
<value> <string>engaged</string> </value>
</item>
<item>
<key> <string>cell_getter_method</string> </key>
<value> <string>BudgetLine_getEngagedBudgetCell</string> </value>
......
......@@ -183,9 +183,10 @@ for budget in budget_list:\n
consumed_budget_dict = budget_line.getConsumedBudgetDict()\n
engaged_budget_dict = budget_line.getEngagedBudgetDict()\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.BudgetLine_asCellRange(matrixbox=1)\n
budget_line.BudgetLine_asCellRange(\'engaged\', matrixbox=1)\n
\n
dependant_dimension_dict = budget_line.BudgetLine_getSummaryDimensionKeyDict()\n
\n
......
......@@ -99,6 +99,7 @@
<string>my_budget_variation</string>
<string>my_variation_base_category</string>
<string>my_inventory_axis</string>
<string>my_full_consumption_detail</string>
</list>
</value>
</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 @@
<string>my_aggregate_title_list</string>
<string>my_include_virtual_none_node</string>
<string>my_include_virtual_other_node</string>
<string>my_full_consumption_detail</string>
</list>
</value>
</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
\ No newline at end of file
371
\ No newline at end of file
......@@ -33,7 +33,7 @@ from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.XMLMatrix import XMLMatrix
from Products.ERP5Type.Core.Predicate import Predicate
from Products.ERP5.mixin.variated import VariatedMixin
from Products.ERP5Type.Cache import transactional_cached
class BudgetLine(Predicate, XMLMatrix, VariatedMixin):
""" A Line of budget, variated in budget cells.
......@@ -103,6 +103,8 @@ class BudgetLine(Predicate, XMLMatrix, VariatedMixin):
return budget_dict
@transactional_cached(key_method=lambda self, **kw:
(self.getRelativeUrl(), tuple(kw.items())))
def _getBudgetDict(self, simulation_period='Current', **kw):
"""Use getCurrentInventoryList to compute all budget cell consumptions at
once, and returns them in a dict.
......
......@@ -74,6 +74,26 @@ class BudgetModel(Predicate):
cell_range.extend(variation_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):
"""Returns the query dict to pass to simulation query for a budget cell
"""
......
......@@ -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] 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):
""" Query dict to pass to simulation query
"""
......@@ -141,9 +173,19 @@ class CategoryBudgetVariation(BudgetVariation):
'mirror_section', 'mirror_node' ):
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
for category in context.getVariationCategoryList(
base_category_list=(base_category,)):
base_category_list=(base_category,)):
if axis.endswith('_uid'):
category = self.getPortalObject().portal_categories\
.getCategoryUid(category)
......
......@@ -103,6 +103,39 @@ class NodeBudgetVariation(BudgetVariation):
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]]
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):
""" Query dict to pass to simulation query
"""
......@@ -223,10 +256,20 @@ class NodeBudgetVariation(BudgetVariation):
# if we have a virtual "all others" node, we don't set a criterion here.
if self.getProperty('include_virtual_other_node'):
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
for node_url in context.getVariationCategoryList(
base_category_list=(base_category,)):
for node_url in category_list:
if node_url != '%s/budget_special_node/none' % base_category:
__traceback_info__ = (node_url, )
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