Commit 49fc23d9 authored by Romain Courteaud's avatar Romain Courteaud

New implementation of Transformation, to make it more generic. API changed.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@2509 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent a53e0656
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
# #
# Copyright (c) 2002 Coramy SAS and Contributors. All Rights Reserved. # Copyright (c) 2002 Coramy SAS and Contributors. All Rights Reserved.
# Thierry_Faucher <Thierry_Faucher@coramy.com> # Thierry_Faucher <Thierry_Faucher@coramy.com>
# Copyright (c) 2004 Nexedi SARL and Contributors. All Rights Reserved.
# Romain Courteaud <romain@nexedi.com>
# #
# WARNING: This program as such is intended to be used by professional # WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential # programmers who take the whole responsability of assessing all potential
...@@ -37,6 +39,7 @@ from Products.ERP5.Variated import Variated ...@@ -37,6 +39,7 @@ from Products.ERP5.Variated import Variated
from Products.ERP5.Document.Domain import Domain from Products.ERP5.Document.Domain import Domain
import string
from zLOG import LOG from zLOG import LOG
class Transformation(XMLObject, Domain, Variated): class Transformation(XMLObject, Domain, Variated):
...@@ -46,26 +49,13 @@ class Transformation(XMLObject, Domain, Variated): ...@@ -46,26 +49,13 @@ class Transformation(XMLObject, Domain, Variated):
Use of default_resource... (to define the variation range, Use of default_resource... (to define the variation range,
to ...) to ...)
XXX Transformation works only for a miximum of 3 variation base category...
About ranges: Matrixbox must be rewrite for a clean implementation of n base category
getDomainBaseCategoryList -> base categories which allow to select state...
getDomainRangeBaseCategoryList -> base categories which allow to select state...
getDomainCategoryList -> bonne id?.... = DomainValue...
base category which defines the state
(and other things)
getDomainRangeCategoryList -> bonne id?.... = DomainValue...
""" """
meta_type = 'ERP5 Transformation' meta_type = 'ERP5 Transformation'
portal_type = 'Transformation' portal_type = 'Transformation'
add_permission = Permissions.AddPortalContent
isPortalContent = 1
isRADContent = 1
# Declarative security # Declarative security
security = ClassSecurityInfo() security = ClassSecurityInfo()
...@@ -78,139 +68,82 @@ class Transformation(XMLObject, Domain, Variated): ...@@ -78,139 +68,82 @@ class Transformation(XMLObject, Domain, Variated):
, PropertySheet.DublinCore , PropertySheet.DublinCore
, PropertySheet.VariationRange , PropertySheet.VariationRange
, PropertySheet.Domain , PropertySheet.Domain
#, PropertySheet.Resource
, PropertySheet.TransformedResource
, PropertySheet.Path
, PropertySheet.Transformation , PropertySheet.Transformation
) )
# Declarative interfaces # Declarative interfaces
__implements__ = ( Interface.Variated, ) __implements__ = ( Interface.Variated, )
# Factory Type Information
factory_type_information = \ security.declareProtected(Permissions.AccessContentsInformation, 'updateVariationCategoryList')
{ 'id' : portal_type def updateVariationCategoryList(self):
, 'meta_type' : meta_type """
, 'description' : """\ Check if variation category list of the resource changed and update transformation
une gamme...""" and transformation line
, 'icon' : 'transformation_icon.gif' """
, 'product' : 'ERP5' self.setVariationBaseCategoryList( self.getVariationBaseCategoryList() )
, 'factory' : 'addTransformation' transformation_line_list = self.contentValues()
, 'immediate_view' : 'transformation_view' for transformation_line in transformation_line_list:
, 'allow_discussion' : 1 transformation_line.updateVariationCategoryList()
, 'allowed_content_types': ('Transformed Resource',
) security.declareProtected(Permissions.AccessContentsInformation, 'getVariationRangeBaseCategoryList')
, 'filter_content_types' : 1
, 'global_allow' : 1
, 'actions' :
( { 'id' : 'view'
, 'name' : 'View'
, 'category' : 'object_view'
, 'action' : 'transformation_view'
, 'permissions' : (
Permissions.View, )
}
, { 'id' : 'list'
, 'name' : 'Object Contents'
, 'category' : 'object_action'
, 'action' : 'folder_contents'
, 'permissions' : (
Permissions.View, )
}
, { 'id' : 'print'
, 'name' : 'Print'
, 'category' : 'object_print'
, 'action' : 'transformation_print'
, 'permissions' : (
Permissions.View, )
}
, { 'id' : 'metadata'
, 'name' : 'Metadata'
, 'category' : 'object_view'
, 'action' : 'metadata_edit'
, 'permissions' : (
Permissions.View, )
}
, { 'id' : 'translate'
, 'name' : 'Translate'
, 'category' : 'object_action'
, 'action' : 'translation_template_view'
, 'permissions' : (
Permissions.TranslateContent, )
}
)
}
security.declareProtected(Permissions.AccessContentsInformation,
'getVariationRangeBaseCategoryList')
def getVariationRangeBaseCategoryList(self): def getVariationRangeBaseCategoryList(self):
""" """
Returns possible variation base_category ids of the Returns possible variation base_category ids of the
default resource of this transformation default resource which can be used a variation axis
in the transformation.
""" """
resource = self.getDefaultResourceValue() #resource = self.getDefaultResourceValue()
resource = self.getResourceValue()
if resource is not None: if resource is not None:
#result = [''] + resource.getVariationBaseCategoryList()
result = resource.getVariationBaseCategoryList() result = resource.getVariationBaseCategoryList()
else: else:
result = self.getBaseCategoryIds() # XXX result = self.getBaseCategoryIds()
# Why calling this method ?
# Get a global variable which define a list of variation base category
# XXX I don' t like this approch, maybe can we define this variable
# on Transformation property sheet ? (Romain)
result = self.getPortalVariationBaseCategoryList()
return result return result
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation, 'getVariationRangeBaseCategoryItemList')
'getTransformationVariationRangeCategoryList')
def getTransformationVariationRangeCategoryList(self):
"""
Possible categories (ie. of the default resource)
"""
return self.getResourceValue().getVariationCategoryList(base_category_list=
self.getTransformationVariationBaseCategoryList())
security.declareProtected(Permissions.AccessContentsInformation,
'getTransformationVariationCategoryList')
def getTransformationVariationCategoryList(self):
"""
Possible categories (ie. of the default resource)
"""
return self.getVariationCategoryList(base_category_list=
self.getTransformationVariationBaseCategoryList())
security.declareProtected(Permissions.AccessContentsInformation,
'getTransformationVariationRangeBaseCategoryList')
def getTransformationVariationRangeBaseCategoryList(self):
"""
Returns possible variation base_category ids of the
default resource which can be used a variation axis
in the transformation (ie. all ids of
getVariationRangeBaseCategoryList except ids which
are used as a transformation state as defined in
domain_base_category)
"""
result = ['',] + list(self.getVariationRangeBaseCategoryList())
forbidden_id = self.getDomainBaseCategoryList()
forbidden_id = asList(forbidden_id) # This will soon be useless
return rejectIn(result, forbidden_id)
security.declareProtected(Permissions.AccessContentsInformation,
'getVariationRangeBaseCategoryItemList')
def getVariationRangeBaseCategoryItemList(self): def getVariationRangeBaseCategoryItemList(self):
""" """
Returns possible variations of the resource Returns possible variations of the transformation
as a list of tuples (id, title). This is mostly as a list of tuples (id, title). This is mostly
useful in ERP5Form instances to generate selection useful in ERP5Form instances to generate selection
menus. menus.
""" """
return self.portal_categories.getItemList(self.getVariationRangeBaseCategoryList()) return self.portal_categories.getItemList( self.getVariationRangeBaseCategoryList() )
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,'getVariationRangeCategoryList')
'getTransformationVariationRangeBaseCategoryItemList') def getVariationRangeCategoryList(self, base_category_list = ()):
def getTransformationVariationRangeBaseCategoryItemList(self):
""" """
Returns possible variations of the transformation Returns possible variation category values for the
as a list of tuples (id, title). This is mostly transformation according to the default resource.
useful in ERP5Form instances to generate selection Possible category values is provided as a list of
menus. id.
User may want to define generic transformation without
any resource define.
Result is left display.
""" """
return self.portal_categories.getItemList( if base_category_list is ():
self.getTransformationVariationRangeBaseCategoryList()) base_category_list = self.getVariationBaseCategoryList()
resource = self.getResourceValue()
if resource != None:
result = resource.getVariationRangeCategoryList(base_category_list)
else:
# No resource is define on transformation. We want to display content of base categories
result = self.portal_categories.getCategoryChildList(base_category_list, base=1)
return result
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,'getVariationRangeCategoryItemList')
'getVariationRangeCategoryItemList')
def getVariationRangeCategoryItemList(self, base_category_list = ()): def getVariationRangeCategoryItemList(self, base_category_list = ()):
""" """
Returns possible variation category values for the Returns possible variation category values for the
...@@ -219,33 +152,105 @@ une gamme...""" ...@@ -219,33 +152,105 @@ une gamme..."""
tuples (id, title). This is mostly tuples (id, title). This is mostly
useful in ERP5Form instances to generate selection useful in ERP5Form instances to generate selection
menus. menus.
User may want to define generic transformation without
any resource define.
""" """
if base_category_list is (): if base_category_list is ():
base_category_list = self.getVariationBaseCategoryList() base_category_list = self.getVariationBaseCategoryList()
try:
result = self.getDefaultResourceValue( resource = self.getResourceValue()
).getVariationRangeCategoryItemList(base_category_list) if resource != None:
except: result = resource.getVariationRangeCategoryItemList(base_category_list)
result = self.portal_categories.getCategoryChildItemList(base_category_list, else:
base=1) # 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)
return result return result
# Aliases to simplify access to range information for TransformedResources security.declareProtected(Permissions.AccessContentsInformation, 'getVariationBaseCategoryItemList')
security.declareProtected(Permissions.AccessContentsInformation, def getVariationBaseCategoryItemList(self):
'getTransformationVariationBaseCategoryList')
def getTransformationVariationBaseCategoryList(self):
""" """
Returns a list of base_category ids for this tranformation Returns a list of base_category tuples for this tranformation
""" """
return self.getVariationBaseCategoryList() return self.portal_categories.getItemList(self.getVariationBaseCategoryList())
security.declareProtected(Permissions.AccessContentsInformation,
'getTransformationVariationBaseCategoryItemList') security.declareProtected(Permissions.AccessContentsInformation, '_setVariationBaseCategoryList')
def getTransformationVariationBaseCategoryItemList(self): def _setVariationBaseCategoryList(self, value):
""" """
Returns a list of base_category tuples for this tranformation Define the possible base categories
""" """
return self.portal_categories.getItemList(self.getVariationBaseCategoryList()) # 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() )
security.declareProtected(Permissions.AccessContentsInformation, 'setVariationBaseCategoryList')
def setVariationBaseCategoryList(self, value):
"""
Define the possible base categories and reindex object
"""
self._setVariationBaseCategoryList(value)
self.reindexObject()
security.declareProtected(Permissions.AccessContentsInformation, 'getVariationCategoryItemList')
def getVariationCategoryItemList(self, base_category_list=()):
"""
Returns a list of variation tuples for this tranformation
Result is left display.
"""
if base_category_list == ():
base_category_list = self.getVariationBaseCategoryList()
variation_category_item_list = map(lambda x: (x,x), self.getVariationCategoryList( base_category_list=base_category_list ))
return variation_category_item_list
security.declareProtected(Permissions.AccessContentsInformation, 'getVariationCategoryItemList')
def getVariationCategoryItemList(self, base_category_list = (), base=1, display_id='getTitleOrId', current_category=None):
"""
Returns the list of possible variations
XXX Copied and modified from Variated
Result is left display.
"""
variation_category_item_list = []
# What is this parameter ?
# if current_category is not None:
# variation_category_item_list.append((current_category,current_category))
if base_category_list == ():
base_category_list = self.getVariationBaseCategoryList()
variation_category_list = self.getVariationCategoryList(base_category_list=base_category_list)
for variation_category in variation_category_list:
resource = self.portal_categories.resolveCategory(variation_category)
if resource.getPortalType() == 'Category':
# Category is unusable if only Title is displayed...
value = getattr(resource, 'getLogicalPath')()
else:
# And displaying LogicalPath for variation is unusable for user...
value = getattr(resource, display_id)()
if base:
index = variation_category.find('/')
base_category = variation_category[:index]
label = base_category+'/'+value
else:
label = value
# Result is left display
variation_category_item_list.append((label, variation_category ))
return variation_category_item_list
# This is the main method to do any BOM related calculation # This is the main method to do any BOM related calculation
security.declareProtected(Permissions.AccessContentsInformation, 'getAggregatedAmountList') security.declareProtected(Permissions.AccessContentsInformation, 'getAggregatedAmountList')
...@@ -260,95 +265,79 @@ une gamme...""" ...@@ -260,95 +265,79 @@ une gamme..."""
# LOG('getAggregatedAmountList',0,str((context, REQUEST, kw))) # LOG('getAggregatedAmountList',0,str((context, REQUEST, kw)))
REQUEST = self.asContext(context=context, REQUEST=REQUEST, **kw) REQUEST = self.asContext(context=context, REQUEST=REQUEST, **kw)
# First we need to get the list of transformations which this transformation depends on # First we need to get the list of transformations which this transformation depends on
# At this moment, we only consider 1 dependency # XXX At this moment, we only consider 1 dependency
transformation_list = [self] + self.getSpecialiseValueList() template_transformation_list = self.getSpecialiseValueList()
# We consider that the specific parameters to take into account # We consider that the specific parameters to take into account
# are acquired through the REQUEST parameter # are acquired through the REQUEST parameter
# The REQUEST can either be a Zope REQUEST or a dictionnary provided by the use # The REQUEST can either be a Zope REQUEST or a dictionnary provided by the use
if REQUEST is None: # if REQUEST is None:
# At this moment XXXXXXXXXXXXXXXXXXXXXXXX # # At this moment XXX
# we initialize the request to a default value in order # # we initialize the request to a default value in order
# to make sure we have something to test MappedValues on # # to make sure we have something to test MappedValues on
REQUEST = {'categories': ('taille/enfant/08 ans','coloris/modele/701C402/2')} # #REQUEST = {'categories': ('taille/enfant/08 ans','coloris/modele/701C402/2')}
# We define some initial values # REQUEST = {}
# result holds a list of dictionaries
# price holds a list of dictionaries result = None
summary_list = []
grand_total_variated_source_base_price = 0.0
grand_total_source_base_price = 0.0
grand_total_base_price = 0.0
grand_total_variated_base_price = 0.0
grand_total_variated_source_base_price = 0.0
grand_total_duration = 0.0
# Browse all involved transformations and create one line per line of transformation # 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 # Currently, we do not consider abstractions, we just add whatever we find in all
# transformations # transformations
for transformation in transformation_list: for transformation in [self] + transformation_list:
# Browse each transformed or assorted resource of the current transformation # Browse each transformed or assorted resource of the current transformation
for transformed_resource in transformation.objectValues(): for transformed_resource in transformation.objectValues():
#LOG("for transformed_resource in transformation",0,transformed_resource.getId())
line_item_list, total_base_price, total_source_base_price, \ if result==None:
total_variated_base_price, total_variated_source_base_price, duration \ result = transformed_resource.getAggregatedAmountList(REQUEST)
= transformed_resource.getAggregatedAmountList(REQUEST) else:
summary_list += line_item_list result += transformed_resource.getAggregatedAmountList(REQUEST)
grand_total_base_price += total_base_price
grand_total_source_base_price += total_source_base_price return result
grand_total_variated_base_price += total_variated_base_price
grand_total_variated_source_base_price += total_variated_source_base_price
grand_total_duration += duration # # UPDATED BY JPS
#
#LOG("Transformation Agg summary",0, # # XXX This should not be there, but in Document/TransformedResource.py or something like
# str(map(lambda o: (o.resource_id, o.quantity_defined_by), summary_list))) # # this, but actually this does not work, we should find why.
# security.declareProtected(Permissions.ModifyPortalContent, '_setVariationBaseCategoryList')
# Return values as a tuple # def _setVariationBaseCategoryList(self, new_base_category_list):
return map(lambda x: x.__dict__, summary_list) , grand_total_base_price, \ # """
grand_total_source_base_price, grand_total_duration, \ # We override the default behaviour generated by Utils.py in order
grand_total_variated_base_price, grand_total_variated_source_base_price # to update all TransformedResource contained in this transformation
# """
# UPDATED BY JPS # # Get the list of previous base_category that have been removed or kept
# removed_base_category = []
# XXX This should not be there, but in Document/TransformedResource.py or something like # kept_base_category = []
# this, but actually this does not work, we should find why. # for cat in self.getVariationBaseCategoryList():
security.declareProtected(Permissions.ModifyPortalContent, '_setVariationBaseCategoryList') # if cat in new_base_category_list:
def _setVariationBaseCategoryList(self, new_base_category_list): # kept_base_category += [cat]
""" # else:
We override the default behaviour generated by Utils.py in order # removed_base_category += [cat]
to update all TransformedResource contained in this transformation #
""" # # Update variation_base_category_list
# Get the list of previous base_category that have been removed or kept # self.variation_base_category_list = new_base_category_list
removed_base_category = [] #
kept_base_category = [] # # Make sure there is no reference to categories
for cat in self.getVariationBaseCategoryList(): # # of removed_base_category
if cat in new_base_category_list: # # in categories
kept_base_category += [cat] # if len(removed_base_category) > 0:
else: # self._setCategoryMembership(removed_base_category, [], base=1)
removed_base_category += [cat] #
# # Filter all fields which are based on base_category
# Update variation_base_category_list # if self.getVariationBaseCategoryLine() not in new_base_category_list:
self.variation_base_category_list = new_base_category_list # self._setVariationBaseCategoryLine(None)
# if self.getVariationBaseCategoryColumn() not in new_base_category_list:
# Make sure there is no reference to categories # self._setVariationBaseCategoryColumn(None)
# of removed_base_category # self._setVariationBaseCategoryTabList(keepIn(self.getVariationBaseCategoryTabList(),
# in categories # new_base_category_list))
if len(removed_base_category) > 0: #
self._setCategoryMembership(removed_base_category, [], base=1) # # Make sure that all sub-objects use a valid range
# # We simply call range functions on each object to force
# Filter all fields which are based on base_category # # range update in XMLMatrix
if self.getVariationBaseCategoryLine() not in new_base_category_list: # for o in self.objectValues():
self._setVariationBaseCategoryLine(None) # if hasattr(o,'v_variation_base_category_list'):
if self.getVariationBaseCategoryColumn() not in new_base_category_list: # o.setVVariationBaseCategoryList(keepIn(o.getVVariationBaseCategoryList(),
self._setVariationBaseCategoryColumn(None) # new_base_category_list))
self._setVariationBaseCategoryTabList(keepIn(self.getVariationBaseCategoryTabList(), # if hasattr(o,'q_variation_base_category_list'):
new_base_category_list)) # o.setQVariationBaseCategoryList(keepIn(o.getQVariationBaseCategoryList(),
# new_base_category_list))
# Make sure that all sub-objects use a valid range
# We simply call range functions on each object to force
# range update in XMLMatrix
for o in self.objectValues():
if hasattr(o,'v_variation_base_category_list'):
o.setVVariationBaseCategoryList(keepIn(o.getVVariationBaseCategoryList(),
new_base_category_list))
if hasattr(o,'q_variation_base_category_list'):
o.setQVariationBaseCategoryList(keepIn(o.getQVariationBaseCategoryList(),
new_base_category_list))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment