Skip to content

Commit

Permalink
WIP: Cleaning up endpoints and responses
Browse files Browse the repository at this point in the history
  • Loading branch information
flashingpumpkin committed Nov 23, 2017
1 parent 6ae6a7f commit dd5dfb7
Show file tree
Hide file tree
Showing 13 changed files with 296 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package uk.gov.hmrc.epayeapi.controllers

import java.util.NoSuchElementException
import javax.inject.{Inject, Singleton}

import akka.stream.Materializer
Expand All @@ -27,32 +28,35 @@ import uk.gov.hmrc.domain.EmpRef
import uk.gov.hmrc.epayeapi.connectors.EpayeConnector
import uk.gov.hmrc.epayeapi.models.Formats._
import uk.gov.hmrc.epayeapi.models.api.{ApiJsonError, ApiNotFound, ApiSuccess}
import uk.gov.hmrc.epayeapi.models.{ApiError, TotalsResponse}
import uk.gov.hmrc.epayeapi.models.{ApiError, SummaryResponse}

import scala.concurrent.ExecutionContext

@Singleton
case class GetTotalsController @Inject()(
case class GetSummaryController @Inject()(
authConnector: AuthConnector,
epayeConnector: EpayeConnector,
implicit val ec: ExecutionContext,
implicit val mat: Materializer
)
extends ApiController {

def getTotals(empRef: EmpRef): EssentialAction = EmpRefAction(empRef) {
def getSummary(empRef: EmpRef): EssentialAction = EmpRefAction(empRef) {
Action.async { request =>
epayeConnector.getTotals(empRef, hc(request)).map {
case ApiSuccess(totals) =>
Ok(Json.toJson(TotalsResponse(empRef, totals)))
case ApiJsonError(err) =>
Logger.error(s"Upstream returned invalid json: $err")
InternalServerError(Json.toJson(ApiError.InternalServerError))
case ApiNotFound() =>
val totalsResp = epayeConnector.getTotals(empRef, hc(request))
val totalsByTypeResp = epayeConnector.getTotalsByType(empRef, hc(request))

val resp = for {
ApiSuccess(totals) <- totalsResp
ApiSuccess(totalsByType) <- totalsByTypeResp
} yield {
Ok(Json.toJson(SummaryResponse(empRef, totals, totalsByType)))
}

// TODO: Revisit and add error handling!
resp.recover {
case ex: NoSuchElementException =>
NotFound(Json.toJson(ApiError.EmpRefNotFound))
case error =>
Logger.error(s"Error while fetching totals: $error")
InternalServerError(Json.toJson(ApiError.InternalServerError))
}
}
}
Expand Down
19 changes: 19 additions & 0 deletions app/uk/gov/hmrc/epayeapi/models/AggregatedTotals.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright 2017 HM Revenue & Customs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package uk.gov.hmrc.epayeapi.models

case class AggregatedTotals(credit: BigDecimal, debit: BigDecimal)
35 changes: 0 additions & 35 deletions app/uk/gov/hmrc/epayeapi/models/AggregatedTotalsByType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,41 +18,6 @@ package uk.gov.hmrc.epayeapi.models

import uk.gov.hmrc.domain.EmpRef

case class AggregatedTotals(credit: BigDecimal, debit: BigDecimal)

case class AggregatedTotalsByType(rti: AggregatedTotals, nonRti: AggregatedTotals)

case class TotalsResponse(
credit: BigDecimal,
debit: BigDecimal,
_links: TotalsLinks
)

object TotalsResponse {
def apply(empRef: EmpRef, totals: AggregatedTotals): TotalsResponse =
TotalsResponse(totals.credit, totals.debit, TotalsLinks(empRef))
}

case class TotalsByTypeResponse(
rti: AggregatedTotals,
non_rti: AggregatedTotals,
_links: TotalsLinks
)

object TotalsByTypeResponse {
def apply(empRef: EmpRef, totals: AggregatedTotalsByType): TotalsByTypeResponse =
TotalsByTypeResponse(
AggregatedTotals(totals.rti.credit, totals.rti.debit),
AggregatedTotals(totals.nonRti.credit, totals.nonRti.debit),
TotalsLinks(empRef)
)
}

case class TotalsLinks(
empRefs: Link
)

object TotalsLinks {
def apply(empRef: EmpRef): TotalsLinks = TotalsLinks(Link.empRefsLink(empRef))
}

32 changes: 10 additions & 22 deletions app/uk/gov/hmrc/epayeapi/models/EmpRefsResponse.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@ package uk.gov.hmrc.epayeapi.models

import uk.gov.hmrc.domain.EmpRef

case class EmpRefsResponse(_embedded: Seq[EmpRefItem])
case class EmpRefsResponse(
empRefs: Seq[EmpRefItem],
_links: EmpRefsLinks
)

object EmpRefsResponse {
def fromSeq(seq: Seq[EmpRef]): EmpRefsResponse =
EmpRefsResponse(seq.map(EmpRefItem(_)))
EmpRefsResponse(seq.map(EmpRefItem(_)), EmpRefsLinks())
def apply(empRef: EmpRef): EmpRefsResponse =
EmpRefsResponse(Seq(EmpRefItem(empRef)))
EmpRefsResponse(Seq(EmpRefItem(empRef)), EmpRefsLinks())
}

case class EmpRefItem(empRef: EmpRef, _links: EmpRefLinks)
Expand All @@ -34,30 +37,15 @@ object EmpRefItem {
EmpRefItem(empRef, EmpRefLinks(empRef))
}

case class EmpRefLinks(totals: Link, byType: Link)
case class EmpRefsLinks(self: Link = Link.empRefsLink())

case class EmpRefLinks(summary: Link)

object EmpRefLinks {
def apply(empRef: EmpRef): EmpRefLinks =
EmpRefLinks(Link.totalLink(empRef),
Link.totalBreakdownLink(empRef))
EmpRefLinks(summary = Link.summaryLink(empRef))
}

case class Link (href: String)

object Link {


val prefix = "/paye-for-employers"

private def apply(empRef: EmpRef, path: String): Link =
Link(s"$prefix/${empRef.taxOfficeNumber}/${empRef.taxOfficeReference}/$path/")

def totalLink(empRef: EmpRef): Link = apply(empRef, "total")
def totalBreakdownLink(empRef: EmpRef): Link = apply(empRef, "total/by-type")
def empRefsLink(empRef: EmpRef): Link = Link(s"$prefix/")
}





Expand Down
65 changes: 65 additions & 0 deletions app/uk/gov/hmrc/epayeapi/models/Example.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright 2017 HM Revenue & Customs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package uk.gov.hmrc.epayeapi.models

object Example extends App {
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.concurrent.Await
import scala.concurrent.duration.Duration
import scala.util.{Success, Failure}

sealed trait Resp
case class Good(i: Int) extends Resp
case class Bad(s: String) extends Resp

object Foo {
def run: Int = {
val first: Future[Resp] = Future.successful(Good(1))
val econd: Future[Resp] = Future.successful(Bad("nope"))


val res = for {
Good(one) <- first
Good(two) <- econd
} yield Good(one + two)

//
// res.onComplete {
// case Success(res) =>
// println("OK")
// res
// case Failure(res) =>
// println(s"Fail: $res")
// res
// }

val finalREsult: Resp = Await.result(res.recover {
case ex: Exception =>
println(ex)
Bad("Exception handler")
}, Duration.Inf)

println(s"Final: $finalREsult")

100
}
}

Foo.run

}
11 changes: 7 additions & 4 deletions app/uk/gov/hmrc/epayeapi/models/Formats.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,17 @@ trait Formats {
override def writes(o: EmpRef): JsValue = JsString(s"${o.taxOfficeNumber}/${o.taxOfficeReference}")
}
implicit val linkFormat: Format[Link] = Json.format[Link]
implicit val empRefLinksFormat: Format[EmpRefLinks] = Json.format[EmpRefLinks]
implicit val empRefItemFormat: Format[EmpRefItem] = Json.format[EmpRefItem]
implicit val empRefsLinksFormat: Format[EmpRefsLinks] = Json.format[EmpRefsLinks]
implicit val empRefLinksFormat: Format[EmpRefLinks] = Json.format[EmpRefLinks]
implicit val empRefItemFormat: Format[EmpRefItem] = Json.format[EmpRefItem]
implicit val empRefsResponseFormat: Format[EmpRefsResponse] = Json.format[EmpRefsResponse]
implicit val apiErrorFormat: Format[ApiError] = Json.format[ApiError]
implicit val aggregatedTotalsFormat: Format[AggregatedTotals] = Json.format[AggregatedTotals]
implicit val aggregatedTotalsByTypeFormat: Format[AggregatedTotalsByType] = Json.format[AggregatedTotalsByType]
implicit val totalsLinksFormat: Format[TotalsLinks] = Json.format[TotalsLinks]
implicit val totalsResponseFormat: Format[TotalsResponse] = Json.format[TotalsResponse]
implicit val breakdown: Format[Breakdown] = Json.format[Breakdown]
implicit val outstandingCharges: Format[OutstandingCharges] = Json.format[OutstandingCharges]
implicit val totalsLinksFormat: Format[SummaryLinks] = Json.format[SummaryLinks]
implicit val totalsResponseFormat: Format[SummaryResponse] = Json.format[SummaryResponse]
implicit val totalsByTypeResponseFormat: Format[TotalsByTypeResponse] = Json.format[TotalsByTypeResponse]
implicit val debitAndCreditFormat: Format[DebitAndCredit] = Json.format[DebitAndCredit]
implicit val clearedFormat: Format[Cleared] = Json.format[Cleared]
Expand Down
31 changes: 31 additions & 0 deletions app/uk/gov/hmrc/epayeapi/models/Link.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2017 HM Revenue & Customs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package uk.gov.hmrc.epayeapi.models

import uk.gov.hmrc.domain.EmpRef

case class Link(href: String)

object Link {
val prefix = "/organisation/paye"

def summaryLink(empRef: EmpRef): Link =
Link(s"$prefix/${empRef.taxOfficeNumber}/${empRef.taxOfficeReference}/")

def empRefsLink(): Link =
Link(s"$prefix/")
}
76 changes: 76 additions & 0 deletions app/uk/gov/hmrc/epayeapi/models/SummaryResponse.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright 2017 HM Revenue & Customs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package uk.gov.hmrc.epayeapi.models

import uk.gov.hmrc.domain.EmpRef

case class Breakdown(
rti: BigDecimal,
nonRti: BigDecimal
)

case class OutstandingCharges(
amount: BigDecimal,
breakdown: Breakdown
)

case class SummaryResponse(
outstandingCharges: OutstandingCharges,
_links: SummaryLinks
)

object SummaryResponse {
def apply(empRef: EmpRef, totals: AggregatedTotals, byType: AggregatedTotalsByType): SummaryResponse =
SummaryResponse(
OutstandingCharges(
totals.debit,
Breakdown(
byType.rti.debit,
byType.nonRti.debit
)
),
SummaryLinks(empRef)
)
}

case class TotalsByTypeResponse(
rti: AggregatedTotals,
non_rti: AggregatedTotals,
_links: SummaryLinks
)

object TotalsByTypeResponse {
def apply(empRef: EmpRef, totals: AggregatedTotalsByType): TotalsByTypeResponse =
TotalsByTypeResponse(
AggregatedTotals(totals.rti.credit, totals.rti.debit),
AggregatedTotals(totals.nonRti.credit, totals.nonRti.debit),
SummaryLinks(empRef)
)
}

case class SummaryLinks(
empRefs: Link,
self: Link
)

object SummaryLinks {
def apply(empRef: EmpRef): SummaryLinks = SummaryLinks(
Link.empRefsLink(),
Link.summaryLink(empRef)
)
}

12 changes: 4 additions & 8 deletions app/uk/gov/hmrc/epayeapi/router/ApiRouter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,19 @@ import play.api.routing.Router.Routes
import play.api.routing.{Router, SimpleRouter}
import play.api.routing.sird._
import uk.gov.hmrc.domain.EmpRef
import uk.gov.hmrc.epayeapi.controllers.{AnnualSummaryController, GetTotalsByTypeController, GetTotalsController}
import uk.gov.hmrc.epayeapi.controllers.{AnnualSummaryController, GetTotalsByTypeController, GetSummaryController}

@Singleton
case class ApiRouter @Inject() (
prodRoutes: prod.Routes,
getTotalsController: GetTotalsController,
getTotalsController: GetSummaryController,
getTotalsByTypeController: GetTotalsByTypeController,
annualSummaryController: AnnualSummaryController
) extends SimpleRouter {

val appRoutes = Router.from {
case GET(p"/$taxOfficeNumber/$taxOfficeReference/total") =>
getTotalsController.getTotals(EmpRef(taxOfficeNumber, taxOfficeReference))
case GET(p"/$taxOfficeNumber/$taxOfficeReference/total/by-type") =>
getTotalsByTypeController.getTotalsByType(EmpRef(taxOfficeNumber, taxOfficeReference))
case GET(p"/$taxOfficeNumber/$taxOfficeReference/charges-summary" ? q_o"taxYear=$taxYear") =>
annualSummaryController.getAnnualSummary(EmpRef(taxOfficeNumber, taxOfficeReference), taxYear)
case GET(p"/$taxOfficeNumber/$taxOfficeReference/") =>
getTotalsController.getSummary(EmpRef(taxOfficeNumber, taxOfficeReference))
}

val routes: Routes = appRoutes.routes.orElse(prodRoutes.routes)
Expand Down
Loading

0 comments on commit dd5dfb7

Please sign in to comment.