Commit 476ec3f7 authored by Jérome Perrin's avatar Jérome Perrin

- use selected uids in getInventoryList as cell keys, this makes the "inventory

  list" way of calculating consumption working properly with summary cells
- cache cell keys lookups
- support movement_strict_membership inventory axis
- add tests



git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@37282 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent af636246
...@@ -116,14 +116,15 @@ class BudgetLine(Predicate, XMLMatrix, Variated): ...@@ -116,14 +116,15 @@ class BudgetLine(Predicate, XMLMatrix, Variated):
query_dict.setdefault('ignore_group_by', True) query_dict.setdefault('ignore_group_by', True)
sign = self.BudgetLine_getConsumptionSign() sign = self.BudgetLine_getConsumptionSign()
cell_key_cache = dict()
budget_dict = dict() budget_dict = dict()
for brain in self.getPortalObject().portal_simulation\ for brain in self.getPortalObject().portal_simulation\
.getCurrentInventoryList(**query_dict): .getCurrentInventoryList(**query_dict):
cell_key = budget_model._getCellKeyFromInventoryListBrain(brain, self,
cell_key_cache=cell_key_cache)
# XXX total_quantity or total_price ?? # XXX total_quantity or total_price ??
previous_value = budget_dict.get( previous_value = budget_dict.get(cell_key, 0)
budget_model._getCellKeyFromInventoryListBrain(brain, self), 0) budget_dict[cell_key] = previous_value + brain.total_price * sign
budget_dict[budget_model._getCellKeyFromInventoryListBrain(brain, self)] = \
previous_value + brain.total_price * sign
return budget_dict return budget_dict
...@@ -99,10 +99,16 @@ class BudgetModel(Predicate): ...@@ -99,10 +99,16 @@ class BudgetModel(Predicate):
for budget_variation in sorted(self.contentValues( for budget_variation in sorted(self.contentValues(
portal_type=self.getPortalBudgetVariationTypeList()), portal_type=self.getPortalBudgetVariationTypeList()),
key=lambda x:x.getIntIndex()): key=lambda x:x.getIntIndex()):
variation_query_dict = budget_variation.getInventoryListQueryDict(budget_line) variation_query_dict = budget_variation.getInventoryListQueryDict(
# Merge group_by argument. All other arguments should not conflict budget_line)
# Merge group_by and select_list arguments.
# Other arguments should not conflict
if 'group_by' in query_dict and 'group_by' in variation_query_dict: if 'group_by' in query_dict and 'group_by' in variation_query_dict:
variation_query_dict['group_by'].extend(query_dict['group_by']) variation_query_dict['group_by'].extend(query_dict['group_by'])
if 'select_list' in query_dict \
and 'select_list' in variation_query_dict:
variation_query_dict['select_list'].extend(
query_dict['select_list'])
query_dict.update(variation_query_dict) query_dict.update(variation_query_dict)
...@@ -114,7 +120,8 @@ class BudgetModel(Predicate): ...@@ -114,7 +120,8 @@ class BudgetModel(Predicate):
query_dict.setdefault('at_date', start_date_range_max.latestTime()) query_dict.setdefault('at_date', start_date_range_max.latestTime())
return query_dict return query_dict
def _getCellKeyFromInventoryListBrain(self, brain, budget_line): def _getCellKeyFromInventoryListBrain(self, brain, budget_line,
cell_key_cache=None):
"""Compute the cell key from an inventory brain, the cell key can be used """Compute the cell key from an inventory brain, the cell key can be used
to retrieve the budget cell in the corresponding budget line. to retrieve the budget cell in the corresponding budget line.
""" """
...@@ -122,8 +129,8 @@ class BudgetModel(Predicate): ...@@ -122,8 +129,8 @@ class BudgetModel(Predicate):
for budget_variation in sorted(self.contentValues( for budget_variation in sorted(self.contentValues(
portal_type=self.getPortalBudgetVariationTypeList()), portal_type=self.getPortalBudgetVariationTypeList()),
key=lambda x:x.getIntIndex()): key=lambda x:x.getIntIndex()):
key = budget_variation._getCellKeyFromInventoryListBrain(brain, key = budget_variation._getCellKeyFromInventoryListBrain(
budget_line) brain, budget_line, cell_key_cache=cell_key_cache)
if key: if key:
cell_key += (key,) cell_key += (key,)
return cell_key return cell_key
......
...@@ -96,10 +96,12 @@ class BudgetVariation(Predicate): ...@@ -96,10 +96,12 @@ class BudgetVariation(Predicate):
""" """
return {} return {}
def _getCellKeyFromInventoryListBrain(self, brain, budget_line): def _getCellKeyFromInventoryListBrain(self, brain, budget_line,
cell_key_cache=None):
"""Compute the cell key from an inventory brain. """Compute the cell key from an inventory brain.
The cell key can be used to retrieve the budget cell in the corresponding The cell key can be used to retrieve the budget cell in the corresponding
budget line using budget_line.getCell budget line using budget_line.getCell
A dictionnary can be passed as "cell_key_cache" to cache catalog lookups
""" """
if not self.isMemberOf('budget_variation/budget_cell'): if not self.isMemberOf('budget_variation/budget_cell'):
return None return None
...@@ -111,54 +113,29 @@ class BudgetVariation(Predicate): ...@@ -111,54 +113,29 @@ class BudgetVariation(Predicate):
if not base_category: if not base_category:
return None return None
movement = brain.getObject() getObject = self.getPortalObject().portal_catalog.getObject
# axis 'movement' is simply a category membership on movements def getUrlFromUidNoCache(uid):
if axis == 'movement': relative_url = getObject(uid).getRelativeUrl()
return movement.getDefaultAcquiredCategoryMembership(base_category, if relative_url.startswith('%s/' % base_category):
base=True) return relative_url
return '%s/%s' % (base_category, relative_url)
# is it a source brain or destination brain ?
is_source_brain = True if cell_key_cache is not None:
if (brain.node_uid != brain.mirror_node_uid): def getUrlFromUidWithCache(uid):
is_source_brain = (brain.node_uid == movement.getSourceUid()) try:
elif (brain.section_uid != brain.mirror_section_uid): return cell_key_cache[uid]
is_source_brain = (brain.section_uid == movement.getSourceSectionUid()) except KeyError:
elif brain.total_quantity: relative_url = getUrlFromUidNoCache(uid)
is_source_brain = (brain.total_quantity == movement.getQuantity()) cell_key_cache[uid] = relative_url
else: return relative_url
raise NotImplementedError('Could not guess brain side') getUrlFromUid = getUrlFromUidWithCache
if axis.endswith('_category') or\
axis.endswith('_category_strict_membership'):
# if the axis is category, we get the node and then returns the category
# from that node
if axis.endswith('_category'):
axis = axis[:-len('_category')]
if axis.endswith('_category_strict_membership'):
axis = axis[:-len('_category_strict_membership')]
if is_source_brain:
if axis == 'node':
node = movement.getSourceValue()
else:
node = movement.getProperty('source_%s_value' % axis)
else: else:
if axis == 'node': getUrlFromUid = getUrlFromUidNoCache
node = movement.getDestinationValue()
else:
node = movement.getProperty('destination_%s_value' % axis)
if node is not None:
return node.getDefaultAcquiredCategoryMembership(base_category,
base=True)
return None
# otherwise we just return the node if axis == 'movement':
if is_source_brain: return getUrlFromUid(getattr(brain, 'default_%s_uid' % base_category))
if axis == 'node': elif axis == 'movement_strict_membership':
return '%s/%s' % (base_category, movement.getSource()) return getUrlFromUid(getattr(brain,
return '%s/%s' % (base_category, 'default_strict_%s_uid' % base_category))
movement.getProperty('source_%s' % axis)) return getUrlFromUid(getattr(brain, '%s_uid' % axis))
if axis == 'node':
return '%s/%s' % (base_category, movement.getDestination())
return '%s/%s' % (base_category,
movement.getProperty('destination_%s' % axis))
...@@ -95,6 +95,8 @@ class CategoryBudgetVariation(BudgetVariation): ...@@ -95,6 +95,8 @@ class CategoryBudgetVariation(BudgetVariation):
# Different possible inventory axis here # Different possible inventory axis here
if axis == 'movement': if axis == 'movement':
return {'default_%s_uid' % base_category: category_uid} return {'default_%s_uid' % base_category: category_uid}
if axis == 'movement_strict_membership':
return {'default_strict_%s_uid' % base_category: category_uid}
if axis in ('node', 'section', 'payment', 'function', 'project', if axis in ('node', 'section', 'payment', 'function', 'project',
'mirror_section', 'mirror_node' ): 'mirror_section', 'mirror_node' ):
return {'%s_uid' % axis: category_uid} return {'%s_uid' % axis: category_uid}
...@@ -117,8 +119,13 @@ class CategoryBudgetVariation(BudgetVariation): ...@@ -117,8 +119,13 @@ class CategoryBudgetVariation(BudgetVariation):
query_dict = dict() query_dict = dict()
if axis == 'movement': if axis == 'movement':
axis = 'default_%s_uid' % base_category
query_dict['group_by'] = [axis]
query_dict['select_list'] = [axis]
elif axis == 'movement_strict_membership':
axis = 'default_strict_%s_uid' % base_category axis = 'default_strict_%s_uid' % base_category
query_dict['group_by'] = [axis] query_dict['group_by'] = [axis]
query_dict['select_list'] = [axis]
else: else:
query_dict['group_by_%s' % axis] = True query_dict['group_by_%s' % axis] = True
if axis in ('node', 'section', 'payment', 'function', 'project', if axis in ('node', 'section', 'payment', 'function', 'project',
......
...@@ -147,8 +147,11 @@ class NodeBudgetVariation(BudgetVariation): ...@@ -147,8 +147,11 @@ class NodeBudgetVariation(BudgetVariation):
if criterion_base_category == base_category: if criterion_base_category == base_category:
if axis == 'movement': if axis == 'movement':
axis = 'default_%s' % base_category axis = 'default_%s' % base_category
# TODO: This is not correct if axis is a category (such as if axis == 'movement_strict_membership':
# section_category) axis = 'default_strict_%s' % base_category
# TODO: This is not correct if axis is a category such as
# section_category, because getInventoryList for now does not support
# parameters such as section_category_uid
axis = '%s_uid' % axis axis = '%s_uid' % axis
if node_url == budget_line.getRelativeUrl(): if node_url == budget_line.getRelativeUrl():
# This is the "All Other" virtual node # This is the "All Other" virtual node
...@@ -181,7 +184,12 @@ class NodeBudgetVariation(BudgetVariation): ...@@ -181,7 +184,12 @@ class NodeBudgetVariation(BudgetVariation):
query_dict = dict() query_dict = dict()
if axis == 'movement': if axis == 'movement':
axis = 'default_%s_uid' % base_category axis = 'default_%s_uid' % base_category
query_dict['select_list'] = [axis]
if axis == 'movement_strict_membership':
axis = 'default_strict_%s_uid' % base_category
query_dict['select_list'] = [axis]
query_dict['group_by_%s' % axis] = True query_dict['group_by_%s' % axis] = True
# TODO: This is not correct if axis is a category (such as # TODO: This is not correct if axis is a category (such as
# section_category) # section_category)
axis = '%s_uid' % axis axis = '%s_uid' % axis
...@@ -197,11 +205,13 @@ class NodeBudgetVariation(BudgetVariation): ...@@ -197,11 +205,13 @@ class NodeBudgetVariation(BudgetVariation):
base_category=base_category).getUid()) base_category=base_category).getUid())
return query_dict return query_dict
def _getCellKeyFromInventoryListBrain(self, brain, budget_line): def _getCellKeyFromInventoryListBrain(self, brain, budget_line,
"""Compute key from inventory brain, with support for "all others" virtual node. cell_key_cache=None):
"""Compute key from inventory brain, with support for "all others" virtual
node.
""" """
key = BudgetVariation._getCellKeyFromInventoryListBrain( key = BudgetVariation._getCellKeyFromInventoryListBrain(
self, brain, budget_line) self, brain, budget_line, cell_key_cache=cell_key_cache)
if self.getProperty('include_virtual_other_node'): if self.getProperty('include_virtual_other_node'):
if key not in [x[1] for x in if key not in [x[1] for x in
self.getBudgetVariationRangeCategoryList(budget_line)]: self.getBudgetVariationRangeCategoryList(budget_line)]:
......
...@@ -634,11 +634,14 @@ class TestBudget(ERP5TypeTestCase): ...@@ -634,11 +634,14 @@ class TestBudget(ERP5TypeTestCase):
at_date=DateTime(2000, 12, 31).latestTime(), at_date=DateTime(2000, 12, 31).latestTime(),
node_uid=[self.portal.account_module.goods_purchase.getUid(), node_uid=[self.portal.account_module.goods_purchase.getUid(),
self.portal.account_module.fixed_assets.getUid(),], self.portal.account_module.fixed_assets.getUid(),],
default_strict_product_line_uid=[product_line_1.getUid(), default_product_line_uid=[product_line_1.getUid(),
product_line_1_11.getUid(), product_line_1_11.getUid(),
product_line_1_12.getUid(),], product_line_1_12.getUid(),],
section_category=['group/demo_group'], section_category=['group/demo_group'],
group_by=['default_strict_product_line_uid'], group_by=['default_product_line_uid'],
# select list is passed, because getInventoryList does not add
# group by related keys to select
select_list=['default_product_line_uid'],
group_by_node=True, group_by_node=True,
group_by_section_category=True, group_by_section_category=True,
), ),
...@@ -668,28 +671,123 @@ class TestBudget(ERP5TypeTestCase): ...@@ -668,28 +671,123 @@ class TestBudget(ERP5TypeTestCase):
self.assertEquals( self.assertEquals(
{('source/account_module/fixed_assets', 'product_line/1/1.2'): -100.0, {('source/account_module/fixed_assets', 'product_line/1/1.2'): -100.0,
('source/account_module/goods_purchase', 'product_line/1/1.1'): 100.0, ('source/account_module/goods_purchase', 'product_line/1/1.1'): 100.0,
# summary line is automatically added (TODO) # summary lines are automatically added
## ('source/account_module/goods_purchase', 'product_line/1'): 100.0 ('source/account_module/fixed_assets', 'product_line/1'): -100.0,
('source/account_module/goods_purchase', 'product_line/1'): 100.0
}, },
budget_line.getConsumedBudgetDict()) budget_line.getConsumedBudgetDict())
self.assertEquals( self.assertEquals(
{('source/account_module/fixed_assets', 'product_line/1/1.2'): -100.0, {('source/account_module/fixed_assets', 'product_line/1/1.2'): -100.0,
('source/account_module/goods_purchase', 'product_line/1/1.1'): 100.0, ('source/account_module/goods_purchase', 'product_line/1/1.1'): 100.0,
# summary line is automatically added (TODO) ('source/account_module/fixed_assets', 'product_line/1'): -100.0,
## ('source/account_module/goods_purchase', 'product_line/1'): 100.0 ('source/account_module/goods_purchase', 'product_line/1'): 100.0
}, },
budget_line.getEngagedBudgetDict()) budget_line.getEngagedBudgetDict())
self.assertEquals( self.assertEquals(
{('source/account_module/fixed_assets', 'product_line/1/1.2'): 100.0, {('source/account_module/fixed_assets', 'product_line/1/1.2'): 100.0,
('source/account_module/goods_purchase', 'product_line/1/1.1'): -98.0, ('source/account_module/goods_purchase', 'product_line/1/1.1'): -98.0,
# summary line is automatically added (TODO) ('source/account_module/fixed_assets', 'product_line/1'): 100.0,
## ('source/account_module/goods_purchase', 'product_line/1'): 98.0 ('source/account_module/goods_purchase', 'product_line/1'): -98,
('source/account_module/goods_purchase', 'product_line/1'): 2.0
}, },
budget_line.getAvailableBudgetDict()) budget_line.getAvailableBudgetDict())
def test_consumption_category_variation_summary(self):
budget_model = self.portal.budget_model_module.newContent(
portal_type='Budget Model')
budget_model.newContent(
portal_type='Category Budget Variation',
int_index=1,
budget_variation='budget_cell',
inventory_axis='section_category',
variation_base_category='group',)
budget_model.newContent(
portal_type='Node Budget Variation',
int_index=2,
budget_variation='budget_cell',
inventory_axis='node',
variation_base_category='source',
aggregate_value_list=(
self.portal.account_module.goods_purchase,
self.portal.account_module.fixed_assets,
))
budget = self.portal.budget_module.newContent(
portal_type='Budget',
start_date_range_min=DateTime(2000, 1, 1),
start_date_range_max=DateTime(2000, 12, 31),
specialise_value=budget_model)
budget_line = budget.newContent(portal_type='Budget Line',)
# set the range, this will adjust the matrix
budget_line.edit(
variation_category_list=(
'source/account_module/goods_purchase',
'group/demo_group',
'group/demo_group/sub1',
))
form = budget_line.BudgetLine_view
self.portal.REQUEST.other.update(
dict(AUTHENTICATED_USER=getSecurityManager().getUser(),
field_membership_criterion_base_category_list=
form.membership_criterion_base_category_list.get_value('default'),
field_mapped_value_property_list=
form.mapped_value_property_list.get_value('default'),
field_matrixbox_quantity_cell_0_0_0="",
field_matrixbox_membership_criterion_category_list_cell_0_0_0=[],
field_matrixbox_quantity_cell_1_0_0="500",
field_matrixbox_membership_criterion_category_list_cell_1_0_0=[
'group/demo_group/sub1',
'source/account_module/goods_purchase', ],
))
budget_line.Base_edit(form_id=form.getId())
self.assertEquals(1, len(budget_line.contentValues()))
self.assertEquals(
dict(from_date=DateTime(2000, 1, 1),
at_date=DateTime(2000, 12, 31).latestTime(),
node_uid=[self.portal.account_module.goods_purchase.getUid(),],
section_category=['group/demo_group',
'group/demo_group/sub1'],
group_by_node=True,
group_by_section_category=True,
),
budget_model.getInventoryListQueryDict(budget_line))
atransaction = self.portal.accounting_module.newContent(
portal_type='Accounting Transaction',
resource_value=self.portal.currency_module.euro,
source_section_value=self.portal.organisation_module.my_organisation,
start_date=DateTime(2000, 1, 2))
atransaction.newContent(
portal_type='Accounting Transaction Line',
source_value=self.portal.account_module.goods_purchase,
source_debit=100)
atransaction.newContent(
portal_type='Accounting Transaction Line',
source_value=self.portal.account_module.fixed_assets,
source_credit=100)
atransaction.stop()
transaction.commit()
self.tic()
self.assertEquals(
{('group/demo_group/sub1', 'source/account_module/goods_purchase'): 100.0,
('group/demo_group', 'source/account_module/goods_purchase'): 100.0,},
budget_line.getConsumedBudgetDict())
self.assertEquals(
{('group/demo_group/sub1', 'source/account_module/goods_purchase'): 100.0,
('group/demo_group', 'source/account_module/goods_purchase'): 100.0,},
budget_line.getEngagedBudgetDict())
def test_budget_consumption_report(self): def test_budget_consumption_report(self):
budget_model = self.portal.budget_model_module.newContent( budget_model = self.portal.budget_model_module.newContent(
...@@ -837,9 +935,316 @@ class TestBudget(ERP5TypeTestCase): ...@@ -837,9 +935,316 @@ class TestBudget(ERP5TypeTestCase):
self.fail(''.join(err_list)) self.fail(''.join(err_list))
# Other TODOs: def test_update_summary_cell_simple(self):
# test the action to create or update quantity on summary cells
budget_model = self.portal.budget_model_module.newContent(
portal_type='Budget Model')
budget_model.newContent(
portal_type='Category Budget Variation',
int_index=1,
budget_variation='budget_cell',
inventory_axis='movement',
variation_base_category='product_line',)
budget_model.newContent(
portal_type='Node Budget Variation',
int_index=2,
budget_variation='budget_cell',
inventory_axis='node',
variation_base_category='source',
aggregate_value_list=(
self.portal.account_module.goods_purchase,
self.portal.account_module.fixed_assets,
))
budget_model.newContent(
portal_type='Category Budget Variation',
int_index=3,
budget_variation='budget_cell',
inventory_axis='section_category',
variation_base_category='group',)
budget = self.portal.budget_module.newContent(
portal_type='Budget',
start_date_range_min=DateTime(2000, 1, 1),
start_date_range_max=DateTime(2000, 12, 31),
specialise_value=budget_model)
budget_line = budget.newContent(portal_type='Budget Line')
# set the range, this will adjust the matrix
budget_line.edit(
variation_category_list=(
'group/demo_group',
'group/demo_group/sub1',
'group/demo_group/sub2',
'source/account_module/goods_purchase',
'source/account_module/fixed_assets',
'product_line/1',
'product_line/1/1.1',
'product_line/1/1.2', ))
form = budget_line.BudgetLine_view
self.portal.REQUEST.other.update(
dict(AUTHENTICATED_USER=getSecurityManager().getUser(),
field_membership_criterion_base_category_list=
form.membership_criterion_base_category_list.get_value('default'),
field_mapped_value_property_list=
form.mapped_value_property_list.get_value('default'),
# section_category & summary # group/demo_group
field_matrixbox_quantity_cell_0_0_0="",
field_matrixbox_membership_criterion_category_list_cell_0_0_0=[],
field_matrixbox_quantity_cell_1_0_0="",
field_matrixbox_membership_criterion_category_list_cell_1_0_0=[],
field_matrixbox_quantity_cell_2_0_0="",
field_matrixbox_membership_criterion_category_list_cell_2_0_0=[],
field_matrixbox_quantity_cell_0_1_0="",
field_matrixbox_membership_criterion_category_list_cell_0_1_0=[],
field_matrixbox_quantity_cell_1_1_0="",
field_matrixbox_membership_criterion_category_list_cell_1_1_0=[],
# This is a summary cell, but we set a manual value.
field_matrixbox_quantity_cell_2_1_0="100",
field_matrixbox_membership_criterion_category_list_cell_2_1_0=[
'product_line/1/1.2',
'source/account_module/fixed_assets',
'group/demo_group',
],
# group/demo_group/sub1
field_matrixbox_quantity_cell_0_0_1="",
field_matrixbox_membership_criterion_category_list_cell_0_0_1=[],
field_matrixbox_quantity_cell_1_0_1="1",
field_matrixbox_membership_criterion_category_list_cell_1_0_1=[
'product_line/1/1.1',
'source/account_module/goods_purchase',
'group/demo_group/sub1',
],
field_matrixbox_quantity_cell_2_0_1="2",
field_matrixbox_membership_criterion_category_list_cell_2_0_1=[
'product_line/1/1.2',
'source/account_module/goods_purchase',
'group/demo_group/sub1',
],
field_matrixbox_quantity_cell_0_1_1="",
field_matrixbox_membership_criterion_category_list_cell_0_1_1=[],
field_matrixbox_quantity_cell_1_1_1="3",
field_matrixbox_membership_criterion_category_list_cell_1_1_1=[
'product_line/1/1.1',
'source/account_module/fixed_assets',
'group/demo_group/sub1',
],
field_matrixbox_quantity_cell_2_1_1="4",
field_matrixbox_membership_criterion_category_list_cell_2_1_1=[
'product_line/1/1.2',
'source/account_module/fixed_assets',
'group/demo_group/sub1',
],
# group/demo_group/sub2
field_matrixbox_quantity_cell_0_0_2="",
field_matrixbox_membership_criterion_category_list_cell_0_0_2=[],
# we only have 1 cell here
field_matrixbox_quantity_cell_1_0_2="5",
field_matrixbox_membership_criterion_category_list_cell_1_0_2=[
'product_line/1/1.1',
'source/account_module/goods_purchase',
'group/demo_group/sub2',
],
field_matrixbox_quantity_cell_2_0_2="",
field_matrixbox_membership_criterion_category_list_cell_2_0_2=[],
# we have no cells here
field_matrixbox_quantity_cell_0_1_2="",
field_matrixbox_membership_criterion_category_list_cell_0_1_2=[],
field_matrixbox_quantity_cell_1_1_2="",
field_matrixbox_membership_criterion_category_list_cell_1_1_2=[],
field_matrixbox_quantity_cell_2_1_2="",
field_matrixbox_membership_criterion_category_list_cell_2_1_2=[],
))
budget_line.Base_edit(form_id=form.getId())
self.assertEquals(6, len(budget_line.contentValues()))
budget_line.BudgetLine_setQuantityOnSummaryCellList()
# summary cells have been created:
self.assertEquals(14, len(budget_line.contentValues()))
# those cells are aggregating
self.assertEquals(1+2, budget_line.getCell(
'product_line/1',
'source/account_module/goods_purchase',
'group/demo_group/sub1',).getQuantity())
self.assertEquals(4+3, budget_line.getCell(
'product_line/1',
'source/account_module/fixed_assets',
'group/demo_group/sub1',).getQuantity())
self.assertEquals(1+5, budget_line.getCell(
'product_line/1/1.1',
'source/account_module/goods_purchase',
'group/demo_group',).getQuantity())
self.assertEquals(1+2+5, budget_line.getCell(
'product_line/1',
'source/account_module/goods_purchase',
'group/demo_group',).getQuantity())
# the cell that we have modified is erased
self.assertEquals(4, budget_line.getCell(
'product_line/1/1.2',
'source/account_module/fixed_assets',
'group/demo_group',).getQuantity())
# test all cells for complete coverage
self.assertEquals(6, budget_line.getCell(
'product_line/1/1.1',
'source/account_module/goods_purchase',
'group/demo_group',).getQuantity())
self.assertEquals(2, budget_line.getCell(
'product_line/1/1.2',
'source/account_module/goods_purchase',
'group/demo_group',).getQuantity())
self.assertEquals(3+4, budget_line.getCell(
'product_line/1',
'source/account_module/fixed_assets',
'group/demo_group',).getQuantity())
self.assertEquals(3, budget_line.getCell(
'product_line/1/1.1',
'source/account_module/fixed_assets',
'group/demo_group',).getQuantity())
self.assertEquals(4, budget_line.getCell(
'product_line/1/1.2',
'source/account_module/fixed_assets',
'group/demo_group',).getQuantity())
self.assertEquals(5, budget_line.getCell(
'product_line/1',
'source/account_module/goods_purchase',
'group/demo_group/sub2',).getQuantity())
# change a cell quantity and call again
budget_cell = budget_line.getCell(
'product_line/1/1.2',
'source/account_module/goods_purchase',
'group/demo_group/sub1')
self.assertNotEquals(None, budget_cell)
self.assertEquals(2, budget_cell.getQuantity())
budget_cell.setQuantity(6)
budget_line.BudgetLine_setQuantityOnSummaryCellList()
self.assertEquals(14, len(budget_line.contentValues()))
self.assertEquals(1+6, budget_line.getCell(
'product_line/1',
'source/account_module/goods_purchase',
'group/demo_group/sub1',).getQuantity())
self.assertEquals(4+3, budget_line.getCell(
'product_line/1',
'source/account_module/fixed_assets',
'group/demo_group/sub1',).getQuantity())
self.assertEquals(1+5, budget_line.getCell(
'product_line/1/1.1',
'source/account_module/goods_purchase',
'group/demo_group',).getQuantity())
self.assertEquals(1+6+5, budget_line.getCell(
'product_line/1',
'source/account_module/goods_purchase',
'group/demo_group',).getQuantity())
def test_update_summary_cell_non_strict_and_second_summary(self):
# test the action to create or update quantity on summary cells, variation
# which are strict are not updated, and multiple level summary does not
# aggregate again intermediate summaries
budget_model = self.portal.budget_model_module.newContent(
portal_type='Budget Model')
budget_model.newContent(
portal_type='Category Budget Variation',
int_index=1,
budget_variation='budget_cell',
inventory_axis='movement_strict_membership',
variation_base_category='product_line',)
budget_model.newContent(
portal_type='Node Budget Variation',
int_index=2,
budget_variation='budget_cell',
inventory_axis='node',
variation_base_category='source',
aggregate_value_list=(
self.portal.account_module.goods_purchase,
self.portal.account_module.fixed_assets,
))
budget_model.newContent(
portal_type='Category Budget Variation',
int_index=3,
budget_variation='budget_cell',
inventory_axis='node_category',
variation_base_category='account_type',)
budget = self.portal.budget_module.newContent(
portal_type='Budget',
start_date_range_min=DateTime(2000, 1, 1),
start_date_range_max=DateTime(2000, 12, 31),
specialise_value=budget_model)
budget_line = budget.newContent(portal_type='Budget Line')
# set the range, this will adjust the matrix
budget_line.edit(
variation_category_list=(
'account_type/asset',
'account_type/asset/cash',
'account_type/asset/cash/bank',
'source/account_module/goods_purchase',
'product_line/1',
'product_line/1/1.1', ))
form = budget_line.BudgetLine_view
self.portal.REQUEST.other.update(
dict(AUTHENTICATED_USER=getSecurityManager().getUser(),
field_membership_criterion_base_category_list=
form.membership_criterion_base_category_list.get_value('default'),
field_mapped_value_property_list=
form.mapped_value_property_list.get_value('default'),
field_matrixbox_quantity_cell_0_0_0="",
field_matrixbox_membership_criterion_category_list_cell_0_0_0=[],
field_matrixbox_quantity_cell_1_0_0="",
field_matrixbox_membership_criterion_category_list_cell_1_0_0=[],
field_matrixbox_quantity_cell_0_0_1="",
field_matrixbox_membership_criterion_category_list_cell_0_0_1=[],
field_matrixbox_quantity_cell_1_0_1="",
field_matrixbox_membership_criterion_category_list_cell_1_0_1=[],
field_matrixbox_quantity_cell_0_0_2="",
field_matrixbox_membership_criterion_category_list_cell_0_0_2=[],
field_matrixbox_quantity_cell_1_0_2="1",
field_matrixbox_membership_criterion_category_list_cell_1_0_2=[
'product_line/1/1.1',
'source/account_module/goods_purchase',
'account_type/asset/cash/bank',
],
))
budget_line.Base_edit(form_id=form.getId())
self.assertEquals(1, len(budget_line.contentValues()))
budget_line.BudgetLine_setQuantityOnSummaryCellList()
self.assertEquals(3, len(budget_line.contentValues()))
budget_cell = budget_line.getCell(
'product_line/1/1.1',
'source/account_module/goods_purchase',
'account_type/asset/cash')
self.assertNotEquals(None, budget_cell)
self.assertEquals(1, budget_cell.getQuantity())
budget_cell = budget_line.getCell(
'product_line/1/1.1',
'source/account_module/goods_purchase',
'account_type/asset',)
self.assertNotEquals(None, budget_cell)
self.assertEquals(1, budget_cell.getQuantity())
# Other TODOs:
# budget level variation and budget cell level variation for same inventory # budget level variation and budget cell level variation for same inventory
# axis # axis
......
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