| Quintiq file version 2.0 | 
| #parent: #root | 
| Method CapacityPlanningAlgorithmHandleFeasibleSalesDemand ( | 
|   CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program, | 
|   const RunContextForCapacityPlanning runcontext, | 
|   LibOpt_Scope scope, | 
|   ProductInStockingPointInPeriodPlannings pispipsinrun | 
| ) | 
| { | 
|   Description: 'Set the sales demand fulfillment quantity, and postpone sales demands if optimizer are allowed to do so, and choose to do so' | 
|   TextBody: | 
|   [* | 
|     /* | 
|     REMOVE := true; cmt := 'tmp';   | 
|     if ( REMOVE )  | 
|     { | 
|       count := 0;  | 
|       traverse( this, MacroPlan.SalesDemand.SalesDemandInPeriod, s )  | 
|       { | 
|         count++;  | 
|         s.OptimizerMetaDebugOldFulfilledQuantity( s.FulfilledQuantity() );  | 
|         if ( count < 10 )  | 
|         { | 
|           debuginfo( s.SalesSegmentName(), s.OptimizerMetaDebugOldFulfilledQuantity() );  | 
|         } | 
|       } | 
|     } | 
|     */ | 
|      | 
|     this.MergeSalesDemands(scope, pispipsinrun ); // removes postponed sd for all sd in scope (provided the postponedsd has its pispip in scope)  | 
|      | 
|     // Leaf Sales Demands  | 
|     traverse( scope.GetLeafSalesDemandInPeriodInRun(), Elements, sd, isnull( sd.OriginalSalesDemand() ) or sd.IsManuallyPostponed() ) | 
|     { | 
|       qty := this.GetOptimalValue( program.SalesDemandQtyVariables().Get( sd ) ); | 
|       sd.UpdateOptimizerFulfillment( true, qty ); | 
|        | 
|       this.CapacityPlanningAlgorithmHandleFeasibleDelayedSalesDemand( sd, program, runcontext, scope, 1 ); | 
|     } | 
|      | 
|     // Aggregated sales demands for higher product level | 
|     traverse( scope.GetAggregatedSalesDemandInPeriodInRun(), Elements, asdip ) // Aggregated does not have pisp asdip.ProductInStockingPoint_MP().GetIsInOptimizerRun() | 
|     {  | 
|       // No optimizer variables for AggregatedSalesDemandInPeriod | 
|       // Traverse the children ( Disaggregated Sales demands ) | 
|       // skip postponed sales demand. Instead of using IsPostponed which requires a transaction propagate, we will just check for null OriginalSalesDemand | 
|       traverse ( asdip, DisaggregatedSalesDemandInPeriod, dasdip,  | 
|                  isnull( dasdip.OriginalSalesDemand() ) | 
|                  and scope.Contains( dasdip.AsPlanningBaseSalesDemandInPeriod().PISPIPInOptimizerRun() ) )  | 
|       { | 
|         // Type    : DisaggregatedSalesDemandInPeriod | 
|         // Variable: 'DisaggregatedSalesDemandQty' UoM: PISP | 
|         var := this.GetOptimalValue( program.DisaggregatedSalesDemandQtyVariables().Get( dasdip ) ); | 
|         dasdip.UpdateOptimizerFulfillment( true, var ); | 
|         // Type    : DelayedDisaggregatedSalesDemandInPeriod | 
|         // Variable: 'DelayedDisaggregatedSalesDemandQty' UoM: PISP | 
|         this.CapacityPlanningAlgorithmHandleFeasibleDelayedSalesDemand( dasdip, program, runcontext, scope, 1 ); | 
|       } | 
|     } | 
|      | 
|     // Sales demand before the optimization horizon, including those before the planning horizon. | 
|     // Leaf sales demands | 
|     traverse( scope.GetSDIPBeforeScopeInRun(), Elements.astype( LeafSalesDemandInPeriod ), lsdip ) | 
|     { | 
|       this.CapacityPlanningAlgorithmHandleFeasibleDelayedSalesDemand( lsdip, program, runcontext, scope, lsdip.SDIPBeforeScopeInRun().OptMinPostponementPeriod() ); | 
|     } | 
|      | 
|     // Aggregated sales demands for higher product level | 
|     traverse( scope.GetSDIPBeforeScopeInRun(), Elements.astype( AggregatedSalesDemandInPeriod ).DisaggregatedSalesDemandInPeriod, dasdip ) | 
|     { | 
|       this.CapacityPlanningAlgorithmHandleFeasibleDelayedSalesDemand( dasdip, program, runcontext, scope, | 
|                                                                       dasdip.AggregatedSalesDemandInPeriod().SDIPBeforeScopeInRun().OptMinPostponementPeriod() ); | 
|     } | 
|   *] | 
|   InterfaceProperties { Accessibility: 'Module' } | 
| } |