Skip to content

Commit

Permalink
Merge pull request #1951 from UKHomeOffice/DRTII-1683-API-update-for-ES
Browse files Browse the repository at this point in the history
Drtii 1683 api update for es
  • Loading branch information
richbirch authored Nov 13, 2024
2 parents 85f433f + d6bb7bf commit 832f5c8
Show file tree
Hide file tree
Showing 14 changed files with 59 additions and 37 deletions.
2 changes: 1 addition & 1 deletion client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions server/src/main/resources/routes
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,11 @@ GET /api/passengers/:startLocalDate/:endLocalDate/:terminalName
PUT /api/passengers/:localDate controllers.application.SummariesController.populatePassengersForDate(localDate: String)

GET /api/v1/queues controllers.application.api.v1.QueuesApiController.queues()
+ nocsrf
PUT /api/v1/queues/:startDateLocal/:endDateLocal controllers.application.api.v1.QueuesApiController.populateQueues(startDateLocal: String, endDateLocal: String)

GET /api/v1/flights controllers.application.api.v1.FlightsApiController.flights()
+ nocsrf
PUT /api/v1/flights/:startDateLocal/:endDateLocal controllers.application.api.v1.FlightsApiController.populateFlights(startDateLocal: String, endDateLocal: String)

GET /debug/flights/:persistenceId/:dateString/:messages controllers.application.DebugController.getMessagesForFlightPersistenceIdAtTime(persistenceId: String, dateString: String, messages: Int)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package controllers.application
import com.google.inject.Inject
import drt.shared._
import play.api.mvc.{Action, AnyContent, ControllerComponents}
import services.AirportToCountry
import services.AirportInfoService
import uk.gov.homeoffice.drt.auth.Roles.ArrivalsAndSplitsView
import uk.gov.homeoffice.drt.crunchsystem.DrtSystemInterface
import uk.gov.homeoffice.drt.ports.PortCode
Expand All @@ -19,7 +19,7 @@ class AirportInfoController @Inject()(cc: ControllerComponents, ctrl: DrtSystemI
.flatMap(_.headOption)
.map(codes => codes
.split(",")
.map(code => (PortCode(code), AirportToCountry.airportInfoByIataPortCode.get(code)))
.map(code => (PortCode(code), AirportInfoService.airportInfoByIataPortCode.get(code)))
.collect {
case (code, Some(info)) => (code, info)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import akka.pattern.ask
import com.google.inject.Inject
import drt.shared._
import play.api.mvc.{Action, AnyContent, ControllerComponents}
import services.AirportToCountry
import services.AirportInfoService
import spray.json.{DefaultJsonProtocol, JsArray, JsNumber, JsObject, JsString, JsValue, RootJsonFormat, enrichAny}
import uk.gov.homeoffice.drt.actor.commands.Commands.GetState
import uk.gov.homeoffice.drt.crunchsystem.DrtSystemInterface
Expand All @@ -21,7 +21,7 @@ class RedListsController@Inject()(cc: ControllerComponents, ctrl: DrtSystemInter
Action.async { _ =>
ctrl.applicationService.redListUpdatesActor.ask(GetState).mapTo[RedListUpdates].map { redListUpdates =>
val forDate = SDate(dateString, europeLondonTimeZone).millisSinceEpoch
val redListPorts = AirportToCountry.airportInfoByIataPortCode.values.collect {
val redListPorts = AirportInfoService.airportInfoByIataPortCode.values.collect {
case AirportInfo(_, _, country, portCode) if redListUpdates.countryCodesByName(forDate).contains(country) =>
PortCode(portCode)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import services.api.v1.FlightExport
import services.api.v1.serialisation.FlightApiJsonProtocol
import spray.json.enrichAny
import uk.gov.homeoffice.drt.arrivals.{Arrival, FlightsWithSplits}
import uk.gov.homeoffice.drt.auth.Roles.{ApiFlightAccess, ApiQueueAccess}
import uk.gov.homeoffice.drt.auth.Roles.{ApiFlightAccess, ApiQueueAccess, SuperAdmin}
import uk.gov.homeoffice.drt.crunchsystem.DrtSystemInterface
import uk.gov.homeoffice.drt.ports.FeedSource
import uk.gov.homeoffice.drt.ports.Terminals.Terminal
Expand Down Expand Up @@ -63,7 +63,7 @@ class FlightsApiController @Inject()(cc: ControllerComponents, ctrl: DrtSystemIn
}

def populateFlights(start: String, end: String): Action[AnyContent] =
authByRole(ApiQueueAccess) {
authByRole(SuperAdmin) {
Action {
val startDate = UtcDate.parse(start).getOrElse(throw new Exception("Invalid start date"))
val endDate = UtcDate.parse(end).getOrElse(throw new Exception("Invalid end date"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import providers.MinutesProvider
import services.api.v1.QueueExport
import services.api.v1.serialisation.QueueApiJsonProtocol
import spray.json.enrichAny
import uk.gov.homeoffice.drt.auth.Roles.ApiQueueAccess
import uk.gov.homeoffice.drt.auth.Roles.{ApiQueueAccess, SuperAdmin}
import uk.gov.homeoffice.drt.crunchsystem.DrtSystemInterface
import uk.gov.homeoffice.drt.model.{CrunchMinute, TQM}
import uk.gov.homeoffice.drt.ports.Queues
Expand Down Expand Up @@ -55,7 +55,7 @@ class QueuesApiController @Inject()(cc: ControllerComponents, ctrl: DrtSystemInt
}

def populateQueues(start: String, end: String): Action[AnyContent] =
authByRole(ApiQueueAccess) {
authByRole(SuperAdmin) {
Action {
val startDate = UtcDate.parse(start).getOrElse(throw new Exception("Invalid start date"))
val endDate = UtcDate.parse(end).getOrElse(throw new Exception("Invalid end date"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import uk.gov.homeoffice.drt.redlist.RedListUpdates
import scala.io.Codec
import scala.util.Try

object AirportToCountry {
object AirportInfoService {

lazy val airportInfoByIataPortCode: Map[String, AirportInfo] = {
val bufferedSource = scala.io.Source.fromURL(getClass.getResource("/airports.dat"))(Codec.UTF8)
Expand All @@ -24,6 +24,8 @@ object AirportToCountry {
}.map(ai => (ai.code, ai)).toMap
}

def airportInfo(code: PortCode): Option[AirportInfo] = airportInfoByIataPortCode.get(code.iata)

def stripQuotes(row1: String): String = {
row1.substring(1, row1.length - 1)
}
Expand Down
24 changes: 15 additions & 9 deletions server/src/main/scala/services/api/v1/FlightExport.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package services.api.v1

import akka.NotUsed
import akka.stream.Materializer
import akka.stream.scaladsl.{Sink, Source}
import services.AirportInfoService
import uk.gov.homeoffice.drt.arrivals.Arrival
import uk.gov.homeoffice.drt.ports.Terminals.Terminal
import uk.gov.homeoffice.drt.ports.{FeedSource, PortCode}
Expand All @@ -15,8 +15,11 @@ import scala.util.Try
object FlightExport {

case class FlightJson(code: String,
originPort: String,
originPortIata: String,
originPortName: String,
scheduledTime: Long,
estimatedLandingTime: Option[Long],
actualChocksTime: Option[Long],
estimatedPcpStartTime: Option[Long],
estimatedPcpEndTime: Option[Long],
estimatedPaxCount: Option[Int],
Expand All @@ -26,13 +29,16 @@ object FlightExport {
object FlightJson {
def apply(ar: Arrival)
(implicit sourceOrderPreference: List[FeedSource]): FlightJson = FlightJson(
ar.flightCodeString,
ar.Origin.iata,
ar.Scheduled,
Try(ar.pcpRange(sourceOrderPreference).min).toOption,
Try(ar.pcpRange(sourceOrderPreference).max).toOption,
ar.bestPcpPaxEstimate(sourceOrderPreference),
ar.Status.description,
code = ar.flightCodeString,
originPortIata = ar.Origin.iata,
originPortName = AirportInfoService.airportInfo(ar.Origin).map(_.airportName).getOrElse("n/a"),
scheduledTime = ar.Scheduled,
estimatedLandingTime = ar.Estimated,
actualChocksTime = ar.ActualChox,
estimatedPcpStartTime = Try(ar.pcpRange(sourceOrderPreference).min).toOption,
estimatedPcpEndTime = Try(ar.pcpRange(sourceOrderPreference).max).toOption,
estimatedPaxCount = ar.bestPcpPaxEstimate(sourceOrderPreference),
status = ar.displayStatus.description,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ trait FlightApiJsonProtocol extends DefaultJsonProtocol {
val maybePax = obj.estimatedPaxCount.filter(_ > 0)
JsObject(
"code" -> obj.code.toJson,
"originPort" -> obj.originPort.toJson,
"originPortIata" -> obj.originPortIata.toJson,
"originPortName" -> obj.originPortName.toJson,
"scheduledTime" -> SDate(obj.scheduledTime).toISOString.toJson,
"estimatedLandingTime" -> obj.estimatedLandingTime.map(SDate(_).toISOString).toJson,
"actualChocksTime" -> obj.actualChocksTime.map(SDate(_).toISOString).toJson,
"estimatedPcpStartTime" -> maybePax.flatMap(_ => obj.estimatedPcpStartTime.map(SDate(_).toISOString)).toJson,
"estimatedPcpEndTime" -> maybePax.flatMap(_ => obj.estimatedPcpEndTime.map(SDate(_).toISOString)).toJson,
"estimatedPcpPaxCount" -> obj.estimatedPaxCount.toJson,
Expand All @@ -24,8 +27,11 @@ trait FlightApiJsonProtocol extends DefaultJsonProtocol {
override def read(json: JsValue): FlightJson = json match {
case JsObject(fields) => FlightJson(
fields.get("code").map(_.convertTo[String]).getOrElse(""),
fields.get("originPort").map(_.convertTo[String]).getOrElse(""),
fields.get("originPortIata").map(_.convertTo[String]).getOrElse(""),
fields.get("originPortName").map(_.convertTo[String]).getOrElse(""),
fields.get("scheduledTime").map(_.convertTo[Long]).getOrElse(0L),
fields.get("estimatedLandingTime").map(_.convertTo[Long]),
fields.get("actualChocksTime").map(_.convertTo[Long]),
fields.get("estimatedPcpStartTime").map(_.convertTo[Long]),
fields.get("estimatedPcpEndTime").map(_.convertTo[Long]),
fields.get("estimatedPcpPaxCount").map(_.convertTo[Int]),
Expand All @@ -35,7 +41,7 @@ trait FlightApiJsonProtocol extends DefaultJsonProtocol {
}
}

implicit val flightJsonFormat: RootJsonFormat[FlightJson] = jsonFormat7(FlightJson.apply)
implicit val flightJsonFormat: RootJsonFormat[FlightJson] = jsonFormat10(FlightJson.apply)

implicit object TerminalJsonFormat extends RootJsonFormat[Terminal] {
override def write(obj: Terminal): JsValue = obj.toString.toJson
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package services.exports.flights.templates
import actors.PartitionedPortStateActor.{FlightsRequest, GetFlightsForTerminals}
import drt.shared._
import drt.shared.redlist.{LhrRedListDatesImpl, LhrTerminalTypes}
import services.AirportToCountry
import services.AirportInfoService
import uk.gov.homeoffice.drt.arrivals.ApiFlightWithSplits
import uk.gov.homeoffice.drt.ports.FeedSource
import uk.gov.homeoffice.drt.ports.Terminals._
Expand All @@ -26,7 +26,7 @@ trait LHRFlightsWithSplitsExportWithDiversions extends FlightsExport {
val redListUpdates: RedListUpdates

val directRedListFilter: LhrFlightDisplayFilter =
LhrFlightDisplayFilter(redListUpdates, AirportToCountry.isRedListed, LhrTerminalTypes(LhrRedListDatesImpl))
LhrFlightDisplayFilter(redListUpdates, AirportInfoService.isRedListed, LhrTerminalTypes(LhrRedListDatesImpl))

override val flightsFilter: (ApiFlightWithSplits, Terminal) => Boolean =
directRedListFilter.filterReflectingDivertedRedListFlights
Expand Down
4 changes: 2 additions & 2 deletions server/src/main/scala/services/graphstages/FlightFilter.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package services.graphstages

import drt.shared.redlist.{LhrRedListDatesImpl, LhrTerminalTypes}
import services.AirportToCountry
import services.AirportInfoService
import uk.gov.homeoffice.drt.arrivals.ApiFlightWithSplits
import uk.gov.homeoffice.drt.ports.Terminals.Terminal
import uk.gov.homeoffice.drt.ports.{AirportConfig, PortCode}
Expand All @@ -26,7 +26,7 @@ object FlightFilter {

val lhrRedListFilter: FlightFilter = FlightFilter { (fws, redListUpdates) =>
val isGreenOnlyTerminal = terminalTypes.lhrNonRedListTerminalsForDate(fws.apiFlight.Scheduled).contains(fws.apiFlight.Terminal)
val isRedListOrigin = AirportToCountry.isRedListed(fws.apiFlight.Origin, fws.apiFlight.Scheduled, redListUpdates)
val isRedListOrigin = AirportInfoService.isRedListed(fws.apiFlight.Origin, fws.apiFlight.Scheduled, redListUpdates)
val okToProcess = !isRedListOrigin || !isGreenOnlyTerminal
okToProcess
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package serialization
import drt.shared.CrunchApi._
import drt.shared._
import org.specs2.mutable.Specification
import services.AirportToCountry
import services.AirportInfoService
import uk.gov.homeoffice.drt.Nationality
import uk.gov.homeoffice.drt.arrivals.SplitStyle.Percentage
import uk.gov.homeoffice.drt.arrivals._
Expand Down Expand Up @@ -76,7 +76,7 @@ class JsonSerializationSpec extends Specification {
}

"AirportInfo" >> {
val info: Map[String, AirportInfo] = AirportToCountry.airportInfoByIataPortCode
val info: Map[String, AirportInfo] = AirportInfoService.airportInfoByIataPortCode

val asJson: String = write(info)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import uk.gov.homeoffice.drt.ports.PortCode
import uk.gov.homeoffice.drt.redlist.{RedListUpdate, RedListUpdates}
import uk.gov.homeoffice.drt.time.SDate

object AirportToCountryTests extends SpecificationLike {
object AirportInfoServiceTests$ extends SpecificationLike {
"can load csv" >> {
val result = AirportToCountry.airportInfoByIataPortCode.get("GKA")
val result = AirportInfoService.airportInfoByIataPortCode.get("GKA")
val expected = Some(AirportInfo("Goroka", "Goroka", "Papua New Guinea", "GKA"))
result === expected
}
Expand All @@ -17,7 +17,7 @@ object AirportToCountryTests extends SpecificationLike {
"AirportToCountry should tell me it's a red list port" >> {
val bulawayoAirport = PortCode("BUQ")
val updates = RedListUpdates(Map(0L -> RedListUpdate(0L, Map("Zimbabwe" -> "ZWE"), List())))
AirportToCountry.isRedListed(bulawayoAirport, SDate("2021-08-01T00:00").millisSinceEpoch, updates) === true
AirportInfoService.isRedListed(bulawayoAirport, SDate("2021-08-01T00:00").millisSinceEpoch, updates) === true
}
}
}
Expand Down
17 changes: 11 additions & 6 deletions server/src/test/scala/services/exports/FlightExportSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,30 @@ class FlightExportSpec extends AnyWordSpec with Matchers {

"FlightExport" should {
"return a PortFlightsJson with the correct structure and only the flight with passengers in the requested time range" in {
val sched1 = SDate("2024-10-15T12:00")
val sched2 = SDate("2024-10-15T13:55")
val source = (_: SDateLike, _: SDateLike, _: Terminal) => {
Future.successful(Seq(
ArrivalGenerator.arrival(iata = "BA0001", schDt = "2024-10-15T11:00", totalPax = Option(100), transPax = Option(10), feedSource = LiveFeedSource),
ArrivalGenerator.arrival(iata = "BA0002", schDt = "2024-10-15T12:00", totalPax = Option(100), transPax = Option(10), feedSource = LiveFeedSource),
ArrivalGenerator.arrival(iata = "BA0003", schDt = "2024-10-15T13:55", totalPax = Option(200), transPax = Option(10), feedSource = LiveFeedSource),
ArrivalGenerator.arrival(iata = "BA0002", schDt = sched1.toISOString, estDt = sched1.addMinutes(1).toISOString,
actChoxDt = sched1.addMinutes(5).toISOString, totalPax = Option(100), transPax = Option(10), feedSource = LiveFeedSource),
ArrivalGenerator.arrival(iata = "BA0003", schDt = sched2.toISOString, totalPax = Option(200), transPax = Option(10), feedSource = LiveFeedSource),
ArrivalGenerator.arrival(iata = "BA0004", schDt = "2024-10-15T15:00", totalPax = Option(200), transPax = Option(10), feedSource = LiveFeedSource),
))
}
val export = FlightExport(source, Seq(T1), PortCode("LHR"))
val sched1 = SDate("2024-10-15T12:00")
val sched2 = SDate("2024-10-15T13:55")
Await.result(export(startMinute, endMinute), 1.second) shouldEqual
PortFlightsJson(
PortCode("LHR"),
List(TerminalFlightsJson(
T1,
List(
FlightJson("BA0002", "JFK", sched1.millisSinceEpoch, Some(sched1.addMinutes(5).millisSinceEpoch), Some(sched1.addMinutes(9).millisSinceEpoch), Some(90), ""),
FlightJson("BA0003", "JFK", sched2.millisSinceEpoch, Some(sched2.addMinutes(5).millisSinceEpoch), Some(sched2.addMinutes(14).millisSinceEpoch), Some(190), ""),
FlightJson("BA0002", "JFK", "John F Kennedy Intl", sched1.millisSinceEpoch,
Option(sched1.addMinutes(1).millisSinceEpoch), Option(sched1.addMinutes(5).millisSinceEpoch),
Some(sched1.addMinutes(5).millisSinceEpoch), Some(sched1.addMinutes(9).millisSinceEpoch), Some(90), "On Chocks"),
FlightJson("BA0003", "JFK", "John F Kennedy Intl", sched2.millisSinceEpoch,
None, None,
Some(sched2.addMinutes(5).millisSinceEpoch), Some(sched2.addMinutes(14).millisSinceEpoch), Some(190), "Scheduled"),
)
)
)
Expand Down

0 comments on commit 832f5c8

Please sign in to comment.