Allow creating the property criterion maps directly in createPredicate()

Both for _identity_criterion and _range_criterion

Add tests showing direct criteria specification in predicate scripts

And rule tests to match on simulation movements, since this is what rules match
most of the time.
parent ec81c0c6
......@@ -79,7 +79,12 @@ class TestRuleMixin(TestOrderMixin):
else:
self.pl = pl_module.objectValues()[0]
#delete applied_rule
self._wipe(self.getSimulationTool())
simulation_tool = self.getSimulationTool()
self._wipe(simulation_tool)
# create one manual simulation movement for rule testing
self.ar = simulation_tool.newContent(portal_type='Applied Rule')
self.sm = self.ar.newContent(portal_type='Simulation Movement')
self.sm.setStartDate("2007-07-01") # for the date based rule tests
# commit
transaction.commit()
self.tic()
......@@ -138,7 +143,7 @@ class TestRule(TestRuleMixin, ERP5TypeTestCase) :
self.assertEquals(self.getRuleTool().countFolder(
validation_state="validated")[0][0], 1)
self.assertEquals(len(self.getRuleTool().searchRuleList(self.pl)), 0)
self.assertEquals(len(self.getRuleTool().searchRuleList(self.sm)), 0)
def test_02_WrongTestMethod(self, quiet=quiet, run=run_all_test):
"""
......@@ -157,7 +162,7 @@ class TestRule(TestRuleMixin, ERP5TypeTestCase) :
self.assertEquals(self.getRuleTool().countFolder(
validation_state="validated")[0][0], 1)
self.assertEquals(len(self.getRuleTool().searchRuleList(self.pl)), 0)
self.assertEquals(len(self.getRuleTool().searchRuleList(self.sm)), 0)
def test_03_GoodTestMethod(self, quiet=quiet, run=run_all_test):
"""
......@@ -176,7 +181,7 @@ class TestRule(TestRuleMixin, ERP5TypeTestCase) :
self.assertEquals(self.getRuleTool().countFolder(
validation_state="validated")[0][0], 1)
self.assertEquals(len(self.getRuleTool().searchRuleList(self.pl)), 1)
self.assertEquals(len(self.getRuleTool().searchRuleList(self.sm)), 1)
def test_04_NotValidatedRule(self, quiet=quiet, run=run_all_test):
"""
......@@ -197,7 +202,7 @@ class TestRule(TestRuleMixin, ERP5TypeTestCase) :
self.assertEquals(self.getRuleTool().countFolder(
validation_state="validated")[0][0], 0)
self.assertEquals(len(self.getRuleTool().searchRuleList(self.pl)), 0)
self.assertEquals(len(self.getRuleTool().searchRuleList(self.sm)), 0)
def test_06_WrongDateRange(self, quiet=quiet, run=run_all_test):
"""
......@@ -219,7 +224,7 @@ class TestRule(TestRuleMixin, ERP5TypeTestCase) :
self.assertEquals(self.getRuleTool().countFolder(
validation_state="validated")[0][0], 1)
self.assertEquals(len(self.getRuleTool().searchRuleList(self.pl)), 0)
self.assertEquals(len(self.getRuleTool().searchRuleList(self.sm)), 0)
def test_07_GoodDateRange(self, quiet=quiet, run=run_all_test):
"""
......@@ -241,7 +246,56 @@ class TestRule(TestRuleMixin, ERP5TypeTestCase) :
self.assertEquals(self.getRuleTool().countFolder(
validation_state="validated")[0][0], 1)
self.assertEquals(len(self.getRuleTool().searchRuleList(self.pl)), 1)
self.assertEquals(len(self.getRuleTool().searchRuleList(self.sm)), 1)
def test_070_direct_criteria_specification(self):
"""
test that rule-specific scripts can specify identity and range criteria
"""
skin_folder = self.getPortal().portal_skins.custom
# add an always-matching predicate test script to the rule
createZODBPythonScript(skin_folder, 'good_script', 'rule',
'return True')
delivery_rule = self.getRule('default_delivery_rule')
delivery_rule.setTestMethodId('good_script')
# but add a predicate building script that only matches on
# Simulation Movements, to affect all rules
createZODBPythonScript(skin_folder, 'RuleMixin_asPredicate', '',
"""
return context.generatePredicate(
identity_criterion=dict(portal_type=(context.movement_type,)),
)
""")
# and validate it, which will indirectly reindex the predicate.
delivery_rule.validate()
transaction.commit()
self.tic()
# now rules don't match packing lists by default
self.assertEqual(len(self.getRuleTool().searchRuleList(self.pl)), 0)
# only simulation movements
self.assertEqual(len(self.getRuleTool().searchRuleList(self.sm)), 1)
# unless they have more specific predicate script telling them otherwise:
predicate_script = createZODBPythonScript(
skin_folder, 'DeliveryRootSimulationRule_asPredicate', '',
"""
return context.generatePredicate(
identity_criterion=dict(portal_type=('Sale Packing List',)),
range_criterion=dict(start_date=(%r, None)),
)
""" % self.pl.getStartDate())
delivery_rule.reindexObject()
transaction.commit()
self.tic()
# now they match the packing list, but not the simulation movement
self.assertEqual(len(self.getRuleTool().searchRuleList(self.pl)), 1)
self.assertEqual(len(self.getRuleTool().searchRuleList(self.sm)), 0)
# Note that we added a range criterion above, which means that if
# the packing list no longer falls within the range:
self.pl.setStartDate(self.pl.getStartDate() - 1)
transaction.commit()
self.tic()
# the rule no longer matches the packing list:
self.assertEqual(len(self.getRuleTool().searchRuleList(self.pl)), 0)
def test_08_updateAppliedRule(self, quiet=quiet, run=run_all_test):
"""
......
......@@ -517,7 +517,9 @@ class Predicate(XMLObject):
security.declareProtected(Permissions.AccessContentsInformation, 'generatePredicate')
def generatePredicate(self, multimembership_criterion_base_category_list=(),
membership_criterion_base_category_list=(),
criterion_property_list=()):
criterion_property_list=(),
identity_criterion=None,
range_criterion=None,):
"""
This method generates a new temporary predicate based on an ad-hoc
interpretation of local properties of an object. For example,
......@@ -554,16 +556,11 @@ class Predicate(XMLObject):
# We need to build new criteria for asContext, and we should not
# modify the original, so we always make copies. Since the usage is
# temporary, use dicts instead of persistent mappings.
identity_criterion = getattr(self, '_identity_criterion', None)
if identity_criterion is None:
identity_criterion = {}
else:
identity_criterion = dict(identity_criterion)
range_criterion = getattr(self, '_range_criterion', None)
if range_criterion is None:
range_criterion = {}
else:
range_criterion = dict(range_criterion)
new_identity_criterion = dict(getattr(self, '_identity_criterion', None) or
{})
new_identity_criterion.update(identity_criterion or {})
new_range_criterion = dict(getattr(self, '_range_criterion', None) or {})
new_range_criterion.update(range_criterion or {})
# Look at local properties and make it criterion properties
for property in criterion_property_list:
......@@ -574,11 +571,11 @@ class Predicate(XMLObject):
property_max = property + '_range_max'
if getattr(self, 'get%s' % convertToUpperCase(property), None) is not None\
and self.getProperty(property) is not None:
identity_criterion[property] = self.getProperty(property)
new_identity_criterion[property] = self.getProperty(property)
elif getattr(self, 'get%s' % convertToUpperCase(property_min), None) is not None:
min = self.getProperty(property_min)
max = self.getProperty(property_max)
range_criterion[property] = (min,max)
new_range_criterion[property] = (min,max)
# Return a new context with new properties, like if
# we have a predicate with local properties
new_self = self.asContext(
......@@ -586,8 +583,8 @@ class Predicate(XMLObject):
membership_criterion_base_category=new_membership_criterion_base_category_list,
multimembership_criterion_base_category=new_multimembership_criterion_base_category_list,
criterion_property_list=new_criterion_property_list,
_identity_criterion=identity_criterion,
_range_criterion=range_criterion)
_identity_criterion=new_identity_criterion,
_range_criterion=new_range_criterion)
return new_self
......
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