DomainTool.py 8.32 KB
Newer Older
Jean-Paul Smets's avatar
Jean-Paul Smets committed
1 2 3 4
##############################################################################
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
#                    Jean-Paul Smets-Solanes <jp@nexedi.com>
5
#                    Sebastien Robin <seb@nexedi.com>
Jean-Paul Smets's avatar
Jean-Paul Smets committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
##############################################################################

from Products.CMFCore.utils import UniqueObject

from Acquisition import Implicit
from AccessControl import ClassSecurityInfo
from Globals import InitializeClass, DTMLFile
from Products.ERP5Type import Permissions
from Products.ERP5Type import _dtmldir
from Products.ERP5Type.Tool.BaseTool import BaseTool
from Products.ERP5Type.Document.Folder import Folder
39
from zLOG import LOG
Jean-Paul Smets's avatar
Jean-Paul Smets committed
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

class DomainTool(BaseTool):
    """
         A tool to define ranges and subranges (predicates)
    """
    id = 'portal_domains'
    meta_type = 'ERP5 Domain Tool'    
    portal_type     = 'Domain Tool'
    allowed_types   = ( 'ERP5 Domain',)

    # Declarative Security
    security = ClassSecurityInfo()

    #
    #   ZMI methods
    #
    #manage_options =  Folder.manage_options                     

    security.declareProtected( Permissions.ManagePortal, 'manage_overview' )
    manage_overview = DTMLFile( 'explainDomainTool', _dtmldir )

61
    security.declarePublic('searchPredicateList')
62
    def searchPredicateList(self,context,test=1,sort_method=None,
Sebastien Robin's avatar
Sebastien Robin committed
63
                            ignored_category_list=None,filter_method=None,**kw):
64 65
      """
      Search all predicates wich corresponds to this particular context.
66 67 68 69 70 71 72 73 74
      
      - The sort_method parameter allows to give a method wich will be
        used in order to sort the list of predicates founds. The most
        important predicate is the first one in the list.

      - ignored_category_list :  this is the list of category that we do
        not want to test. For example, we might want to not test the 
        destination or the source of a predicate.

75 76 77 78 79 80 81 82 83 84 85 86 87 88
      """
      portal_catalog = context.portal_catalog
      portal_categories = context.portal_categories
      column_list = []
      expression_list = []
      checked_column_list = []
      sql_kw = {}
      for column in portal_catalog.getColumnIds():
        if column.startswith('predicate.'):
          column_list.append(column.split('.')[1])
      for column in column_list:
        if column in checked_column_list:
          continue
        range_property = 0
89
        if column.endswith('_range_min') or column.endswith('_range_max'):
90
          range_property = 1
91 92
          property = column[-len('_range_min')]
        if '%s_range_min' % column in column_list:
93 94 95 96 97
          range_property = 1
          property = column
        if range_property:
          # We have to check a range property
          base_name = 'predicate.%s' % property
98 99 100 101
#           LOG('searchPredicateList, getPath',0,context.getPath())
#           LOG('searchPredicateList, base_name',0,base_name)
#           LOG('searchPredicateList, property',0,property)
#           LOG('searchPredicateList, getProperty',0,context.getProperty(property))
102
          value = context.getProperty(property)
103
          expression = ''
104
          if value is None:
105 106
            expression += "%s is NULL AND %s_range_min is NULL AND %s_range_max is NULL" \
                                   % ((base_name,)*3)
107
          else:
108 109 110
            expression = "%s is NULL AND %s_range_min is NULL AND %s_range_max is NULL " % ((base_name,)*3) 
            expression += "OR %s = '%s' " % (base_name,value)
            expression += "OR %s_range_min <= '%s' AND %s_range_max is NULL " \
111
                           % (base_name,value,base_name)
112
            expression += "OR %s_range_min is NULL AND %s_range_max > '%s' " \
113
                           % (base_name,base_name,value)
114
            expression += "OR %s_range_min <= '%s' AND %s_range_max > '%s' " \
115
                           % (base_name,value,base_name,value)
116 117
          expression = '( ' + expression + ' )'
          expression_list.append(expression)
118
          checked_column_list.append('%s' % property)
119 120
          checked_column_list.append('%s_range_min' % property)
          checked_column_list.append('%s_range_max' % property)
121 122
      # Add predicate.uid for automatic join
      sql_kw['predicate.uid'] = '!=0'
123
      where_expression = ' AND '.join(expression_list)
124 125 126 127 128 129 130

      # Add category selection
      category_list = context.getCategoryList()
      if len(category_list)==0:
        category_list = ['NULL']
      category_expression = portal_categories.buildSQLSelector(category_list,query_table='predicate_category')
      if len(where_expression)>0:
131
        where_expression = '(%s) AND (%s)' % (where_expression,category_expression)
132 133 134 135 136 137
      else:
        where_expression = category_expression
      sql_kw['where_expression'] = where_expression
      # Add predicate_category.uid for automatic join
      sql_kw['predicate_category.uid'] = '!=0'
      kw.update(sql_kw)
138
#       LOG('searchPredicateList, kw',0,kw)
139 140

      sql_result_list = portal_catalog.searchResults(**kw)
Sebastien Robin's avatar
Sebastien Robin committed
141 142
      if kw.has_key('src__') and kw['src__']:
        return sql_result_list
143 144
      result_list = []
      for predicate in [x.getObject() for x in sql_result_list]:
145
        if test==0 or predicate.test(context):
146
          result_list.append(predicate)
147
      #LOG('searchPredicateList, result_list before sort',0,result_list)
Sebastien Robin's avatar
Sebastien Robin committed
148 149
      if filter_method is not None:
        result_list = filter_method(result_list)
Sebastien Robin's avatar
Sebastien Robin committed
150 151
      if sort_method is not None:
        result_list.sort(sort_method)
152
      #LOG('searchPredicateList, result_list after sort',0,result_list)
153 154 155
      return result_list

    security.declarePublic('generateMappedValue')
156
    def generateMappedValue(self,context,test=1,predicate_list=None,**kw):
157
      """
Sebastien Robin's avatar
Sebastien Robin committed
158
      We will generate a mapped value with the list of all predicates founds. Let's say
Sebastien Robin's avatar
Sebastien Robin committed
159 160 161 162 163 164 165 166
      we have 3 predicates (in the order we want) like this:
      Predicate 1   [ base_price1,           ,   ,   ,    ,    , ]
      Predicate 2   [ base_price2, quantity2 ,   ,   ,    ,    , ]
      Predicate 3   [ base_price3, quantity3 ,   ,   ,    ,    , ]

      Our MappedValue generated will have the base_price of the predicate1, and the quantity of 
      the Predicate2, because Predicate 1 is the first one wich defines a base_price and the
      Predicate2 is the first one wich defines a quantity
167
      """
Sebastien Robin's avatar
Sebastien Robin committed
168
      # First get the list of predicates
169 170 171 172
      if predicate_list is None:
        predicate_list = self.searchPredicateList(context,test=test,**kw)
      if len(predicate_list)==0:
        return None
Sebastien Robin's avatar
Sebastien Robin committed
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188

      #mapped_value = newTempBase(self.getPortalObject(),'new_mapped_value')
      from Products.ERP5Type.Document import newTempDeliveryCell
      mapped_value = newTempDeliveryCell(self.getPortalObject(),'new_mapped_value')
      mapped_value_property_dict = {}

      # Look for each property the first predicate wich defines the property
      for predicate in predicate_list:
        for mapped_value_property in predicate.getMappedValuePropertyList():
          if not mapped_value_property_dict.has_key(mapped_value_property):
            value = predicate.getProperty(mapped_value_property)
            if value is not None:
              mapped_value_property_dict[mapped_value_property] = value
      mapped_value = mapped_value.asContext(**mapped_value_property_dict)
      return mapped_value
      
189 190


Jean-Paul Smets's avatar
Jean-Paul Smets committed
191
InitializeClass(DomainTool)