# -*- coding: utf-8 -*- ############################################################################## # # Copyright (c) 2017 Nexedi SA and Contributors. All Rights Reserved. # Sebastien Robin <seb@nexedi.com> # # 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. # ############################################################################## import zope.interface from AccessControl import ClassSecurityInfo from Products.ERP5Type import Permissions, PropertySheet, interfaces from Products.ERP5Type.XMLObject import XMLObject from Products.ERP5Type.Globals import PersistentMapping from Products.ERP5.mixin.solver import SolverMixin from Products.ERP5.Document.QuantitySplitSolver import QuantitySplitSolver class QuantitySplitMoveSolver(QuantitySplitSolver): """Target solver that split the prevision based on quantity. Similar to QuantitySplitSolver, it creates another prevision movement with the delta quantity between decision and prevision. But this time we will move quantities to an existing delivery that would be passed as parameter to this solver (usually selected directly by user). """ meta_type = 'ERP5 Quantity Split And Move Solver' portal_type = 'Quantity Split And Move Solver' add_permission = Permissions.AddPortalContent isIndexable = 0 # We do not want to fill the catalog with objects on which we need no reporting # Declarative security security = ClassSecurityInfo() security.declareObjectProtected(Permissions.AccessContentsInformation) # Declarative interfaces zope.interface.implements(interfaces.ISolver, interfaces.IConfigurable, ) # ISolver Implementation def _solve(self, activate_kw=None): """ Split simulation movements, and build them into existing delivery """ portal = self.getPortalObject() diverged_simulation_movement = self.getDeliveryValue() solver_dict = self._solveBySplitting(activate_kw=activate_kw) configuration_dict = self.getConfigurationPropertyDict() new_movement_list = solver_dict['new_movement_list'] delivery = diverged_simulation_movement.getDeliveryValue().getParentValue() assert delivery.isDelivery() trade_phase = self.getDeliveryValue().getTradePhase() assert trade_phase is not None, "Unable to solve, no trade phase is defined for %s" % diverged_simulation_movement.getRelativeUrl() business_link_list = diverged_simulation_movement.asComposedDocument().getBusinessLinkValueList(trade_phase=trade_phase) assert len(business_link_list) == 1, "Expected to find only one business link for trade_phase %s, but found %r" % (trade_phase, [x.getRelativeUrl() for x in business_link_list]) business_link, = business_link_list delivery_builder_list = business_link.getDeliveryBuilderValueList() assert len(delivery_builder_list) == 1, "Expected to find only one builder on business link, but found %r" % ( business_link.getRelativeUrl(), [x.getRelativeUrl() for x in delivery_builder_list]) delivery_builder, = delivery_builder_list # Update simulation movements to make sure they match the new delivery delivery_level_movement_group = [x for x in delivery_builder.objectValues() if x.getCollectOrderGroup() == "delivery"] delivery_to_move = portal.unrestrictedTraverse(configuration_dict['delivery_url']) assert delivery_to_move.getDivergenceList() == [] for movement_group in delivery_level_movement_group: tested_property_list = movement_group.getTestedPropertyList() for tested_property in tested_property_list: for new_movement in new_movement_list: new_movement.setPropertyList(tested_property, delivery_to_move.getPropertyList(tested_property)) new_movement.recordProperty(tested_property) delivery_builder.build(delivery_relative_url_list=[configuration_dict['delivery_url']], movement_list=new_movement_list) # Now the delivery_builder has chance to be divergent. In such case, make sure to accept value # from simulation divergence_list = delivery_to_move.getDivergenceList() if divergence_list: """def _solveDivergence(self, document, property, solver, **kw):""" """Solve divergence by using solver tool""" solver_process_tool = portal.portal_solver_processes solver_process = solver_process_tool.newSolverProcess(delivery_to_move) solver_decision, = [x for x in solver_process.contentValues() if x.getCausalityValue().getTestedProperty() == "quantity"] # use Quantity Accept Solver. solver_decision.setSolverValue(portal.portal_solvers['Adopt Solver']) # configure for Accept Solver. solver_decision.updateConfiguration(tested_property_list=['quantity']) solver_process.buildTargetSolverList() solver_process.solve()