Transformation.py 12.2 KB
Newer Older
1
# -*- coding: utf8 -*-
Jean-Paul Smets's avatar
Jean-Paul Smets committed
2 3 4 5
##############################################################################
#
# Copyright (c) 2002 Coramy SAS and Contributors. All Rights Reserved.
#                    Thierry_Faucher <Thierry_Faucher@coramy.com>
6
# Copyright (c) 2004-2009 Nexedi SA and Contributors. All Rights Reserved.
7
#                    Romain Courteaud <romain@nexedi.com>
8
#                    Łukasz Nowak <luke@nexedi.com>
Jean-Paul Smets's avatar
Jean-Paul Smets committed
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
#
# 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 AccessControl import ClassSecurityInfo

35
from Products.ERP5Type import Permissions, PropertySheet, Interface
Jean-Paul Smets's avatar
Jean-Paul Smets committed
36 37 38 39
from Products.ERP5Type.XMLObject import XMLObject

from Products.ERP5.Variated import Variated

40
from Products.ERP5.Document.Predicate import Predicate
Jean-Paul Smets's avatar
Jean-Paul Smets committed
41

42
from Products.CMFCategory.Renderer import Renderer
43
from Products.ERP5.AggregatedAmountList import AggregatedAmountList
Jean-Paul Smets's avatar
Jean-Paul Smets committed
44

45
class Transformation(XMLObject, Predicate, Variated):
Jean-Paul Smets's avatar
Jean-Paul Smets committed
46 47 48 49 50 51
    """
      Build of material - contains a list of transformed resources

      Use of default_resource... (to define the variation range,
      to ...)

52 53
      XXX Transformation works only for a miximum of 3 variation base category...
      Matrixbox must be rewrite for a clean implementation of n base category
Jean-Paul Smets's avatar
Jean-Paul Smets committed
54 55

    """
56
    isMovement = 1 # XXX very stupid, but for doing a test on catalog
Jean-Paul Smets's avatar
Jean-Paul Smets committed
57 58 59 60 61 62

    meta_type = 'ERP5 Transformation'
    portal_type = 'Transformation'

    # Declarative security
    security = ClassSecurityInfo()
63
    security.declareObjectProtected(Permissions.AccessContentsInformation)
Jean-Paul Smets's avatar
Jean-Paul Smets committed
64 65 66 67 68 69 70

    # Declarative properties
    property_sheets = ( PropertySheet.Base
                      , PropertySheet.XMLObject
                      , PropertySheet.CategoryCore
                      , PropertySheet.DublinCore
                      , PropertySheet.VariationRange
71
                      , PropertySheet.Predicate
72 73
                      , PropertySheet.Comment
                      , PropertySheet.Reference
74 75 76
                      #, PropertySheet.Resource
                      , PropertySheet.TransformedResource
                      , PropertySheet.Path
Jean-Paul Smets's avatar
Jean-Paul Smets committed
77 78 79 80 81 82
                      , PropertySheet.Transformation
                      )

    # Declarative interfaces
    __implements__ = ( Interface.Variated, )

83

84 85
    security.declareProtected(Permissions.AccessContentsInformation, 
                              'updateVariationCategoryList')
86 87 88 89 90
    def updateVariationCategoryList(self):
      """
        Check if variation category list of the resource changed and update transformation
        and transformation line
      """
91
      self.setVariationBaseCategoryList(self.getVariationBaseCategoryList())
92 93 94 95
      transformation_line_list = self.contentValues()
      for transformation_line in transformation_line_list:
        transformation_line.updateVariationCategoryList()

96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
    security.declareProtected(Permissions.AccessContentsInformation,
                              'getVariationRangeBaseCategoryList')
    def getVariationRangeBaseCategoryList(self):
      """
        Returns possible variation base_category ids of the
        default resource which can be used a variation axis
        in the transformation.
      """
      resource = self.getResourceValue()
      if resource is not None:
        result = resource.getVariationBaseCategoryList()
      else:
        # XXX result = self.getBaseCategoryIds()
        # Why calling this method ?
        # Get a global variable which define a list of variation base category
        result = self.getPortalVariationBaseCategoryList()
      return result

114 115
    security.declareProtected(Permissions.AccessContentsInformation, 
                              'getVariationRangeBaseCategoryItemList')
116
    def getVariationRangeBaseCategoryItemList(self, display_id='getTitleOrId', **kw):
Jean-Paul Smets's avatar
Jean-Paul Smets committed
117
        """
118
          Returns possible variations of the transformation
Jean-Paul Smets's avatar
Jean-Paul Smets committed
119 120 121 122
          as a list of tuples (id, title). This is mostly
          useful in ERP5Form instances to generate selection
          menus.
        """
123 124 125
        return self.portal_categories.getItemList( 
                              self.getVariationRangeBaseCategoryList(),
                              display_id=display_id, **kw)
Jean-Paul Smets's avatar
Jean-Paul Smets committed
126

127 128
    security.declareProtected(Permissions.AccessContentsInformation,
                              'getVariationRangeCategoryItemList')
129
    def getVariationRangeCategoryItemList(self, base_category_list=(),
130
                                          omit_individual_variation=0,
131
                                          display_base_category=1, **kw):
Jean-Paul Smets's avatar
Jean-Paul Smets committed
132 133 134 135 136 137 138
        """
          Returns possible variation category values for the
          transformation according to the default resource.
          Possible category values is provided as a list of
          tuples (id, title). This is mostly
          useful in ERP5Form instances to generate selection
          menus.
139 140
          User may want to define generic transformation without
          any resource define.
Jean-Paul Smets's avatar
Jean-Paul Smets committed
141 142 143
        """
        if base_category_list is ():
          base_category_list = self.getVariationBaseCategoryList()
144 145 146

        resource = self.getResourceValue()
        if resource != None:
147
          result = resource.getVariationCategoryItemList(
148
                        base_category_list=base_category_list,
149
                        omit_individual_variation=omit_individual_variation,
150
                        display_base_category=display_base_category,**kw)
151
        else:
152 153 154 155
          # No resource is define on transformation. 
          # We want to display content of base categories
          result = self.portal_categories.getCategoryChildTitleItemList(
                         base_category_list, base=1, display_none_category=0)
Jean-Paul Smets's avatar
Jean-Paul Smets committed
156 157
        return result

158 159
    security.declareProtected(Permissions.AccessContentsInformation, 
                              '_setVariationBaseCategoryList')
160
    def _setVariationBaseCategoryList(self, value):
Jean-Paul Smets's avatar
Jean-Paul Smets committed
161
      """
162
        Define the possible base categories
Jean-Paul Smets's avatar
Jean-Paul Smets committed
163
      """
164 165 166 167 168 169 170 171 172 173
#      XXX TransformedResource works only for a maximum of 3 variation base category...
#      Matrixbox must be rewrite for a clean implementation of n base category
      if len(value) <= 3:
        self._baseSetVariationBaseCategoryList(value)
      else:
        raise MoreThan3VariationBaseCategory

      # create relations between resource variation and transformation
      self._setVariationCategoryList( self.getVariationRangeCategoryList() )

174 175
    security.declareProtected(Permissions.AccessContentsInformation, 
                              'setVariationBaseCategoryList')
176 177 178 179 180 181 182
    def setVariationBaseCategoryList(self, value):
      """
        Define the possible base categories and reindex object
      """
      self._setVariationBaseCategoryList(value)
      self.reindexObject()

183 184
    security.declareProtected(Permissions.AccessContentsInformation, 
                              'getVariationCategoryItemList')
185 186
    def getVariationCategoryItemList(self, base_category_list=(), base=1, 
                                     display_id='title', 
187 188
                                     current_category=None,
                                     **kw):
189 190 191 192 193 194 195 196 197
      """
        Returns the list of possible variations
        XXX Copied and modified from Variated
        Result is left display.
      """
      variation_category_item_list = []
      if base_category_list == ():
        base_category_list = self.getVariationBaseCategoryList()

198 199 200 201 202 203 204 205 206 207 208 209
      for base_category in base_category_list:
        variation_category_list = self.getVariationCategoryList(
                                            base_category_list=[base_category])

        resource_list = [self.portal_categories.resolveCategory(x) for x in\
                         variation_category_list]
        category_list = [x for x in resource_list \
                         if x.getPortalType() == 'Category']
        variation_category_item_list.extend(Renderer(
                               is_right_display=0,
                               display_none_category=0, base=base,
                               current_category=current_category,
210
                               display_id='logical_path',**kw).\
211 212 213 214 215 216 217 218
                                                 render(category_list))
        object_list = [x for x in resource_list \
                         if x.getPortalType() != 'Category']
        variation_category_item_list.extend(Renderer(
                               is_right_display=0,
                               base_category=base_category, 
                               display_none_category=0, base=base,
                               current_category=current_category,
219
                               display_id=display_id,**kw).\
220
                                                 render(object_list))
221 222
      return variation_category_item_list

223 224 225
    security.declareProtected(Permissions.AccessContentsInformation, 
                              'getAggregatedAmountList')
    def getAggregatedAmountList(self, context=None, REQUEST=None,
226
                                ind_phase_url_list=None, 
227 228
                                rejected_resource_uid_list=None, 
                                context_quantity=0,**kw):
Jean-Paul Smets's avatar
Jean-Paul Smets committed
229
      """
230 231 232
        getAggregatedAmountList returns a AggregatedAmountList which
        can be used either to do some calculation (ex. price, BOM)
        or to display a detailed view of a transformation.
233 234 235

        context_quantity : if set to one, multiply all quantities
                           with the quantity of the context
Jean-Paul Smets's avatar
Jean-Paul Smets committed
236
      """
237
      context = self.asContext(context=context, REQUEST=REQUEST, **kw)
238 239 240
      # First we need to get the list of transformations which this 
      # transformation depends on
      # At this moment, we only consider 1 dependency
241
      template_transformation_list = self.getSpecialiseValueList()
242
      result = AggregatedAmountList()
243 244 245 246 247 248 249 250
      # Browse all involved transformations and create one line per 
      # line of transformation
      # Currently, we do not consider abstractions, we just add 
      # whatever we find in all transformations
      transformation_line_list = []
      for transformation in ([self]+template_transformation_list):
        transformation_line_list.extend(transformation.objectValues())
      # Get only lines related to a precise industrial_phase
251 252 253 254 255 256 257 258
      if ind_phase_url_list is not None:
        new_transf_line_list = []
        for line in transformation_line_list:
          ind_ph = line.getIndustrialPhaseValue()
          if ind_ph is not None:
            if ind_ph.getRelativeUrl() in ind_phase_url_list:
              new_transf_line_list.append(line)
        transformation_line_list = new_transf_line_list
259 260 261 262 263 264
      # Filter lines with resource we do not want to see
      if rejected_resource_uid_list is not None:
        transformation_line_list = filter(
                        lambda x: x.getResourceUid() not in\
                                                   rejected_resource_uid_list,
                        transformation_line_list)
265 266 267 268
      for transformation_line in transformation_line_list:
        # Browse each transformed or assorted resource of the current 
        # transformation
        result.extend(transformation_line.getAggregatedAmountList(context))
269 270
      if context_quantity:
        result.multiplyQuantity(context=context)
271
      return result