Commit d215f07a authored by Jean-Paul Smets's avatar Jean-Paul Smets

Initial pseudo-code

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@30366 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent b9c74460
......@@ -33,3 +33,30 @@ class FIFO(DeliverySolver):
"""
The FIFO solver reduces deliveted quantity by reducing the quantity of simulation movements from the last order.
"""
def solve(self, simulation_movement_list, new_quantity):
"""
"""
result = []
def sortByOrderStartDate(a, b);
return cmp(a.getExplainationValue().getStartDate() b.getExplainationValue().getStartDate())
simulation_movement_list.sort(sortByOrderStartDate)
simulation_movement_list.reverse()
total_quantity = 0
for movement in simulation_movement_list:
total_quantity += movement.getQuantity()
remaining_quantity = total_quantity - new_quantity
for movement in simulation_movement_list:
if remaining_quantity:
if movement.getQuantity() < remaining_quantity:
result.append((movement, movement.getQuantity()))
remaining_quantity -= movement.getQuantity()
movement.setQuantity(0)
else:
result.append((movement, remaining_quantity))
movement.setQuantity(movement.getQuantity() - remaining_quantity)
remaining_quantity = 0
# Return movement, split_quantity tuples
for movement in simulation_movement_list:
movement.setDeliveryRatio(movement.getQuantity() / new_quantity)
return result
\ No newline at end of file
......@@ -53,3 +53,18 @@ class AcceptSolver(XMLObject):
, PropertySheet.CategoryCore
, PropertySheet.DublinCore
)
# Implementation
def solve(self):
"""
"""
# Adopt new property, keep the original one recorded
solved_property = self.getPortalTypeValue().getTestedProperty()
for movement in self.getDeliveryValueList():
new_value = movement.getProperty(solved_property)
for simulation_movement in movement.getDeliveryRelatedValueList():
if not simulation_movement.isPropertyRecorded(solved_property):
simulation_movement.recordProperty(solved_property)
solved_property.setProperty(solved_property, new_value)
# Finish solving
self.succeed()
\ No newline at end of file
......@@ -55,3 +55,19 @@ class QuantitySplitSolver(XMLObject):
, PropertySheet.DublinCore
, PropertySheet.Arrow
)
# Implementation
def solve(self):
"""
"""
delivery_solver = self.portal_solvers.buildDeliverySolver(self.getDeliverySolver())
for delivery_line in self.getDeliveryValueList():
decision_quantity = delivery_line.getQuantity()
simulation_movement_list = self.getDeliveryRelatedValueList()
# Update the quantity using delivery solver algorithm
split_list = delivery_solver.solve(simulation_movement_list, decision_quantity)
# Create split movements
for (simulation_movement, split_quantity) in split_list:
new_movement = simulation_movement.copy() # Copy at same level
new_movement._setQuantity(split_quantity)
new_movement._setStartDate(self.getStartDate())
new_movement._setStopDate(self.getStopDate())
\ No newline at end of file
......@@ -72,3 +72,61 @@ class SolverProcess(XMLObject, ActiveProcess):
, PropertySheet.CategoryCore
, PropertySheet.DublinCore
)
def buildTargetSolverList(self):
"""
Builds target solvers from solver decisions
"""
solver_dict = {}
movement_dict = {}
types_tool = context.portal_types
# First create a mapping between delivery movements and solvers
# in order to know for each movements which solvers are needed
# and which parameters with
for decision in context.contentValues(portal_type="Solver Decision"):
solver = decision.getSolverValue()
solver_type = solver.getId() # ex. Postpone Production Solver
solver_conviguration_dict = decision.getConfigurationPropertyDict()
solver_conviguration_key = solver_conviguration_dict.items()
for movement in decision.getDeliveryValueList():
# Detect incompatibilities
movement_solver_dict = movement_dict.setdefault(movement.getRelativeUrl(), {})
movement_solver_configuration_dict = movement_solver_dict.setdefault(solver_type, {})
movement_solver_configuration_dict[solver_key] = None
# Second, make sure solvers do not conflict and configuration is valid
for movement_url, movement_solver_dict in movement_dict.items():
for solver_type, movement_solver_configuration_dict in movement_solver_dict.items():
solver = types_tool[solver_type]
for other_solver in movement_solver_dict.keys():
if solver.conflictsWithSolver(other_solver):
raise "Solver %s conflicts with solver %s on movement %s" % (solver_type, other_solver, movement_url)
# Make sure multiple configuration are possible
try:
# Solver key contains only those properties which differentiate
# solvers (ex. there should be only Production Reduction Solver)
solver_key = solver.reduceConfigurationList(movement_solver_configuration_dict.keys())
except:
raise
solver_key_dict = solver_dict.setdefault(solver_type, {})
solver_movement_dict = solver_key_dict.setdefault(solver_key, {})
solver_movement_dict[movement_url] = movement_solver_configuration_dict.keys()
# Third, build target solvers
for portal_type, solver_key_dict in solver_dict.items():
for solver_key, solver_movement_dict in solver_key_dict.items():
solver_instance = self.newContent(portal_type=solver_type)
solver_instance._setDeliveryList(solver_movement_dict.keys())
for movement_url, configuration_list:
for configuration_kw in configuration_list:
solver_instance.updateConfiguration(**configuration_kw)
# Solver Process Workflow Interface
# NOTE: how can we consider that a workflow defines or provides an interface ?
def solve(self):
"""
Start solving
"""
for solver in self.contentValues(portal_type=self.getPortalObject().getPortalTargetSolverTypeList()):
solver.activate(active_process=self).solve()
\ No newline at end of file
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