From 6456f669ef67cee8afa2b1809cfb157e121b17cd Mon Sep 17 00:00:00 2001 From: Romain Courteaud <romain@nexedi.com> Date: Tue, 12 Jul 2005 12:22:11 +0000 Subject: [PATCH] Split DeliveryBuilder in order to generate "auto-planned" Order. git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@3449 20353a03-c40f-0410-a6d1-a30d3c3de9de --- product/ERP5/Document/DeliveryBuilder.py | 373 +---------------------- 1 file changed, 6 insertions(+), 367 deletions(-) diff --git a/product/ERP5/Document/DeliveryBuilder.py b/product/ERP5/Document/DeliveryBuilder.py index 1deb7075ac..4cd4f0f920 100755 --- a/product/ERP5/Document/DeliveryBuilder.py +++ b/product/ERP5/Document/DeliveryBuilder.py @@ -29,16 +29,14 @@ from AccessControl import ClassSecurityInfo from Products.CMFCore.utils import getToolByName from Products.ERP5Type import Permissions, PropertySheet, Constraint, Interface -from Products.ERP5Type.XMLObject import XMLObject -from Products.ERP5.Document.Predicate import Predicate -from Products.ERP5.Document.Amount import Amount from Acquisition import aq_base, aq_parent, aq_inner, aq_acquire from Products.ERP5 import MovementGroup from Products.ERP5Type.Utils import convertToUpperCase +from Products.ERP5.Document.OrderBuilder import OrderBuilder from zLOG import LOG -class DeliveryBuilder(XMLObject, Amount, Predicate): +class DeliveryBuilder(OrderBuilder): """ Delivery Builder objects allow to gather multiple Simulation Movements into a single Delivery. @@ -95,349 +93,6 @@ class DeliveryBuilder(XMLObject, Amount, Predicate): , PropertySheet.DeliveryBuilder ) - security.declareProtected(Permissions.ModifyPortalContent, 'build') - def build(self, applied_rule_uid=None, movement_relative_url_list=[], - delivery_relative_url_list=[]): - """ - Build deliveries from a list of movements - - Delivery Builders can also be provided with optional parameters to - restrict selection to a given root Applied Rule caused by a single Order - or to Simulation Movements related to a limited set of existing - """ - # Select - if movement_relative_url_list == []: - movement_list = self.searchMovementList( - applied_rule_uid=applied_rule_uid) - else: - movement_list = [self.restrictedTraverse(relative_url) for relative_url\ - in movement_relative_url_list] - # Collect - root_group = self.collectMovement(movement_list) - # Build - delivery_list = self.buildDeliveryList( - root_group, - delivery_relative_url_list=delivery_relative_url_list) - # Call script on each delivery built - delivery_after_generation_script_id =\ - self.getDeliveryAfterGenerationScriptId() - if delivery_after_generation_script_id not in ["", None]: - for delivery in delivery_list: - getattr(delivery, delivery_after_generation_script_id)() - return delivery_list - - def searchMovementList(self, applied_rule_uid=None): - """ - defines how to query all Simulation Movements which meet certain criteria - (including the above path path definition). - - First, select movement matching to criteria define on DeliveryBuilder - Then, call script simulation_select_method to restrict movement_list - """ - movement_list = [] - kw = {} - # We only search Simulation Movement - kw['portal_type'] = 'Simulation Movement' - # Search only child movement from this applied rule - if applied_rule_uid is not None: - kw['parent_uid'] = applied_rule_uid - # XXX Add profile query - # Add resource query - if self.resource_portal_type not in ('', None): - kw['resourceType'] = self.resource_portal_type - - if self.simulation_select_method_id in ['', None]: - kw.update(self.portal_catalog.buildSQLQuery(**kw)) - movement_list = [x.getObject() for x in self.portal_catalog(**kw)] - else: - select_method = getattr(self, self.simulation_select_method_id) - movement_list = select_method(**kw) - - # XXX Use buildSQLQuery will be better - movement_list = filter(lambda x: x.getDeliveryRelatedValueList()==[], - movement_list) - - # XXX Add predicate test - return movement_list - - def getCollectOrderList(self): - """ - Simply method to get the 3 collect order lists define on a - DeliveryBuilder - """ - return self.getDeliveryCollectOrderList()+\ - self.getDeliveryLineCollectOrderList()+\ - self.getDeliveryCellCollectOrderList() - - def collectMovement(self, movement_list): - """ - group movements in the way we want. Thanks to this method, we are able - to retrieve movement classed by order, resource, criterion,.... - - movement_list : the list of movement wich we want to group - - check_list : the list of classes used to group movements. The order - of the list is important and determines by what we will - group movement first - Typically, check_list is : - [DateMovementGroup,PathMovementGroup,...] - """ - class_list = [] - for class_name in self.getCollectOrderList(): - class_list.append(getattr(MovementGroup, class_name)) - - last_line_class_name = self.getDeliveryLineCollectOrderList()[-1] - separate_method_name_list = self.getDeliveryCellSeparateOrderList() - - my_root_group = MovementGroup.RootMovementGroup( - class_list, - last_line_class_name=last_line_class_name, - separate_method_name_list=separate_method_name_list) - for movement in movement_list: - my_root_group.append(movement) - - return my_root_group - - def testObjectProperties(self, object, property_dict): - """ - Test object properties. - """ - result = 1 - for key in property_dict: - getter_name = 'get%s' % convertToUpperCase(key) - if hasattr(object, getter_name): - value = getattr(object, getter_name)() - if value != property_dict[key]: - result = 0 - break - else: - result = 0 - break - return result - - def buildDeliveryList(self, movement_group, delivery_relative_url_list=[]): - """ - Build deliveries from a list of movements - """ - # Module where we can create new deliveries - delivery_module = getattr(self, self.getDeliveryModule()) - - delivery_to_update_list = [self.restrictedTraverse(relative_url) for\ - relative_url in delivery_relative_url_list] - # Deliveries we are trying to update - delivery_select_method_id = self.getDeliverySelectMethodId() - if delivery_select_method_id not in ["", None]: - movement_list = [] - for movement in movement_group.getMovementList() : - if movement.__class__.__name__ == "FakeMovement": - movement_list += movement.getMovementList() - else: - movement_list += [movement] - to_update_delivery_sql_list = getattr(self, delivery_select_method_id)\ - (movement_list=movement_list) - delivery_to_update_list.extend([x.getObject() for x\ - in to_update_delivery_sql_list]) - - delivery_list = self._deliveryGroupProcessing( - delivery_module, - movement_group, - self.getDeliveryCollectOrderList(), - {}, - delivery_to_update_list=delivery_to_update_list) - - return delivery_list - - def _deliveryGroupProcessing(self, delivery_module, movement_group, - collect_order_list, property_dict, - delivery_to_update_list=[]): - """ - Build empty delivery from a list of movement - """ - delivery_list = [] - - # Get current properties from current movement group - # And fill property_dict - property_dict.update(movement_group.getGroupEditDict()) - - if collect_order_list != []: - # Get sorted movement for each delivery - for group in movement_group.getGroupList(): - new_delivery_list = self._deliveryGroupProcessing( - delivery_module, - group, - collect_order_list[1:], - property_dict.copy(), - delivery_to_update_list=delivery_to_update_list) - - delivery_list.extend(new_delivery_list) - - else: - # Test if we can update a existing delivery, or if we need to create - # a new one - delivery = None - for delivery_to_update in delivery_to_update_list: - if self.testObjectProperties(delivery_to_update, property_dict): - # Check if delivery has the correct portal_type - if delivery_to_update.getPortalType() ==\ - self.getDeliveryPortalType(): - delivery = delivery_to_update - break - - if delivery == None: - # Create delivery - new_delivery_id = str(delivery_module.generateNewId()) - delivery = delivery_module.newContent( - portal_type=self.getDeliveryPortalType(), - id=new_delivery_id) - # Put properties on delivery - delivery.edit(**property_dict) - - # Then, create delivery line - for group in movement_group.getGroupList(): - self._deliveryLineGroupProcessing( - delivery, - group, - self.getDeliveryLineCollectOrderList()[1:], - {}) - - delivery_list.append(delivery) - - return delivery_list - - def _deliveryLineGroupProcessing(self, delivery, movement_group, - collect_order_list, property_dict): - """ - Build delivery line from a list of movement on a delivery - """ - # Get current properties from current movement group - # And fill property_dict - property_dict.update(movement_group.getGroupEditDict()) - - if collect_order_list != []: - # Get sorted movement for each delivery line - for group in movement_group.getGroupList(): - self._deliveryLineGroupProcessing( - delivery, group, collect_order_list[1:], property_dict.copy()) - else: - # Test if we can update an existing line, or if we need to create a new - # one - delivery_line = None - update_existing_line=0 - for delivery_line_to_update in delivery.contentValues( - filter={'portal_type':self.getDeliveryLinePortalType()}): - if self.testObjectProperties(delivery_line_to_update, property_dict): - delivery_line = delivery_line_to_update - update_existing_line=1 - break - - if delivery_line == None: - # Create delivery line - new_delivery_line_id = str(delivery.generateNewId()) - delivery_line = delivery.newContent( - portal_type=self.getDeliveryLinePortalType(), - id=new_delivery_line_id, - variation_category_list=[]) - # Put properties on delivery line - delivery_line.edit(**property_dict) - - # Update variation category list on line - line_variation_category_list = delivery_line.getVariationCategoryList() - for movement in movement_group.getMovementList(): - line_variation_category_list.extend( - movement.getVariationCategoryList()) - # erase double - line_variation_category_list = dict([(x, 1) for x in\ - line_variation_category_list]).keys() - delivery_line.setVariationCategoryList(line_variation_category_list) - - # Then, create delivery movement (delivery cell or complete delivery - # line) - for group in movement_group.getGroupList(): - self._deliveryCellGroupProcessing( - delivery_line, - group, - self.getDeliveryCellCollectOrderList()[1:], - {}, - update_existing_line=update_existing_line) - - def _deliveryCellGroupProcessing(self, delivery_line, movement_group, - collect_order_list, property_dict, - update_existing_line=0): - """ - Build delivery cell from a list of movement on a delivery line - or complete delivery line - """ - # Get current properties from current movement group - # And fill property_dict - property_dict.update(movement_group.getGroupEditDict()) - - if collect_order_list != []: - # Get sorted movement for each delivery line - for group in movement_group.getGroupList(): - self._deliveryCellGroupProcessing( - delivery_line, - group, - collect_order_list[1:], - property_dict.copy(), - update_existing_line=update_existing_line) - else: - movement_list = movement_group.getMovementList() - if len(movement_list) != 1: - raise "CollectError", "DeliveryBuilder: %s unable to distinct those\ - movements: %s" % (self.getId(), str(movement_list)) - else: - # XXX Hardcoded value - base_id = 'movement' - object_to_update = None - # We need to initialize the cell - update_existing_movement=0 - movement = movement_list[0] - # decide if we create a cell or if we update the line - # Decision can only be made with line matrix range: - # because matrix range can be empty even if line variation category - # list is not empty - if list(delivery_line.getCellKeyList(base_id=base_id)) == []: - # update line - object_to_update = delivery_line - if self.testObjectProperties(delivery_line, property_dict): - if update_existing_line == 1: - # We update a initialized line - update_existing_movement=1 - - else: - for cell_key in delivery_line.getCellKeyList(base_id=base_id): - if delivery_line.hasCell(base_id=base_id, *cell_key): - cell = delivery_line.getCell(base_id=base_id, *cell_key) - if self.testObjectProperties(cell, property_dict): - # We update a existing cell - # delivery_ratio of new related movement to this cell - # must be updated to 0. - update_existing_movement=1 - object_to_update = cell - break - - if object_to_update is None: - # create a new cell - cell_key = movement.getVariationCategoryList() - if not delivery_line.hasCell(base_id=base_id, *cell_key): - cell = delivery_line.newCell(base_id=base_id,\ - portal_type=self.getDeliveryCellPortalType(), *cell_key) - cell._edit(category_list=cell_key, - # XXX hardcoded value - mapped_value_property_list=['quantity', 'price'], - membership_criterion_category_list=cell_key, - membership_criterion_base_category_list=movement.\ - getVariationBaseCategoryList()) - object_to_update = cell - - else: - raise 'MatrixError', 'Cell: %s already exists on %s' %\ - (str(cell_key), str(delivery_line)) - - self._setDeliveryMovementProperties( - object_to_update, movement, property_dict, - update_existing_movement=update_existing_movement) - def _setDeliveryMovementProperties(self, delivery_movement, simulation_movement, property_dict, update_existing_movement=0): @@ -447,26 +102,10 @@ class DeliveryBuilder(XMLObject, Amount, Predicate): Create the relation between simulation movement and delivery movement. """ - if update_existing_movement == 1: - # Important. - # Attributes of object_to_update must not be modified here. - # Because we can not change values that user modified. - # Delivery will probably diverge now, but this is not the job of - # DeliveryBuilder to resolve such problem. - # Use Solver instead. - #simulation_movement.setDeliveryRatio(0) - simulation_movement.edit(delivery_ratio=0) - else: - # Now, only 1 movement is possible, so copy from this movement - # XXX hardcoded value - property_dict['quantity'] = simulation_movement.getQuantity() - property_dict['price'] = simulation_movement.getPrice() - - # Update properties on object (quantity, price...) - delivery_movement.edit(**property_dict) - #simulation_movement.setDeliveryRatio(1) - simulation_movement.edit(delivery_ratio=1) - + OrderBuilder._setDeliveryMovementProperties( + self, delivery_movement, + simulation_movement, property_dict, + update_existing_movement=update_existing_movement) # Update simulation movement #simulation_movement.setDeliveryValue(delivery_movement) simulation_movement.edit(delivery_value=delivery_movement) -- 2.30.9