| Quintiq file version 2.0 | 
| #parent: #root | 
| Method CalculateSalesDemandFulfillmentOnHigherLevel | 
| { | 
|   TextBody: | 
|   [* | 
|     // Only "Propagate" the updated scope: The Product family | 
|     updateScope := selectsortedset( this.ProductInStockingPoint_MP().GetAllParent(), Elements, e,  | 
|                                     not e.IsLeaf() and e.SalesDemand( relsize ) > 0, | 
|                                     -e.Product_MP().Level() ); | 
|      | 
|     if( updateScope.Size() > 0 )  | 
|     { | 
|       traverse( updateScope, Elements, e ) | 
|       { | 
|         e.ResetSalesDemandFulfilledQuantity( this.Period_MP() ); | 
|       } | 
|        | 
|       // Propagate all PISPIP quantities before calculate for fulfillment on demand on higher level | 
|       Transaction::Transaction().Propagate(); | 
|        | 
|       // Initialize SystemRemainingQuantity | 
|       traverse( updateScope, Elements.SalesDemand.SalesDemandInPeriod.astype( AggregatedSalesDemandInPeriod ), sdip ) | 
|       {  | 
|         sdip.SystemRemainingQuantity( sdip.Quantity() - sdip.FulfilledQuantity() ); | 
|       } | 
|        | 
|       // Go through the PISPIP and onwards | 
|       traverse( updateScope, Elements.ProductInStockingPointInPeriodPlanning, parentPispip,  | 
|                 parentPispip.Period_MP().SequenceNr() >= this.Period_MP().SequenceNr() ) | 
|       { | 
|      | 
|         traverse( parentPispip.GetLeavesOfProductDimension(), Elements.astype( ProductInStockingPointInPeriodPlanningLeaf ), pispip ) | 
|         { | 
|           // The supply quantity will be updated when the algorithm used the supply to fulfill the demand in previous period. | 
|           Transaction::Transaction().Propagate( attribute( ProductInStockingPointInPeriod, SupplyQuantity) ); | 
|           remainingQuantity := pispip.SupplyQuantity()  | 
|                                /* We dont care about optimizer in this scope, manual planning will reset all optimizer fulfillments  | 
|                                - pispip.OptimizerFulfilledDemandQuantity()   | 
|                                - pispip.OptimizerReservedQuantity() */ | 
|                                 | 
|           // We don't allow total remaining qty to go below -ve | 
|           // Although totalremaining = 0, still need to proceed with the greedy to reset the demands systemfulfilledquantity to 0 | 
|           remainingQuantity := maxvalue( remainingQuantity, 0.0 ); | 
|            | 
|           // We will consider all Greedy algorithm sorting here which includes Leaf & Disaagregated sales demand in periods | 
|           salesdemands := selectsortedset( pispip, PlanningBaseSalesDemandInPeriod, sd, | 
|                                            sd.NeedsToBePlanned() and sd.IsNotRestricted(), //Should not consider DSDIP that is restricted by FR | 
|                                            guard( -sd.Priority().Weight(), 0 ), | 
|                                            -sd.BasePricePerQuantity(), | 
|                                            ( not sd.MasterSalesDemand().IsLeaf() ).AsQUILL() /*Always fulfill leaf first*/ ); | 
|            | 
|           traverse( salesdemands, Elements, sdip ) | 
|           {  | 
|             ontype( sdip ) | 
|             { | 
|               LeafSalesDemandInPeriod as leafsalesdemandinperiod: | 
|               { | 
|                 // The fulfillment of the leaf sales demand in period will be assign by the greedy from PISPIP.CalcSystemFulfilledQuantity | 
|                 // We dont assign any fulfillment to leaf sales demand in period from here but only use it to reduce the totalremaining supply quantity | 
|                 qtyToFulfill := leafsalesdemandinperiod.Quantity(); | 
|                 qtyAbleToFulfill := minvalue( remainingQuantity, qtyToFulfill ); | 
|                  | 
|                 remainingQuantity := remainingQuantity - qtyAbleToFulfill;           | 
|               } | 
|               DisaggregatedSalesDemandInPeriod as disaggregatedsalesdemandinperiod: | 
|               { | 
|                 qtyToFulfill := disaggregatedsalesdemandinperiod.AggregatedSalesDemandInPeriod().SystemRemainingQuantity(); | 
|                 qtyAbleToFulfill := minvalue( remainingQuantity, qtyToFulfill ); | 
|      | 
|                 disaggregatedsalesdemandinperiod.SystemAssignedQuantity( qtyAbleToFulfill ); | 
|                 disaggregatedsalesdemandinperiod.AggregatedSalesDemandInPeriod().SystemRemainingQuantity( qtyToFulfill - qtyAbleToFulfill ); | 
|                  | 
|                 remainingQuantity := remainingQuantity - qtyAbleToFulfill;  | 
|               } | 
|             } | 
|           } | 
|         } | 
|       } | 
|     } | 
|   *] | 
| } |