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