From 8ceef6bd2b1b64d8308e65d611c79e8c777f82fb Mon Sep 17 00:00:00 2001 From: Julien Muchembled <jm@nexedi.com> Date: Fri, 15 Oct 2010 17:45:38 +0000 Subject: [PATCH] Make testLegacyProductionOrder work with new amount generator git-svn-id: https://svn.erp5.org/repos/public/erp5/sandbox/amount_generator@39253 20353a03-c40f-0410-a6d1-a30d3c3de9de --- .../DocumentTemplateItem/Transformation.py | 309 ---------------- .../TransformedResource.py | 334 ------------------ .../bt/template_document_id_list | 4 +- product/ERP5/Document/AssortedResource.py | 15 +- product/ERP5/Document/SupplyLink.py | 11 +- product/ERP5/Document/TransformedResource.py | 63 ++-- .../SQLCatalog_catalogTransformation.xml | 5 +- product/ERP5/mixin/amount_generator.py | 16 +- .../ERP5Legacy/Document/TransformationRule.py | 23 +- .../tests/testLegacyProductionOrder.py | 3 +- 10 files changed, 65 insertions(+), 718 deletions(-) delete mode 100644 bt5/erp5_simulation_legacy/DocumentTemplateItem/Transformation.py delete mode 100644 bt5/erp5_simulation_legacy/DocumentTemplateItem/TransformedResource.py diff --git a/bt5/erp5_simulation_legacy/DocumentTemplateItem/Transformation.py b/bt5/erp5_simulation_legacy/DocumentTemplateItem/Transformation.py deleted file mode 100644 index b328e680fd..0000000000 --- a/bt5/erp5_simulation_legacy/DocumentTemplateItem/Transformation.py +++ /dev/null @@ -1,309 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# Copyright (c) 2002 Coramy SAS and Contributors. All Rights Reserved. -# Thierry_Faucher <Thierry_Faucher@coramy.com> -# Copyright (c) 2004-2009 Nexedi SA and Contributors. All Rights Reserved. -# Romain Courteaud <romain@nexedi.com> -# Åukasz Nowak <luke@nexedi.com> -# -# 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. -# -############################################################################## - -import zope.interface - -from warnings import warn -from AccessControl import ClassSecurityInfo - -from Products.ERP5Type import Permissions, PropertySheet, interfaces -from Products.ERP5Type.XMLObject import XMLObject - -from Products.ERP5.Variated import Variated - -from Products.ERP5.Document.Predicate import Predicate - -from Products.CMFCategory.Renderer import Renderer -from Products.ERP5.AggregatedAmountList import AggregatedAmountList - -from zLOG import LOG, WARNING - -class Transformation(XMLObject, Predicate, Variated): - """ - Build of material - contains a list of transformed resources - - Use of default_resource... (to define the variation range, - to ...) - - XXX Transformation works only for a maximum of 3 variation base category... - Matrixbox must be rewritten for a clean implementation of n base category - - """ - meta_type = 'ERP5 Transformation' - portal_type = 'Transformation' - - # Declarative security - security = ClassSecurityInfo() - security.declareObjectProtected(Permissions.AccessContentsInformation) - - # Declarative properties - property_sheets = ( PropertySheet.Base - , PropertySheet.XMLObject - , PropertySheet.CategoryCore - , PropertySheet.DublinCore - , PropertySheet.VariationRange - , PropertySheet.Predicate - , PropertySheet.Comment - , PropertySheet.Reference - , PropertySheet.Version - #, PropertySheet.Resource - , PropertySheet.TransformedResource - , PropertySheet.Path - , PropertySheet.Transformation - ) - - # Declarative interfaces - zope.interface.implements(interfaces.IVariated, - interfaces.IAmountGenerator - ) - - - - security.declareProtected(Permissions.AccessContentsInformation, - 'updateVariationCategoryList') - def updateVariationCategoryList(self): - """ - Check if variation category list of the resource has changed and update - transformation and transformation line - """ - self.setVariationBaseCategoryList(self.getVariationBaseCategoryList()) - transformation_line_list = self.contentValues() - for transformation_line in transformation_line_list: - transformation_line.updateVariationCategoryList() - - security.declareProtected(Permissions.AccessContentsInformation, - 'getVariationRangeBaseCategoryList') - def getVariationRangeBaseCategoryList(self): - """ - Returns possible variation base_category ids of the - default resource which can be used as 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 - - security.declareProtected(Permissions.AccessContentsInformation, - 'getVariationRangeBaseCategoryItemList') - def getVariationRangeBaseCategoryItemList(self, display_id='getTitleOrId', **kw): - """ - Returns possible variations of the transformation - as a list of tuples (id, title). This is mostly - useful in ERP5Form instances to generate selection - menus. - """ - return self.portal_categories.getItemList( - self.getVariationRangeBaseCategoryList(), - display_id=display_id, **kw) - - security.declareProtected(Permissions.AccessContentsInformation, - 'getVariationRangeCategoryItemList') - def getVariationRangeCategoryItemList(self, base_category_list=(), - omit_individual_variation=0, - display_base_category=1, **kw): - """ - Returns possible variation category values for the - transformation according to the default resource. - Possible category values are provided as a list of - tuples (id, title). This is mostly - useful in ERP5Form instances to generate selection - menus. - User may want to define generic transformation without - any defined resource. - """ - if base_category_list is (): - base_category_list = self.getVariationBaseCategoryList() - - resource = self.getResourceValue() - if resource is not None: - result = resource.getVariationCategoryItemList( - base_category_list=base_category_list, - omit_individual_variation=omit_individual_variation, - display_base_category=display_base_category,**kw) - else: - # 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 - - 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=(), base=1, - display_id='title', - current_category=None, - **kw): - """ - 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() - - category_renderer = Renderer( - is_right_display=0, - display_none_category=0, base=base, - current_category=current_category, - display_id='logical_path', **kw) - - for base_category in base_category_list: - variation_category_list = self.getVariationCategoryList( - base_category_list=[base_category]) - - category_list = [] - object_list = [] - for variation_category in variation_category_list: - resource = self.portal_categories.resolveCategory(variation_category) - if resource.getPortalType() == 'Category': - category_list.append(resource) - else: - object_list.append(resource) - - variation_category_item_list.extend(category_renderer.\ - render(category_list)) - - variation_category_item_list.extend(Renderer( - is_right_display=0, - base_category=base_category, - display_none_category=0, base=base, - current_category=current_category, - display_id=display_id,**kw).\ - render(object_list)) - return variation_category_item_list - - def updateAggregatedAmountList(self, context, **kw): - raise NotImplementedError, 'need?' - - security.declareProtected(Permissions.AccessContentsInformation, - 'getAggregatedAmountList') - def getAggregatedAmountList(self, context=None, REQUEST=None, - trade_phase_list=None, - # obsolete, use trade_phase_list instead - ind_phase_url_list=None, - rejected_resource_uid_list=None, - **kw): - """ - getAggregatedAmountList returns an AggregatedAmountList which - can be used either to do some calculation (ex. price, BOM) - or to display a detailed view of a transformation. - """ - if isinstance(context, list): - context = context[0] - if context is None: - warn("Calling Transformation.getAggregatedAmountList without context " \ - "is wrong. Context should be an Amount defining the resource to " \ - "produce", DeprecationWarning) - from Products.ERP5Type.Document import newTempAmount - context = newTempAmount(self, "deprecated_usage") - context.setResourceValue(self.getResourceValue()) - context.setQuantity(1.0) - - - # A list of functions taking a transformation_line as sole argument - # and returning True iif the line should be kept in the result - filter_list = [] - - # Get only lines related to a precise trade_phase - if trade_phase_list is not None: - def trade_phase_filter(line): - return line.getTradePhase() in trade_phase_list - - filter_list.append(trade_phase_filter) - - # Get only lines related to a precise industrial_phase - if ind_phase_url_list is not None: - LOG("Transformation", WARNING, "ind_phase_list is obsolete") - def industrial_phase_filter(line): - ind_ph = line.getIndustrialPhaseValue() - if ind_ph is not None: - return ind_ph.getRelativeUrl() in ind_phase_url_list - return False - - filter_list.append(industrial_phase_filter) - - # Filter lines with resource we do not want to see - if rejected_resource_uid_list is not None: - def rejected_uid_filter(line): - return line.getResourceUid() not in rejected_resource_uid_list - - filter_list.append(rejected_uid_filter) - - def line_is_included(line): - # XXX > 2.5 : all(f(line) for f in filter_list) - for filterr in filter_list: - if not filterr(line): - return False - return True - - # First we need to get the list of transformations which this - # transformation depends on - # At this moment, we only consider 1 dependency - template_transformation_list = self.getSpecialiseValueList() - - # 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 - result = AggregatedAmountList() - for transformation in ([self] + template_transformation_list): - for transformation_line in transformation.objectValues(): - # Browse each transformed or assorted resource of the current - # transformation - if line_is_included(transformation_line): - try: - line_result = transformation_line.getAggregatedAmountList(context) - except KeyError: - # KeyError is raised by TransformedResource.getAggregatedAmountList - # in case of misconfiguration of a Cell. - # Just ignore the line - pass - else: - result.extend(line_result) - - return result diff --git a/bt5/erp5_simulation_legacy/DocumentTemplateItem/TransformedResource.py b/bt5/erp5_simulation_legacy/DocumentTemplateItem/TransformedResource.py deleted file mode 100644 index d3991ab213..0000000000 --- a/bt5/erp5_simulation_legacy/DocumentTemplateItem/TransformedResource.py +++ /dev/null @@ -1,334 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# Copyright (c) 2002, 2004 Nexedi SARL and Contributors. All Rights Reserved. -# Jean-Paul Smets-Solanes <jp@nexedi.com> -# Romain Courteaud <romain@nexedi.com> -# -# 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. -# -############################################################################## -import zope.interface - -from warnings import warn -from AccessControl import ClassSecurityInfo - -from Products.ERP5Type import Permissions, PropertySheet, interfaces -from Products.ERP5Type.XMLObject import XMLObject -from Products.ERP5Type.XMLMatrix import XMLMatrix - -from Products.ERP5.Document.Amount import Amount -from Products.ERP5.AggregatedAmountList import AggregatedAmountList - -from Products.ERP5.Document.Predicate import Predicate - -class TransformedResource(Predicate, XMLObject, XMLMatrix, Amount): - """ - TransformedResource defines which - resource is being transformed - - - variation - - quantity - - Maybe defined by mapped values inside the transformed resource - - XXX Transformation works only for a miximum of 3 variation base category... - Matrixbox must be rewrite for a clean implementation of n base category - - - """ - - meta_type = 'ERP5 Transformed Resource' - portal_type = 'Transformed Resource' - - # Declarative security - security = ClassSecurityInfo() - security.declareObjectProtected(Permissions.AccessContentsInformation) - - # Declarative properties - property_sheets = ( PropertySheet.Base - , PropertySheet.SimpleItem - , PropertySheet.CategoryCore - , PropertySheet.Amount - , PropertySheet.Reference - , PropertySheet.TransformedResource - ) - - # Declarative interfaces - zope.interface.implements(interfaces.IAmountGenerator,) - - ### Variation matrix definition - # - 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, - '_setQVariationBaseCategoryList') - def _setQVariationBaseCategoryList(self, value): - """ - Defines the possible base categories which Quantity value (Q) - variate on - """ - self._baseSetQVariationBaseCategoryList(value) - self._updateCellRange('quantity') - - 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() - - security.declareProtected(Permissions.ModifyPortalContent, - '_setVVariationBaseCategoryList') - def _setVVariationBaseCategoryList(self, value): - """ - Defines the possible base categories which Variation value (V) - variate on - """ - self._baseSetVVariationBaseCategoryList(value) - self._updateCellRange('variation') - - 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() - - def updateAggregatedAmountList(self, context, **kw): - raise NotImplementedError('TODO') - - security.declareProtected(Permissions.AccessContentsInformation, - 'getAggregatedAmountList') - def getAggregatedAmountList(self, context, REQUEST=None, **kw): - """ - Get all interesting amount value and return AggregatedAmountList - """ - # Create the result object - aggregated_amount_list = AggregatedAmountList() - test_result = self.test(context) - if test_result: - # The line must match the context - # If no predicate is defined on line, the result of the test - # must be true - # Create temporary object to store amount - parent = self.getParentValue() - # Be careful: this id must be unique, and change when the context is - # changing. Failure to do so exposes to possible erroneous cache hits - # for physical path based caching. - tmp_id = '_'.join((parent.getId(), self.getId(), context.getId())) - tmp_amount = parent.newContent(id=tmp_id, - temp_object=1, portal_type=self.getPortalType()) - # Create error string - error_string = '' - # Add resource relation - resource = self.getDefaultResourceValue() - if resource is not None: - tmp_amount.setResourceValue(resource) - else: - error_string += 'No resource defined on %s' % self.getRelativeUrl() - # 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 - # Set quantity unit - quantity_unit = self.getQuantityUnit() - if quantity_unit is not None: - tmp_amount.setQuantityUnitValue(quantity_unit) - # Set efficiency - efficiency = self.getEfficiency() - if efficiency is None or efficiency is '' or efficiency == 0.0: - efficiency = 1.0 - else: - efficiency = float(efficiency) -### current get quantity comportment exemple ### -# We define on transformation line: -# default_quantity = q -# quantity matrix -# | Child | Child/32 | Child/34 | Men | Women | -# | a | | b | c | | -# Result from getAggregatedAmountList: -# context | quantity -# _________________________ -# Child | a -# Child/32 | a => acquired from Child -# Child/34 | a or b => we do not know which cell will be choosed -# Child/36 | a => acquired from Child -# Men | c -# Women | Error => no cell found -# noContext | Error => cell exist, but no context given - -### comportment that JPS want ?? ### -# We define on transformation line: -# default_quantity = q -# quantity matrix -# | Child | Child/32 | Child/34 | Men | Women | -# | a | | b | c | | -# Result from getAggregatedAmountList: -# context | quantity -# _________________________ -# Child | a -# Child/32 | a => acquired from Child -# Child/34 | a or b => we do not know which cell will be choosed -# Child/36 | Error => no such key in matrixbox cell range -# Men | c -# Women | Error => no cell found -# noContext | Error => cell exist, but no context given - -# futur cool get quantity comportment exemple -# We define on transformation line: -# default_quantity = q -# quantity matrix -# | Child | Child/32 | Child/34 | Men | Women | -# | a | | b | c | | -# Result from getAggregatedAmountList: -# context | quantity -# _________________________ -# Child | a -# Child/32 | a => acquired from Child -# Child/34 | b => test method must return a priority to choose between Child and Child/34 -# Child/36 | Error => no such key in matrixbox cell range -# Men | c -# Women | q => acquired from default quantity -# noContext | q => acquired from default quantity - - # get Quantity - quantity_defined_by = None - quantity = None - # We will browse the mapped values and determine which apply - cell_key_list = self.getCellKeyList(base_id='quantity') - if cell_key_list not in [(),[]]: - if context is None: - raise KeyError, \ - "No context defined on TransformedResource '%s'" % \ - (self.getRelativeUrl(), ) - for key in cell_key_list: - 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,'']: - raise KeyError, \ - "No cell quantity matching on TransformedResource '%s' for "\ - "current context" % ( self.getRelativeUrl() , ) - else: - quantity = self.getQuantity() - quantity_defined_by = self.getRelativeUrl() - if quantity in [None,'']: - raise KeyError, \ - "No quantity defined on TransformedResource '%s' for "\ - "current context" % (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 ValueError: - error_string += 'Quantity is not a float.' - - # If IAmount specifies that 4 resources are needed, all quantities - # need to be multiplicated by 4... - context_quantity = None - quantity_getter = getattr(context, "getQuantity", None) - if quantity_getter is not None: - _marker = object() - context_quantity = quantity_getter(_marker) - if context_quantity is _marker: - # XXX Backwards compatibility: - # previously, quantity property of the Amount was completely - # ignored, and was assumed to be 1.0 . Re-enact this old - # behavior (quantity default value is 0.0) to avoid breakages - warn("No quantity was defined on the Amount passed to " \ - "getAggregatedAmountList, 1.0 was assumed", DeprecationWarning) - context_quantity = 1.0 - else: - raise KeyError("No quantity defined on context") - quantity *= float(context_quantity) - - # Get the variation category list - variation_category_list_defined_by = None - variation_category_list = None - # We will browse the mapped values and determine which apply - cell_key_list = self.getCellKeyList( base_id = 'variation') - if cell_key_list not in [(),[]]: - if context is None: - raise KeyError, \ - "No context defined on TransformedResource '%s'" % \ - (self.getRelativeUrl(), ) - for key in cell_key_list: - 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,'',[], ()]: - if quantity == 0: - return aggregated_amount_list - else: - raise KeyError, \ - "No cell variation matching on TransformedResource '%s' "\ - "for current context" % (self.getRelativeUrl(), ) - else: - variation_category_list = self._getVariationCategoryList() - variation_category_list_defined_by = self.getRelativeUrl() - if hasattr(self,"getTradePhase"): - # After installing BPM, trade_phase category to be exists - trade_phase = self.getTradePhase() - else: - trade_phase = None - # Store values in Amount - tmp_amount._edit( - # Properties define on transformation line - title=self.getTitle(), - 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, - trade_phase=trade_phase, - error_string=error_string - ) - tmp_amount.setVariationCategoryList(variation_category_list) - # Variation property dict - tmp_amount.setVariationPropertyDict(self.getVariationPropertyDict()) - aggregated_amount_list.append(tmp_amount) - return aggregated_amount_list diff --git a/bt5/erp5_simulation_legacy/bt/template_document_id_list b/bt5/erp5_simulation_legacy/bt/template_document_id_list index e3331613d0..25df69c417 100644 --- a/bt5/erp5_simulation_legacy/bt/template_document_id_list +++ b/bt5/erp5_simulation_legacy/bt/template_document_id_list @@ -11,6 +11,4 @@ ProductionOrderModelRootSimulationRule ProductionOrderRootSimulationRule RootAppliedRuleCausalityMovementGroup SimulationLegacyPatches -TradeModelSimulationRule -Transformation -TransformedResource \ No newline at end of file +TradeModelSimulationRule \ No newline at end of file diff --git a/product/ERP5/Document/AssortedResource.py b/product/ERP5/Document/AssortedResource.py index 97cc4a6856..09201e2ff4 100644 --- a/product/ERP5/Document/AssortedResource.py +++ b/product/ERP5/Document/AssortedResource.py @@ -31,6 +31,7 @@ from AccessControl import ClassSecurityInfo from Products.ERP5Type import Permissions, PropertySheet, Constraint from Products.ERP5Type.XMLMatrix import XMLMatrix from Products.ERP5Type.Utils import cartesianProduct +from Products.ERP5.Document.AmountGeneratorLine import AmountGeneratorLine from Products.ERP5.Document.TransformedResource import TransformedResource from Products.ERP5Type.Base import TempBase @@ -114,14 +115,6 @@ class AssortedResource(TransformedResource): security = ClassSecurityInfo() security.declareObjectProtected(Permissions.AccessContentsInformation) - # Declarative properties - property_sheets = ( PropertySheet.Base - , PropertySheet.SimpleItem - , PropertySheet.CategoryCore - , PropertySheet.Amount - , PropertySheet.TransformedResource - ) - # Local property sheet _properties = ( { 'id' : 'variation_base_category', @@ -138,6 +131,8 @@ class AssortedResource(TransformedResource): 'mode' : 'w' }, ) + getCellAggregateKey = AmountGeneratorLine.getCellAggregateKey + security.declareProtected(Permissions.AccessContentsInformation, 'getAssortedVariationCategoryList') def getAssortedVariationCategoryList(self, cell_index): """ @@ -500,8 +495,8 @@ class AssortedResource(TransformedResource): return error_list - security.declareProtected(Permissions.AccessContentsInformation, 'getAggregatedAmountList') - def getAggregatedAmountList(self, REQUEST): + if 0: # obsolete + def getAggregatedAmountList(self, REQUEST): # 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 diff --git a/product/ERP5/Document/SupplyLink.py b/product/ERP5/Document/SupplyLink.py index b6abcb911e..425b76142a 100644 --- a/product/ERP5/Document/SupplyLink.py +++ b/product/ERP5/Document/SupplyLink.py @@ -139,7 +139,7 @@ class SupplyLink(Path, XMLObject): supply_chain.getNextProductionIndustrialPhaseList(self) # XXX GetRelativeUrl copy/paste from transformation # Code duplication - ind_phase_url_list = [x.getRelativeUrl() \ + ind_phase_url_list = [x.getCategoryRelativeUrl() for x in next_industrial_phase_list] # Get the transformation to use @@ -147,10 +147,11 @@ class SupplyLink(Path, XMLObject): rule = applied_rule.getSpecialiseValue() transformation = rule.getTransformation(movement) # Call getAggregatedAmountList - amount_list = transformation.getAggregatedAmountList( - movement.getParentValue().getParentValue(), - ind_phase_url_list=ind_phase_url_list) - resource_list = [x.getResourceValue() for x in amount_list] + tmp_context = movement.getParentValue().getParentValue().asContext() + tmp_context.asComposedDocument = lambda *args: transformation + resource_list = [x.getResourceValue() + for x in tmp_context.getAggregatedAmountList() + if x.getCausalityValue().getIndustrialPhase() in ind_phase_url_list] current_resource = movement.getResourceValue() if current_resource not in resource_list: # We can delivered this resource diff --git a/product/ERP5/Document/TransformedResource.py b/product/ERP5/Document/TransformedResource.py index 4a9802ecf7..21fb470db0 100644 --- a/product/ERP5/Document/TransformedResource.py +++ b/product/ERP5/Document/TransformedResource.py @@ -29,21 +29,13 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ############################################################################## -import zope.interface -from warnings import warn from AccessControl import ClassSecurityInfo - from Products.ERP5Type import Permissions, PropertySheet, interfaces -from Products.ERP5Type.XMLObject import XMLObject -from Products.ERP5Type.XMLMatrix import XMLMatrix - -from Products.ERP5.Document.Amount import Amount -from Products.ERP5.Document.MappedValue import MappedValue +from Products.ERP5.Document.AmountGeneratorLine import AmountGeneratorLine -from Products.ERP5.Document.Predicate import Predicate -class TransformedResource(MappedValue, XMLMatrix, Amount): +class TransformedResource(AmountGeneratorLine): """ TransformedResource defines which resource is being transformed in order to produce a product define in the parent Transformation @@ -51,8 +43,8 @@ class TransformedResource(MappedValue, XMLMatrix, Amount): TODO: - transformations used to work perfectly for more than 3 dimensions - of variations. However, this feature was broken with time and - is no longer usable. It is time to reimplement it. This is + of variations. However, this feature was broken with time and + is no longer usable. It is time to reimplement it. This is completely unrelated to MatrixBox reimplementation unlike what is stated in some comments. """ @@ -65,18 +57,8 @@ class TransformedResource(MappedValue, XMLMatrix, Amount): security.declareObjectProtected(Permissions.AccessContentsInformation) # Declarative properties - property_sheets = ( PropertySheet.Base - , PropertySheet.SimpleItem - , PropertySheet.CategoryCore - , PropertySheet.Amount - , PropertySheet.Reference - , PropertySheet.TransformedResource - ) - - # Declarative interfaces - zope.interface.implements(interfaces.IAmountGenerator, - interfaces.IVariated, - interfaces.IVariationRange,) + property_sheets = (PropertySheet.TransformedResource, ) + ### Mapped Value Definition # Provide default mapped value properties and categories if # not defined @@ -91,30 +73,41 @@ class TransformedResource(MappedValue, XMLMatrix, Amount): result = self.getVariationRangeBaseCategoryList() # The current resource variation return result + def getCellAggregateKey(self): + """Define a key in order to aggregate amounts at cell level""" + return None + + @classmethod + def getBaseAmountQuantity(cls, delivery_amount, base_application, rounding): + value = delivery_amount.getGeneratedAmountQuantity(base_application) + if base_application == 'produced_quantity': + value += delivery_amount.getQuantity() + return value + def getBaseApplication(self): """ - + """ + return self.getBaseApplicationList()[0] + + def getBaseApplicationList(self): + """ """ # It is OK to try to acquire - if getattr(self, '_baseGetBaseApplication', None) is not None: - result = self._baseGetBaseApplication() - if result: - return result - return 'produced_quantity' + return self._categoryGetBaseApplicationList() or ['produced_quantity'] ### Variation matrix definition # XXX-JPS Some explanation needed - security.declareProtected(Permissions.AccessContentsInformation, + security.declareProtected(Permissions.AccessContentsInformation, 'updateVariationCategoryList') def updateVariationCategoryList(self): """ - Check if variation category list of the resource changed and + 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, + security.declareProtected(Permissions.ModifyPortalContent, '_setQVariationBaseCategoryList') def _setQVariationBaseCategoryList(self, value): """ @@ -124,7 +117,7 @@ class TransformedResource(MappedValue, XMLMatrix, Amount): self._baseSetQVariationBaseCategoryList(value) self._updateCellRange('quantity') - security.declareProtected(Permissions.ModifyPortalContent, + security.declareProtected(Permissions.ModifyPortalContent, '_setVVariationBaseCategoryList') def _setVVariationBaseCategoryList(self, value): """ @@ -137,7 +130,7 @@ class TransformedResource(MappedValue, XMLMatrix, Amount): # XXX-JPS This should be handled by interaction workflow or interactor # XXX-JPS SO many cases are not handled well... - security.declareProtected(Permissions.ModifyPortalContent, + security.declareProtected(Permissions.ModifyPortalContent, 'setVVariationBaseCategoryList') def setVVariationBaseCategoryList(self, value): """ diff --git a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_catalogTransformation.xml b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_catalogTransformation.xml index 2c7c338c55..6840db5f81 100644 --- a/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_catalogTransformation.xml +++ b/product/ERP5/bootstrap/erp5_mysql_innodb_catalog/CatalogMethodTemplateItem/portal_catalog/erp5_mysql_innodb/SQLCatalog_catalogTransformation.xml @@ -75,13 +75,14 @@ for transformation_relative_url, variation_list_list in transformation_item_list continue\n for variation_list in variation_list_list:\n movement = newTempMovement(resource, \'temp\',\n + specialise_value=transformation,\n variation_category_list=variation_list,\n - resource=resource.getRelativeUrl(),\n + resource_value=resource,\n quantity=1.0)\n base_row = dict(uid=resource.getUid(), variation_text=movement.getVariationText())\n \n row_dict_list = []\n - for amount in transformation.getAggregatedAmountList([movement]):\n + for amount in movement.getAggregatedAmountList():\n transformed_resource_uid = amount.getResourceUid()\n quantity = amount.getQuantity()\n if transformed_resource_uid is not None and quantity is not None:\n diff --git a/product/ERP5/mixin/amount_generator.py b/product/ERP5/mixin/amount_generator.py index fe113164cb..b7249e866f 100644 --- a/product/ERP5/mixin/amount_generator.py +++ b/product/ERP5/mixin/amount_generator.py @@ -234,7 +234,9 @@ class AmountGeneratorMixin: # Then collect the mapped values (quantity, price, trade_phase...) for key in cell.getMappedValuePropertyList(): # XXX-JPS Make sure handling of list properties can be handled - property_dict[key] = cell.getProperty(key) + dict_key = key in ('net_quantity', 'converted_quantity', + 'net_converted_quantity') and 'quantity' or key + property_dict[dict_key] = cell.getProperty(key) category_list = cell.getAcquiredCategoryMembershipList( cell.getMappedValueBaseCategoryList(), base=1) property_dict['category_list'] += category_list @@ -279,14 +281,10 @@ class AmountGeneratorMixin: # (XXX is it OK ?) XXX-JPS Need careful review with taxes quantity = float(sum(map(base_amount.getGeneratedAmountQuantity, base_application_set))) - for quantity_key in ('net_quantity', 'converted_quantity', - 'net_converted_quantity', 'quantity'): - if quantity_key in property_dict: - try: - quantity *= property_dict.pop(quantity_key) - except TypeError: # None or '' - pass - break + try: + quantity *= property_dict.pop('quantity', 1) + except TypeError: # None or '' + pass if not quantity: continue # Backward compatibility diff --git a/product/ERP5Legacy/Document/TransformationRule.py b/product/ERP5Legacy/Document/TransformationRule.py index 6573b6ab9e..1397f2638f 100644 --- a/product/ERP5Legacy/Document/TransformationRule.py +++ b/product/ERP5Legacy/Document/TransformationRule.py @@ -217,24 +217,27 @@ class TransformationRule(TransformationSourcingRuleMixin, Rule): base_category_list=base_category_list) # Get the transformation to use transformation = self.getTransformation(applied_rule) - # Generate the fake context - tmp_context = parent_movement.asContext( - context=parent_movement, - REQUEST={'categories':category_list}) + # Generate the fake context + tmp_context = parent_movement.asContext(categories=category_list) + tmp_context.asComposedDocument = lambda *args: transformation # Calculate the industrial phase list previous_ind_phase_list = supply_chain.\ getPreviousPackingListIndustrialPhaseList(current_supply_link) - ind_phase_id_list = [x.getRelativeUrl() for x in previous_ind_phase_list] + ind_phase_url_list = [x.getCategoryRelativeUrl() + for x in previous_ind_phase_list] # Call getAggregatedAmountList # XXX expand failed if transformation is not defined. # Do we need to catch the exception ? - amount_list = transformation.getAggregatedAmountList( - tmp_context, - ind_phase_url_list=ind_phase_id_list) + amount_list = tmp_context.getAggregatedAmountList() # Add entries in the consumed_movement_dict consumed_movement_dict = {} for amount in amount_list: - consumed_mvt_id = "%s_%s" % ("cr", amount.getId()) + model_line = amount.getCausalityValue() + if model_line.getIndustrialPhase() not in ind_phase_url_list: + continue + consumed_mvt_id = "cr_%s_%s_%s" % (model_line.getParentId(), + model_line.getId(), + tmp_context.getId()) stop_date = parent_movement.getStartDate() resource_price = amount.getResourcePrice() price = None @@ -248,7 +251,7 @@ class TransformationRule(TransformationSourcingRuleMixin, Rule): amount.getVariationCategoryList(), "variation_property_dict": \ amount.getVariationPropertyDict(), - "quantity": amount.getNetQuantity(), # getNetQuantity to support efficency from transformation + "quantity": amount.getNetQuantity(), # getNetQuantity to support efficency from < "price": price, "quantity_unit": amount.getQuantityUnit(), "destination_list": (), diff --git a/product/ERP5Legacy/tests/testLegacyProductionOrder.py b/product/ERP5Legacy/tests/testLegacyProductionOrder.py index 832ac06757..1067da5066 100644 --- a/product/ERP5Legacy/tests/testLegacyProductionOrder.py +++ b/product/ERP5Legacy/tests/testLegacyProductionOrder.py @@ -65,7 +65,8 @@ class TestProductionOrderMixin(TestOrderMixin): def getBusinessTemplateList(self): """ """ - return TestOrderMixin.getBusinessTemplateList(self) + ('erp5_mrp',) + return TestOrderMixin.getBusinessTemplateList(self) + ( + 'erp5_mrp', 'erp5_mrp_simulation_legacy') def setUpPreferences(self): portal = self.getPortal() -- 2.30.9