TransformedResource.py 10.4 KB
Newer Older
Jean-Paul Smets's avatar
Jean-Paul Smets committed
1 2
##############################################################################
#
3
# Copyright (c) 2002, 2004 Nexedi SARL and Contributors. All Rights Reserved.
4
#                    Jean-Paul Smets-Solanes <jp@nexedi.com>
5
#                    Romain Courteaud <romain@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
#
# 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 Globals import InitializeClass
from AccessControl import ClassSecurityInfo

from Products.ERP5Type import Permissions, PropertySheet, Constraint, Interface
from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Type.XMLMatrix import XMLMatrix
from Products.ERP5Type.Utils import cartesianProduct
Yoshinori Okuji's avatar
Yoshinori Okuji committed
37
from Products.ERP5Type.Base import TempBase
Jean-Paul Smets's avatar
Jean-Paul Smets committed
38

39
from Products.ERP5.Document.Amount import Amount
40
from Products.ERP5.Document.Transformation import AggregatedAmountList
Jean-Paul Smets's avatar
Jean-Paul Smets committed
41

42
from Products.CMFCore.Expression import Expression
Jean-Paul Smets's avatar
Jean-Paul Smets committed
43 44 45 46 47 48 49 50 51 52 53 54 55

from zLOG import LOG

class TransformedResource(XMLObject, XMLMatrix, Amount):
    """
        TransformedResource defines which
        resource is being transformed

        - variation
        - quantity

        Maybe defined by mapped values inside the transformed resource

56 57 58
      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
59 60 61 62 63 64 65 66 67 68 69 70 71

    """

    meta_type = 'ERP5 Transformed Resource'
    portal_type = 'Transformed Resource'

    # Declarative security
    security = ClassSecurityInfo()
    security.declareObjectProtected(Permissions.View)

    # Declarative properties
    property_sheets = ( PropertySheet.Base
                      , PropertySheet.SimpleItem
Jean-Paul Smets's avatar
Jean-Paul Smets committed
72
                      , PropertySheet.CategoryCore
Jean-Paul Smets's avatar
Jean-Paul Smets committed
73 74 75 76 77 78 79
                      , PropertySheet.Amount
                      , PropertySheet.TransformedResource
                      )

    # Declarative interfaces
    __implements__ = ( Interface.Variated, )

80

Jean-Paul Smets's avatar
Jean-Paul Smets committed
81 82 83

    ### Variation matrix definition
    #
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
    security.declareProtected(Permissions.AccessContentsInformation, 'updateVariationCategoryList')
    def updateVariationCategoryList(self):
      """
        Check if variation category list of the resource changed and update transformed resource
        by doing a set cell range
      """
      self.setQVariationBaseCategoryList( self.getQVariationBaseCategoryList() )
      self.setVVariationBaseCategoryList( self.getVVariationBaseCategoryList() )

    security.declareProtected(Permissions.ModifyPortalContent, '_updateQMatrixCellRange')
    def _updateQMatrixCellRange(self):
      cell_range =  self.TransformedResource_asCellRange('quantity')

#      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(cell_range) <= 3:
        self.setCellRange(base_id='quantity', *cell_range)
      else:
        raise MoreThan3VariationBaseCategory

Jean-Paul Smets's avatar
Jean-Paul Smets committed
104 105 106 107 108 109 110
    security.declareProtected(Permissions.ModifyPortalContent, '_setQVariationBaseCategoryList')
    def _setQVariationBaseCategoryList(self, value):
      """
        Defines the possible base categories which Quantity value (Q)
        variate on
      """
      self._baseSetQVariationBaseCategoryList(value)
111
      self._updateQMatrixCellRange()
Jean-Paul Smets's avatar
Jean-Paul Smets committed
112 113 114 115 116 117 118 119 120 121

    security.declareProtected(Permissions.ModifyPortalContent, 'setQVariationBaseCategoryList')
    def setQVariationBaseCategoryList(self, value):
      """
        Defines the possible base categories which Quantity value (Q)
        variate on and reindex the object
      """
      self._setQVariationBaseCategoryList(value)
      self.reindexObject()

122 123 124 125 126 127 128 129 130 131
    security.declareProtected(Permissions.ModifyPortalContent, '_updateVMatrixCellRange')
    def _updateVMatrixCellRange(self):
      cell_range =  self.TransformedResource_asCellRange('variation')
#      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(cell_range) <= 3:
        self.setCellRange(base_id='variation', *cell_range)
      else:
        raise MoreThan3VariationBaseCategory

Jean-Paul Smets's avatar
Jean-Paul Smets committed
132 133 134 135 136 137 138
    security.declareProtected(Permissions.ModifyPortalContent, '_setVVariationBaseCategoryList')
    def _setVVariationBaseCategoryList(self, value):
      """
        Defines the possible base categories which Variation value (V)
        variate on
      """
      self._baseSetVVariationBaseCategoryList(value)
139
      self._updateVMatrixCellRange()
Jean-Paul Smets's avatar
Jean-Paul Smets committed
140 141 142 143 144 145 146 147 148 149 150

    security.declareProtected(Permissions.ModifyPortalContent, 'setVVariationBaseCategoryList')
    def setVVariationBaseCategoryList(self, value):
      """
        Defines the possible base categories which Variation value (V)
        variate on and reindex the object
      """
      self._setVVariationBaseCategoryList(value)
      self.reindexObject()


151 152 153 154 155 156 157 158 159 160 161 162
    security.declareProtected(Permissions.AccessContentsInformation,'getVariationRangeCategoryItemList')
    def getVariationRangeCategoryItemList(self, base_category_list = ()):
        """
          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.
          Display is left...
        """
        resource = self.getResourceValue()
Jean-Paul Smets's avatar
Jean-Paul Smets committed
163
        result = []
164 165 166
        if resource != None:
          if base_category_list is ():
            base_category_list = resource.getVariationBaseCategoryList()
Jean-Paul Smets's avatar
Jean-Paul Smets committed
167

168
          result = resource.getVariationRangeCategoryItemList(base_category_list=base_category_list )
Jean-Paul Smets's avatar
Jean-Paul Smets committed
169

170
        return result
Jean-Paul Smets's avatar
Jean-Paul Smets committed
171

172
    security.declareProtected(Permissions.AccessContentsInformation, 'getAggregatedAmountList')
173
    def getAggregatedAmountList(self, context=None, REQUEST=None, **kw):
Jean-Paul Smets's avatar
Jean-Paul Smets committed
174
      """
175
        Get all interesting amount value and return TempAmount
Jean-Paul Smets's avatar
Jean-Paul Smets committed
176
      """
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
      context = self.asContext(context=context, REQUEST=REQUEST, **kw)
      # Create the result object
      aggregated_amount_list = AggregatedAmountList()
      
      # Create temporary object to store amount
      from Products.ERP5Type.Document import newTempAmount
      tmp_amount = newTempAmount(self.getPortalObject(), self.getId())
      
      error_string = ''

      # add resource relation
      resource = self.getDefaultResourceValue()
      if resource != None:
        tmp_amount.setResourceValue(resource)
      else:
        error_string += 'No resource defined on %s' % self.getRelativeUrl()
Yoshinori Okuji's avatar
Yoshinori Okuji committed
193 194 195 196

      # First, we set initial values for quantity and variation
      # Currently, we only consider discrete variations
      # Continuous variations will be implemented in a future version of ERP5
197

Yoshinori Okuji's avatar
Yoshinori Okuji committed
198
      quantity_unit = self.getQuantityUnit()
199 200
      if quantity_unit is not None:
        tmp_amount.setQuantityUnitValue(quantity_unit)
201 202


203 204 205 206 207
      efficiency =  self.getEfficiency()
      if efficiency is None or efficiency is '' or efficiency == 0.0:
        efficiency = 1.0
      else:
        efficiency = float(efficiency)
208

209
      quantity_defined_by = None
210

211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
      # get Quantity
      quantity = None
      if context != None:
        # We will browse the mapped values and determine which apply
        for key in self.getCellKeyList( base_id = 'quantity'):
          if self.hasCell(base_id='quantity', *key):
            mapped_value = self.getCell(base_id='quantity', *key)
            if mapped_value.test(context):
              if 'quantity' in mapped_value.getMappedValuePropertyList():
                quantity = mapped_value.getProperty('quantity')
                quantity_defined_by = mapped_value.getRelativeUrl()

      if quantity in [None,'']:
        quantity = self.getQuantity()
        quantity_defined_by = self.getRelativeUrl()

      # If we have to do this, then there is a problem....
      # We'd better have better API for this, like an update function in the mapped_value
      try:
        quantity = float(quantity)
      except:
        error_string += 'Quantity is not a float.'


      variation_category_list_defined_by = None

      # get Variation Category List
      variation_category_list = None
      if context != None:
240
        # We will browse the mapped values and determine which apply
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
        for key in self.getCellKeyList( base_id = 'variation'):
          if self.hasCell(base_id='variation', *key):
            mapped_value = self.getCell(base_id='variation', *key)

            if mapped_value.test(context):
              vcl = mapped_value.getCategoryList()
              if vcl != []:
                variation_category_list = vcl
                variation_category_list_defined_by = mapped_value.getRelativeUrl()

      if variation_category_list in [None,'',[], ()]:
        variation_category_list = self._getVariationCategoryList()
        variation_category_list_defined_by = self.getRelativeUrl()

      tmp_amount._edit(
        # Properties define on transformation line
        description =  self.getDescription(),
        efficiency = efficiency,
        quantity = quantity,

        # This fields only store some informations for debugging if necessary
        quantity_defined_by  = quantity_defined_by,
        variation_category_list_defined_by = variation_category_list_defined_by, 
        error_string = error_string
      )

      tmp_amount.setVariationCategoryList(variation_category_list)
        
      aggregated_amount_list.append( tmp_amount )

      return aggregated_amount_list