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
Quintiq file version 2.0
#parent: #root
FunctionOverride CalcStockLevelInDays
{
  TextBody:
  [*
    totalDays := 0.0;
    if ( not this.Period_MP().MacroPlan().IsMetaOptimizerRunning() ) 
    {
      // Calculate stock level in days
      futureperiods := selectsortedset( this, ProductInStockingPoint_MP.ProductInStockingPointInPeriodPlanning.astype( ProductInStockingPointInPeriodPlanningLeaf ), p,
                                        p.Start() >= this.End(), p.Start() );
      
      balanceInv := this.InventoryLevelEnd();
      
      
      /*
        Track if consecutive future periods has 0 demand (although we have balance supply, but if remaining future periods has 0 demand not consider as coverable).
        Accumulate the coverable days and only add to total days if manage to find a subsequent period with demand.
      */
      zeroDemandMode := false;
      tempTotalDays := 0.0;
      continue := true; // Terminate calculation once remaining supply is 0
      
      traverse( futureperiods, Elements, pispip, continue )
      {
        balanceInv := balanceInv - pispip.ExpiredInPeriodShelfLifeSupplyQuantity(); // Reduce inventory as expired
        if( balanceInv > 0.0 )
        {
          demandQty := pispip.DependentDemandAndSalesDemandQuantity();
          if( balanceInv > demandQty ) // Remaining supply can cover demand in period
          {
            if( not zeroDemandMode and demandQty = 0.0 ) // Hit first period with 0 demand
            {
              zeroDemandMode := true; 
            }
            else if( zeroDemandMode and demandQty > 0.0 )
            {
              // Previous period(s) has 0 demand and finally this period has demand so add accumualted temp coverable days before we calculate this period coverable days
              zeroDemandMode := false; // Reset so we calculate coverable days as usual (as the period has demand now)
              totalDays := totalDays + tempTotalDays;
              tempTotalDays := 0.0; 
            }
            
            if( zeroDemandMode )
            {
              // Temporary days coverable if there is 0 demand
              tempTotalDays := tempTotalDays + pispip.Period_MP().DurationInDays(); 
            }
            else
            {
              totalDays := totalDays + pispip.Period_MP().DurationInDays(); 
            }
            balanceInv := balanceInv - demandQty; 
          } 
          else // Remaining supply partially cover the demand in period
          {
            // Main calc logic
            totalDays := totalDays + ( balanceInv / demandQty * pispip.Period_MP().DurationInDays() );
            balanceInv := 0.0;
          }
        }
        
        continue := balanceInv > 0.0;
      }
    }
    this.StockLevelInDays( totalDays );
  *]
}