Transformation.py 12.6 KB
Newer Older
Yusei Tahara's avatar
Yusei Tahara committed
1
# -*- coding: utf-8 -*-
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, interfaces
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 46
from zLOG import LOG, WARNING

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

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

54 55
      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
56 57

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

    meta_type = 'ERP5 Transformation'
    portal_type = 'Transformation'

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

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

    # Declarative interfaces
83
    __implements__ = ( interfaces.IVariated, )
Jean-Paul Smets's avatar
Jean-Paul Smets committed
84

85

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

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
    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

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

129 130
    security.declareProtected(Permissions.AccessContentsInformation,
                              'getVariationRangeCategoryItemList')
131
    def getVariationRangeCategoryItemList(self, base_category_list=(),
132
                                          omit_individual_variation=0,
133
                                          display_base_category=1, **kw):
Jean-Paul Smets's avatar
Jean-Paul Smets committed
134 135 136 137 138 139 140
        """
          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.
141 142
          User may want to define generic transformation without
          any resource define.
Jean-Paul Smets's avatar
Jean-Paul Smets committed
143 144 145
        """
        if base_category_list is ():
          base_category_list = self.getVariationBaseCategoryList()
146 147 148

        resource = self.getResourceValue()
        if resource != None:
149
          result = resource.getVariationCategoryItemList(
150
                        base_category_list=base_category_list,
151
                        omit_individual_variation=omit_individual_variation,
152
                        display_base_category=display_base_category,**kw)
153
        else:
154 155 156 157
          # 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
158 159
        return result

Fabien Morin's avatar
Fabien Morin committed
160
    security.declareProtected(Permissions.AccessContentsInformation,
161
                              '_setVariationBaseCategoryList')
162
    def _setVariationBaseCategoryList(self, value):
Jean-Paul Smets's avatar
Jean-Paul Smets committed
163
      """
164
        Define the possible base categories
Jean-Paul Smets's avatar
Jean-Paul Smets committed
165
      """
166 167 168 169 170 171 172 173 174 175
#      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() )

Fabien Morin's avatar
Fabien Morin committed
176
    security.declareProtected(Permissions.AccessContentsInformation,
177
                              'setVariationBaseCategoryList')
178 179 180 181 182 183 184
    def setVariationBaseCategoryList(self, value):
      """
        Define the possible base categories and reindex object
      """
      self._setVariationBaseCategoryList(value)
      self.reindexObject()

Fabien Morin's avatar
Fabien Morin committed
185
    security.declareProtected(Permissions.AccessContentsInformation,
186
                              'getVariationCategoryItemList')
Fabien Morin's avatar
Fabien Morin committed
187 188
    def getVariationCategoryItemList(self, base_category_list=(), base=1,
                                     display_id='title',
189 190
                                     current_category=None,
                                     **kw):
191 192 193 194 195 196 197 198 199
      """
        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()

200 201 202 203 204 205 206 207 208 209 210 211
      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,
212
                               display_id='logical_path',**kw).\
213 214 215 216 217
                                                 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,
Fabien Morin's avatar
Fabien Morin committed
218
                               base_category=base_category,
219 220
                               display_none_category=0, base=base,
                               current_category=current_category,
221
                               display_id=display_id,**kw).\
222
                                                 render(object_list))
223 224
      return variation_category_item_list

Fabien Morin's avatar
Fabien Morin committed
225
    security.declareProtected(Permissions.AccessContentsInformation,
226 227
                              'getAggregatedAmountList')
    def getAggregatedAmountList(self, context=None, REQUEST=None,
228 229 230
                                trade_phase_list=None,
                                # obsolete, use trade_phase_list instead
                                ind_phase_url_list=None,
Fabien Morin's avatar
Fabien Morin committed
231
                                rejected_resource_uid_list=None,
232
                                context_quantity=0,**kw):
Jean-Paul Smets's avatar
Jean-Paul Smets committed
233
      """
234 235 236
        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.
237 238 239

        context_quantity : if set to one, multiply all quantities
                           with the quantity of the context
Jean-Paul Smets's avatar
Jean-Paul Smets committed
240
      """
241
      context = self.asContext(context=context, REQUEST=REQUEST, **kw)
242 243 244
      # First we need to get the list of transformations which this 
      # transformation depends on
      # At this moment, we only consider 1 dependency
245
      template_transformation_list = self.getSpecialiseValueList()
246
      result = AggregatedAmountList()
247 248 249 250 251 252 253
      # 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())
254 255 256 257 258
      # Get only lines related to a precise trade_phase
      if trade_phase_list is not None:
        transformation_line_list = filter(
            lambda line: line.getTradePhase() in trade_phase_list,
            transformation_line_list)
259
      # Get only lines related to a precise industrial_phase
260
      if ind_phase_url_list is not None:
261
        LOG("Transformation", WARNING, "ind_phase_list is obsolete")
262 263 264 265 266 267 268
        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
269 270 271 272 273 274
      # 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)
275 276 277 278
      for transformation_line in transformation_line_list:
        # Browse each transformed or assorted resource of the current 
        # transformation
        result.extend(transformation_line.getAggregatedAmountList(context))
279 280
      if context_quantity:
        result.multiplyQuantity(context=context)
281
      return result