yanweiyuan3
2023-08-09 588bc7829387dfc761cc25f06f77d4c81818bd10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
Quintiq file version 2.0
#parent: #root
MethodOverride TransformDataFromSetObject (
  const LibDEF_SetObject setObject_i
)
{
  TextBody:
  [*
    /*
    When receive Manufacturing demand data from DP, the following transformation is needed:
    - Just create Sales Demand for within planning horizon
    - Quantity wise:
      1. If Q2 > Q1, take Q2
      2. if Q1 > Q2, create 2 sales demand object, where:
         1. Forecast SD with value = Q1 - Q2
         2. Actual SD with value = Q2
    
    *  Q1 = forecast qty
       Q2 = actual sales qty
    
    Bear in mind that the time series is in <start>;<end|also start for next series>... format,
    so, if there are 13 items in the date vector, there are actually 12 time series.
    and, Dates vector has 1 element more than that in vector Quantities<1,2,3>
    
    1. Convert vector to DataTypes type accordingly, E.g: DateVector to DateTimes, QuantityVector to Reals
    2. Find PISP
    3. If PISP exists, and all vector size are same
         - create SalesDemand if it doesn't exists
         - update sales demand if it exists
    */
    
    salesDemandExternal    := setObject_i.astype( LibDEC_ManufacturingDemand );
    macroPlan              := this.GetMacroPlan();
    startOfPlanningHorizon := macroPlan.StartOfPlanningPeriod().StartDate();
    endOfPlanningHorizon   := macroPlan.End().Date();                          
    
    if( salesDemandExternal.Dates().Size() > 0 ) // DateTimeVector::Construct() will get error if there is nothing in the dates
    {
      dateTimes              := DateTimeVector::Construct( salesDemandExternal.Dates()       ).AsValues();
      forecastQuantities     := RealVector::Construct    ( salesDemandExternal.Quantities1() ).AsValues();
      actualSalesQuantities  := RealVector::Construct    ( salesDemandExternal.Quantities2() ).AsValues();
      revenues               := RealVector::Construct    ( salesDemandExternal.Quantities3() ).AsValues();
      nrOfDates              := dateTimes.Size();
      nrOfForecastQuantities := forecastQuantities.Size();
      nrOfActualQuantities   := actualSalesQuantities.Size();
      nrOfRevenues           := revenues.Size();
    
      // Find create pisp if it doesn't already exist
      pisp := ProductInStockingPoint_MP::Create( salesDemandExternal.ProductID(), salesDemandExternal.LocationID() );
    
      if( not isnull( pisp )
          and nrOfDates = nrOfForecastQuantities + 1
          and nrOfForecastQuantities = nrOfActualQuantities
          and nrOfActualQuantities   = nrOfRevenues )
      {
        for( i := 0; i < dateTimes.Size() - 1 ; i++ )
        {
          startDate := dateTimes.Element( i ).Date();
          endDate   := dateTimes.Element( i + 1 ).Date();
          revenue   := ifexpr( revenues.Element( i ).IsNaN(), 0.0, revenues.Element( i ) ); //Translate NANs to zero-s                        
          forecastQuantity := ifexpr( forecastQuantities.Element( i ).IsNaN(), 0.0, forecastQuantities.Element( i ) );   
          actualQuantity   := ifexpr( actualSalesQuantities.Element( i ).IsNaN(), 0.0, actualSalesQuantities.Element( i ) );
          demanduncertaintypercentage := [Real] salesDemandExternal.DemandUncertaintyPercentage();
    
    
          if( endDate > startOfPlanningHorizon
              and startDate < endOfPlanningHorizon )  // ONLY create sales demand within planning horizon
          {
            if( actualQuantity > 0.0 )
            {
              // create HIGH priority sales demand with quantity = actual quantity
              quantity               := actualQuantity;
              priorityName           := DataTransformationManufacturingDemand::FormatPriorityName( salesDemandExternal.PriorityID(), DataTransformationManufacturingDemand::SalesDemandPriorityName_High() );
              formattedSalesDemandID := DataTransformationManufacturingDemand::FormatSalesDemandID( salesDemandExternal.ID(), startDate, priorityName );
              this.CreateUpdateSalesDemand( pisp.Product_MP(), pisp.StockingPoint_MP(), salesDemandExternal,
                                            formattedSalesDemandID, startDate, endDate, quantity, revenue, priorityName, demanduncertaintypercentage,
                                            false );
            }
    
            if( forecastQuantity > actualQuantity
                and forecastQuantity > 0.0 ) // make sure forecast quantity > 0.0
            {
              // create NORMAL priority sales demand with quantity = forecast - actual quantity
              quantity               := forecastQuantity - actualQuantity;
              priorityName           := DataTransformationManufacturingDemand::FormatPriorityName( salesDemandExternal.PriorityID(), DataTransformationManufacturingDemand::SalesDemandPriorityName_Normal() );
              formattedSalesDemandID := DataTransformationManufacturingDemand::FormatSalesDemandID( salesDemandExternal.ID(), startDate, priorityName );
              this.CreateUpdateSalesDemand( pisp.Product_MP(), pisp.StockingPoint_MP(), salesDemandExternal,
                                            formattedSalesDemandID, startDate, endDate, quantity, revenue, priorityName, demanduncertaintypercentage,
                                            false );
            }
          }
        }
      }
    }
  *]
}