Quintiq file version 2.0
|
#parent: #root
|
StaticMethod AddSalesDemandsBeforeScope (
|
LibOpt_Scope scope,
|
RunContextForCapacityPlanning runcontext
|
)
|
{
|
TextBody:
|
[*
|
asdips := construct( AggregatedSalesDemandInPeriods );
|
if ( runcontext.IsMetaIteration() )
|
{
|
SelectorMeta::ComputeFirstLastPISPIPInScope( scope ); // make sure to set these relations - we can limit to nonlead because leaf has already been done in smartplan gap fill
|
}
|
|
traverse( scope.GetProductInStockingPointInOptimizerRun(), Elements, pisp )
|
{
|
maxpostponementperiod := pisp.OptimizerMaxPostponementPeriod();
|
|
pispipstart := null( ProductInStockingPointInPeriodPlanning );
|
|
if( runcontext.IsMetaIteration() )
|
{
|
pispipstart := pisp.EarliestPISPIPInScope();
|
}
|
else
|
{
|
pispipstart := minselect( pisp, ProductInStockingPointInPeriodPlanning, pispip, scope.Contains( pispip.PISPIPInOptimizerRun() ), pispip.Start() );
|
}
|
|
periodstart := pispipstart.Period_MP();
|
|
previouspispip := pispipstart.PreviousPlanningPISPIP();
|
|
for( i := 1;
|
i <= maxpostponementperiod // within the maximum number of postponement periods
|
and not isnull( previouspispip ); // the previous pispip exists
|
i++
|
)
|
{
|
// For non-aggregated demand, we can select directly
|
traverse( previouspispip, SalesDemandInPeriodBase.astype( LeafSalesDemandInPeriod ), lsdip,
|
guard( lsdip.PostponementSpecification().IsValidData(), false )
|
and not lsdip.IsPostponed()
|
and lsdip.CanOptimizeWhenPostponed( periodstart )
|
and lsdip.NeedsToBePlanned()
|
and lsdip.IsWithinThresholdQuantity()
|
and lsdip.GetIsPISPAndProductInOptimizerRun( scope, runcontext.IsPostProcessing() ) )
|
{
|
scope.AddSDIPBeforeScope( lsdip );
|
lsdip.SDIPBeforeScopeInRun().OptMinPostponementPeriod( periodstart.SequenceNrInPeriodSpecification()
|
- lsdip.AsSalesDemandInPeriodBase().Period_MP().SequenceNrInPeriodSpecification()
|
);
|
}
|
|
// For aggregated demand, we need to select from the disaggregated demands, since the aggregated demand might have a different horizon
|
traverse( previouspispip, SalesDemandInPeriodBase.astype( DisaggregatedSalesDemandInPeriod ).AggregatedSalesDemandInPeriod, asdip,
|
guard( asdip.PostponementSpecification().IsValidData(), false )
|
and not asdip.IsPostponed()
|
and asdip.CanOptimizeWhenPostponed( periodstart )
|
and asdip.NeedsToBePlanned()
|
and asdip.IsWithinThresholdQuantity() )
|
{
|
asdips.Add( asdip );
|
}
|
|
previouspispip := previouspispip.PreviousPlanningPISPIP();
|
}
|
}
|
|
// The same aggregated SDIP may be selected multiple times from different disaggregated SDIPs, so get the unique ones.
|
uniqueasdips := asdips.Unique();
|
|
traverse( uniqueasdips, Elements, asdip )
|
{
|
scope.AddSDIPBeforeScope( asdip );
|
|
// Since the horizons of the disaggregated sales demand PISPs may differ, we set the minimum value
|
asdip.SDIPBeforeScopeInRun().OptMinPostponementPeriod( 1 );
|
}
|
*]
|
InterfaceProperties { Accessibility: 'Module' }
|
}
|