Quintiq file version 2.0
|
#parent: #root
|
Method OTSPrepareInventoryLevelTargetsBeforeScope (
|
Date firstperioddate
|
)
|
{
|
Description: 'Inventory targets ( min, max, safety ) prior to the optimizer scope are converted from target in days into absolute targets (having value equal to the current min / max / safety level).'
|
TextBody:
|
[*
|
traverse( this, MacroPlan.Product_MP.ProductInStockingPoint_MP.ProductInStockingPointInPeriodPlanning, pispip )
|
{
|
pispip.DebugCheckOTSPreprocessingMax( pispip.MaxInventoryLevel() );
|
pispip.DebugCheckOTSPreprocessingMin( pispip.MinInventoryLevel() );
|
pispip.DebugCheckOTSPreprocessingSafety( pispip.TargetInventoryLevel() );
|
}
|
|
traverse( this, MacroPlan.Product_MP, product )
|
{
|
traverse( product, ProductInStockingPoint_MP, pisp )
|
{
|
istoprocess := selectsortedset( pisp,
|
InventorySpecification,
|
is,
|
( is.HasMaxLevelInDays() or is.HasMinLevelInDays() ) and is.Start() < firstperioddate ,
|
firstperioddate - is.Start() ); // go from later to earlier
|
|
firstinscopeis := InventorySpecification::FindInventorySpecificationTypeIndex( product.ID(), pisp.StockingPointID(), firstperioddate );
|
if ( isnull( firstinscopeis ) and istoprocess.Size() > 0 )
|
{
|
is := istoprocess.Element( 0 ); // carry over information from last istoprocess in time
|
InventorySpecification::Create( product,
|
pisp.StockingPoint_MP(),
|
firstperioddate,
|
false, // hastargetindays
|
0.0, // target in days
|
0.0, // target in qty
|
is.HasMinLevelInDays(), // hasminindays
|
is.MinLevelInDays(), // min in days
|
is.MinLevelInQuantity(), // in in qty
|
is.HasMaxLevel(),
|
is.HasMaxLevelInDays(), // has max level in days
|
is.MaxLevelInDays(), // max level in days
|
is.MaxLevelInQuantity(), // max level in qty
|
is.IsCalculated(), // is calculated
|
is.IsManuallyConfigured() ); // is from db
|
}
|
|
lastdate := firstperioddate;
|
traverse( istoprocess, Elements, is )
|
{
|
sp := is.StockingPoint_MP();
|
isstart := is.Start();
|
hasmaxlevel := is.HasMaxLevel();
|
manualconf := is.IsManuallyConfigured();
|
|
is.Delete();
|
|
traverse( this, MacroPlan.PlanningPeriod, period, period.StartDate() < lastdate and period.StartDate() >= isstart ) // up to where previous process is starts
|
{
|
pispip := select( pisp, ProductInStockingPointInPeriodPlanning, p, true, p.Start() = period.Start() );
|
|
mininqty := pispip.MinInventoryLevel();
|
maxinqty := pispip.MaxInventoryLevel();
|
|
InventorySpecification::Create( product,
|
sp,
|
period.StartDate(),
|
false, // hastargetindays
|
0.0, // target in days
|
0.0, // target in qty
|
false, // hasminindays
|
0.0, // min in days
|
mininqty, // in in qty
|
hasmaxlevel,
|
false, // has max level in days
|
0.0, // max level in days
|
maxinqty, // max level in qty
|
false, // is calculated
|
manualconf ); // is from db
|
|
}
|
lastdate := isstart; // end point for next iteration of traverse for InventorySpecification object
|
}
|
|
safetytoprocess := selectsortedset( pisp, SafetyStock, s, s.HasTargetInDays() and s.Start() < firstperioddate, firstperioddate - s.Start() ); // go from later to earlier
|
|
firstinscopess := SafetyStock::FindTypeIndexSafetyStock( product.ID(), pisp.StockingPointID(), firstperioddate );
|
// check for safety stock starting on firsperiodate. If nothing then we should create a new one, otherwise ok
|
if ( isnull( firstinscopess ) and safetytoprocess.Size() > 0 )
|
{
|
sstock := safetytoprocess.Element( 0 ); // carry over information from last safety stock before 'firstperioddate'
|
SafetyStock::Create( product,
|
pisp.StockingPoint_MP(),
|
firstperioddate,
|
sstock.HasTargetInDays(), // has target in days
|
sstock.TargetInDays(), // target in days
|
sstock.TargetInQuantity(), // target in qty
|
sstock.IsCalculated(), // is calculated
|
sstock.HasUserTarget(), // has user target
|
sstock.IsManuallyConfigured() );
|
}
|
|
lastdate := firstperioddate;
|
traverse( safetytoprocess, Elements, sstock )
|
{
|
sp := sstock.StockingPoint_MP();
|
pisp := select( product, ProductInStockingPoint_MP, p, true, p.StockingPoint_MP() = sp );
|
ismanual := sstock.IsManuallyConfigured();
|
sstockstart := sstock.Start();
|
hasuser := sstock.HasUserTarget();
|
|
sstock.Delete();
|
|
traverse( this, MacroPlan.PlanningPeriod, period, period.StartDate() < lastdate and period.StartDate() >= sstockstart )
|
{
|
pispip := select( pisp, ProductInStockingPointInPeriodPlanning, p, true, p.Start() = period.Start() );
|
|
slevel := pispip.TargetInventoryLevel();
|
|
SafetyStock::Create( product,
|
sp,
|
period.StartDate(),
|
false, // has target in days
|
0.0, // target in days
|
slevel, // target in qty
|
false, // is calculated
|
hasuser, // has user target
|
ismanual );
|
}
|
lastdate := sstockstart; // end point for next iteration of traverse on safety stock objects
|
}
|
}
|
}
|
|
Transaction::Transaction().Propagate( attribute( ProductInStockingPointInPeriodPlanning, MinInventoryLevel ) );
|
Transaction::Transaction().Propagate( attribute( ProductInStockingPointInPeriodPlanning, MaxInventoryLevel ) );
|
Transaction::Transaction().Propagate( attribute( ProductInStockingPointInPeriodPlanning, TargetInventoryLevel ) );
|
|
unchanged := true;
|
traverse( this, MacroPlan.Product_MP.ProductInStockingPoint_MP.ProductInStockingPointInPeriodPlanning, pispip )
|
{
|
if ( pispip.DebugCheckOTSPreprocessingMax() <> pispip.MaxInventoryLevel() )
|
{
|
unchanged := false;
|
debuginfo( 'Changed max', pispip.Start(), pispip.ProductInStockingPoint_MP().Name(), 'old=', pispip.DebugCheckOTSPreprocessingMax() , 'new=', pispip.MaxInventoryLevel() );
|
}
|
if ( pispip.DebugCheckOTSPreprocessingMin() <> pispip.MinInventoryLevel() )
|
{
|
unchanged := false;
|
debuginfo( 'Changed min', pispip.Start(), pispip.ProductInStockingPoint_MP().Name(), 'old=', pispip.DebugCheckOTSPreprocessingMin() , 'new=', pispip.MinInventoryLevel() );
|
}
|
if ( pispip.DebugCheckOTSPreprocessingSafety() <> pispip.TargetInventoryLevel() )
|
{
|
unchanged := false;
|
debuginfo( 'Changed safety', pispip.Start(), pispip.ProductInStockingPoint_MP().Name(), 'old=', pispip.DebugCheckOTSPreprocessingSafety() , 'new=', pispip.TargetInventoryLevel() );
|
}
|
}
|
verify( unchanged, 'Failure to change inventory / safety stock in days' );
|
*]
|
InterfaceProperties { Accessibility: 'Module' }
|
}
|