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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
Quintiq file version 2.0
#parent: #root
MethodOverride Update (
  Real quantity
)
{
  TextBody:
  [*
    // soh yee Sep-25-2015 (created)
    nonlockingsupplies := selectset( this.GetNewSupplies(), Elements, ns,
                                     not ns.GetHasUserQuantity() );
    
    
    // ************ Locking with current quantity ratio  ************
    // For those with user quantity, the quantity will be adjusted accordingly based on its previous ratio
    // Porportional disaggregation
    lockingsupplies := this.GetNewSupplies().Difference( nonlockingsupplies );
    totallockingquantity := 0.0;
    thisquantity := this.Quantity();
    
    
    if( thisquantity > 0 )
    {
      traverse( lockingsupplies, Elements, ns )
      {
        newquantity := quantity * ns.Quantity() / thisquantity;
        ns.Update( newquantity );
    
        totallockingquantity := totallockingquantity + newquantity;
      }
    }
    else
    {
      // In case of aggregated supply quantity is 0, we will treat the locked supply as nonlock to disaggregate using default factor
      nonlockingsupplies := lockingsupplies.Union( nonlockingsupplies );
    }
    
    // ************ Locking using default factor ************
    // The remaining quantity will be disaggregated to the new supplies not set by the user, using the default factor specified by user
    // Manual disaggregation
    remainingquantity := quantity - totallockingquantity;
    
    // Disaggregation based on pisp
    // To keep it simply, take the effective accumulated disggregation factor that belongs to the supply period.
    period := this.ProductInStockingPointInPeriod().Period_MP();
    totalpispfactor := sum( nonlockingsupplies,
                            Elements.ProcessOutput.ProductInStockingPoint_MP,
                            pisp,
                            pisp.GetAccumulateDisaggregationFactor( period ) );
    
    traverse( nonlockingsupplies, Elements, ns )
    {
      pisp := ns.ProcessOutput().ProductInStockingPoint_MP();
    
      // Disaggregation on period dimension
      // If there is at least a unit period planned infinite, we will distribute the quantity based on the duration of the period to planned infinite periods.
      totalavailability := sum( nonlockingsupplies, Elements, nns,
                                nns.ProcessOutput().ProductInStockingPoint_MP() = pisp
                                and nns.PeriodTask_MP().UnitPeriod().IsPlannedInfinite(),
                                nns.PeriodTask_MP().UnitPeriod().Duration().DaysAsReal() );
    
      hasinfiniteperiod := totalavailability > 0;
    
      if( totalavailability = 0 )
      {
        // The disaggregated quantity on pisp will be disaggregated to each period based on unit period availability of the period
        totalavailability := sum( nonlockingsupplies, Elements, nns, nns.ProcessOutput().ProductInStockingPoint_MP() = pisp,
                                  nns.GetUnitPeriodAvailableCapacity() );
      }
      disaggqty := 0.0;
    
      if( totalpispfactor > 0 and totalavailability > 0 )
      {
        availability := 0.0;
        unitperiod := ns.PeriodTask_MP().UnitPeriod();
    
        if( hasinfiniteperiod )
        {
          if( unitperiod.IsPlannedInfinite() )
          {
            availability := unitperiod.Duration().DaysAsReal();
          }
        }
        else
        {
          availability := ns.GetUnitPeriodAvailableCapacity();
        }
        disaggqty := remainingquantity
                      * ns.GetProductAccumulateDisaggregationFactor() / totalpispfactor
                      * availability / totalavailability;
    
        /*
        debuginfo('disaggr qty:', disaggqty , '=',
                  '*', ns.GetProductAccumulateDisaggregationFactor(), 'adf',
                  '/', totalpispfactor, 'ttlpispf',
                  '*', availability, 'av',
                  '/', totalavailability, 'ttlav'
                 );
        */
      }
      ns.Update( disaggqty );
    }
    
    // ********** Create new supplies that belongs to this aggregated supplies but do not exist yet ***********
    // The quantity on the leaf level will be locked whenever its aggregated supply is manually edited.
    // Thus, the new supplies will be created and will be locked (set to 0 with hasuser flag) to prevent the optimizer overrides it
    operation := guard( this.Process_MP().astype( Operation ), null( Operation ) );
    
    if( not isnull( operation ) )
    {
      this.ProductInStockingPointInPeriod().CreateOperationNewSupplies( operation, 0.0, true );
    }
  *]
}