| Quintiq file version 2.0 | 
| #parent: #root | 
| FunctionOverride CalcTotalAvailableCapacity | 
| { | 
|   TextBody: | 
|   [* | 
|     value := Duration::Zero(); | 
|     planningcapacity := 1.0; | 
|      | 
|     if( this.IsPlanning() or this.IsBase() ) | 
|     { | 
|       planningup := ifexpr( this.IsPlanning(),  | 
|                             this,                                                  // Case 1: planning UnitPeriod: aggregate values from associated period tasks  | 
|                             this.PlanningUP().astype( UnitPeriodTransportTime ) ); // Case 2: base, non planning UnitPeriod: disaggregate value from planning UnitPeriod | 
|      | 
|      | 
|       if( not isnull( planningup ) ) | 
|       { | 
|         // Determined by the used shift pattern, the efficiency rate, maintenance considering its maintenance factor, allocation, max load percentage and calendar elements. | 
|          | 
|         if( not isnull( planningup.Period_MP() )  | 
|             and not isnull( planningup.ShiftPattern() )  | 
|             and not planningup.Period_MP().IsInHour() ) //gdn1 HourlyPeriod is not applicable for ShiftPattern | 
|         { | 
|           lastshiftday := planningup.StartDate() - planningup.Period_MP().Start().StartOfWeek().Date() + 1 | 
|        | 
|           nrdaysinthisperiod := planningup.Duration().DaysAsReal(); | 
|           firstday := planningup.Period_MP().Start(); | 
|           numberofshiftday := planningup.ShiftPattern().ShiftDay( relsize ); | 
|        | 
|           if( not isnull( planningup.Previous() ) ) | 
|           { | 
|             lastshiftday := planningup.Previous().astype( UnitPeriodTransportTime ).PreviousPeriodLastShiftDay() + 1; | 
|           } | 
|        | 
|           for( i := 0; i < nrdaysinthisperiod and firstday + Duration::Days( i ) >= planningup.Unit().StartDate().DateTime() ; i++ ) | 
|           { | 
|             shiftday := lastshiftday + i; | 
|        | 
|             if( shiftday > numberofshiftday ) | 
|             { | 
|               shiftday := shiftday mod numberofshiftday; | 
|        | 
|               if( shiftday = 0 ) | 
|               { | 
|                 shiftday := numberofshiftday; | 
|               } | 
|             } | 
|        | 
|             shift := select( planningup.ShiftPattern(), ShiftDay, shift, shift.Day() = shiftday, true ); | 
|             unavailable := planningup.Unit().UnavailableTime( firstday + Duration::Days( i ), firstday + Duration::Days( i + 1 ) ); | 
|        | 
|             if( not isnull( shift ) ) | 
|             { | 
|               value := value + maxvalue( ( shift.Capacity() - unavailable ), Duration::Zero() ); | 
|             } | 
|           } | 
|         } | 
|         else if ( planningup.Period_MP().DurationInDays() < 1 )   //gdn1 HourlyPeriod is always same as PeriodDuration  | 
|         { | 
|           value := planningup.Unit().UnitCalendar().AvailableTime( planningup.Start(), planningup.End(), 0.00000001 ); // Check calendar to make hourly period work with the calendar | 
|         } | 
|          | 
|         value := maxvalue( ( value - planningup.Maintenance() ) * planningup.NrOfOpen(), Duration::Zero() ); | 
|        | 
|         planningcapacity := value.HoursAsReal() * planningup.MaximumLoadPercentage() / 100; | 
|          | 
|         planningcapacity := this.PlanningSystemRatio() * planningcapacity; | 
|       } | 
|     } | 
|     else | 
|     { // Case 3: aggregated UnitPeriod: aggregate values from base | 
|       planningcapacity := sum( this.GetChildrenOfPeriodDimension(), Elements.astype( UnitPeriodTransportTime ), e, e.TotalAvailableCapacity().HoursAsReal() ); | 
|     } | 
|      | 
|     this.TotalAvailableCapacity( Duration::Hours( planningcapacity ) ); | 
|   *] | 
| } |