| 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 ); | 
|     } | 
|   *] | 
| } |