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 @@ ...@@ -270,10 +270,7 @@
<string>my_view_mode_trade_date</string> <string>my_view_mode_trade_date</string>
<string>my_view_mode_base_application_list</string> <string>my_view_mode_base_application_list</string>
<string>my_view_mode_calculation_script_id</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_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_core_mode_total_price</string>
<string>my_view_mode_listbox_read_only_start_date</string> <string>my_view_mode_listbox_read_only_start_date</string>
<string>my_report_mode_aggregation_level</string> <string>my_report_mode_aggregation_level</string>
...@@ -305,6 +302,7 @@ ...@@ -305,6 +302,7 @@
<string>my_view_mode_listbox_movement_relative_url</string> <string>my_view_mode_listbox_movement_relative_url</string>
<string>my_view_mode_movement_listbox_price</string> <string>my_view_mode_movement_listbox_price</string>
<string>my_view_mode_movement_listbox_quantity</string> <string>my_view_mode_movement_listbox_quantity</string>
<string>my_view_mode_target_delivery</string>
</list> </list>
</value> </value>
</item> </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 @@ ...@@ -12,12 +12,14 @@
<item> <item>
<key> <string>delegated_list</string> </key> <key> <string>delegated_list</string> </key>
<value> <value>
<list/> <list>
<string>title</string>
</list>
</value> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>my_create_line</string> </value> <value> <string>my_view_mode_target_delivery</string> </value>
</item> </item>
<item> <item>
<key> <string>message_values</string> </key> <key> <string>message_values</string> </key>
...@@ -74,16 +76,20 @@ ...@@ -74,16 +76,20 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>field_id</string> </key> <key> <string>field_id</string> </key>
<value> <string>my_view_mode_create_line</string> </value> <value> <string>my_checkbox</string> </value>
</item> </item>
<item> <item>
<key> <string>form_id</string> </key> <key> <string>form_id</string> </key>
<value> <string>Base_viewTradeFieldLibrary</string> </value> <value> <string>Base_viewFieldLibrary</string> </value>
</item> </item>
<item> <item>
<key> <string>target</string> </key> <key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value> <value> <string>Click to edit the target</string> </value>
</item> </item>
<item>
<key> <string>title</string> </key>
<value> <string>Target Delivery</string> </value>
</item>
</dictionary> </dictionary>
</value> </value>
</item> </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 @@ ...@@ -107,8 +107,8 @@
<string>my_resource_title</string> <string>my_resource_title</string>
<string>my_price</string> <string>my_price</string>
<string>my_quantity</string> <string>my_quantity</string>
<string>my_efficiency</string> <string>my_trade_phase</string>
<string>my_create_line</string> <string>my_use</string>
</list> </list>
</value> </value>
</item> </item>
...@@ -116,10 +116,9 @@ ...@@ -116,10 +116,9 @@
<key> <string>right</string> </key> <key> <string>right</string> </key>
<value> <value>
<list> <list>
<string>my_trade_phase</string> <string>my_target_delivery</string>
<string>my_base_application_list</string> <string>my_base_application_list</string>
<string>my_base_contribution_list</string> <string>my_base_contribution_list</string>
<string>my_use</string>
</list> </list>
</value> </value>
</item> </item>
......
...@@ -74,11 +74,11 @@ ...@@ -74,11 +74,11 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>field_id</string> </key> <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>
<item> <item>
<key> <string>form_id</string> </key> <key> <string>form_id</string> </key>
<value> <string>Base_viewTradeFieldLibrary</string> </value> <value> <string>Base_viewFieldLibrary</string> </value>
</item> </item>
<item> <item>
<key> <string>target</string> </key> <key> <string>target</string> </key>
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>my_efficiency</string> </value> <value> <string>my_target_delivery</string> </value>
</item> </item>
<item> <item>
<key> <string>message_values</string> </key> <key> <string>message_values</string> </key>
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>field_id</string> </key> <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>
<item> <item>
<key> <string>form_id</string> </key> <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 @@ ...@@ -28,19 +28,11 @@
# #
############################################################################## ##############################################################################
import zope.interface
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.CMFCore.utils import getToolByName from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type import Permissions, PropertySheet, interfaces from Products.ERP5.Document.AmountGeneratorLine import AmountGeneratorLine
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
class TradeModelLine(MappedValue, XMLMatrix, Amount, AmountGeneratorMixin): class TradeModelLine(AmountGeneratorLine):
"""Trade Model Line is a way to represent trade transformation for movements""" """Trade Model Line is a way to represent trade transformation for movements"""
meta_type = 'ERP5 Trade Model Line' meta_type = 'ERP5 Trade Model Line'
portal_type = 'Trade Model Line' portal_type = 'Trade Model Line'
...@@ -49,34 +41,18 @@ class TradeModelLine(MappedValue, XMLMatrix, Amount, AmountGeneratorMixin): ...@@ -49,34 +41,18 @@ class TradeModelLine(MappedValue, XMLMatrix, Amount, AmountGeneratorMixin):
security = ClassSecurityInfo() security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation) security.declareObjectProtected(Permissions.AccessContentsInformation)
# Declarative interfaces
zope.interface.implements(
interfaces.IAmountGenerator,
interfaces.IVariated
)
# Declarative properties # Declarative properties
property_sheets = ( PropertySheet.Base property_sheets = (PropertySheet.TradeModelLine, )
, PropertySheet.SimpleItem
, PropertySheet.CategoryCore
, PropertySheet.Amount
, PropertySheet.Price
, PropertySheet.TradeModelLine
, PropertySheet.Reference
, PropertySheet.Predicate
, PropertySheet.MappedValue
)
# XXX to be specificied in an interface (IAmountGeneratorLine ?) @classmethod
def getAmountProperty(self, amount, base_application, amount_list, rounding): def _getBaseAmountQuantity(cls, delivery_amount):
""" return delivery_amount.getTotalPrice()
Produced amount quantity is needed to initialize transformation
"""
return amount.getTotalPrice()
### Mapped Value Definition ### Mapped Value Definition
# Provide default mapped value properties and categories if # Provide default mapped value properties and categories if
# not defined # not defined
security.declareProtected(Permissions.AccessContentsInformation,
'getMappedValuePropertyList')
def getMappedValuePropertyList(self): def getMappedValuePropertyList(self):
""" """
""" """
...@@ -90,10 +66,7 @@ class TradeModelLine(MappedValue, XMLMatrix, Amount, AmountGeneratorMixin): ...@@ -90,10 +66,7 @@ class TradeModelLine(MappedValue, XMLMatrix, Amount, AmountGeneratorMixin):
return ('price', 'efficiency') return ('price', 'efficiency')
def getMappedValueBaseCategoryList(self): def getMappedValueBaseCategoryList(self):
result = self._baseGetMappedValueBaseCategoryList() return self._baseGetMappedValueBaseCategoryList() or ('trade_phase',)
if result:
return result
return ('base_contribution', 'trade_phase', )
# #
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
......
...@@ -104,14 +104,15 @@ class TradeModelRuleMovementGenerator(MovementGeneratorMixin): ...@@ -104,14 +104,15 @@ class TradeModelRuleMovementGenerator(MovementGeneratorMixin):
amount_generator_type_list=('Purchase Trade Condition', amount_generator_type_list=('Purchase Trade Condition',
'Sale Trade Condition', 'Sale Trade Condition',
'Trade Model Line')): 'Trade Model Line')):
# FIXME: Is it the right way to have source/destination and other if amount.getResource():
# non-Amount properties set on the generated movement ? # FIXME: Is it the right way to have source/destination and other
movement = input_movement.asContext(**dict((k, v) # non-Amount properties set on the generated movement ?
for k, v in amount.__dict__.iteritems() movement = input_movement.asContext(**dict((k, v)
if k[0] != '_' and k != 'categories')) for k, v in amount.__dict__.iteritems()
base_category_set = set(amount.getBaseCategoryList()) if k[0] != '_' and k != 'categories'))
base_category_set.remove('price_currency') # XXX base_category_set = set(amount.getBaseCategoryList())
movement._setCategoryMembership(base_category_set, base_category_set.remove('price_currency') # XXX
amount.getCategoryList(), movement._setCategoryMembership(base_category_set,
base=True) amount.getCategoryList(),
yield movement base=True)
yield movement
...@@ -81,17 +81,15 @@ class TransformedResource(MappedValue, XMLMatrix, Amount): ...@@ -81,17 +81,15 @@ class TransformedResource(MappedValue, XMLMatrix, Amount):
# Provide default mapped value properties and categories if # Provide default mapped value properties and categories if
# not defined # not defined
def getMappedValuePropertyList(self): def getMappedValuePropertyList(self):
result = self._baseGetMappedValuePropertyList() return self._baseGetMappedValuePropertyList() or (
if result: 'converted_quantity', 'efficiency')
return result
return ('quantity',)
def getMappedValueBaseCategoryList(self): def getMappedValueBaseCategoryList(self):
result = self._baseGetMappedValueBaseCategoryList() result = self._baseGetMappedValueBaseCategoryList()
if not result: if not result:
if not self.hasCellContent(base_id='variation'): if not self.hasCellContent(base_id='variation'):
result = self.getVariationRangeBaseCategoryList() # The current resource variation result = self.getVariationRangeBaseCategoryList() # The current resource variation
return list(result) + ['quantity_unit'] return result
def getBaseApplication(self): 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 -*- # -*- coding: utf-8 -*-
############################################################################## ##############################################################################
# #
# Copyright (c) 2009 Nexedi SA and Contributors. All Rights Reserved. # Copyright (c) 2010 Nexedi SA and Contributors. All Rights Reserved.
# Łukasz Nowak <luke@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
...@@ -26,23 +25,10 @@ ...@@ -26,23 +25,10 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# #
############################################################################## ##############################################################################
from AccessControl import ModuleSecurityInfo
class TradeModelLine: class TradeModelLine:
""" """
Properties for trade model lines Properties for trade model lines
""" """
_properties = ( _categories = ('trade_phase',)
{ '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',
)
...@@ -182,6 +182,7 @@ ...@@ -182,6 +182,7 @@
<string>listbox_modification_date</string> <string>listbox_modification_date</string>
<string>listbox_creation_date</string> <string>listbox_creation_date</string>
<string>listbox_owner_title</string> <string>listbox_owner_title</string>
<string>my_view_mode_amount_generator_quantity</string>
</list> </list>
</value> </value>
</item> </item>
......
...@@ -2,10 +2,7 @@ ...@@ -2,10 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<tuple> <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
<tuple/>
</tuple>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
...@@ -13,15 +10,13 @@ ...@@ -13,15 +10,13 @@
<key> <string>delegated_list</string> </key> <key> <string>delegated_list</string> </key>
<value> <value>
<list> <list>
<string>description</string>
<string>title</string>
<string>default</string> <string>default</string>
</list> </list>
</value> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <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>
<item> <item>
<key> <string>message_values</string> </key> <key> <string>message_values</string> </key>
...@@ -83,12 +78,12 @@ ...@@ -83,12 +78,12 @@
<value> <value>
<dictionary> <dictionary>
<item> <item>
<key> <string>description</string> </key> <key> <string>default</string> </key>
<value> <string>Useful for intermediated lines.</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>field_id</string> </key> <key> <string>field_id</string> </key>
<value> <string>my_checkbox</string> </value> <value> <string>my_quantity</string> </value>
</item> </item>
<item> <item>
<key> <string>form_id</string> </key> <key> <string>form_id</string> </key>
...@@ -98,10 +93,6 @@ ...@@ -98,10 +93,6 @@
<key> <string>target</string> </key> <key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value> <value> <string>Click to edit the target</string> </value>
</item> </item>
<item>
<key> <string>title</string> </key>
<value> <string>Create Line</string> </value>
</item>
</dictionary> </dictionary>
</value> </value>
</item> </item>
...@@ -110,16 +101,13 @@ ...@@ -110,16 +101,13 @@
</record> </record>
<record id="2" aka="AAAAAAAAAAI="> <record id="2" aka="AAAAAAAAAAI=">
<pickle> <pickle>
<tuple> <global name="TALESMethod" module="Products.Formulator.TALESField"/>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
<tuple/>
</tuple>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item> <item>
<key> <string>_text</string> </key> <key> <string>_text</string> </key>
<value> <string>here/isCreateLine</string> </value> <value> <string>python: here.getQuantity(None)</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -82,3 +82,33 @@ class IAmountGenerator(Interface): ...@@ -82,3 +82,33 @@ class IAmountGenerator(Interface):
- implement rounding appropriately (True or False seems - implement rounding appropriately (True or False seems
simplistic) 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 ...@@ -33,9 +33,7 @@ import transaction
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from DateTime import DateTime from DateTime import DateTime
from Products.ERP5Type.tests.utils import createZODBPythonScript, reindex
from Products.CMFCore.utils import getToolByName
from Products.ERP5Type.tests.utils import reindex
class TestBPMMixin(ERP5TypeTestCase): class TestBPMMixin(ERP5TypeTestCase):
"""Skeletons for tests which depend on BPM""" """Skeletons for tests which depend on BPM"""
...@@ -60,9 +58,9 @@ class TestBPMMixin(ERP5TypeTestCase): ...@@ -60,9 +58,9 @@ class TestBPMMixin(ERP5TypeTestCase):
@reindex @reindex
def createCategories(self): def createCategories(self):
category_tool = getToolByName(self.portal, 'portal_categories') category_tool = self.portal.portal_categories
self.createCategoriesInCategory(category_tool.base_amount, ['discount', 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.createCategoriesInCategory(category_tool.use,
self.normal_resource_use_category_list + \ self.normal_resource_use_category_list + \
self.invoicing_resource_use_category_list) self.invoicing_resource_use_category_list)
......
This diff is collapsed.
...@@ -659,23 +659,31 @@ def registerBaseCategories(property_sheet): ...@@ -659,23 +659,31 @@ def registerBaseCategories(property_sheet):
base_category_dict[bc] = 1 base_category_dict[bc] = 1
def importLocalInterface(module_id, path = None, is_erp5_type=False): def importLocalInterface(module_id, path = None, is_erp5_type=False):
if path is None: def provides(class_id):
instance_home = getConfiguration().instancehome # Create interface getter
path = os.path.join(instance_home, "interfaces") accessor_name = 'provides' + class_id
path = os.path.join(path, "%s.py" % module_id) setattr(BaseClass, accessor_name, lambda self: self.provides(class_id))
f = open(path) BaseClass.security.declarePublic(accessor_name)
try: class_id = "I" + convertToUpperCase(module_id)
class_id = "I" + convertToUpperCase(module_id) if is_erp5_type:
if not 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) module = imp.load_source(class_id, path, f)
import Products.ERP5Type.interfaces finally:
setattr(Products.ERP5Type.interfaces, class_id, getattr(module, class_id)) f.close()
finally: from zope.interface import Interface
f.close() from Products.ERP5Type import interfaces
# Create interface getter InterfaceClass = type(Interface)
accessor_name = 'provides' + class_id for k, v in module.__dict__.iteritems():
setattr(BaseClass, accessor_name, lambda self: self.provides(class_id)) if type(v) is InterfaceClass and v is not Interface:
BaseClass.security.declarePublic(accessor_name) setattr(interfaces, k, v)
provides(class_id)
def importLocalConstraint(class_id, path = None): def importLocalConstraint(class_id, path = None):
import Products.ERP5Type.Constraint 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