| Quintiq file version 2.0 | 
| #parent: #root | 
| Method InitConstraintsForShelfLifeSumConstraints ( | 
|   CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program, | 
|   const constcontent ProductInStockingPointInPeriods smartplanpispips, | 
|   constcontent ProductInStockingPoint_MPs intermediatepisps, | 
|   const ProductInStockingPointInPeriodPlanning pispip, | 
|   DateTime firstpispipstart, | 
|   DateTime lastpispipstart, | 
|   const LibOpt_Scope scope, | 
|   Real scalefactor_mass, | 
|   Real scalefactor_rhs_constr | 
| ) const | 
| { | 
|   Description: 'sum constraints split variables' | 
|   TextBody: | 
|   [* | 
|     // >> sum of split InvQty = InvQty  | 
|     { | 
|       constr := program.InvQtyShelfLifeSumConstraints().New( pispip );  | 
|       if ( scope.Contains( pispip.PISPIPInOptimizerRun() ) )  | 
|       { | 
|         constr.NewTerm( -1.0 * scalefactor_mass, program.InvQtyVariables().Get( pispip ) );  | 
|       } | 
|       else | 
|       { | 
|         constr.RHSValue( pispip.InventoryLevelEnd() * scalefactor_rhs_constr ); // optimizer itself figure out what has expired - so just sum to the total inventory quantity.  | 
|       } | 
|       traverse( pispip, ProductInStockingPoint_MP.IncomingShelfLifeDay, islday )   | 
|       { | 
|         constr.NewTerm( 1.0 * scalefactor_mass, program.InvQtyShelfLifeVariables().Get( pispip, islday ) );  | 
|       } | 
|     } | 
|      | 
|     // sum of split dependent demand = dependent demand  | 
|     { | 
|       constr := program.DependentDemandInPISPIPShelfLifeSumConstraints().New( pispip ); | 
|       if ( scope.Contains( pispip.PISPIPInOptimizerRun() ) )  | 
|       { | 
|         constr.NewTerm( -1.0 * scalefactor_mass, program.DependentDemandInPISPIPVariables().Get( pispip ) );  | 
|       } | 
|       else | 
|       { | 
|         constr.RHSValue( scalefactor_rhs_constr * pispip.DependentDemandQuantity() );  | 
|       } | 
|       traverse( pispip, ProductInStockingPoint_MP.IncomingShelfLifeDay, islday )   | 
|       { | 
|         traverse( pispip, ProductInStockingPoint_MP.OutgoingShelfLifeDay, oslday )  | 
|         { | 
|           constr.NewTerm( 1.0 * scalefactor_mass, program.DependentDemandInPISPIPShelfLifeVariables().Get( pispip, islday, oslday ) );  | 
|         } | 
|       } | 
|     } | 
|     // sum of split expired = expired on pispip | 
|     { | 
|       constr := program.ExpiredConstraints().New( pispip );  | 
|       constr.NewTerm( -1.0 * scalefactor_mass, program.ExpiredVariables().Get( pispip ) );  | 
|       traverse( pispip, ProductInStockingPoint_MP.IncomingShelfLifeDay, islday )  | 
|       { | 
|         constr.NewTerm( 1.0 * scalefactor_mass, program.ExpiredForAgeVariables().Get( pispip, islday ) );  | 
|       } | 
|     } | 
|      | 
|      | 
|     traverse( pispip.GetLeafSalesDemandInPeriod(), Elements, lsdip, not lsdip.IsPostponed() ) | 
|     { | 
|       constr := program.SalesDemandQtyShelfLifeSumConstraints().New( lsdip );  | 
|       if( scope.Contains( pispip.PISPIPInOptimizerRun() ) )   | 
|       { | 
|         constr.NewTerm( -1.0 * scalefactor_mass, program.SalesDemandQtyVariables().Get( lsdip ) );  | 
|       } | 
|       else | 
|       { | 
|         constr.RHSValue( lsdip.FulfilledQuantity() * scalefactor_rhs_constr );  | 
|       } | 
|       traverse( lsdip, ProductInStockingPoint_MP.IncomingShelfLifeDay, islday )  | 
|       { | 
|         constr.NewTerm( 1.0 * scalefactor_mass, program.SalesDemandShelfLifeQtyVariables().Get( lsdip, islday ) );  | 
|       } | 
|        | 
|       if( lsdip.CanBePostponed() and lsdip.NeedsToBePlanned() ) | 
|       { | 
|         nextpispip := lsdip.AsPlanningBaseSalesDemandInPeriod().NextPlanningPISPIP(); | 
|         minpostponement := guard( lsdip.SDIPBeforeScopeInRun().OptMinPostponementPeriod(), 1 ); // if object null, then no min postponement  | 
|         for( i := 2; i <= minpostponement and not isnull( nextpispip ); i++ ) | 
|         { | 
|           nextpispip := nextpispip.NextPlanningPISPIP(); | 
|         } | 
|          | 
|         for( i := minpostponement; | 
|              i <= lsdip.MaxPostponementPeriod()                                           // within the maximum number of postponement periods | 
|              and not isnull( nextpispip );                                          // the next pispip exists | 
|              i++ ) | 
|         { | 
|           constrsum := program.DelayedSalesDemandQtyShelfLifeSumConstraints().New( lsdip, nextpispip.Period_MP() ); | 
|           if ( scope.Contains(  nextpispip.PISPIPInOptimizerRun() ) )  | 
|           // can avoid scope.Contains(  nextpispip.PISPIPInOptimizerRun() ) ) because we are in the same transaction | 
|           { | 
|             constrsum.NewTerm( -1.0 * scalefactor_mass, program.DelayedSalesDemandQtyVariables().Get( lsdip, nextpispip.Period_MP() ) ); | 
|           } | 
|           else | 
|           { | 
|             postponedty := sum( lsdip, PostponedSalesDemand, psd, psd.ProductInStockingPointInPeriodPlanning() = nextpispip, psd.QuantityToPlan() );  | 
|             constrsum.RHSValue( postponedty * scalefactor_rhs_constr );  | 
|           } | 
|           traverse( lsdip, ProductInStockingPoint_MP.IncomingShelfLifeDay, islday )  | 
|           { | 
|             splitvar := program.DelayedSalesDemandShelfLifeQtyVariables().Get( lsdip, nextpispip.Period_MP(), islday ); | 
|             constrsum.NewTerm( 1.0 * scalefactor_mass, splitvar );  | 
|           } | 
|           nextpispip := nextpispip.NextPlanningPISPIP(); | 
|         } | 
|       }  | 
|     } | 
|      | 
|     traverse( pispip.GetDisaggregatedSalesDemandInPeriod(), Elements, dsdip ) | 
|     { | 
|       constr := program.DisAggregatedSalesDemandQtyShelfLifeSumConstraints().New( dsdip );  | 
|       if ( scope.Contains( pispip.PISPIPInOptimizerRun() ) )  | 
|       // can avoid scope.Contains( pispip.PISPIPInOptimizerRun() ) ) because we are in the same transaction | 
|       { | 
|         constr.NewTerm( -1.0 *scalefactor_mass, program.DisaggregatedSalesDemandQtyVariables().Get( dsdip ) );  | 
|       } | 
|       else | 
|       { | 
|         constr.RHSValue( dsdip.FulfilledQuantity() * scalefactor_rhs_constr );  | 
|       } | 
|       traverse( dsdip, ProductInStockingPoint_MP.IncomingShelfLifeDay, islday )  | 
|       { | 
|         program.DisaggregatedSalesDemandShelfLifeQtyVariables().Get( dsdip, islday ); | 
|       } | 
|        | 
|       if ( dsdip.CanBePostponed() and dsdip.NeedsToBePlanned() )  | 
|       { | 
|      | 
|         nextperiod := dsdip.AsSalesDemandInPeriodBase().Period_MP().NextPlanningPeriod();  // It is not possible to traverse PISPIP from disaggregated but not from Aggregated. | 
|         minpostponement := guard( dsdip.AggregatedSalesDemandInPeriod().SDIPBeforeScopeInRun().OptMinPostponementPeriod(), 1 ); // if object null, then no min postponement  | 
|         for( i := 2; i <= minpostponement and not isnull( nextperiod ); i++ ) | 
|         { | 
|           nextperiod := nextperiod.NextPlanningPeriod(); | 
|         } | 
|          | 
|         for( i := minpostponement; | 
|              i <= dsdip.MaxPostponementPeriod()                                           // within the maximum number of postponement periods | 
|              and not isnull( nextperiod );                                          // the next pispip exists | 
|              i++ ) | 
|         { | 
|           constrsum := program.DelayedDisaggregatedSalesDemandQtyShelfLifeSumConstraints().New( dsdip, nextperiod );  | 
|           var := program.DelayedDisaggregatedSalesDemandQtyVariables().Get( dsdip, nextperiod );  | 
|           if ( not isnull( var ) ) // if we are in the optimizer scope we need to use te var other obtain from model  | 
|           { | 
|             constrsum.NewTerm( -1.0 * scalefactor_mass, var );  | 
|           } | 
|           else | 
|           { | 
|             postponedqty := sum( dsdip, PostponedSalesDemand, psd, psd.ProductInStockingPointInPeriodPlanning().Period_MP() = nextperiod, psd.QuantityToPlan() );   | 
|             constrsum.RHSValue( postponedqty * scalefactor_rhs_constr );  | 
|           } | 
|           traverse( dsdip, ProductInStockingPoint_MP.IncomingShelfLifeDay, islday )  | 
|           { | 
|             constrsum.NewTerm( 1.0 * scalefactor_mass, program.DelayedDisaggregatedSalesDemandShelfLifeQtyVariables().Get( dsdip, nextperiod, islday ) );  | 
|           } | 
|           nextperiod := nextperiod.NextPlanningPeriod(); | 
|         } | 
|       } | 
|     } | 
|   *] | 
|   InterfaceProperties { Accessibility: 'Module' } | 
| } |