Commit 6c2bffed authored by Jérome Perrin's avatar Jérome Perrin

*: refactor edit_order of Base._edit

Instead of overriding the method and adjusting edit order in some class,
define "_default_edit_order" as a class value and use it in Base._edit
as default value when caller do not explicitly pass edit_order.

This was made to keep the default edit order consistent with the order
of edits on python2 for properties where the edit order matters.

This affects mostly scripts, when for example in a script we do:

  delivery.edit(start_date=d, stop_date=d)

on python2 without PYTHONHASHSEED, stop_date is also set, so we keep
this behavior (that is assumed by some tests).

We also change the order of edit for other properties not constraint
by edit_order to edit them in alphabetic order, to have a constant
deterministic behavior.
Co-authored-by: Kazuhiko Shiozaki's avatarKazuhiko SHIOZAKI <kazuhiko@nexedi.com>
parent 37049166
...@@ -70,6 +70,8 @@ class Resource(XMLObject, XMLMatrix, VariatedMixin): ...@@ -70,6 +70,8 @@ class Resource(XMLObject, XMLMatrix, VariatedMixin):
, PropertySheet.Aggregated , PropertySheet.Aggregated
) )
_default_edit_order = XMLObject._default_edit_order + VariatedMixin._default_edit_order
# Is it OK now ? # Is it OK now ?
# The same method is at about 3 different places # The same method is at about 3 different places
# Some genericity is needed # Some genericity is needed
......
...@@ -66,6 +66,29 @@ class Amount(Base, VariatedMixin): ...@@ -66,6 +66,29 @@ class Amount(Base, VariatedMixin):
, PropertySheet.Reference , PropertySheet.Reference
) )
_default_edit_order = Base._default_edit_order + (
'resource',
'resource_value',
'resource_uid',
# If variations and resources are set at the same time, resource must be
# set before any variation.
'variation_base_category_list',
'variation_category_list',
# If (quantity unit, base_contribution, or use) and resource are set at the same time,
# resource must be set first, because of an interaction that copies quantity unit
# base contribution and use from resource if not set.
'quantity_unit_value',
'quantity_unit',
'use_value',
'use',
'base_contribution_list',
'base_contribution_value_list',
'base_contribution_value',
'base_contribution',
)
# A few more mix-in methods which should be relocated # A few more mix-in methods which should be relocated
# THIS MUST BE UPDATE WITH CATEGORY ACQUISITION # THIS MUST BE UPDATE WITH CATEGORY ACQUISITION
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
......
...@@ -50,6 +50,8 @@ class AmountGeneratorLine(MappedValue, XMLMatrix, Amount, ...@@ -50,6 +50,8 @@ class AmountGeneratorLine(MappedValue, XMLMatrix, Amount,
property_sheets = (PropertySheet.DublinCore, property_sheets = (PropertySheet.DublinCore,
PropertySheet.AmountGeneratorLine) PropertySheet.AmountGeneratorLine)
_default_edit_order = Amount._default_edit_order
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'getCellAggregateKey') 'getCellAggregateKey')
def getCellAggregateKey(self): def getCellAggregateKey(self):
......
...@@ -80,6 +80,11 @@ class Delivery(XMLObject, ImmobilisationDelivery, SimulableMixin, ...@@ -80,6 +80,11 @@ class Delivery(XMLObject, ImmobilisationDelivery, SimulableMixin,
, PropertySheet.Price , PropertySheet.Price
) )
_default_edit_order = XMLObject._default_edit_order + (
'stop_date',
'start_date',
)
security.declareProtected(Permissions.AccessContentsInformation, 'isAccountable') security.declareProtected(Permissions.AccessContentsInformation, 'isAccountable')
def isAccountable(self): def isAccountable(self):
""" """
......
...@@ -124,24 +124,6 @@ class DeliveryCell(MappedValue, Movement, ImmobilisationMovement): ...@@ -124,24 +124,6 @@ class DeliveryCell(MappedValue, Movement, ImmobilisationMovement):
self._setPredicateValueList(new_predicate_value) self._setPredicateValueList(new_predicate_value)
# No reindex needed since uid stable # No reindex needed since uid stable
# XXX FIXME: option variation are today not well implemented
# This little hack is needed to make the matrixbox working
# in DeliveryLine_viewIndustrialPhase
# Generic form (DeliveryLine_viewOption) is required
def _edit(self, **kw):
"""
Store variation_category_list, in order to store new value of
industrial_phase after.
"""
edit_order = ['variation_category_list', # edit this one first
'item_id_list'] # this one must be the last
edit_order[1:1] = [x for x in kw.pop('edit_order', ())
if x not in edit_order]
# Base._edit updates unordered properties first
edit_order[1:1] = [x for x in kw if x not in edit_order]
MappedValue._edit(self, edit_order=edit_order, **kw)
# if self.isSimulated():
# self.getRootDeliveryValue().activate().propagateResourceToSimulation()
security.declareProtected(Permissions.ModifyPortalContent, security.declareProtected(Permissions.ModifyPortalContent,
'updateSimulationDeliveryProperties') 'updateSimulationDeliveryProperties')
......
...@@ -36,9 +36,6 @@ from Products.ERP5Type.XMLMatrix import XMLMatrix ...@@ -36,9 +36,6 @@ from Products.ERP5Type.XMLMatrix import XMLMatrix
from erp5.component.document.Movement import Movement from erp5.component.document.Movement import Movement
from erp5.component.document.ImmobilisationMovement import ImmobilisationMovement from erp5.component.document.ImmobilisationMovement import ImmobilisationMovement
from inspect import getargspec
from Products.ERP5Type.Base import Base
edit_args_list = getargspec(Base._edit).args
from erp5.component.interface.IDivergenceController import IDivergenceController from erp5.component.interface.IDivergenceController import IDivergenceController
...@@ -75,29 +72,6 @@ class DeliveryLine(Movement, XMLMatrix, ImmobilisationMovement): ...@@ -75,29 +72,6 @@ class DeliveryLine(Movement, XMLMatrix, ImmobilisationMovement):
# Multiple inheritance definition # Multiple inheritance definition
updateRelatedContent = XMLMatrix.updateRelatedContent updateRelatedContent = XMLMatrix.updateRelatedContent
# Force in _edit to modify variation_base_category_list first
def _edit(self, edit_order=(), **kw):
# XXX FIXME For now, special cases are handled in _edit methods in many
# documents : DeliveryLine, DeliveryCell ... Ideally, to prevent code
# duplication, it should be handled in a _edit method present only in
# Amount.py
# If variations and resources are set at the same time, resource must be
# set before any variation.
before_order = ('resource', 'resource_value',
'variation_base_category_list',
'variation_category_list')
before_kw = {k: kw.pop(k) for k in before_order if k in kw}
if before_kw:
before_kw.update((k, kw[k]) for k in edit_args_list if k in kw)
Base._edit(self, edit_order=before_order, **before_kw)
if kw:
Movement._edit(self, edit_order=edit_order, **kw)
# We must check if the user has changed the resource of particular line
security.declareProtected( Permissions.ModifyPortalContent, 'edit' )
def edit(self, REQUEST=None, force_update = 0, reindex_object=1, **kw):
return self._edit(REQUEST=REQUEST, force_update=force_update, reindex_object=reindex_object, **kw)
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'isAccountable') 'isAccountable')
......
...@@ -73,7 +73,7 @@ class Movement(XMLObject, Amount, CompositionMixin, AmountGeneratorMixin): ...@@ -73,7 +73,7 @@ class Movement(XMLObject, Amount, CompositionMixin, AmountGeneratorMixin):
to define quantities in orders to define quantities in orders
- Deliveries: movements track the actual transfer of resources - Deliveries: movements track the actual transfer of resources
in the past (accounting) or in the future (planning / budgetting) in the past (accounting) or in the future (planning / budgeting)
For example, the following objects are Orders: For example, the following objects are Orders:
...@@ -217,8 +217,13 @@ class Movement(XMLObject, Amount, CompositionMixin, AmountGeneratorMixin): ...@@ -217,8 +217,13 @@ class Movement(XMLObject, Amount, CompositionMixin, AmountGeneratorMixin):
, PropertySheet.Movement , PropertySheet.Movement
, PropertySheet.Price , PropertySheet.Price
, PropertySheet.Simulation # XXX-JPS property should be moved to GeneratedMovement class , PropertySheet.Simulation # XXX-JPS property should be moved to GeneratedMovement class
)
_default_edit_order = Amount._default_edit_order + (
'stop_date',
'start_date',
) )
def isPropertyRecorded(self, k): # XXX-JPS method should be moved to GeneratedMovement class def isPropertyRecorded(self, k): # XXX-JPS method should be moved to GeneratedMovement class
return False return False
...@@ -726,9 +731,6 @@ class Movement(XMLObject, Amount, CompositionMixin, AmountGeneratorMixin): ...@@ -726,9 +731,6 @@ class Movement(XMLObject, Amount, CompositionMixin, AmountGeneratorMixin):
def _edit(self, edit_order=(), **kw): def _edit(self, edit_order=(), **kw):
"""Overloaded _edit to support setting debit and credit at the same time, """Overloaded _edit to support setting debit and credit at the same time,
which is required for the GUI. which is required for the GUI.
Also sets the variation category list and property dict at the end, because
_setVariationCategoryList and _setVariationPropertyDict needs the resource
to be set.
""" """
quantity = 0 quantity = 0
if 'source_debit' in kw and 'source_credit' in kw: if 'source_debit' in kw and 'source_credit' in kw:
...@@ -757,9 +759,7 @@ class Movement(XMLObject, Amount, CompositionMixin, AmountGeneratorMixin): ...@@ -757,9 +759,7 @@ class Movement(XMLObject, Amount, CompositionMixin, AmountGeneratorMixin):
if kw.get('destination_asset_credit') in (None, ''): if kw.get('destination_asset_credit') in (None, ''):
kw.pop('destination_asset_credit', None) kw.pop('destination_asset_credit', None)
if not edit_order: return super(Movement, self)._edit(edit_order=edit_order, **kw)
edit_order = ('variation_category_list', 'variation_property_dict', 'quantity_unit',)
return XMLObject._edit(self, edit_order=edit_order, **kw)
# Debit and credit methods for asset # Debit and credit methods for asset
security.declareProtected( Permissions.AccessContentsInformation, security.declareProtected( Permissions.AccessContentsInformation,
......
...@@ -59,6 +59,11 @@ class VariatedMixin: ...@@ -59,6 +59,11 @@ class VariatedMixin:
isRADContent = 1 # for 'property_sheets' isRADContent = 1 # for 'property_sheets'
property_sheets = (PropertySheet.VariationRange, ) property_sheets = (PropertySheet.VariationRange, )
_default_edit_order = (
'variation_base_category_list',
'variation_category_list',
)
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'getVariationBaseCategoryList') 'getVariationBaseCategoryList')
def getVariationBaseCategoryList(self, omit_optional_variation=0, def getVariationBaseCategoryList(self, omit_optional_variation=0,
......
...@@ -779,6 +779,11 @@ class Base( ...@@ -779,6 +779,11 @@ class Base(
# Declarative properties # Declarative properties
property_sheets = ( PropertySheet.Base, ) property_sheets = ( PropertySheet.Base, )
_default_edit_order = (
'title',
'reference',
)
# We want to use a default property view # We want to use a default property view
manage_main = manage_propertiesForm = DTMLFile( 'properties', _dtmldir ) manage_main = manage_propertiesForm = DTMLFile( 'properties', _dtmldir )
manage_main._setName('manage_main') manage_main._setName('manage_main')
...@@ -1478,7 +1483,7 @@ class Base( ...@@ -1478,7 +1483,7 @@ class Base(
# Object attributes update method # Object attributes update method
def _edit(self, REQUEST=None, force_update=0, reindex_object=0, def _edit(self, REQUEST=None, force_update=0, reindex_object=0,
keep_existing=0, activate_kw=None, edit_order=[], restricted=0, **kw): keep_existing=0, activate_kw=None, edit_order=(), restricted=0, **kw):
""" """
Generic edit Method for all ERP5 object Generic edit Method for all ERP5 object
The purpose of this method is to update attributed, eventually do The purpose of this method is to update attributed, eventually do
...@@ -1496,7 +1501,8 @@ class Base( ...@@ -1496,7 +1501,8 @@ class Base(
""" """
if not kw: if not kw:
return return
key_list = kw.keys() edit_order = edit_order or self._default_edit_order
key_list = sorted(kw.keys())
modified_property_dict = self._v_modified_property_dict = {} modified_property_dict = self._v_modified_property_dict = {}
modified_object_dict = {} modified_object_dict = {}
......
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