hongji.li
2023-11-07 1a1ba3ad5ed9e4380185aa1ccad20204a0e5f115
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
Quintiq file version 2.0
#parent: #root
StaticMethod CreateOrUpdateForUnitPeriodTime (
  UnitPeriodTime unitperiodtime,
  Boolean isbatcheditmaintenance,
  String timeunit,
  Duration maintenance,
  Boolean isbatcheditefficiency,
  Real efficiency,
  Boolean isbatcheditallocation,
  Real allocation,
  Boolean isbatcheditshiftpattern,
  ShiftPattern shiftpattern,
  Boolean isbatcheditmaxloadpercentage,
  Real maxloadpercentage,
  Boolean isbatcheditnrofunitsopen,
  Number nrofunitsopen,
  Boolean isthisperiodonwards,
  Boolean isbatcheditminimumloadthreshold,
  Real minimumloadthreshold
)
{
  Description: "Create or update the unit availability when we want only the particular unit period time user's value ( get from unit availability ) change."
  TextBody:
  [*
    // soh yee Feb-20-2013 (modified)
    // This method can be used to change either shift pattern or number of units open / close for the unit period time too.
    
    unitavailability := unitperiodtime.UnitAvailability();
    unit := unitperiodtime.Unit();
    
    // If the batch edit checkbox in UI is unchecked, we get back the current unit availability data.
    // Did not use guard for better readability.
    if( not isbatcheditmaintenance )
    {
      timeunit := unitperiodtime.Period_MP().TimeUnit() ;
      maintenance := Duration::Zero();
    
      if( unitperiodtime.HasCapacityDefinition() )
      {
        timeunit := unitavailability.TimeUnit();
        maintenance := unitavailability.Maintenance();
      }
    }
    
    if( not isbatcheditefficiency )
    {
      efficiency := unitperiodtime.Efficiency();
    
      if( unitperiodtime.HasCapacityDefinition() )
      {
        efficiency := unitavailability.Efficiency();
      }
    }
    
    if( not isbatcheditallocation )
    {
      allocation := unitperiodtime.Allocation();
    
      if( unitperiodtime.HasCapacityDefinition() )
      {
        allocation := unitavailability.Allocation();
      }
    }
    
    if( not isbatcheditshiftpattern )
    {
      shiftpattern := unitperiodtime.ShiftPattern();
    
      if( unitperiodtime.HasCapacityDefinition() )
      {
        shiftpattern := unitavailability.ShiftPattern();
      }
    }
    
    if( not isbatcheditmaxloadpercentage )
    {
      maxloadpercentage := unitperiodtime.MaximumLoadPercentage();
    
      if( unitperiodtime.HasCapacityDefinition() )
      {
        maxloadpercentage := unitavailability.MaximumLoadPercentage();
      }
    }
    
    if( not isbatcheditnrofunitsopen )
    {
      nrofunitsopen := unitperiodtime.NrOfOpen();
    
      if( unitperiodtime.HasCapacityDefinition() )
      {
        nrofunitsopen := unitavailability.NrOfUnitsOpen();
      }
    }
    
    if( not isbatcheditminimumloadthreshold )
    {  
      minimumloadthreshold := unitperiodtime.MinimumLoadThreshold();
    
      if( unitperiodtime.HasCapacityDefinition() )
      {
        minimumloadthreshold := unitavailability.MinimumLoadThreshold();
      }
    }
    
    /*
    Case1: all unit period time are referring to Jan, S12
    Unit period time      Unit availability
      Jan                     Jan, S12
      Feb
      Mar
      Apr
    
    Case2: when user drop S15 to Mar, (a) and (b) are created.
    Unit period time      Unit availability
      Jan                     Jan, S12
      Feb                     Mar, S15 (a)
      Mar                     Apr, S12 (b)
      Apr
    
    
    Case3: when user drop S15 to Jan, (c) is updated.
    Unit period time      Unit availability
      Jan                     Jan, S15 (c)
      Feb                     Mar, S15 (a)
      Mar                     Apr, S12 (b)
      Apr
    
    Special case: When the scenario have parallel periods, for example Weeks and Days.
    Unit period quantity      Unit capacity
    Week 1 (isbase)           Week 1
    Week 2 (isbase)           Week 2
    Week 3 (not base)         Day 1, Day 2, Day 3, Day 5, Day 6, Day 7
    Week 4 (not base)         Day 1, Day 2, Day 3, Day 5, Day 6, Day 7
    */
    
    nextupt := unitperiodtime.Next().astype( UnitPeriodTime );
    nextunitavailability := guard( nextupt.UnitAvailability(), null( UnitAvailability ) );
    
    // Get all period dimension children's unit capacity, for handling special case and when isthisperiodonwads is true
    unitavailabilities := selectset( unit, UnitAvailability, ua,
                                     ua.Start() >= unitperiodtime.Start()
                                     and ( ua.Start() < unitperiodtime.Period_MP().End() // Ignore the end if isthisperiodonwards
                                           or isthisperiodonwards ) );
    
    // To handle special case and when isthisperiodonwads is true
    if( unitavailabilities.Size() > 0
        and not isnull( nextupt ) )
    {
      lastchilduc := null( UnitAvailability );
    
      // If have next uc, we want to shift the last uc from the childuc as next period uc
      if( not isthisperiodonwards )
      {
        // Shift the last uc of the child period to next period
        lastchilduc := maxselect( unit, UnitAvailability, ua, unitperiodtime.End() >= ua.Start(), ua.Start() );
    
        if( UnitAvailability::IsPrimaryKeysUnique( unit, nextupt.Start(), null( UnitAvailability ) ) )
        {
          // Keep all value except the start, to handle period > day where it have uc start in the middle of the period
          // We will shift the last uc to next period
          lastchilduc.Update( lastchilduc.Unit(),
                              nextupt.Start(),
                              lastchilduc.TimeUnit(),
                              lastchilduc.Maintenance(),
                              lastchilduc.Efficiency(),
                              lastchilduc.Allocation(),
                              lastchilduc.ShiftPattern(),
                              lastchilduc.MaximumLoadPercentage(),
                              lastchilduc.NrOfUnitsOpen(),
                              lastchilduc.MinimumLoadThreshold(),
                              false 
                            );
        }
      }
    
      // Delete all uc except the shifted one (also for handle isthisperiodonwads for week 3, 4 Day 1~7 for the given example)
      traverse( unitavailabilities, Elements, e,
                e <> unitavailability
                and e <> lastchilduc )
      {
        e.Delete();
      }
    
      // Propogate the relation to unit period quantity.
      // This is needed for the following checking.
      Transaction::Transaction().Propagate();
    }
    
    if( not isthisperiodonwards
        and not isnull( nextupt )
        and nextunitavailability = unitavailability
        and UnitAvailability::IsPrimaryKeysUnique( unit, nextupt.Start(), null( UnitAvailability ) ) )
    {
      // Case2: creating (b)
      periodspec := nextupt.Period_MP().PeriodSpecification_MP(); 
      nexttimeunit := ifexpr( not isnull( periodspec ), periodspec.TimeUnit(), nextupt.Period_MP().TimeUnit() );
      nextmaintenance := Duration::Zero();
      nextefficiency := nextupt.Efficiency();
      nextallocation := nextupt.Allocation();
      nextshiftpattern := nextupt.ShiftPattern();
      nextmaxloadpercentage := nextupt.MaximumLoadPercentage()
      nextnrofunitsopen := nextupt.NrOfOpen();
      nextminimumloadthreshold := nextupt.MinimumLoadThreshold();
    
      if( unitperiodtime.HasCapacityDefinition() )
      {
        nexttimeunit := unitavailability.TimeUnit();
        nextmaintenance := unitavailability.Maintenance();
        nextefficiency := unitavailability.Efficiency();
        nextallocation := unitavailability.Allocation();
        nextshiftpattern := unitavailability.ShiftPattern();
        nextmaxloadpercentage := unitavailability.MaximumLoadPercentage();
        nextnrofunitsopen := unitavailability.NrOfUnitsOpen();
        nextminimumloadthreshold := unitavailability.MinimumLoadThreshold();
      }
    
      UnitAvailability::Create( unit,
                                nextupt.Start(),
                                nexttimeunit,
                                nextmaintenance,
                                nextefficiency,
                                nextallocation,
                                nextshiftpattern,
                                nextmaxloadpercentage,
                                nextnrofunitsopen,
                                nextminimumloadthreshold,
                                false
                              );
    
      // Propogate the relation to unit period time.
      // This is needed for the following checking.
      Transaction::Transaction().Propagate();
    }
    
    // Create a new unit availability for that particular unit period time if it does not bind to any unit availability, or if it has a unit availability,
    // the related unit availability doesn't have the same start as the unit period time.
    if( not unitperiodtime.HasCapacityDefinition()
        or UnitAvailability::IsPrimaryKeysUnique( unit, unitperiodtime.Start(), null( UnitAvailability ) ) )
    {
      // Case2: creating (a)
      UnitAvailability::Create( unit,
                                unitperiodtime.Start(),
                                timeunit,
                                maintenance,
                                efficiency,
                                allocation,
                                shiftpattern,
                                maxloadpercentage,
                                nrofunitsopen,
                                minimumloadthreshold,
                                false
                              );
    }
    
    else
    {
      // Case3
      unitavailability.Update( unit,
                               unitavailability.Start(),
                               timeunit,
                               maintenance,
                               efficiency,
                               allocation,
                               shiftpattern,
                               maxloadpercentage,
                               nrofunitsopen,
                               minimumloadthreshold,
                               false
                             );
    }
  *]
}