[Erp5-report] r37282 jerome - in /erp5/trunk/products/ERP5: Document/ tests/

nobody at svn.erp5.org nobody at svn.erp5.org
Tue Jul 27 14:43:00 CEST 2010


Author: jerome
Date: Tue Jul 27 14:42:41 2010
New Revision: 37282

URL: http://svn.erp5.org?rev=37282&view=rev
Log:
- 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


Modified:
    erp5/trunk/products/ERP5/Document/BudgetLine.py
    erp5/trunk/products/ERP5/Document/BudgetModel.py
    erp5/trunk/products/ERP5/Document/BudgetVariation.py
    erp5/trunk/products/ERP5/Document/CategoryBudgetVariation.py
    erp5/trunk/products/ERP5/Document/NodeBudgetVariation.py
    erp5/trunk/products/ERP5/tests/testBudget.py

Modified: erp5/trunk/products/ERP5/Document/BudgetLine.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/BudgetLine.py?rev=37282&r1=37281&r2=37282&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/BudgetLine.py [utf8] (original)
+++ erp5/trunk/products/ERP5/Document/BudgetLine.py [utf8] Tue Jul 27 14:42:41 2010
@@ -116,14 +116,15 @@ class BudgetLine(Predicate, XMLMatrix, V
     query_dict.setdefault('ignore_group_by', True)
 
     sign = self.BudgetLine_getConsumptionSign()
+    cell_key_cache = dict()
     budget_dict = dict()
     for brain in self.getPortalObject().portal_simulation\
                              .getCurrentInventoryList(**query_dict):
+      cell_key = budget_model._getCellKeyFromInventoryListBrain(brain, self,
+                                       cell_key_cache=cell_key_cache)
       # XXX total_quantity or total_price ??
-      previous_value = budget_dict.get(
-          budget_model._getCellKeyFromInventoryListBrain(brain, self), 0)
-      budget_dict[budget_model._getCellKeyFromInventoryListBrain(brain, self)] = \
-                  previous_value + brain.total_price * sign
+      previous_value = budget_dict.get(cell_key, 0)
+      budget_dict[cell_key] = previous_value + brain.total_price * sign
 
     return budget_dict
 

Modified: erp5/trunk/products/ERP5/Document/BudgetModel.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/BudgetModel.py?rev=37282&r1=37281&r2=37282&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/BudgetModel.py [utf8] (original)
+++ erp5/trunk/products/ERP5/Document/BudgetModel.py [utf8] Tue Jul 27 14:42:41 2010
@@ -99,10 +99,16 @@ class BudgetModel(Predicate):
     for budget_variation in sorted(self.contentValues(
               portal_type=self.getPortalBudgetVariationTypeList()),
               key=lambda x:x.getIntIndex()):
-      variation_query_dict = budget_variation.getInventoryListQueryDict(budget_line)
-      # Merge group_by argument. All other arguments should not conflict
+      variation_query_dict = budget_variation.getInventoryListQueryDict(
+                                                      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:
         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)
  
@@ -114,7 +120,8 @@ class BudgetModel(Predicate):
       query_dict.setdefault('at_date', start_date_range_max.latestTime())
     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
     to retrieve the budget cell in the corresponding budget line.
     """
@@ -122,8 +129,8 @@ class BudgetModel(Predicate):
     for budget_variation in sorted(self.contentValues(
               portal_type=self.getPortalBudgetVariationTypeList()),
               key=lambda x:x.getIntIndex()):
-      key = budget_variation._getCellKeyFromInventoryListBrain(brain,
-                                                               budget_line)
+      key = budget_variation._getCellKeyFromInventoryListBrain(
+                  brain, budget_line, cell_key_cache=cell_key_cache)
       if key:
         cell_key += (key,)
     return cell_key

Modified: erp5/trunk/products/ERP5/Document/BudgetVariation.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/BudgetVariation.py?rev=37282&r1=37281&r2=37282&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/BudgetVariation.py [utf8] (original)
+++ erp5/trunk/products/ERP5/Document/BudgetVariation.py [utf8] Tue Jul 27 14:42:41 2010
@@ -96,10 +96,12 @@ class BudgetVariation(Predicate):
     """
     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.
     The cell key can be used to retrieve the budget cell in the corresponding
     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'):
       return None
@@ -110,55 +112,30 @@ class BudgetVariation(Predicate):
     base_category = self.getProperty('variation_base_category')
     if not base_category:
       return None
-
-    movement = brain.getObject()
-    # axis 'movement' is simply a category membership on movements
-    if axis == 'movement':
-      return movement.getDefaultAcquiredCategoryMembership(base_category,
-                                                           base=True)
-
-    # is it a source brain or destination brain ?
-    is_source_brain = True
-    if (brain.node_uid != brain.mirror_node_uid):
-      is_source_brain = (brain.node_uid == movement.getSourceUid())
-    elif (brain.section_uid != brain.mirror_section_uid):
-      is_source_brain = (brain.section_uid == movement.getSourceSectionUid())
-    elif brain.total_quantity:
-      is_source_brain = (brain.total_quantity == movement.getQuantity())
+    
+    getObject = self.getPortalObject().portal_catalog.getObject
+    def getUrlFromUidNoCache(uid):
+      relative_url = getObject(uid).getRelativeUrl()
+      if relative_url.startswith('%s/' % base_category):
+        return relative_url
+      return '%s/%s' % (base_category, relative_url)
+
+    if cell_key_cache is not None:
+      def getUrlFromUidWithCache(uid):
+        try:
+          return cell_key_cache[uid]
+        except KeyError:
+          relative_url = getUrlFromUidNoCache(uid)
+          cell_key_cache[uid] = relative_url
+          return relative_url
+      getUrlFromUid = getUrlFromUidWithCache
     else:
-      raise NotImplementedError('Could not guess brain side')
+      getUrlFromUid = getUrlFromUidNoCache
 
-    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:
-        if axis == 'node':
-          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 is_source_brain:
-      if axis == 'node':
-        return '%s/%s' % (base_category, movement.getSource())
-      return '%s/%s' % (base_category,
-                        movement.getProperty('source_%s' % axis))
-    if axis == 'node':
-      return '%s/%s' % (base_category, movement.getDestination())
-    return '%s/%s' % (base_category,
-                      movement.getProperty('destination_%s' % axis))
+    if axis == 'movement':
+      return getUrlFromUid(getattr(brain, 'default_%s_uid' % base_category))
+    elif axis == 'movement_strict_membership':
+      return getUrlFromUid(getattr(brain,
+                                   'default_strict_%s_uid' % base_category))
+    return getUrlFromUid(getattr(brain, '%s_uid' % axis))
 

Modified: erp5/trunk/products/ERP5/Document/CategoryBudgetVariation.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/CategoryBudgetVariation.py?rev=37282&r1=37281&r2=37282&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/CategoryBudgetVariation.py [utf8] (original)
+++ erp5/trunk/products/ERP5/Document/CategoryBudgetVariation.py [utf8] Tue Jul 27 14:42:41 2010
@@ -95,6 +95,8 @@ class CategoryBudgetVariation(BudgetVari
         # Different possible inventory axis here
         if axis == 'movement':
           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',
                     'mirror_section', 'mirror_node' ):
           return {'%s_uid' % axis: category_uid}
@@ -117,8 +119,13 @@ class CategoryBudgetVariation(BudgetVari
 
     query_dict = dict()
     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
       query_dict['group_by'] = [axis]
+      query_dict['select_list'] = [axis]
     else:
       query_dict['group_by_%s' % axis] = True
       if axis in ('node', 'section', 'payment', 'function', 'project',
@@ -126,7 +133,7 @@ class CategoryBudgetVariation(BudgetVari
         axis = '%s_uid' % axis
 
     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)

Modified: erp5/trunk/products/ERP5/Document/NodeBudgetVariation.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/NodeBudgetVariation.py?rev=37282&r1=37281&r2=37282&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/NodeBudgetVariation.py [utf8] (original)
+++ erp5/trunk/products/ERP5/Document/NodeBudgetVariation.py [utf8] Tue Jul 27 14:42:41 2010
@@ -147,8 +147,11 @@ class NodeBudgetVariation(BudgetVariatio
       if criterion_base_category == base_category:
         if axis == 'movement':
           axis = 'default_%s' % base_category
-        # TODO: This is not correct if axis is a category (such as
-        # section_category)
+        if axis == 'movement_strict_membership':
+          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
         if node_url == budget_line.getRelativeUrl():
           # This is the "All Other" virtual node
@@ -181,7 +184,12 @@ class NodeBudgetVariation(BudgetVariatio
     query_dict = dict()
     if axis == 'movement':
       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
+
     # TODO: This is not correct if axis is a category (such as
     # section_category)
     axis = '%s_uid' % axis
@@ -191,17 +199,19 @@ class NodeBudgetVariation(BudgetVariatio
       return query_dict
 
     for node_url in context.getVariationCategoryList(
-                                          base_category_list=(base_category,)):
+                          base_category_list=(base_category,)):
       query_dict.setdefault(axis, []).append(
                 portal_categories.getCategoryValue(node_url,
                       base_category=base_category).getUid())
     return query_dict
   
-  def _getCellKeyFromInventoryListBrain(self, brain, budget_line):
-    """Compute key from inventory brain, with support for "all others" virtual node.
+  def _getCellKeyFromInventoryListBrain(self, brain, budget_line,
+                                         cell_key_cache=None):
+    """Compute key from inventory brain, with support for "all others" virtual
+    node.
     """
     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 key not in [x[1] for x in
           self.getBudgetVariationRangeCategoryList(budget_line)]:

Modified: erp5/trunk/products/ERP5/tests/testBudget.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/tests/testBudget.py?rev=37282&r1=37281&r2=37282&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/tests/testBudget.py [utf8] (original)
+++ erp5/trunk/products/ERP5/tests/testBudget.py [utf8] Tue Jul 27 14:42:41 2010
@@ -634,11 +634,14 @@ class TestBudget(ERP5TypeTestCase):
              at_date=DateTime(2000, 12, 31).latestTime(),
              node_uid=[self.portal.account_module.goods_purchase.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_12.getUid(),],
              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_section_category=True,
              ),
@@ -668,28 +671,123 @@ class TestBudget(ERP5TypeTestCase):
     self.assertEquals(
       {('source/account_module/fixed_assets', 'product_line/1/1.2'): -100.0,
        ('source/account_module/goods_purchase', 'product_line/1/1.1'): 100.0,
-       # summary line is automatically added (TODO)
-##       ('source/account_module/goods_purchase', 'product_line/1'): 100.0
+       # summary lines are automatically added
+       ('source/account_module/fixed_assets', 'product_line/1'): -100.0,
+       ('source/account_module/goods_purchase', 'product_line/1'): 100.0
        },
         budget_line.getConsumedBudgetDict())
 
     self.assertEquals(
       {('source/account_module/fixed_assets', 'product_line/1/1.2'): -100.0,
        ('source/account_module/goods_purchase', 'product_line/1/1.1'): 100.0,
-       # summary line is automatically added (TODO)
-##       ('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.getEngagedBudgetDict())
 
     self.assertEquals(
       {('source/account_module/fixed_assets', 'product_line/1/1.2'): 100.0,
        ('source/account_module/goods_purchase', 'product_line/1/1.1'): -98.0,
-       # summary line is automatically added (TODO)
-##       ('source/account_module/goods_purchase', 'product_line/1'): 98.0 
-       ('source/account_module/goods_purchase', 'product_line/1'): 2.0 
+       ('source/account_module/fixed_assets', 'product_line/1'): 100.0,
+       ('source/account_module/goods_purchase', 'product_line/1'): -98,
        },
         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):
     budget_model = self.portal.budget_model_module.newContent(
@@ -837,9 +935,316 @@ class TestBudget(ERP5TypeTestCase):
       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'),
+            
+             # 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)
 
-  # section_category & summary
+    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
   # axis




More information about the Erp5-report mailing list