Commit e2075796 authored by Julien Muchembled's avatar Julien Muchembled

Review new amount generator

- Update API and interfaces
- Make it possible to:
  - do non-linear calculation (via global type-based script)
    for every considered base_amount
    (i.e. not only for base_application of input movements).
    To avoid performance issue, the type-based script is changed to return
    functions instead of calculating results directly.
  - get accumulated values from movements while generating amounts for a
    delivery (i.e. for Amount Generator Lines targetting deliveries).
- Produce amounts even if there is no resource, for reporting.
- Drop probably useless create_line property: checking if there is a resource
  should be enough.
- Prepare refactoring of MRP/Trade/Payroll by introducing AmountGeneratorLine
  class and property sheet.
- Stop doing anything if there is no base_application on an AGL to avoid
  conflicts while figuring out if a movement was created manually or not.
- Update some forms.
- Update testTradeModelLine

git-svn-id: https://svn.erp5.org/repos/public/erp5/sandbox/amount_generator@39028 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 4c416f78
......@@ -270,10 +270,7 @@
<string>my_view_mode_trade_date</string>
<string>my_view_mode_base_application_list</string>
<string>my_view_mode_calculation_script_id</string>
<string>my_view_mode_create_line</string>
<string>my_view_mode_ratio_price</string>
<string>my_view_mode_fixed_quantity</string>
<string>my_view_mode_target_level</string>
<string>my_core_mode_total_price</string>
<string>my_view_mode_listbox_read_only_start_date</string>
<string>my_report_mode_aggregation_level</string>
......@@ -305,6 +302,7 @@
<string>my_view_mode_listbox_movement_relative_url</string>
<string>my_view_mode_movement_listbox_price</string>
<string>my_view_mode_movement_listbox_quantity</string>
<string>my_view_mode_target_delivery</string>
</list>
</value>
</item>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<tuple>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>description</string>
<string>title</string>
<string>default</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_view_mode_fixed_quantity</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>default</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>description</string> </key>
<value> <string>Trade Model Line with a Fixed Quantity. If this is set, Ratio is ignored.</string> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_view_mode_quantity</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Fixed Quantity</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<tuple>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python:test(here.getQuantity(None) is None, \'\', here.getQuantity())</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -12,12 +12,14 @@
<item>
<key> <string>delegated_list</string> </key>
<value>
<list/>
<list>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_create_line</string> </value>
<value> <string>my_view_mode_target_delivery</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
......@@ -74,16 +76,20 @@
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_view_mode_create_line</string> </value>
<value> <string>my_checkbox</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewTradeFieldLibrary</string> </value>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Target Delivery</string> </value>
</item>
</dictionary>
</value>
</item>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<tuple>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>title</string>
<string>items</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_view_mode_target_level</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>items</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_list_field</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Target Level</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<tuple>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python:((\'\', \'\'), (\'Delivery Level\', modules[\'Products.ERP5.PropertySheet.TradeModelLine\'].TARGET_LEVEL_DELIVERY), (\'Movement Level\', modules[\'Products.ERP5.PropertySheet.TradeModelLine\'].TARGET_LEVEL_MOVEMENT))</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -107,8 +107,8 @@
<string>my_resource_title</string>
<string>my_price</string>
<string>my_quantity</string>
<string>my_efficiency</string>
<string>my_create_line</string>
<string>my_trade_phase</string>
<string>my_use</string>
</list>
</value>
</item>
......@@ -116,10 +116,9 @@
<key> <string>right</string> </key>
<value>
<list>
<string>my_trade_phase</string>
<string>my_target_delivery</string>
<string>my_base_application_list</string>
<string>my_base_contribution_list</string>
<string>my_use</string>
</list>
</value>
</item>
......
......@@ -74,11 +74,11 @@
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_view_mode_fixed_quantity</string> </value>
<value> <string>my_view_mode_amount_generator_quantity</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewTradeFieldLibrary</string> </value>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
......
......@@ -17,7 +17,7 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_efficiency</string> </value>
<value> <string>my_target_delivery</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
......@@ -74,7 +74,7 @@
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_view_mode_efficiency</string> </value>
<value> <string>my_view_mode_target_delivery</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
......
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010 Nexedi SA and Contributors. All Rights Reserved.
#
# 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 AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5Type.XMLMatrix import XMLMatrix
from Products.ERP5.Document.Amount import Amount
from Products.ERP5.Document.MappedValue import MappedValue
from Products.ERP5.mixin.amount_generator import AmountGeneratorMixin
class AmountGeneratorLine(MappedValue, XMLMatrix, Amount,
AmountGeneratorMixin):
"""Abstract class to represent amount transformation for movements"""
meta_type = 'ERP5 Amount Generator Line'
portal_type = 'Amount Generator Line'
# Declarative security
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative interfaces
zope.interface.implements(interfaces.IAmountGeneratorLine)
# Declarative properties
property_sheets = (PropertySheet.AmountGeneratorLine, )
security.declareProtected(Permissions.AccessContentsInformation,
'getCellAggregateKey')
def getCellAggregateKey(self):
"""Define a key in order to aggregate amounts at cell level"""
return (self.getResource(),
self.getVariationText()) # Variation UID, Hash ?
security.declareProtected(Permissions.AccessContentsInformation,
'getBaseAmountQuantity')
@classmethod
def getBaseAmountQuantity(cls, delivery_amount, base_application, rounding):
"""Default method to compute quantity for the given base_application"""
value = delivery_amount.getGeneratedAmountQuantity(base_application)
if base_application in delivery_amount.getBaseContributionList():
value += cls._getBaseAmountQuantity(delivery_amount)
return value
@classmethod
def _getBaseAmountQuantity(cls, delivery_amount):
"""Get default quantity contributed by the input amount"""
raise NotImplementedError
......@@ -28,19 +28,11 @@
#
##############################################################################
import zope.interface
from AccessControl import ClassSecurityInfo
from Products.CMFCore.utils import getToolByName
from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5Type.XMLMatrix import XMLMatrix
from Products.ERP5.Document.Amount import Amount
from Products.ERP5.Document.MappedValue import MappedValue
from Products.ERP5.AggregatedAmountList import AggregatedAmountList
from Products.ERP5.Document.TradeCondition import TradeCondition
from Products.ERP5.mixin.amount_generator import AmountGeneratorMixin
import zope.interface
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5.Document.AmountGeneratorLine import AmountGeneratorLine
class TradeModelLine(MappedValue, XMLMatrix, Amount, AmountGeneratorMixin):
class TradeModelLine(AmountGeneratorLine):
"""Trade Model Line is a way to represent trade transformation for movements"""
meta_type = 'ERP5 Trade Model Line'
portal_type = 'Trade Model Line'
......@@ -49,34 +41,18 @@ class TradeModelLine(MappedValue, XMLMatrix, Amount, AmountGeneratorMixin):
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative interfaces
zope.interface.implements(
interfaces.IAmountGenerator,
interfaces.IVariated
)
# Declarative properties
property_sheets = ( PropertySheet.Base
, PropertySheet.SimpleItem
, PropertySheet.CategoryCore
, PropertySheet.Amount
, PropertySheet.Price
, PropertySheet.TradeModelLine
, PropertySheet.Reference
, PropertySheet.Predicate
, PropertySheet.MappedValue
)
property_sheets = (PropertySheet.TradeModelLine, )
# XXX to be specificied in an interface (IAmountGeneratorLine ?)
def getAmountProperty(self, amount, base_application, amount_list, rounding):
"""
Produced amount quantity is needed to initialize transformation
"""
return amount.getTotalPrice()
@classmethod
def _getBaseAmountQuantity(cls, delivery_amount):
return delivery_amount.getTotalPrice()
### Mapped Value Definition
# Provide default mapped value properties and categories if
# not defined
security.declareProtected(Permissions.AccessContentsInformation,
'getMappedValuePropertyList')
def getMappedValuePropertyList(self):
"""
"""
......@@ -90,10 +66,7 @@ class TradeModelLine(MappedValue, XMLMatrix, Amount, AmountGeneratorMixin):
return ('price', 'efficiency')
def getMappedValueBaseCategoryList(self):
result = self._baseGetMappedValueBaseCategoryList()
if result:
return result
return ('base_contribution', 'trade_phase', )
return self._baseGetMappedValueBaseCategoryList() or ('trade_phase',)
#
security.declareProtected(Permissions.AccessContentsInformation,
......
......@@ -104,14 +104,15 @@ class TradeModelRuleMovementGenerator(MovementGeneratorMixin):
amount_generator_type_list=('Purchase Trade Condition',
'Sale Trade Condition',
'Trade Model Line')):
# FIXME: Is it the right way to have source/destination and other
# non-Amount properties set on the generated movement ?
movement = input_movement.asContext(**dict((k, v)
for k, v in amount.__dict__.iteritems()
if k[0] != '_' and k != 'categories'))
base_category_set = set(amount.getBaseCategoryList())
base_category_set.remove('price_currency') # XXX
movement._setCategoryMembership(base_category_set,
amount.getCategoryList(),
base=True)
yield movement
if amount.getResource():
# FIXME: Is it the right way to have source/destination and other
# non-Amount properties set on the generated movement ?
movement = input_movement.asContext(**dict((k, v)
for k, v in amount.__dict__.iteritems()
if k[0] != '_' and k != 'categories'))
base_category_set = set(amount.getBaseCategoryList())
base_category_set.remove('price_currency') # XXX
movement._setCategoryMembership(base_category_set,
amount.getCategoryList(),
base=True)
yield movement
......@@ -81,17 +81,15 @@ class TransformedResource(MappedValue, XMLMatrix, Amount):
# Provide default mapped value properties and categories if
# not defined
def getMappedValuePropertyList(self):
result = self._baseGetMappedValuePropertyList()
if result:
return result
return ('quantity',)
return self._baseGetMappedValuePropertyList() or (
'converted_quantity', 'efficiency')
def getMappedValueBaseCategoryList(self):
result = self._baseGetMappedValueBaseCategoryList()
if not result:
if not self.hasCellContent(base_id='variation'):
result = self.getVariationRangeBaseCategoryList() # The current resource variation
return list(result) + ['quantity_unit']
return result
def getBaseApplication(self):
"""
......
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010 Nexedi SA and Contributors. All Rights Reserved.
#
# 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.
#
##############################################################################
class AmountGeneratorLine:
"""
Properties for amount generator lines
"""
_properties = (
{ 'id' : 'target_delivery',
'description' : "Defines if amount generator line should be applied on"
" delivery (e.g. a stamp on an order) instead of"
" movements (e.g. VAT to every order line).",
'type' : 'boolean',
'mode' : 'w',
},
)
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2009 Nexedi SA and Contributors. All Rights Reserved.
# Łukasz Nowak <luke@nexedi.com>
# Copyright (c) 2010 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
......@@ -26,23 +25,10 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from AccessControl import ModuleSecurityInfo
class TradeModelLine:
"""
Properties for trade model lines
"""
_properties = (
{ 'id' : 'create_line',
'description' : 'A flag indicating if the corresponding line will'
' be created',
'type' : 'boolean',
'mode' : 'w',
'default' : True,
},
)
_categories = (
'base_application', 'base_contribution', 'trade_phase',
)
_categories = ('trade_phase',)
......@@ -182,6 +182,7 @@
<string>listbox_modification_date</string>
<string>listbox_creation_date</string>
<string>listbox_owner_title</string>
<string>my_view_mode_amount_generator_quantity</string>
</list>
</value>
</item>
......
......@@ -2,10 +2,7 @@
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<tuple>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
<tuple/>
</tuple>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
......@@ -13,15 +10,13 @@
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>description</string>
<string>title</string>
<string>default</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_view_mode_create_line</string> </value>
<value> <string>my_view_mode_amount_generator_quantity</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
......@@ -83,12 +78,12 @@
<value>
<dictionary>
<item>
<key> <string>description</string> </key>
<value> <string>Useful for intermediated lines.</string> </value>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_checkbox</string> </value>
<value> <string>my_quantity</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
......@@ -98,10 +93,6 @@
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Create Line</string> </value>
</item>
</dictionary>
</value>
</item>
......@@ -110,16 +101,13 @@
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<tuple>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
<tuple/>
</tuple>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>here/isCreateLine</string> </value>
<value> <string>python: here.getQuantity(None)</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -82,3 +82,33 @@ class IAmountGenerator(Interface):
- implement rounding appropriately (True or False seems
simplistic)
"""
class IAmountGeneratorLine(Interface):
"""Amount Generator Line interface specification
"""
def getCellAggregateKey():
"""Define a key in order to aggregate amounts at cell level
Transformed Resource (Transformation)
key must be None because:
- quantity and variation are defined in different cells so that the
user does not need to enter values depending on all axes
- amount_generator_cell.test should filter only 1 variant
current key = (acquired resource, acquired variation)
Assorted Resource (Transformation)
key = (assorted resource, assorted resource variation)
usually resource and quantity provided together
Payroll
key = (payroll resource, payroll resource variation)
Tax
key = (tax resource, tax resource variation)
"""
def getBaseAmountQuantity(delivery_amount, base_application, rounding):
"""Default method to compute quantity for the given base_application
"""
This diff is collapsed.
......@@ -33,9 +33,7 @@ import transaction
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from DateTime import DateTime
from Products.CMFCore.utils import getToolByName
from Products.ERP5Type.tests.utils import reindex
from Products.ERP5Type.tests.utils import createZODBPythonScript, reindex
class TestBPMMixin(ERP5TypeTestCase):
"""Skeletons for tests which depend on BPM"""
......@@ -60,9 +58,9 @@ class TestBPMMixin(ERP5TypeTestCase):
@reindex
def createCategories(self):
category_tool = getToolByName(self.portal, 'portal_categories')
category_tool = self.portal.portal_categories
self.createCategoriesInCategory(category_tool.base_amount, ['discount',
'tax', 'total_tax', 'total_discount', 'total'])
'tax', 'total_tax', 'total_discount', 'total', 'fixed_quantity'])
self.createCategoriesInCategory(category_tool.use,
self.normal_resource_use_category_list + \
self.invoicing_resource_use_category_list)
......
This diff is collapsed.
......@@ -659,23 +659,31 @@ def registerBaseCategories(property_sheet):
base_category_dict[bc] = 1
def importLocalInterface(module_id, path = None, is_erp5_type=False):
if path is None:
instance_home = getConfiguration().instancehome
path = os.path.join(instance_home, "interfaces")
path = os.path.join(path, "%s.py" % module_id)
f = open(path)
try:
class_id = "I" + convertToUpperCase(module_id)
if not is_erp5_type:
def provides(class_id):
# Create interface getter
accessor_name = 'provides' + class_id
setattr(BaseClass, accessor_name, lambda self: self.provides(class_id))
BaseClass.security.declarePublic(accessor_name)
class_id = "I" + convertToUpperCase(module_id)
if is_erp5_type:
provides(class_id)
else:
if path is None:
instance_home = getConfiguration().instancehome
path = os.path.join(instance_home, "interfaces")
path = os.path.join(path, "%s.py" % module_id)
f = open(path)
try:
module = imp.load_source(class_id, path, f)
import Products.ERP5Type.interfaces
setattr(Products.ERP5Type.interfaces, class_id, getattr(module, class_id))
finally:
f.close()
# Create interface getter
accessor_name = 'provides' + class_id
setattr(BaseClass, accessor_name, lambda self: self.provides(class_id))
BaseClass.security.declarePublic(accessor_name)
finally:
f.close()
from zope.interface import Interface
from Products.ERP5Type import interfaces
InterfaceClass = type(Interface)
for k, v in module.__dict__.iteritems():
if type(v) is InterfaceClass and v is not Interface:
setattr(interfaces, k, v)
provides(class_id)
def importLocalConstraint(class_id, path = None):
import Products.ERP5Type.Constraint
......
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