Commit 34e52cbd authored by Kazuhiko Shiozaki's avatar Kazuhiko Shiozaki

move comparison part to _compare() and use it in both explain() and compare().


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@30690 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent a80a5c22
......@@ -91,37 +91,76 @@ class FloatDivergenceTester(Predicate):
NOTE: should we provide compatibility here ?
"""
tested_property = self.getTestedProperty()
delivery_mvt = simulation_movement.getDeliveryValue()
delivery_mvt_property = delivery_mvt.getProperty(tested_property)
if simulation_movement.isPropertyRecorded(tested_property):
simulation_mvt_property = simulation_movement.getRecordedProperty(tested_property)
if isinstance(simulation_mvt_property, (list, tuple)):
simulation_mvt_property = simulation_mvt_property[0]
delivery_movement = simulation_movement.getDeliveryValue()
compare_result = self._compare(simulation_movement, delivery_movement)
if compare_result is None:
return None
else:
simulation_mvt_property = simulation_movement.getProperty(tested_property)
def getErrorMessage(message, mapping):
prevision_value, decision_value, message, mapping = compare_result
return DivergenceMessage(
# XXX do we still need divergence_scope ?
divergence_scope='property',
object_relative_url=delivery_mvt.getRelativeUrl(),
object_relative_url=delivery_movement.getRelativeUrl(),
simulation_movement=simulation_movement,
decision_value=delivery_mvt_property,
prevision_value=simulation_mvt_property,
tested_property=tested_property,
decision_value=decision_value,
prevision_value=prevision_value,
tested_property=self.getTestedProperty(),
message=message,
mapping=mapping
)
delta = delivery_mvt_property - simulation_mvt_property
def generateHashKey(self, movement):
"""
Returns a hash key which can be used to optimise the
matching algorithm between movements. The purpose
of this hash key is to reduce the size of lists of
movements which need to be compared using the compare
method (quadratic complexity).
If decision_movement is a simulation movement, use
the recorded properties instead of the native ones.
"""
raise NotImplementedError
def compare(self, prevision_movement, decision_movement):
"""
Returns True if simulation_movement and delivery_movement
match. Returns False else. The method is asymmetric and
the order of parameter matters. For example, a sourcing
rule may use a tester which makes sure that movements are
delivered no sooner than 2 weeks before production but
no later than the production date.
If decision_movement is a simulation movement, use
the recorded properties instead of the native ones.
prevision_movement -- a simulation movement (prevision)
decision_movement -- a delivery movement (decision)
"""
return (self._compare(prevision_movement, decision_movement) is None)
def _compare(self, prevision_movement, decision_movement):
"""
If prevision_movement and decision_movement dont match, it returns a
list : (prevision_value, decision_value, message, mapping)
"""
tested_property = self.getTestedProperty()
decision_value = decision_movement.getProperty(tested_property)
if prevision_movement.isPropertyRecorded(tested_property):
prevision_value = prevision_movement.getRecordedProperty(tested_property)
if isinstance(prevision_value, (list, tuple)):
prevision_value = prevision_value[0]
else:
prevision_value = prevision_movement.getProperty(tested_property)
delta = decision_value - prevision_value
# XXX we should use appropriate property sheets and getter methods
# for these properties.
absolute_tolerance_min = self.getProperty('quantity_range_min') or \
self.getProperty('quantity')
if absolute_tolerance_min is not None and \
delta < absolute_tolerance_min:
return getErrorMessage(
return (
prevision_value, decision_value,
'The difference of ${prperty_name} between decision and prevision is less than ${value}.',
dict(property_name=tested_property,
value=absolute_tolerance_min))
......@@ -129,7 +168,8 @@ class FloatDivergenceTester(Predicate):
self.getProperty('quantity')
if absolute_tolerance_max is not None and \
delta > absolute_tolerance_max:
return getErrorMessage(
return (
prevision_value, decision_value,
'The difference of ${prperty_name} between decision and prevision is larger than ${value}.',
dict(property_name=tested_property,
value=absolute_tolerance_max))
......@@ -137,12 +177,12 @@ class FloatDivergenceTester(Predicate):
tolerance_base = self.getProperty('tolerance_base')
if tolerance_base == 'currency_precision':
try:
precision = simulation_movement.getSectionValue().getPriceCurrencyValue().getQuantityPrecision()
precision = prevision_movement.getSectionValue().getPriceCurrencyValue().getQuantityPrecision()
base = 10 ** -precision
except AttributeError:
base = None
elif tolerance_base == 'quantity':
base = simulation_mvt_property
base = prevision_value
else:
base = None
if base is not None:
......@@ -151,12 +191,14 @@ class FloatDivergenceTester(Predicate):
if relative_tolerance_min is not None and \
delta < relative_tolerance_min * base:
if tolerance_base == 'price_currency':
return getErrorMessage(
return (
prevision_value, decision_value,
'The difference of ${prperty_name} between decision and prevision is less than ${value} times of the currency precision.',
dict(property_name=tested_property,
value=relative_tolerance_min))
else:
return getErrorMessage(
return (
prevision_value, decision_value,
'The difference of ${prperty_name} between decision and prevision is less than ${value} times of the prevision value.',
dict(property_name=tested_property,
value=relative_tolerance_min))
......@@ -165,51 +207,23 @@ class FloatDivergenceTester(Predicate):
if relative_tolerance_max is not None and \
delta < relative_tolerance_max * base:
if tolerance_base == 'price_currency':
return getErrorMessage(
return (
prevision_value, decision_value,
'The difference of ${prperty_name} between decision and prevision is less than ${value} times of the currency precision.',
dict(property_name=tested_property,
value=relative_tolerance_max))
else:
return getErrorMessage(
return (
prevision_value, decision_value,
'The difference of ${prperty_name} between decision and prevision is less than ${value} times of the prevision value.',
dict(property_name=tested_property,
value=relative_tolerance_max))
return None
# XXX the followings are not treated yet:
# * decimal_alignment_enabled
# * decimal_rounding_option
# * decimal_exponent
def generateHashKey(self, movement):
"""
Returns a hash key which can be used to optimise the
matching algorithm between movements. The purpose
of this hash key is to reduce the size of lists of
movements which need to be compared using the compare
method (quadratic complexity).
If decision_movement is a simulation movement, use
the recorded properties instead of the native ones.
"""
raise NotImplementedError
def compare(self, prevision_movement, decision_movement):
"""
Returns True if simulation_movement and delivery_movement
match. Returns False else. The method is asymmetric and
the order of parameter matters. For example, a sourcing
rule may use a tester which makes sure that movements are
delivered no sooner than 2 weeks before production but
no later than the production date.
If decision_movement is a simulation movement, use
the recorded properties instead of the native ones.
prevision_movement -- a simulation movement (prevision)
decision_movement -- a delivery movement (decision)
"""
raise NotImplementedError
def update(self, prevision_movement, decision_movement):
"""
Updates decision_movement with properties from
......
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