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
97
98
Quintiq file version 2.0
#parent: #root
StaticMethod SetAvailableAgeAndQuantityVectorAfterDemand (
  RealVector quantityvector,
  RealVector agevector,
  RealVector quantityconsumedvector,
  RealVector ageconsumedvector,
  Real demand,
  Boolean isignorematuration,
  Boolean isconsumeoldeststockfirst,
  ProductInStockingPointInPeriodPlanningLeaf pispippl,
  Real agetobereduced
) declarative
{
  Description: 'Set the remaining age and quantity vector after being consumed by sales demand'
  TextBody:
  [*
    product := pispippl.ProductInStockingPoint_MP().Product_MP();
    delta := demand;
    
    agevectorasvalues := agevector.AsValues();
    agevectordummyasvalues := agevector.AsValues();
    // Sort the age values as ascending
    agevectordummyasvalues := agevectordummyasvalues.Sort();
    // If the the oldest stocks are to be consumed first, sort the age values as descending
    if( isconsumeoldeststockfirst )
    {
      agevectordummyasvalues := agevectordummyasvalues.Reverse();
    }
    for( i := 0;
         i < quantityvector.Size()
         and delta > 0;
         i++ )
    {
    
      age := agevectordummyasvalues.Element( i );
      index := agevectorasvalues.Find( age );
      
      // Check if product has shelf life or maturation
      // Only sales demand or routing dependent demand requires maturation constraint
      // Laneleg dependent demand doesn't have constraint on maturation because the product can continue to mature in trip
      if( ( not product.HasShelfLife()
            or product.GetIsUsableInTargetPeriod( [Real] age, pispippl.Start(), pispippl.Period_MP() ) 
          ) 
          and ( isignorematuration
                or not product.HasMaturation()
                or product.GetIsMaturedInTargetPeriod( [Real] age, pispippl.Start(), pispippl.Period_MP() )
              ) 
        )
      {
        avail_qty := quantityvector.Get( index );
        qtyfulfilled := minvalue( avail_qty, delta );
        quantityvector.Set( index, avail_qty - qtyfulfilled );
        
        quantityconsumedvector.Append( qtyfulfilled );
        ageconsumedvector.Append( age );
        
        delta := delta - qtyfulfilled;
      }
    }
    
    // Get element in quantity vector with valid value
    isquantityvalidvector := quantityvector.GreaterThan( 0.0 );
    validquantityvector := quantityvector.GetSelection( isquantityvalidvector );
    validagevector := agevector.GetSelection( isquantityvalidvector );
    
    // Set the vectors with new elements
    quantityvector.Resize( 0 );
    agevector.Resize( 0 );
    quantityvector.Append( validquantityvector );
    agevector.Append( validagevector );
    
    // When allocating to DependentDemands, the passed in age vector has been aged according to the trip's lead time.
    // Here, we will un-age those supply so that the remaining supplies can still be used.
    // E.g. assuming shelf life is 6 days, DD qty is  7.033, trip's lead time is 3 days.
    // Supply before aged:
    // 178.9(7), 192.967(4), 7.033(3)
    // when being passed into this method, you will get
    // 178.9(10), 192.967(7), 7.033(6)
    // 7.033(6) is the only suitable candidate for the DD because it will not expire when arrives at destination
    // You are left with
    // 178.9(10), 192.967(7)
    // By right in this period, we should have remaining 178.9(7), 192.967(4)
    // If you don't unage them, MergeVectorAccordingToAgeAndExpiration will return 0 
    ageconsumedvector_mod := ageconsumedvector.Minus( agetobereduced );
    ageconsumedvector.Resize( 0 );
    ageconsumedvector.Append( ageconsumedvector_mod );
    
    agevector_mod := agevector.Minus( agetobereduced );
    agevector.Resize( 0 );
    agevector.Append( agevector_mod );
    
    // Merge the elements in vector according to age
    ShelfLife::MergeVectorAccordingToAgeAndExpiration( quantityvector, agevector,
                                                       pispippl,
                                                       pispippl.Start() );
  *]
}