Quintiq file version 2.0
|
#parent: #root
|
Method HandlePostPeriodRollPeriodTaskOperations
|
{
|
Description: 'Finalize the period roll, sychronize periods, aggregate/disaggregate the period task operations.'
|
TextBody:
|
[*
|
// ODE2 May-29-2017 (updated)
|
/* IMPORTANT NOTE
|
This aggregation/disaggregation is performed with the following assumptions:
|
1) Only Planning periods have PeriodTaskOperation
|
2) PeriodTaskOperation AsPeriodTaskOperation relation is procedural
|
Any of the above item changed, this is expected to be broken.
|
*/
|
|
deadperiods := selectset( this, Period_MP, period, period.IsDeleted() or not period.IsPlanning() );
|
affectedoperations := selectset( deadperiods, Elements.UnitPeriod.PeriodTaskOperation.Operation, operation, true );
|
|
// PeriodTaskOperation
|
traverse( affectedoperations, Elements, operation )
|
{
|
// Get all the dead period task operation
|
deadptos := selectset( operation, PeriodTaskOperation, pto,
|
pto.AsPeriodTaskOperationOfUnitPeriod().Period_MP().IsDeleted()
|
or not pto.AsPeriodTaskOperationOfUnitPeriod().Period_MP().IsPlanning() );
|
|
traverse( deadptos, Elements, deadpto )
|
{
|
// Use the procedural relation
|
period := deadpto.AsPeriodTaskOperationOfUnitPeriod().Period_MP();
|
// Get all planning up that is within the range
|
planningups := selectsortedset( operation, Unit.PlanningUnitPeriod, pup,
|
not pup.Period_MP().IsDeleted()
|
and pup.Period_MP().IsInPeriod( deadpto.AsPeriodTaskOperationOfUnitPeriod().Start(),
|
deadpto.AsPeriodTaskOperationOfUnitPeriod().End() ),
|
pup.Start() );
|
|
// Aggregate to planning period
|
// If there is no planning unit period, no aggregation needs to be done (means out of planning & historical scope)
|
if( planningups.Size() = 1 )
|
{
|
planningup := planningups.Element( 0 );
|
oldpto := PeriodTaskOperation::FindPeriodTaskOperationTypeIndex( planningup.Start(), operation.ID() );
|
// There is a chance that aggregation already performed on this pto. Propagation is required as quantity is not calculated yet.
|
Transaction::Transaction().Propagate( attribute( PeriodTaskOperation, Quantity ) );
|
|
newqty := ifexpr( not isnull( oldpto ) and oldpto <> deadpto,
|
oldpto.Quantity() + deadpto.Quantity(),
|
deadpto.Quantity() );
|
|
pto := PeriodTaskOperation::CreateOrUpdate( operation, planningup, newqty, deadpto.HasUserQuantity() );
|
|
traverse( deadpto, PeriodTaskInCampaign, ptc )
|
{
|
pto.PeriodTaskInCampaign( relmove, ptc )
|
}
|
traverse( deadpto, PeriodTaskInTransition, ptt )
|
{
|
pto.PeriodTaskInTransition( relmove, ptt )
|
}
|
|
deadptos.Remove( pto ); // Remove from the objects after having updated the period task.
|
}
|
// Disaggregate to base period
|
else if( planningups.Size() > 1 )
|
{
|
// The dead pto might get updated in the loop, so keep the old value out side the loop.
|
quantity := deadpto.Quantity()
|
duration := period.Duration();
|
|
traverse( planningups, Elements, planningup )
|
{
|
// Disaggregate by factor
|
factor := minvalue( planningup.Period_MP().Duration() / duration, 1.0 );
|
newqty := quantity * factor;
|
pto := PeriodTaskOperation::CreateOrUpdate( operation, planningup, newqty, deadpto.HasUserQuantity() );
|
deadptos.Remove( pto ); // Remove from the objects after updated the period task.
|
}
|
}
|
}
|
// Delete all dead period task
|
PeriodTaskOperation::Delete( deadptos );
|
}
|
*]
|
}
|