[Erp5-report] r17756 - /erp5/trunk/products/ERP5/Document/

nobody at svn.erp5.org nobody at svn.erp5.org
Thu Nov 22 18:47:29 CET 2007


Author: alex
Date: Thu Nov 22 18:47:28 2007
New Revision: 17756

URL: http://svn.erp5.org?rev=17756&view=rev
Log:
* _isTreeDelivered method moved from Rule to AppliedRule and
  SimulationMovement
* added transactional variable based cache to _isTreeDelivered
* activate and flush _isTreeDelivered cache in SimulationMovement.expand and
  AppliedRule.expand (so that it's only active when calling expand, and
  flushed afterwards, to prevent issues if we call expand in the same
  transaction as a builder)
* modified SimulationMovement.expand behaviour, so that it removes applied
  rules that no longer test(), and add new ones, if no movment in the applied
  rule sub tree is linked to a delivery

Modified:
    erp5/trunk/products/ERP5/Document/AppliedRule.py
    erp5/trunk/products/ERP5/Document/DeliveryRule.py
    erp5/trunk/products/ERP5/Document/OrderRule.py
    erp5/trunk/products/ERP5/Document/Rule.py
    erp5/trunk/products/ERP5/Document/SimulationMovement.py

Modified: erp5/trunk/products/ERP5/Document/AppliedRule.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/AppliedRule.py?rev=17756&r1=17755&r2=17756&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/AppliedRule.py (original)
+++ erp5/trunk/products/ERP5/Document/AppliedRule.py Thu Nov 22 18:47:28 2007
@@ -31,8 +31,12 @@
 from Products.ERP5Type import Permissions, PropertySheet, Constraint, Interface
 from Products.ERP5Type.XMLObject import XMLObject
 from Products.ERP5Type.PsycoWrapper import psyco
+from Products.ERP5Type.TransactionalVariable import getTransactionalVariable
 
 from zLOG import LOG
+
+TREE_DELIVERED_CACHE_KEY = 'AppliedRule._isTreeDelivered_cache'
+TREE_DELIVERED_CACHE_ENABLED = 'TREE_DELIVERED_CACHE_ENABLED'
 
 class AppliedRule(XMLObject):
     """
@@ -89,6 +93,14 @@
         An applied rule can be expanded only if its parent movement
         is expanded.
       """
+      tv = getTransactionalVariable(self)
+      cache = tv.setdefault(TREE_DELIVERED_CACHE_KEY, {})
+      cache_enabled = cache.get(TREE_DELIVERED_CACHE_ENABLED, 0)
+
+      # enable cache
+      if not cache_enabled:
+        cache[TREE_DELIVERED_CACHE_ENABLED] = 1
+
       rule = self.getSpecialiseValue()
       if rule is not None:
         if self.isRootAppliedRule():
@@ -102,6 +114,13 @@
 #                                 "recursiveImmediateReindexObject"]).\
 #                                   notifySimulationChange(rule._v_notify_dict)
 
+      # disable and clear cache
+      if not cache_enabled:
+        try:
+          del tv[TREE_DELIVERED_CACHE_KEY]
+        except KeyError:
+          pass
+
     security.declareProtected(Permissions.ModifyPortalContent, 'solve')
     def solve(self, solution_list):
       """
@@ -193,3 +212,33 @@
                delivery_url)
         else:
           delivery_value.notifySimulationChange()
+
+    def _isTreeDelivered(self):
+      """
+      Checks if submovements of this applied rule (going down the complete
+      simulation tree) have a delivery relation.
+      Returns True if at least one is delivered, False if none of them are.
+
+      see SimulationMovement._isTreeDelivered
+      """
+      tv = getTransactionalVariable(self)
+      cache = tv.setdefault(TREE_DELIVERED_CACHE_KEY, {})
+      cache_enabled = cache.get(TREE_DELIVERED_CACHE_ENABLED, 0)
+
+      def getTreeDelivered(applied_rule):
+        for movement in applied_rule.objectValues():
+          if movement._isTreeDelivered():
+            return True
+        return False
+
+      rule_key = self.getRelativeUrl()
+      if cache_enabled:
+        try:
+          return cache[rule_key]
+        except:
+          result = getTreeDelivered(self)
+          cache[rule_key] = result
+          return result
+      else:
+        return getTreeDelivered(self)
+

Modified: erp5/trunk/products/ERP5/Document/DeliveryRule.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/DeliveryRule.py?rev=17756&r1=17755&r2=17756&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/DeliveryRule.py (original)
+++ erp5/trunk/products/ERP5/Document/DeliveryRule.py Thu Nov 22 18:47:28 2007
@@ -85,7 +85,7 @@
             (delivery.getPortalDraftOrderStateList() + \
             delivery.getPortalPlannedOrderStateList()):
           movement_delivery = movement.getDeliveryValue()
-          if not self._isTreeDelivered([movement], ignore_first=1) and \
+          if not movement._isTreeDelivered(ignore_first=1) and \
               movement_delivery not in delivery_movement_list:
             applied_rule._delObject(movement.getId())
           else:
@@ -103,7 +103,7 @@
             # We are on a line
             new_id = deliv_mvt.getId()
           else:
-            # Weare on a cell
+            # We are on a cell
             new_id = "%s_%s" % (deliv_mvt.getParentId(), deliv_mvt.getId())
           # Generate the simulation deliv_mvt
           # XXX Hardcoded value

Modified: erp5/trunk/products/ERP5/Document/OrderRule.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/OrderRule.py?rev=17756&r1=17755&r2=17756&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/OrderRule.py (original)
+++ erp5/trunk/products/ERP5/Document/OrderRule.py Thu Nov 22 18:47:28 2007
@@ -86,7 +86,7 @@
             order.getPortalReservedInventoryStateList() and
             not movement.getLastExpandSimulationState() in
             order.getPortalCurrentInventoryStateList()) and \
-            not self._isTreeDelivered([movement]):
+            not movement._isTreeDelivered():
 
           movement_order = movement.getOrderValue()
           if movement_order in order_movement_list:

Modified: erp5/trunk/products/ERP5/Document/Rule.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/Rule.py?rev=17756&r1=17755&r2=17756&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/Rule.py (original)
+++ erp5/trunk/products/ERP5/Document/Rule.py Thu Nov 22 18:47:28 2007
@@ -220,21 +220,6 @@
     return 1
 
 #### Helpers
-  def _isTreeDelivered(self, movement_list, ignore_first=0):
-    """
-    returns 1 if the movement or any of its child is linked to a delivery
-    """
-    child_movement_list = []
-    for movement in movement_list:
-      if not ignore_first and len(movement.getDeliveryList()) > 0:
-        return 1
-      else:
-        for applied_rule in movement.objectValues():
-          child_movement_list = applied_rule.objectValues()
-    if len(child_movement_list) == 0:
-      return 0
-    return self._isTreeDelivered(child_movement_list)
-
   def _getCurrentMovementList(self, applied_rule, **kw):
     """
     Returns the list of current children of the applied rule, sorted in 3
@@ -263,7 +248,7 @@
       if movement.isFrozen():
         immutable_movement_list.append(movement)
       else:
-        if self._isTreeDelivered([movement]):
+        if movement._isTreeDelivered():
           mutable_movement_list.append(movement)
         else:
           deletable_movement_list.append(movement)

Modified: erp5/trunk/products/ERP5/Document/SimulationMovement.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/SimulationMovement.py?rev=17756&r1=17755&r2=17756&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/SimulationMovement.py (original)
+++ erp5/trunk/products/ERP5/Document/SimulationMovement.py Thu Nov 22 18:47:28 2007
@@ -31,12 +31,15 @@
 from Products.CMFCore.utils import getToolByName
 
 from Products.ERP5Type import Permissions, PropertySheet, Constraint, Interface
+from Products.ERP5Type.TransactionalVariable import getTransactionalVariable
 
 from Products.ERP5.Document.Movement import Movement
 
 from zLOG import LOG
 
 from Acquisition import aq_base
+
+from AppliedRule import TREE_DELIVERED_CACHE_KEY, TREE_DELIVERED_CACHE_ENABLED
 
 # XXX Do we need to create groups ? (ie. confirm group include confirmed, getting_ready and ready
 
@@ -209,36 +212,57 @@
   security.declareProtected(Permissions.ModifyPortalContent, 'expand')
   def expand(self, force=0, **kw):
     """
-      Parses all existing applied rules and make sure they apply.
-      Checks other possible rules and starts expansion process
-      (instanciates rule and calls expand on rule)
-
-      Only movements which applied rule parent is expanded can
-      be expanded.
-    """
-    # XXX Default behaviour is not to expand if it has already been
-    # expanded, but some rules are configuration rules and need to be
-    # reexpanded  each time, because the rule apply only if predicates
-    # are true, then this kind of rule must always be tested. Currently,
-    # we know that invoicing rule acts like this, and that it comes after
-    # invoice or invoicing_rule, so we if we come from invoince rule or
-    # invoicing rule, we always expand regardless of the causality state.
-    if ((self.getParentValue().getSpecialiseReference() not in
-         ('default_invoicing_rule', 'default_invoice_rule')
-         and self.getCausalityState() == 'expanded' ) or \
-         len(self.objectIds()) != 0):
-      # Reexpand
-      for my_applied_rule in self.objectValues():
-        my_applied_rule.expand(force=force,**kw)
-    else:
-      portal_rules = getToolByName(self, 'portal_rules')
-      # Parse each rule and test if it applies
-      for rule in portal_rules.searchRuleList(self):
-        rule.constructNewAppliedRule(self, **kw)
-      for my_applied_rule in self.objectValues() :
-        my_applied_rule.expand(force=force,**kw)
-      # Set to expanded
-      self.setCausalityState('expanded')
+    Checks all existing applied rules and make sure they still apply.
+    Checks for other possible rules and starts expansion process (instanciates
+    applied rules and calls expand on them).
+
+    First get all applicable rules,
+    then, delete all applied rules that no longer match and are not linked to
+    a delivery,
+    finally, apply new rules if no rule with the same type is already applied.
+    """
+    portal_rules = getToolByName(self, 'portal_rules')
+
+    tv = getTransactionalVariable(self)
+    cache = tv.setdefault(TREE_DELIVERED_CACHE_KEY, {})
+    cache_enabled = cache.get(TREE_DELIVERED_CACHE_ENABLED, 0)
+
+    # enable cache
+    if not cache_enabled:
+      cache[TREE_DELIVERED_CACHE_ENABLED] = 1
+
+    applied_rule_dict = {}
+    applicable_rule_dict = {}
+    for rule in portal_rules.searchRuleList(self, sort_on='version',
+        sort_order='descending'):
+      ref = rule.getReference()
+      if ref and ref not in applicable_rule_dict.iterkeys():
+        applicable_rule_dict[ref] = rule
+
+    for applied_rule in self.objectValues():
+      rule = applied_rule.getSpecialiseValue()
+      if not applied_rule._isTreeDelivered() and not rule.test(self):
+        self._delObject(applied_rule.getId())
+      else:
+        applied_rule_dict[rule.getPortalType()] = applied_rule
+
+    for rule in applicable_rule_dict.itervalues():
+      rule_type = rule.getPortalType()
+      if rule_type not in applied_rule_dict.iterkeys():
+        applied_rule = rule.constructNewAppliedRule(self, **kw)
+        applied_rule_dict[rule_type] = applied_rule
+
+    self.setCausalityState('expanded')
+    # expand
+    for applied_rule in applied_rule_dict.itervalues():
+      applied_rule.expand(force=force, **kw)
+
+    # disable and clear cache
+    if not cache_enabled:
+      try:
+        del tv[TREE_DELIVERED_CACHE_KEY]
+      except KeyError:
+        pass
 
   security.declareProtected(Permissions.ModifyPortalContent, 'diverge')
   def diverge(self):
@@ -480,3 +504,38 @@
   #                                         'recursiveImmediateReindexObject']))
   #    activity.edit()
 
+  def _isTreeDelivered(self, ignore_first=0):
+    """
+    checks if subapplied rules  of this movement (going down the complete
+    simulation tree) have a child with a delivery relation.
+    Returns True if at least one is delivered, False if none of them are.
+
+    see AppliedRule._isTreeDelivered
+    """
+    tv = getTransactionalVariable(self)
+    cache = tv.setdefault(TREE_DELIVERED_CACHE_KEY, {})
+    cache_enabled = cache.get(TREE_DELIVERED_CACHE_ENABLED, 0)
+
+    def getTreeDelivered(movement, ignore_first=0):
+      if ignore_first:
+        if len(movement.getDeliveryList()) > 0:
+          return True
+      for applied_rule in movement.objectValues():
+        if applied_rule._isTreeDelivered():
+          return True
+      return False
+
+    if ignore_first:
+      rule_key = (self.getRelativeUrl(), 1)
+    else:
+      rule_key = self.getRelativeUrl()
+    if cache_enabled:
+      try:
+        return cache[rule_key]
+      except:
+        result = getTreeDelivered(self, ignore_first=ignore_first)
+        cache[rule_key] = result
+        return result
+    else:
+      return getTreeDelivered(self, ignore_first=ignore_first)
+




More information about the Erp5-report mailing list