Commit c7af41ac authored by Łukasz Nowak's avatar Łukasz Nowak

- cleanup imports

 - add delivery line solve method
 - put solving/divergence methods near each other


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@28471 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent fb3840cd
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, Constraint, interfaces from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.XMLMatrix import XMLMatrix from Products.ERP5Type.XMLMatrix import XMLMatrix
from Products.ERP5Type.XMLObject import XMLObject from Products.ERP5Type.XMLObject import XMLObject
...@@ -36,8 +36,6 @@ from Products.ERP5.Document.Movement import Movement ...@@ -36,8 +36,6 @@ from Products.ERP5.Document.Movement import Movement
from Products.ERP5.Variated import Variated from Products.ERP5.Variated import Variated
from Products.ERP5.Document.ImmobilisationMovement import ImmobilisationMovement from Products.ERP5.Document.ImmobilisationMovement import ImmobilisationMovement
from zLOG import LOG
class DeliveryLine(Movement, XMLObject, XMLMatrix, Variated, class DeliveryLine(Movement, XMLObject, XMLMatrix, Variated,
ImmobilisationMovement): ImmobilisationMovement):
""" """
...@@ -225,34 +223,6 @@ class DeliveryLine(Movement, XMLObject, XMLMatrix, Variated, ...@@ -225,34 +223,6 @@ class DeliveryLine(Movement, XMLObject, XMLMatrix, Variated,
return XMLMatrix.newCell(self, *kw, **kwd) return XMLMatrix.newCell(self, *kw, **kwd)
security.declareProtected(Permissions.View, 'isDivergent')
def isDivergent(self):
"""
Returns 1 if the target is not met according to the current information
After and edit, the isOutOfTarget will be checked. If it is 1,
a message is emitted
emit targetUnreachable !
"""
if self.getDivergenceList() == []:
return 0
else:
return 1
security.declareProtected(Permissions.View, 'getDivergenceList')
def getDivergenceList(self):
"""
Return a list of messages that contains the divergences
"""
divergence_list = []
if self.hasCellContent():
for cell in self.contentValues(filter={
'portal_type': self.getPortalDeliveryMovementTypeList()}):
divergence_list.extend(cell.getDivergenceList())
return divergence_list
else:
return Movement.getDivergenceList(self)
def applyToDeliveryLineRelatedMovement(self, portal_type='Simulation Movement', method_id = 'expand'): def applyToDeliveryLineRelatedMovement(self, portal_type='Simulation Movement', method_id = 'expand'):
# Find related in simulation # Find related in simulation
for my_simulation_movement in self.getDeliveryRelatedValueList( for my_simulation_movement in self.getDeliveryRelatedValueList(
...@@ -395,3 +365,203 @@ class DeliveryLine(Movement, XMLObject, XMLMatrix, Variated, ...@@ -395,3 +365,203 @@ class DeliveryLine(Movement, XMLObject, XMLMatrix, Variated,
container.reindexObject() container.reindexObject()
return Movement.manage_beforeDelete(self, item, container) return Movement.manage_beforeDelete(self, item, container)
# divergence support with solving
security.declareProtected(Permissions.View, 'isDivergent')
def isDivergent(self):
"""
Returns 1 if the target is not met according to the current information
After and edit, the isOutOfTarget will be checked. If it is 1,
a message is emitted
emit targetUnreachable !
"""
if self.getDivergenceList() == []:
return 0
else:
return 1
security.declareProtected(Permissions.View, 'getDivergenceList')
def getDivergenceList(self):
"""
Return a list of messages that contains the divergences
"""
divergence_list = []
if self.hasCellContent():
for cell in self.contentValues(filter={
'portal_type': self.getPortalDeliveryMovementTypeList()}):
divergence_list.extend(cell.getDivergenceList())
return divergence_list
else:
return Movement.getDivergenceList(self)
def _distributePropertyToSimulation(self, decision):
"""Distributes property from self to all related simulation movements
AKA - accept decision"""
for simulation_movement in self.getDeliveryRelatedValueList(
portal_type='Simulation Movement'):
simulation_movement.edit(**{
decision.divergence.tested_property:
self.getProperty(decision.divergence.tested_property)
})
def _updatePropertyFromSimulation(self, decision_list):
"""Update property from simulation
'Stolen' from Products.ERP5.Document.DeliveryBuilder._solveDivergence
Another possibility is to just simply copy properties or, in case of
quantity, add from all simulation movements.
"""
simulation_movement_list = self.getDeliveryRelatedValueList(
portal_type="Simulation Movement")
business_path = simulation_movement_list[0].getCausalityValue()
delivery = self.getExplanationValue()
delivery_portal_type = delivery.getPortalType()
delivery_line_portal_type = self.getPortalType()
# we need to find only one matching delivery builder
for delivery_builder in business_path.getDeliveryBuilderValueList():
if delivery_builder.getDeliveryPortalType() == \
delivery_portal_type and \
delivery_builder.getDeliveryLinePortalType() == \
delivery_line_portal_type:
break
else:
raise ValueError('No builder found')
self.edit(quantity=0) # adoption have to 'rebuild' delivery line
movement_type_list = (delivery_builder.getDeliveryLinePortalType(),
delivery_builder.getDeliveryCellPortalType())
# Collect
root_group_node = delivery_builder.collectMovement(
simulation_movement_list)
divergence_list = [decision.divergence for decision in decision_list]
# Build
portal = self.getPortalObject()
delivery_module = getattr(portal, delivery_builder.getDeliveryModule())
delivery_to_update_list = [delivery]
delivery_builder._resetUpdated()
delivery_list = delivery_builder._processDeliveryGroup(
delivery_module,
root_group_node,
delivery_builder.getDeliveryMovementGroupList(),
delivery_to_update_list=delivery_to_update_list,
divergence_list=divergence_list,
force_update=1)
new_delivery_list = [x for x in delivery_list if x != delivery]
if new_delivery_list:
raise ValueError('No new deliveries shall be created')
# Then, we should re-apply quantity divergence according to 'Do
# nothing' quantity divergence list because all quantity are already
# calculated in adopt prevision phase.
quantity_dict = {}
for divergence in self.getDivergenceList():
if divergence.getProperty('divergence_scope') != 'quantity' or \
divergence in divergence_list:
continue
s_m = divergence.getProperty('simulation_movement')
delivery_movement = s_m.getDeliveryValue()
assert delivery_movement == self
quantity_gap = divergence.getProperty('decision_value') - \
divergence.getProperty('prevision_value')
delivery_movement.setQuantity(delivery_movement.getQuantity() + \
quantity_gap)
quantity_dict[s_m] = \
divergence.getProperty('decision_value')
# Finally, recalculate delivery_ratio
#
# Here, created/updated movements are not indexed yet. So we try to
# gather delivery relations from simulation movements.
delivery_dict = {}
for s_m in simulation_movement_list:
delivery_path = s_m.getDelivery()
delivery_dict[delivery_path] = \
delivery_dict.get(delivery_path, []) + \
[s_m]
for s_m_list_per_movement in delivery_dict.values():
total_quantity = sum([quantity_dict.get(s_m, s_m.getQuantity()) \
for s_m in s_m_list_per_movement])
if total_quantity != 0.0:
for s_m in s_m_list_per_movement:
delivery_ratio = quantity_dict.get(s_m, s_m.getQuantity()) \
/ total_quantity
s_m.edit(delivery_ratio=delivery_ratio)
else:
for s_m in s_m_list_per_movement:
delivery_ratio = 1.0 / len(s_m_list_per_movement)
s_m.edit(delivery_ratio=delivery_ratio)
def solve(self, decision_list):
"""Solves line according to decision list
decision_list is list of DivergenceDecision class instance
"""
"""How to play
delivery_line = context
from DateTime import DateTime
from Products.ERP5.DivergenceDecision import DivergenceDecision
decision_list = []
# adopt
for d in context.getDivergenceList():
decision = DivergenceDecision(d, 'adopt', None, None)
decision_list.append(decision)
delivery_line.solve(decision_list)
return 'ok'
# split
for d in delivery_line.getDivergenceList():
if d.tested_property == 'quantity':
split_kw = {}
split_kw.update(start_date = DateTime('2009/01/01'),
stop_date = DateTime('2009/01/10'))
decision = DivergenceDecision(d, 'split', None, 'SplitAndDefer',
split_kw = split_kw)
decision_list.append(decision)
delivery_line.solve(decision_list)
return 'ok'
# adopt
for d in delivery_line.getDivergenceList():
if d.tested_property == 'quantity':
decision = DivergenceDecision(d, 'adopt', None, None)
decision_list.append(decision)
delivery_line.solve(decision_list)
return 'ok'
"""
simulation_tool = self.getPortalObject().portal_simulation
solveMovement = simulation_tool.solveMovement
solve_result_list = []
# accept + split
for decision in [q for q in decision_list if q.decision != 'adopt']:
for simulation_movement in self.getDeliveryRelatedValueList(
portal_type='Simulation Movement'):
simulation_movement.appendDecision(decision)
if decision.decision == 'accept':
# accepting - in case of passed DeliverySolver use it, otherwise
# simply copy values to simulation
if not decision.delivery_solver_name:
self._distributePropertyToSimulation(decision)
solveMovement(self, decision.delivery_solver_name,
decision.target_solver_name)
elif decision.decision == 'split':
solveMovement(self, decision.delivery_solver_name,
decision.target_solver_name, **decision.split_kw)
else: # aka - do nothing
pass
# adopt
adopt_decision_list = [q for q in decision_list \
if q.decision == 'adopt']
if adopt_decision_list:
# XXX/FIXME appendDecision in this case
self._updatePropertyFromSimulation(adopt_decision_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