From 8a391f2660ed0cdc51ef8f4b5abb1872d4275dc1 Mon Sep 17 00:00:00 2001
From: Jean-Paul Smets <jp@nexedi.com>
Date: Mon, 31 Jan 2005 10:33:42 +0000
Subject: [PATCH] Major rewrite

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@2352 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 .../ERP5/Document/InvoiceTransactionRule.py   | 136 +++++++-----------
 1 file changed, 55 insertions(+), 81 deletions(-)

diff --git a/product/ERP5/Document/InvoiceTransactionRule.py b/product/ERP5/Document/InvoiceTransactionRule.py
index 7208d870a6..75a24d8d01 100755
--- a/product/ERP5/Document/InvoiceTransactionRule.py
+++ b/product/ERP5/Document/InvoiceTransactionRule.py
@@ -37,8 +37,10 @@ from zLOG import LOG
 
 class InvoiceTransactionRule(Rule, XMLMatrix):
     """
-      Invoice Transaction Rule object make sure an Invoice in the similation
-      is consistent with the real invoice
+      Invoice Transaction Rule object generates accounting movements
+      for each invoice movement based on category membership and
+      other predicated. Template accounting movements are stored
+      in cells inside an instance of the InvoiceTransactionRule.
 
       WARNING: what to do with movement split ?
     """
@@ -61,16 +63,53 @@ class InvoiceTransactionRule(Rule, XMLMatrix):
                       , PropertySheet.DublinCore
                       )
 
+    def _getMatchingCell(self, movement):
+      """
+        Browse all cells and test them until match found
+      """
+      for cell in self.getCellValueList(base_id = 'vat_per_region'):
+        if cell.test(movement):
+          LOG('Found Cell' ,0, cell.getRelativeUrl())
+          return cell
+      return None          
+    
+    def _getMatchingCell1(self, movement):
+      """
+        Browse all predicates and make sur all dimensions match
+        An alternate implementation left as example
+      """
+      dimension_dict = {}   # Possible dimensions
+      tdimension_dict = {}  # Dimensions which responded 1 on test
+      for predicate in self.contentValues():        
+        if predicate.is_predicate:
+          if predicate.getStringIndex() not in tdimension_dict.keys() \
+              and predicate.test(movement):
+            tdimension_dict[predicate.getStringIndex()] = predicate.getRelativeUrl()
+          dimension_dict[predicate.getStringIndex()] = 1
+      if len(dimension_dict) == len(tdimension_dict):
+        # If all dimesions are satisfied, then return 1
+        cell_key = []
+        for matrix_range_item in self.getCellRange(base_id = 'vat_per_region'):
+          for range_item in matrix_range_item:
+            if range_item in tdimension_dict.values():
+              cell_key.append(range_item)
+              break # Just in case, make sure only one range_item per matrix_range_item
+        kwd = {'base_id': 'vat_per_region'}                      
+        return self.getCell(*cell_key, **kwd)
+      return None          
+                    
     def test(self, movement):
       """
         Tests if the rule (still) applies
       """
       # An invoice transaction rule applies when the movement's parent is an invoice rule
-      parent = movement.getParent()
-      parent_rule_id = parent.getSpecialiseId()
-      if ('default_invoice_rule' in parent_rule_id) \
-        or ('default_invoicing_rule' in parent_rule_id) :
-        return 1
+      parent = movement.getParentValue()
+      parent_rule_value = parent.getSpecialiseValue()
+      if parent_rule_value is None:
+        return 0        
+      if parent_rule_value.getPortalType() in ('Invoicing Rule', 'Invoice Rule'):
+        if self._getMatchingCell(movement) is not None:
+          return 1
       return 0
 
     # Simulation workflow
@@ -87,41 +126,19 @@ class InvoiceTransactionRule(Rule, XMLMatrix):
 
       invoice_transaction_line_type = 'Simulation Movement'
 
-      # First, we need the region
-      my_order = applied_rule.getRootAppliedRule().getCausalityValue()
-      
-      my_destination = my_order.getDestinationValue() # maybe DestinationSection instead of Destination
-      my_destination_address = my_destination.get('default_address')
-      if my_destination_address is None :
-        my_destination_region = None
-        LOG('InvoiceTransactionRule.expand :', 0, 'Problem : destination_region is None')
-      else :
-        my_destination_region = my_destination_address.getRegionValue()
-      #LOG('InvoiceTransactionRule.expand :', 0, repr(( 'region', my_order, my_destination, my_destination_address, my_destination_region, )))
-      # Then, the product line
-      my_invoice_line_simulation = applied_rule.getParent()
-      my_resource = my_invoice_line_simulation.getResourceValue()
-      if my_resource is None :
-        my_product_line = None
-        LOG('InvoiceTransactionRule.expand :', 0, 'Problem : product_line is None')
-      else :
-        my_product_line = my_resource.getProductLineValue()
-      #LOG('InvoiceTransactionRule.expand :', 0, repr(( 'product_line', my_invoice_line_simulation, my_resource, my_product_line, )))
-      # Finally, the InvoiceTransactionRule Matrix
-      my_invoice_transaction_rule = applied_rule.getSpecialiseValue()
+      # First, get the simulation movement we were expanded from
+      my_invoice_line_simulation = applied_rule.getParentValue()
 
       # Next, we can try to expand the rule
       if force or \
          (applied_rule.getLastExpandSimulationState() not in self.getPortalReservedInventoryStateList() and \
          applied_rule.getLastExpandSimulationState() not in self.getPortalCurrentInventoryStateList()):
 
-        # get the corresponding Cell
-        new_kw = (('product_line', my_product_line), ('region', my_destination_region))
-        my_cell = my_invoice_transaction_rule.getCellByPredicate(*new_kw) #XXX WARNING ! : my_cell can be None
-        #LOG('InvoiceTransactionRule.expand :', 0, repr(( 'cell', my_cell, my_invoice_transaction_rule.contentValues(), len(my_invoice_transaction_rule.searchFolder()), )))
+        # Find a matching cell
+        my_cell = self._getMatchingCell(my_invoice_line_simulation)
 
         if my_cell is not None :
-          my_cell_transaction_id_list = map(lambda x : x.getId(), my_cell.contentValues())
+          my_cell_transaction_id_list = my_cell.contentIds()
         else :
           my_cell_transaction_id_list = []
 
@@ -130,7 +147,7 @@ class InvoiceTransactionRule(Rule, XMLMatrix):
           # those that we don't need
           for movement in applied_rule.objectValues():
             if movement.getId() not in my_cell_transaction_id_list :
-              movement.flushActivity(invoke=0)
+              # movement.flushActivity(invoke=0) XXX never use it
               applied_rule.deleteContent(movement.getId())
 
           # Add every movement from the Matrix to the Simulation
@@ -143,6 +160,8 @@ class InvoiceTransactionRule(Rule, XMLMatrix):
             #LOG('InvoiceTransactionRule.expand :', 0, repr(( 'movement', simulation_movement, transaction_line.getSource(), transaction_line.getDestination(), (my_invoice_line_simulation.getQuantity() * my_invoice_line_simulation.getPrice()) * transaction_line.getQuantity() )))
             simulation_movement._edit(source = transaction_line.getSource()
                 , destination = transaction_line.getDestination()
+                , source_section = my_invoice_line_simulation.getSourceSection()
+                , destination_section = my_invoice_line_simulation.getDestinationSection()
                 , quantity = (my_invoice_line_simulation.getQuantity() * my_invoice_line_simulation.getPrice())
                   * transaction_line.getQuantity()
                   # calculate (quantity * price) * cell_quantity
@@ -233,7 +252,6 @@ class InvoiceTransactionRule(Rule, XMLMatrix):
         for k in cell_range_key_list :
           c = self.newCell(*k, **kwd)
           c.edit( mapped_value_property_list = ( 'title',),
-                  predicate_operator = 'SUPERSET_OF',
                   predicate_category_list = filter(lambda k_item: k_item is not None, k),
                   title = 'Transaction %s' % repr(map(lambda k_item : self.restrictedTraverse(k_item).getTitle(), k)),
                   force_update = 1
@@ -243,48 +261,4 @@ class InvoiceTransactionRule(Rule, XMLMatrix):
         cell_range_id_list = self.getCellRangeIdList(base_id = base_id)
         for k in cell_range_id_list :
           if self.get(k) is not None :
-            self[k].flushActivity(invoke=0)
-            self[k].immediateReindexObject()
-            self._delObject(k)
-
-    security.declareProtected(Permissions.View, 'getCellByPredicate')
-    def getCellByPredicate(self, *kw) :
-      """
-      Returns the cell that match the *kw predicate.
-
-      *kw is a list of couple (base_category_title, category) we want to test against the predicates
-      """
-      base_id = 'vat_per_region'
-      kwd = {'base_id': base_id}
-
-      predicate_list = self.InvoiceTransactionRule_asCellRange() # This is a site dependent script
-      portal_url = getToolByName(self, 'portal_url')
-
-      class Dummy(UserDict) :
-        def isMemberOf(self, category) :
-          if category in self.data.values() :
-            return 1
-          return 0
-        def getProperty(self, key) :
-          return self.data.get(key)
-
-      my_dummy = Dummy()
-      for (k,v) in kw :
-        if hasattr(v, 'getCategoryRelativeUrl') :
-          my_dummy[k]=v.getCategoryRelativeUrl(base=1)
-        else :
-          my_dummy[k]=v
-
-      selected_predicate_list = []
-      # predicate_list is a list of list of predicate, each dimension is one sublist
-      for predicate_dimension_item_list in predicate_list :
-        for predicate in predicate_dimension_item_list :
-          # test predicate against *kw and append to selected_predicate_list if they match
-          predicate = portal_url.restrictedTraverse(predicate)
-          if predicate.test(my_dummy) :
-            selected_predicate_list.append(predicate.getRelativeUrl())
-            break # we only want to add one predicate per dimension to the list
-          # LOG('cellByPredicate', 0, repr(( 'after', predicate, selected_predicate_list )))
-        # LOG('cellByPredicate', 0, repr(( 'after loop', predicate_dimension_item_list, selected_predicate_list )))
-      return self.getCell(*selected_predicate_list, **kwd)
-
+            self.deleteContent(k)
-- 
2.30.9