Commit 15117664 authored by Julien Muchembled's avatar Julien Muchembled

coding style

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@33963 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 60622d2d
......@@ -35,10 +35,10 @@ from Products.ERP5.Document.Amount import Amount
class AmountGeneratorMixin:
"""
This class provides a generic implementation of IAmountGenerator.
It is used by Transformation, Trade Model, Paysheet, etc. It is
It is used by Transformation, Trade Model, Paysheet, etc. It is
designed to support about any transformation process based
on IMappedValue interface. The key idea is that the Amount Generator
Lines and Cell provide either directly or through acquisition the
Lines and Cell provide either directly or through acquisition the
methods 'getMappedValuePropertyList' and 'getMappedValueBaseCategoryList'
to gather the properties and categories to copy from the model
to the generated amounts.
......@@ -59,7 +59,7 @@ class AmountGeneratorMixin:
properties involved in trade model line or transformation calculation
TODO:
default implementation could use type based method
default implementation could use type based method
"""
raise NotImplementedError
# Example of return value
......@@ -78,7 +78,7 @@ class AmountGeneratorMixin:
properties involved in trade model line or transformation calculation
TODO:
default implementation could use type based method
default implementation could use type based method
"""
raise NotImplementedError
# Example of return value
......@@ -99,9 +99,10 @@ class AmountGeneratorMixin:
# on the weight in tons
)
security.declareProtected(Permissions.AccessContentsInformation, 'getGeneratedAmountList')
security.declareProtected(Permissions.AccessContentsInformation,
'getGeneratedAmountList')
def getGeneratedAmountList(self, context, amount_list=None, rounding=False):
"""
"""
Implementation of a generic transformation algorithm which is
applicable to payroll, tax generation and BOMs. Return the
list of amounts without any aggregation.
......@@ -117,15 +118,16 @@ class AmountGeneratorMixin:
# Initialize base_amount global properties (which can be modified
# during the calculation process)
base_amount = self._getGlobalPropertyDict(context, amount_list=amount_list, rounding=rounding)
base_amount = self._getGlobalPropertyDict(context, amount_list=amount_list,
rounding=rounding)
portal_roundings = self.portal_roundings
# Set empty result by default
result = []
# If amount_list is None, then try to collect amount_list from
# If amount_list is None, then try to collect amount_list from
# the current context
if amount_list is None:
if amount_list is None:
if context.providesIMovementCollection():
amount_list = context.getMovementList()
elif context.providesIAmount():
......@@ -133,14 +135,16 @@ class AmountGeneratorMixin:
elif context.providesIAmountList():
amount_list = context
else:
raise ValueError('amount_list must implement IMovementCollection, IAmount or IAmountList')
raise ValueError(
'context must implement IMovementCollection, IAmount or IAmountList')
# Each amount in amount_list creates a new amount to take into account
# We thus need to start with a loop on amount_list
for delivery_amount in amount_list:
# Initialize base_amount with per amount properties
amount_propert_dict = self._getAmountPropertyDict(delivery_amount, amount_list=amount_list, rounding=rounding)
base_amount.update(amount_propert_dict)
amount_property_dict = self._getAmountPropertyDict(delivery_amount,
amount_list=amount_list, rounding=rounding)
base_amount.update(amount_property_dict)
# Initialize base_amount with total_price for each amount applications
#for application in delivery_amount.getBaseApplicationList(): # Acquired from Resource - XXX-JPS ?
......@@ -149,167 +153,172 @@ class AmountGeneratorMixin:
total_price = delivery_amount.getTotalPrice()
for application in application_list: # Acquired from Resource - seems more normal
base_amount[application] = total_price
# Browse recursively the trade model and accumulate
# applicable values - first define the recursive method
def accumulateAmountList(amount_generator_line):
amount_generator_line_list = amount_generator_line.contentValues(portal_type=self.getPortalAmountGeneratorLineTypeList())
amount_generator_line_list = amount_generator_line.contentValues(
portal_type=self.getPortalAmountGeneratorLineTypeList())
# Recursively feed base_amount
if len(amount_generator_line_list):
amount_generator_line_list.sort(key=lambda x: x.getIntIndex())
for amount_generator_line in amount_generator_line_list:
accumulateAmountList(amount_generator_line)
return
return
# Try to collect cells and aggregate their mapped properties
# using resource + variation as aggregation key or base_application
# for intermediate lines
amount_generator_cell_list = amount_generator_line.contentValues(portal_type=self.getPortalAmountGeneratorCellTypeList())
if not amount_generator_cell_list:
amount_generator_cell_list = amount_generator_line.contentValues(
portal_type=self.getPortalAmountGeneratorCellTypeList())
if not amount_generator_cell_list:
# Consider the line as the unique cell
amount_generator_cell_list = [amount_generator_line]
resource_amount_aggregate = {} # aggregates final line information
value_amount_aggregate = {} # aggregates intermediate line information
for amount_generator_cell in amount_generator_cell_list:
if amount_generator_cell.test(delivery_amount): # XXX-JPS getTargetLevel not supported
# Case 1: the cell defines a final amount of resource
if amount_generator_cell.getResource() and\
getattr(amount_generator_cell, 'getBaseApplication', None) is not None:
# Define a key in order to aggregate amounts
# in transformations where variation and quantity
# are defined in different cells
#
# Transformed Resource (Transformation)
# key = anything (only one cell selected)
# 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)
key = (amount_generator_cell.getResource(), amount_generator_cell.getVariationText()) # Variation UID, Hash ?
resource_amount_aggregate.setdefault(key, {})
# Then collect the mapped properties (resource, quantity, net_converted_quantity, base_contribution_list, base_application, etc.)
for property_key in amount_generator_cell.getMappedValuePropertyList():
# XXX-JPS Make sure handling of list properties can be handled
resource_amount_aggregate[key][property_key] = amount_generator_cell.getProperty(property_key)
resource_amount_aggregate[key]['category_list'] = amount_generator_cell.getCategoryMembershipList(
amount_generator_cell.getMappedValueBaseCategoryList(), base=1)
resource_amount_aggregate[key]['resource'] = amount_generator_cell.getResource()
# For final amounts, base_application and id MUST be defined
resource_amount_aggregate[key]['base_application'] = amount_generator_cell.getBaseApplication() # Required
#resource_amount_aggregate[key]['trade_phase_list'] = amount_generator_cell.getTradePhaseList() # Required moved to MappedValue
resource_amount_aggregate[key]['id'] = amount_generator_cell.getRelativeUrl().replace('/', '_')
# Case 2: the cell defines a temporary calculation line
elif getattr(amount_generator_cell, 'getBaseContributionList', None) is not None\
and getattr(amount_generator_cell, 'getBaseApplication', None) is not None:
# Define a key in order to aggregate amounts in cells
# base_application MUST be defined
#
# Single line case: key = base_application
#
# Payroll
#
# key = base_application
# it is not possible to use cells to add amounts
# in intermediate calculation but only to
# select one amount
#
# key = (base_application, XXX) would be required
#
# Use of a method to generate keys is probably better.
# than hardcoding it here
key = amount_generator_cell.getBaseApplication()
value_amount_aggregate.setdefault(key, {})
# Then collect the mapped properties
for property_key in amount_generator_cell.getMappedValuePropertyList():
value_amount_aggregate[key][property_key] = amount_generator_cell.getProperty(property_key)
value_amount_aggregate[key]['category_list'] = amount_generator_cell.getCategoryMembershipList(
amount_generator_cell.getMappedValueBaseCategoryList(), base=1)
# For intermediate calculations, base_contribution_list MUST be defined
value_amount_aggregate[key]['base_contribution_list'] = amount_generator_cell.getBaseContributionList() # Required
if resource_amount_aggregate:
for key, property_dict in resource_amount_aggregate.items():
resource, variation_text = key
if property_dict.get('category_list', None) is not None:
category_list = property_dict['category_list']
del property_dict['category_list']
else:
category_list = None
base_application = property_dict['base_application']
del property_dict['base_application']
# property_dict should include
# resource - VAT service or a Component in MRP
# quantity - quantity in component in MRP, (what else XXX)
# variation params - color, size, employer share, etc.
# price - empty (like in Transformation) price of a product (ex. a Stamp)
# or tax ratio (ie. price per value units)
# base_contribution_list - needed to produce reports with getTotalPrice
getBaseApplication = \
getattr(amount_generator_cell, 'getBaseApplication', None)
if (getBaseApplication is None or
# XXX-JPS getTargetLevel not supported
not amount_generator_cell.test(delivery_amount)):
continue
resource = amount_generator_cell.getResource()
# Case 1: the cell defines a final amount of resource
if resource:
# Define a key in order to aggregate amounts
# in transformations where variation and quantity
# are defined in different cells
#
# Transformed Resource (Transformation)
# key = anything (only one cell selected)
# 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
#
# Quantity is used as a multiplier (like in transformations for MRP)
# net_converted_quantity is used preferrably to quantity since we need
# values converted to the default management unit
# If not quantity is provided, we consider that the value is 1.0 (XXX is it OK ?) XXX-JPS Need careful review with taxes
property_dict['quantity'] = base_amount[amount_generator_line.getBaseApplication()] * \
(property_dict.get('net_converted_quantity', property_dict.get('quantity', 1.0)))
# This sounds wrong if cell has getBaseApplication()
# We should not keep net_converted_quantity
if property_dict.get('net_converted_quantity', None) is not None:
del property_dict['net_converted_quantity']
# Create an Amount object
id = property_dict['id']
del property_dict['id']
amount = newTempAmount(portal, id) # XXX-JPS Could we use a movement for safety ?
if category_list: amount._setCategoryList(category_list)
amount._edit(**property_dict)
if rounding:
# We hope here that rounding is sufficient at line level
amount = portal_roundings.getRoundingProxy(amount, context=amount_generator_line)
result.append(amount)
if value_amount_aggregate:
for base_application, property_dict in value_amount_aggregate.items():
# property_dict should include
# base_contribution_list - needed to produce reports with getTotalPrice
# quantity - quantity in component in MRP, (what else XXX)
# price - empty (like in Transformation) price of a product (ex. a Stamp)
# or tax ratio (ie. price per value units)
base_contribution_list = property_dict['base_contribution_list']
value = base_amount[base_application] * \
(property_dict.get('quantity', None) or 1.0) * \
(property_dict.get('price', None) or 1.0) # XXX-JPS is it really 1.0 ?
# Quantity is used as a multiplier
# Price is used as a ratio (also a kind of multiplier)
for base_key in base_contribution_list:
base_amount[base_key] += value
# key = (tax resource, tax resource variation)
key = (amount_generator_cell.getResource(),
# Variation UID, Hash ?
amount_generator_cell.getVariationText())
property_dict = resource_amount_aggregate.setdefault(key, {})
# Then collect the mapped properties (net_converted_quantity,
# resource, quantity, base_contribution_list, base_application...)
for key in amount_generator_cell.getMappedValuePropertyList():
# XXX-JPS Make sure handling of list properties can be handled
property_dict[key] = amount_generator_cell.getProperty(key)
property_dict['category_list'] = \
amount_generator_cell.getCategoryMembershipList(
amount_generator_cell.getMappedValueBaseCategoryList(), base=1)
property_dict['resource'] = resource
# For final amounts, base_application and id MUST be defined
property_dict['base_application'] = getBaseApplication() # Required
#property_dict['trade_phase_list'] = amount_generator_cell.getTradePhaseList() # Required moved to MappedValue
property_dict['id'] = amount_generator_cell.getRelativeUrl().replace('/', '_')
# Case 2: the cell defines a temporary calculation line
elif getattr(amount_generator_cell, 'getBaseContributionList', None) is not None:
# Define a key in order to aggregate amounts in cells
# base_application MUST be defined
#
# Single line case: key = base_application
#
# Payroll
#
# key = base_application
# it is not possible to use cells to add amounts
# in intermediate calculation but only to
# select one amount
#
# key = (base_application, XXX) would be required
#
# Use of a method to generate keys is probably better.
# than hardcoding it here
key = getBaseApplication()
property_dict = value_amount_aggregate.setdefault(key, {})
# Then collect the mapped properties
for key in amount_generator_cell.getMappedValuePropertyList():
property_dict[key] = amount_generator_cell.getProperty(key)
property_dict['category_list'] = \
amount_generator_cell.getCategoryMembershipList(
amount_generator_cell.getMappedValueBaseCategoryList(), base=1)
# For intermediate calculations,
# base_contribution_list MUST be defined
property_dict['base_contribution_list'] = \
amount_generator_cell.getBaseContributionList() # Required
for property_dict in resource_amount_aggregate.itervalues():
base_application = property_dict.pop('base_application')
# property_dict should include
# resource - VAT service or a Component in MRP
# quantity - quantity in component in MRP, (what else XXX)
# variation params - color, size, employer share, etc.
# price - empty (like in Transformation) price of a product
# (ex. a Stamp) or tax ratio (ie. price per value units)
# base_contribution_list - needed to produce reports with
# getTotalPrice
#
# Quantity is used as a multiplier (like in transformations for MRP)
# net_converted_quantity is used preferrably to quantity since we
# need values converted to the default management unit
# If no quantity is provided, we consider that the value is 1.0
# (XXX is it OK ?) XXX-JPS Need careful review with taxes
property_dict['quantity'] = base_amount[base_application] * \
property_dict.pop('net_converted_quantity',
property_dict.get('quantity', 1.0))
# Create an Amount object
# XXX-JPS Could we use a movement for safety ?
amount = newTempAmount(portal, property_dict.pop('id'),
**property_dict)
if rounding:
# We hope here that rounding is sufficient at line level
amount = portal_roundings.getRoundingProxy(amount,
context=amount_generator_line)
result.append(amount)
for base_application, property_dict in \
value_amount_aggregate.iteritems():
# property_dict should include
# base_contribution_list - needed to produce reports with
# getTotalPrice
# quantity - quantity in component in MRP, (what else XXX)
# price - empty (like in Transformation) price of a product
# (ex. a Stamp) or tax ratio (ie. price per value units)
value = base_amount[base_application] * \
(property_dict.get('quantity') or 1.0) * \
(property_dict.get('price') or 1.0) # XXX-JPS is it really 1.0 ?
# Quantity is used as a multiplier
# Price is used as a ratio (also a kind of multiplier)
for base_key in property_dict['base_contribution_list']:
base_amount[base_key] += value
# Browse recursively the trade model and accumulate
# applicable values - now execute the method
accumulateAmountList(self)
# Purge base_amount of amount applications
for application in amount_propert_dict.keys():
for application in amount_property_dict:
del base_amount[application]
return result
security.declareProtected(Permissions.AccessContentsInformation, 'getAggregatedAmountList')
def getAggregatedAmountList(self, context, movement_list=None, rounding=False):
security.declareProtected(Permissions.AccessContentsInformation,
'getAggregatedAmountList')
def getAggregatedAmountList(self, context, movement_list=None,
rounding=False):
"""
Implementation of a generic transformation algorith which is
applicable to payroll, tax generation and BOMs. Return the
list of amounts with aggregation.
TODO:
- make working sample code
"""
raise NotImplementedError
# Example of return code
result = self.getGeneratedAmountList(context, movement_list=movement_list, rounding=rounding)
result = self.getGeneratedAmountList(context, movement_list=movement_list,
rounding=rounding)
return SomeMovementGroup(result)
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