| Quintiq file version 2.0 | 
| #parent: #root | 
| StaticMethod CreateOrUpdateForUnitPeriodQuantity ( | 
|   UnitPeriodQuantity unitperiodquantity, | 
|   Boolean isbatcheditcapacity, | 
|   String timeunit, | 
|   Real mincapacity, | 
|   Real maxcapacity, | 
|   Boolean isbatcheditmaxloadpercentage, | 
|   Real maxloadpercentage, | 
|   Boolean isbatcheditnrofunitsopen, | 
|   Number nrofunitsopen, | 
|   Boolean isthisperiodonwards | 
| ) | 
| { | 
|   Description: "Create or update the unit capacity when we want only the particular unit period quantity user's value ( get from unit capacity ) change." | 
|   TextBody: | 
|   [* | 
|     // soh yee Feb-20-2013 (modified) | 
|     unit := unitperiodquantity.Unit(); | 
|     defaultmaxcapacity := unit.MacroPlan().GlobalParameters_MP().DefaultMaxCapacityPerDayForUnit(); | 
|     unitcapacity := unitperiodquantity.UnitCapacity(); | 
|      | 
|     // If the batch edit checkbox in UI is unchecked, we get the data from the current unit capacity. | 
|     // Didn't use guard for more readability. | 
|     if( not isbatcheditcapacity ) | 
|     { | 
|       timeunit := unitperiodquantity.Period_MP().PeriodSpecification_MP().TimeUnit(); | 
|       mincapacity := 0.0; | 
|       maxcapacity := defaultmaxcapacity; | 
|      | 
|       if( unitperiodquantity.HasUnitCapacity() ) | 
|       { | 
|         timeunit := unitcapacity.TimeUnit(); | 
|         mincapacity := unitcapacity.MinCapacity(); | 
|         maxcapacity := unitcapacity.MaxCapacity(); | 
|       } | 
|     } | 
|      | 
|     if( not isbatcheditmaxloadpercentage ) | 
|     { | 
|       maxloadpercentage := unitperiodquantity.MaximumLoadPercentage(); | 
|      | 
|       if( unitperiodquantity.HasUnitCapacity() ) | 
|       { | 
|         maxloadpercentage := unitcapacity.MaximumLoadPercentage(); | 
|       } | 
|     } | 
|      | 
|     if( not isbatcheditnrofunitsopen ) | 
|     { | 
|       nrofunitsopen := unitperiodquantity.NrOfOpen(); | 
|      | 
|       if( unitperiodquantity.HasUnitCapacity() ) | 
|       { | 
|         nrofunitsopen := unitcapacity.NrOfUnitsOpen(); | 
|       } | 
|     } | 
|      | 
|     /* | 
|     Case1: all unit period quantitys are referring to Jan, 1(nrofunitsopen), 0(nrofunitstempclose). | 
|     Unit period quantity      Unit capacity | 
|       Jan                     Jan, 1, 0 | 
|       Feb | 
|       Mar | 
|       Apr | 
|      | 
|     Case2: when user open 1 more unit on Mar, (a) and (b) are created. | 
|     Unit period quantity      Unit capacity | 
|       Jan                     Jan, 1, 0 | 
|       Feb                     Mar, 2, 0 (a) | 
|       Mar                     Apr, 1, 0 (b) | 
|       Apr | 
|      | 
|      | 
|     Case3: when user open 1 more unit starting from Apr, (b) is updated. | 
|     Unit period quantity      Unit capacity | 
|       Jan                     Jan, 1,0 | 
|       Feb                     Mar, 2,0 (a) | 
|       Mar                     Apr, 2,0 (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 | 
|     */ | 
|      | 
|     nextupq := unitperiodquantity.Next().astype( UnitPeriodQuantity ); | 
|     nextunitcapacity := guard( nextupq.UnitCapacity(), null( UnitCapacity ) ); | 
|      | 
|     // Get all period dimension children's unit capacity, for handling special case and when isthisperiodonwads is true | 
|     unitcapacitys := selectset( unit, UnitCapacity, uc, | 
|                                 uc.Start() >= unitperiodquantity.Start() | 
|                                 and ( uc.Start() < unitperiodquantity.Period_MP().End() // Ignore the end if isthisperiodonwards | 
|                                       or isthisperiodonwards ) ); | 
|      | 
|     // To handle special case and when isthisperiodonwads is true | 
|     if( unitcapacitys.Size() > 0 | 
|         and not isnull( nextupq ) ) | 
|     { | 
|       lastchilduc := null( UnitCapacity ); | 
|      | 
|       // 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, UnitCapacity, uc, unitperiodquantity.End() >= uc.Start(), uc.Start() ); | 
|      | 
|         if( UnitCapacity::IsPrimaryKeysUnique( unit, nextupq.Start(), null( UnitCapacity ) ) ) | 
|         { | 
|           // 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(), | 
|                               nextupq.Start(), | 
|                               lastchilduc.TimeUnit(), | 
|                               lastchilduc.MinCapacity(), | 
|                               lastchilduc.MaxCapacity(), | 
|                               lastchilduc.MaximumLoadPercentage(), | 
|                               lastchilduc.NrOfUnitsOpen(), | 
|                               false ); | 
|         } | 
|       } | 
|      | 
|       // Delete all uc except the shifted one (also for handle isthisperiodonwads for week 3, 4 Day 1~7 for the given example) | 
|       traverse( unitcapacitys, Elements, e, | 
|                 e <> unitcapacity | 
|                 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( nextupq ) | 
|         and nextunitcapacity = unitcapacity | 
|         and UnitCapacity::IsPrimaryKeysUnique( unit, nextupq.Start(), null( UnitCapacity ) ) ) | 
|     { | 
|       // Case2: creating (b) | 
|       nexttimeunit := Translations::MP_GlobalParameters_Day(); // Default to capacity in global paramter which is in day | 
|       nextmincapacity := unit.MacroPlan().GlobalParameters_MP().DefaultMinCapacityPerDayForUnit(); | 
|       nextmaxcapacity := unit.MacroPlan().GlobalParameters_MP().DefaultMaxCapacityPerDayForUnit(); | 
|       nextmaxloadpercentage := unit.MacroPlan().GlobalParameters_MP().DefaultMaxLoadPercentage(); | 
|       nextnrofunitsopen := nextupq.NrOfOpen(); | 
|      | 
|       if( unitperiodquantity.HasUnitCapacity() ) | 
|       { | 
|         nexttimeunit := unitcapacity.TimeUnit(); | 
|         nextmincapacity := unitcapacity.MinCapacity(); | 
|         nextmaxcapacity := unitcapacity.MaxCapacity(); | 
|         nextmaxloadpercentage := unitcapacity.MaximumLoadPercentage(); | 
|         nextnrofunitsopen := unitcapacity.NrOfUnitsOpen(); | 
|       } | 
|      | 
|       UnitCapacity::Create( unit, | 
|                             nextupq.Start(), | 
|                             nexttimeunit, | 
|                             nextmincapacity, | 
|                             nextmaxcapacity, | 
|                             nextmaxloadpercentage, | 
|                             nextnrofunitsopen, | 
|                             false ); | 
|      | 
|       // Propogate the relation to unit period quantity. | 
|       // This is needed for the following checking. | 
|       Transaction::Transaction().Propagate(); | 
|     } | 
|      | 
|     // Create a new unit capacity for that particular unit period quantity if it does not bind to any unit capacity, or if it already has a unit capacity, | 
|     // the related unit capacity doesn't have the same start as the unit period quantity. | 
|     if( not unitperiodquantity.HasUnitCapacity() | 
|         or UnitCapacity::IsPrimaryKeysUnique( unit, unitperiodquantity.Start(), null( UnitCapacity ) ) ) | 
|     { | 
|       // Case2: creating (a) | 
|       UnitCapacity::Create( unit, | 
|                             unitperiodquantity.Start(), | 
|                             timeunit, | 
|                             mincapacity, | 
|                             maxcapacity, | 
|                             maxloadpercentage, | 
|                             nrofunitsopen, | 
|                             false ); | 
|     } | 
|      | 
|     else | 
|     { | 
|       // Case3, (b) is updated. | 
|       // The to-be created unit capacity has the same primary keys with existing data. Therefore, we update it instead of creating a new data to avoid duplication. | 
|       unitcapacity.Update( unit, | 
|                            unitcapacity.Start(), | 
|                            timeunit, | 
|                            mincapacity, | 
|                            maxcapacity, | 
|                            maxloadpercentage, | 
|                            nrofunitsopen, | 
|                            false ); | 
|     } | 
|   *] | 
| } |