Commit 009dd3c7 authored by Jérome Perrin's avatar Jérome Perrin

simulation: introduce Rule.getSimulationMovementSimulationState

See merge request !2001
parents 22d3da6e 5e21f77f
Pipeline #37713 failed with stage
in 0 seconds
...@@ -291,7 +291,10 @@ class TestBPMDummyDeliveryMovementMixin(TestBPMMixin): ...@@ -291,7 +291,10 @@ class TestBPMDummyDeliveryMovementMixin(TestBPMMixin):
# first level rule with simulation movement # first level rule with simulation movement
self.applied_rule = self.portal.portal_simulation.newContent( self.applied_rule = self.portal.portal_simulation.newContent(
portal_type='Applied Rule', causality_value=order) portal_type='Applied Rule',
causality_value=order,
specialise_value=self.portal.portal_rules.new_order_root_simulation_rule,
)
def setTestClassProperty(prefix, property_name, document): def setTestClassProperty(prefix, property_name, document):
if prefix: if prefix:
...@@ -316,7 +319,9 @@ class TestBPMDummyDeliveryMovementMixin(TestBPMMixin): ...@@ -316,7 +319,9 @@ class TestBPMDummyDeliveryMovementMixin(TestBPMMixin):
# second level rule with simulation movement # second level rule with simulation movement
document = setTestClassProperty(prefix, 'delivery_rule', document = setTestClassProperty(prefix, 'delivery_rule',
document.newContent( document.newContent(
portal_type='Applied Rule')) portal_type='Applied Rule',
specialise_value=self.portal.portal_rules.new_delivery_simulation_rule,
))
document = setTestClassProperty(prefix, 'delivery_simulation_movement', document = setTestClassProperty(prefix, 'delivery_simulation_movement',
document.newContent( document.newContent(
portal_type='Simulation Movement', portal_type='Simulation Movement',
...@@ -329,7 +334,9 @@ class TestBPMDummyDeliveryMovementMixin(TestBPMMixin): ...@@ -329,7 +334,9 @@ class TestBPMDummyDeliveryMovementMixin(TestBPMMixin):
# third level rule with simulation movement # third level rule with simulation movement
document = setTestClassProperty(prefix, 'invoicing_rule', document = setTestClassProperty(prefix, 'invoicing_rule',
document.newContent( document.newContent(
portal_type='Applied Rule')) portal_type='Applied Rule',
specialise_value=self.portal.portal_rules.new_invoice_simulation_rule,
))
document = setTestClassProperty(prefix, document = setTestClassProperty(prefix,
'invoicing_simulation_movement', 'invoicing_simulation_movement',
document.newContent( document.newContent(
......
...@@ -36,8 +36,6 @@ from Products.ERP5Type.Utils import ensure_list ...@@ -36,8 +36,6 @@ from Products.ERP5Type.Utils import ensure_list
from erp5.component.document.Movement import Movement from erp5.component.document.Movement import Movement
from erp5.component.module.ExpandPolicy import policy_dict, TREE_DELIVERED_CACHE_KEY from erp5.component.module.ExpandPolicy import policy_dict, TREE_DELIVERED_CACHE_KEY
from zLOG import LOG, WARNING
from Products.ERP5.mixin.property_recordable import PropertyRecordableMixin from Products.ERP5.mixin.property_recordable import PropertyRecordableMixin
from erp5.component.mixin.ExplainableMixin import ExplainableMixin from erp5.component.mixin.ExplainableMixin import ExplainableMixin
from erp5.component.interface.IExpandable import IExpandable from erp5.component.interface.IExpandable import IExpandable
...@@ -82,22 +80,6 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin): ...@@ -82,22 +80,6 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin):
- delivered (the movement is now archived in a delivery) - delivered (the movement is now archived in a delivery)
The simulation worklow uses some variables, which are
set by the template
- is_order_required
- is_delivery_required
XX
- is_problem_checking_required ?
Other flag
(forzen flag)
NEW: we do not use DCWorklow so that the simulation process
can be as much as possible independent of a Zope / CMF implementation.
""" """
meta_type = 'ERP5 Simulation Movement' meta_type = 'ERP5 Simulation Movement'
portal_type = 'Simulation Movement' portal_type = 'Simulation Movement'
...@@ -144,13 +126,8 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin): ...@@ -144,13 +126,8 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin):
def getSimulationState(self, id_only=1): def getSimulationState(self, id_only=1):
"""Returns the current state in simulation """Returns the current state in simulation
Inherit from delivery or parent (using a conversion table to make orders Inherit from delivery when built, otherwise, let the rule decide.
planned when parent is confirmed).
In the case of simulation coming from an item, the simulation state is
delegated to the item.
XXX: movements in zero stock rule can not acquire simulation state
""" """
delivery = self.getDeliveryValue() delivery = self.getDeliveryValue()
if delivery is not None: if delivery is not None:
...@@ -161,18 +138,9 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin): ...@@ -161,18 +138,9 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin):
return order.getSimulationState() return order.getSimulationState()
applied_rule = self.getParentValue() applied_rule = self.getParentValue()
parent = applied_rule.getParentValue() rule = applied_rule.getSpecialiseValue()
try: if rule is not None:
if isinstance(parent, SimulationMovement): return rule.getSimulationMovementSimulationState(self)
return parent_to_movement_simulation_state[parent.getSimulationState()]
getState = applied_rule.getCausalityValue() \
.aq_explicit.getSimulationMovementSimulationState
except (AttributeError, KeyError):
LOG('SimulationMovement.getSimulationState', WARNING,
'Could not acquire simulation state from %s'
% self.getRelativeUrl(), error=True)
else:
return getState(self)
security.declareProtected( Permissions.AccessContentsInformation, security.declareProtected( Permissions.AccessContentsInformation,
'getTranslatedSimulationStateTitle') 'getTranslatedSimulationStateTitle')
......
...@@ -41,7 +41,7 @@ class IRule(IMovementCollectionUpdater): ...@@ -41,7 +41,7 @@ class IRule(IMovementCollectionUpdater):
""" """
Create a new applied rule in the context. Create a new applied rule in the context.
An applied rule is an instanciation of a Rule. The applied rule is An applied rule is an instantiation of a Rule. The applied rule is
linked to the Rule through the `specialise` relation. linked to the Rule through the `specialise` relation.
context -- usually, a parent simulation movement of the context -- usually, a parent simulation movement of the
...@@ -56,7 +56,7 @@ class IRule(IMovementCollectionUpdater): ...@@ -56,7 +56,7 @@ class IRule(IMovementCollectionUpdater):
applied rule. applied rule.
At expand time, we must replace or compensate certain At expand time, we must replace or compensate certain
properties. However, if some properties were overwriten properties. However, if some properties were overwritten
by a decision (ie. a resource if changed), then we by a decision (ie. a resource if changed), then we
should not try to compensate such a decision. The principles should not try to compensate such a decision. The principles
of compensation are implemented through of compensation are implemented through
...@@ -73,3 +73,8 @@ class IRule(IMovementCollectionUpdater): ...@@ -73,3 +73,8 @@ class IRule(IMovementCollectionUpdater):
Available policies: immediate, deferred, vertical_time_bound Available policies: immediate, deferred, vertical_time_bound
""" """
def getSimulationMovementSimulationState(simulation_movement):
"""
Compute the simulation state of this simulation movement.
"""
...@@ -26,16 +26,22 @@ ...@@ -26,16 +26,22 @@
# #
############################################################################## ##############################################################################
import logging
import zope.interface import zope.interface
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type.Globals import InitializeClass from Products.ERP5Type.Globals import InitializeClass
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
from Products.ERP5Type.Core.Predicate import Predicate from Products.ERP5Type.Core.Predicate import Predicate
from erp5.component.module.ExpandPolicy import policy_dict from erp5.component.module.ExpandPolicy import policy_dict
from erp5.component.document.SimulationMovement import SimulationMovement, parent_to_movement_simulation_state
from erp5.component.interface.IRule import IRule from erp5.component.interface.IRule import IRule
from erp5.component.interface.IDivergenceController import IDivergenceController from erp5.component.interface.IDivergenceController import IDivergenceController
from erp5.component.interface.IMovementCollectionUpdater import IMovementCollectionUpdater from erp5.component.interface.IMovementCollectionUpdater import IMovementCollectionUpdater
logger = logging.getLogger(__name__)
def _compare(tester_list, prevision_movement, decision_movement): def _compare(tester_list, prevision_movement, decision_movement):
for tester in tester_list: for tester in tester_list:
if not tester.compare(prevision_movement, decision_movement): if not tester.compare(prevision_movement, decision_movement):
...@@ -108,7 +114,7 @@ class RuleMixin(Predicate): ...@@ -108,7 +114,7 @@ class RuleMixin(Predicate):
policy_dict[expand_policy](**kw).expand(self, applied_rule) policy_dict[expand_policy](**kw).expand(self, applied_rule)
def _expandNow(self, maybe_expand, applied_rule): def _expandNow(self, maybe_expand, applied_rule):
# Update moveme-nts # Update movements
# NOTE-JPS: it is OK to make rounding a standard parameter of rules # NOTE-JPS: it is OK to make rounding a standard parameter of rules
# although rounding in simulation is not recommended at all # although rounding in simulation is not recommended at all
self.updateMovementCollection(applied_rule, self.updateMovementCollection(applied_rule,
...@@ -127,6 +133,36 @@ class RuleMixin(Predicate): ...@@ -127,6 +133,36 @@ class RuleMixin(Predicate):
""" """
return not movement.getDelivery() return not movement.getDelivery()
security.declareProtected(Permissions.AccessContentsInformation,
'getSimulationMovementSimulationState')
def getSimulationMovementSimulationState(self, simulation_movement):
"""
Compute the simulation state of this simulation movement.
Inherit from parent movement, using a conversion table to make
orders planned when parent is confirmed.
In the case of simulation coming from an item, the simulation state is
delegated to the item.
This method can be overridden in custom rule class to generate movements
with a different simulation state.
"""
applied_rule = simulation_movement.getParentValue()
parent_simulation_movement = applied_rule.getParentValue()
try:
if isinstance(parent_simulation_movement, SimulationMovement):
return parent_to_movement_simulation_state[parent_simulation_movement.getSimulationState()]
getSimulationMovementSimulationState = applied_rule.getCausalityValue() \
.aq_explicit.getSimulationMovementSimulationState
except (AttributeError, KeyError):
logger.warning(
'getSimulationState: Could not acquire simulation state from %s',
simulation_movement,
exc_info=True)
else:
return getSimulationMovementSimulationState(simulation_movement)
# Implementation of IDivergenceController # XXX-JPS move to IDivergenceController only mixin for # Implementation of IDivergenceController # XXX-JPS move to IDivergenceController only mixin for
security.declareProtected( Permissions.AccessContentsInformation, security.declareProtected( Permissions.AccessContentsInformation,
'isDivergent') 'isDivergent')
......
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