Commit 18fd24c0 authored by Jérome Perrin's avatar Jérome Perrin

SimulationState.getSimulationMovement should be delegated to the expandable item.

Introduce a new interface expandable_item which extends expandable and add this
functionality, and provides default implementation that maybe have to be
extended for some specific subscription items usages.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@44254 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent c21fa62c
...@@ -26,12 +26,13 @@ ...@@ -26,12 +26,13 @@
# #
############################################################################## ##############################################################################
import zope.interface
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from DateTime import DateTime from DateTime import DateTime
from string import capitalize from string import capitalize
from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5Type.XMLObject import XMLObject from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Type.DateUtils import addToDate, getClosestDate, roundDate from Products.ERP5Type.DateUtils import addToDate, getClosestDate, roundDate
from Products.ERP5Type.DateUtils import getRoundedMonthBetween, millis from Products.ERP5Type.DateUtils import getRoundedMonthBetween, millis
...@@ -77,6 +78,24 @@ class ImmobilisableItem(XMLObject, Amount): ...@@ -77,6 +78,24 @@ class ImmobilisableItem(XMLObject, Amount):
, PropertySheet.Amortisation , PropertySheet.Amortisation
) )
zope.interface.implements(interfaces.IExpandableItem,)
# IExpandableItem interface implementation
def getSimulationMovementSimulationState(self, simulation_movement):
"""Returns the simulation state for this simulation movement.
"""
portal = self.getPortalObject()
draft_state_list = portal.getDraftOrderStateList()
# if we have an order which is not draft, we'll consider the generated
# simulation movement are planned.
# This is probably oversimplified implementation, as we may want to look
# deliveries / invoices.
for movement in self.getAggregateRelatedValueList(
portal_type=portal.getPortalOrderMovementTypeList(),):
if movement.getSimulationState() not in draft_state_list:
return 'planned'
return 'draft'
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'getImmobilisationRelatedMovementList') 'getImmobilisationRelatedMovementList')
def getImmobilisationRelatedMovementList(self, def getImmobilisationRelatedMovementList(self,
......
...@@ -153,11 +153,13 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin): ...@@ -153,11 +153,13 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin):
security.declareProtected( Permissions.AccessContentsInformation, security.declareProtected( Permissions.AccessContentsInformation,
'getSimulationState') 'getSimulationState')
def getSimulationState(self, id_only=1): def getSimulationState(self, id_only=1):
""" """Returns the current state in simulation
Returns the current state in simulation
Inherit from delivery or parent (using a conversion table to make orders
planned when parent is confirmed).
Inherit from order or delivery or parent (but use a conversion In the case of simulation coming from an item, the simulation state is
table to make orders planned when parent is confirmed) delegated to the item.
XXX: movements in zero stock rule can not acquire simulation state XXX: movements in zero stock rule can not acquire simulation state
""" """
...@@ -168,13 +170,22 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin): ...@@ -168,13 +170,22 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin):
order = self.getOrderValue() order = self.getOrderValue()
if order is not None: if order is not None:
return order.getSimulationState() return order.getSimulationState()
try:
parent_state = None
try: try:
parent_state = self.getParentValue().getSimulationState() parent_state = self.getParentValue().getSimulationState()
except AttributeError:
item = self.getParentValue().getCausalityValue(
portal_type=self.getPortalItemTypeList())
if interfaces.IExpandableItem.providedBy(item):
return item.getSimulationMovementSimulationState(self)
raise
return parent_to_movement_simulation_state[parent_state] return parent_to_movement_simulation_state[parent_state]
except (KeyError, AttributeError): except (KeyError, AttributeError):
LOG('SimulationMovement.getSimulationState', WARNING, LOG('SimulationMovement.getSimulationState', WARNING,
'Could not acquire simulation state from %s' 'Could not acquire simulation state from %s'
% self.getRelativeUrl()) % self.getRelativeUrl(), error=True)
return None return None
security.declareProtected( Permissions.AccessContentsInformation, security.declareProtected( Permissions.AccessContentsInformation,
......
...@@ -67,7 +67,7 @@ class SubscriptionItem(Item, MovementGeneratorMixin, PeriodicityMixin): ...@@ -67,7 +67,7 @@ class SubscriptionItem(Item, MovementGeneratorMixin, PeriodicityMixin):
) )
# Declarative interfaces # Declarative interfaces
zope.interface.implements(interfaces.IExpandable, zope.interface.implements(interfaces.IExpandableItem,
interfaces.IMovementGenerator, interfaces.IMovementGenerator,
) )
...@@ -92,6 +92,20 @@ class SubscriptionItem(Item, MovementGeneratorMixin, PeriodicityMixin): ...@@ -92,6 +92,20 @@ class SubscriptionItem(Item, MovementGeneratorMixin, PeriodicityMixin):
if my_applied_rule is not None: if my_applied_rule is not None:
my_applied_rule.expand(activate_kw=activate_kw, **kw) # XXX-JPS why **kw ? my_applied_rule.expand(activate_kw=activate_kw, **kw) # XXX-JPS why **kw ?
# IExpandableItem interface implementation
def getSimulationMovementSimulationState(self, simulation_movement):
"""Returns the simulation state for this simulation movement.
This generic implementation assumes that if there is one open order line
which is validated or archived, the movements will be planned. This
behaviour might have to be adapted in subclasses.
"""
for path in self.getAggregateRelatedValueList(
portal_type=self.getPortalObject().getPortalSupplyPathTypeList(),):
if path.getValidationState() in ('validated', 'archived'):
return 'planned'
return 'draft'
def isSimulated(self): def isSimulated(self):
""" """
We are never simulated (unlike deliveries) We are never simulated (unlike deliveries)
......
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2011 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.
#
##############################################################################
"""
Products.ERP5.interfaces.expandable_item
"""
from Products.ERP5.interfaces.expandable import IExpandable
class IExpandableItem(IExpandable):
""" An expandable item is an item that generate simulation, such as a
Subscription Item or an Immobilisation Item.
Such items are also responsible for returning the simulation state of the
movements they build.
"""
def getSimulationMovementSimulationState(simulation_movement):
"""Returns the simulation state of this simulation movement, unless it is
built and related to a delivery.
"""
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