diff --git a/product/ERP5/Document/Delivery.py b/product/ERP5/Document/Delivery.py index e1927188e4e1281d968c41095e00b14fda8db8f0..71bac8d50b11a68eb9958f763f7b66b8b45f4ea1 100755 --- a/product/ERP5/Document/Delivery.py +++ b/product/ERP5/Document/Delivery.py @@ -627,14 +627,55 @@ une liste de mouvements...""" # else Do we need to create a simulation movement ? XXX probably not return 1 - security.declareProtected(Permissions.View, 'isDivergent') - def isDivergent(self): + security.declareProtected(Permissions.View, 'isArrowDivergent') + def isArrowDivergent(self): + if self.isSourceDivergent(): return 1 + if self.isDestinationDivergent(): return 1 + if self.isSourceSectionDivergent(): return 1 + if self.isDestinationSectionDivergent(): return 1 + return 0 + + security.declareProtected(Permissions.View, 'isSourceDivergent') + def isSourceDivergent(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 + Source is divergent if simulated and target values differ + or if multiple sources are defined + """ + return self.getSource() != self.getTargetSource() \ + or len(self.getSourceList()) > 1 \ + or len(self.getTargetSourceList()) > 1 + + security.declareProtected(Permissions.View, 'isDestinationDivergent') + def isDestinationDivergent(self): + """ + Destination is divergent if simulated and target values differ + or if multiple destinations are defined + """ + return self.getDestination() != self.getTargetDestination() \ + or len(self.getDestinationList()) > 1 \ + or len(self.getTargetDestinationList()) > 1 - emit targetUnreachable ! + security.declareProtected(Permissions.View, 'isSourceSectionDivergent') + def isSourceSectionDivergent(self): + """ + Same as isSourceDivergent for source_section + """ + return self.getSourceSection() != self.getTargetSourceSection() \ + or len(self.getSourceSectionList()) > 1 \ + or len(self.getTargetSourceSectionList()) > 1 + + security.declareProtected(Permissions.View, 'isDestinationSectionDivergent') + def isDestinationSectionDivergent(self): + """ + Same as isDestinationDivergent for source_section + """ + return self.getDestinationSection() != self.getTargetDestinationSection() \ + or len(self.getDestinationSectionList()) > 1 \ + or len(self.getTargetDestinationSectionList()) > 1 + + security.declareProtected(Permissions.View, 'isDateDivergent') + def isDateDivergent(self): + """ """ from DateTime import DateTime if self.getStartDate() is None or self.getTargetStartDate() is None \ @@ -643,34 +684,51 @@ une liste de mouvements...""" # This is uggly but required due to python2.2/2.3 Zope 2.6/2.7 inconsistency in _millis calculation if self.getStartDate().Date() != self.getTargetStartDate().Date() or \ self.getStopDate().Date() != self.getTargetStopDate().Date(): - LOG("isDivergent getStartDate", 0, repr(self.getStartDate())) - LOG("isDivergent getTargetStartDate", 0, repr(self.getTargetStartDate())) - LOG("isDivergent getStopDate", 0, repr(self.getStopDate())) - LOG("isDivergent getTargetStopDate", 0, repr(self.getTargetStopDate())) - - LOG("isDivergent getStartDate", 0, repr(self.getStartDate())) - LOG("isDivergent getTargetStartDate", 0, repr(self.getTargetStartDate())) - LOG("isDivergent getStopDate", 0, repr(self.getStopDate())) - LOG("isDivergent getTargetStopDate", 0, repr(self.getTargetStopDate())) - LOG("isDivergent getStartDate", 0, repr(self.getStartDate()._millis)) - LOG("isDivergent getTargetStartDate", 0, repr(self.getTargetStartDate()._millis)) - LOG("isDivergent getStopDate", 0, repr(self.getStopDate()._millis)) - LOG("isDivergent getTargetStopDate", 0, repr(self.getTargetStopDate()._millis)) - LOG("isDivergent class getStartDate", 0, repr(self.getStartDate().__class__)) - LOG("isDivergent class getTargetStartDate", 0, repr(self.getTargetStartDate().__class__)) - LOG("isDivergent class getStopDate", 0, repr(self.getStopDate().__class__)) - LOG("isDivergent class getTargetStopDate", 0, repr(self.getTargetStopDate().__class__)) - LOG("isDivergent", 0, repr(type(self.getStartDate()))) - LOG("isDivergent", 0, repr(type(self.getTargetStartDate()))) - LOG("isDivergent ==", 0, str(self.getStartDate() == self.getTargetStartDate())) - LOG("isDivergent !=", 0, str(self.getStartDate() != self.getTargetStartDate())) - LOG("isDivergent", 0, str(self.getStopDate() != self.getTargetStopDate())) +# LOG("isDivergent getStartDate", 0, repr(self.getStartDate())) +# LOG("isDivergent getTargetStartDate", 0, repr(self.getTargetStartDate())) +# LOG("isDivergent getStopDate", 0, repr(self.getStopDate())) +# LOG("isDivergent getTargetStopDate", 0, repr(self.getTargetStopDate())) +# +# LOG("isDivergent getStartDate", 0, repr(self.getStartDate())) +# LOG("isDivergent getTargetStartDate", 0, repr(self.getTargetStartDate())) +# LOG("isDivergent getStopDate", 0, repr(self.getStopDate())) +# LOG("isDivergent getTargetStopDate", 0, repr(self.getTargetStopDate())) +# LOG("isDivergent getStartDate", 0, repr(self.getStartDate()._millis)) +# LOG("isDivergent getTargetStartDate", 0, repr(self.getTargetStartDate()._millis)) +# LOG("isDivergent getStopDate", 0, repr(self.getStopDate()._millis)) +# LOG("isDivergent getTargetStopDate", 0, repr(self.getTargetStopDate()._millis)) +# LOG("isDivergent class getStartDate", 0, repr(self.getStartDate().__class__)) +# LOG("isDivergent class getTargetStartDate", 0, repr(self.getTargetStartDate().__class__)) +# LOG("isDivergent class getStopDate", 0, repr(self.getStopDate().__class__)) +# LOG("isDivergent class getTargetStopDate", 0, repr(self.getTargetStopDate().__class__)) +# LOG("isDivergent", 0, repr(type(self.getStartDate()))) +# LOG("isDivergent", 0, repr(type(self.getTargetStartDate()))) +# LOG("isDivergent ==", 0, str(self.getStartDate() == self.getTargetStartDate())) +# LOG("isDivergent !=", 0, str(self.getStartDate() != self.getTargetStartDate())) +# LOG("isDivergent", 0, str(self.getStopDate() != self.getTargetStopDate())) return 1 - + + security.declareProtected(Permissions.View, 'isQuantityDivergent') + def isQuantityDivergent(self): + """ + """ for line in self.contentValues(filter={'portal_type': movement_type_list}): if line.isDivergent(): return 1 + + 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.isArrowDivergent(): return 1 + if self.isDateDivergent(): return 1 + if self.isQuantityDivergent(): return 1 + return 0 security.declareProtected(Permissions.ModifyPortalContent, 'solve') @@ -1031,3 +1089,71 @@ une liste de mouvements...""" force_update = 1) # Use unit price JPSforYO return invoice_line_list + + # Simulation consistency propagation + security.declareProtected(Permissions.ModifyPortalContent, 'updateFromSimulation') + def updateFromSimulation(self, update_target = 0): + """ + Updates all lines and cells of this delivery based on movements + in the simulation related to this delivery through the delivery relation + + Error: resource in sim could change - we should disconnect in this case + """ + source_list = [] + destination_list = [] + target_source_list = [] + target_destination_list = [] + for l in self.objectValues(filter={'portal_type':delivery_movement_type_list}): + if l.hasCellContent(): + for c in l.objectValues(filter={'portal_type':delivery_movement_type_list}): + source_list.extend(c.getSimulationSourceList()) + destination_list.extend(c.getDestinationSourceList()) + c._setQuantity(c.getSimulationQuantity()) # Only update quantity here + if update_target: + c._setTargetQuantity(c.getSimulationTargetQuantity()) + else: + source_list.extend(l.getSimulationSourceList()) + destination_list.extend(l.getDestinationSourceList()) + l._setQuantity(l.getSimulationQuantity()) # Only update quantity here + if update_target: + c._setTargetQuantity(c.getSimulationTargetQuantity()) + # Update source list + self._setSourceSet(source_list) # Set should make sure each item is only once + self._setDestinationSet(destination_list) + if update_target: + self._setTargetSourceSet(target_source_list) # Set should make sure each item is only once + self._setTargetDestinationSet(target_destination_list) + + security.declareProtected(Permissions.ModifyPortalContent, 'propagateResourceToSimulation') + def propagateResourceToSimulation(self): + """ + Propagates any changes on resources or variations to the simulation + by disconnecting simulation movements refering to another resource/variation, + creating DeliveryRules for new resources and setting target_quantity to 0 for resources + which are no longer delivered + + propagateResourceToSimulation has priority (ie. must be executed befoire) over updateFromSimulation + """ + unmatched_simulation_movement = [] + unmatched_delivery_movement = [] + for l in self.objectValues(filter={'portal_type':delivery_movement_type_list}): + if l.hasCellContent(): + for c in l.objectValues(filter={'portal_type':delivery_movement_type_list}): + for s in c.getDeliveryRelatedValueList(): + if s.getResource() != c.getResource() or s.getVariationText() != c.getVariationText(): # We should use here some day getVariationValue and __cmp__ + unmatched_delivery_movement.append(c) + unmatched_simulation_movement.append(s) + s.setDelivery(None) # Disconnect + l._setQuantity(0.0) + else: + for s in l.getDeliveryRelatedValueList(): + if s.getResource() != l.getResource() or s.getVariationText() != l.getVariationText(): + unmatched_delivery_movement.append(l) + unmatched_simulation_movement.append(s) + s.setDelivery(None) # Disconnect + l._setQuantity(0.0) + # Build delivery list with unmatched_simulation_movement + new_delivery_list = self.portal_simulation.buildDeliveryList(unmatched_simulation_movement) + # And merge into us + self.portal_simulation.doFusion([self].extend(new_delivery_list)) + \ No newline at end of file