| Quintiq file version 2.0 | 
| #parent: #root | 
| Method ChangeDatasetAndExportData ( | 
|   LibSCIIntegrationInterface libsci, | 
|   LibSCIScenario libsciscenario | 
| ) #extension | 
| { | 
|   TextBody: | 
|   [* | 
|     // LibSCIScenario | 
|     libsci.AddScenarioForExport( libsciscenario.Uri(), libsciscenario.Name(), libsciscenario.Assumptions() ,libsciscenario.IsCurrent(), libsciscenario.IsBase() ); | 
|     m := stream[Void]::Success(); | 
|      | 
|     options := DatasetFindOptions::Construct( libsciscenario.Uri() ); | 
|     key := DatasetController::FindUnique( options ); | 
|     // Prevent Empty Key and error in UTF | 
|     if( key <> Key::ZeroKey() ) | 
|     { | 
|       MDSMacroPlan::Root( key ) | 
|       ->( macroplan ) | 
|       { | 
|         startofplanning := macroplan.StartOfPlanning(); | 
|         firstplanningstart := macroplan.FirstPlanningPeriod().Start(); | 
|         endofplanning:= macroplan.LastPlanningPeriod().End(); | 
|         bottleneckthreshold := macroplan.GlobalParameters_MP().UnitLowerBottleneckThreshold();  | 
|         resources:= selectset( macroplan, Unit, resource, resource.HasCapacityTypeTime() and resource.Child( relsize ) = 0 ); | 
|         safetystocks := selectsortedset( macroplan, Product_MP.SafetyStock, ss, ss.Start(), ss.ProductID(), ss.StockingPointID() ); | 
|         pisphasiventorylevelend := selectset(  macroplan, Product_MP.ProductInStockingPoint_MP, pisp, pisp.HasInventoryLevelEndInPlanningPeriod() ); | 
|          | 
|        // Product_MP -> Item | 
|         traverse( macroplan, Product_MP, p, not p.IsSystem() ) | 
|         { | 
|           libsci.AddItemForExport( p.ID(), p.Name(), p.ParentID() ) | 
|         } | 
|          | 
|         // Resource | 
|         traverse( macroplan, Unit, u ) | 
|         { | 
|           libsci.AddResourceForExport( u.ID(), u.Name(), u.ParentUnitID() ) | 
|           libsci.AddMaximumProjectedResourceUtilizationExport( u.Name(), libsciscenario.Name(), startofplanning, endofplanning, bottleneckthreshold ); | 
|            | 
|           if ( libsciscenario.IsCurrent() and firstplanningstart < startofplanning ) | 
|           { | 
|             libsci.AddMaximumResourceUtilizationExport( u.Name(), firstplanningstart, startofplanning, bottleneckthreshold ); | 
|           } | 
|         } | 
|          | 
|         // Period_MP -> PeriodOfTime | 
|         periods := selectset( macroplan, PeriodSpecification_MP, ps, not ps.IsDummyPlanningPeriod() ); | 
|         traverse( periods, Elements.Period_MP, p ) | 
|         { | 
|           libsci.AddPeriodOfTimeForExport( p.StartDate(), p.EndDate(), p.PeriodSpecificationID(), p.TimeUnit() ) | 
|         } | 
|          | 
|         // PeriodSpecifications_MP -> PeriodOfTimeDefinition | 
|         traverse( macroplan, PeriodSpecification_MP, ps, not ps.IsDummyPlanningPeriod() ) | 
|         { | 
|           libsci.AddPeriodOfTimeDefinitionForExport( ps.ID(), ps.TimeUnit() ) | 
|         } | 
|          | 
|         // SalesSegments_MP -> SalesSegment | 
|         traverse( macroplan, SalesSegment_MP, ss ) | 
|         { | 
|           libsci.AddSaleSegmentForExport( ss.Name(), ss.ParentName() ) | 
|         } | 
|          | 
|         // StockingPoint_MP -> StockLocation | 
|         traverse( macroplan, StockingPoint_MP, sp, not sp.IsSystem() ) | 
|         { | 
|           libsci.AddStockLocationForExport( sp.ID(), sp.Name() ) | 
|         } | 
|          | 
|         traverse( resources, Elements.PlanningUnitPeriod.astype( UnitPeriodTime ), unitperiodtime , not unitperiodtime.Period_MP().IsHistorical() ) | 
|         { | 
|           libsci.AddPlannedResourceUtilizationForExport( libsciscenario.Uri(), unitperiodtime.Unit().ID(), unitperiodtime.StartDate(),  | 
|                                                          unitperiodtime.End().Date(), unitperiodtime.TotalAvailableCapacity().HoursAsReal(),  | 
|                                                          unitperiodtime.GetDisplayUsedCapacity().HoursAsReal() );   | 
|         } | 
|         | 
|         // Only export TargetFillRate / Actuals for IsCurrent LibScenario | 
|         if( libsciscenario.IsCurrent() ) | 
|         { | 
|           libsci.AddCompanyForExport( startofplanning, macroplan.BaseCurrency().Symbol() ); | 
|            | 
|           traverse( macroplan, FulfillmentTarget,ft ) | 
|           { | 
|             // FulfillmentTarget -> TargetFillRateQuantity | 
|             libsci.AddTargetFillRateQuantityForExport( ft.ProductID(), ft.StockingPointID(), ft.SalesSegmentName(), ft.Start(), ft.End(), ft.TargetPercentage(), ft.TargetPercentage() ); | 
|             // FulfillmentTarget -> TargetFillRateRevenue | 
|             libsci.AddTargetFillRateRevenueForExport( ft.ProductID(), ft.StockingPointID(), ft.SalesSegmentName(), ft.Start(), ft.End(), ft.TargetPercentage(), ft.TargetPercentage() ); | 
|           } | 
|            | 
|           traverse( macroplan, Period_MP, p, p.IsHistorical() ) | 
|           { | 
|             sdips := selectset( p, ProductInStockingPointInPeriod.SalesDemandInPeriodBase, sdip, not sdip.istype( DisaggregatedSalesDemandInPeriod ) ); | 
|             salessegments := selectset( sdips, Elements.AsPlanningSalesDemandInPeriod.SalesSegment_MP, ss, true ); | 
|              | 
|             traverse( sdips, Elements.AsSalesDemandInPeriodBase, pispip ) | 
|             { | 
|               traverse( salessegments, Elements, ss ) | 
|               { | 
|                 quantity := 0.0; | 
|                 fulfilledQuantity := 0.0; | 
|                 revenueQuantity := 0.0; | 
|                 revenueFulfilled := 0.0; | 
|                 hasdata := false; | 
|              | 
|                 traverse( pispip, SalesDemandInPeriodBase, sdipb, sdipb.SalesSegmentName() = ss.Name() and not sdipb.istype( DisaggregatedSalesDemandInPeriod ) ) | 
|                 { | 
|                   quantity := quantity + sdipb.Quantity(); | 
|                   fulfilledQuantity :=  fulfilledQuantity + sdipb.FulfilledQuantity(); | 
|                   revenueQuantity := revenueQuantity + sdipb.Quantity() * sdipb.BasePricePerQuantity(); | 
|                   revenueFulfilled := revenueFulfilled + sdipb.FulfilledQuantity() * sdipb.BasePricePerQuantity(); | 
|                   hasdata := true; | 
|                 } | 
|                  | 
|                 if( hasdata ) | 
|                 { | 
|                   // SalesDemandInPeriod -> ActualSales | 
|                   libsci.AddActualSalesForExport( pispip.ProductInStockingPoint_MP().ProductID(), pispip.ProductInStockingPoint_MP().StockingPointID(), ss.Name(), p.StartDate(), p.EndDate(), fulfilledQuantity, revenueFulfilled ); | 
|                   // SalesDemandInPeriod -> TotalOrders | 
|                   libsci.AddTotalOrdersForExport( pispip.ProductInStockingPoint_MP().ProductID(), pispip.ProductInStockingPoint_MP().StockingPointID(), ss.Name(), p.StartDate(), p.EndDate(), quantity, revenueQuantity ); | 
|                 } | 
|               } | 
|             } | 
|              | 
|             // Export inventory level from historical period | 
|             traverse( p, ProductInStockingPointInPeriod.astype( ProductInStockingPointInPeriodPlanningLeaf ), pispip, pispip.ProductInStockingPoint_MP().HasInventoryLevelEndInHistoricalPeriod() ) | 
|             { | 
|               pisp := pispip.ProductInStockingPoint_MP(); | 
|               item := pisp.Product_MP().Name(); | 
|               stocklocation := pisp.StockingPoint_MP().Name(); | 
|               libsci.AddActualInventoryLevelForExport( item, stocklocation, p.Start(), p.End(), pispip.InventoryLevelEnd() );   | 
|             } | 
|              | 
|           }//IsHistorical Period | 
|                      | 
|           traverse( resources, Elements.PlanningUnitPeriod.astype( UnitPeriodTime ), unitperiodtime, unitperiodtime.Period_MP().IsHistorical() ) | 
|           { | 
|             actual := ifexpr( unitperiodtime.HasActual(), unitperiodtime.ActualTotalAvailableCapacity(), unitperiodtime.TotalAvailableCapacity().HoursAsReal() ); | 
|             used := ifexpr( unitperiodtime.HasActual(), unitperiodtime.ActualUtilizationPercentage()/100.0 * unitperiodtime.ActualTotalAvailableCapacity(), unitperiodtime.GetDisplayUsedCapacity().HoursAsReal() ); | 
|             libsci.AddActualResourceUtilizationForExport( unitperiodtime.Unit().ID(), unitperiodtime.StartDate(),  | 
|                                                           unitperiodtime.End().Date(), actual,  | 
|                                                           used );   | 
|           } | 
|           // MinimumResourceUtilization | 
|           traverse( resources, Elements, resource ) | 
|           {   | 
|             unitavailabilities := selectsortedset( resource, UnitAvailability, ua, ua.Start() < startofplanning, ua.Start() );  | 
|             for( i:=0; i<unitavailabilities.Size(); i++ ) | 
|             { | 
|               endtime := minvalue( guard( unitavailabilities.Element( i + 1 ).Start(), startofplanning ), startofplanning ); | 
|               this.AddMinimumResourceUtilizationExport( resource.Name(), unitavailabilities.Element( i ).Start(), endtime, unitavailabilities.Element( i ).MinimumLoadThreshold() );  | 
|              | 
|             }   | 
|            | 
|           }  | 
|           // Export of Historical InventoryValue | 
|           inventoryvalues := selectsortedset( macroplan, Product_MP.InventoryValueAndCost, inv,  | 
|                                               inv.Start().DateTime() < macroplan.StartOfPlanning(),  | 
|                                               inv.ProductID(), inv.StockingPointID(), inv.Start() )  | 
|                                               | 
|           this.AddInventoryValue( libsciscenario.Name(), macroplan, inventoryvalues, true );   | 
|            | 
|           inventorytargets := selectsortedset( macroplan, Product_MP.InventorySpecification, it,  | 
|                                               it.HasMaxLevel() and not it.HasMaxLevelInDays() and it.Start().DateTime() < startofplanning ,  | 
|                                               it.Start(), it.ProductID(), it.StockingPointID() ); | 
|           this.AddMaximumInventoryValue( libsciscenario, macroplan, inventorytargets, true );                                     | 
|       | 
|         }// End of only for IsCurrent scenario | 
|         // MinimumProjectedResourceUtilization     | 
|         traverse( resources, Elements, resource ) | 
|         {   | 
|           unitavailabilities := selectsortedset( resource, UnitAvailability, ua, ua.Start() );  | 
|         | 
|           start := startofplanning; | 
|           end := endofplanning;  | 
|           i := 0; | 
|           skip := false; | 
|           while ( i < unitavailabilities.Size() )  | 
|           { | 
|              current := unitavailabilities.Element( i ); | 
|              next:= guard( unitavailabilities.Element( i + 1 ), null( UnitAvailability ) ); | 
|              // if there are more than 1 unitavailability that < start of planning take the last one | 
|              skip := current.Start() < startofplanning and not isnull( next ) and next.Start() <= startofplanning;  | 
|              if ( not skip )  | 
|              { | 
|                 start := maxvalue( startofplanning, current.Start() ); | 
|                 end := minvalue( endofplanning, guard( next.Start(), endofplanning ) );  | 
|                 this.AddMinimumProjectedResourceUtilizationExport( resource.Name(), libsciscenario.Name(), start, end, current.MinimumLoadThreshold() );  | 
|              }  | 
|              i := i+1; | 
|           } | 
|         }  | 
|         traverse( macroplan, Period_MP, p, not p.IsHistorical() ) | 
|         { | 
|           sdips := selectset( p, ProductInStockingPointInPeriod.SalesDemandInPeriodBase, sdip, not sdip.istype( DisaggregatedSalesDemandInPeriod ) ); | 
|           salessegments := selectset( sdips, Elements.AsPlanningSalesDemandInPeriod.SalesSegment_MP, ss, true ); | 
|            | 
|           traverse( sdips, Elements.AsSalesDemandInPeriodBase, pispip ) | 
|           { | 
|             traverse( salessegments, Elements, ss ) | 
|             { | 
|               quantity := 0.0; | 
|               fulfilledQuantity := 0.0; | 
|               revenueQuantity := 0.0; | 
|               revenueFulfilled := 0.0; | 
|               hasdata := false; | 
|            | 
|               traverse( pispip, SalesDemandInPeriodBase, sdipb, sdipb.SalesSegmentName() = ss.Name() and not sdipb.istype( DisaggregatedSalesDemandInPeriod ) ) | 
|               { | 
|                 quantity := quantity + sdipb.Quantity(); | 
|                 fulfilledQuantity :=  fulfilledQuantity + sdipb.FulfilledQuantity(); | 
|                 revenueQuantity := revenueQuantity + sdipb.Quantity() * sdipb.BasePricePerQuantity(); | 
|                 revenueFulfilled := revenueFulfilled + sdipb.FulfilledQuantity() * sdipb.BasePricePerQuantity(); | 
|                 hasdata := true; | 
|               } | 
|                | 
|               if( hasdata ) | 
|               { | 
|                 // SalesDemandInPeriod -> ConstrainedDemand | 
|                 libsci.AddConstrainedDemandForExport( libsciscenario.Uri(), pispip.ProductInStockingPoint_MP().ProductID(), pispip.ProductInStockingPoint_MP().StockingPointID(), ss.Name(), p.StartDate(), p.EndDate(), fulfilledQuantity, revenueFulfilled ); | 
|                 // SalesDemandInPeriod -> UnconstrainedDemand | 
|                 libsci.AddUnconstrainedDemandForExport( libsciscenario.Uri(), pispip.ProductInStockingPoint_MP().ProductID(), pispip.ProductInStockingPoint_MP().StockingPointID(), ss.Name(), p.StartDate(), p.EndDate(), quantity, revenueQuantity ); | 
|               } | 
|             } | 
|           } | 
|         }// end of not period IsHistorical | 
|       | 
|         // PlannedInventoryLevel | 
|         traverse( pisphasiventorylevelend, Elements.ProductInStockingPointInPeriod.astype( ProductInStockingPointInPeriodPlanningLeaf ), pispip, not pispip.Period_MP().IsHistorical() ) | 
|         { | 
|            pisp := pispip.ProductInStockingPoint_MP(); | 
|            item := pisp.Product_MP().Name(); | 
|            stocklocation := pisp.StockingPoint_MP().Name(); | 
|            libsci.AddPlannedInventoryLevelForExport( libsciscenario.Name(), item, stocklocation, pispip.Period_MP().Start(), pispip.Period_MP().End(), pispip.InventoryLevelEnd() ); | 
|         } | 
|         // SafetyStocks for both historical and future | 
|         pispips := selectsortedset( safetystocks, Elements.ProductInStockingPoint_MP.ProductInStockingPointInPeriod.astype( ProductInStockingPointInPeriodPlanningLeaf ),  | 
|                                     pispip, pispip.ProductInStockingPoint_MP().ProductID(), pispip.ProductInStockingPoint_MP().StockingPointID(), pispip.Start() ); | 
|         traverse( pispips, Elements, pispip ) | 
|         { | 
|           pisp := pispip.ProductInStockingPoint_MP(); | 
|           item := pisp.Product_MP().Name(); | 
|           stocklocation := pisp.StockingPoint_MP().Name(); | 
|           period := pispip.Period_MP(); | 
|           scenario := ifexpr( period.IsHistorical(), LibSCIIntegration_Utility::SCI_CurrentSOPPlan(), libsciscenario.Name() ); | 
|           appliedmetric := ifexpr( period.IsHistorical(), LibSCIIntegration_Utility::SCI_Metric_ActualInventoryLevel(), LibSCIIntegration_Utility::SCI_Metric_PlannedInventoryLevel() ); | 
|           addtoreport := period.IsHistorical() and libsciscenario.IsCurrent() or not period.IsHistorical();  | 
|           | 
|           if ( addtoreport ) | 
|           { | 
|             this.AddSafetyStockLevelForExport( scenario, appliedmetric, item, stocklocation, pispip.Period_MP().Start(), pispip.Period_MP().End(), pispip.TargetInventoryLevel() ); | 
|           }   | 
|         }// SafetyStocks Level | 
|          | 
|          // Export of future InventoryValue | 
|          inventoryvalues := selectsortedset( macroplan, Product_MP.InventoryValueAndCost, inv,  | 
|                                              inv.End().DateTime() > startofplanning, | 
|                                              inv.ProductID(), inv.StockingPointID(), inv.Start() )  | 
|          this.AddInventoryValue( libsciscenario.Name(), macroplan, inventoryvalues, false );                                    | 
|                                               | 
|          inventorytargets := selectsortedset( macroplan, Product_MP.InventorySpecification, it,  | 
|                                               it.HasMaxLevel() and not it.HasMaxLevelInDays()  | 
|                                                 and ( it.Start().DateTime() >= startofplanning  | 
|                                                        or ( it.Start().DateTime() < startofplanning  | 
|                                                             and guard( it.NextInventorySpecification().Start().DateTime(), macroplan.End() ) > startofplanning ) ),  | 
|                                               it.Start(), it.ProductID(), it.StockingPointID() ); | 
|          this.AddMaximumInventoryValue( libsciscenario, macroplan, inventorytargets, false ); | 
|              | 
|          | 
|       } | 
|     } | 
|      | 
|      | 
|     return m; | 
|   *] | 
| } |