Commit 69e2ce64 authored by Julien Muchembled's avatar Julien Muchembled

Several fixes & improvements to migration of simulation trees

- Handle splitted SM, including those at root.
- Allow caller to drop root SM (via 'get_matching_key').
- Fix detection of draft trees that are out of sync
  (cf commit 200bf7cb)
parent 8d7e9851
...@@ -324,8 +324,13 @@ class AppliedRule(XMLObject, ExplainableMixin): ...@@ -324,8 +324,13 @@ class AppliedRule(XMLObject, ExplainableMixin):
# Delivery is/was not is draft state # Delivery is/was not is draft state
order_dict = {} order_dict = {}
old_dict = {} old_dict = {}
for sm in list(self.objectValues()): # Caller may want to drop duplicate SM, like a unbuilt SM if there's
old_dict[sm.getOrder() or sm.getDelivery()] = sm_dict = {} # already a built one, or one with no quantity. So first call
# 'get_matching_key' on SM that would be kept. 'get_matching_key' would
# remember them and returns None for duplicates.
sort_sm = lambda x: (not x.getDelivery(), not x.getQuantity(), x.getId())
for sm in sorted(self.objectValues(), key=sort_sm):
sm_dict = old_dict.setdefault(sm.getOrder() or sm.getDelivery(), {})
recurse_list = deque(({get_matching_key(sm): (sm,)},)) recurse_list = deque(({get_matching_key(sm): (sm,)},))
while recurse_list: while recurse_list:
for k, x in recurse_list.popleft().iteritems(): for k, x in recurse_list.popleft().iteritems():
...@@ -333,6 +338,8 @@ class AppliedRule(XMLObject, ExplainableMixin): ...@@ -333,6 +338,8 @@ class AppliedRule(XMLObject, ExplainableMixin):
continue continue
if len(x) > 1: if len(x) > 1:
x = [x for x in x if x.getDelivery() or x.getQuantity()] x = [x for x in x if x.getDelivery() or x.getQuantity()]
if len(x) > 1:
x.sort(key=sort_sm)
sm_dict.setdefault(k, []).extend(x) sm_dict.setdefault(k, []).extend(x)
for x in x: for x in x:
r = {} r = {}
...@@ -353,8 +360,11 @@ class AppliedRule(XMLObject, ExplainableMixin): ...@@ -353,8 +360,11 @@ class AppliedRule(XMLObject, ExplainableMixin):
# does not see the simulated movements we've just deleted. # does not see the simulated movements we've just deleted.
if delivery.isSimulated(): if delivery.isSimulated():
break break
# Do not try to keep simulation tree for draft delivery
# if it was already out of sync.
if delivery.getSimulationState() in draft_state_list and \ if delivery.getSimulationState() in draft_state_list and \
any(x not in old_dict for x in delivery.getMovementList()): any(x.getRelativeUrl() not in old_dict
for x in delivery.getMovementList()):
break break
if root_rule: if root_rule:
self.setSpecialise(root_rule) self.setSpecialise(root_rule)
...@@ -376,7 +386,10 @@ class AppliedRule(XMLObject, ExplainableMixin): ...@@ -376,7 +386,10 @@ class AppliedRule(XMLObject, ExplainableMixin):
# currently expanded applied rule. We first try to preserve same # currently expanded applied rule. We first try to preserve same
# tree structure (new & old parent SM match), then we look for an # tree structure (new & old parent SM match), then we look for an
# old possible parent that is in the same branch. # old possible parent that is in the same branch.
old_parent = old_dict[new_parent] try:
old_parent = old_dict[new_parent]
except KeyError:
old_parent = simulation_tool
best_dict = {} best_dict = {}
for old_sm in sm_list: for old_sm in sm_list:
parent = old_sm.getParentValue().getParentValue() parent = old_sm.getParentValue().getParentValue()
...@@ -398,24 +411,31 @@ class AppliedRule(XMLObject, ExplainableMixin): ...@@ -398,24 +411,31 @@ class AppliedRule(XMLObject, ExplainableMixin):
# We may have several old matching SM, e.g. in case of split. # We may have several old matching SM, e.g. in case of split.
for old_sm in sm_list: for old_sm in sm_list:
movement = old_sm.getDeliveryValue() movement = old_sm.getDeliveryValue()
if sm is None:
sm = context.newContent(portal_type=rule.movement_type)
sm.__dict__ = dict(kw, **sm.__dict__)
order_dict[sm] = sm_dict
if delivery: if delivery:
assert movement.getRelativeUrl() == delivery assert movement.getRelativeUrl() == delivery
elif movement is not None: elif movement is not None:
if sm is None:
sm = context.newContent(portal_type=rule.movement_type)
sm.__dict__ = dict(kw, **sm.__dict__)
order_dict[sm] = sm_dict
sm._setDeliveryValue(movement) sm._setDeliveryValue(movement)
delivery_set.add(sm.getExplanationValue()) delivery_set.add(sm.getExplanationValue())
recorded_property_dict = {} recorded_property_dict = {}
edit_kw = {} edit_kw = {}
kw['quantity'] = 0
for tester in rule._getUpdatingTesterList(): for tester in rule._getUpdatingTesterList():
old = get_original_property_dict(tester, old_sm, sm, movement) old = get_original_property_dict(tester, old_sm, sm, movement)
if old is not None: if old is not None:
new = tester.getUpdatablePropertyDict(sm, movement) new = tester.getUpdatablePropertyDict(sm, movement)
if old != new: if old != new:
recorded_property_dict.update(new)
edit_kw.update(old) edit_kw.update(old)
if 'quantity' in new and old_sm is not sm_list[-1]:
quantity = new.pop('quantity')
kw['quantity'] = quantity - old.pop('quantity')
if new != old or sm.quantity != quantity:
raise NotImplementedError # quantity_unit/efficiency ?
else:
recorded_property_dict.update(new)
if recorded_property_dict: if recorded_property_dict:
sm._recorded_property_dict = PersistentMapping( sm._recorded_property_dict = PersistentMapping(
recorded_property_dict) recorded_property_dict)
...@@ -423,6 +443,9 @@ class AppliedRule(XMLObject, ExplainableMixin): ...@@ -423,6 +443,9 @@ class AppliedRule(XMLObject, ExplainableMixin):
old_dict[sm] = old_sm old_dict[sm] = old_sm
sm = None sm = None
deleted = old_dict.items() deleted = old_dict.items()
for delivery, sm_dict in deleted:
if not sm_dict:
del old_dict[delivery]
from Products.ERP5.mixin.movement_collection_updater import \ from Products.ERP5.mixin.movement_collection_updater import \
MovementCollectionUpdaterMixin as mixin MovementCollectionUpdaterMixin as mixin
# Patch is already protected by WorkflowMethod.disable lock. # Patch is already protected by WorkflowMethod.disable lock.
......
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