Quintiq file version 2.0 
 | 
#parent: #root 
 | 
Method AddTermsToServiceLevelConstraints ( 
 | 
  CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program, 
 | 
  const constcontent BaseSalesDemandInPeriods bsdips, 
 | 
  Real scalefactor_salesdemandqty_constfromsd_det, 
 | 
  Real scalefactor_salesdemandqty_constfromsd_sto, 
 | 
  const LibOpt_Scope scope 
 | 
) const 
 | 
{ 
 | 
  Description: 'Add the sales demand term to the service level from sales demand constraints' 
 | 
  TextBody: 
 | 
  [* 
 | 
    // Only define the constraints if the sd needs to be planned and is on a pispip that is part of this optimizer run 
 | 
    traverse( bsdips,  
 | 
              Elements,  
 | 
              sd, 
 | 
              sd.NeedsToBePlanned() 
 | 
              and sd.IsWithinThresholdQuantity() ) 
 | 
    { 
 | 
      uomconversion := sd.DefaultUOMConversionFactor(); 
 | 
      ids := sd.ServiceLevelBaseIDs().Tokenize( ';' ); 
 | 
      traverse( ids, Elements, id, not id = '' ) 
 | 
      {  
 | 
        sl := ServiceLevelBase::FindServiceLevelBaseTypeIndex( id );  
 | 
        if ( sl.IsEnabled() )  
 | 
        {         
 | 
          constr := null(  MPConstraint );  
 | 
          scalefactor := 0.0;  
 | 
          if ( sl.IsUsedForPlanningFulfillmentSystem() ) 
 | 
          { 
 | 
            constr := program.FulfillmentTargetFromSDQtyConstraints().Get(  sl );   
 | 
            scalefactor := scalefactor_salesdemandqty_constfromsd_det;  
 | 
          } 
 | 
          else if ( sl.IsUsedForSafetyStockCalculation() )  
 | 
          { 
 | 
            constr := program.ServiceLevelFromSDQtyConstraints().Get( sl ); 
 | 
            scalefactor := scalefactor_salesdemandqty_constfromsd_sto;  
 | 
          } 
 | 
           
 | 
          if ( not isnull( constr ) )  
 | 
          {    
 | 
            constr.Enabled( true ); // adding a term so make it enabled 
 | 
            if( sd.istype( LeafSalesDemandInPeriod ) ) 
 | 
            { 
 | 
                constr.NewTerm( -uomconversion * scalefactor, program.SalesDemandQtyVariables().Get( sd.astype( LeafSalesDemandInPeriod ) ) ); 
 | 
            } 
 | 
            else if( sd.istype( DisaggregatedSalesDemandInPeriod ) ) 
 | 
            { 
 | 
                constr.NewTerm( -uomconversion * scalefactor, program.DisaggregatedSalesDemandQtyVariables().Get( sd.astype( DisaggregatedSalesDemandInPeriod ) ) ); 
 | 
            } 
 | 
             
 | 
            // track existing fulfilled qty. Then what is out of scope is computed 
 | 
            // by sl.TotalFulFilledQuantity - sl.OptimizerConstantTerm 
 | 
            var_workaround_const := program.Variable( 'OptimizerConstantTerm', sl );  
 | 
            newvalue := var_workaround_const.UpperBound() + sd.FulfilledQuantityInDefaultUOM();  
 | 
            this.StoreValueInVariable( var_workaround_const, newvalue );  
 | 
          }                                                                                               
 | 
        } // end if isenabled 
 | 
      } // traverse sl  
 | 
    } 
 | 
  *] 
 | 
  InterfaceProperties { Accessibility: 'Module' } 
 | 
} 
 |