Commit 93a0f39f authored by Jérome Perrin's avatar Jérome Perrin

simulation: introduce MovementGeneratorMixin._updateGeneratedMovementList

This allows custom movement generators to set ad-hoc properties on
generated movements depending on properties of the corresponding
input movement.

There was already _getUpdatePropertyDict which is similar, but was
sometimes not enough because it can only be use to set extra
properties on all movements.

As a result, when we needed a rule with custom properties on
generated movements, we resorted to overriding getGeneratedMovementList
and duplicating the full logic of the method. Existing cases have
been updated to use the new _updateGeneratedMovementList and in the
case of InventoryAssetPriceAccountingRuleMovementGenerator we no
longer need to duplicate the logic.

Also remove the comment suggesting overriding getGeneratedMovementList
in subclasses, now several "extension" methods exists, so it should
not be needed to override getGeneratedMovementList, every needs
should be coverred by defining _updateGeneratedMovementList or
_getUpdatePropertyDict
parent 6c6a8098
...@@ -124,11 +124,18 @@ class InvoiceTransactionRuleMovementGenerator(MovementGeneratorMixin): ...@@ -124,11 +124,18 @@ class InvoiceTransactionRuleMovementGenerator(MovementGeneratorMixin):
kw = {'delivery': None, 'resource': resource, 'price': 1} kw = {'delivery': None, 'resource': resource, 'price': 1}
return kw return kw
def getGeneratedMovementList(self, movement_list=None, rounding=False): def _updateGeneratedMovementList(self, input_movement, generated_movement_list):
movement_list = super(InvoiceTransactionRuleMovementGenerator, self).getGeneratedMovementList(movement_list=movement_list, rounding=rounding)
portal = self._applied_rule.getPortalObject() portal = self._applied_rule.getPortalObject()
for arrow in 'destination', 'source': generated_movement_list = super(
for movement in movement_list: InvoiceTransactionRuleMovementGenerator,
self,
)._updateGeneratedMovementList(
input_movement,
generated_movement_list,
)
for arrow, sign in ('destination', 1), ('source', -1):
for movement in generated_movement_list:
resource = movement.getResource() resource = movement.getResource()
if resource is not None: if resource is not None:
section = movement.getDefaultAcquiredValue(arrow + '_section') section = movement.getDefaultAcquiredValue(arrow + '_section')
...@@ -144,13 +151,8 @@ class InvoiceTransactionRuleMovementGenerator(MovementGeneratorMixin): ...@@ -144,13 +151,8 @@ class InvoiceTransactionRuleMovementGenerator(MovementGeneratorMixin):
categories=('price_currency/' + currency_url, categories=('price_currency/' + currency_url,
'resource/' + resource))) 'resource/' + resource)))
if exchange_ratio is not None: if exchange_ratio is not None:
if arrow == 'destination':
sign = 1
else:
sign = -1
movement.setProperty(arrow + '_total_asset_price', movement.getQuantity() * exchange_ratio * sign) movement.setProperty(arrow + '_total_asset_price', movement.getQuantity() * exchange_ratio * sign)
return generated_movement_list
return movement_list
def _getInputMovementList(self, movement_list=None, rounding=False): def _getInputMovementList(self, movement_list=None, rounding=False):
simulation_movement = self._applied_rule.getParentValue() simulation_movement = self._applied_rule.getParentValue()
......
...@@ -32,67 +32,37 @@ from erp5.component.document.InvoiceTransactionSimulationRule import (InvoiceTra ...@@ -32,67 +32,37 @@ from erp5.component.document.InvoiceTransactionSimulationRule import (InvoiceTra
class InventoryAssetPriceAccountingRuleMovementGenerator(InvoiceTransactionRuleMovementGenerator): class InventoryAssetPriceAccountingRuleMovementGenerator(InvoiceTransactionRuleMovementGenerator):
""" """
""" """
# CMF Type Definition
meta_type = 'ERP5 Inventory Asset Price Accounting Simulation Rule'
portal_type = 'Inventory Asset Price Accounting Simulation Rule'
# XXX: Copy/paste from erp5.component.mixin.RuleMixin to support Transit use case
def getGeneratedMovementList(self, movement_list=None, rounding=False):
"""
Returns a list of movements generated by that rule.
movement_list - optional IMovementList which can be passed explicitely
rounding - boolean argument, which controls if rounding shall be applied on def _updateGeneratedMovementList(self, input_movement, generated_movement_list):
generated movements or not """Support Transit use case
NOTE:
- implement rounding appropriately (True or False seems
simplistic)
""" """
# Default implementation below can be overriden by subclasses generated_movement_list = super(
# however it should be generic enough not to be overriden InventoryAssetPriceAccountingRuleMovementGenerator,
# by most classes self,
# Results will be appended to result )._updateGeneratedMovementList(
result = [] input_movement,
# Build a list of movement and business path generated_movement_list,
input_movement_list = self._getInputMovementList( )
movement_list=movement_list, rounding=rounding) for movement in generated_movement_list:
for input_movement in input_movement_list: update_dict = {}
# Merge movement and business path properties (core implementation) if movement.getLedger() in ('stock/stock/entree',
# Lookup Business Process through composition (NOT UNION) 'stock/preparation/entree',
business_process = input_movement.asComposedDocument() 'stock/transit/sortie',
explanation = self._applied_rule # We use applied rule as local explanation 'stock/customs/entree'):
trade_phase = self._getTradePhaseList(input_movement, business_process) # XXX-JPS not convenient to handle update_dict['start_date'] = update_dict['stop_date'] = input_movement.getStopDate()
update_property_dict = self._getUpdatePropertyDict(input_movement) elif movement.getLedger() in ('stock/stock/sortie',
'stock/preparation/sortie',
for movement in business_process.getTradePhaseMovementList(explanation, input_movement, 'stock/transit/entree'):
trade_phase=trade_phase, delay_mode=None, update_dict['start_date'] = update_dict['stop_date'] = input_movement.getStartDate()
update_property_dict=update_property_dict): movement._edit(**update_dict)
# PATCH-BEGIN
update_dict = {} input_movement.log("%r (input_movement=%r): ledger=%r, start_date=%r, stop_date=%r" %
if movement.getLedger() in ('stock/stock/entree', (movement,
'stock/preparation/entree', input_movement,
'stock/transit/sortie', movement.getLedger(),
'stock/customs/entree'): movement.getStartDate(),
update_dict['start_date'] = update_dict['stop_date'] = input_movement.getStopDate() movement.getStopDate()))
elif movement.getLedger() in ('stock/stock/sortie', return generated_movement_list
'stock/preparation/sortie',
'stock/transit/entree'):
update_dict['start_date'] = update_dict['stop_date'] = input_movement.getStartDate()
movement._edit(**update_dict)
input_movement.log("%r (input_movement=%r): ledger=%r, start_date=%r, stop_date=%r" %
(movement,
input_movement,
movement.getLedger(),
movement.getStartDate(),
movement.getStopDate()))
# PATCH-END
result.append(movement)
# And return list of generated movements
return result
def _getInputMovementList(self, movement_list=None, rounding=False): def _getInputMovementList(self, movement_list=None, rounding=False):
simulation_movement = self._applied_rule.getParentValue() simulation_movement = self._applied_rule.getParentValue()
...@@ -115,7 +85,12 @@ class InventoryAssetPriceAccountingRuleMovementGenerator(InvoiceTransactionRuleM ...@@ -115,7 +85,12 @@ class InventoryAssetPriceAccountingRuleMovementGenerator(InvoiceTransactionRuleM
return update_property_dict return update_property_dict
class InventoryAssetPriceAccountingSimulationRule(InvoiceTransactionSimulationRule): class InventoryAssetPriceAccountingSimulationRule(InvoiceTransactionSimulationRule):
# CMF Type Definition
meta_type = 'ERP5 Inventory Asset Price Accounting Simulation Rule'
portal_type = 'Inventory Asset Price Accounting Simulation Rule'
def _getMovementGenerator(self, context): def _getMovementGenerator(self, context):
return InventoryAssetPriceAccountingRuleMovementGenerator( return InventoryAssetPriceAccountingRuleMovementGenerator(
applied_rule=context, rule=self) applied_rule=context, rule=self)
...@@ -74,9 +74,6 @@ class MovementGeneratorMixin(object): ...@@ -74,9 +74,6 @@ class MovementGeneratorMixin(object):
- implement rounding appropriately (True or False seems - implement rounding appropriately (True or False seems
simplistic) simplistic)
""" """
# Default implementation below can be overriden by subclasses
# however it should be generic enough not to be overriden
# by most classes
# Results will be appended to result # Results will be appended to result
result = [] result = []
# Build a list of movement and business path # Build a list of movement and business path
...@@ -89,9 +86,13 @@ class MovementGeneratorMixin(object): ...@@ -89,9 +86,13 @@ class MovementGeneratorMixin(object):
explanation = self._applied_rule # We use applied rule as local explanation explanation = self._applied_rule # We use applied rule as local explanation
trade_phase = self._getTradePhaseList(input_movement, business_process) # XXX-JPS not convenient to handle trade_phase = self._getTradePhaseList(input_movement, business_process) # XXX-JPS not convenient to handle
update_property_dict = self._getUpdatePropertyDict(input_movement) update_property_dict = self._getUpdatePropertyDict(input_movement)
result.extend(business_process.getTradePhaseMovementList(explanation, input_movement, generated_movement_list = business_process.getTradePhaseMovementList(
trade_phase=trade_phase, delay_mode=None, explanation,
update_property_dict=update_property_dict)) input_movement,
trade_phase=trade_phase,
delay_mode=None,
update_property_dict=update_property_dict)
result.extend(self._updateGeneratedMovementList(input_movement, generated_movement_list))
# And return list of generated movements # And return list of generated movements
return result return result
...@@ -102,6 +103,9 @@ class MovementGeneratorMixin(object): ...@@ -102,6 +103,9 @@ class MovementGeneratorMixin(object):
# Other movement generators usually want to reset delivery. # Other movement generators usually want to reset delivery.
return {'delivery': input_movement.getRelativeUrl()} return {'delivery': input_movement.getRelativeUrl()}
def _updateGeneratedMovementList(self, input_movement, generated_movement_list):
return generated_movement_list
def _getTradePhaseList(self, input_movement, business_process): # XXX-JPS WEIRD def _getTradePhaseList(self, input_movement, business_process): # XXX-JPS WEIRD
if self._trade_phase_list: if self._trade_phase_list:
return self._trade_phase_list return self._trade_phase_list
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment