From 3b8f44307ea74de988082dc3996494af8067e46a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Perrin?= <jerome@nexedi.com> Date: Tue, 12 Oct 2010 16:09:05 +0000 Subject: [PATCH] amendments to r39010: this feature was not working when only "none" was selected, and when none and actual values where selected on the same axis. git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@39068 20353a03-c40f-0410-a6d1-a30d3c3de9de --- product/ERP5/Document/NodeBudgetVariation.py | 38 ++++--- product/ERP5/tests/testBudget.py | 110 ++++++++++++++++++- 2 files changed, 134 insertions(+), 14 deletions(-) diff --git a/product/ERP5/Document/NodeBudgetVariation.py b/product/ERP5/Document/NodeBudgetVariation.py index b56179a214..5a52a2ffa6 100644 --- a/product/ERP5/Document/NodeBudgetVariation.py +++ b/product/ERP5/Document/NodeBudgetVariation.py @@ -31,7 +31,6 @@ from AccessControl.ZopeGuards import guarded_getattr from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5.Document.BudgetVariation import BudgetVariation from Products.ZSQLCatalog.SQLCatalog import Query, NegatedQuery, ComplexQuery -from Products.ERP5Type.Message import translateString class NodeBudgetVariation(BudgetVariation): @@ -131,6 +130,7 @@ class NodeBudgetVariation(BudgetVariation): # parameters such as section_category_uid axis = '%s_uid' % axis + query = None portal_categories = self.getPortalObject().portal_categories for criterion_category in context.getMembershipCriterionCategoryList(): if '/' not in criterion_category: # safe ... @@ -139,8 +139,8 @@ class NodeBudgetVariation(BudgetVariation): if criterion_base_category == base_category: if node_url == 'budget_special_node/none': # This is the "Nothing" virtual node - query_dict.setdefault(axis, []).append(Query(**{axis: None})) - if node_url == 'budget_special_node/all_other': + query = Query(**{axis: None}) + elif node_url == 'budget_special_node/all_other': # This is the "All Other" virtual node other_uid_list = [] none_node_selected = False @@ -153,19 +153,28 @@ class NodeBudgetVariation(BudgetVariation): other_uid_list.append(node.getUid()) if none_node_selected: # in this case we don't want to include NULL in All others - query_dict.setdefault(axis, []).append( - NegatedQuery(Query(**{axis: other_uid_list}))) + query = NegatedQuery(Query(**{axis: other_uid_list})) else: - query_dict.setdefault(axis, []).append( - ComplexQuery( + query = ComplexQuery( NegatedQuery(Query(**{axis: other_uid_list})), Query(**{axis: None}), - operator="OR")) + operator="OR") - query_dict.setdefault(axis, []).append( + else: + query_dict.setdefault(axis, []).append( portal_categories.getCategoryValue(node_url, base_category=criterion_base_category).getUid()) + if query: + if axis in query_dict: + query_dict[axis] = ComplexQuery( + query, + Query(**{axis: query_dict[axis]}), + operator='OR') + else: + query_dict[axis] = query + + return query_dict def getInventoryListQueryDict(self, budget_line): @@ -210,10 +219,13 @@ class NodeBudgetVariation(BudgetVariation): found = True if found: if self.getProperty('include_virtual_none_node'): - query_dict[axis] = ComplexQuery( - Query(**{axis: None}), - Query(**{axis: query_dict[axis]}), - operator="OR") + if axis in query_dict: + query_dict[axis] = ComplexQuery( + Query(**{axis: None}), + Query(**{axis: query_dict[axis]}), + operator="OR") + else: + query_dict[axis] = Query(**{axis: None}) return query_dict return dict() diff --git a/product/ERP5/tests/testBudget.py b/product/ERP5/tests/testBudget.py index 1e83b38ab7..3f0f003be2 100644 --- a/product/ERP5/tests/testBudget.py +++ b/product/ERP5/tests/testBudget.py @@ -31,7 +31,7 @@ import transaction from DateTime import DateTime from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase -from Products.ZSQLCatalog.SQLCatalog import ComplexQuery +from Products.ZSQLCatalog.SQLCatalog import ComplexQuery, Query from AccessControl import getSecurityManager class TestBudget(ERP5TypeTestCase): @@ -657,7 +657,115 @@ class TestBudget(ERP5TypeTestCase): {('source_project/organisation_module/my_organisation',): 200.0, ('source_project/budget_special_node/none',): -300.0 }, budget_line.getEngagedBudgetDict()) + + def test_only_none_virtual_node(self): + # tests consumptions, by using only "none" virtual node on a node budget + # variation + budget_model = self.portal.budget_model_module.newContent( + portal_type='Budget Model') + budget_model.newContent( + portal_type='Node Budget Variation', + int_index=1, + budget_variation='budget_cell', + # this does not work for movement, node and section + # categories ... + inventory_axis='project', + variation_base_category='source_project', + aggregate_value_list=( + self.portal.organisation_module.my_organisation,), + include_virtual_none_node=True) + budget_model.newContent( + portal_type='Category Budget Variation', + int_index=2, + budget_variation='budget_line', + inventory_axis='node_category_strict_membership', + 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') + + budget_line.edit( + variation_category_list=( + 'source_project/budget_special_node/none', # this is 'none' + 'account_type/expense',)) + + 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="200", + field_matrixbox_membership_criterion_category_list_cell_0_0_0=[ + 'source_project/budget_special_node/none',], + )) + budget_line.Base_edit(form_id=form.getId()) + + self.assertEquals(1, len(budget_line.contentValues())) + + class ReferenceQuery: + """Helper class to compare queries + """ + def __eq__(me, query): + self.assertTrue(isinstance(query, Query)) + self.assertEquals(query.kw, {'project_uid': None}) + return True + + self.assertEquals( + dict(from_date=DateTime(2000, 1, 1), + at_date=DateTime(2000, 12, 31).latestTime(), + node_category_strict_membership=['account_type/expense',], + project_uid=ReferenceQuery(), + group_by_node_category_strict_membership=True, + group_by_project=True, + ), + budget_model.getInventoryListQueryDict(budget_line)) + + budget_cell = budget_line.contentValues()[0] + self.assertEquals( + dict(from_date=DateTime(2000, 1, 1), + at_date=DateTime(2000, 12, 31).latestTime(), + node_category_strict_membership=['account_type/expense',], + project_uid=ReferenceQuery(), + ), + budget_model.getInventoryQueryDict(budget_cell)) + + atransaction = self.portal.accounting_module.newContent( + portal_type='Accounting Transaction', + source_section_value=self.portal.organisation_module.my_organisation, + resource_value=self.portal.currency_module.euro, + start_date=DateTime(2000, 1, 2)) + atransaction.newContent( + portal_type='Accounting Transaction Line', + source_value=self.portal.account_module.goods_purchase, + source_project_value=self.portal.organisation_module.my_organisation, + source_debit=200) + atransaction.newContent( + portal_type='Accounting Transaction Line', + source_value=self.portal.account_module.goods_purchase, + source_credit=300) + atransaction.stop() + + transaction.commit() + self.tic() + + self.assertEquals( + {('source_project/budget_special_node/none',): -300.0 + }, budget_line.getConsumedBudgetDict()) + + self.assertEquals( + {('source_project/budget_special_node/none',): -300.0 + }, budget_line.getEngagedBudgetDict()) + self.assertEquals(-300, budget_cell.getConsumedBudget()) def test_none_and_all_others_virtual_nodes_together(self): # tests consumptions, by using "none" and "all other" virtual nodes -- 2.30.9