admin
2025-01-22 7e31442f0e9b07764e9c6a9680d3d4aeba5fe1de
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
Quintiq file version 2.0
#parent: #root
Method GetPISPIPsForInventorySpecifications (
  const LibOpt_Scope scope,
  Boolean leafpispipsonly,
  constcontent output owning ProductInStockingPointInPeriodPlannings leafpispips
) const as constcontent owning ProductInStockingPointInPeriodPlannings
{
  Description: 'Get all pispips for which an inventory specification should be considered'
  TextBody:
  [*
    // Select all leaf pispips that are in the optimizer run and have an inventory specification
    
    leafpisps := selectset(  scope.GetProductInStockingPointInOptimizerRunConst(), Elements, pisp, true, pisp.IsLeaf() ); 
    leafpispips := construct( ProductInStockingPointInPeriodPlannings, constcontent ); 
    traverse( leafpisps, Elements, pisp, pisp.HasInventorySpecification() ) 
    {
      current := pisp.EarliestPISPIPInScope(); 
      laststart := guard( pisp.LatestPISPIPInScope().Start(), DateTime::MinDateTime() ); 
      while ( not isnull( current ) and current.Start() <= laststart ) 
      {
        leafpispips.Add( current ); 
        current := current.NextPlanningPISPIP(); 
      }
    }
    
    
    // Select all non leaf pispips that have an inventory specification and that should be part of this optimizer run
    // Select them by looking at all the parents of all the leaf pispips that are in the optimizer run
    nonleafpispips := construct( ProductInStockingPointInPeriodPlannings, constcontent );
    
    if ( not leafpispipsonly ) 
    {
      nrofproductlevels := this.MacroPlan().ProductLevel_MP( relsize );
      
      traverse( leafpisps, Elements, pisp, pisp.HasAncestorWithInventorySpecification() ) 
      {
        firstpispip := pisp.EarliestPISPIPInScope();
        lastpispip := pisp.LatestPISPIPInScope(); 
        currentpisp := pisp; 
        // In principle the for loop should terminate because at some point we reach a pispip that does not have a parent anymore
        // As a safety check we make sure that the for loop also terminates once i has reached the number of product levels
        for( i := 1;
             not isnull( currentpisp.ParentOfProductDimension() )
             and i <= nrofproductlevels;
             i++ )
        {
          currentpisp := currentpisp.ParentOfProductDimension(); 
          firstpispip := firstpispip.ParentOfProductDimension().astype( ProductInStockingPointInPeriodPlanning )
          lastpispip := lastpispip.ParentOfProductDimension().astype( ProductInStockingPointInPeriodPlanning )
          if( currentpisp.HasInventorySpecification() )
          {
            // add from first to last to nonleafpispips
            current := firstpispip; 
            laststart := lastpispip.Start(); 
            while ( not isnull( current ) and current.Start() <= laststart ) 
            {
              nonleafpispips.Add( current ); 
              current := current.NextPlanningPISPIP(); 
            }
          }
        }
      }
    }
    
    pispips := leafpispips.Union( nonleafpispips );
    additionalpispips := construct( ProductInStockingPointInPeriodPlannings, constcontent ); 
    
    additionalpispips := this.GetAdditionalPISPIPSInventorySpecification( scope, pispips ); // for meta optimizer we add pispips prior to scope to deal with specifications in days
    
    allpispips := pispips.Union( additionalpispips ); 
    return &allpispips;
  *]
  InterfaceProperties { Accessibility: 'Module' }
}