Quintiq file version 2.0 
 | 
#parent: #root 
 | 
MethodOverride Update ( 
 | 
  Real quantity 
 | 
) 
 | 
{ 
 | 
  TextBody: 
 | 
  [* 
 | 
    // soh yee Sep-25-2015 (created) 
 | 
    nonlockingsupplies := selectset( this.GetNewSupplies(), Elements, ns, 
 | 
                                     not ns.GetHasUserQuantity() ); 
 | 
     
 | 
     
 | 
    // ************ Locking with current quantity ratio  ************ 
 | 
    // For those with user quantity, the quantity will be adjusted accordingly based on its previous ratio 
 | 
    // Porportional disaggregation 
 | 
    lockingsupplies := this.GetNewSupplies().Difference( nonlockingsupplies ); 
 | 
    totallockingquantity := 0.0; 
 | 
    thisquantity := this.Quantity(); 
 | 
     
 | 
     
 | 
    if( thisquantity > 0 ) 
 | 
    { 
 | 
      traverse( lockingsupplies, Elements, ns ) 
 | 
      { 
 | 
        newquantity := quantity * ns.Quantity() / thisquantity; 
 | 
        ns.Update( newquantity ); 
 | 
     
 | 
        totallockingquantity := totallockingquantity + newquantity; 
 | 
      } 
 | 
    } 
 | 
    else 
 | 
    { 
 | 
      // In case of aggregated supply quantity is 0, we will treat the locked supply as nonlock to disaggregate using default factor 
 | 
      nonlockingsupplies := lockingsupplies.Union( nonlockingsupplies ); 
 | 
    } 
 | 
     
 | 
    // ************ Locking using default factor ************ 
 | 
    // The remaining quantity will be disaggregated to the new supplies not set by the user, using the default factor specified by user 
 | 
    // Manual disaggregation 
 | 
    remainingquantity := quantity - totallockingquantity; 
 | 
     
 | 
    // Disaggregation based on pisp 
 | 
    // To keep it simply, take the effective accumulated disggregation factor that belongs to the supply period. 
 | 
    period := this.ProductInStockingPointInPeriod().Period_MP(); 
 | 
    totalpispfactor := sum( nonlockingsupplies, 
 | 
                            Elements.ProcessOutput.ProductInStockingPoint_MP, 
 | 
                            pisp, 
 | 
                            pisp.GetAccumulateDisaggregationFactor( period ) ); 
 | 
     
 | 
    traverse( nonlockingsupplies, Elements, ns ) 
 | 
    { 
 | 
      pisp := ns.ProcessOutput().ProductInStockingPoint_MP(); 
 | 
     
 | 
      // Disaggregation on period dimension 
 | 
      // If there is at least a unit period planned infinite, we will distribute the quantity based on the duration of the period to planned infinite periods. 
 | 
      totalavailability := sum( nonlockingsupplies, Elements, nns, 
 | 
                                nns.ProcessOutput().ProductInStockingPoint_MP() = pisp 
 | 
                                and nns.PeriodTask_MP().UnitPeriod().IsPlannedInfinite(), 
 | 
                                nns.PeriodTask_MP().UnitPeriod().Duration().DaysAsReal() ); 
 | 
     
 | 
      hasinfiniteperiod := totalavailability > 0; 
 | 
     
 | 
      if( totalavailability = 0 ) 
 | 
      { 
 | 
        // The disaggregated quantity on pisp will be disaggregated to each period based on unit period availability of the period 
 | 
        totalavailability := sum( nonlockingsupplies, Elements, nns, nns.ProcessOutput().ProductInStockingPoint_MP() = pisp, 
 | 
                                  nns.GetUnitPeriodAvailableCapacity() ); 
 | 
      } 
 | 
      disaggqty := 0.0; 
 | 
     
 | 
      if( totalpispfactor > 0 and totalavailability > 0 ) 
 | 
      { 
 | 
        availability := 0.0; 
 | 
        unitperiod := ns.PeriodTask_MP().UnitPeriod(); 
 | 
     
 | 
        if( hasinfiniteperiod ) 
 | 
        { 
 | 
          if( unitperiod.IsPlannedInfinite() ) 
 | 
          { 
 | 
            availability := unitperiod.Duration().DaysAsReal(); 
 | 
          } 
 | 
        } 
 | 
        else 
 | 
        { 
 | 
          availability := ns.GetUnitPeriodAvailableCapacity(); 
 | 
        } 
 | 
        disaggqty := remainingquantity 
 | 
                      * ns.GetProductAccumulateDisaggregationFactor() / totalpispfactor 
 | 
                      * availability / totalavailability; 
 | 
     
 | 
        /* 
 | 
        debuginfo('disaggr qty:', disaggqty , '=', 
 | 
                  '*', ns.GetProductAccumulateDisaggregationFactor(), 'adf', 
 | 
                  '/', totalpispfactor, 'ttlpispf', 
 | 
                  '*', availability, 'av', 
 | 
                  '/', totalavailability, 'ttlav' 
 | 
                 ); 
 | 
        */ 
 | 
      } 
 | 
      ns.Update( disaggqty ); 
 | 
    } 
 | 
     
 | 
    // ********** Create new supplies that belongs to this aggregated supplies but do not exist yet *********** 
 | 
    // The quantity on the leaf level will be locked whenever its aggregated supply is manually edited. 
 | 
    // Thus, the new supplies will be created and will be locked (set to 0 with hasuser flag) to prevent the optimizer overrides it 
 | 
    operation := guard( this.Process_MP().astype( Operation ), null( Operation ) ); 
 | 
     
 | 
    if( not isnull( operation ) ) 
 | 
    { 
 | 
      this.ProductInStockingPointInPeriod().CreateOperationNewSupplies( operation, 0.0, true ); 
 | 
    } 
 | 
  *] 
 | 
} 
 |