How to create an Order calculated custom value using C# formulas

Order calculated custom values allow for automatic calculation ggagebased upon order data, avoiding manual custom value selection.

Order calculated custom value C# formulas are added by the FBO One support team only. Contact support@amsterdamsoftware.com for guidance.

Contents:

Information

Custom values in FBO One allow for extending data for contacts, aircraft registrations, products, and handling orders with user-defined fields. These fields are called Custom Properties and Custom Values. and can have different usage in the system including Pricing, Ordering services, Reporting, Email communication, etc.

Generally, users must manually assign custom values and keep assignments up to date. For master data (contacts, products, registrations) assigning a custom value is mostly a one-time operation, but for working orders, this process needs to be done for every new order. This process is now improved using calculated custom values based on C# expressions. The calculation follows the same logic as for auto-add services where a service is auto-added based on the order data context and refreshed during the live cycle of the order. 

For custom values, we can specify a c# formula expression using the same syntax as Auto-add products which returns a text result; the text result is refreshed and saved per order. These can then be used in Custom Value Price calculators or Unit Price Formula Calculators, Entry Exporters, Reports, Email template variables specific to Orders like movement messages, Client notifications, etc.

Custom values can be used in email templates variables like any other custom values using syntax ~Custom-Arrival OOH assistance~

The expressions that can be used in the formula include:

  • Any Order data provider field: input.GetOrderField("name of the field"): see list of fields here

  • Any Order linked custom value: input.GetCustomValue("code of the custom value")

  • Any Order template variable: input.GetTemplateValue("template value key"): see list here

Note: custom value formulas applies to all orders automatically during the recalculation of orders. If needed, expressions can be made very specific so it returns empty values for scenarios when not applicable. Also to disable a formula, you can clear the expression of the custom value and unlink the custom property from the Order table. 

How to create an order calculated custom value

To create a calculated custom value:

  1. Go to the Administration page | Custom values

  2. Add a new Custom property

  3. Add a new Custom value and fill in the Formula field your C# expression

  4. Link the Custom property to the Order table

  • In the below example, a Custom property has been created indicating when an arrival time is occurring Out of Hours. The value is called 'Arrival OOH Assistance'.

  • The calculated custom value formula is shown in the 'Formula' field below contains the times during which the airport is open 06:00-20:00LT.

  • If the arrival time is entered or updated (via CFMU, FlightAware, or manually), and falls outside of these hours, the Custom Value shown in the order screen will show 'Arrival OOH Assistance - YES'.

  • If the arrival time falls between the times during which the airport is open, the value will show 'Arrival OOH Assistance - NO'.

Calculated custom value examples

Aircraft

Create an email variable to display the aircraft wingspan in meters
1 2 3 4 5 6 7 8 9 ((Func<string>)(() => { { var orderField = (decimal?)input.GetOrderField("WingSpanInMeter"); if (!orderField.HasValue) return "-"; else return $"{orderField.Value:0.##}" + ""; } }))();
Calculate an order warning based upon a custom value e.g. if the aircraft type code is 1d, 1e, 1d, etc. 

In this case, the warning "TYPE C or ABOVE" will be displayed

1 2 3 4 5 6 7 8 9 10 11 12 13 ((Func<string>)(() => { { var aerodrome_reference_codes = new[] { "1d", "1e", "2c", "2d", "2e", "3c", "3d", "3e", "4c", "4d", "4e", }; string current = input.GetCustomValue("aerodrome_reference_code") ?? ""; if (aerodrome_reference_codes.Contains(current.ToLower())) { return "TYPE C or ABOVE"; } else return ""; } }))();
Calculate Prior Orders count (e.g. to show on Orders for info purposes) 
1 $"{input.GetPriorActualHandlingCountByRegistration("StartDate=2013-01-01")}"
NOX emissions for an aircraft if 0 pax out
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ((Func<string>)(() => { { int.TryParse($"{input.GetOrderField("AircraftNumberOfEngines")}", out var aircraftEngine); int.TryParse($"{input.GetCustomValue("NOX Emissions")}", out var emissions); var paxCountOut = (int?)input.GetOrderField("PaxCountOut") ?? 0; if (paxCountOut == 0) { var emissionsZeroPax = (decimal?)(emissions * aircraftEngine) / 1000; return $"{emissionsZeroPax}"; } // if there are pax, charges are different / via another formula and price agreements return "0"; } }))();
NOX emissions for an aircraft if greater than 0 pax out
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ((Func<string>)(() => { { int.TryParse($"{input.GetOrderField("AircraftNumberOfEngines")}", out var aircraftEngine); int.TryParse(input.GetCustomValue("NOX Emissions"), out var emissions); var paxCountOut = (int?)input.GetOrderField("PaxCountOut") ?? 0; if (paxCountOut != 0) { var emissionsPerPax = (decimal)((emissions * aircraftEngine) / paxCountOut); if (emissionsPerPax > 400) emissionsPerPax = emissionsPerPax - 400; else emissionsPerPax = 0; return $"{emissionsPerPax}"; } else { // no pax return "0"; } } }))();
Add a special message for certain aircraft types
1 2 3 4 5 6 7 8 9 10 11 12 13 ((Func<string>)(() => { { var aircraftType = new[] { "c130", "c17", "c5" }; var currentType = (input.GetOrderField("AircraftTypeICAO") as string) ?? ""; if (aircraftType.Contains(currentType.ToLower())) { return "**ATTENTION: Operator need to bring their own tow bar**"; } else return "~~"; } }))();
Show message if aircraft engine count is missing
1 2 3 4 5 6 7 8 9 ((Func<string>)(() => { { var engineCount = (int?)input.GetOrderField("AircraftNumberOfEngines"); if (engineCount > 0) return ""; else return "Engine count required for NOX calculations"; } }))();
Show message if NOX emissions custom value is missing for an aircraft
1 2 3 4 5 6 7 8 9 10 ((Func<string>)(() => { { var noxValue = ((string)input.GetCustomValue("NOX Emissions")); if (noxValue == "" || noxValue == null) return "Set value to A/C Type or Reg"; else return ""; } }))();
Add a parking group number based upon the dimensions of an aircraft
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 ((Func<string>)(() => { { var wingSpanMeters = Math.Ceiling((decimal?)input.GetOrderField("WingSpanInMeter") ?? 0M); var lengthMeters = Math.Ceiling((decimal?)input.GetOrderField("LengthInMeter") ?? 0M); if (wingSpanMeters <= 20 && lengthMeters <= 25) return "1"; if (wingSpanMeters <= 30 && lengthMeters <= 32) return "2"; if (wingSpanMeters <= 38 && lengthMeters <= 47) return "3"; if (wingSpanMeters <= 48 && lengthMeters <= 58) return "4"; if (wingSpanMeters <= 52 && lengthMeters <= 62) return "5"; if (wingSpanMeters <= 61 && lengthMeters <= 64) return "6"; if (wingSpanMeters <= 65 && lengthMeters <= 71) return "7"; if (wingSpanMeters <= 65 && lengthMeters <= 76) return "8"; if (wingSpanMeters > 65 && lengthMeters > 76) return "9"; return "1"; } }))();
Return free parking minutes based upon the MTOW of an aircraft
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ((Func<string>)(() => { { var mtowKg = (int?)input.GetOrderField("MTOWkg") ?? 0; if (mtowKg <= 25000) return "60"; if (mtowKg <= 100000) return "90"; if (mtowKg <= 140000) return "120"; if (mtowKg <= 200000) return "150"; if (mtowKg <= 300000) return "180"; if (mtowKg <= 425000) return "240"; return "300"; } }))();

Arrival / Departure

Arrival OOH assistance expression
1 2 3 4 5 6 7 8 9 ((Func<string>)(() => {{ var arrivalTime = ((DateTime?)input.GetOrderField("MostActualArrivalDateTimeLT"))?.TimeOfDay; if (!arrivalTime.HasValue) return "UNKNOWN"; else if (arrivalTime.Value < TimeSpan.Parse("06:00") || arrivalTime.Value > TimeSpan.Parse("20:00")) return "YES"; else return "NO"; }}))();
Departure OOH assistance expression

To set up the same for Departure, the formula is shown in the code block below may be used

1 2 3 4 5 6 7 8 9 ((Func<string>)(() => {{ var departureTime = ((DateTime?)input.GetOrderField("MostActualDepartureDateTimeLt"))?.TimeOfDay; if (!departureTime.HasValue) return "UNKNOWN"; else if (departureTime.Value < TimeSpan.Parse("06:30") || departureTime.Value > TimeSpan.Parse("20:00")) return "YES"; else return "NO"; }}))();
Display ETA at destination formatted as ddMMM in movement messages:
  • Create a custom property named 'EtaAtDestinationUtc as ddMMM' and link the property to the order table. 

  • Add one custom value and enter in the Formula box the below expression. On the property, you can set the 'Visible in Order screen' flag to see the calculated value on the Order page.

  • Add ~Custom-EtaAtDestinationUtc as ddMMM~ as a template variable in the movement message.

1 2 3 4 5 ((Func<string>)(() => {{ var dateFormat = "ddMMM"; var etaAtDestinationUtc = (DateTime?)input.GetOrderField("EtaAtDestinationUtc"); return etaAtDestinationUtc.HasValue ? etaAtDestinationUtc.Value.ToString(dateFormat).ToUpper() : ""; }}))();
Display On/Off Blocks UTC times in format HHmm (e.g. 1544)
  • Create a Custom Property e.g. OnBlocksTimeUtc

  • Add a custom value and in the 'formula' field add the below formula

  • The custom value e.g. OnBlocksTimeUtc can be added as a variable to the relevant template using the variable e.g. ~Custom-OnBlocksTimeUtc~ 

1 2 3 4 5 6 7 8 9 10 11 12 13 ((Func<string>)(() => { { var onBlockText = (string)input.GetTemplateValue("ArrivalOnBlocksDateTimeUtc"); var indexUtc = onBlockText.IndexOf("(UTC)"); if (indexUtc > 0) { DateTime onBlock; if (DateTime.TryParse(onBlockText.Substring(0, indexUtc), out onBlock)) return $"{ onBlock:HHmm}"; } return ""; } }))();
Calculate the number of minutes between MostActualArrivalDateTime and MostActualDepartureDateTime (Groundtime)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ((Func<string>)(() => { var result = "~~"; var mostActualDepartureDateTime = (DateTime?)input.GetOrderField("MostActualDepartureDateTime"); var mostActualArrivalDateTime = (DateTime?)input.GetOrderField("MostActualArrivalDateTime"); if (mostActualDepartureDateTime.HasValue && mostActualArrivalDateTime.HasValue) { var onGroundMinutes = (mostActualDepartureDateTime.Value - mostActualArrivalDateTime.Value).Duration().TotalMinutes; return $"{onGroundMinutes:0}"; } else { result = "0"; } return result; }))();
Calculate the number of nights between MostActualArrivalDateTime and MostActualDepartureDateTime
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ((Func<string>)(() => {{ var dateFormat = "ddMMM"; var mostActualArrivalDateTime = (DateTime?)input.GetOrderField("MostActualArrivalDateTime"); var mostActualDepartureDateTime = (DateTime?)input.GetOrderField("MostActualDepartureDateTime"); if (!mostActualArrivalDateTime.HasValue || !mostActualDepartureDateTime.HasValue) return ""; else { var diff = Math.Abs(mostActualArrivalDateTime.Value.Date.Subtract(mostActualDepartureDateTime.Value.Date).Days); if(diff == 0) return ""; else return diff.ToString(dateFormat); } }}))();
Calculate the number of nights between MostActualArrivalDateTime and MostActualDepartureDateTime (with a minimum 6 hours difference)

Note: A night is considered a time difference bigger than 6 hours and also a date difference that includes the midnight hour

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ((Func<string>)(() => {{ var dateFormat = "ddMMM"; var mostActualArrivalDateTime = (DateTime?)input.GetOrderField("MostActualArrivalDateTime"); var mostActualDepartureDateTime = (DateTime?)input.GetOrderField("MostActualDepartureDateTime"); if (!mostActualArrivalDateTime.HasValue || !mostActualDepartureDateTime.HasValue) return ""; else if (Math.Abs(mostActualArrivalDateTime.Value.Subtract(mostActualDepartureDateTime.Value).TotalHours) < 6) return ""; else { var diff = Math.Abs(mostActualArrivalDateTime.Value.Date.Subtract(mostActualDepartureDateTime.Value.Date).Days); if(diff == 0) return ""; else return diff.ToString(dateFormat); } }}))();
Show whether the From Station ICAO is authorised or not. Show ? if from station is blank
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ((Func<string>)(() => { // authorized airport ICAOs var authorizedIcaos = new string[] { "LATI", "UDYZ", "LOWW", "UBBB" }; var fromIcao = (string)input.GetOrderField("FromIcao"); if(string.IsNullOrEmpty(fromIcao)) return "?"; else { var isAuthorizedIcao = authorizedIcaos.Any(c => c == fromIcao.ToUpper()); return isAuthorizedIcao ? "YES" : "NO"; } }))();
Show whether the station from which an A/C is arriving from or departing to is Schengen

Arrival Schengen? Yes/No

1 2 3 4 5 6 7 8 9 10 ((Func<string>)(() => { // Schengen countries var countriesGroup = new string[] { "Austria", "Belgium", "Czech Republic", "Denmark", "Estonia", "Finland", "France", "Germany", "Greece", "Hungary", "Iceland", "Italy", "Latvia", "Liechtenstein", "Lithuania", "Luxembourg", "Malta", "Netherlands", "Norway", "Poland", "Portugal", "Portugal | Acores", "Slovakia", "Slovenia", "Spain", "Sweden", "Switzerland", "Monaco", "San Marino", "Vatican City"}; var countryField = input.GetOrderField("FromStationCountry"); var country = countryField != null ? countryField.ToString() : ""; var isSchengenCountry = countriesGroup.Any(c => c == country); return isSchengenCountry ? "Yes" : "No"; }))();

This can then be used as a template variable to display the relevant Flight Number in the Supply Order template (e.g for an Overflight Permit Request)

1 2 3 4 5 6 7 8 9 10 11 12 ((Func<string>)(() => { var mostActualDepartureDateTime = (DateTime?)input.GetOrderField("MostActualDepartureDateTime"); var mostActualArrivalDateTime = (DateTime?)input.GetOrderField("MostActualArrivalDateTime"); var arrivalIsPending = (bool)input.GetOrderField("ArrivalIsPending"); var departureIsPending = (bool)input.GetOrderField("DepartureIsPending"); if (mostActualDepartureDateTime.HasValue || mostActualArrivalDateTime.HasValue || arrivalIsPending || departureIsPending) return (string)input.GetOrderField("FlightNumberOut"); return (string)input.GetCustomValue("Flight Number"); }))();
Add the mention 'Yes' when the criteria for the 'Self-Quarantine' value is met, and 'No' when it's not

Criteria: Arriving from Countries list..... / Arriving from Station ICAO's list / Inbound Pax Count >0

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ((Func<string>)(() => { var fromCountries = new string[] {"armenia", "belgium", "czech Republic", "french polynesia"}; var fromICAOs = new string[] {"LFAY","LFQD","LFOB","LFAF","LFQQ","LFPG","LFPB","LFPO"}; var paxIn = (int?)input.GetOrderField("PaxCountIn") ?? 0; var countryField = input.GetOrderField("FromStationCountry"); var country = countryField != null ? countryField.ToString().ToLower() : ""; var fromICAOField = input.GetOrderField("FromICAO"); var fromICAO = fromICAOField != null ? fromICAOField.ToString().ToUpper() : ""; return (paxIn > 0 && (fromCountries.Any(c => c == country) || fromICAOs.Any(c => c == fromICAO))) ? "Yes" : "No"; }))();
Indicate either "Within allowed Timeframe" or "Exceeded Deadline" text-based upon MostActualArrivalDateTime

Determine whether the MostActualArrivalDateTime is either within 48-hours of the current time or beyond this time (excludes weekends). If we are beyond 48-hours before the MostActualArrivalDateTime, then show "Within allowed Timeframe" and if we are within 48-hours of the STA, then show "DEADLINE EXCEEDED"

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 ((Func<string>)(() => { { var currentTimeUtc = DateTime.UtcNow; var staTimeUtc = (DateTime?)input.GetOrderField("MostActualArrivalDateTime"); double timeFrame = 2880; var countedMinutes = 0; if (staTimeUtc != null) { var time = staTimeUtc.Value; var min = 0; do { min++; time = staTimeUtc.Value.AddMinutes(-min); if ((int)time.DayOfWeek == 0 || (int)time.DayOfWeek == 6) // for sunday or saturday we don't count the minutes continue; countedMinutes++; } while (time > currentTimeUtc); var result = ""; if (countedMinutes < 2880) return "DEADLINE EXCEEDED"; else return "WITHIN ALLOWED TIMEFRAME"; } else { return "UNKNOWN"; } } }))();
Return Yes/No based on Destination Country and Specific Stations
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ((Func<string>)(() => { // Schengen countries var countriesGroup = new string[] { "Belgium", "Bulgaria", "Czech Republic", "Denmark", "Estonia", "Germany", "France", "Germany", "Greece", "Ireland", "Spain", "France", "Croatia", "Italy", "Cyprus", "Lithuania", "Latvia", "Luxembourg", "Hungary", "Malta", "Netherlands", "Austria", "Poland", "Portugal", "Romania", "Slovenia", "Finland", "Sweden", "Slovenia" }; var stationsGroup = new string[] { "EGAA", "EGAB", "EGAC", "EGAD", "EGAE", "EGAL" }; var toStation = (input.GetOrderField("ToIcao") as string) ?? ""; var isSchengenStation = stationsGroup.Any(c => c == toStation); var toCountry = (input.GetOrderField("ToStationCountry") as string) ?? ""; var isSchengenCountry = countriesGroup.Any(c => c == toCountry); bool autoAdd = !(isSchengenCountry || isSchengenStation); string yesOrNoResponse = autoAdd ? "Yes" : "No"; return yesOrNoResponse; }))();
Display if the arrival origin is an EU country
1 2 3 4 5 6 7 8 9 ((Func<string>)(() => { // EU countries var countriesGroup = new string[] { "Austria", "Belgium", "Bulgaria", "Croatia", "Cyprus", "Czech Republic", "Denmark", "Estonia", "Finland", "France", "Germany", "Greece", "Hungary", "Ireland", "Italy", "Latvia", "Lithuania", "Luxembourg", "Malta", "Netherlands", "Poland", "Portugal", "Romania", "Slovakia", "Slovenia", "Spain", "Sweden", "United Kingdom" }; var countryField = input.GetOrderField("FromStationCountry"); var country = countryField != null ? countryField.ToString() : ""; var isEUCountry = countriesGroup.Any(c => c == country); return isEUCountry ? "Yes" : "No"; }))();
Display if the departure destination is an EU country
1 2 3 4 5 6 7 8 9 ((Func<string>)(() => { // EU countries var countriesGroup = new string[] { "Austria", "Belgium", "Bulgaria", "Croatia", "Cyprus", "Czech Republic", "Denmark", "Estonia", "Finland", "France", "Germany", "Greece", "Hungary", "Ireland", "Italy", "Latvia", "Lithuania", "Luxembourg", "Malta", "Netherlands", "Poland", "Portugal", "Romania", "Slovakia", "Slovenia", "Spain", "Sweden", "United Kingdom" }; var countryField = input.GetOrderField("ToStationCountry"); var country = countryField != null ? countryField.ToString() : ""; var isEUCountry = countriesGroup.Any(c => c == country); return isEUCountry ? "Yes" : "No"; }))();
Add a self-quarantine message if arriving from a certain country or station
1 2 3 4 5 6 7 8 9 10 11 ((Func<string>)(() => { var fromCountries = new string[] { "albania", "austria", "bahrain", "brazil", "colombia", "czech republic", "estonia", "ireland", "israel", "latvia", "lebanon", "lithuania", "malta", "monaco", "montenegro", "netherlands", "panama", "portugal", "saint lucia", "saint vincent and the grenadines", "repubblica di san marino", "serbia", "seychelles", "slovakia", "slovenia", "south africa", "spain", "sweden", "united Aarab emirates", "united kingdom", "united states of america" }; var fromICAOs = new string[] { "EDUB", "EDBM", "EDCB", "EDAD", "EDAQ", "EDDE", "LIPY", "LIBF", "LIBD", "LIBR", "LIBN", "LIRZ", "LIPE", "LIMP", "LIPK", "LIPD", "LIPQ", "LIPG", "NTAA", "LFOO", "LFOQ", "LFLD", "LFOR", "LFEJ", "LFLX", "LFOJ", "LFPZ", "LFEN", "LFOT", "LFAY", "LFQD", "LFOB", "LFAF", "LFQQ", "LFPG", "LFPB", "LFPO", "LFOH", "LFOY", "LFMU", "LFMK", "LFMT", "LFNG", "LFME", "LFTW", "LFMP", "LFBF", "LFBO", "LFCL", "LFIO", "LFIT", "LFBH", "LFBR", "LFBI", "LFBL", "LFXF", "LFBV", "LFBD", "LFCS", "LFDO", "LFDY", "LFYQ", "LFBA", "LFBP", "LFBZ", "LFRS", "LFRA", "LFRM", "LFOV", "LFRI", "LFMV", "LFNT", "LFMD", "LFTG", "LFNA", "LFML", "LFMN", "LFTN", "LFTS" }; var paxIn = (int?)input.GetOrderField("PaxCountIn") ?? 0; var countryField = input.GetOrderField("FromStationCountry"); var country = countryField != null ? countryField.ToString().ToLower() : ""; var fromICAOField = input.GetOrderField("FromICAO"); var fromICAO = fromICAOField != null ? fromICAOField.ToString().ToUpper() : ""; return (paxIn > 0 && (fromCountries.Any(c => c == country) || fromICAOs.Any(c => c == fromICAO))) ? " * *All passengers arriving from your origin have to undergo a mandatory 10 - day self - quarantine.The Contact Tracing Card(s) have to be physically handed - over to the border control officer.A later completion of the card or a digital version in advance is not allowed in any case.**" : " - "; }))();
Show the arrival on blocks time
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ((Func<string>)(() => { { var onBlockText = (string)input.GetTemplateValue("ArrivalOnBlocksDateTimeUtc"); var indexUtc = onBlockText.IndexOf("(UTC)"); if (indexUtc > 0) { DateTime onBlock; if (DateTime.TryParse(onBlockText.Substring(0, indexUtc), out onBlock)) return $"{ onBlock:HHmm}"; } return ""; } }))();
Show the departure off blocks time
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ((Func<string>)(() => { { var offBlocksText = (string)input.GetTemplateValue("DepartureOffBlocksDateTimeUtc"); var indexOfUtc = offBlocksText.IndexOf("(UTC)"); if (indexOfUtc > 0) { DateTime offBlocks; if (DateTime.TryParse(offBlocksText.Substring(0, indexOfUtc), out offBlocks)) return $"{ offBlocks:HHmm}"; } return ""; } }))();
Show a departure delay (minutes) based upon the STD and final off blocks time
1 2 3 4 5 6 7 8 9 10 11 12 13 ((Func<string>)(() => { var result = "~~"; var StdTime = (DateTime?)input.GetOrderField("StdDateTime"); var FinalOffBlocksDateTimeUtc = (DateTime?)input.GetOrderField("FinalOffBlocksDateTimeUtc"); if (StdTime.HasValue && FinalOffBlocksDateTimeUtc.HasValue && FinalOffBlocksDateTimeUtc.Value > StdTime.Value) { var depDelayMinutes = (FinalOffBlocksDateTimeUtc.Value - StdTime.Value).Duration().TotalMinutes; return $"{depDelayMinutes:0}"; } else { result = "0"; } return result; }))();
Show an arrival or departure delay (whichever is greater) (in minutes) based upon the STA and initial off blocks time, and the STD and final off blocks time
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ((Func<string>)(() => { var staTime = (DateTime?)input.GetOrderField("StaDateTime"); var initialOnBlocksDateTimeUtc = (DateTime?)input.GetOrderField("InitialOnBlocksDateTimeUtc"); double arrDelayMinutes = 0; if (staTime.HasValue && initialOnBlocksDateTimeUtc.HasValue && staTime < initialOnBlocksDateTimeUtc) arrDelayMinutes = (initialOnBlocksDateTimeUtc.Value - staTime.Value).Duration().TotalMinutes; var stdTime = (DateTime?)input.GetOrderField("StdDateTime"); var finalOffBlocksDateTimeUtc = (DateTime?)input.GetOrderField("FinalOffBlocksDateTimeUtc"); double depDelayMinutes = 0; if (stdTime.HasValue && finalOffBlocksDateTimeUtc.HasValue && finalOffBlocksDateTimeUtc > stdTime) depDelayMinutes = (finalOffBlocksDateTimeUtc.Value - stdTime.Value).Duration().TotalMinutes; double delay = arrDelayMinutes; if (depDelayMinutes > arrDelayMinutes) delay = depDelayMinutes; return $"{delay:0}"; }))()

Baggage

Show baggage pieces in
1 2 3 4 5 6 7 8 9 10 ((Func<string>)(() => { { var orderField = (int?)input.GetOrderField("BaggagePiecesIn"); if (!orderField.HasValue) return "-"; else return orderField.Value + ""; } }))();
Show baggage pieces out
1 2 3 4 5 6 7 8 9 10 ((Func<string>)(() => { { var orderField = (int?)input.GetOrderField("BaggagePiecesOut"); if (!orderField.HasValue) return "-"; else return orderField.Value + ""; } }))();
Setup Baggage Weight in Kilogram and Baggage Pieces Custom Values For Mvt Messages
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 using FboOne.Client; using FboOne.ServiceModel; using System; using System.Collections.Generic; using System.Linq; namespace FboOne.Scripts { ///PPP-3517 Add baggagepieces as template variable for movement messages (workaround with custom variables) public class BaggageCustomValuesSetup { private TableEntry OrderTableEntry; private List<CustomProperty> CustomProperties; private List<CustomValue> CustomValues; private List<CustomPropertyTable> CustomPropertyTables; private const string Kilogram = "kg"; private const string Pound = "lb"; private const string BagWeightArrivalKg = "BagWeightArrivalKg"; private const string BagWeightArrivalLb = "BagWeightArrivalLb"; private const string BagWeightDepartureKg = "BagWeightDepartureKg"; private const string BagWeightDepartureLb = "BagWeightDepartureLb"; private const string BagPiecesArrival = "BagPiecesArrival"; private const string BagPiecesDeparture = "BagPiecesDeparture"; public void Main() { SetupBaggageWeigthInKg(); SetupBaggagePieces(); } public void SetupBaggageWeigthInKg() { LoadRepositories(); CreateCustomValue( customPropertyName: BagWeightArrivalKg, customPropertyDescription: "Baggage weigth at arrival (kg)", customValueFormula: WeightFormula(orderField: "BaggageWeightIn", unit: Kilogram)); CreateCustomValue( customPropertyName: BagWeightDepartureKg, customPropertyDescription: "Baggage weigth at departure (kg)", customValueFormula: WeightFormula(orderField: "BaggageWeightOut", unit: Kilogram)); } public void SetupBaggageWeigthInLb() { LoadRepositories(); CreateCustomValue( customPropertyName: BagWeightArrivalLb, customPropertyDescription: "Baggage weigth at arrival (lb)", customValueFormula: WeightFormula(orderField: "BaggageWeightIn", unit: Pound)); CreateCustomValue( customPropertyName: BagWeightDepartureLb, customPropertyDescription: "Baggage weigth at departure (lb)", customValueFormula: WeightFormula(orderField: "BaggageWeightOut", unit: Pound)); } public void SetupBaggagePieces() { LoadRepositories(); CreateCustomValue( customPropertyName: BagPiecesArrival, customPropertyDescription: "Baggage pieces at arrival", customValueFormula: PiecesFormula(orderField: "BaggagePiecesIn")); CreateCustomValue( customPropertyName: BagPiecesDeparture, customPropertyDescription: "Baggage pieces at departure", customValueFormula: PiecesFormula(orderField: "BaggagePiecesOut")); } public void Remove() { LoadRepositories(); RemoveCustomValue(BagWeightArrivalKg); RemoveCustomValue(BagWeightArrivalLb); RemoveCustomValue(BagWeightDepartureKg); RemoveCustomValue(BagWeightDepartureLb); RemoveCustomValue(BagPiecesArrival); RemoveCustomValue(BagPiecesDeparture); } private void LoadRepositories() { CustomProperties = CustomPropertyRepository.Get(); CustomValues = CustomValueRepository.Get(); CustomPropertyTables = CustomPropertyTableRepository.Get(); OrderTableEntry = TableEntryRepository.Get().Single(t => t.NameInDatabase == "Order"); } private void RemoveCustomValue(string customProperyName) { var customProperty = CustomProperties.SingleOrDefault(p => p.Name.Equals(customProperyName, StringComparison.InvariantCultureIgnoreCase)); if (customProperty != null) { customProperty.DefaultCustomValueId = null; customProperty.Save(); var customTables = CustomPropertyTables.Where(c => c.CustomPropertyId == customProperty.Id); foreach (var customTable in customTables) customTable.Delete(); var values = CustomValues.Where(v => v.CustomPropertyId == customProperty.Id); foreach (var value in values) value.Delete(); customProperty.Delete(); } } private string WeightFormula(string orderField, string unit) { var poundConvertion = (unit != Pound) ? "" : "* 2.2046226218"; var formula = $@"((Func<string>)(() => {{ {{ var orderField = (int?)input.GetOrderField(""{orderField}""); if (!orderField.HasValue) return ""-""; else return String.Format(""{{0:0.00}}"", orderField.Value {poundConvertion}) + "" {unit}""; }} }}))();"; return formula; } private string PiecesFormula(string orderField) { var formula = $@"((Func<string>)(() => {{ {{ var orderField = (int?)input.GetOrderField(""{orderField}""); if (!orderField.HasValue) return ""-""; else return orderField.Value + """"; }} }}))();"; return formula; } private void CreateCustomValue(string customPropertyName, string customPropertyDescription, string customValueFormula) { if (!CustomProperties.Any(c => c.Name == customPropertyName)) { var customProperty = new CustomProperty { Name = customPropertyName, Description = customPropertyDescription, IsVisibleInOrderScreen = false, IsFreeTextField = false }.Save(); if (!CustomValues.Any(c => c.CustomPropertyId == customProperty.Id && c.Formula == customValueFormula)) { var customValue = new CustomValue { Value = "-", CustomPropertyId = customProperty.Id, Formula = customValueFormula, IsActive = true }.Save(); customProperty.DefaultCustomValueId = customValue.Id; customProperty.Save(); } if (!CustomPropertyTables.Any(c => c.TableDictionaryEntryId == OrderTableEntry.Id && c.CustomPropertyId == customProperty.Id)) { new CustomPropertyTable { TableDictionaryEntryId = OrderTableEntry.Id, CustomPropertyId = customProperty.Id }.Save(); } } } } }
Setup Baggage Weight in Pounds and Baggage Pieces Custom Values For Mvt Messages
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 using FboOne.Client; using FboOne.ServiceModel; using System; using System.Collections.Generic; using System.Linq; namespace FboOne.Scripts { ///PPP-3517 Add baggagepieces as template variable for movement messages (workaround with custom variables) public class BaggageCustomValuesSetup { private TableEntry OrderTableEntry; private List<CustomProperty> CustomProperties; private List<CustomValue> CustomValues; private List<CustomPropertyTable> CustomPropertyTables; private const string Kilogram = "kg"; private const string Pound = "lb"; private const string BagWeightArrivalKg = "BagWeightArrivalKg"; private const string BagWeightArrivalLb = "BagWeightArrivalLb"; private const string BagWeightDepartureKg = "BagWeightDepartureKg"; private const string BagWeightDepartureLb = "BagWeightDepartureLb"; private const string BagPiecesArrival = "BagPiecesArrival"; private const string BagPiecesDeparture = "BagPiecesDeparture"; public void Main() { SetupBaggageWeigthInLb(); SetupBaggagePieces(); } public void SetupBaggageWeigthInKg() { LoadRepositories(); CreateCustomValue( customPropertyName: BagWeightArrivalKg, customPropertyDescription: "Baggage weigth at arrival (kg)", customValueFormula: WeightFormula(orderField: "BaggageWeightIn", unit: Kilogram)); CreateCustomValue( customPropertyName: BagWeightDepartureKg, customPropertyDescription: "Baggage weigth at departure (kg)", customValueFormula: WeightFormula(orderField: "BaggageWeightOut", unit: Kilogram)); } public void SetupBaggageWeigthInLb() { LoadRepositories(); CreateCustomValue( customPropertyName: BagWeightArrivalLb, customPropertyDescription: "Baggage weigth at arrival (lb)", customValueFormula: WeightFormula(orderField: "BaggageWeightIn", unit: Pound)); CreateCustomValue( customPropertyName: BagWeightDepartureLb, customPropertyDescription: "Baggage weigth at departure (lb)", customValueFormula: WeightFormula(orderField: "BaggageWeightOut", unit: Pound)); } public void SetupBaggagePieces() { LoadRepositories(); CreateCustomValue( customPropertyName: BagPiecesArrival, customPropertyDescription: "Baggage pieces at arrival", customValueFormula: PiecesFormula(orderField: "BaggagePiecesIn")); CreateCustomValue( customPropertyName: BagPiecesDeparture, customPropertyDescription: "Baggage pieces at departure", customValueFormula: PiecesFormula(orderField: "BaggagePiecesOut")); } public void Remove() { LoadRepositories(); RemoveCustomValue(BagWeightArrivalKg); RemoveCustomValue(BagWeightArrivalLb); RemoveCustomValue(BagWeightDepartureKg); RemoveCustomValue(BagWeightDepartureLb); RemoveCustomValue(BagPiecesArrival); RemoveCustomValue(BagPiecesDeparture); } private void LoadRepositories() { CustomProperties = CustomPropertyRepository.Get(); CustomValues = CustomValueRepository.Get(); CustomPropertyTables = CustomPropertyTableRepository.Get(); OrderTableEntry = TableEntryRepository.Get().Single(t => t.NameInDatabase == "Order"); } private void RemoveCustomValue(string customProperyName) { var customProperty = CustomProperties.SingleOrDefault(p => p.Name.Equals(customProperyName, StringComparison.InvariantCultureIgnoreCase)); if (customProperty != null) { customProperty.DefaultCustomValueId = null; customProperty.Save(); var customTables = CustomPropertyTables.Where(c => c.CustomPropertyId == customProperty.Id); foreach (var customTable in customTables) customTable.Delete(); var values = CustomValues.Where(v => v.CustomPropertyId == customProperty.Id); foreach (var value in values) value.Delete(); customProperty.Delete(); } } private string WeightFormula(string orderField, string unit) { var poundConvertion = (unit != Pound) ? "" : "* 2.2046226218"; var formula = $@"((Func<string>)(() => {{ {{ var orderField = (int?)input.GetOrderField(""{orderField}""); if (!orderField.HasValue) return ""-""; else return String.Format(""{{0:0.00}}"", orderField.Value {poundConvertion}) + "" {unit}""; }} }}))();"; return formula; } private string PiecesFormula(string orderField) { var formula = $@"((Func<string>)(() => {{ {{ var orderField = (int?)input.GetOrderField(""{orderField}""); if (!orderField.HasValue) return ""-""; else return orderField.Value + """"; }} }}))();"; return formula; } private void CreateCustomValue(string customPropertyName, string customPropertyDescription, string customValueFormula) { if (!CustomProperties.Any(c => c.Name == customPropertyName)) { var customProperty = new CustomProperty { Name = customPropertyName, Description = customPropertyDescription, IsVisibleInOrderScreen = false, IsFreeTextField = false }.Save(); if (!CustomValues.Any(c => c.CustomPropertyId == customProperty.Id && c.Formula == customValueFormula)) { var customValue = new CustomValue { Value = "-", CustomPropertyId = customProperty.Id, Formula = customValueFormula, IsActive = true }.Save(); customProperty.DefaultCustomValueId = customValue.Id; customProperty.Save(); } if (!CustomPropertyTables.Any(c => c.TableDictionaryEntryId == OrderTableEntry.Id && c.CustomPropertyId == customProperty.Id)) { new CustomPropertyTable { TableDictionaryEntryId = OrderTableEntry.Id, CustomPropertyId = customProperty.Id }.Save(); } } } } }

Contact

Add a comment based upon if the debtor has 0 days credit
1 2 3 4 5 6 7 8 9 10 ((Func<string>)(() => { { var creditTermsInDays = (int?)input.GetOrderField("DebtorCredit"); if (creditTermsInDays > 0) return ""; else return "Please provide the credit card details which can be used to guarantee payment of our handling invoice"; } }))();
To define whether the Operator is EEA based or not (Countries list)
1 2 3 4 5 6 7 8 9 10 ((Func<string>)(() => { // EEA countries var countriesGroup = new string[] {"Austria (AT)", "Belgium (BE)", "Bulgaria (BG)", "Croatia (HR)", "Cyprus (CY)", "Czech Republic (CZ)", "Denmark (DK)", "Estonia (EE)", "Finland (FI)", "France (FR)", "Germany (DE)", "Greece (GR)", "Hungary (HU)", "Ireland (IE)", "Italy (IT)", "Latvia (LV)", "Lithuania (LT)", "Luxembourg (LU)", "Malta (MT)", "Netherlands (NL)", "Poland (PL)", "Portugal (PT)", "Romania (RO)", "Slovakia (SK)", "Slovenia (SI)", "Spain (ES)", "Sweden (SE)", "Iceland (IS)", "Liechtenstein (LI)", "Norway (NO)"}; var countryField = input.GetOrderField("OperatorCountry"); var country = countryField != null ? countryField.ToString() : ""; var isEEACountry = countriesGroup.Any(c => c == country); return isEEACountry ? "Yes" : "No"; }))();
Check if an operator has an AOC for commercial flights
1 2 3 4 5 6 7 8 9 10 11 12 13 ((Func<string>)(() => { { var flightTypeIn = (string)input.GetOrderField("FlightTypeIn") ?? ""; var flightTypeOut = (string)input.GetOrderField("FlightTypeOut") ?? ""; var isCommercial = flightTypeIn == "Commercial" || flightTypeOut == "Commercial"; var hasAOC = ((string)input.GetOrderField("OperatorAocNumber") ?? "") != ""; if (isCommercial && !hasAOC) return "Commercial flight must be AOC holders"; else return ""; } }))();

Crew / pax

Calculate the number of security agents required for a flight based on aircraft MTOW above 10,000kgs, departure flight type, and number of departure pax
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 ((Func<string>)(() => { { var flightTypeOut = (string)input.GetOrderField("FlightTypeOut") ?? ""; var mtowKg = (int?)input.GetOrderField("MTOWkg") ?? 0; var paxOut = (int?)input.GetOrderField("PaxCountOut") ?? 0; var flightTypes = new string[] { "qualifying flight" }; if (flightTypes.Contains(flightTypeOut) && mtowKg > 10000 && paxOut > 0) { if (paxOut <= 5) return "5"; if (paxOut <= 15) return "6"; if (paxOut <= 40) return "8"; if (paxOut <= 80) return "9"; return "10"; } else return "0"; } }))();
Calculate a passenger departure fee minus quantity "x" of exempt pax such as infant, military, etc. 

This is combined with another custom value "Departure Pax Tax Exempt"

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ((Func<string>)(() => { var paxTaxExempt = ((string)input.GetCustomValue("Departure Pax Tax Exempt")) ?? ""; var paxTaxExemptCount = 0; int.TryParse(paxTaxExempt, out paxTaxExemptCount); var paxOut = ((int?)input.GetOrderField("PaxCountOut")) ?? 0M; if (paxTaxExemptCount > 0 && paxOut > 0) { var paxToTax = paxOut - paxTaxExemptCount; if (paxToTax < 0) paxToTax = 0; return paxToTax.ToString(); } else if (paxOut > 0) return paxOut.ToString(); else return "0"; }))();

 

Calculate the number of total pax i.e Arrival + Departure
1 2 3 4 5 6 7 8 ((Func<string>)(() => { var paxOut = (int?)input.GetOrderField("PaxCountOut") ?? 0; var paxIn = (int?)input.GetOrderField("PaxCountIn") ?? 0; int total = paxIn + paxOut; return $"{total}"; }))();
Show the PIC and SIC names in the order screen
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ((Func<string>)(() => {{ var crewPICNameIn = (string)input.GetOrderField("PilotNamesIn") +" "; var crewSICNameIn = (string)input.GetOrderField("SecondInCommandNamesIn"); var crewPICNameOut = (string)input.GetOrderField("PilotNamesOut") +" "; var crewSICNameOut = (string)input.GetOrderField("SecondInCommandNamesOut"); var crewIn = "Crew in: "; var crewOut = "Crew out: "; if ( crewPICNameIn == null && crewSICNameIn == null && crewPICNameOut == null && crewSICNameOut == null) { return " "; } return crewIn + crewPICNameIn + crewSICNameIn + Environment.NewLine + crewOut + crewPICNameOut + crewSICNameOut; }}))();
Return Yes/No based on Origin and Pax Count In >0
1 2 3 4 5 6 7 8 9 ((Func<string>)(() => { var countriesGroup = new string[] { "Austria", "Belgium", "Czech Republic", "Denmark", "Estonia", "Finland", "France", "Germany", "Greece", "Hungary", "Iceland", "Italy", "Latvia", "Liechtenstein", "Lithuania", "Luxembourg", "Malta", "Netherlands", "Norway", "Poland", "Portugal", "Slovakia", "Slovenia", "Spain", "Sweden", "Switzerland" }; var fromCountry = (input.GetOrderField("FromStationCountry") as string) ?? ""; var PPCountry = countriesGroup.Any(c => c == fromCountry); var hasPax = input.GetOrderField("PaxCountIn") != null && ((int?)input.GetOrderField("PaxCountIn")).Value > 0; var yesOrNoResponse = !PPCountry && hasPax; return yesOrNoResponse ? "Yes" : "No"; }))();
Calculate excess pax count based on MtowKg
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ((Func<string>)(() => { int paxIn = ((int?)input.GetOrderField("PaxCountIn")) ?? 0; int paxOut = ((int?)input.GetOrderField("PaxCountOut")) ?? 0; int mtowKg = ((int?)input.GetOrderField("MTOWkg")) ?? 0; var pax = Math.Max(paxIn, paxOut); var paxLimit = 0; if (mtowKg < 15000) paxLimit = 8; else if (mtowKg < 45000) paxLimit = 12; else paxLimit = 15; var additionalPax = 0; if (pax > paxLimit) additionalPax = pax - paxLimit; return $"{additionalPax:0}"; }))();
Pax count in excluding transit pax
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ((Func<string>)(() => { var paxTaxExempt = ((string)input.GetCustomValue("Transit Pax")) ?? ""; var paxTaxExemptCount = 0; int.TryParse(paxTaxExempt, out paxTaxExemptCount); var paxOut = ((int?)input.GetOrderField("PaxCountOut")) ?? 0M; if (paxTaxExemptCount > 0 && paxOut > 0) { var paxToTax = paxOut - paxTaxExemptCount; if (paxToTax < 0) paxToTax = 0; return paxToTax.ToString(); } else if (paxOut > 0) return paxOut.ToString(); else return "0"; }))();
Pax count out excluding transit pax
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ((Func<string>)(() => { var paxTaxExempt = ((string)input.GetCustomValue("Transit Pax")) ?? ""; var paxTaxExemptCount = 0; int.TryParse(paxTaxExempt, out paxTaxExemptCount); var paxOut = ((int?)input.GetOrderField("PaxCountOut")) ?? 0M; if (paxTaxExemptCount > 0 && paxOut > 0) { var paxToTax = paxOut - paxTaxExemptCount; if (paxToTax < 0) paxToTax = 0; return paxToTax.ToString(); } else if (paxOut > 0) return paxOut.ToString(); else return "0"; }))();

Custom value

Convert a Kg based custom value into per 100kgs custom value
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ((Func<string>)(() => { var inboundCargo = ((string)input.GetCustomValue("Cargo-In-Kgs")) ?? ""; if (inboundCargo.Trim() == "") return "0"; else { decimal cargoInKgs = 0; decimal.TryParse(inboundCargo, out cargoInKgs); return Math.Ceiling(cargoInKgs/100) + ""; } }))();

 

 

 

1 2 3 4 5 6 7 8 ((Func<string>)(() => { int mtowKg = ((int?)input.GetOrderField("MTOWkg")) ?? 0; if (mtowKg < 45500) return ""; else return "Screening Required"; }))();
Add text-based upon if a custom value is set or left blank

The below formula looks for the custom value, if the custom value is set, it will return the value of the custom value. If no custom value is set it will add a default text e.g Interest 2.5% Per Month will be charged for any outstanding payment.

1 2 3 4 5 6 7 8 ((Func<string>)(() => { var interestRateMention = input.GetCustomValue("Interest Rates") ?? ""; if (string.IsNullOrEmpty(interestRateMention)) return "Interest 2.5% Per Month will be charged for any outstanding payment."; else return interestRateMention ; }))();

Flight type

Display custom text on the Handling Confirmation Email Body when specific Flight Types are used:

Example: Comments/Info to display when Flight Type is 'Medical'

  • Create a Custom Property e.g 'Medical Flight Comments'

  • Add a custom value and in the 'formula' field add the below formula

  • Under 'Email Message Settings' > 'HnConfirmationEmailBody' insert the custom value as required within the email body. e.g. as format ~Custom-Medical Flight Comments~

1 2 3 4 5 6 7 8 9 10 11 12 13 ((Func<string>)(() => { { var medicalFlight = new [] {"medical","medical (private)"}; string currentFlightType = (string)input.GetOrderField("FlightTypeIn"); if (medicalFlight.Contains(currentFlightType.ToLower())) { return "**Please note we are not equipped to handle hazmat flights or medical waste**"; } else return "~~"; } }))();

Fuel

Calculate total fuel volume sold
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ((Func<string>)(() => { { decimal soldFuel = 0M; var soldFuelText = input.GetTemplateValue("SoldFuelVolumeInAllRelatedOrders-AVGAS - BGR"); decimal.TryParse(soldFuelText, out soldFuel); if (soldFuel == 0M) { soldFuelText = input.GetTemplateValue("SoldFuelVolumeInAllRelatedOrders-JET A - BGR"); decimal.TryParse(soldFuelText, out soldFuel); } return soldFuelText; } }))();
Minimum fuel uplift

Minimum fuel amount based upon MGLW of an aircraft.

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 ((Func<string>)(() => { var minFuel = 0M; var mglwLbsText = input.GetCustomValue(""MGLW(lbs)""); decimal mglwLbs = 0; if (decimal.TryParse(mglwLbsText, out mglwLbs)) { if (mglwLbs < 10001) minFuel = 0; else if (mglwLbs < 25001) minFuel = 50; else if (mglwLbs < 45001) minFuel = 200; else if (mglwLbs < 70001) minFuel = 500; else if (mglwLbs < 99001) minFuel = 850; else if (mglwLbs < 115001) minFuel = 1000; else if (mglwLbs < 185001) minFuel = 2200; else if (mglwLbs < 350001) minFuel = 3500; else minFuel = 4500; } string minFuelText = minFuel.ToString(); return minFuelText; }))();
Minimum fuel fee percentage rate
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 ((Func<string>)(() => { { decimal soldFuel = 0M; var soldFuelText = input.GetTemplateValue("SoldFuelVolumeInAllRelatedOrders-JET A - KDAL"); decimal.TryParse(soldFuelText, out soldFuel); if (soldFuel == 0M) { soldFuelText = input.GetTemplateValue("SoldFuelVolumeInAllRelatedOrders-AVGAS - KDAL"); decimal.TryParse(soldFuelText, out soldFuel); } var minFuelText = input.GetCustomValue("Min Fuel"); decimal minFuel = 0; if (soldFuel == 0) return "1.00"; if (decimal.TryParse(minFuelText, out minFuel)) { var percentage = 0M; if (minFuel != 0M) { percentage = (soldFuel * 100) / minFuel; if (percentage <= 25) percentage = 25; else if (percentage <= 50) percentage = 50; else if (percentage <= 75) percentage = 75; else percentage = 100; var minFeeToPay = 100 - percentage; return $"{minFeeToPay / 100:0.00}"; } } return "1.00"; // full rate } }))();

Slots

Display a Warning message for In/Outbound Airport Slots when the Arrival/Departure times fall outside of the specified tolerance  
  • Create 2 Custom Properties e.g Inbound Slot Warning / Outbound Slot Warning. Ensure the check box 'Is visible in Order Screen' is checked so that the warning also displays within the order as a warning to users as well

  • Add a Custom Value to each of the Custom Properties, and in the 'formula' fields add the below formulas (these are just examples - see page: 'How to display warnings when Airport Slots fall outside of a designated window of tolerance' for further details on how to customize this accordingly)

  • Ensure the Custom Properties/Values are linked to the 'Order' table

  • These Custom Values can then be added for example to the HandlingConfirmationTextOnly or HnConfirmationEmailBody to display the warning within the email itself.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ((Func<string>)(() => { var result = "~~"; // this will make the output of the template variable to be an empty text instead of '-' var inSlotLt = (DateTime?)input.GetOrderField("AirportSlotInDateTimeLt"); if (inSlotLt.HasValue) { var arrivalText = (string)input.GetTemplateValue("MostActualArrivalTimeLTOrPendingTextWithoutSlots"); if (!string.IsNullOrEmpty(arrivalText)) { var indexOfLt = arrivalText.IndexOf("(LT)"); if (indexOfLt > 0) { DateTime arrivallt; if (DateTime.TryParse(arrivalText.Substring(0, indexOfLt), out arrivallt)) { if ((arrivallt - inSlotLt.Value).Duration().TotalMinutes > 15) result = "Warning - Requested arrival time is outside the permitted slot tolerance ± 15mins"; } } } } return result; }))();
Outbound Slot Tolerance Warning
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 (((Func<string>)(() => { var result = "~~"; // this will make the output of the template variable to be an empty text instead of '-' var outSlotLt = (DateTime?)input.GetOrderField("AirportSlotOutDateTimeLt"); if (outSlotLt.HasValue) { var departureText = (string)input.GetTemplateValue("MostActualDepartureTimeLTOrPendingTextWithoutSlots"); if (!string.IsNullOrEmpty(departureText)) { var indexOfLt = departureText.IndexOf("(LT)"); if (indexOfLt > 0) { DateTime departurelt; if (DateTime.TryParse(departureText.Substring(0, indexOfLt), out departurelt)) { if ((departurelt - outSlotLt.Value).Duration().TotalMinutes > 15) result = "Warning - Requested departure time is outside the permitted slot tolerance ± 15mins"; } } } } return result; }))();
Display Arrival Date/Time in format ddMMM (e.g. 04JAN) for use in e.g. Slot Requests
1 2 3 4 5 ((Func<string>)(() => {{ var dateFormat = "ddMMM"; var mostActualArrivalDateTime = (DateTime?)input.GetOrderField("MostActualArrivalDateTime"); return mostActualArrivalDateTime.HasValue ? mostActualArrivalDateTime.Value.ToString(dateFormat).ToUpper() : ""; }}))();
Define a "period code" based on arrival date which can be used in Slot Requests e.g. Winter 2017 = W17 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ((Func<string>)(() => { // If Month is JAN, FEB or MAR display W followed by Year-1 e.g Jan-17 = W16 // If Month is APR, MAY, JUN, JUL, AUG or SEP display S followed by current year e.g S17 // If Month is OCT, NOV or DEC display W followed by current year e.g W17 var result = "~~"; var arrivalDateTime = (DateTime?)input.GetOrderField("MostActualArrivalDateTimeLT"); if (arrivalDateTime.HasValue) { var month = arrivalDateTime.Value.Month; var year = arrivalDateTime.Value.Year - 2000; // to get 17, 18 .. etc if (year < 17) return result; if (month <= 3) result = $"W{year - 1}"; if (month >= 4 && month <= 9) result = $"S{year}"; if (month > 9) result = $"W{year}"; } return result; }))();
Create a 4-digit Slot number using the Order Key

NOTE: This formula always uses the last 4-digits of the Order key and the number is not unique e.g. Order Key FBO-4 = 0004 and FBO-10004 =0004.
The formula adds zeros as padding whereby the Order Key is below 1000

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 ((Func<string>)(() => { { // generate slot numbers based on order number. // Slot numbers must be max 4 digits and different than 0000 // it is OK if they are re-use string number = input.GetOrderField("PrimaryOrderNumber").ToString(); if (number.Length > 4) { // 10 000 => 0000; 10 001 => 0001; etc var slotNumber = number.Substring(number.Length-4, 4); // it is OK to re-use numbers but we need to avoid '0000' if (slotNumber == "0000") slotNumber = "1000"; return slotNumber; } else { // 1000 => 1000; 100 => 0100 var length = 4 - number.Length; var zeros = ""; if (length > 0) zeros = new string('0', length); var slotNumber = zeros + number; return slotNumber; } } }))();