From d6e41d56cd49a0d553ab3918288b301a894460e2 Mon Sep 17 00:00:00 2001 From: AnotherMattWright <270914550+AnotherMattWright@users.noreply.github.com> Date: Mon, 20 Apr 2026 15:23:32 +0100 Subject: [PATCH 01/16] DTR-4210 BusinessName first attempt at creating backend call for BusinessName --- .../controllers/GamblingController.scala | 16 ++++++ .../gambling/models/BusinessName.scala | 35 ++++++++++++ .../GamblingDataCacheRepository.scala | 54 ++++++++++++++++++- .../gambling/services/GamblingService.scala | 19 +++++++ 4 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingController.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingController.scala index a86e070..f855cbd 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingController.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingController.scala @@ -48,6 +48,22 @@ class GamblingController @Inject() (authorise: AuthAction, service: GamblingServ } } } + def getBusinessName(mgdRegNumber: String): Action[AnyContent] = authorise.async { implicit request => + + service.getBusinessName(mgdRegNumber).map { + case Right(summary) => Ok(Json.toJson(summary)) + case Left(error) => + val logMessage = s"[GamblingController][getReturnSummary] code=${error.code} mgdRegNumber=$mgdRegNumber" + error match { + case InvalidMgdRegNumber => + logger.warn(logMessage) + BadRequest(errorResponse(error)) + case UnexpectedError => + logger.error(logMessage) + InternalServerError(errorResponse(error)) + } + } + } private def errorResponse(error: GamblingError) = Json.obj("code" -> error.code, "message" -> error.message) } diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala new file mode 100644 index 0000000..b926f92 --- /dev/null +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala @@ -0,0 +1,35 @@ +/* + * Copyright 2026 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.rdsdatacacheproxy.gambling.models +import play.api.libs.json.{Json, OFormat} +//import java.time.LocalDate + +case class BusinessName( + mgdRegNumber: String, + solePropType: String, + solePropFirstName: String, + solePropMidName: String, + solePropLastName: String, + businessName: String, + businessType: String, + tradingName: String, +// systemDate: LocalDate, + ) + +object BusinessName { + implicit val format: OFormat[BusinessName] = Json.format[BusinessName] +} \ No newline at end of file diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala index 06120e4..95971c9 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala @@ -18,13 +18,13 @@ package uk.gov.hmrc.rdsdatacacheproxy.gambling.repositories import play.api.Logging import play.api.db.{Database, NamedDatabase} -import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.ReturnSummary - +import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.* import javax.inject.{Inject, Singleton} import scala.concurrent.{ExecutionContext, Future} trait GamblingDataSource { def getReturnSummary(mgdRegNumber: String): Future[ReturnSummary] + def getBusinessName(mgdRegNumber: String): Future[BusinessName] } @Singleton @@ -77,4 +77,54 @@ class GamblingDataCacheRepository @Inject() ( } }(ec) } + override def getBusinessName(mgdRegNumber: String): Future[BusinessName] = { + + logger.info(s"[GamblingDataCacheRepository][getReturnSummary] mgdRegNumber=$mgdRegNumber") + + Future { + db.withConnection { conn => + + val cs = conn.prepareCall("{ call MGD_DC_VARIATION_PK.GET_BUSINESS_NAME(?, ?) }") + + try { + cs.setString(1, mgdRegNumber) + cs.registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR) + cs.execute() + + val rs = cs.getObject(2).asInstanceOf[java.sql.ResultSet] + + if (rs == null) { + val msg = s"Null cursor returned for mgdRegNumber=$mgdRegNumber" + logger.error(s"[GamblingDataCacheRepository] $msg") + throw new RuntimeException(msg) + } + + try { + if (rs.next()) { + BusinessName( + mgdRegNumber = rs.getString("MGD_REG_NUMBER"), + solePropType = rs.getString("SOLE_PROP_TITLE"), + solePropFirstName = rs.getString("SOLE_PROP_FIRST_NAME"), + solePropMidName = rs.getString("SOLE_PROP_MIDDLE_NAME"), + solePropLastName = rs.getString("SOLE_PROP_LAST_NAME"), + businessName = rs.getString("BUSINESS_NAME"), + businessType = rs.getString("BUSINESS_TYPE"), + tradingName = rs.getString("TRADING_NAME") + // how do we deal with system date? + // systemDate = part of the prototype + ) + } else { + val msg = s"Empty result set for mgdRegNumber=$mgdRegNumber" + logger.error(s"[GamblingDataCacheRepository] $msg") + throw new RuntimeException(msg) + } + } finally { + rs.close() + } + } finally { + cs.close() + } + } + }(ec) + } } diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingService.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingService.scala index 5fac57f..dae7aa7 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingService.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingService.scala @@ -50,4 +50,23 @@ class GamblingService @Inject() ( } } } + + def getBusinessName(rawMgdRegNumber: String)(implicit hc: HeaderCarrier): Future[Either[GamblingError, BusinessName]] = { + + val mgdRegNumber = rawMgdRegNumber.trim.toUpperCase + + if (!mgdRegNumberPattern.matcher(mgdRegNumber).matches()) { + logger.warn(s"[GamblingService][getReturnSummary] Invalid pattern for mgdRegNumber=$mgdRegNumber") + Future.successful(Left(InvalidMgdRegNumber)) + } else { + + repository + .getBusinessName(mgdRegNumber) + .map(summary => Right(summary)) + .recover { case ex: Exception => + logger.error(s"[GamblingService][getReturnSummary] Unexpected error mgdRegNumber=$mgdRegNumber", ex) + Left(UnexpectedError) + } + } + } } From 1ed2e4695b56670d9300f03ed2ce401e137031a7 Mon Sep 17 00:00:00 2001 From: AnotherMattWright <270914550+AnotherMattWright@users.noreply.github.com> Date: Mon, 20 Apr 2026 16:01:24 +0100 Subject: [PATCH 02/16] solved date addition to object --- .../gambling/models/BusinessName.scala | 24 +++++++++---------- .../GamblingDataCacheRepository.scala | 5 ++-- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala index b926f92..95ea6dc 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala @@ -16,20 +16,20 @@ package uk.gov.hmrc.rdsdatacacheproxy.gambling.models import play.api.libs.json.{Json, OFormat} -//import java.time.LocalDate +import java.sql.Date case class BusinessName( - mgdRegNumber: String, - solePropType: String, - solePropFirstName: String, - solePropMidName: String, - solePropLastName: String, - businessName: String, - businessType: String, - tradingName: String, -// systemDate: LocalDate, - ) + mgdRegNumber: String, + solePropType: String, + solePropFirstName: String, + solePropMidName: String, + solePropLastName: String, + businessName: String, + businessType: String, + tradingName: String, + systemDate: Date +) object BusinessName { implicit val format: OFormat[BusinessName] = Json.format[BusinessName] -} \ No newline at end of file +} diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala index 95971c9..c468748 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala @@ -109,9 +109,8 @@ class GamblingDataCacheRepository @Inject() ( solePropLastName = rs.getString("SOLE_PROP_LAST_NAME"), businessName = rs.getString("BUSINESS_NAME"), businessType = rs.getString("BUSINESS_TYPE"), - tradingName = rs.getString("TRADING_NAME") - // how do we deal with system date? - // systemDate = part of the prototype + tradingName = rs.getString("TRADING_NAME"), + systemDate = rs.getDate("SYSTEM_DATE") ) } else { val msg = s"Empty result set for mgdRegNumber=$mgdRegNumber" From ccef18eff0bc4e3bb30e003fbe09217e6f0d7283 Mon Sep 17 00:00:00 2001 From: AnotherMattWright <270914550+AnotherMattWright@users.noreply.github.com> Date: Mon, 20 Apr 2026 17:01:16 +0100 Subject: [PATCH 03/16] added test case in gambling controller spec for business name --- conf/app.routes | 1 + .../controllers/GamblingControllerSpec.scala | 84 +++++++++++++++++-- 2 files changed, 77 insertions(+), 8 deletions(-) diff --git a/conf/app.routes b/conf/app.routes index 726920a..3e73215 100644 --- a/conf/app.routes +++ b/conf/app.routes @@ -36,3 +36,4 @@ GET /charities/organisations/:charityRef uk.gov.hmrc.rdsdatacac #MGD routes GET /gambling/return-summary/:mgdRegNumber uk.gov.hmrc.rdsdatacacheproxy.gambling.controllers.GamblingController.getReturnSummary(mgdRegNumber: String) +GET /gambling/business-name/:mgdRegNumber uk.gov.hmrc.rdsdatacacheproxy.gambling.controllers.GamblingController.getBusinessName(mgdRegNumber: String) diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala index 7f93b8e..9dddb53 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala @@ -38,12 +38,14 @@ import org.mockito.Mockito.* import org.mockito.ArgumentMatchers.{any, eq as eqTo} import org.scalatest.matchers.should.Matchers.{should, shouldBe} import play.api.libs.json.{JsValue, Json} +import java.sql.Date import play.api.test.FakeRequest import play.api.test.Helpers.* import uk.gov.hmrc.rdsdatacacheproxy.base.SpecBase import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.GamblingError.{InvalidMgdRegNumber, UnexpectedError} import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.ReturnSummary +import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.BusinessName import uk.gov.hmrc.rdsdatacacheproxy.gambling.services.GamblingService import scala.concurrent.Future @@ -87,14 +89,80 @@ class GamblingControllerSpec extends SpecBase with MockitoSugar { verify(mockService).getReturnSummary(eqTo("XWM00000001770"))(any()) } + "returns 400 when InvalidMgdRegNumber" in new Setup { + when(mockService.getReturnSummary(any())(any())) + .thenReturn(Future.successful(Left(InvalidMgdRegNumber))) + + val req = FakeRequest(GET, "/gambling/return-summary/jhrfdshgksdhg") + val res = controller.getReturnSummary(" ")(req) + + status(res) mustBe BAD_REQUEST + contentAsJson(res) mustBe Json.obj( + "code" -> "INVALID_MGD_REG_NUMBER", + "message" -> "mgdRegNumber does not exist" + ) + + verify(mockService).getReturnSummary(eqTo(" "))(any()) + } + + "returns 500 when UnexpectedError" in new Setup { + when(mockService.getReturnSummary(any())(any())) + .thenReturn(Future.successful(Left(UnexpectedError))) + + val req = FakeRequest(GET, "/gambling/return-summary/ERR00001770") + val res = controller.getReturnSummary("ERR00001770")(req) + + status(res) mustBe INTERNAL_SERVER_ERROR + contentAsJson(res) mustBe Json.obj( + "code" -> "UNEXPECTED_ERROR", + "message" -> "Unexpected error occurred" + ) + + verify(mockService).getReturnSummary(eqTo("ERR00001770"))(any()) + } } + "GamblingController#getBusinessName" - { + + "returns 200 when service succeeds" in new Setup { + val sqlDate: Date = Date.valueOf("2026-04-20") + val name = BusinessName("XWM00000001770", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", sqlDate) + + when(mockService.getBusinessName(eqTo("XWM00000001770"))(any())) + .thenReturn(Future.successful(Right(name))) + + val req = FakeRequest(GET, "/gambling/business-name/XWM00000001770") + val res = controller.getBusinessName("XWM00000001770")(req) + + status(res) mustBe OK + contentType(res) mustBe Some(JSON) + contentAsJson(res) mustBe Json.toJson(name) + + verify(mockService).getBusinessName(eqTo("XWM00000001770"))(any()) + verifyNoMoreInteractions(mockService) + } + + "allows request through AuthAction" in new Setup { + val sqlDate: Date = Date.valueOf("2026-04-20") + val name = BusinessName("XWM00000001770", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", sqlDate) + + when(mockService.getBusinessName(any())(any())) + .thenReturn(Future.successful(Right(name))) + + val req = FakeRequest(GET, "/gambling/business-name/XWM00000001770") + val res = controller.getBusinessName("XWM00000001770")(req) + + status(res) mustBe OK + + verify(mockService).getBusinessName(eqTo("XWM00000001770"))(any()) + } + } "returns 400 when InvalidMgdRegNumber" in new Setup { - when(mockService.getReturnSummary(any())(any())) + when(mockService.getBusinessName(any())(any())) .thenReturn(Future.successful(Left(InvalidMgdRegNumber))) - val req = FakeRequest(GET, "/gambling/return-summary/jhrfdshgksdhg") - val res = controller.getReturnSummary(" ")(req) + val req = FakeRequest(GET, "/gambling/business-name/jhrfdshgksdhg") + val res = controller.getBusinessName(" ")(req) status(res) mustBe BAD_REQUEST contentAsJson(res) mustBe Json.obj( @@ -102,15 +170,15 @@ class GamblingControllerSpec extends SpecBase with MockitoSugar { "message" -> "mgdRegNumber does not exist" ) - verify(mockService).getReturnSummary(eqTo(" "))(any()) + verify(mockService).getBusinessName(eqTo(" "))(any()) } "returns 500 when UnexpectedError" in new Setup { - when(mockService.getReturnSummary(any())(any())) + when(mockService.getBusinessName(any())(any())) .thenReturn(Future.successful(Left(UnexpectedError))) - val req = FakeRequest(GET, "/gambling/return-summary/ERR00001770") - val res = controller.getReturnSummary("ERR00001770")(req) + val req = FakeRequest(GET, "/gambling/business-name/ERR00001770") + val res = controller.getBusinessName("ERR00001770")(req) status(res) mustBe INTERNAL_SERVER_ERROR contentAsJson(res) mustBe Json.obj( @@ -118,7 +186,7 @@ class GamblingControllerSpec extends SpecBase with MockitoSugar { "message" -> "Unexpected error occurred" ) - verify(mockService).getReturnSummary(eqTo("ERR00001770"))(any()) + verify(mockService).getBusinessName(eqTo("ERR00001770"))(any()) } } From ed940598b022c95a42accbce15f01c96bc081fea Mon Sep 17 00:00:00 2001 From: AnotherMattWright <270914550+AnotherMattWright@users.noreply.github.com> Date: Wed, 22 Apr 2026 11:57:51 +0100 Subject: [PATCH 04/16] test cases completed up to 77.69% coverage --- .../controllers/GamblingController.scala | 2 +- .../gambling/models/BusinessName.scala | 2 +- .../GamblingDataCacheRepository.scala | 4 +- .../gambling/services/GamblingService.scala | 4 +- .../GamblingControllerIntegrationSpec.scala | 192 ++++++++++++++++-- .../GamblingDataCacheRepositoryISpec.scala | 133 +++++++++++- .../gambling/GamblingStubData.scala | 79 ++++++- .../GamblingDataCacheRepositorySpec.scala | 48 ++++- .../services/GamblingServiceSpec.scala | 72 ++++++- 9 files changed, 503 insertions(+), 33 deletions(-) diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingController.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingController.scala index f855cbd..1f53780 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingController.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingController.scala @@ -53,7 +53,7 @@ class GamblingController @Inject() (authorise: AuthAction, service: GamblingServ service.getBusinessName(mgdRegNumber).map { case Right(summary) => Ok(Json.toJson(summary)) case Left(error) => - val logMessage = s"[GamblingController][getReturnSummary] code=${error.code} mgdRegNumber=$mgdRegNumber" + val logMessage = s"[GamblingController][getBusinessName] code=${error.code} mgdRegNumber=$mgdRegNumber" error match { case InvalidMgdRegNumber => logger.warn(logMessage) diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala index 95ea6dc..cf39b66 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala @@ -20,7 +20,7 @@ import java.sql.Date case class BusinessName( mgdRegNumber: String, - solePropType: String, + solePropTitle: String, solePropFirstName: String, solePropMidName: String, solePropLastName: String, diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala index c468748..0509b39 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala @@ -79,7 +79,7 @@ class GamblingDataCacheRepository @Inject() ( } override def getBusinessName(mgdRegNumber: String): Future[BusinessName] = { - logger.info(s"[GamblingDataCacheRepository][getReturnSummary] mgdRegNumber=$mgdRegNumber") + logger.info(s"[GamblingDataCacheRepository][getBusinessName] mgdRegNumber=$mgdRegNumber") Future { db.withConnection { conn => @@ -103,7 +103,7 @@ class GamblingDataCacheRepository @Inject() ( if (rs.next()) { BusinessName( mgdRegNumber = rs.getString("MGD_REG_NUMBER"), - solePropType = rs.getString("SOLE_PROP_TITLE"), + solePropTitle = rs.getString("SOLE_PROP_TITLE"), solePropFirstName = rs.getString("SOLE_PROP_FIRST_NAME"), solePropMidName = rs.getString("SOLE_PROP_MIDDLE_NAME"), solePropLastName = rs.getString("SOLE_PROP_LAST_NAME"), diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingService.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingService.scala index dae7aa7..499f457 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingService.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingService.scala @@ -56,7 +56,7 @@ class GamblingService @Inject() ( val mgdRegNumber = rawMgdRegNumber.trim.toUpperCase if (!mgdRegNumberPattern.matcher(mgdRegNumber).matches()) { - logger.warn(s"[GamblingService][getReturnSummary] Invalid pattern for mgdRegNumber=$mgdRegNumber") + logger.warn(s"[GamblingService][getBusinessName] Invalid pattern for mgdRegNumber=$mgdRegNumber") Future.successful(Left(InvalidMgdRegNumber)) } else { @@ -64,7 +64,7 @@ class GamblingService @Inject() ( .getBusinessName(mgdRegNumber) .map(summary => Right(summary)) .recover { case ex: Exception => - logger.error(s"[GamblingService][getReturnSummary] Unexpected error mgdRegNumber=$mgdRegNumber", ex) + logger.error(s"[GamblingService][getBusinessName] Unexpected error mgdRegNumber=$mgdRegNumber", ex) Left(UnexpectedError) } } diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingControllerIntegrationSpec.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingControllerIntegrationSpec.scala index a0cf505..1165ca7 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingControllerIntegrationSpec.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingControllerIntegrationSpec.scala @@ -28,6 +28,7 @@ import uk.gov.hmrc.rdsdatacacheproxy.gambling.repositories.GamblingDataSource import uk.gov.hmrc.rdsdatacacheproxy.itutil.{ApplicationWithWiremock, AuthStub} import scala.concurrent.Future +import java.sql.Date class GamblingControllerIntegrationSpec extends AnyWordSpec @@ -41,8 +42,13 @@ class GamblingControllerIntegrationSpec Future { GamblingStubData.getReturnSummary(mgdRegNumber) } + override def getBusinessName(mgdRegNumber: String) = + Future { + GamblingStubData.getBusinessName(mgdRegNumber) + } } + override lazy val app: Application = new GuiceApplicationBuilder() .configure(extraConfig) @@ -51,14 +57,15 @@ class GamblingControllerIntegrationSpec ) .build() - private val endpoint = "/gambling/return-summary" + private val endpointReturnSummary = "/gambling/return-summary" + private val endpointBusinessName = "/gambling/business-name" "GET /gambling/return-summary (stubbed repo, no DB)" should { "return 200 with correct summary (0,0)" in { AuthStub.authorised() - val response = get(s"$endpoint/XYZ00000000000").futureValue + val response = get(s"$endpointReturnSummary/XYZ00000000000").futureValue response.status mustBe OK response.contentType mustBe "application/json" @@ -70,14 +77,14 @@ class GamblingControllerIntegrationSpec "normalise lowercase input" in { AuthStub.authorised() - val response = get(s"$endpoint/xyz00000000012 ").futureValue + val response = get(s"$endpointReturnSummary/xyz00000000012 ").futureValue response.status mustBe OK (response.json \ "mgdRegNumber").as[String] mustBe "XYZ00000000012" } "return default values for unknown mgdRegNumber" in { AuthStub.authorised() - val response = get(s"$endpoint/XYZ99999999999").futureValue + val response = get(s"$endpointReturnSummary/XYZ99999999999").futureValue response.status mustBe OK (response.json \ "returnsDue").as[Int] mustBe 3 (response.json \ "returnsOverdue").as[Int] mustBe 4 @@ -85,7 +92,7 @@ class GamblingControllerIntegrationSpec "return 200 with correct summary (1,2)" in { AuthStub.authorised() - val response = get(s"$endpoint/XYZ00000000012").futureValue + val response = get(s"$endpointReturnSummary/XYZ00000000012").futureValue response.status mustBe OK response.contentType mustBe "application/json" (response.json \ "mgdRegNumber").as[String] mustBe "XYZ00000000012" @@ -95,7 +102,7 @@ class GamblingControllerIntegrationSpec "return 200 with correct summary (2,1)" in { AuthStub.authorised() - val response = get(s"$endpoint/XYZ00000000021").futureValue + val response = get(s"$endpointReturnSummary/XYZ00000000021").futureValue response.status mustBe OK (response.json \ "returnsDue").as[Int] mustBe 2 (response.json \ "returnsOverdue").as[Int] mustBe 1 @@ -103,41 +110,190 @@ class GamblingControllerIntegrationSpec "trim whitespace around mgdRegNumber" in { AuthStub.authorised() - val response = get(s"$endpoint/ XYZ00000000010 ").futureValue + val response = get(s"$endpointReturnSummary/ XYZ00000000010 ").futureValue + response.status mustBe OK + (response.json \ "mgdRegNumber").as[String] mustBe "XYZ00000000010" + } + + "return consistent results across multiple calls" in { + AuthStub.authorised() + val res1 = get(s"$endpointReturnSummary/XYZ00000000012").futureValue + val res2 = get(s"$endpointReturnSummary/XYZ00000000012").futureValue + res1.json mustBe res2.json + } + + "return JSON content type for valid response" in { + AuthStub.authorised() + val response = get(s"$endpointReturnSummary/XYZ00000000012").futureValue + response.contentType mustBe "application/json" + } + + + "return 400 for partially valid mgdRegNumber (wrong length)" in { + AuthStub.authorised() + val response = get(s"$endpointReturnSummary/XYZ123").futureValue + response.status mustBe BAD_REQUEST + } + + "return 400 for mgdRegNumber with special characters" in { + AuthStub.authorised() + val response = get(s"$endpointReturnSummary/XYZ00000@00000").futureValue + response.status mustBe BAD_REQUEST + } + + "return 400 for invalid mgdRegNumber format" in { + AuthStub.authorised() + + val response = get(s"$endpointReturnSummary/INVALID").futureValue + response.status mustBe BAD_REQUEST + (response.json \ "code").as[String] mustBe "INVALID_MGD_REG_NUMBER" + (response.json \ "message").as[String] mustBe "mgdRegNumber does not exist" + } + + "return 401 when unauthorised" in { + AuthStub.unauthorised() + val response = get(s"$endpointReturnSummary/XYZ00000000000").futureValue + response.status mustBe UNAUTHORIZED + } + + "return 404 for missing mgdRegNumber" in { + AuthStub.authorised() + val response = get(s"$endpointReturnSummary/").futureValue + response.status mustBe NOT_FOUND + } + + "return 404 for whitespace-only mgdRegNumber" in { + AuthStub.authorised() + val response = get(s"$endpointReturnSummary/ ").futureValue + response.status mustBe NOT_FOUND + } + + "return 500 when stub simulates failure" in { + AuthStub.authorised() + val response = get(s"$endpointReturnSummary/ERR00000000000").futureValue + response.status mustBe INTERNAL_SERVER_ERROR + (response.json \ "code").as[String] mustBe "UNEXPECTED_ERROR" + } + + "return correct error structure for 500 response" in { + AuthStub.authorised() + val response = get(s"$endpointReturnSummary/ERR00000000000").futureValue + response.status mustBe INTERNAL_SERVER_ERROR + (response.json \ "code").as[String] mustBe "UNEXPECTED_ERROR" + (response.json \ "message").as[String] mustBe "Unexpected error occurred" + } + + } + + "GET /gambling/business-name (stubbed repo, no DB)" should { + + "return 200 with correct summary" in { + AuthStub.authorised() + + val response = get(s"$endpointBusinessName/XYZ00000000000").futureValue + + response.status mustBe OK + response.contentType mustBe "application/json" + (response.json \ "mgdRegNumber").as[String] mustBe "XYZ00000000000" + (response.json \ "solePropTitle").as[String] mustBe "Mr" + (response.json \ "solePropFirstName").as[String] mustBe "John" + (response.json \ "solePropMidName").as[String] mustBe "C" + (response.json \ "solePropLastName").as[String] mustBe "Doe" + (response.json \ "businessName").as[String] mustBe "John Doe Co." + (response.json \ "businessType").as[String] mustBe "Sole Proprietor" + (response.json \ "tradingName").as[String] mustBe "DoeDoe" + (response.json \ "systemDate").as[Date] mustBe Date.valueOf("2026-04-20") + } + + "normalise lowercase input" in { + AuthStub.authorised() + val response = get(s"$endpointBusinessName/xyz00000000012 ").futureValue + response.status mustBe OK + (response.json \ "mgdRegNumber").as[String] mustBe "XYZ00000000012" + } + + "return default values for unknown mgdRegNumber" in { + AuthStub.authorised() + val response = get(s"$endpointBusinessName/XYZ99999999999").futureValue + response.status mustBe OK + (response.json \ "solePropTitle").as[String] mustBe "Mr" + (response.json \ "solePropFirstName").as[String] mustBe "Foo" + (response.json \ "solePropMidName").as[String] mustBe "B" + (response.json \ "solePropLastName").as[String] mustBe "Bar" + (response.json \ "businessName").as[String] mustBe "FooBar Co." + (response.json \ "businessType").as[String] mustBe "Sole Proprietor" + (response.json \ "tradingName").as[String] mustBe "Foobar" + (response.json \ "systemDate").as[Date] mustBe Date.valueOf("2026-04-20") + } + + "return 200 with correct summary of Miss Catherine Haversham" in { + AuthStub.authorised() + val response = get(s"$endpointBusinessName/XYZ00000000012").futureValue + response.status mustBe OK + response.contentType mustBe "application/json" + (response.json \ "mgdRegNumber").as[String] mustBe "XYZ00000000012" + (response.json \ "solePropTitle").as[String] mustBe "Miss" + (response.json \ "solePropFirstName").as[String] mustBe "Catherine" + (response.json \ "solePropMidName").as[String] mustBe "" + (response.json \ "solePropLastName").as[String] mustBe "Havisham" + (response.json \ "businessName").as[String] mustBe "Failed Expectations" + (response.json \ "businessType").as[String] mustBe "Sole Proprietor" + (response.json \ "tradingName").as[String] mustBe "Miss Havisham" + (response.json \ "systemDate").as[Date] mustBe Date.valueOf("1992-01-01") + } + + "return 200 with correct summary of Mr Eugine H Krabs" in { + AuthStub.authorised() + val response = get(s"$endpointBusinessName/XYZ00000000021").futureValue + response.status mustBe OK + (response.json \ "mgdRegNumber").as[String] mustBe "XYZ00000000021" + (response.json \ "solePropTitle").as[String] mustBe "Mr" + (response.json \ "solePropFirstName").as[String] mustBe "Eugine" + (response.json \ "solePropMidName").as[String] mustBe "H" + (response.json \ "solePropLastName").as[String] mustBe "Krabs" + (response.json \ "businessName").as[String] mustBe "Krusty Krab" + (response.json \ "businessType").as[String] mustBe "Sole Proprietor" + (response.json \ "tradingName").as[String] mustBe "Mr Krabs" + (response.json \ "systemDate").as[Date] mustBe Date.valueOf("1992-01-01") + } + + "trim whitespace around mgdRegNumber" in { + AuthStub.authorised() + val response = get(s"$endpointBusinessName/ XYZ00000000010 ").futureValue response.status mustBe OK (response.json \ "mgdRegNumber").as[String] mustBe "XYZ00000000010" } "return consistent results across multiple calls" in { AuthStub.authorised() - val res1 = get(s"$endpoint/XYZ00000000012").futureValue - val res2 = get(s"$endpoint/XYZ00000000012").futureValue + val res1 = get(s"$endpointBusinessName/XYZ00000000012").futureValue + val res2 = get(s"$endpointBusinessName/XYZ00000000012").futureValue res1.json mustBe res2.json } "return JSON content type for valid response" in { AuthStub.authorised() - val response = get(s"$endpoint/XYZ00000000012").futureValue + val response = get(s"$endpointBusinessName/XYZ00000000012").futureValue response.contentType mustBe "application/json" } "return 400 for partially valid mgdRegNumber (wrong length)" in { AuthStub.authorised() - val response = get(s"$endpoint/XYZ123").futureValue + val response = get(s"$endpointBusinessName/XYZ123").futureValue response.status mustBe BAD_REQUEST } "return 400 for mgdRegNumber with special characters" in { AuthStub.authorised() - val response = get(s"$endpoint/XYZ00000@00000").futureValue + val response = get(s"$endpointBusinessName/XYZ00000@00000").futureValue response.status mustBe BAD_REQUEST } "return 400 for invalid mgdRegNumber format" in { AuthStub.authorised() - val response = get(s"$endpoint/INVALID").futureValue + val response = get(s"$endpointBusinessName/INVALID").futureValue response.status mustBe BAD_REQUEST (response.json \ "code").as[String] mustBe "INVALID_MGD_REG_NUMBER" (response.json \ "message").as[String] mustBe "mgdRegNumber does not exist" @@ -145,32 +301,32 @@ class GamblingControllerIntegrationSpec "return 401 when unauthorised" in { AuthStub.unauthorised() - val response = get(s"$endpoint/XYZ00000000000").futureValue + val response = get(s"$endpointBusinessName/XYZ00000000000").futureValue response.status mustBe UNAUTHORIZED } "return 404 for missing mgdRegNumber" in { AuthStub.authorised() - val response = get(s"$endpoint/").futureValue + val response = get(s"$endpointBusinessName/").futureValue response.status mustBe NOT_FOUND } "return 404 for whitespace-only mgdRegNumber" in { AuthStub.authorised() - val response = get(s"$endpoint/ ").futureValue + val response = get(s"$endpointBusinessName/ ").futureValue response.status mustBe NOT_FOUND } "return 500 when stub simulates failure" in { AuthStub.authorised() - val response = get(s"$endpoint/ERR00000000000").futureValue + val response = get(s"$endpointBusinessName/ERR00000000000").futureValue response.status mustBe INTERNAL_SERVER_ERROR (response.json \ "code").as[String] mustBe "UNEXPECTED_ERROR" } "return correct error structure for 500 response" in { AuthStub.authorised() - val response = get(s"$endpoint/ERR00000000000").futureValue + val response = get(s"$endpointBusinessName/ERR00000000000").futureValue response.status mustBe INTERNAL_SERVER_ERROR (response.json \ "code").as[String] mustBe "UNEXPECTED_ERROR" (response.json \ "message").as[String] mustBe "Unexpected error occurred" diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala index dd7e862..7642246 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala @@ -23,10 +23,11 @@ import org.scalatestplus.play.guice.GuiceOneAppPerSuite import play.api.Application import play.api.inject.bind import play.api.inject.guice.GuiceApplicationBuilder -import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.ReturnSummary +import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.* import uk.gov.hmrc.rdsdatacacheproxy.gambling.repositories.GamblingDataSource import scala.concurrent.Future +import java.sql.Date class GamblingDataCacheRepositoryISpec extends AnyWordSpec @@ -38,6 +39,8 @@ class GamblingDataCacheRepositoryISpec class GamblingRdsStub extends GamblingDataSource { override def getReturnSummary(mgdRegNumber: String): Future[ReturnSummary] = Future.successful(GamblingStubData.getReturnSummary(mgdRegNumber)) + override def getBusinessName(mgdRegNumber: String): Future[BusinessName] = + Future.successful(GamblingStubData.getBusinessName(mgdRegNumber)) } override lazy val app: Application = new GuiceApplicationBuilder() @@ -55,8 +58,8 @@ class GamblingDataCacheRepositoryISpec val result = repository.getReturnSummary("XYZ00000000000").futureValue result mustBe ReturnSummary( - mgdRegNumber = "XYZ00000000000", - returnsDue = 0, + mgdRegNumber = "XYZ00000000000", + returnsDue = 0, returnsOverdue = 0 ) } @@ -136,4 +139,128 @@ class GamblingDataCacheRepositoryISpec result.returnsOverdue must be >= 0 } } + "getBusinessName (stubbed repository)" should { + + "return John Doe as Sole Proprietor" in { + val result = repository.getBusinessName("XYZ00000000000").futureValue + + result mustBe BusinessName( + mgdRegNumber = "XYZ00000000000", + solePropTitle = "Mr", + solePropFirstName = "John", + solePropMidName = "C", + solePropLastName = "Doe", + businessName = "John Doe Co.", + businessType = "Sole Proprietor", + tradingName = "DoeDoe", + systemDate = Date.valueOf("2026-04-20") + ) + } + + "return Marge Simpson as Sole Proprietor" in { + val result = repository.getBusinessName("XYZ00000000010").futureValue + + result mustBe BusinessName( + mgdRegNumber = "XYZ00000000010", + solePropTitle = "Mrs", + solePropFirstName = "Marge", + solePropMidName = "Jacqueline", + solePropLastName = "Simpson", + businessName = "Pretzel Wagon", + businessType = "Sole Proprietor", + tradingName = "Marge Simpson", + systemDate = Date.valueOf("2026-04-20") + ) + } + + "return last name and business name correctly" in { + val result = repository.getBusinessName("XYZ00000000001").futureValue + + result.solePropLastName mustBe "Doe" + result.businessName mustBe "Jane Doe Co." + } + + "return correct middle name and system date" in { + val result = repository.getBusinessName("XYZ00000000010").futureValue + + result.solePropMidName mustBe "Jacqueline" + result.systemDate mustBe Date.valueOf("2026-04-20") + } + + "return correct title and trading name" in { + val result = repository.getBusinessName("XYZ00000000012").futureValue + + result.solePropTitle mustBe "Miss" + result.tradingName mustBe "Miss Havisham" + } + + "return correct business type and first name" in { + val result = repository.getBusinessName("XYZ00000000021").futureValue + + result.solePropFirstName mustBe "Eugine" + result.businessType mustBe "Sole Proprietor" + } + + "return default values for unknown mgdRegNumber" in { + val result = repository.getBusinessName("XYZ99999999999").futureValue + + result mustBe BusinessName( + mgdRegNumber = "XYZ99999999999", + solePropTitle = "Mr", + solePropFirstName = "Foo", + solePropMidName = "B", + solePropLastName = "Bar", + businessName = "FooBar Co.", + businessType = "Sole Proprietor", + tradingName = "Foobar", + systemDate = Date.valueOf("2026-04-20") + ) + } + + "return consistent results across multiple calls" in { + val result1 = repository.getBusinessName("XYZ00000000012").futureValue + val result2 = repository.getBusinessName("XYZ00000000012").futureValue + + result1 mustBe result2 + } + + "handle different valid mgdRegNumbers independently" in { + val result1 = repository.getBusinessName("XYZ00000000010").futureValue + val result2 = repository.getBusinessName("XYZ00000000001").futureValue + + result1 must not be result2 + } + + "propagate downstream failure from stub" in { + val exception = intercept[RuntimeException] { + repository.getBusinessName("ERR00000000000").futureValue + } + + exception.getMessage must include("Simulated downstream failure") + } + + "handle special characters in mgdRegNumber" in { + val result = repository.getBusinessName("XYZ-123/ABC").futureValue + + result.mgdRegNumber mustBe "XYZ-123/ABC" + } + + "handle whitespace mgdRegNumber" in { + val result = repository.getBusinessName(" ").futureValue + + result.mgdRegNumber mustBe (" ") + } + + "return populated fields for all required responses" in { + val result = repository.getBusinessName("XYZ00000000012").futureValue + + result.mgdRegNumber must not be empty + result.solePropTitle must not be empty + result.solePropFirstName must not be empty + result.solePropLastName must not be empty + result.businessName must not be empty + result.businessType must not be empty + result.tradingName must not be empty + } + } } \ No newline at end of file diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala index be6d087..17ab27b 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala @@ -16,10 +16,11 @@ package uk.gov.hmrc.rdsdatacacheproxy.gambling -import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.ReturnSummary +import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.* +import java.sql.Date object GamblingStubData { - def getReturnSummary(mgdRegNumber: String): ReturnSummary = + def getReturnSummary(mgdRegNumber: String): ReturnSummary = { mgdRegNumber match { case "XYZ00000000000" => ReturnSummary(mgdRegNumber, returnsDue = 0, returnsOverdue = 0) @@ -35,5 +36,77 @@ object GamblingStubData { throw new RuntimeException("Simulated downstream failure") case _ => ReturnSummary(mgdRegNumber, returnsDue = 3, returnsOverdue = 4) + } } -} + def getBusinessName(mgdRegNumber: String): BusinessName = { + val sqlDateOne: Date = Date.valueOf("2026-04-20") + val sqlDateTwo: Date = Date.valueOf("2026-01-01") + val sqlDateThree: Date = Date.valueOf("1992-01-01") + mgdRegNumber match { + case "XYZ00000000000" => + BusinessName(mgdRegNumber, + solePropTitle = "Mr", + solePropFirstName = "John", + solePropMidName = "C", + solePropLastName = "Doe", + businessName = "John Doe Co.", + businessType = "Sole Proprietor", + tradingName = "DoeDoe", + systemDate = sqlDateOne) + case "XYZ00000000001" => + BusinessName(mgdRegNumber, + solePropTitle = "Mrs", + solePropFirstName = "Jane", + solePropMidName = "C", + solePropLastName = "Doe", + businessName = "Jane Doe Co.", + businessType = "Sole Proprietor", + tradingName = "DoeDoe", + systemDate = sqlDateTwo) + case "XYZ00000000010" => + BusinessName(mgdRegNumber, + solePropTitle = "Mrs", + solePropFirstName = "Marge", + solePropMidName = "Jacqueline", + solePropLastName = "Simpson", + businessName = "Pretzel Wagon", + businessType = "Sole Proprietor", + tradingName = "Marge Simpson", + systemDate = sqlDateOne) + case "XYZ00000000012" => + BusinessName(mgdRegNumber, + solePropTitle = "Miss", + solePropFirstName = "Catherine", + solePropMidName = "", + solePropLastName = "Havisham", + businessName = "Failed Expectations", + businessType = "Sole Proprietor", + tradingName = "Miss Havisham", + systemDate = sqlDateThree) + case "XYZ00000000021" => + BusinessName(mgdRegNumber, + solePropTitle = "Mr", + solePropFirstName = "Eugine", + solePropMidName = "H", + solePropLastName = "Krabs", + businessName = "Krusty Krab", + businessType = "Sole Proprietor", + tradingName = "Mr Krabs", + systemDate = sqlDateThree) + case "ERR00000000000" => + throw new RuntimeException("Simulated downstream failure") + case _ => + BusinessName(mgdRegNumber, + solePropTitle= "Mr", + solePropFirstName= "Foo", + solePropMidName= "B", + solePropLastName= "Bar", + businessName= "FooBar Co.", + businessType= "Sole Proprietor", + tradingName= "Foobar", + systemDate= sqlDateOne + ) + } + } + } + diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala index a06046b..f236378 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala @@ -23,9 +23,9 @@ import org.scalatest.concurrent.ScalaFutures.convertScalaFuture import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers import play.api.db.Database -import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.ReturnSummary +import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.* -import java.sql.{CallableStatement, Connection, ResultSet} +import java.sql.{CallableStatement, Connection, Date, ResultSet} import scala.concurrent.ExecutionContext.Implicits.global class GamblingDataCacheRepositorySpec extends AnyFlatSpec with Matchers with BeforeAndAfter { @@ -93,6 +93,50 @@ class GamblingDataCacheRepositorySpec extends AnyFlatSpec with Matchers with Bef verifyCleanup() } + "getBusinessName" should "return Business Name when stored procedure returns data" in { + + val mgdRegNumber = "XWM12345678901" + + when(mockResultSet.next()).thenReturn(true) + when(mockResultSet.getString("MGD_REG_NUMBER")).thenReturn(mgdRegNumber) + when(mockResultSet.getString("SOLE_PROP_TITLE")).thenReturn("Mr") + when(mockResultSet.getString("SOLE_PROP_FIRST_NAME")).thenReturn("Foo") + when(mockResultSet.getString("SOLE_PROP_MIDDLE_NAME")).thenReturn("B") + when(mockResultSet.getString("SOLE_PROP_LAST_NAME")).thenReturn("Bar") + when(mockResultSet.getString("BUSINESS_NAME")).thenReturn("Foo Bar Co.") + when(mockResultSet.getString("BUSINESS_TYPE")).thenReturn("Sole Proprietor") + when(mockResultSet.getString("TRADING_NAME")).thenReturn("Foobar") + when(mockResultSet.getDate("SYSTEM_DATE")).thenReturn(Date.valueOf("2026-04-20")) + + val result = repository.getBusinessName(mgdRegNumber).futureValue + + result shouldBe BusinessName( + mgdRegNumber = mgdRegNumber, + solePropTitle = "Mr", + solePropFirstName = "Foo", + solePropMidName = "B", + solePropLastName = "Bar", + businessName = "Foo Bar Co.", + businessType = "Sole Proprietor", + tradingName = "Foobar", + systemDate = Date.valueOf("2026-04-20") + ) + verifyDbSetup(mgdRegNumber) + + verify(mockResultSet).next() + verify(mockResultSet).getString("MGD_REG_NUMBER") + verify(mockResultSet).getString("SOLE_PROP_TITLE") + verify(mockResultSet).getString("SOLE_PROP_FIRST_NAME") + verify(mockResultSet).getString("SOLE_PROP_MIDDLE_NAME") + verify(mockResultSet).getString("SOLE_PROP_LAST_NAME") + verify(mockResultSet).getString("BUSINESS_NAME") + verify(mockResultSet).getString("BUSINESS_TYPE") + verify(mockResultSet).getString("TRADING_NAME") + verify(mockResultSet).getDate("SYSTEM_DATE") + + verifyCleanup() + } + it should "handle null values in result set safely" in { when(mockResultSet.next()).thenReturn(true) when(mockResultSet.getString("MGD_REG_NUMBER")).thenReturn(null) diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala index 698f290..756c103 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala @@ -20,11 +20,12 @@ import org.mockito.ArgumentMatchers.eq as eqTo import org.mockito.Mockito.{reset, verify, verifyNoMoreInteractions, when} import org.scalatest.matchers.must.Matchers.mustBe import uk.gov.hmrc.rdsdatacacheproxy.base.SpecBase -import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.ReturnSummary +import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.* import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.GamblingError.{InvalidMgdRegNumber, UnexpectedError} import uk.gov.hmrc.rdsdatacacheproxy.gambling.repositories.GamblingDataSource import scala.concurrent.Future +import java.sql.Date final class GamblingServiceSpec extends SpecBase { @@ -82,6 +83,75 @@ final class GamblingServiceSpec extends SpecBase { verifyNoMoreInteractions(repository) } + "return UnexpectedError when repository throws exception" in { + + when(repository.getReturnSummary(eqTo(validMgdRegNumber))) + .thenReturn(Future.failed(new RuntimeException("DB failure when calling repo"))) + val result = service.getReturnSummary(validMgdRegNumber).futureValue + result mustBe Left(UnexpectedError) + verify(repository).getReturnSummary(eqTo(validMgdRegNumber)) + verifyNoMoreInteractions(repository) + } + } + "GamblingService#getBusinessName" - { + + "return Right(summary) when repository succeeds" in { + + val summary = BusinessName( + mgdRegNumber = validMgdRegNumber, + solePropTitle = "Mr", + solePropFirstName = "Foo", + solePropMidName = "B", + solePropLastName = "Bar", + businessName = "FooBar Co.", + businessType = "Sole Proprietor", + tradingName = "Foobar", + systemDate = Date.valueOf("1992-01-01") + ) + + when(repository.getBusinessName(eqTo(validMgdRegNumber))) + .thenReturn(Future.successful(summary)) + + val result = service.getBusinessName(validMgdRegNumber).futureValue + + result mustBe Right(summary) + verify(repository).getBusinessName(eqTo(validMgdRegNumber)) + verifyNoMoreInteractions(repository) + } + + "normalise input (trim + uppercase) before calling repository" in { + + val rawInput = " xwm12345678901 " + + val summary = BusinessName( + mgdRegNumber = normalisedMgdRegNumber, + solePropTitle = "Mr", + solePropFirstName = "John", + solePropMidName = "C", + solePropLastName = "Doe", + businessName = "John Doe Co.", + businessType = "Sole Proprietor", + tradingName = "DoeDoe", + systemDate = Date.valueOf("1992-01-01") + ) + + when(repository.getBusinessName(eqTo(normalisedMgdRegNumber))) + .thenReturn(Future.successful(summary)) + + val result = service.getBusinessName(rawInput).futureValue + result mustBe Right(summary) + verify(repository).getBusinessName(eqTo(normalisedMgdRegNumber)) + verifyNoMoreInteractions(repository) + } + + "return InvalidMgdRegNumber and not call repository when input is invalid" in { + + val invalidInput = "xwm12345678" + val result = service.getBusinessName(invalidInput).futureValue + result mustBe Left(InvalidMgdRegNumber) + verifyNoMoreInteractions(repository) + } + "return UnexpectedError when repository throws exception" in { when(repository.getReturnSummary(eqTo(validMgdRegNumber))) From 76fc1a06d7092e2c17ad56e5d8e6c928bdbbe25f Mon Sep 17 00:00:00 2001 From: AnotherMattWright <270914550+AnotherMattWright@users.noreply.github.com> Date: Thu, 23 Apr 2026 12:20:54 +0100 Subject: [PATCH 05/16] test coverage complete for 79.78% --- .../gambling/models/BusinessName.scala | 4 +- .../GamblingDataCacheRepository.scala | 2 +- .../GamblingControllerIntegrationSpec.scala | 10 +-- .../GamblingDataCacheRepositoryISpec.scala | 10 +-- .../gambling/GamblingStubData.scala | 20 ++--- .../controllers/GamblingControllerSpec.scala | 10 +-- .../gambling/models/GamblingModelSpec.scala | 89 +++++++++++++++++++ .../GamblingDataCacheRepositorySpec.scala | 47 ++++++++-- .../services/GamblingServiceSpec.scala | 7 +- 9 files changed, 162 insertions(+), 37 deletions(-) create mode 100644 test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingModelSpec.scala diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala index cf39b66..9b5daad 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala @@ -16,7 +16,7 @@ package uk.gov.hmrc.rdsdatacacheproxy.gambling.models import play.api.libs.json.{Json, OFormat} -import java.sql.Date +import java.time.LocalDate case class BusinessName( mgdRegNumber: String, @@ -27,7 +27,7 @@ case class BusinessName( businessName: String, businessType: String, tradingName: String, - systemDate: Date + systemDate: Option[LocalDate] ) object BusinessName { diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala index 0509b39..31bcf4e 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala @@ -110,7 +110,7 @@ class GamblingDataCacheRepository @Inject() ( businessName = rs.getString("BUSINESS_NAME"), businessType = rs.getString("BUSINESS_TYPE"), tradingName = rs.getString("TRADING_NAME"), - systemDate = rs.getDate("SYSTEM_DATE") + systemDate = Option(rs.getDate("SYSTEM_DATE")).map(_.toLocalDate) ) } else { val msg = s"Empty result set for mgdRegNumber=$mgdRegNumber" diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingControllerIntegrationSpec.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingControllerIntegrationSpec.scala index 1165ca7..87d2426 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingControllerIntegrationSpec.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingControllerIntegrationSpec.scala @@ -28,7 +28,7 @@ import uk.gov.hmrc.rdsdatacacheproxy.gambling.repositories.GamblingDataSource import uk.gov.hmrc.rdsdatacacheproxy.itutil.{ApplicationWithWiremock, AuthStub} import scala.concurrent.Future -import java.sql.Date +import java.time.LocalDate class GamblingControllerIntegrationSpec extends AnyWordSpec @@ -202,7 +202,7 @@ class GamblingControllerIntegrationSpec (response.json \ "businessName").as[String] mustBe "John Doe Co." (response.json \ "businessType").as[String] mustBe "Sole Proprietor" (response.json \ "tradingName").as[String] mustBe "DoeDoe" - (response.json \ "systemDate").as[Date] mustBe Date.valueOf("2026-04-20") + (response.json \ "systemDate").as[LocalDate] mustBe LocalDate.of(2026, 4, 20) } "normalise lowercase input" in { @@ -223,7 +223,7 @@ class GamblingControllerIntegrationSpec (response.json \ "businessName").as[String] mustBe "FooBar Co." (response.json \ "businessType").as[String] mustBe "Sole Proprietor" (response.json \ "tradingName").as[String] mustBe "Foobar" - (response.json \ "systemDate").as[Date] mustBe Date.valueOf("2026-04-20") + (response.json \ "systemDate").as[LocalDate] mustBe LocalDate.of(2026, 4, 20) } "return 200 with correct summary of Miss Catherine Haversham" in { @@ -239,7 +239,7 @@ class GamblingControllerIntegrationSpec (response.json \ "businessName").as[String] mustBe "Failed Expectations" (response.json \ "businessType").as[String] mustBe "Sole Proprietor" (response.json \ "tradingName").as[String] mustBe "Miss Havisham" - (response.json \ "systemDate").as[Date] mustBe Date.valueOf("1992-01-01") + (response.json \ "systemDate").as[LocalDate] mustBe LocalDate.of(1991, 1, 1) } "return 200 with correct summary of Mr Eugine H Krabs" in { @@ -254,7 +254,7 @@ class GamblingControllerIntegrationSpec (response.json \ "businessName").as[String] mustBe "Krusty Krab" (response.json \ "businessType").as[String] mustBe "Sole Proprietor" (response.json \ "tradingName").as[String] mustBe "Mr Krabs" - (response.json \ "systemDate").as[Date] mustBe Date.valueOf("1992-01-01") + (response.json \ "systemDate").as[LocalDate] mustBe LocalDate.of(1991, 1, 1) } "trim whitespace around mgdRegNumber" in { diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala index 7642246..ef1a801 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala @@ -27,7 +27,7 @@ import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.* import uk.gov.hmrc.rdsdatacacheproxy.gambling.repositories.GamblingDataSource import scala.concurrent.Future -import java.sql.Date +import java.time.LocalDate class GamblingDataCacheRepositoryISpec extends AnyWordSpec @@ -153,7 +153,7 @@ class GamblingDataCacheRepositoryISpec businessName = "John Doe Co.", businessType = "Sole Proprietor", tradingName = "DoeDoe", - systemDate = Date.valueOf("2026-04-20") + systemDate = Some(LocalDate.of(2026, 4, 20)) ) } @@ -169,7 +169,7 @@ class GamblingDataCacheRepositoryISpec businessName = "Pretzel Wagon", businessType = "Sole Proprietor", tradingName = "Marge Simpson", - systemDate = Date.valueOf("2026-04-20") + systemDate = Some(LocalDate.of(2026, 4, 20)) ) } @@ -184,7 +184,7 @@ class GamblingDataCacheRepositoryISpec val result = repository.getBusinessName("XYZ00000000010").futureValue result.solePropMidName mustBe "Jacqueline" - result.systemDate mustBe Date.valueOf("2026-04-20") + result.systemDate mustBe Some(LocalDate.of(2026, 4, 20)) } "return correct title and trading name" in { @@ -213,7 +213,7 @@ class GamblingDataCacheRepositoryISpec businessName = "FooBar Co.", businessType = "Sole Proprietor", tradingName = "Foobar", - systemDate = Date.valueOf("2026-04-20") + systemDate = Some(LocalDate.of(2026, 4, 20)) ) } diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala index 17ab27b..6057b76 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala @@ -17,7 +17,7 @@ package uk.gov.hmrc.rdsdatacacheproxy.gambling import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.* -import java.sql.Date +import java.time.LocalDate object GamblingStubData { def getReturnSummary(mgdRegNumber: String): ReturnSummary = { @@ -39,9 +39,9 @@ object GamblingStubData { } } def getBusinessName(mgdRegNumber: String): BusinessName = { - val sqlDateOne: Date = Date.valueOf("2026-04-20") - val sqlDateTwo: Date = Date.valueOf("2026-01-01") - val sqlDateThree: Date = Date.valueOf("1992-01-01") + val dateTimeOne: Some[LocalDate] = Some(LocalDate.of(2026, 4, 20)) + val dateTimeTwo: Some[LocalDate] = Some(LocalDate.of(2026, 1, 1)) + val dateTimeThree: Some[LocalDate] = Some(LocalDate.of(1991, 1, 1)) mgdRegNumber match { case "XYZ00000000000" => BusinessName(mgdRegNumber, @@ -52,7 +52,7 @@ object GamblingStubData { businessName = "John Doe Co.", businessType = "Sole Proprietor", tradingName = "DoeDoe", - systemDate = sqlDateOne) + systemDate = dateTimeOne) case "XYZ00000000001" => BusinessName(mgdRegNumber, solePropTitle = "Mrs", @@ -62,7 +62,7 @@ object GamblingStubData { businessName = "Jane Doe Co.", businessType = "Sole Proprietor", tradingName = "DoeDoe", - systemDate = sqlDateTwo) + systemDate = dateTimeTwo) case "XYZ00000000010" => BusinessName(mgdRegNumber, solePropTitle = "Mrs", @@ -72,7 +72,7 @@ object GamblingStubData { businessName = "Pretzel Wagon", businessType = "Sole Proprietor", tradingName = "Marge Simpson", - systemDate = sqlDateOne) + systemDate = dateTimeOne) case "XYZ00000000012" => BusinessName(mgdRegNumber, solePropTitle = "Miss", @@ -82,7 +82,7 @@ object GamblingStubData { businessName = "Failed Expectations", businessType = "Sole Proprietor", tradingName = "Miss Havisham", - systemDate = sqlDateThree) + systemDate = dateTimeThree) case "XYZ00000000021" => BusinessName(mgdRegNumber, solePropTitle = "Mr", @@ -92,7 +92,7 @@ object GamblingStubData { businessName = "Krusty Krab", businessType = "Sole Proprietor", tradingName = "Mr Krabs", - systemDate = sqlDateThree) + systemDate = dateTimeThree) case "ERR00000000000" => throw new RuntimeException("Simulated downstream failure") case _ => @@ -104,7 +104,7 @@ object GamblingStubData { businessName= "FooBar Co.", businessType= "Sole Proprietor", tradingName= "Foobar", - systemDate= sqlDateOne + systemDate= dateTimeOne ) } } diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala index 9dddb53..d8b64fa 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala @@ -38,7 +38,7 @@ import org.mockito.Mockito.* import org.mockito.ArgumentMatchers.{any, eq as eqTo} import org.scalatest.matchers.should.Matchers.{should, shouldBe} import play.api.libs.json.{JsValue, Json} -import java.sql.Date +import java.time.LocalDate import play.api.test.FakeRequest import play.api.test.Helpers.* @@ -125,8 +125,8 @@ class GamblingControllerSpec extends SpecBase with MockitoSugar { "GamblingController#getBusinessName" - { "returns 200 when service succeeds" in new Setup { - val sqlDate: Date = Date.valueOf("2026-04-20") - val name = BusinessName("XWM00000001770", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", sqlDate) + val dateTime: Some[LocalDate] = Some(LocalDate.of(2026, 4, 20)) + val name = BusinessName("XWM00000001770", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", dateTime) when(mockService.getBusinessName(eqTo("XWM00000001770"))(any())) .thenReturn(Future.successful(Right(name))) @@ -143,8 +143,8 @@ class GamblingControllerSpec extends SpecBase with MockitoSugar { } "allows request through AuthAction" in new Setup { - val sqlDate: Date = Date.valueOf("2026-04-20") - val name = BusinessName("XWM00000001770", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", sqlDate) + val dateTime: Some[LocalDate] = Some(LocalDate.of(2026, 4, 20)) + val name = BusinessName("XWM00000001770", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", dateTime) when(mockService.getBusinessName(any())(any())) .thenReturn(Future.successful(Right(name))) diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingModelSpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingModelSpec.scala new file mode 100644 index 0000000..52cbe54 --- /dev/null +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingModelSpec.scala @@ -0,0 +1,89 @@ +/* + * Copyright 2026 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. + */ + +import org.scalatest.matchers.must.Matchers +import org.scalatest.wordspec.AnyWordSpec +import play.api.libs.json.Json +import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.* +import java.time.LocalDate + + +class GamblingModelSpec extends AnyWordSpec with Matchers { + + + "ReturnSummaryModel" should { + "read and write a full-populated object" in { + val jsonAsString: String = + s""" + |{ + |"mgdRegNumber": "XYZ00000000000", + |"returnsDue": 2, + |"returnsOverdue": 1 + |} + """.stripMargin + + + val json = Json.parse(jsonAsString) + val model = json.as[ReturnSummary] + + model mustBe ReturnSummary( + mgdRegNumber = "XYZ00000000000", + returnsDue = 2, + returnsOverdue = 1 + ) + + Json.toJson(model) mustBe json + } + } + "BusinessNameModel" should { + val dateBusinessName: LocalDate = LocalDate.of(1991, 1, 1) + "read and write a full-populated object" in { + val jsonAsString: String = + s""" + |{ + |"mgdRegNumber": "XYZ00000000000", + |"solePropTitle": "Mr", + |"solePropFirstName": "John", + |"solePropMidName": "C", + |"solePropLastName": "Doe", + |"businessName": "John Doe Co.", + |"businessType": "Sole Proprietor", + |"tradingName": "DoeDoe", + |"systemDate": "$dateBusinessName" + |} + """.stripMargin + + + val json = Json.parse(jsonAsString) + val model = json.as[BusinessName] + + model mustBe BusinessName( + mgdRegNumber = "XYZ00000000000", + solePropTitle = "Mr", + solePropFirstName = "John", + solePropMidName = "C", + solePropLastName = "Doe", + businessName = "John Doe Co.", + businessType = "Sole Proprietor", + tradingName = "DoeDoe", + systemDate = Some(dateBusinessName) + ) + + Json.toJson(model) mustBe json + } + } +} + diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala index f236378..939def8 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala @@ -25,7 +25,8 @@ import org.scalatest.matchers.should.Matchers import play.api.db.Database import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.* -import java.sql.{CallableStatement, Connection, Date, ResultSet} +import java.time.LocalDate +import java.sql.{CallableStatement, Connection, ResultSet} import scala.concurrent.ExecutionContext.Implicits.global class GamblingDataCacheRepositorySpec extends AnyFlatSpec with Matchers with BeforeAndAfter { @@ -106,7 +107,7 @@ class GamblingDataCacheRepositorySpec extends AnyFlatSpec with Matchers with Bef when(mockResultSet.getString("BUSINESS_NAME")).thenReturn("Foo Bar Co.") when(mockResultSet.getString("BUSINESS_TYPE")).thenReturn("Sole Proprietor") when(mockResultSet.getString("TRADING_NAME")).thenReturn("Foobar") - when(mockResultSet.getDate("SYSTEM_DATE")).thenReturn(Date.valueOf("2026-04-20")) + when(mockResultSet.getDate("SYSTEM_DATE")).thenReturn(java.sql.Date.valueOf("2024-04-21")) val result = repository.getBusinessName(mgdRegNumber).futureValue @@ -119,7 +120,7 @@ class GamblingDataCacheRepositorySpec extends AnyFlatSpec with Matchers with Bef businessName = "Foo Bar Co.", businessType = "Sole Proprietor", tradingName = "Foobar", - systemDate = Date.valueOf("2026-04-20") + systemDate = Some(LocalDate.of(2024, 4, 21)) ) verifyDbSetup(mgdRegNumber) @@ -173,7 +174,7 @@ class GamblingDataCacheRepositorySpec extends AnyFlatSpec with Matchers with Bef ) } - it should "throw exception when result set is empty" in { + it should "throw exception when result set is empty (returnSummary)" in { val mgdRegNumber = "XWM12345678901" @@ -189,6 +190,22 @@ class GamblingDataCacheRepositorySpec extends AnyFlatSpec with Matchers with Bef verifyCleanup() } + it should "throw exception when result set is empty (businessName)" in { + + val mgdRegNumber = "XWM12345678901" + + when(mockResultSet.next()).thenReturn(false) + + val exception = intercept[RuntimeException] { + repository.getBusinessName(mgdRegNumber).futureValue + } + + exception.getMessage should include("Empty result set") + + verifyDbSetup(mgdRegNumber) + verifyCleanup() + } + it should "fail when cursor is not a ResultSet" in { when(mockCallableStatement.getObject(2)).thenReturn("invalid") @@ -234,7 +251,7 @@ class GamblingDataCacheRepositorySpec extends AnyFlatSpec with Matchers with Bef verify(mockCallableStatement).close() } - it should "throw exception when cursor is null" in { + it should "throw exception when cursor is null (returnSummary)" in { val mgdRegNumber = "ABC12345678901" @@ -254,4 +271,24 @@ class GamblingDataCacheRepositorySpec extends AnyFlatSpec with Matchers with Bef verify(mockCallableStatement).close() } + it should "throw exception when cursor is null (businessName)" in { + + val mgdRegNumber = "ABC12345678901" + + when(mockCallableStatement.getObject(2)).thenReturn(null) + + val exception = intercept[RuntimeException] { + repository.getBusinessName(mgdRegNumber).futureValue + } + + exception.getMessage should include("Null cursor") + + verify(mockCallableStatement).setString(1, mgdRegNumber) + verify(mockCallableStatement).registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR) + verify(mockCallableStatement).execute() + verify(mockCallableStatement).getObject(2) + + verify(mockCallableStatement).close() + } + } diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala index 756c103..c5d291b 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala @@ -25,8 +25,7 @@ import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.GamblingError.{InvalidMgdRe import uk.gov.hmrc.rdsdatacacheproxy.gambling.repositories.GamblingDataSource import scala.concurrent.Future -import java.sql.Date - +import java.time.LocalDate final class GamblingServiceSpec extends SpecBase { private val repository = mock[GamblingDataSource] @@ -106,7 +105,7 @@ final class GamblingServiceSpec extends SpecBase { businessName = "FooBar Co.", businessType = "Sole Proprietor", tradingName = "Foobar", - systemDate = Date.valueOf("1992-01-01") + systemDate = Some(LocalDate.of(1991, 1, 1)) ) when(repository.getBusinessName(eqTo(validMgdRegNumber))) @@ -132,7 +131,7 @@ final class GamblingServiceSpec extends SpecBase { businessName = "John Doe Co.", businessType = "Sole Proprietor", tradingName = "DoeDoe", - systemDate = Date.valueOf("1992-01-01") + systemDate = Some(LocalDate.of(1991, 1, 1)) ) when(repository.getBusinessName(eqTo(normalisedMgdRegNumber))) From 44e1e0c457f16548547c3cf7ea016f8d66038eef Mon Sep 17 00:00:00 2001 From: AnotherMattWright <270914550+AnotherMattWright@users.noreply.github.com> Date: Fri, 24 Apr 2026 14:36:21 +0100 Subject: [PATCH 06/16] DTR-4218 pulled into DTR-4210 --- .../controllers/GamblingController.scala | 17 ++ .../gambling/models/BusinessDetails.scala | 34 ++++ .../GamblingDataCacheRepository.scala | 49 ++++++ .../gambling/services/GamblingService.scala | 19 +++ conf/app.routes | 1 + .../GamblingControllerIntegrationSpec.scala | 161 +++++++++++++++++- .../GamblingDataCacheRepositoryISpec.scala | 99 ++++++++++- .../gambling/GamblingStubData.scala | 55 ++++++ .../controllers/GamblingControllerSpec.scala | 71 +++++++- .../gambling/models/GamblingModelSpec.scala | 62 +++++-- .../GamblingDataCacheRepositorySpec.scala | 129 +++++++++++++- .../services/GamblingServiceSpec.scala | 68 +++++++- 12 files changed, 741 insertions(+), 24 deletions(-) create mode 100644 app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessDetails.scala diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingController.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingController.scala index 1f53780..357acae 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingController.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingController.scala @@ -65,5 +65,22 @@ class GamblingController @Inject() (authorise: AuthAction, service: GamblingServ } } + def getBusinessDetails(mgdRegNumber: String): Action[AnyContent] = authorise.async { implicit request => + + service.getBusinessDetails(mgdRegNumber).map { + case Right(summary) => Ok(Json.toJson(summary)) + case Left(error) => + val logMessage = s"[GamblingController][getBusinessDetails] code=${error.code} mgdRegNumber=$mgdRegNumber" + error match { + case InvalidMgdRegNumber => + logger.warn(logMessage) + BadRequest(errorResponse(error)) + case UnexpectedError => + logger.error(logMessage) + InternalServerError(errorResponse(error)) + } + } + } + private def errorResponse(error: GamblingError) = Json.obj("code" -> error.code, "message" -> error.message) } diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessDetails.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessDetails.scala new file mode 100644 index 0000000..f134fee --- /dev/null +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessDetails.scala @@ -0,0 +1,34 @@ +/* + * Copyright 2026 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.rdsdatacacheproxy.gambling.models + +import play.api.libs.json.{Json, OFormat} + +import java.time.LocalDate + +case class BusinessDetails(mgdRegNumber: String, + businessType: Int, + currentlyRegistered: Int, + groupReg: String, + dateOfRegistration: Option[LocalDate], + businessPartnerNumber: String, + systemDate: Option[LocalDate] + ) + +object BusinessDetails { + implicit val format: OFormat[BusinessDetails] = Json.format[BusinessDetails] +} diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala index 31bcf4e..8cd0a04 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala @@ -24,6 +24,7 @@ import scala.concurrent.{ExecutionContext, Future} trait GamblingDataSource { def getReturnSummary(mgdRegNumber: String): Future[ReturnSummary] + def getBusinessDetails(mgdRegNumber: String): Future[BusinessDetails] def getBusinessName(mgdRegNumber: String): Future[BusinessName] } @@ -126,4 +127,52 @@ class GamblingDataCacheRepository @Inject() ( } }(ec) } + + override def getBusinessDetails(mgdRegNumber: String): Future[BusinessDetails] = { + + logger.info(s"[GamblingDataCacheRepository][getBusinessDetails] mgdRegNumber=$mgdRegNumber") + + Future { + db.withConnection { conn => + + val cs = conn.prepareCall("{ call MGD_DC_VARIATION_PK.GET_BUSINESS_DETAILS(?, ?) }") + + try { + cs.setString(1, mgdRegNumber) + cs.registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR) + cs.execute() + + val rs = cs.getObject(2).asInstanceOf[java.sql.ResultSet] + + if (rs == null) { + val msg = s"Null cursor returned for mgdRegNumber=$mgdRegNumber" + logger.error(s"[GamblingDataCacheRepository] $msg") + throw new RuntimeException(msg) + } + + try { + if (rs.next()) { + BusinessDetails( + mgdRegNumber = rs.getString("MGD_REG_NUMBER"), + businessType = rs.getInt("BUSINESS_TYPE"), + currentlyRegistered = rs.getInt("CURRENTLY_REGISTERED"), + groupReg = rs.getString("GROUP_REG"), + dateOfRegistration = Option(rs.getDate("DATE_OF_REGISTRATION")).map(_.toLocalDate), + businessPartnerNumber = rs.getString("BUSINESS_PARTNER_NUMBER"), + systemDate = Option(rs.getDate("SYSTEM_DATE")).map(_.toLocalDate) + ) + } else { + val msg = s"Empty result set for mgdRegNumber=$mgdRegNumber" + logger.error(s"[GamblingDataCacheRepository] $msg") + throw new RuntimeException(msg) + } + } finally { + rs.close() + } + } finally { + cs.close() + } + } + }(ec) + } } diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingService.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingService.scala index 499f457..58ccb84 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingService.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingService.scala @@ -69,4 +69,23 @@ class GamblingService @Inject() ( } } } + + def getBusinessDetails(rawMgdRegNumber: String)(implicit hc: HeaderCarrier): Future[Either[GamblingError, BusinessDetails]] = { + + val mgdRegNumber = rawMgdRegNumber.trim.toUpperCase + + if (!mgdRegNumberPattern.matcher(mgdRegNumber).matches()) { + logger.warn(s"[GamblingService][getBusinessDetails] Invalid pattern for mgdRegNumber=$mgdRegNumber") + Future.successful(Left(InvalidMgdRegNumber)) + } else { + + repository + .getBusinessDetails(mgdRegNumber) + .map(summary => Right(summary)) + .recover { case ex: Exception => + logger.error(s"[GamblingService][getBusinessDetails] Unexpected error mgdRegNumber=$mgdRegNumber", ex) + Left(UnexpectedError) + } + } + } } diff --git a/conf/app.routes b/conf/app.routes index 3e73215..4bfc8db 100644 --- a/conf/app.routes +++ b/conf/app.routes @@ -36,4 +36,5 @@ GET /charities/organisations/:charityRef uk.gov.hmrc.rdsdatacac #MGD routes GET /gambling/return-summary/:mgdRegNumber uk.gov.hmrc.rdsdatacacheproxy.gambling.controllers.GamblingController.getReturnSummary(mgdRegNumber: String) +GET /gambling/business-details/:mgdRegNumber uk.gov.hmrc.rdsdatacacheproxy.gambling.controllers.GamblingController.getBusinessDetails(mgdRegNumber: String) GET /gambling/business-name/:mgdRegNumber uk.gov.hmrc.rdsdatacacheproxy.gambling.controllers.GamblingController.getBusinessName(mgdRegNumber: String) diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingControllerIntegrationSpec.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingControllerIntegrationSpec.scala index 87d2426..29db7ef 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingControllerIntegrationSpec.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingControllerIntegrationSpec.scala @@ -23,12 +23,14 @@ import play.api.Application import play.api.http.Status.* import play.api.inject.bind import play.api.inject.guice.GuiceApplicationBuilder +import play.api.libs.json.Reads + import scala.concurrent.ExecutionContext.Implicits.global import uk.gov.hmrc.rdsdatacacheproxy.gambling.repositories.GamblingDataSource import uk.gov.hmrc.rdsdatacacheproxy.itutil.{ApplicationWithWiremock, AuthStub} -import scala.concurrent.Future import java.time.LocalDate +import scala.concurrent.Future class GamblingControllerIntegrationSpec extends AnyWordSpec @@ -46,6 +48,11 @@ class GamblingControllerIntegrationSpec Future { GamblingStubData.getBusinessName(mgdRegNumber) } + + override def getBusinessDetails(mgdRegNumber: String) = + Future { + GamblingStubData.getBusinessDetails(mgdRegNumber) + } } @@ -57,6 +64,14 @@ class GamblingControllerIntegrationSpec ) .build() + private val businessDetailEndpoint = "/gambling/business-details" + + implicit val localDateReads: Reads[LocalDate] = + Reads.localDateReads("yyyy-MM-dd") + + implicit val optLocalDateReads: Reads[Option[LocalDate]] = + Reads.optionWithNull[LocalDate] + private val endpointReturnSummary = "/gambling/return-summary" private val endpointBusinessName = "/gambling/business-name" @@ -333,4 +348,148 @@ class GamblingControllerIntegrationSpec } } + + "GET /gambling/business-details (stubbed repo, no DB)" should { + + "return 200 with correct summary (0,0)" in { + AuthStub.authorised() + + val response = get(s"$businessDetailEndpoint/XYZ00000000000").futureValue + + response.status mustBe OK + response.contentType mustBe "application/json" + + (response.json \ "mgdRegNumber").as[String] mustBe "XYZ00000000000" + (response.json \ "businessType").as[Int] mustBe 6 + (response.json \ "currentlyRegistered").as[Int] mustBe 2 + (response.json \ "groupReg").as[String] mustBe "foo" + (response.json \ "dateOfRegistration").as[Option[LocalDate]] mustBe Some(LocalDate.of(2024, 4, 21)) + (response.json \ "businessPartnerNumber").as[String] mustBe "bar" + (response.json \ "systemDate").as[Option[LocalDate]] mustBe Some(LocalDate.of(2024, 4, 21)) + } + + "normalise lowercase input" in { + AuthStub.authorised() + val response = get(s"$businessDetailEndpoint/xyz00000000012 ").futureValue + response.status mustBe OK + (response.json \ "mgdRegNumber").as[String] mustBe "XYZ00000000012" + } + + "return default values for unknown mgdRegNumber" in { + AuthStub.authorised() + val response = get(s"$businessDetailEndpoint/XYZ99999999999").futureValue + response.status mustBe OK + (response.json \ "businessType").as[Int] mustBe 0 + (response.json \ "currentlyRegistered").as[Int] mustBe 0 + (response.json \ "groupReg").as[String] mustBe "unknown" + (response.json \ "dateOfRegistration").as[Option[LocalDate]] mustBe Some(LocalDate.of(2026, 4, 22)) + (response.json \ "businessPartnerNumber").as[String] mustBe "unknown" + (response.json \ "systemDate").as[Option[LocalDate]] mustBe Some(LocalDate.of(2026, 4, 22)) + + } + + "return 200 with correct summary (1,2)" in { + AuthStub.authorised() + val response = get(s"$businessDetailEndpoint/XYZ00000000012").futureValue + response.status mustBe OK + response.contentType mustBe "application/json" + (response.json \ "mgdRegNumber").as[String] mustBe "XYZ00000000012" + (response.json \ "businessType").as[Int] mustBe 1 + (response.json \ "currentlyRegistered").as[Int] mustBe 2 + (response.json \ "groupReg").as[String] mustBe "foobar" + (response.json \ "dateOfRegistration").as[Option[LocalDate]] mustBe Some(LocalDate.of(2023, 4, 21)) + (response.json \ "businessPartnerNumber").as[String] mustBe "barfoo" + (response.json \ "systemDate").as[Option[LocalDate]] mustBe Some(LocalDate.of(2023, 4, 21)) + + } + + "return 200 with correct summary (2,1)" in { + AuthStub.authorised() + val response = get(s"$businessDetailEndpoint/XYZ00000000021").futureValue + response.status mustBe OK + (response.json \ "businessType").as[Int] mustBe 5 + (response.json \ "currentlyRegistered").as[Int] mustBe 2 + (response.json \ "groupReg").as[String] mustBe "foofoo" + (response.json \ "dateOfRegistration").as[Option[LocalDate]] mustBe Some(LocalDate.of(2024, 1, 21)) + (response.json \ "businessPartnerNumber").as[String] mustBe "barbar" + (response.json \ "systemDate").as[Option[LocalDate]] mustBe Some(LocalDate.of(2024, 1, 21)) + + } + + "trim whitespace around mgdRegNumber" in { + AuthStub.authorised() + val response = get(s"$businessDetailEndpoint/ XYZ00000000010 ").futureValue + response.status mustBe OK + (response.json \ "mgdRegNumber").as[String] mustBe "XYZ00000000010" + } + + "return consistent results across multiple calls" in { + AuthStub.authorised() + val res1 = get(s"$businessDetailEndpoint/XYZ00000000012").futureValue + val res2 = get(s"$businessDetailEndpoint/XYZ00000000012").futureValue + res1.json mustBe res2.json + } + + "return JSON content type for valid response" in { + AuthStub.authorised() + val response = get(s"$businessDetailEndpoint/XYZ00000000012").futureValue + response.contentType mustBe "application/json" + } + + + "return 400 for partially valid mgdRegNumber (wrong length)" in { + AuthStub.authorised() + val response = get(s"$businessDetailEndpoint/XYZ123").futureValue + response.status mustBe BAD_REQUEST + } + + "return 400 for mgdRegNumber with special characters" in { + AuthStub.authorised() + val response = get(s"$businessDetailEndpoint/XYZ00000@00000").futureValue + response.status mustBe BAD_REQUEST + } + + "return 400 for invalid mgdRegNumber format" in { + AuthStub.authorised() + + val response = get(s"$businessDetailEndpoint/INVALID").futureValue + response.status mustBe BAD_REQUEST + (response.json \ "code").as[String] mustBe "INVALID_MGD_REG_NUMBER" + (response.json \ "message").as[String] mustBe "mgdRegNumber does not exist" + } + + "return 401 when unauthorised" in { + AuthStub.unauthorised() + val response = get(s"$businessDetailEndpoint/XYZ00000000000").futureValue + response.status mustBe UNAUTHORIZED + } + + "return 404 for missing mgdRegNumber" in { + AuthStub.authorised() + val response = get(s"$businessDetailEndpoint/").futureValue + response.status mustBe NOT_FOUND + } + + "return 404 for whitespace-only mgdRegNumber" in { + AuthStub.authorised() + val response = get(s"$businessDetailEndpoint/ ").futureValue + response.status mustBe NOT_FOUND + } + + "return 500 when stub simulates failure" in { + AuthStub.authorised() + val response = get(s"$businessDetailEndpoint/ERR00000000000").futureValue + response.status mustBe INTERNAL_SERVER_ERROR + (response.json \ "code").as[String] mustBe "UNEXPECTED_ERROR" + } + + "return correct error structure for 500 response" in { + AuthStub.authorised() + val response = get(s"$businessDetailEndpoint/ERR00000000000").futureValue + response.status mustBe INTERNAL_SERVER_ERROR + (response.json \ "code").as[String] mustBe "UNEXPECTED_ERROR" + (response.json \ "message").as[String] mustBe "Unexpected error occurred" + } + + } } \ No newline at end of file diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala index ef1a801..3628ac7 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala @@ -26,8 +26,8 @@ import play.api.inject.guice.GuiceApplicationBuilder import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.* import uk.gov.hmrc.rdsdatacacheproxy.gambling.repositories.GamblingDataSource -import scala.concurrent.Future import java.time.LocalDate +import scala.concurrent.Future class GamblingDataCacheRepositoryISpec extends AnyWordSpec @@ -41,6 +41,9 @@ class GamblingDataCacheRepositoryISpec Future.successful(GamblingStubData.getReturnSummary(mgdRegNumber)) override def getBusinessName(mgdRegNumber: String): Future[BusinessName] = Future.successful(GamblingStubData.getBusinessName(mgdRegNumber)) + + override def getBusinessDetails(mgdRegNumber: String): Future[BusinessDetails] = + Future.successful(GamblingStubData.getBusinessDetails(mgdRegNumber)) } override lazy val app: Application = new GuiceApplicationBuilder() @@ -263,4 +266,98 @@ class GamblingDataCacheRepositoryISpec result.tradingName must not be empty } } + + "getBusinessDetails (stubbed repository)" should { + + "return values correctly" in { + val result = repository.getBusinessDetails("XYZ00000000000").futureValue + + result mustBe BusinessDetails( + mgdRegNumber = "XYZ00000000000", + businessType = 6, + currentlyRegistered = 2, + groupReg = "foo", + dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = "bar", systemDate = Some(LocalDate.of(2024, 4, 21)) + ) + } + + "return business type correctly" in { + val result = repository.getBusinessDetails("XYZ00000000001").futureValue + + result.businessType mustBe 1 + result.currentlyRegistered mustBe 1 + result.groupReg mustBe "foofoo" + result.dateOfRegistration mustBe Some(LocalDate.of(2024, 4, 21)) + result.businessPartnerNumber mustBe "bar" + result.systemDate mustBe Some(LocalDate.of(2024, 4, 21)) + } + + "return group reg correctly" in { + val result = repository.getBusinessDetails("XYZ00000000010").futureValue + + result.businessType mustBe 3 + result.currentlyRegistered mustBe 2 + result.groupReg mustBe "foo" + result.dateOfRegistration mustBe Some(LocalDate.of(2024, 4, 21)) + result.businessPartnerNumber mustBe "bar" + result.systemDate mustBe Some(LocalDate.of(2024, 4, 21)) + } + + "return both date values correctly" in { + val result = repository.getBusinessDetails("XYZ00000000012").futureValue + + result mustBe BusinessDetails("XYZ00000000012", 1, 2, "foobar", Some(LocalDate.of(2023, 4, 21)), "barfoo", Some(LocalDate.of(2023, 4, 21))) + } + + "handle multiple values" in { + val result = repository.getBusinessDetails("XYZ00000000021").futureValue + + result.businessType mustBe 5 + result.currentlyRegistered mustBe 2 + result.groupReg mustBe "foofoo" + result.dateOfRegistration mustBe Some(LocalDate.of(2024, 1, 21)) + result.businessPartnerNumber mustBe "barbar" + result.systemDate mustBe Some(LocalDate.of(2024, 1, 21)) + } + + "return default values for unknown mgdRegNumber" in { + val result = repository.getBusinessDetails("XYZ99999999999").futureValue + + result mustBe BusinessDetails("XYZ99999999999", 0, 0, "unknown", Some(LocalDate.of(2026, 4, 22)), "unknown", Some(LocalDate.of(2026, 4, 22))) + } + + "return consistent results across multiple calls" in { + val result1 = repository.getBusinessDetails("XYZ00000000012").futureValue + val result2 = repository.getBusinessDetails("XYZ00000000012").futureValue + + result1 mustBe result2 + } + + "handle different valid mgdRegNumbers independently" in { + val result1 = repository.getBusinessDetails("XYZ00000000010").futureValue + val result2 = repository.getBusinessDetails("XYZ00000000001").futureValue + + result1 must not be result2 + } + + "propagate downstream failure from stub" in { + val exception = intercept[RuntimeException] { + repository.getBusinessDetails("ERR00000000000").futureValue + } + + exception.getMessage must include("Simulated downstream failure") + } + + "handle special characters in mgdRegNumber" in { + val result = repository.getBusinessDetails("XYZ-123/ABC").futureValue + + result mustBe BusinessDetails("XYZ-123/ABC", 0, 0, "unknown", Some(LocalDate.of(2026, 4, 22)), "unknown", Some(LocalDate.of(2026, 4, 22))) + } + + "handle whitespace mgdRegNumber" in { + val result = repository.getBusinessDetails(" ").futureValue + + result mustBe BusinessDetails(" ", 0, 0, "unknown", Some(LocalDate.of(2026, 4, 22)), "unknown", Some(LocalDate.of(2026, 4, 22))) + } + } } \ No newline at end of file diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala index 6057b76..9ccc4d3 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala @@ -110,3 +110,58 @@ object GamblingStubData { } } + + def getBusinessDetails(mgdRegNumber: String): BusinessDetails = + mgdRegNumber match { + case "XYZ00000000000" => + BusinessDetails( + mgdRegNumber = mgdRegNumber, + businessType = 6, + currentlyRegistered = 2, + groupReg = "foo", + dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = "bar", systemDate = Some(LocalDate.of(2024, 4, 21)) + ) + case "XYZ00000000001" => + BusinessDetails( + mgdRegNumber = mgdRegNumber, + businessType = 1, + currentlyRegistered = 1, + groupReg = "foofoo", + dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = "bar", systemDate = Some(LocalDate.of(2024, 4, 21)) + ) + case "XYZ00000000010" => + BusinessDetails( + mgdRegNumber = mgdRegNumber, + businessType = 3, + currentlyRegistered = 2, + groupReg = "foo", + dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = "bar", systemDate = Some(LocalDate.of(2024, 4, 21)) + ) + case "XYZ00000000012" => + BusinessDetails( + mgdRegNumber = mgdRegNumber, + businessType = 1, + currentlyRegistered = 2, + groupReg = "foobar", + dateOfRegistration = Some(LocalDate.of(2023, 4, 21)), businessPartnerNumber = "barfoo", systemDate = Some(LocalDate.of(2023, 4, 21)) + ) + case "XYZ00000000021" => + BusinessDetails( + mgdRegNumber = mgdRegNumber, + businessType = 5, + currentlyRegistered = 2, + groupReg = "foofoo", + dateOfRegistration = Some(LocalDate.of(2024, 1, 21)), businessPartnerNumber = "barbar", systemDate = Some(LocalDate.of(2024, 1, 21)) + ) + case "ERR00000000000" => + throw new RuntimeException("Simulated downstream failure") + case _ => + BusinessDetails( + mgdRegNumber = mgdRegNumber, + businessType = 0, + currentlyRegistered = 0, + groupReg = "unknown", + dateOfRegistration = Some(LocalDate.of(2026, 4, 22)), businessPartnerNumber = "unknown", systemDate = Some(LocalDate.of(2026, 4, 22)) + ) + } +} diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala index d8b64fa..84d8fb9 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala @@ -38,16 +38,15 @@ import org.mockito.Mockito.* import org.mockito.ArgumentMatchers.{any, eq as eqTo} import org.scalatest.matchers.should.Matchers.{should, shouldBe} import play.api.libs.json.{JsValue, Json} -import java.time.LocalDate - import play.api.test.FakeRequest import play.api.test.Helpers.* import uk.gov.hmrc.rdsdatacacheproxy.base.SpecBase import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.GamblingError.{InvalidMgdRegNumber, UnexpectedError} -import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.ReturnSummary +import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.{BusinessDetails, ReturnSummary} import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.BusinessName import uk.gov.hmrc.rdsdatacacheproxy.gambling.services.GamblingService +import java.time.LocalDate import scala.concurrent.Future class GamblingControllerSpec extends SpecBase with MockitoSugar { @@ -189,4 +188,70 @@ class GamblingControllerSpec extends SpecBase with MockitoSugar { verify(mockService).getBusinessName(eqTo("ERR00001770"))(any()) } + "GamblingController#getBusinessDetails" - { + + "returns 200 when service succeeds for BusinessDetails" in new Setup { + val summary = BusinessDetails("XWM00000001770", 2, 1, "foo", Some(LocalDate.of(2024, 4, 21)), "bar", Some(LocalDate.of(2024, 4, 21))) + + when(mockService.getBusinessDetails(eqTo("XWM00000001770"))(any())) + .thenReturn(Future.successful(Right(summary))) + + val req = FakeRequest(GET, "/gambling/business-details/XWM00000001770") + val res = controller.getBusinessDetails("XWM00000001770")(req) + + status(res) mustBe OK + contentType(res) mustBe Some(JSON) + contentAsJson(res) mustBe Json.toJson(summary) + + verify(mockService).getBusinessDetails(eqTo("XWM00000001770"))(any()) + verifyNoMoreInteractions(mockService) + } + + "allows request through AuthAction for BusinessDetails" in new Setup { + val summary = BusinessDetails("XWM00000001770", 2, 1, "foo", Some(LocalDate.of(2024, 4, 21)), "bar", Some(LocalDate.of(2024, 4, 21))) + + when(mockService.getBusinessDetails(any())(any())) + .thenReturn(Future.successful(Right(summary))) + + val req = FakeRequest(GET, "/gambling/business-details/XWM00000001770") + val res = controller.getBusinessDetails("XWM00000001770")(req) + + status(res) mustBe OK + + verify(mockService).getBusinessDetails(eqTo("XWM00000001770"))(any()) + } + } + + "returns 400 when InvalidMgdRegNumber for BusinessDetails" in new Setup { + when(mockService.getBusinessDetails(any())(any())) + .thenReturn(Future.successful(Left(InvalidMgdRegNumber))) + + val req = FakeRequest(GET, "/gambling/business-details/jhrfdshgksdhg") + val res = controller.getBusinessDetails(" ")(req) + + status(res) mustBe BAD_REQUEST + contentAsJson(res) mustBe Json.obj( + "code" -> "INVALID_MGD_REG_NUMBER", + "message" -> "mgdRegNumber does not exist" + ) + + verify(mockService).getBusinessDetails(eqTo(" "))(any()) + } + + "returns 500 when UnexpectedError for BusinessDetails" in new Setup { + when(mockService.getBusinessDetails(any())(any())) + .thenReturn(Future.successful(Left(UnexpectedError))) + + val req = FakeRequest(GET, "/gambling/business-details/ERR00001770") + val res = controller.getBusinessDetails("ERR00001770")(req) + + status(res) mustBe INTERNAL_SERVER_ERROR + contentAsJson(res) mustBe Json.obj( + "code" -> "UNEXPECTED_ERROR", + "message" -> "Unexpected error occurred" + ) + + verify(mockService).getBusinessDetails(eqTo("ERR00001770"))(any()) + } + } diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingModelSpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingModelSpec.scala index 52cbe54..5251101 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingModelSpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingModelSpec.scala @@ -20,10 +20,8 @@ import play.api.libs.json.Json import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.* import java.time.LocalDate - class GamblingModelSpec extends AnyWordSpec with Matchers { - "ReturnSummaryModel" should { "read and write a full-populated object" in { val jsonAsString: String = @@ -35,21 +33,20 @@ class GamblingModelSpec extends AnyWordSpec with Matchers { |} """.stripMargin - val json = Json.parse(jsonAsString) val model = json.as[ReturnSummary] model mustBe ReturnSummary( - mgdRegNumber = "XYZ00000000000", - returnsDue = 2, + mgdRegNumber = "XYZ00000000000", + returnsDue = 2, returnsOverdue = 1 ) Json.toJson(model) mustBe json } } - "BusinessNameModel" should { - val dateBusinessName: LocalDate = LocalDate.of(1991, 1, 1) + "BusinessNameModel" should { + val dateBusinessName: LocalDate = LocalDate.of(1991, 1, 1) "read and write a full-populated object" in { val jsonAsString: String = s""" @@ -66,24 +63,55 @@ class GamblingModelSpec extends AnyWordSpec with Matchers { |} """.stripMargin - val json = Json.parse(jsonAsString) val model = json.as[BusinessName] model mustBe BusinessName( - mgdRegNumber = "XYZ00000000000", - solePropTitle = "Mr", + mgdRegNumber = "XYZ00000000000", + solePropTitle = "Mr", solePropFirstName = "John", - solePropMidName = "C", - solePropLastName = "Doe", - businessName = "John Doe Co.", - businessType = "Sole Proprietor", - tradingName = "DoeDoe", - systemDate = Some(dateBusinessName) + solePropMidName = "C", + solePropLastName = "Doe", + businessName = "John Doe Co.", + businessType = "Sole Proprietor", + tradingName = "DoeDoe", + systemDate = Some(dateBusinessName) ) Json.toJson(model) mustBe json } } -} + "BusinessDetailsModel" should { + val date: LocalDate = LocalDate.of(2000, 1, 1) + "read and write a full-populated object" in { + val jsonAsString: String = + s""" + |{ + |"mgdRegNumber": "XYZ00000000000", + |"businessType": 1, + |"currentlyRegistered": 1, + |"groupReg": "foo", + |"dateOfRegistration": "$date", + |"businessPartnerNumber": "bar", + |"systemDate": "$date" + |} + """.stripMargin + + val json = Json.parse(jsonAsString) + val model = json.as[BusinessDetails] + + model mustBe BusinessDetails( + mgdRegNumber = "XYZ00000000000", + businessType = 1, + currentlyRegistered = 1, + groupReg = "foo", + dateOfRegistration = Some(LocalDate.of(2000, 1, 1)), + businessPartnerNumber = "bar", + systemDate = Some(LocalDate.of(2000, 1, 1)) + ) + + Json.toJson(model) mustBe json + } + } +} diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala index 939def8..fcab321 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala @@ -25,8 +25,8 @@ import org.scalatest.matchers.should.Matchers import play.api.db.Database import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.* -import java.time.LocalDate import java.sql.{CallableStatement, Connection, ResultSet} +import java.time.LocalDate import scala.concurrent.ExecutionContext.Implicits.global class GamblingDataCacheRepositorySpec extends AnyFlatSpec with Matchers with BeforeAndAfter { @@ -291,4 +291,131 @@ class GamblingDataCacheRepositorySpec extends AnyFlatSpec with Matchers with Bef verify(mockCallableStatement).close() } + "getBusinessDetails" should "return BusinessDetails when stored procedure returns data" in { + + val mgdRegNumber = "XWM12345678901" + + when(mockResultSet.next()).thenReturn(true) + when(mockResultSet.getString("MGD_REG_NUMBER")).thenReturn(mgdRegNumber) + when(mockResultSet.getInt("BUSINESS_TYPE")).thenReturn(5) + when(mockResultSet.getInt("CURRENTLY_REGISTERED")).thenReturn(2) + when(mockResultSet.getString("GROUP_REG")).thenReturn("foo") + when(mockResultSet.getDate("DATE_OF_REGISTRATION")).thenReturn(java.sql.Date.valueOf("2024-04-21")) + when(mockResultSet.getString("BUSINESS_PARTNER_NUMBER")).thenReturn("bar") + when(mockResultSet.getDate("SYSTEM_DATE")).thenReturn(java.sql.Date.valueOf("2024-04-21")) + + val result = repository.getBusinessDetails(mgdRegNumber).futureValue + + result shouldBe BusinessDetails( + mgdRegNumber = mgdRegNumber, + businessType = 5, + currentlyRegistered = 2, + groupReg = "foo", + dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), + businessPartnerNumber = "bar", + systemDate = Some(LocalDate.of(2024, 4, 21)) + ) + verifyDbSetup(mgdRegNumber) + + verify(mockResultSet).next() + verify(mockResultSet).getString("MGD_REG_NUMBER") + verify(mockResultSet).getInt("BUSINESS_TYPE") + verify(mockResultSet).getInt("CURRENTLY_REGISTERED") + verify(mockResultSet).getString("GROUP_REG") + verify(mockResultSet).getDate("DATE_OF_REGISTRATION") + verify(mockResultSet).getString("BUSINESS_PARTNER_NUMBER") + verify(mockResultSet).getDate("SYSTEM_DATE") + + verifyCleanup() + } + + it should "handle null values in result set safely" in { + when(mockResultSet.next()).thenReturn(true) + when(mockResultSet.getString("MGD_REG_NUMBER")).thenReturn(null) + + val result = repository.getBusinessDetails("XWM12345678901").futureValue + + result.mgdRegNumber shouldBe null + } + + it should "throw exception when result set is empty" in { + + val mgdRegNumber = "XWM12345678901" + + when(mockResultSet.next()).thenReturn(false) + + val exception = intercept[RuntimeException] { + repository.getBusinessDetails(mgdRegNumber).futureValue + } + + exception.getMessage should include("Empty result set") + + verifyDbSetup(mgdRegNumber) + verifyCleanup() + } + + it should "fail when cursor is not a ResultSet" in { + when(mockCallableStatement.getObject(2)).thenReturn("invalid") + + val ex = repository.getBusinessDetails("XWM12345678901").failed.futureValue + ex shouldBe a[ClassCastException] + } + + it should "close resources even when exception occurs" in { + + val mgdRegNumber = "XWM12345678901" + when(mockCallableStatement.execute()).thenThrow(new RuntimeException("DB error")) + + val ex = repository.getBusinessDetails(mgdRegNumber).failed.futureValue + ex.getMessage should include("DB error") + + verify(mockCallableStatement).setString(1, mgdRegNumber) + verify(mockCallableStatement).registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR) + verify(mockCallableStatement).execute() + verify(mockResultSet, never()).close() + + verifyCleanup(rsOpened = false) + } + + it should "close ResultSet when exception occurs after it is opened" in { + + val mgdRegNumber = "XWM12345678901" + + when(mockCallableStatement.getObject(2)).thenReturn(mockResultSet) + when(mockResultSet.next()).thenThrow(new RuntimeException("RS error")) + + val ex = repository.getBusinessDetails(mgdRegNumber).failed.futureValue + + ex shouldBe a[RuntimeException] + ex.getMessage should include("RS error") + + verify(mockCallableStatement).setString(1, mgdRegNumber) + verify(mockCallableStatement).registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR) + verify(mockCallableStatement).execute() + verify(mockCallableStatement).getObject(2) + + verify(mockResultSet).close() + verify(mockCallableStatement).close() + } + + it should "throw exception when cursor is null" in { + + val mgdRegNumber = "ABC12345678901" + + when(mockCallableStatement.getObject(2)).thenReturn(null) + + val exception = intercept[RuntimeException] { + repository.getBusinessDetails(mgdRegNumber).futureValue + } + + exception.getMessage should include("Null cursor") + + verify(mockCallableStatement).setString(1, mgdRegNumber) + verify(mockCallableStatement).registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR) + verify(mockCallableStatement).execute() + verify(mockCallableStatement).getObject(2) + + verify(mockCallableStatement).close() + } + } diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala index c5d291b..b02097d 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala @@ -24,8 +24,9 @@ import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.* import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.GamblingError.{InvalidMgdRegNumber, UnexpectedError} import uk.gov.hmrc.rdsdatacacheproxy.gambling.repositories.GamblingDataSource -import scala.concurrent.Future import java.time.LocalDate +import scala.concurrent.Future + final class GamblingServiceSpec extends SpecBase { private val repository = mock[GamblingDataSource] @@ -161,4 +162,69 @@ final class GamblingServiceSpec extends SpecBase { verifyNoMoreInteractions(repository) } } + + "GamblingService#BusinessDetails" - { + + "return Right(summary) when repository succeeds" in { + + val summary = BusinessDetails( + mgdRegNumber = normalisedMgdRegNumber, + businessType = 1, + currentlyRegistered = 2, + groupReg = "foo", + dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), + businessPartnerNumber = "bar", + systemDate = Some(LocalDate.of(2024, 4, 21)) + ) + when(repository.getBusinessDetails(eqTo(validMgdRegNumber))) + .thenReturn(Future.successful(summary)) + + val result = service.getBusinessDetails(validMgdRegNumber).futureValue + + result mustBe Right(summary) + verify(repository).getBusinessDetails(eqTo(validMgdRegNumber)) + verifyNoMoreInteractions(repository) + } + + "normalise input (trim + uppercase) before calling repository" in { + + val rawInput = " xwm12345678901 " + + val summary = BusinessDetails( + mgdRegNumber = normalisedMgdRegNumber, + businessType = 1, + currentlyRegistered = 2, + groupReg = "foo", + dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), + businessPartnerNumber = "bar", + systemDate = Some(LocalDate.of(2024, 4, 21)) + ) + + when(repository.getBusinessDetails(eqTo(normalisedMgdRegNumber))) + .thenReturn(Future.successful(summary)) + + val result = service.getBusinessDetails(rawInput).futureValue + result mustBe Right(summary) + verify(repository).getBusinessDetails(eqTo(normalisedMgdRegNumber)) + verifyNoMoreInteractions(repository) + } + + "return InvalidMgdRegNumber and not call repository when input is invalid" in { + + val invalidInput = "xwm12345678" + val result = service.getBusinessDetails(invalidInput).futureValue + result mustBe Left(InvalidMgdRegNumber) + verifyNoMoreInteractions(repository) + } + + "return UnexpectedError when repository throws exception" in { + + when(repository.getBusinessDetails(eqTo(validMgdRegNumber))) + .thenReturn(Future.failed(new RuntimeException("DB failure when calling repo"))) + val result = service.getBusinessDetails(validMgdRegNumber).futureValue + result mustBe Left(UnexpectedError) + verify(repository).getBusinessDetails(eqTo(validMgdRegNumber)) + verifyNoMoreInteractions(repository) + } + } } From 02a73d4857035d380b3a38e6cdbc631f6b5d8db1 Mon Sep 17 00:00:00 2001 From: AnotherMattWright <270914550+AnotherMattWright@users.noreply.github.com> Date: Mon, 27 Apr 2026 16:35:57 +0100 Subject: [PATCH 07/16] fixed business name model and classes to have correct field types --- .../gambling/models/BusinessName.scala | 4 +-- .../GamblingDataCacheRepository.scala | 4 +-- .../GamblingControllerIntegrationSpec.scala | 10 +++---- .../GamblingDataCacheRepositoryISpec.scala | 19 +++++++------- .../gambling/GamblingStubData.scala | 26 +++++++++---------- .../controllers/GamblingControllerSpec.scala | 4 +-- .../gambling/models/GamblingModelSpec.scala | 6 ++--- .../GamblingDataCacheRepositorySpec.scala | 8 +++--- .../services/GamblingServiceSpec.scala | 8 +++--- 9 files changed, 45 insertions(+), 44 deletions(-) diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala index 9b5daad..17cdffc 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala @@ -22,10 +22,10 @@ case class BusinessName( mgdRegNumber: String, solePropTitle: String, solePropFirstName: String, - solePropMidName: String, + solePropMidName: Option[String], solePropLastName: String, businessName: String, - businessType: String, + businessType: Int, tradingName: String, systemDate: Option[LocalDate] ) diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala index 8cd0a04..f8aa068 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala @@ -106,10 +106,10 @@ class GamblingDataCacheRepository @Inject() ( mgdRegNumber = rs.getString("MGD_REG_NUMBER"), solePropTitle = rs.getString("SOLE_PROP_TITLE"), solePropFirstName = rs.getString("SOLE_PROP_FIRST_NAME"), - solePropMidName = rs.getString("SOLE_PROP_MIDDLE_NAME"), + solePropMidName = Option(rs.getString("SOLE_PROP_MIDDLE_NAME")), solePropLastName = rs.getString("SOLE_PROP_LAST_NAME"), businessName = rs.getString("BUSINESS_NAME"), - businessType = rs.getString("BUSINESS_TYPE"), + businessType = rs.getInt("BUSINESS_TYPE"), tradingName = rs.getString("TRADING_NAME"), systemDate = Option(rs.getDate("SYSTEM_DATE")).map(_.toLocalDate) ) diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingControllerIntegrationSpec.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingControllerIntegrationSpec.scala index 29db7ef..c98135d 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingControllerIntegrationSpec.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingControllerIntegrationSpec.scala @@ -215,7 +215,7 @@ class GamblingControllerIntegrationSpec (response.json \ "solePropMidName").as[String] mustBe "C" (response.json \ "solePropLastName").as[String] mustBe "Doe" (response.json \ "businessName").as[String] mustBe "John Doe Co." - (response.json \ "businessType").as[String] mustBe "Sole Proprietor" + (response.json \ "businessType").as[Int] mustBe 1 (response.json \ "tradingName").as[String] mustBe "DoeDoe" (response.json \ "systemDate").as[LocalDate] mustBe LocalDate.of(2026, 4, 20) } @@ -236,7 +236,7 @@ class GamblingControllerIntegrationSpec (response.json \ "solePropMidName").as[String] mustBe "B" (response.json \ "solePropLastName").as[String] mustBe "Bar" (response.json \ "businessName").as[String] mustBe "FooBar Co." - (response.json \ "businessType").as[String] mustBe "Sole Proprietor" + (response.json \ "businessType").as[Int] mustBe 1 (response.json \ "tradingName").as[String] mustBe "Foobar" (response.json \ "systemDate").as[LocalDate] mustBe LocalDate.of(2026, 4, 20) } @@ -249,10 +249,10 @@ class GamblingControllerIntegrationSpec (response.json \ "mgdRegNumber").as[String] mustBe "XYZ00000000012" (response.json \ "solePropTitle").as[String] mustBe "Miss" (response.json \ "solePropFirstName").as[String] mustBe "Catherine" - (response.json \ "solePropMidName").as[String] mustBe "" + (response.json \ "solePropMidName").asOpt[String] mustBe None (response.json \ "solePropLastName").as[String] mustBe "Havisham" (response.json \ "businessName").as[String] mustBe "Failed Expectations" - (response.json \ "businessType").as[String] mustBe "Sole Proprietor" + (response.json \ "businessType").as[Int] mustBe 1 (response.json \ "tradingName").as[String] mustBe "Miss Havisham" (response.json \ "systemDate").as[LocalDate] mustBe LocalDate.of(1991, 1, 1) } @@ -267,7 +267,7 @@ class GamblingControllerIntegrationSpec (response.json \ "solePropMidName").as[String] mustBe "H" (response.json \ "solePropLastName").as[String] mustBe "Krabs" (response.json \ "businessName").as[String] mustBe "Krusty Krab" - (response.json \ "businessType").as[String] mustBe "Sole Proprietor" + (response.json \ "businessType").as[Int] mustBe 1 (response.json \ "tradingName").as[String] mustBe "Mr Krabs" (response.json \ "systemDate").as[LocalDate] mustBe LocalDate.of(1991, 1, 1) } diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala index 3628ac7..7db951d 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala @@ -151,10 +151,10 @@ class GamblingDataCacheRepositoryISpec mgdRegNumber = "XYZ00000000000", solePropTitle = "Mr", solePropFirstName = "John", - solePropMidName = "C", + solePropMidName = Some("C"), solePropLastName = "Doe", businessName = "John Doe Co.", - businessType = "Sole Proprietor", + businessType = 1, tradingName = "DoeDoe", systemDate = Some(LocalDate.of(2026, 4, 20)) ) @@ -167,10 +167,10 @@ class GamblingDataCacheRepositoryISpec mgdRegNumber = "XYZ00000000010", solePropTitle = "Mrs", solePropFirstName = "Marge", - solePropMidName = "Jacqueline", + solePropMidName = Some("Jacqueline"), solePropLastName = "Simpson", businessName = "Pretzel Wagon", - businessType = "Sole Proprietor", + businessType = 1, tradingName = "Marge Simpson", systemDate = Some(LocalDate.of(2026, 4, 20)) ) @@ -186,7 +186,7 @@ class GamblingDataCacheRepositoryISpec "return correct middle name and system date" in { val result = repository.getBusinessName("XYZ00000000010").futureValue - result.solePropMidName mustBe "Jacqueline" + result.solePropMidName mustBe Some("Jacqueline") result.systemDate mustBe Some(LocalDate.of(2026, 4, 20)) } @@ -201,7 +201,7 @@ class GamblingDataCacheRepositoryISpec val result = repository.getBusinessName("XYZ00000000021").futureValue result.solePropFirstName mustBe "Eugine" - result.businessType mustBe "Sole Proprietor" + result.businessType mustBe 1 } "return default values for unknown mgdRegNumber" in { @@ -211,10 +211,10 @@ class GamblingDataCacheRepositoryISpec mgdRegNumber = "XYZ99999999999", solePropTitle = "Mr", solePropFirstName = "Foo", - solePropMidName = "B", + solePropMidName = Some("B"), solePropLastName = "Bar", businessName = "FooBar Co.", - businessType = "Sole Proprietor", + businessType = 1, tradingName = "Foobar", systemDate = Some(LocalDate.of(2026, 4, 20)) ) @@ -262,7 +262,8 @@ class GamblingDataCacheRepositoryISpec result.solePropFirstName must not be empty result.solePropLastName must not be empty result.businessName must not be empty - result.businessType must not be empty + result.businessType must be > 0 + result.businessType must be <= 5 result.tradingName must not be empty } } diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala index 9ccc4d3..1224b81 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala @@ -47,50 +47,50 @@ object GamblingStubData { BusinessName(mgdRegNumber, solePropTitle = "Mr", solePropFirstName = "John", - solePropMidName = "C", + solePropMidName = Some("C"), solePropLastName = "Doe", businessName = "John Doe Co.", - businessType = "Sole Proprietor", + businessType = 1, tradingName = "DoeDoe", systemDate = dateTimeOne) case "XYZ00000000001" => BusinessName(mgdRegNumber, solePropTitle = "Mrs", solePropFirstName = "Jane", - solePropMidName = "C", + solePropMidName = Some("C"), solePropLastName = "Doe", businessName = "Jane Doe Co.", - businessType = "Sole Proprietor", + businessType = 1, tradingName = "DoeDoe", systemDate = dateTimeTwo) case "XYZ00000000010" => BusinessName(mgdRegNumber, solePropTitle = "Mrs", solePropFirstName = "Marge", - solePropMidName = "Jacqueline", + solePropMidName = Some("Jacqueline"), solePropLastName = "Simpson", businessName = "Pretzel Wagon", - businessType = "Sole Proprietor", + businessType = 1, tradingName = "Marge Simpson", systemDate = dateTimeOne) case "XYZ00000000012" => BusinessName(mgdRegNumber, solePropTitle = "Miss", solePropFirstName = "Catherine", - solePropMidName = "", + solePropMidName = None, solePropLastName = "Havisham", businessName = "Failed Expectations", - businessType = "Sole Proprietor", + businessType = 1, tradingName = "Miss Havisham", systemDate = dateTimeThree) case "XYZ00000000021" => BusinessName(mgdRegNumber, solePropTitle = "Mr", solePropFirstName = "Eugine", - solePropMidName = "H", + solePropMidName = Some("H"), solePropLastName = "Krabs", businessName = "Krusty Krab", - businessType = "Sole Proprietor", + businessType = 1, tradingName = "Mr Krabs", systemDate = dateTimeThree) case "ERR00000000000" => @@ -99,16 +99,16 @@ object GamblingStubData { BusinessName(mgdRegNumber, solePropTitle= "Mr", solePropFirstName= "Foo", - solePropMidName= "B", + solePropMidName= Some("B"), solePropLastName= "Bar", businessName= "FooBar Co.", - businessType= "Sole Proprietor", + businessType= 1, tradingName= "Foobar", systemDate= dateTimeOne ) } } - } + def getBusinessDetails(mgdRegNumber: String): BusinessDetails = diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala index 84d8fb9..cb596a4 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala @@ -125,7 +125,7 @@ class GamblingControllerSpec extends SpecBase with MockitoSugar { "returns 200 when service succeeds" in new Setup { val dateTime: Some[LocalDate] = Some(LocalDate.of(2026, 4, 20)) - val name = BusinessName("XWM00000001770", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", dateTime) + val name = BusinessName("XWM00000001770", "fooBar", "foobar", Some("fooBar"), "fooBar", "fooBar", 1, "fooBar", dateTime) when(mockService.getBusinessName(eqTo("XWM00000001770"))(any())) .thenReturn(Future.successful(Right(name))) @@ -143,7 +143,7 @@ class GamblingControllerSpec extends SpecBase with MockitoSugar { "allows request through AuthAction" in new Setup { val dateTime: Some[LocalDate] = Some(LocalDate.of(2026, 4, 20)) - val name = BusinessName("XWM00000001770", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", "fooBar", dateTime) + val name = BusinessName("XWM00000001770", "fooBar", "foobar", Some("fooBar"), "fooBar", "fooBar", 1, "fooBar", dateTime) when(mockService.getBusinessName(any())(any())) .thenReturn(Future.successful(Right(name))) diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingModelSpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingModelSpec.scala index 5251101..29bd88b 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingModelSpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingModelSpec.scala @@ -57,7 +57,7 @@ class GamblingModelSpec extends AnyWordSpec with Matchers { |"solePropMidName": "C", |"solePropLastName": "Doe", |"businessName": "John Doe Co.", - |"businessType": "Sole Proprietor", + |"businessType": 1, |"tradingName": "DoeDoe", |"systemDate": "$dateBusinessName" |} @@ -70,10 +70,10 @@ class GamblingModelSpec extends AnyWordSpec with Matchers { mgdRegNumber = "XYZ00000000000", solePropTitle = "Mr", solePropFirstName = "John", - solePropMidName = "C", + solePropMidName = Some("C"), solePropLastName = "Doe", businessName = "John Doe Co.", - businessType = "Sole Proprietor", + businessType = 1, tradingName = "DoeDoe", systemDate = Some(dateBusinessName) ) diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala index fcab321..fa0844d 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala @@ -105,7 +105,7 @@ class GamblingDataCacheRepositorySpec extends AnyFlatSpec with Matchers with Bef when(mockResultSet.getString("SOLE_PROP_MIDDLE_NAME")).thenReturn("B") when(mockResultSet.getString("SOLE_PROP_LAST_NAME")).thenReturn("Bar") when(mockResultSet.getString("BUSINESS_NAME")).thenReturn("Foo Bar Co.") - when(mockResultSet.getString("BUSINESS_TYPE")).thenReturn("Sole Proprietor") + when(mockResultSet.getInt("BUSINESS_TYPE")).thenReturn(1) when(mockResultSet.getString("TRADING_NAME")).thenReturn("Foobar") when(mockResultSet.getDate("SYSTEM_DATE")).thenReturn(java.sql.Date.valueOf("2024-04-21")) @@ -115,10 +115,10 @@ class GamblingDataCacheRepositorySpec extends AnyFlatSpec with Matchers with Bef mgdRegNumber = mgdRegNumber, solePropTitle = "Mr", solePropFirstName = "Foo", - solePropMidName = "B", + solePropMidName = Some("B"), solePropLastName = "Bar", businessName = "Foo Bar Co.", - businessType = "Sole Proprietor", + businessType = 1, tradingName = "Foobar", systemDate = Some(LocalDate.of(2024, 4, 21)) ) @@ -131,7 +131,7 @@ class GamblingDataCacheRepositorySpec extends AnyFlatSpec with Matchers with Bef verify(mockResultSet).getString("SOLE_PROP_MIDDLE_NAME") verify(mockResultSet).getString("SOLE_PROP_LAST_NAME") verify(mockResultSet).getString("BUSINESS_NAME") - verify(mockResultSet).getString("BUSINESS_TYPE") + verify(mockResultSet).getInt("BUSINESS_TYPE") verify(mockResultSet).getString("TRADING_NAME") verify(mockResultSet).getDate("SYSTEM_DATE") diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala index b02097d..7cf4f99 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala @@ -101,10 +101,10 @@ final class GamblingServiceSpec extends SpecBase { mgdRegNumber = validMgdRegNumber, solePropTitle = "Mr", solePropFirstName = "Foo", - solePropMidName = "B", + solePropMidName = Some("B"), solePropLastName = "Bar", businessName = "FooBar Co.", - businessType = "Sole Proprietor", + businessType = 1, tradingName = "Foobar", systemDate = Some(LocalDate.of(1991, 1, 1)) ) @@ -127,10 +127,10 @@ final class GamblingServiceSpec extends SpecBase { mgdRegNumber = normalisedMgdRegNumber, solePropTitle = "Mr", solePropFirstName = "John", - solePropMidName = "C", + solePropMidName = Some("C"), solePropLastName = "Doe", businessName = "John Doe Co.", - businessType = "Sole Proprietor", + businessType = 1, tradingName = "DoeDoe", systemDate = Some(LocalDate.of(1991, 1, 1)) ) From cd8432ac354f445379bade2f1026ff577c3adf7a Mon Sep 17 00:00:00 2001 From: AnotherMattWright <270914550+AnotherMattWright@users.noreply.github.com> Date: Tue, 28 Apr 2026 15:30:00 +0100 Subject: [PATCH 08/16] solved faulty merge & conflicts, temp removed test cases for Bus Name Bus Details --- .../GamblingDataCacheRepository.scala | 1 - .../GamblingDataCacheRepositorySpec.scala | 273 +----------------- 2 files changed, 1 insertion(+), 273 deletions(-) diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala index bb0c7b7..0ef5c62 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala @@ -20,7 +20,6 @@ import play.api.Logging import play.api.db.{Database, NamedDatabase} import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.* - import javax.inject.{Inject, Singleton} import scala.concurrent.{ExecutionContext, Future, blocking} diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala index 3c6ca9e..2b9d417 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala @@ -25,8 +25,6 @@ import org.scalatest.matchers.should.Matchers import play.api.db.Database import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.* -import java.sql.{CallableStatement, Connection, ResultSet} -import java.time.LocalDate import java.sql.{CallableStatement, Connection, Date, ResultSet} import java.time.LocalDate import scala.concurrent.ExecutionContext.Implicits.global @@ -70,89 +68,6 @@ class GamblingDataCacheRepositorySpec extends AnyFlatSpec with Matchers with Bef when(returnSummaryRs.getString("MGD_REG_NUMBER")).thenReturn(mgdRegNumber) when(returnSummaryRs.getInt("RETURNS_DUE")).thenReturn(5) when(returnSummaryRs.getInt("RETURNS_OVERDUE")).thenReturn(2) - when(mockResultSet.next()).thenReturn(true) - when(mockResultSet.getString("MGD_REG_NUMBER")).thenReturn(mgdRegNumber) - when(mockResultSet.getInt("RETURNS_DUE")).thenReturn(5) - when(mockResultSet.getInt("RETURNS_OVERDUE")).thenReturn(2) - - val result = repository.getReturnSummary(mgdRegNumber).futureValue - - result shouldBe ReturnSummary( - mgdRegNumber = mgdRegNumber, - returnsDue = 5, - returnsOverdue = 2 - ) - verifyDbSetup(mgdRegNumber) - - verify(mockResultSet).next() - verify(mockResultSet).getString("MGD_REG_NUMBER") - verify(mockResultSet).getInt("RETURNS_DUE") - verify(mockResultSet).getInt("RETURNS_OVERDUE") - - verifyCleanup() - } - - "getBusinessName" should "return Business Name when stored procedure returns data" in { - - val mgdRegNumber = "XWM12345678901" - - when(mockResultSet.next()).thenReturn(true) - when(mockResultSet.getString("MGD_REG_NUMBER")).thenReturn(mgdRegNumber) - when(mockResultSet.getString("SOLE_PROP_TITLE")).thenReturn("Mr") - when(mockResultSet.getString("SOLE_PROP_FIRST_NAME")).thenReturn("Foo") - when(mockResultSet.getString("SOLE_PROP_MIDDLE_NAME")).thenReturn("B") - when(mockResultSet.getString("SOLE_PROP_LAST_NAME")).thenReturn("Bar") - when(mockResultSet.getString("BUSINESS_NAME")).thenReturn("Foo Bar Co.") - when(mockResultSet.getInt("BUSINESS_TYPE")).thenReturn(1) - when(mockResultSet.getString("TRADING_NAME")).thenReturn("Foobar") - when(mockResultSet.getDate("SYSTEM_DATE")).thenReturn(java.sql.Date.valueOf("2024-04-21")) - - val result = repository.getBusinessName(mgdRegNumber).futureValue - - result shouldBe BusinessName( - mgdRegNumber = mgdRegNumber, - solePropTitle = "Mr", - solePropFirstName = "Foo", - solePropMidName = Some("B"), - solePropLastName = "Bar", - businessName = "Foo Bar Co.", - businessType = 1, - tradingName = "Foobar", - systemDate = Some(LocalDate.of(2024, 4, 21)) - ) - verifyDbSetup(mgdRegNumber) - - verify(mockResultSet).next() - verify(mockResultSet).getString("MGD_REG_NUMBER") - verify(mockResultSet).getString("SOLE_PROP_TITLE") - verify(mockResultSet).getString("SOLE_PROP_FIRST_NAME") - verify(mockResultSet).getString("SOLE_PROP_MIDDLE_NAME") - verify(mockResultSet).getString("SOLE_PROP_LAST_NAME") - verify(mockResultSet).getString("BUSINESS_NAME") - verify(mockResultSet).getInt("BUSINESS_TYPE") - verify(mockResultSet).getString("TRADING_NAME") - verify(mockResultSet).getDate("SYSTEM_DATE") - - verifyCleanup() - } - - it should "handle null values in result set safely" in { - when(mockResultSet.next()).thenReturn(true) - when(mockResultSet.getString("MGD_REG_NUMBER")).thenReturn(null) - - val result = repository.getReturnSummary("XWM12345678901").futureValue - - result.mgdRegNumber shouldBe null // or expected behaviour - } - - it should "handle zero counts correctly" in { - - val mgdRegNumber = "XWM12345678901" - - when(mockResultSet.next()).thenReturn(true) - when(mockResultSet.getString("MGD_REG_NUMBER")).thenReturn(mgdRegNumber) - when(mockResultSet.getInt("RETURNS_DUE")).thenReturn(0) - when(mockResultSet.getInt("RETURNS_OVERDUE")).thenReturn(0) val result = repository.getReturnSummary(mgdRegNumber).futureValue @@ -165,7 +80,7 @@ class GamblingDataCacheRepositorySpec extends AnyFlatSpec with Matchers with Bef verify(mockCs).close() } - it should "throw exception when result set is empty (returnSummary)" in { + it should "throw exception when result set is empty" in { when(mockCs.getObject(2)).thenReturn(returnSummaryRs) when(returnSummaryRs.next()).thenReturn(false) @@ -263,24 +178,6 @@ class GamblingDataCacheRepositorySpec extends AnyFlatSpec with Matchers with Bef verify(mockCs).close() } - it should "throw exception when result set is empty (businessName)" in { - - val mgdRegNumber = "XWM12345678901" - - when(mockResultSet.next()).thenReturn(false) - - val exception = intercept[RuntimeException] { - repository.getBusinessName(mgdRegNumber).futureValue - } - - exception.getMessage should include("Empty result set") - - verifyDbSetup(mgdRegNumber) - verifyCleanup() - } - - it should "fail when cursor is not a ResultSet" in { - when(mockCallableStatement.getObject(2)).thenReturn("invalid") it should "handle null cursors safely" in { when(mockCs.getObject(24)).thenReturn(null) @@ -305,172 +202,4 @@ class GamblingDataCacheRepositorySpec extends AnyFlatSpec with Matchers with Bef verify(mockCs).close() } - - it should "throw exception when cursor is null (returnSummary)" in { - - val mgdRegNumber = "ABC12345678901" - - when(mockCallableStatement.getObject(2)).thenReturn(null) - - val exception = intercept[RuntimeException] { - repository.getReturnSummary(mgdRegNumber).futureValue - } - - exception.getMessage should include("Null cursor") - - verify(mockCallableStatement).setString(1, mgdRegNumber) - verify(mockCallableStatement).registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR) - verify(mockCallableStatement).execute() - verify(mockCallableStatement).getObject(2) - - verify(mockCallableStatement).close() - } - - it should "throw exception when cursor is null (businessName)" in { - - val mgdRegNumber = "ABC12345678901" - - when(mockCallableStatement.getObject(2)).thenReturn(null) - - val exception = intercept[RuntimeException] { - repository.getBusinessName(mgdRegNumber).futureValue - } - - exception.getMessage should include("Null cursor") - - verify(mockCallableStatement).setString(1, mgdRegNumber) - verify(mockCallableStatement).registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR) - verify(mockCallableStatement).execute() - verify(mockCallableStatement).getObject(2) - - verify(mockCallableStatement).close() - } - - "getBusinessDetails" should "return BusinessDetails when stored procedure returns data" in { - - val mgdRegNumber = "XWM12345678901" - - when(mockResultSet.next()).thenReturn(true) - when(mockResultSet.getString("MGD_REG_NUMBER")).thenReturn(mgdRegNumber) - when(mockResultSet.getInt("BUSINESS_TYPE")).thenReturn(5) - when(mockResultSet.getInt("CURRENTLY_REGISTERED")).thenReturn(2) - when(mockResultSet.getString("GROUP_REG")).thenReturn("foo") - when(mockResultSet.getDate("DATE_OF_REGISTRATION")).thenReturn(java.sql.Date.valueOf("2024-04-21")) - when(mockResultSet.getString("BUSINESS_PARTNER_NUMBER")).thenReturn("bar") - when(mockResultSet.getDate("SYSTEM_DATE")).thenReturn(java.sql.Date.valueOf("2024-04-21")) - - val result = repository.getBusinessDetails(mgdRegNumber).futureValue - - result shouldBe BusinessDetails( - mgdRegNumber = mgdRegNumber, - businessType = 5, - currentlyRegistered = 2, - groupReg = "foo", - dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), - businessPartnerNumber = "bar", - systemDate = Some(LocalDate.of(2024, 4, 21)) - ) - verifyDbSetup(mgdRegNumber) - - verify(mockResultSet).next() - verify(mockResultSet).getString("MGD_REG_NUMBER") - verify(mockResultSet).getInt("BUSINESS_TYPE") - verify(mockResultSet).getInt("CURRENTLY_REGISTERED") - verify(mockResultSet).getString("GROUP_REG") - verify(mockResultSet).getDate("DATE_OF_REGISTRATION") - verify(mockResultSet).getString("BUSINESS_PARTNER_NUMBER") - verify(mockResultSet).getDate("SYSTEM_DATE") - - verifyCleanup() - } - - it should "handle null values in result set safely" in { - when(mockResultSet.next()).thenReturn(true) - when(mockResultSet.getString("MGD_REG_NUMBER")).thenReturn(null) - - val result = repository.getBusinessDetails("XWM12345678901").futureValue - - result.mgdRegNumber shouldBe null - } - - it should "throw exception when result set is empty" in { - - val mgdRegNumber = "XWM12345678901" - - when(mockResultSet.next()).thenReturn(false) - - val exception = intercept[RuntimeException] { - repository.getBusinessDetails(mgdRegNumber).futureValue - } - - exception.getMessage should include("Empty result set") - - verifyDbSetup(mgdRegNumber) - verifyCleanup() - } - - it should "fail when cursor is not a ResultSet" in { - when(mockCallableStatement.getObject(2)).thenReturn("invalid") - - val ex = repository.getBusinessDetails("XWM12345678901").failed.futureValue - ex shouldBe a[ClassCastException] - } - - it should "close resources even when exception occurs" in { - - val mgdRegNumber = "XWM12345678901" - when(mockCallableStatement.execute()).thenThrow(new RuntimeException("DB error")) - - val ex = repository.getBusinessDetails(mgdRegNumber).failed.futureValue - ex.getMessage should include("DB error") - - verify(mockCallableStatement).setString(1, mgdRegNumber) - verify(mockCallableStatement).registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR) - verify(mockCallableStatement).execute() - verify(mockResultSet, never()).close() - - verifyCleanup(rsOpened = false) - } - - it should "close ResultSet when exception occurs after it is opened" in { - - val mgdRegNumber = "XWM12345678901" - - when(mockCallableStatement.getObject(2)).thenReturn(mockResultSet) - when(mockResultSet.next()).thenThrow(new RuntimeException("RS error")) - - val ex = repository.getBusinessDetails(mgdRegNumber).failed.futureValue - - ex shouldBe a[RuntimeException] - ex.getMessage should include("RS error") - - verify(mockCallableStatement).setString(1, mgdRegNumber) - verify(mockCallableStatement).registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR) - verify(mockCallableStatement).execute() - verify(mockCallableStatement).getObject(2) - - verify(mockResultSet).close() - verify(mockCallableStatement).close() - } - - it should "throw exception when cursor is null" in { - - val mgdRegNumber = "ABC12345678901" - - when(mockCallableStatement.getObject(2)).thenReturn(null) - - val exception = intercept[RuntimeException] { - repository.getBusinessDetails(mgdRegNumber).futureValue - } - - exception.getMessage should include("Null cursor") - - verify(mockCallableStatement).setString(1, mgdRegNumber) - verify(mockCallableStatement).registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR) - verify(mockCallableStatement).execute() - verify(mockCallableStatement).getObject(2) - - verify(mockCallableStatement).close() - } - } From 7687b3dab0aa7e500dc6a106567d47df6f50b3b3 Mon Sep 17 00:00:00 2001 From: AnotherMattWright <270914550+AnotherMattWright@users.noreply.github.com> Date: Fri, 1 May 2026 13:20:12 +0100 Subject: [PATCH 09/16] refactor of models to type fields to optional --- .../gambling/models/BusinessDetails.scala | 8 +- .../gambling/models/BusinessName.scala | 12 +- .../GamblingDataCacheRepository.scala | 20 +-- .../GamblingDataCacheRepositoryISpec.scala | 90 +++++++------ .../gambling/GamblingStubData.scala | 120 +++++++++--------- .../controllers/GamblingControllerSpec.scala | 8 +- .../gambling/models/GamblingModelSpec.scala | 20 +-- .../services/GamblingServiceSpec.scala | 40 +++--- 8 files changed, 158 insertions(+), 160 deletions(-) diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessDetails.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessDetails.scala index f134fee..1f71d0a 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessDetails.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessDetails.scala @@ -21,11 +21,11 @@ import play.api.libs.json.{Json, OFormat} import java.time.LocalDate case class BusinessDetails(mgdRegNumber: String, - businessType: Int, - currentlyRegistered: Int, - groupReg: String, + businessType: Option[Int], + currentlyRegistered: Option[Int], + groupReg: Option[String], dateOfRegistration: Option[LocalDate], - businessPartnerNumber: String, + businessPartnerNumber: Option[String], systemDate: Option[LocalDate] ) diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala index 17cdffc..5115fae 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala @@ -20,13 +20,13 @@ import java.time.LocalDate case class BusinessName( mgdRegNumber: String, - solePropTitle: String, - solePropFirstName: String, + solePropTitle: Option[String], + solePropFirstName: Option[String], solePropMidName: Option[String], - solePropLastName: String, - businessName: String, - businessType: Int, - tradingName: String, + solePropLastName: Option[String], + businessName: Option[String], + businessType: Option[Int], + tradingName: Option[String], systemDate: Option[LocalDate] ) diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala index 0ef5c62..2bf1f60 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala @@ -264,13 +264,13 @@ class GamblingDataCacheRepository @Inject() ( if (rs.next()) { BusinessName( mgdRegNumber = rs.getString("MGD_REG_NUMBER"), - solePropTitle = rs.getString("SOLE_PROP_TITLE"), - solePropFirstName = rs.getString("SOLE_PROP_FIRST_NAME"), + solePropTitle = Option(rs.getString("SOLE_PROP_TITLE")), + solePropFirstName = Option(rs.getString("SOLE_PROP_FIRST_NAME")), solePropMidName = Option(rs.getString("SOLE_PROP_MIDDLE_NAME")), - solePropLastName = rs.getString("SOLE_PROP_LAST_NAME"), - businessName = rs.getString("BUSINESS_NAME"), - businessType = rs.getInt("BUSINESS_TYPE"), - tradingName = rs.getString("TRADING_NAME"), + solePropLastName = Option(rs.getString("SOLE_PROP_LAST_NAME")), + businessName = Option(rs.getString("BUSINESS_NAME")), + businessType = Option(rs.getInt("BUSINESS_TYPE")), + tradingName = Option(rs.getString("TRADING_NAME")), systemDate = Option(rs.getDate("SYSTEM_DATE")).map(_.toLocalDate) ) } else { @@ -314,11 +314,11 @@ class GamblingDataCacheRepository @Inject() ( if (rs.next()) { BusinessDetails( mgdRegNumber = rs.getString("MGD_REG_NUMBER"), - businessType = rs.getInt("BUSINESS_TYPE"), - currentlyRegistered = rs.getInt("CURRENTLY_REGISTERED"), - groupReg = rs.getString("GROUP_REG"), + businessType = Option(rs.getInt("BUSINESS_TYPE")), + currentlyRegistered = Option(rs.getInt("CURRENTLY_REGISTERED")), + groupReg = Option(rs.getString("GROUP_REG")), dateOfRegistration = Option(rs.getDate("DATE_OF_REGISTRATION")).map(_.toLocalDate), - businessPartnerNumber = rs.getString("BUSINESS_PARTNER_NUMBER"), + businessPartnerNumber = Option(rs.getString("BUSINESS_PARTNER_NUMBER")), systemDate = Option(rs.getDate("SYSTEM_DATE")).map(_.toLocalDate) ) } else { diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala index 0f4230b..a7dc863 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala @@ -153,13 +153,13 @@ class GamblingDataCacheRepositoryISpec result mustBe BusinessName( mgdRegNumber = "XYZ00000000000", - solePropTitle = "Mr", - solePropFirstName = "John", + solePropTitle = Some("Mr"), + solePropFirstName = Some("John"), solePropMidName = Some("C"), - solePropLastName = "Doe", - businessName = "John Doe Co.", - businessType = 1, - tradingName = "DoeDoe", + solePropLastName = Some("Doe"), + businessName = Some("John Doe Co."), + businessType = Some(1), + tradingName = Some("DoeDoe"), systemDate = Some(LocalDate.of(2026, 4, 20)) ) } @@ -169,13 +169,13 @@ class GamblingDataCacheRepositoryISpec result mustBe BusinessName( mgdRegNumber = "XYZ00000000010", - solePropTitle = "Mrs", - solePropFirstName = "Marge", + solePropTitle = Some("Mrs"), + solePropFirstName = Some("Marge"), solePropMidName = Some("Jacqueline"), - solePropLastName = "Simpson", - businessName = "Pretzel Wagon", - businessType = 1, - tradingName = "Marge Simpson", + solePropLastName = Some("Simpson"), + businessName = Some("Pretzel Wagon"), + businessType = Some(1), + tradingName = Some("Marge Simpson"), systemDate = Some(LocalDate.of(2026, 4, 20)) ) } @@ -183,8 +183,8 @@ class GamblingDataCacheRepositoryISpec "return last name and business name correctly" in { val result = repository.getBusinessName("XYZ00000000001").futureValue - result.solePropLastName mustBe "Doe" - result.businessName mustBe "Jane Doe Co." + result.solePropLastName mustBe Some("Doe") + result.businessName mustBe Some("Jane Doe Co.") } "return correct middle name and system date" in { @@ -197,15 +197,15 @@ class GamblingDataCacheRepositoryISpec "return correct title and trading name" in { val result = repository.getBusinessName("XYZ00000000012").futureValue - result.solePropTitle mustBe "Miss" - result.tradingName mustBe "Miss Havisham" + result.solePropTitle mustBe Some("Miss") + result.tradingName mustBe Some("Miss Havisham") } "return correct business type and first name" in { val result = repository.getBusinessName("XYZ00000000021").futureValue - result.solePropFirstName mustBe "Eugine" - result.businessType mustBe 1 + result.solePropFirstName mustBe Some("Eugine") + result.businessType mustBe Some(1) } "return default values for unknown mgdRegNumber" in { @@ -213,13 +213,13 @@ class GamblingDataCacheRepositoryISpec result mustBe BusinessName( mgdRegNumber = "XYZ99999999999", - solePropTitle = "Mr", - solePropFirstName = "Foo", + solePropTitle = Some("Mr"), + solePropFirstName = Some("Foo"), solePropMidName = Some("B"), - solePropLastName = "Bar", - businessName = "FooBar Co.", - businessType = 1, - tradingName = "Foobar", + solePropLastName = Some("Bar"), + businessName = Some("FooBar Co."), + businessType = Some(1), + tradingName = Some("Foobar"), systemDate = Some(LocalDate.of(2026, 4, 20)) ) } @@ -266,8 +266,6 @@ class GamblingDataCacheRepositoryISpec result.solePropFirstName must not be empty result.solePropLastName must not be empty result.businessName must not be empty - result.businessType must be > 0 - result.businessType must be <= 5 result.tradingName must not be empty } } @@ -279,56 +277,56 @@ class GamblingDataCacheRepositoryISpec result mustBe BusinessDetails( mgdRegNumber = "XYZ00000000000", - businessType = 6, - currentlyRegistered = 2, - groupReg = "foo", - dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = "bar", systemDate = Some(LocalDate.of(2024, 4, 21)) + businessType = Some(6), + currentlyRegistered = Some(2), + groupReg = Some("foo"), + dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = Some("bar"), systemDate = Some(LocalDate.of(2024, 4, 21)) ) } "return business type correctly" in { val result = repository.getBusinessDetails("XYZ00000000001").futureValue - result.businessType mustBe 1 - result.currentlyRegistered mustBe 1 - result.groupReg mustBe "foofoo" + result.businessType mustBe Some(1) + result.currentlyRegistered mustBe Some(1) + result.groupReg mustBe Some("foofoo") result.dateOfRegistration mustBe Some(LocalDate.of(2024, 4, 21)) - result.businessPartnerNumber mustBe "bar" + result.businessPartnerNumber mustBe Some("bar") result.systemDate mustBe Some(LocalDate.of(2024, 4, 21)) } "return group reg correctly" in { val result = repository.getBusinessDetails("XYZ00000000010").futureValue - result.businessType mustBe 3 - result.currentlyRegistered mustBe 2 - result.groupReg mustBe "foo" + result.businessType mustBe Some(3) + result.currentlyRegistered mustBe Some(2) + result.groupReg mustBe Some("foo") result.dateOfRegistration mustBe Some(LocalDate.of(2024, 4, 21)) - result.businessPartnerNumber mustBe "bar" + result.businessPartnerNumber mustBe Some("bar") result.systemDate mustBe Some(LocalDate.of(2024, 4, 21)) } "return both date values correctly" in { val result = repository.getBusinessDetails("XYZ00000000012").futureValue - result mustBe BusinessDetails("XYZ00000000012", 1, 2, "foobar", Some(LocalDate.of(2023, 4, 21)), "barfoo", Some(LocalDate.of(2023, 4, 21))) + result mustBe BusinessDetails("XYZ00000000012", Some(1), Some(2), Some("foobar"), Some(LocalDate.of(2023, 4, 21)), Some("barfoo"), Some(LocalDate.of(2023, 4, 21))) } "handle multiple values" in { val result = repository.getBusinessDetails("XYZ00000000021").futureValue - result.businessType mustBe 5 - result.currentlyRegistered mustBe 2 - result.groupReg mustBe "foofoo" + result.businessType mustBe Some(5) + result.currentlyRegistered mustBe Some(2) + result.groupReg mustBe Some("foofoo") result.dateOfRegistration mustBe Some(LocalDate.of(2024, 1, 21)) - result.businessPartnerNumber mustBe "barbar" + result.businessPartnerNumber mustBe Some("barbar") result.systemDate mustBe Some(LocalDate.of(2024, 1, 21)) } "return default values for unknown mgdRegNumber" in { val result = repository.getBusinessDetails("XYZ99999999999").futureValue - result mustBe BusinessDetails("XYZ99999999999", 0, 0, "unknown", Some(LocalDate.of(2026, 4, 22)), "unknown", Some(LocalDate.of(2026, 4, 22))) + result mustBe BusinessDetails("XYZ99999999999", Some(0), Some(0), Some("unknown"), Some(LocalDate.of(2026, 4, 22)), Some("unknown"), Some(LocalDate.of(2026, 4, 22))) } "return consistent results across multiple calls" in { @@ -356,13 +354,13 @@ class GamblingDataCacheRepositoryISpec "handle special characters in mgdRegNumber" in { val result = repository.getBusinessDetails("XYZ-123/ABC").futureValue - result mustBe BusinessDetails("XYZ-123/ABC", 0, 0, "unknown", Some(LocalDate.of(2026, 4, 22)), "unknown", Some(LocalDate.of(2026, 4, 22))) + result mustBe BusinessDetails("XYZ-123/ABC", Some(0), Some(0), Some("unknown"), Some(LocalDate.of(2026, 4, 22)), Some("unknown"), Some(LocalDate.of(2026, 4, 22))) } "handle whitespace mgdRegNumber" in { val result = repository.getBusinessDetails(" ").futureValue - result mustBe BusinessDetails(" ", 0, 0, "unknown", Some(LocalDate.of(2026, 4, 22)), "unknown", Some(LocalDate.of(2026, 4, 22))) + result mustBe BusinessDetails(" ", Some(0), Some(0), Some("unknown"), Some(LocalDate.of(2026, 4, 22)), Some("unknown"), Some(LocalDate.of(2026, 4, 22))) } } } \ No newline at end of file diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala index 1224b81..f5f4eac 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala @@ -45,65 +45,65 @@ object GamblingStubData { mgdRegNumber match { case "XYZ00000000000" => BusinessName(mgdRegNumber, - solePropTitle = "Mr", - solePropFirstName = "John", + solePropTitle = Some("Mr"), + solePropFirstName = Some("John"), solePropMidName = Some("C"), - solePropLastName = "Doe", - businessName = "John Doe Co.", - businessType = 1, - tradingName = "DoeDoe", + solePropLastName = Some("Doe"), + businessName = Some("John Doe Co."), + businessType = Some(1), + tradingName = Some("DoeDoe"), systemDate = dateTimeOne) case "XYZ00000000001" => BusinessName(mgdRegNumber, - solePropTitle = "Mrs", - solePropFirstName = "Jane", + solePropTitle = Some("Mrs"), + solePropFirstName = Some("Jane"), solePropMidName = Some("C"), - solePropLastName = "Doe", - businessName = "Jane Doe Co.", - businessType = 1, - tradingName = "DoeDoe", + solePropLastName = Some("Doe"), + businessName = Some("Jane Doe Co."), + businessType = Some(1), + tradingName = Some("DoeDoe"), systemDate = dateTimeTwo) case "XYZ00000000010" => BusinessName(mgdRegNumber, - solePropTitle = "Mrs", - solePropFirstName = "Marge", + solePropTitle = Some("Mrs"), + solePropFirstName = Some("Marge"), solePropMidName = Some("Jacqueline"), - solePropLastName = "Simpson", - businessName = "Pretzel Wagon", - businessType = 1, - tradingName = "Marge Simpson", + solePropLastName = Some("Simpson"), + businessName = Some("Pretzel Wagon"), + businessType = Some(1), + tradingName = Some("Marge Simpson"), systemDate = dateTimeOne) case "XYZ00000000012" => BusinessName(mgdRegNumber, - solePropTitle = "Miss", - solePropFirstName = "Catherine", + solePropTitle = Some("Miss"), + solePropFirstName = Some("Catherine"), solePropMidName = None, - solePropLastName = "Havisham", - businessName = "Failed Expectations", - businessType = 1, - tradingName = "Miss Havisham", + solePropLastName = Some("Havisham"), + businessName = Some("Failed Expectations"), + businessType = Some(1), + tradingName = Some("Miss Havisham"), systemDate = dateTimeThree) case "XYZ00000000021" => BusinessName(mgdRegNumber, - solePropTitle = "Mr", - solePropFirstName = "Eugine", + solePropTitle = Some("Mr"), + solePropFirstName = Some("Eugine"), solePropMidName = Some("H"), - solePropLastName = "Krabs", - businessName = "Krusty Krab", - businessType = 1, - tradingName = "Mr Krabs", + solePropLastName = Some("Krabs"), + businessName = Some("Krusty Krab"), + businessType = Some(1), + tradingName = Some("Mr Krabs"), systemDate = dateTimeThree) case "ERR00000000000" => throw new RuntimeException("Simulated downstream failure") case _ => BusinessName(mgdRegNumber, - solePropTitle= "Mr", - solePropFirstName= "Foo", + solePropTitle= Some("Mr"), + solePropFirstName= Some("Foo"), solePropMidName= Some("B"), - solePropLastName= "Bar", - businessName= "FooBar Co.", - businessType= 1, - tradingName= "Foobar", + solePropLastName= Some("Bar"), + businessName= Some("FooBar Co."), + businessType= Some(1), + tradingName= Some("Foobar"), systemDate= dateTimeOne ) } @@ -116,52 +116,52 @@ object GamblingStubData { case "XYZ00000000000" => BusinessDetails( mgdRegNumber = mgdRegNumber, - businessType = 6, - currentlyRegistered = 2, - groupReg = "foo", - dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = "bar", systemDate = Some(LocalDate.of(2024, 4, 21)) + businessType = Some(6), + currentlyRegistered = Some(2), + groupReg = Some("foo"), + dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = Some("bar"), systemDate = Some(LocalDate.of(2024, 4, 21)) ) case "XYZ00000000001" => BusinessDetails( mgdRegNumber = mgdRegNumber, - businessType = 1, - currentlyRegistered = 1, - groupReg = "foofoo", - dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = "bar", systemDate = Some(LocalDate.of(2024, 4, 21)) + businessType = Some(1), + currentlyRegistered = Some(1), + groupReg = Some("foofoo"), + dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = Some("bar"), systemDate = Some(LocalDate.of(2024, 4, 21)) ) case "XYZ00000000010" => BusinessDetails( mgdRegNumber = mgdRegNumber, - businessType = 3, - currentlyRegistered = 2, - groupReg = "foo", - dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = "bar", systemDate = Some(LocalDate.of(2024, 4, 21)) + businessType = Some(3), + currentlyRegistered = Some(2), + groupReg = Some("foo"), + dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = Some("bar"), systemDate = Some(LocalDate.of(2024, 4, 21)) ) case "XYZ00000000012" => BusinessDetails( mgdRegNumber = mgdRegNumber, - businessType = 1, - currentlyRegistered = 2, - groupReg = "foobar", - dateOfRegistration = Some(LocalDate.of(2023, 4, 21)), businessPartnerNumber = "barfoo", systemDate = Some(LocalDate.of(2023, 4, 21)) + businessType = Some(1), + currentlyRegistered = Some(2), + groupReg = Some("foobar"), + dateOfRegistration = Some(LocalDate.of(2023, 4, 21)), businessPartnerNumber = Some("barfoo"), systemDate = Some(LocalDate.of(2023, 4, 21)) ) case "XYZ00000000021" => BusinessDetails( mgdRegNumber = mgdRegNumber, - businessType = 5, - currentlyRegistered = 2, - groupReg = "foofoo", - dateOfRegistration = Some(LocalDate.of(2024, 1, 21)), businessPartnerNumber = "barbar", systemDate = Some(LocalDate.of(2024, 1, 21)) + businessType = Some(5), + currentlyRegistered = Some(2), + groupReg = Some("foofoo"), + dateOfRegistration = Some(LocalDate.of(2024, 1, 21)), businessPartnerNumber = Some("barbar"), systemDate = Some(LocalDate.of(2024, 1, 21)) ) case "ERR00000000000" => throw new RuntimeException("Simulated downstream failure") case _ => BusinessDetails( mgdRegNumber = mgdRegNumber, - businessType = 0, - currentlyRegistered = 0, - groupReg = "unknown", - dateOfRegistration = Some(LocalDate.of(2026, 4, 22)), businessPartnerNumber = "unknown", systemDate = Some(LocalDate.of(2026, 4, 22)) + businessType = Some(0), + currentlyRegistered = Some(0), + groupReg = Some("unknown"), + dateOfRegistration = Some(LocalDate.of(2026, 4, 22)), businessPartnerNumber = Some("unknown"), systemDate = Some(LocalDate.of(2026, 4, 22)) ) } } diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala index cb596a4..afe559d 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala @@ -125,7 +125,7 @@ class GamblingControllerSpec extends SpecBase with MockitoSugar { "returns 200 when service succeeds" in new Setup { val dateTime: Some[LocalDate] = Some(LocalDate.of(2026, 4, 20)) - val name = BusinessName("XWM00000001770", "fooBar", "foobar", Some("fooBar"), "fooBar", "fooBar", 1, "fooBar", dateTime) + val name = BusinessName("XWM00000001770", Some("fooBar"), Some("foobar"), Some("fooBar"), Some("fooBar"), Some("fooBar"), Some(1), Some("fooBar"), dateTime) when(mockService.getBusinessName(eqTo("XWM00000001770"))(any())) .thenReturn(Future.successful(Right(name))) @@ -143,7 +143,7 @@ class GamblingControllerSpec extends SpecBase with MockitoSugar { "allows request through AuthAction" in new Setup { val dateTime: Some[LocalDate] = Some(LocalDate.of(2026, 4, 20)) - val name = BusinessName("XWM00000001770", "fooBar", "foobar", Some("fooBar"), "fooBar", "fooBar", 1, "fooBar", dateTime) + val name = BusinessName("XWM00000001770", Some("fooBar"), Some("foobar"), Some("fooBar"), Some("fooBar"), Some("fooBar"), Some(1), Some("fooBar"), dateTime) when(mockService.getBusinessName(any())(any())) .thenReturn(Future.successful(Right(name))) @@ -191,7 +191,7 @@ class GamblingControllerSpec extends SpecBase with MockitoSugar { "GamblingController#getBusinessDetails" - { "returns 200 when service succeeds for BusinessDetails" in new Setup { - val summary = BusinessDetails("XWM00000001770", 2, 1, "foo", Some(LocalDate.of(2024, 4, 21)), "bar", Some(LocalDate.of(2024, 4, 21))) + val summary = BusinessDetails("XWM00000001770", Some(2), Some(1), Some("foo"), Some(LocalDate.of(2024, 4, 21)), Some("bar"), Some(LocalDate.of(2024, 4, 21))) when(mockService.getBusinessDetails(eqTo("XWM00000001770"))(any())) .thenReturn(Future.successful(Right(summary))) @@ -208,7 +208,7 @@ class GamblingControllerSpec extends SpecBase with MockitoSugar { } "allows request through AuthAction for BusinessDetails" in new Setup { - val summary = BusinessDetails("XWM00000001770", 2, 1, "foo", Some(LocalDate.of(2024, 4, 21)), "bar", Some(LocalDate.of(2024, 4, 21))) + val summary = BusinessDetails("XWM00000001770", Some(2), Some(1), Some("foo"), Some(LocalDate.of(2024, 4, 21)), Some("bar"), Some(LocalDate.of(2024, 4, 21))) when(mockService.getBusinessDetails(any())(any())) .thenReturn(Future.successful(Right(summary))) diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingModelSpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingModelSpec.scala index 29bd88b..e7deaa8 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingModelSpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingModelSpec.scala @@ -68,13 +68,13 @@ class GamblingModelSpec extends AnyWordSpec with Matchers { model mustBe BusinessName( mgdRegNumber = "XYZ00000000000", - solePropTitle = "Mr", - solePropFirstName = "John", + solePropTitle = Some("Mr"), + solePropFirstName = Some("John"), solePropMidName = Some("C"), - solePropLastName = "Doe", - businessName = "John Doe Co.", - businessType = 1, - tradingName = "DoeDoe", + solePropLastName = Some("Doe"), + businessName = Some("John Doe Co."), + businessType = Some(1), + tradingName = Some("DoeDoe"), systemDate = Some(dateBusinessName) ) @@ -103,11 +103,11 @@ class GamblingModelSpec extends AnyWordSpec with Matchers { model mustBe BusinessDetails( mgdRegNumber = "XYZ00000000000", - businessType = 1, - currentlyRegistered = 1, - groupReg = "foo", + businessType = Some(1), + currentlyRegistered = Some(1), + groupReg = Some("foo"), dateOfRegistration = Some(LocalDate.of(2000, 1, 1)), - businessPartnerNumber = "bar", + businessPartnerNumber = Some("bar"), systemDate = Some(LocalDate.of(2000, 1, 1)) ) diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala index 7cf4f99..8864550 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala @@ -99,13 +99,13 @@ final class GamblingServiceSpec extends SpecBase { val summary = BusinessName( mgdRegNumber = validMgdRegNumber, - solePropTitle = "Mr", - solePropFirstName = "Foo", + solePropTitle = Some("Mr"), + solePropFirstName = Some("Foo"), solePropMidName = Some("B"), - solePropLastName = "Bar", - businessName = "FooBar Co.", - businessType = 1, - tradingName = "Foobar", + solePropLastName = Some("Bar"), + businessName = Some("FooBar Co."), + businessType = Some(1), + tradingName = Some("Foobar"), systemDate = Some(LocalDate.of(1991, 1, 1)) ) @@ -125,13 +125,13 @@ final class GamblingServiceSpec extends SpecBase { val summary = BusinessName( mgdRegNumber = normalisedMgdRegNumber, - solePropTitle = "Mr", - solePropFirstName = "John", + solePropTitle = Some("Mr"), + solePropFirstName = Some("John"), solePropMidName = Some("C"), - solePropLastName = "Doe", - businessName = "John Doe Co.", - businessType = 1, - tradingName = "DoeDoe", + solePropLastName = Some("Doe"), + businessName = Some("John Doe Co."), + businessType = Some(1), + tradingName = Some("DoeDoe"), systemDate = Some(LocalDate.of(1991, 1, 1)) ) @@ -169,11 +169,11 @@ final class GamblingServiceSpec extends SpecBase { val summary = BusinessDetails( mgdRegNumber = normalisedMgdRegNumber, - businessType = 1, - currentlyRegistered = 2, - groupReg = "foo", + businessType = Some(1), + currentlyRegistered = Some(2), + groupReg = Some("foo"), dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), - businessPartnerNumber = "bar", + businessPartnerNumber = Some("bar"), systemDate = Some(LocalDate.of(2024, 4, 21)) ) when(repository.getBusinessDetails(eqTo(validMgdRegNumber))) @@ -192,11 +192,11 @@ final class GamblingServiceSpec extends SpecBase { val summary = BusinessDetails( mgdRegNumber = normalisedMgdRegNumber, - businessType = 1, - currentlyRegistered = 2, - groupReg = "foo", + businessType = Some(1), + currentlyRegistered = Some(2), + groupReg = Some("foo"), dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), - businessPartnerNumber = "bar", + businessPartnerNumber = Some("bar"), systemDate = Some(LocalDate.of(2024, 4, 21)) ) From 50f16a864b39c4c7b74646e57390172f315c9ea1 Mon Sep 17 00:00:00 2001 From: AnotherMattWright <270914550+AnotherMattWright@users.noreply.github.com> Date: Fri, 1 May 2026 13:47:55 +0100 Subject: [PATCH 10/16] GCSpec reformat --- .../controllers/GamblingControllerSpec.scala | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala index afe559d..5ade39d 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala @@ -125,7 +125,16 @@ class GamblingControllerSpec extends SpecBase with MockitoSugar { "returns 200 when service succeeds" in new Setup { val dateTime: Some[LocalDate] = Some(LocalDate.of(2026, 4, 20)) - val name = BusinessName("XWM00000001770", Some("fooBar"), Some("foobar"), Some("fooBar"), Some("fooBar"), Some("fooBar"), Some(1), Some("fooBar"), dateTime) + val name = BusinessName("XWM00000001770", + Some("fooBar"), + Some("foobar"), + Some("fooBar"), + Some("fooBar"), + Some("fooBar"), + Some(1), + Some("fooBar"), + dateTime + ) when(mockService.getBusinessName(eqTo("XWM00000001770"))(any())) .thenReturn(Future.successful(Right(name))) @@ -143,7 +152,16 @@ class GamblingControllerSpec extends SpecBase with MockitoSugar { "allows request through AuthAction" in new Setup { val dateTime: Some[LocalDate] = Some(LocalDate.of(2026, 4, 20)) - val name = BusinessName("XWM00000001770", Some("fooBar"), Some("foobar"), Some("fooBar"), Some("fooBar"), Some("fooBar"), Some(1), Some("fooBar"), dateTime) + val name = BusinessName("XWM00000001770", + Some("fooBar"), + Some("foobar"), + Some("fooBar"), + Some("fooBar"), + Some("fooBar"), + Some(1), + Some("fooBar"), + dateTime + ) when(mockService.getBusinessName(any())(any())) .thenReturn(Future.successful(Right(name))) @@ -191,7 +209,14 @@ class GamblingControllerSpec extends SpecBase with MockitoSugar { "GamblingController#getBusinessDetails" - { "returns 200 when service succeeds for BusinessDetails" in new Setup { - val summary = BusinessDetails("XWM00000001770", Some(2), Some(1), Some("foo"), Some(LocalDate.of(2024, 4, 21)), Some("bar"), Some(LocalDate.of(2024, 4, 21))) + val summary = BusinessDetails("XWM00000001770", + Some(2), + Some(1), + Some("foo"), + Some(LocalDate.of(2024, 4, 21)), + Some("bar"), + Some(LocalDate.of(2024, 4, 21)) + ) when(mockService.getBusinessDetails(eqTo("XWM00000001770"))(any())) .thenReturn(Future.successful(Right(summary))) @@ -208,7 +233,14 @@ class GamblingControllerSpec extends SpecBase with MockitoSugar { } "allows request through AuthAction for BusinessDetails" in new Setup { - val summary = BusinessDetails("XWM00000001770", Some(2), Some(1), Some("foo"), Some(LocalDate.of(2024, 4, 21)), Some("bar"), Some(LocalDate.of(2024, 4, 21))) + val summary = BusinessDetails("XWM00000001770", + Some(2), + Some(1), + Some("foo"), + Some(LocalDate.of(2024, 4, 21)), + Some("bar"), + Some(LocalDate.of(2024, 4, 21)) + ) when(mockService.getBusinessDetails(any())(any())) .thenReturn(Future.successful(Right(summary))) From 49b33bfada535a72998c661011fdea3b9265a231 Mon Sep 17 00:00:00 2001 From: AnotherMattWright <270914550+AnotherMattWright@users.noreply.github.com> Date: Tue, 5 May 2026 09:15:22 +0100 Subject: [PATCH 11/16] add empty line --- .../gambling/GamblingDataCacheRepositoryISpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala index a7dc863..5143c5c 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala @@ -363,4 +363,4 @@ class GamblingDataCacheRepositoryISpec result mustBe BusinessDetails(" ", Some(0), Some(0), Some("unknown"), Some(LocalDate.of(2026, 4, 22)), Some("unknown"), Some(LocalDate.of(2026, 4, 22))) } } -} \ No newline at end of file +} From 9f4f222dee5f6fdf0f14a5d1ae59032f0fba15f2 Mon Sep 17 00:00:00 2001 From: AnotherMattWright <270914550+AnotherMattWright@users.noreply.github.com> Date: Wed, 6 May 2026 15:14:04 +0100 Subject: [PATCH 12/16] merged and refactored across repo for new types --- .../controllers/GamblingController.scala | 23 ------ .../gambling/models/BusinessDetails.scala | 16 ++-- .../gambling/models/BusinessName.scala | 4 +- .../GamblingDataCacheRepository.scala | 80 +++++-------------- .../gambling/services/GamblingService.scala | 19 ----- .../GamblingControllerIntegrationSpec.scala | 6 +- .../GamblingDataCacheRepositoryISpec.scala | 62 ++++++-------- .../gambling/GamblingStubData.scala | 60 +++++++------- .../controllers/GamblingControllerSpec.scala | 32 ++++---- .../gambling/models/GamblingModelSpec.scala | 12 +-- .../gambling/models/GamblingStubData.scala | 25 +++++- .../GamblingDataCacheRepositorySpec.scala | 2 +- .../services/GamblingServiceSpec.scala | 69 +--------------- 13 files changed, 136 insertions(+), 274 deletions(-) diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingController.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingController.scala index cb6ae09..f058fc1 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingController.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingController.scala @@ -104,29 +104,6 @@ class GamblingController @Inject() (authorise: AuthAction, service: GamblingServ } } - def getBusinessDetails(mgdRegNumber: String): Action[AnyContent] = - authorise.async { implicit request => - - service.getBusinessDetails(mgdRegNumber).map { - case Right(details) => - Ok(Json.toJson(details)) - - case Left(error) => - val logMessage = - s"[GamblingController][getBusinessDetails] code=${error.code} mgdRegNumber=$mgdRegNumber" - - error match { - case InvalidMgdRegNumber => - logger.warn(logMessage) - BadRequest(errorResponse(error)) - - case UnexpectedError => - logger.error(logMessage) - InternalServerError(errorResponse(error)) - } - } - } - def getOperatorDetails(mgdRegNumber: String): Action[AnyContent] = authorise.async { implicit request => diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessDetails.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessDetails.scala index a72c59c..be8d38b 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessDetails.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessDetails.scala @@ -21,14 +21,14 @@ import play.api.libs.json.{Json, OFormat} import java.time.LocalDate final case class BusinessDetails( - mgdRegNumber: String, - businessType: Option[BusinessType], - currentlyRegistered: Int, - isGroupMember: Boolean, - dateOfRegistration: Option[LocalDate], - businessPartnerNumber: Option[String], - systemDate: LocalDate - ) + mgdRegNumber: String, + businessType: Option[BusinessType], + currentlyRegistered: Int, + groupReg: Boolean, + dateOfRegistration: Option[LocalDate], + businessPartnerNumber: Option[String], + systemDate: LocalDate +) object BusinessDetails { implicit val format: OFormat[BusinessDetails] = Json.format[BusinessDetails] diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala index 5115fae..820de90 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/BusinessName.scala @@ -18,14 +18,14 @@ package uk.gov.hmrc.rdsdatacacheproxy.gambling.models import play.api.libs.json.{Json, OFormat} import java.time.LocalDate -case class BusinessName( +final case class BusinessName( mgdRegNumber: String, solePropTitle: Option[String], solePropFirstName: Option[String], solePropMidName: Option[String], solePropLastName: Option[String], businessName: Option[String], - businessType: Option[Int], + businessType: Option[BusinessType], tradingName: Option[String], systemDate: Option[LocalDate] ) diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala index 754dac2..5f3e89d 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepository.scala @@ -25,11 +25,10 @@ import scala.concurrent.{ExecutionContext, Future, blocking} trait GamblingDataSource { def getReturnSummary(mgdRegNumber: String): Future[ReturnSummary] - def getBusinessDetails(mgdRegNumber: String): Future[BusinessDetails] def getBusinessName(mgdRegNumber: String): Future[BusinessName] + def getBusinessDetails(mgdRegNumber: String): Future[BusinessDetails] def getMgdCertificate(mgdRegNumber: String): Future[MgdCertificate] def getOperatorDetails(mgdRegNumber: String): Future[OperatorDetails] - def getBusinessDetails(mgdRegNumber: String): Future[BusinessDetails] } @Singleton @@ -101,7 +100,7 @@ class GamblingDataCacheRepository @Inject() ( mgdRegNumber = rs.getString("mgd_reg_number"), businessType = businessType, currentlyRegistered = rs.getInt("currently_registered"), - isGroupMember = groupReg, + groupReg = groupReg, dateOfRegistration = optDate("date_of_registration"), businessPartnerNumber = optString("business_partner_number"), systemDate = java.time.LocalDate.now() @@ -351,50 +350,6 @@ class GamblingDataCacheRepository @Inject() ( } })(ec) } - - override def getReturnSummary(mgdRegNumber: String): Future[ReturnSummary] = { - - logger.info(s"[GamblingDataCacheRepository][getReturnSummary] mgdRegNumber=$mgdRegNumber") - - Future { - db.withConnection { conn => - - val cs = conn.prepareCall("{ call MGD_DC_RTN_PCK.GET_RETURN_SUMMARY(?, ?) }") - - try { - cs.setString(1, mgdRegNumber) - cs.registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR) - cs.execute() - - val rs = cs.getObject(2).asInstanceOf[java.sql.ResultSet] - - if (rs == null) { - val msg = s"Null cursor returned for mgdRegNumber=$mgdRegNumber" - logger.error(s"[GamblingDataCacheRepository] $msg") - throw new RuntimeException(msg) - } - - try { - if (rs.next()) { - ReturnSummary( - mgdRegNumber = rs.getString("MGD_REG_NUMBER"), - returnsDue = rs.getInt("RETURNS_DUE"), - returnsOverdue = rs.getInt("RETURNS_OVERDUE") - ) - } else { - val msg = s"Empty result set for mgdRegNumber=$mgdRegNumber" - logger.error(s"[GamblingDataCacheRepository] $msg") - throw new RuntimeException(msg) - } - } finally { - rs.close() - } - } finally { - cs.close() - } - } - }(ec) - } override def getBusinessName(mgdRegNumber: String): Future[BusinessName] = { logger.info(s"[GamblingDataCacheRepository][getBusinessName] mgdRegNumber=$mgdRegNumber") @@ -419,6 +374,17 @@ class GamblingDataCacheRepository @Inject() ( try { if (rs.next()) { + + def optInt(col: String): Option[Int] = + Option(rs.getObject(col)).map { + case bd: java.math.BigDecimal => bd.intValue() + case n: java.lang.Number => n.intValue() + case other => other.toString.toInt + } + + val businessType: Option[BusinessType] = + optInt("business_type").flatMap(BusinessType.fromCode) + BusinessName( mgdRegNumber = rs.getString("MGD_REG_NUMBER"), solePropTitle = Option(rs.getString("SOLE_PROP_TITLE")), @@ -426,7 +392,7 @@ class GamblingDataCacheRepository @Inject() ( solePropMidName = Option(rs.getString("SOLE_PROP_MIDDLE_NAME")), solePropLastName = Option(rs.getString("SOLE_PROP_LAST_NAME")), businessName = Option(rs.getString("BUSINESS_NAME")), - businessType = Option(rs.getInt("BUSINESS_TYPE")), + businessType = businessType, tradingName = Option(rs.getString("TRADING_NAME")), systemDate = Option(rs.getDate("SYSTEM_DATE")).map(_.toLocalDate) ) @@ -445,14 +411,14 @@ class GamblingDataCacheRepository @Inject() ( }(ec) } - override def getBusinessDetails(mgdRegNumber: String): Future[BusinessDetails] = { + override def getReturnSummary(mgdRegNumber: String): Future[ReturnSummary] = { - logger.info(s"[GamblingDataCacheRepository][getBusinessDetails] mgdRegNumber=$mgdRegNumber") + logger.info(s"[GamblingDataCacheRepository][getReturnSummary] mgdRegNumber=$mgdRegNumber") Future { db.withConnection { conn => - val cs = conn.prepareCall("{ call MGD_DC_VARIATION_PK.GET_BUSINESS_DETAILS(?, ?) }") + val cs = conn.prepareCall("{ call MGD_DC_RTN_PCK.GET_RETURN_SUMMARY(?, ?) }") try { cs.setString(1, mgdRegNumber) @@ -469,14 +435,10 @@ class GamblingDataCacheRepository @Inject() ( try { if (rs.next()) { - BusinessDetails( - mgdRegNumber = rs.getString("MGD_REG_NUMBER"), - businessType = Option(rs.getInt("BUSINESS_TYPE")), - currentlyRegistered = Option(rs.getInt("CURRENTLY_REGISTERED")), - groupReg = Option(rs.getString("GROUP_REG")), - dateOfRegistration = Option(rs.getDate("DATE_OF_REGISTRATION")).map(_.toLocalDate), - businessPartnerNumber = Option(rs.getString("BUSINESS_PARTNER_NUMBER")), - systemDate = Option(rs.getDate("SYSTEM_DATE")).map(_.toLocalDate) + ReturnSummary( + mgdRegNumber = rs.getString("MGD_REG_NUMBER"), + returnsDue = rs.getInt("RETURNS_DUE"), + returnsOverdue = rs.getInt("RETURNS_OVERDUE") ) } else { val msg = s"Empty result set for mgdRegNumber=$mgdRegNumber" diff --git a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingService.scala b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingService.scala index 2cdf83d..64f6675 100644 --- a/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingService.scala +++ b/app/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingService.scala @@ -70,25 +70,6 @@ class GamblingService @Inject() ( } } - def getBusinessDetails(rawMgdRegNumber: String)(implicit hc: HeaderCarrier): Future[Either[GamblingError, BusinessDetails]] = { - - val mgdRegNumber = rawMgdRegNumber.trim.toUpperCase - - if (!mgdRegNumberPattern.matcher(mgdRegNumber).matches()) { - logger.warn(s"[GamblingService][getBusinessDetails] Invalid pattern for mgdRegNumber=$mgdRegNumber") - Future.successful(Left(InvalidMgdRegNumber)) - } else { - - repository - .getBusinessDetails(mgdRegNumber) - .map(summary => Right(summary)) - .recover { case ex: Exception => - logger.error(s"[GamblingService][getBusinessDetails] Unexpected error mgdRegNumber=$mgdRegNumber", ex) - Left(UnexpectedError) - } - } - } - def getMgdCertificate(rawMgdRegNumber: String)(implicit hc: HeaderCarrier): Future[Either[GamblingError, MgdCertificate]] = { val mgdRegNumber = rawMgdRegNumber.trim.toUpperCase diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingControllerIntegrationSpec.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingControllerIntegrationSpec.scala index 5b260e3..6202190 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingControllerIntegrationSpec.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingControllerIntegrationSpec.scala @@ -45,7 +45,7 @@ class GamblingControllerIntegrationSpec extends AnyWordSpec with Matchers with S mgdRegNumber = mgdRegNumber, businessType = None, currentlyRegistered = 1, - isGroupMember = true, + groupReg = true, dateOfRegistration = None, businessPartnerNumber = Some("BP123"), systemDate = java.time.LocalDate.now() @@ -131,7 +131,7 @@ class GamblingControllerIntegrationSpec extends AnyWordSpec with Matchers with S ) .build() - private val businessDetailEndpoint = "/gambling/business-details" + private val endpoint = "/gambling/return-summary" implicit val localDateReads: Reads[LocalDate] = Reads.localDateReads("yyyy-MM-dd") @@ -276,7 +276,7 @@ class GamblingControllerIntegrationSpec extends AnyWordSpec with Matchers with S (response.json \ "mgdRegNumber").as[String] mustBe "XYZ00000000012" (response.json \ "currentlyRegistered").as[Int] mustBe 1 - (response.json \ "isGroupMember").as[Boolean] mustBe true + (response.json \ "groupReg").as[Boolean] mustBe true (response.json \ "businessPartnerNumber").as[String] mustBe "BP123" } diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala index eb1a6db..477f76c 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala @@ -23,7 +23,7 @@ import org.scalatestplus.play.guice.GuiceOneAppPerSuite import play.api.Application import play.api.inject.bind import play.api.inject.guice.GuiceApplicationBuilder -import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.{BusinessDetails, BusinessName, GamblingStubData, OperatorDetails, MgdCertificate, ReturnSummary} +import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.{BusinessDetails, BusinessName, GamblingStubData, OperatorDetails, MgdCertificate, ReturnSummary, BusinessType} import uk.gov.hmrc.rdsdatacacheproxy.gambling.repositories.GamblingDataSource import java.time.LocalDate @@ -258,7 +258,7 @@ class GamblingDataCacheRepositoryISpec extends AnyWordSpec with Matchers with Sc solePropMidName = Some("C"), solePropLastName = Some("Doe"), businessName = Some("John Doe Co."), - businessType = Some(1), + businessType = Some(BusinessType.SoleProprietor), tradingName = Some("DoeDoe"), systemDate = Some(LocalDate.of(2026, 4, 20)) ) @@ -274,7 +274,7 @@ class GamblingDataCacheRepositoryISpec extends AnyWordSpec with Matchers with Sc solePropMidName = Some("Jacqueline"), solePropLastName = Some("Simpson"), businessName = Some("Pretzel Wagon"), - businessType = Some(1), + businessType = Some(BusinessType.SoleProprietor), tradingName = Some("Marge Simpson"), systemDate = Some(LocalDate.of(2026, 4, 20)) ) @@ -305,7 +305,7 @@ class GamblingDataCacheRepositoryISpec extends AnyWordSpec with Matchers with Sc val result = repository.getBusinessName("XYZ00000000021").futureValue result.solePropFirstName mustBe Some("Eugine") - result.businessType mustBe Some(1) + result.businessType mustBe Some(BusinessType.SoleProprietor) } "return default values for unknown mgdRegNumber" in { @@ -318,7 +318,7 @@ class GamblingDataCacheRepositoryISpec extends AnyWordSpec with Matchers with Sc solePropMidName = Some("B"), solePropLastName = Some("Bar"), businessName = Some("FooBar Co."), - businessType = Some(1), + businessType = Some(BusinessType.SoleProprietor), tradingName = Some("Foobar"), systemDate = Some(LocalDate.of(2026, 4, 20)) ) @@ -377,64 +377,53 @@ class GamblingDataCacheRepositoryISpec extends AnyWordSpec with Matchers with Sc result mustBe BusinessDetails( mgdRegNumber = "XYZ00000000000", - businessType = Some(6), - currentlyRegistered = Some(2), - groupReg = Some("foo"), - dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = Some("bar"), systemDate = Some(LocalDate.of(2024, 4, 21)) + businessType = Some(BusinessType.LimitedLiabilityPartnership), + currentlyRegistered = 1, + groupReg = true, + dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = Some("bar"), systemDate = LocalDate.of(2024, 4, 21) ) } "return business type correctly" in { val result = repository.getBusinessDetails("XYZ00000000001").futureValue - result.businessType mustBe Some(1) - result.currentlyRegistered mustBe Some(1) - result.groupReg mustBe Some("foofoo") + result.businessType mustBe Some(BusinessType.LimitedLiabilityPartnership) + result.currentlyRegistered mustBe 1 + result.groupReg mustBe true result.dateOfRegistration mustBe Some(LocalDate.of(2024, 4, 21)) result.businessPartnerNumber mustBe Some("bar") - result.systemDate mustBe Some(LocalDate.of(2024, 4, 21)) + result.systemDate mustBe LocalDate.of(2024, 4, 21) } "return group reg correctly" in { val result = repository.getBusinessDetails("XYZ00000000010").futureValue - result.businessType mustBe Some(3) - result.currentlyRegistered mustBe Some(2) - result.groupReg mustBe Some("foo") + result.businessType mustBe Some(BusinessType.UnincorporatedBody) + result.currentlyRegistered mustBe 2 + result.groupReg mustBe true result.dateOfRegistration mustBe Some(LocalDate.of(2024, 4, 21)) result.businessPartnerNumber mustBe Some("bar") - result.systemDate mustBe Some(LocalDate.of(2024, 4, 21)) + result.systemDate mustBe LocalDate.of(2024, 4, 21) } "return both date values correctly" in { val result = repository.getBusinessDetails("XYZ00000000012").futureValue - result mustBe BusinessDetails("XYZ00000000012", Some(1), Some(2), Some("foobar"), Some(LocalDate.of(2023, 4, 21)), Some("barfoo"), Some(LocalDate.of(2023, 4, 21))) + result mustBe BusinessDetails("XYZ00000000012", Some(BusinessType.UnincorporatedBody), 2, true, Some(LocalDate.of(2023, 4, 21)), Some("barfoo"), LocalDate.of(2023, 4, 21)) } "handle multiple values" in { val result = repository.getBusinessDetails("XYZ00000000021").futureValue - result.businessType mustBe Some(5) - result.currentlyRegistered mustBe Some(2) - result.groupReg mustBe Some("foofoo") + result.businessType mustBe Some(BusinessType.Partnership) + result.currentlyRegistered mustBe 2 + result.groupReg mustBe false result.dateOfRegistration mustBe Some(LocalDate.of(2024, 1, 21)) result.businessPartnerNumber mustBe Some("barbar") - result.systemDate mustBe Some(LocalDate.of(2024, 1, 21)) + result.systemDate mustBe LocalDate.of(2024, 1, 21) } - "return default values for unknown mgdRegNumber" in { - val result = repository.getBusinessDetails("XYZ99999999999").futureValue - - result mustBe BusinessDetails("XYZ99999999999", Some(0), Some(0), Some("unknown"), Some(LocalDate.of(2026, 4, 22)), Some("unknown"), Some(LocalDate.of(2026, 4, 22))) - } - "return consistent results across multiple calls" in { - val result1 = repository.getBusinessDetails("XYZ00000000012").futureValue - val result2 = repository.getBusinessDetails("XYZ00000000012").futureValue - - result1 mustBe result2 - } "handle different valid mgdRegNumbers independently" in { val result1 = repository.getBusinessDetails("XYZ00000000010").futureValue @@ -451,16 +440,11 @@ class GamblingDataCacheRepositoryISpec extends AnyWordSpec with Matchers with Sc exception.getMessage must include("Simulated downstream failure") } - "handle special characters in mgdRegNumber" in { - val result = repository.getBusinessDetails("XYZ-123/ABC").futureValue - - result mustBe BusinessDetails("XYZ-123/ABC", Some(0), Some(0), Some("unknown"), Some(LocalDate.of(2026, 4, 22)), Some("unknown"), Some(LocalDate.of(2026, 4, 22))) - } "handle whitespace mgdRegNumber" in { val result = repository.getBusinessDetails(" ").futureValue - result mustBe BusinessDetails(" ", Some(0), Some(0), Some("unknown"), Some(LocalDate.of(2026, 4, 22)), Some("unknown"), Some(LocalDate.of(2026, 4, 22))) + result mustBe BusinessDetails(" ", Some(BusinessType.SoleProprietor), 0, true, Some(LocalDate.of(2026, 4, 22)), Some("unknown"), LocalDate.of(2026, 4, 22)) } } } diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala index f5f4eac..f9f1fba 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala @@ -50,7 +50,7 @@ object GamblingStubData { solePropMidName = Some("C"), solePropLastName = Some("Doe"), businessName = Some("John Doe Co."), - businessType = Some(1), + businessType = Some(BusinessType.SoleProprietor), tradingName = Some("DoeDoe"), systemDate = dateTimeOne) case "XYZ00000000001" => @@ -60,7 +60,7 @@ object GamblingStubData { solePropMidName = Some("C"), solePropLastName = Some("Doe"), businessName = Some("Jane Doe Co."), - businessType = Some(1), + businessType = Some(BusinessType.SoleProprietor), tradingName = Some("DoeDoe"), systemDate = dateTimeTwo) case "XYZ00000000010" => @@ -70,7 +70,7 @@ object GamblingStubData { solePropMidName = Some("Jacqueline"), solePropLastName = Some("Simpson"), businessName = Some("Pretzel Wagon"), - businessType = Some(1), + businessType = Some(BusinessType.SoleProprietor), tradingName = Some("Marge Simpson"), systemDate = dateTimeOne) case "XYZ00000000012" => @@ -80,7 +80,7 @@ object GamblingStubData { solePropMidName = None, solePropLastName = Some("Havisham"), businessName = Some("Failed Expectations"), - businessType = Some(1), + businessType = Some(BusinessType.SoleProprietor), tradingName = Some("Miss Havisham"), systemDate = dateTimeThree) case "XYZ00000000021" => @@ -90,7 +90,7 @@ object GamblingStubData { solePropMidName = Some("H"), solePropLastName = Some("Krabs"), businessName = Some("Krusty Krab"), - businessType = Some(1), + businessType = Some(BusinessType.SoleProprietor), tradingName = Some("Mr Krabs"), systemDate = dateTimeThree) case "ERR00000000000" => @@ -102,7 +102,7 @@ object GamblingStubData { solePropMidName= Some("B"), solePropLastName= Some("Bar"), businessName= Some("FooBar Co."), - businessType= Some(1), + businessType = Some(BusinessType.SoleProprietor), tradingName= Some("Foobar"), systemDate= dateTimeOne ) @@ -116,52 +116,52 @@ object GamblingStubData { case "XYZ00000000000" => BusinessDetails( mgdRegNumber = mgdRegNumber, - businessType = Some(6), - currentlyRegistered = Some(2), - groupReg = Some("foo"), - dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = Some("bar"), systemDate = Some(LocalDate.of(2024, 4, 21)) + businessType = Some(BusinessType.CorporateBody), + currentlyRegistered = 2, + groupReg = false, + dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = Some("bar"), systemDate = LocalDate.of(2024, 4, 21) ) case "XYZ00000000001" => BusinessDetails( mgdRegNumber = mgdRegNumber, - businessType = Some(1), - currentlyRegistered = Some(1), - groupReg = Some("foofoo"), - dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = Some("bar"), systemDate = Some(LocalDate.of(2024, 4, 21)) + businessType = Some(BusinessType.LimitedLiabilityPartnership), + currentlyRegistered = 1, + groupReg = false, + dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = Some("bar"), systemDate = LocalDate.of(2024, 4, 21) ) case "XYZ00000000010" => BusinessDetails( mgdRegNumber = mgdRegNumber, - businessType = Some(3), - currentlyRegistered = Some(2), - groupReg = Some("foo"), - dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = Some("bar"), systemDate = Some(LocalDate.of(2024, 4, 21)) + businessType = Some(BusinessType.UnincorporatedBody), + currentlyRegistered = 2, + groupReg = true, + dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = Some("bar"), systemDate = LocalDate.of(2024, 4, 21) ) case "XYZ00000000012" => BusinessDetails( mgdRegNumber = mgdRegNumber, - businessType = Some(1), - currentlyRegistered = Some(2), - groupReg = Some("foobar"), - dateOfRegistration = Some(LocalDate.of(2023, 4, 21)), businessPartnerNumber = Some("barfoo"), systemDate = Some(LocalDate.of(2023, 4, 21)) + businessType = Some(BusinessType.SoleProprietor), + currentlyRegistered = 2, + groupReg = true, + dateOfRegistration = Some(LocalDate.of(2023, 4, 21)), businessPartnerNumber = Some("barfoo"), systemDate = LocalDate.of(2023, 4, 21) ) case "XYZ00000000021" => BusinessDetails( mgdRegNumber = mgdRegNumber, - businessType = Some(5), - currentlyRegistered = Some(2), - groupReg = Some("foofoo"), - dateOfRegistration = Some(LocalDate.of(2024, 1, 21)), businessPartnerNumber = Some("barbar"), systemDate = Some(LocalDate.of(2024, 1, 21)) + businessType = Some(BusinessType.Partnership), + currentlyRegistered = 2, + groupReg = false, + dateOfRegistration = Some(LocalDate.of(2024, 1, 21)), businessPartnerNumber = Some("barbar"), systemDate = LocalDate.of(2024, 1, 21) ) case "ERR00000000000" => throw new RuntimeException("Simulated downstream failure") case _ => BusinessDetails( mgdRegNumber = mgdRegNumber, - businessType = Some(0), - currentlyRegistered = Some(0), - groupReg = Some("unknown"), - dateOfRegistration = Some(LocalDate.of(2026, 4, 22)), businessPartnerNumber = Some("unknown"), systemDate = Some(LocalDate.of(2026, 4, 22)) + businessType = Some(BusinessType.Partnership), + currentlyRegistered = 0, + groupReg = false, + dateOfRegistration = Some(LocalDate.of(2026, 4, 22)), businessPartnerNumber = Some("unknown"), systemDate = LocalDate.of(2026, 4, 22) ) } } diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala index 5ade39d..06ca943 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/controllers/GamblingControllerSpec.scala @@ -42,8 +42,7 @@ import play.api.test.FakeRequest import play.api.test.Helpers.* import uk.gov.hmrc.rdsdatacacheproxy.base.SpecBase import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.GamblingError.{InvalidMgdRegNumber, UnexpectedError} -import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.{BusinessDetails, ReturnSummary} -import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.BusinessName +import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.{BusinessDetails, BusinessName, BusinessType, ReturnSummary} import uk.gov.hmrc.rdsdatacacheproxy.gambling.services.GamblingService import java.time.LocalDate @@ -131,7 +130,7 @@ class GamblingControllerSpec extends SpecBase with MockitoSugar { Some("fooBar"), Some("fooBar"), Some("fooBar"), - Some(1), + Some(BusinessType.Partnership), Some("fooBar"), dateTime ) @@ -158,7 +157,7 @@ class GamblingControllerSpec extends SpecBase with MockitoSugar { Some("fooBar"), Some("fooBar"), Some("fooBar"), - Some(1), + Some(BusinessType.Partnership), Some("fooBar"), dateTime ) @@ -210,12 +209,12 @@ class GamblingControllerSpec extends SpecBase with MockitoSugar { "returns 200 when service succeeds for BusinessDetails" in new Setup { val summary = BusinessDetails("XWM00000001770", - Some(2), - Some(1), - Some("foo"), + Some(BusinessType.SoleProprietor), + 1, + true, Some(LocalDate.of(2024, 4, 21)), Some("bar"), - Some(LocalDate.of(2024, 4, 21)) + LocalDate.of(2024, 4, 21) ) when(mockService.getBusinessDetails(eqTo("XWM00000001770"))(any())) @@ -233,14 +232,15 @@ class GamblingControllerSpec extends SpecBase with MockitoSugar { } "allows request through AuthAction for BusinessDetails" in new Setup { - val summary = BusinessDetails("XWM00000001770", - Some(2), - Some(1), - Some("foo"), - Some(LocalDate.of(2024, 4, 21)), - Some("bar"), - Some(LocalDate.of(2024, 4, 21)) - ) + val summary = + BusinessDetails("XWM00000001770", + Some(BusinessType.SoleProprietor), + 1, + true, + Some(LocalDate.of(2024, 4, 21)), + Some("bar"), + LocalDate.of(2024, 4, 21) + ) when(mockService.getBusinessDetails(any())(any())) .thenReturn(Future.successful(Right(summary))) diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingModelSpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingModelSpec.scala index e7deaa8..c2b4cd4 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingModelSpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingModelSpec.scala @@ -73,7 +73,7 @@ class GamblingModelSpec extends AnyWordSpec with Matchers { solePropMidName = Some("C"), solePropLastName = Some("Doe"), businessName = Some("John Doe Co."), - businessType = Some(1), + businessType = Some(BusinessType.SoleProprietor), tradingName = Some("DoeDoe"), systemDate = Some(dateBusinessName) ) @@ -91,7 +91,7 @@ class GamblingModelSpec extends AnyWordSpec with Matchers { |"mgdRegNumber": "XYZ00000000000", |"businessType": 1, |"currentlyRegistered": 1, - |"groupReg": "foo", + |"groupReg": true, |"dateOfRegistration": "$date", |"businessPartnerNumber": "bar", |"systemDate": "$date" @@ -103,12 +103,12 @@ class GamblingModelSpec extends AnyWordSpec with Matchers { model mustBe BusinessDetails( mgdRegNumber = "XYZ00000000000", - businessType = Some(1), - currentlyRegistered = Some(1), - groupReg = Some("foo"), + businessType = Some(BusinessType.SoleProprietor), + currentlyRegistered = 1, + groupReg = true, dateOfRegistration = Some(LocalDate.of(2000, 1, 1)), businessPartnerNumber = Some("bar"), - systemDate = Some(LocalDate.of(2000, 1, 1)) + systemDate = LocalDate.of(2000, 1, 1) ) Json.toJson(model) mustBe json diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingStubData.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingStubData.scala index 7cc1270..1a60e35 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingStubData.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingStubData.scala @@ -95,13 +95,36 @@ object GamblingStubData { mgdRegNumber = mgdRegNumber, businessType = None, currentlyRegistered = 1, - isGroupMember = false, + groupReg = false, dateOfRegistration = Some(LocalDate.now().minusYears(1)), businessPartnerNumber = Some("BPN123456"), systemDate = LocalDate.now() ) } + def getBusinessName(mgdRegNumber: String): BusinessName = + mgdRegNumber match { + + case "ERR00000000000" => + throw new RuntimeException("Simulated downstream failure") + + case "EMPTY000000000" => + throw new RuntimeException("No business details found") + + case _ => + BusinessName( + mgdRegNumber = mgdRegNumber, + solePropTitle = Some("abc"), + solePropFirstName = Some("abc"), + solePropMidName = Some("abc"), + solePropLastName = Some("abc"), + businessName = Some("abc"), + businessType = None, + tradingName = Some("abc"), + systemDate = Some(LocalDate.now()) + ) + } + // ------------------------- // MgdCertificate // ------------------------- diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala index 511a3c8..4fd01ca 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/repositories/GamblingDataCacheRepositorySpec.scala @@ -150,7 +150,7 @@ class GamblingDataCacheRepositorySpec extends AnyFlatSpec with Matchers with Bef result.mgdRegNumber shouldBe mgdRegNumber result.currentlyRegistered shouldBe 1 - result.isGroupMember shouldBe true + result.groupReg shouldBe true result.businessPartnerNumber shouldBe Some("BP123") verify(mockCs).setString(1, mgdRegNumber) diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala index 266babe..f5eccc8 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/services/GamblingServiceSpec.scala @@ -103,7 +103,7 @@ final class GamblingServiceSpec extends SpecBase { solePropMidName = Some("B"), solePropLastName = Some("Bar"), businessName = Some("FooBar Co."), - businessType = Some(1), + businessType = Some(BusinessType.Partnership), tradingName = Some("Foobar"), systemDate = Some(LocalDate.of(1991, 1, 1)) ) @@ -129,7 +129,7 @@ final class GamblingServiceSpec extends SpecBase { solePropMidName = Some("C"), solePropLastName = Some("Doe"), businessName = Some("John Doe Co."), - businessType = Some(1), + businessType = Some(BusinessType.Partnership), tradingName = Some("DoeDoe"), systemDate = Some(LocalDate.of(1991, 1, 1)) ) @@ -162,71 +162,6 @@ final class GamblingServiceSpec extends SpecBase { } } - "GamblingService#BusinessDetails" - { - - "return Right(summary) when repository succeeds" in { - - val summary = BusinessDetails( - mgdRegNumber = normalisedMgdRegNumber, - businessType = Some(1), - currentlyRegistered = Some(2), - groupReg = Some("foo"), - dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), - businessPartnerNumber = Some("bar"), - systemDate = Some(LocalDate.of(2024, 4, 21)) - ) - when(repository.getBusinessDetails(eqTo(validMgdRegNumber))) - .thenReturn(Future.successful(summary)) - - val result = service.getBusinessDetails(validMgdRegNumber).futureValue - - result mustBe Right(summary) - verify(repository).getBusinessDetails(eqTo(validMgdRegNumber)) - verifyNoMoreInteractions(repository) - } - - "normalise input (trim + uppercase) before calling repository" in { - - val rawInput = " xwm12345678901 " - - val summary = BusinessDetails( - mgdRegNumber = normalisedMgdRegNumber, - businessType = Some(1), - currentlyRegistered = Some(2), - groupReg = Some("foo"), - dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), - businessPartnerNumber = Some("bar"), - systemDate = Some(LocalDate.of(2024, 4, 21)) - ) - - when(repository.getBusinessDetails(eqTo(normalisedMgdRegNumber))) - .thenReturn(Future.successful(summary)) - - val result = service.getBusinessDetails(rawInput).futureValue - result mustBe Right(summary) - verify(repository).getBusinessDetails(eqTo(normalisedMgdRegNumber)) - verifyNoMoreInteractions(repository) - } - - "return InvalidMgdRegNumber and not call repository when input is invalid" in { - - val invalidInput = "xwm12345678" - val result = service.getBusinessDetails(invalidInput).futureValue - result mustBe Left(InvalidMgdRegNumber) - verifyNoMoreInteractions(repository) - } - - "return UnexpectedError when repository throws exception" in { - - when(repository.getBusinessDetails(eqTo(validMgdRegNumber))) - .thenReturn(Future.failed(new RuntimeException("DB failure when calling repo"))) - val result = service.getBusinessDetails(validMgdRegNumber).futureValue - result mustBe Left(UnexpectedError) - verify(repository).getBusinessDetails(eqTo(validMgdRegNumber)) - verifyNoMoreInteractions(repository) - } - } - "GamblingService#getMgdCertificate" - { "return Right(certificate) when repository succeeds" in { From 3733332cb9766ab9c885c05a785770db3677b896 Mon Sep 17 00:00:00 2001 From: AnotherMattWright <270914550+AnotherMattWright@users.noreply.github.com> Date: Wed, 6 May 2026 15:26:23 +0100 Subject: [PATCH 13/16] merge from main with integrations --- .../gambling/GamblingDataCacheRepositoryISpec.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala index 477f76c..3086595 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala @@ -165,8 +165,8 @@ class GamblingDataCacheRepositoryISpec extends AnyWordSpec with Matchers with Sc val result = repository.getReturnSummary("XYZ00000000000").futureValue result mustBe ReturnSummary( - mgdRegNumber = "XYZ00000000000", - returnsDue = 0, + mgdRegNumber = "XYZ00000000000", + returnsDue = 0, returnsOverdue = 0 ) } From 2677a763ad6792c6b91f633159a9b33a5d0dbdb1 Mon Sep 17 00:00:00 2001 From: AnotherMattWright <270914550+AnotherMattWright@users.noreply.github.com> Date: Wed, 6 May 2026 16:29:26 +0100 Subject: [PATCH 14/16] all tests pass at 80% coverage --- .../GamblingDataCacheRepositoryISpec.scala | 16 +- .../gambling/GamblingStubData.scala | 2 +- .../gambling/models/GamblingStubData.scala | 152 ++++++++++++++++-- 3 files changed, 144 insertions(+), 26 deletions(-) diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala index 3086595..d284307 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingDataCacheRepositoryISpec.scala @@ -119,7 +119,7 @@ class GamblingDataCacheRepositoryISpec extends AnyWordSpec with Matchers with Sc val result = repository.getBusinessDetails("XYZ00000000001").futureValue result.businessType mustBe None - result.businessPartnerNumber mustBe Some("BPN123456") + result.businessPartnerNumber mustBe Some("bar") } "return consistent results across multiple calls" in { @@ -377,9 +377,9 @@ class GamblingDataCacheRepositoryISpec extends AnyWordSpec with Matchers with Sc result mustBe BusinessDetails( mgdRegNumber = "XYZ00000000000", - businessType = Some(BusinessType.LimitedLiabilityPartnership), - currentlyRegistered = 1, - groupReg = true, + businessType = Some(BusinessType.CorporateBody), + currentlyRegistered = 2, + groupReg = false, dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = Some("bar"), systemDate = LocalDate.of(2024, 4, 21) ) } @@ -387,9 +387,9 @@ class GamblingDataCacheRepositoryISpec extends AnyWordSpec with Matchers with Sc "return business type correctly" in { val result = repository.getBusinessDetails("XYZ00000000001").futureValue - result.businessType mustBe Some(BusinessType.LimitedLiabilityPartnership) + result.businessType mustBe None result.currentlyRegistered mustBe 1 - result.groupReg mustBe true + result.groupReg mustBe false result.dateOfRegistration mustBe Some(LocalDate.of(2024, 4, 21)) result.businessPartnerNumber mustBe Some("bar") result.systemDate mustBe LocalDate.of(2024, 4, 21) @@ -409,7 +409,7 @@ class GamblingDataCacheRepositoryISpec extends AnyWordSpec with Matchers with Sc "return both date values correctly" in { val result = repository.getBusinessDetails("XYZ00000000012").futureValue - result mustBe BusinessDetails("XYZ00000000012", Some(BusinessType.UnincorporatedBody), 2, true, Some(LocalDate.of(2023, 4, 21)), Some("barfoo"), LocalDate.of(2023, 4, 21)) + result mustBe BusinessDetails("XYZ00000000012", Some(BusinessType.SoleProprietor), 2, true, Some(LocalDate.of(2023, 4, 21)), Some("barfoo"), LocalDate.of(2023, 4, 21)) } "handle multiple values" in { @@ -444,7 +444,7 @@ class GamblingDataCacheRepositoryISpec extends AnyWordSpec with Matchers with Sc "handle whitespace mgdRegNumber" in { val result = repository.getBusinessDetails(" ").futureValue - result mustBe BusinessDetails(" ", Some(BusinessType.SoleProprietor), 0, true, Some(LocalDate.of(2026, 4, 22)), Some("unknown"), LocalDate.of(2026, 4, 22)) + result mustBe BusinessDetails(" ", Some(BusinessType.Partnership), 0, false, Some(LocalDate.of(2026, 4, 22)), Some("unknown"), LocalDate.of(2026, 4, 22)) } } } diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala index f9f1fba..94f6f20 100644 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala +++ b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala @@ -124,7 +124,7 @@ object GamblingStubData { case "XYZ00000000001" => BusinessDetails( mgdRegNumber = mgdRegNumber, - businessType = Some(BusinessType.LimitedLiabilityPartnership), + businessType = None, currentlyRegistered = 1, groupReg = false, dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = Some("bar"), systemDate = LocalDate.of(2024, 4, 21) diff --git a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingStubData.scala b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingStubData.scala index 1a60e35..7122d7e 100644 --- a/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingStubData.scala +++ b/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/models/GamblingStubData.scala @@ -83,47 +83,165 @@ object GamblingStubData { // ------------------------- def getBusinessDetails(mgdRegNumber: String): BusinessDetails = mgdRegNumber match { - case "ERR00000000000" => throw new RuntimeException("Simulated downstream failure") case "EMPTY000000000" => throw new RuntimeException("No business details found") - case _ => + case "NULL000000000" => + throw new RuntimeException("Null cursor") + + case "XYZ00000000000" => + BusinessDetails( + mgdRegNumber = mgdRegNumber, + businessType = Some(BusinessType.CorporateBody), + currentlyRegistered = 2, + groupReg = false, + dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), + businessPartnerNumber = Some("bar"), + systemDate = LocalDate.of(2024, 4, 21) + ) + case "XYZ00000000001" => BusinessDetails( mgdRegNumber = mgdRegNumber, businessType = None, currentlyRegistered = 1, groupReg = false, - dateOfRegistration = Some(LocalDate.now().minusYears(1)), - businessPartnerNumber = Some("BPN123456"), - systemDate = LocalDate.now() + dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), + businessPartnerNumber = Some("bar"), + systemDate = LocalDate.of(2024, 4, 21) + ) + case "XYZ00000000010" => + BusinessDetails( + mgdRegNumber = mgdRegNumber, + businessType = Some(BusinessType.UnincorporatedBody), + currentlyRegistered = 2, + groupReg = true, + dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), + businessPartnerNumber = Some("bar"), + systemDate = LocalDate.of(2024, 4, 21) + ) + case "XYZ00000000012" => + BusinessDetails( + mgdRegNumber = mgdRegNumber, + businessType = Some(BusinessType.SoleProprietor), + currentlyRegistered = 2, + groupReg = true, + dateOfRegistration = Some(LocalDate.of(2023, 4, 21)), + businessPartnerNumber = Some("barfoo"), + systemDate = LocalDate.of(2023, 4, 21) + ) + case "XYZ00000000021" => + BusinessDetails( + mgdRegNumber = mgdRegNumber, + businessType = Some(BusinessType.Partnership), + currentlyRegistered = 2, + groupReg = false, + dateOfRegistration = Some(LocalDate.of(2024, 1, 21)), + businessPartnerNumber = Some("barbar"), + systemDate = LocalDate.of(2024, 1, 21) + ) + case _ => + BusinessDetails( + mgdRegNumber = mgdRegNumber, + businessType = Some(BusinessType.Partnership), + currentlyRegistered = 0, + groupReg = false, + dateOfRegistration = Some(LocalDate.of(2026, 4, 22)), + businessPartnerNumber = Some("unknown"), + systemDate = LocalDate.of(2026, 4, 22) ) } - def getBusinessName(mgdRegNumber: String): BusinessName = + def getBusinessName(mgdRegNumber: String): BusinessName = { + val dateTimeOne: Some[LocalDate] = Some(LocalDate.of(2026, 4, 20)) + val dateTimeTwo: Some[LocalDate] = Some(LocalDate.of(2026, 1, 1)) + val dateTimeThree: Some[LocalDate] = Some(LocalDate.of(1991, 1, 1)) mgdRegNumber match { - case "ERR00000000000" => throw new RuntimeException("Simulated downstream failure") case "EMPTY000000000" => - throw new RuntimeException("No business details found") + throw new RuntimeException("No business name found") + case "NULL000000000" => + throw new RuntimeException("Null cursor") + + case "XYZ00000000000" => + BusinessName( + mgdRegNumber, + solePropTitle = Some("Mr"), + solePropFirstName = Some("John"), + solePropMidName = Some("C"), + solePropLastName = Some("Doe"), + businessName = Some("John Doe Co."), + businessType = Some(BusinessType.SoleProprietor), + tradingName = Some("DoeDoe"), + systemDate = dateTimeOne + ) + case "XYZ00000000001" => + BusinessName( + mgdRegNumber, + solePropTitle = Some("Mrs"), + solePropFirstName = Some("Jane"), + solePropMidName = Some("C"), + solePropLastName = Some("Doe"), + businessName = Some("Jane Doe Co."), + businessType = Some(BusinessType.SoleProprietor), + tradingName = Some("DoeDoe"), + systemDate = dateTimeTwo + ) + case "XYZ00000000010" => + BusinessName( + mgdRegNumber, + solePropTitle = Some("Mrs"), + solePropFirstName = Some("Marge"), + solePropMidName = Some("Jacqueline"), + solePropLastName = Some("Simpson"), + businessName = Some("Pretzel Wagon"), + businessType = Some(BusinessType.SoleProprietor), + tradingName = Some("Marge Simpson"), + systemDate = dateTimeOne + ) + case "XYZ00000000012" => + BusinessName( + mgdRegNumber, + solePropTitle = Some("Miss"), + solePropFirstName = Some("Catherine"), + solePropMidName = None, + solePropLastName = Some("Havisham"), + businessName = Some("Failed Expectations"), + businessType = Some(BusinessType.SoleProprietor), + tradingName = Some("Miss Havisham"), + systemDate = dateTimeThree + ) + case "XYZ00000000021" => + BusinessName( + mgdRegNumber, + solePropTitle = Some("Mr"), + solePropFirstName = Some("Eugine"), + solePropMidName = Some("H"), + solePropLastName = Some("Krabs"), + businessName = Some("Krusty Krab"), + businessType = Some(BusinessType.SoleProprietor), + tradingName = Some("Mr Krabs"), + systemDate = dateTimeThree + ) case _ => BusinessName( - mgdRegNumber = mgdRegNumber, - solePropTitle = Some("abc"), - solePropFirstName = Some("abc"), - solePropMidName = Some("abc"), - solePropLastName = Some("abc"), - businessName = Some("abc"), - businessType = None, - tradingName = Some("abc"), - systemDate = Some(LocalDate.now()) + mgdRegNumber, + solePropTitle = Some("Mr"), + solePropFirstName = Some("Foo"), + solePropMidName = Some("B"), + solePropLastName = Some("Bar"), + businessName = Some("FooBar Co."), + businessType = Some(BusinessType.SoleProprietor), + tradingName = Some("Foobar"), + systemDate = dateTimeOne ) } + } // ------------------------- // MgdCertificate From 7b6626fb5bb7e494b56980a1b0d62ae518347876 Mon Sep 17 00:00:00 2001 From: AnotherMattWright <270914550+AnotherMattWright@users.noreply.github.com> Date: Wed, 6 May 2026 16:33:33 +0100 Subject: [PATCH 15/16] remove prev stub --- .../gambling/GamblingStubData.scala | 167 ------------------ 1 file changed, 167 deletions(-) delete mode 100644 it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala diff --git a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala b/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala deleted file mode 100644 index 94f6f20..0000000 --- a/it/test/uk/gov/hmrc/rdsdatacacheproxy/gambling/GamblingStubData.scala +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2026 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.rdsdatacacheproxy.gambling - -import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.* -import java.time.LocalDate - -object GamblingStubData { - def getReturnSummary(mgdRegNumber: String): ReturnSummary = { - mgdRegNumber match { - case "XYZ00000000000" => - ReturnSummary(mgdRegNumber, returnsDue = 0, returnsOverdue = 0) - case "XYZ00000000001" => - ReturnSummary(mgdRegNumber, returnsDue = 0, returnsOverdue = 1) - case "XYZ00000000010" => - ReturnSummary(mgdRegNumber, returnsDue = 1, returnsOverdue = 0) - case "XYZ00000000012" => - ReturnSummary(mgdRegNumber, returnsDue = 1, returnsOverdue = 2) - case "XYZ00000000021" => - ReturnSummary(mgdRegNumber, returnsDue = 2, returnsOverdue = 1) - case "ERR00000000000" => - throw new RuntimeException("Simulated downstream failure") - case _ => - ReturnSummary(mgdRegNumber, returnsDue = 3, returnsOverdue = 4) - } - } - def getBusinessName(mgdRegNumber: String): BusinessName = { - val dateTimeOne: Some[LocalDate] = Some(LocalDate.of(2026, 4, 20)) - val dateTimeTwo: Some[LocalDate] = Some(LocalDate.of(2026, 1, 1)) - val dateTimeThree: Some[LocalDate] = Some(LocalDate.of(1991, 1, 1)) - mgdRegNumber match { - case "XYZ00000000000" => - BusinessName(mgdRegNumber, - solePropTitle = Some("Mr"), - solePropFirstName = Some("John"), - solePropMidName = Some("C"), - solePropLastName = Some("Doe"), - businessName = Some("John Doe Co."), - businessType = Some(BusinessType.SoleProprietor), - tradingName = Some("DoeDoe"), - systemDate = dateTimeOne) - case "XYZ00000000001" => - BusinessName(mgdRegNumber, - solePropTitle = Some("Mrs"), - solePropFirstName = Some("Jane"), - solePropMidName = Some("C"), - solePropLastName = Some("Doe"), - businessName = Some("Jane Doe Co."), - businessType = Some(BusinessType.SoleProprietor), - tradingName = Some("DoeDoe"), - systemDate = dateTimeTwo) - case "XYZ00000000010" => - BusinessName(mgdRegNumber, - solePropTitle = Some("Mrs"), - solePropFirstName = Some("Marge"), - solePropMidName = Some("Jacqueline"), - solePropLastName = Some("Simpson"), - businessName = Some("Pretzel Wagon"), - businessType = Some(BusinessType.SoleProprietor), - tradingName = Some("Marge Simpson"), - systemDate = dateTimeOne) - case "XYZ00000000012" => - BusinessName(mgdRegNumber, - solePropTitle = Some("Miss"), - solePropFirstName = Some("Catherine"), - solePropMidName = None, - solePropLastName = Some("Havisham"), - businessName = Some("Failed Expectations"), - businessType = Some(BusinessType.SoleProprietor), - tradingName = Some("Miss Havisham"), - systemDate = dateTimeThree) - case "XYZ00000000021" => - BusinessName(mgdRegNumber, - solePropTitle = Some("Mr"), - solePropFirstName = Some("Eugine"), - solePropMidName = Some("H"), - solePropLastName = Some("Krabs"), - businessName = Some("Krusty Krab"), - businessType = Some(BusinessType.SoleProprietor), - tradingName = Some("Mr Krabs"), - systemDate = dateTimeThree) - case "ERR00000000000" => - throw new RuntimeException("Simulated downstream failure") - case _ => - BusinessName(mgdRegNumber, - solePropTitle= Some("Mr"), - solePropFirstName= Some("Foo"), - solePropMidName= Some("B"), - solePropLastName= Some("Bar"), - businessName= Some("FooBar Co."), - businessType = Some(BusinessType.SoleProprietor), - tradingName= Some("Foobar"), - systemDate= dateTimeOne - ) - } - } - - - - def getBusinessDetails(mgdRegNumber: String): BusinessDetails = - mgdRegNumber match { - case "XYZ00000000000" => - BusinessDetails( - mgdRegNumber = mgdRegNumber, - businessType = Some(BusinessType.CorporateBody), - currentlyRegistered = 2, - groupReg = false, - dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = Some("bar"), systemDate = LocalDate.of(2024, 4, 21) - ) - case "XYZ00000000001" => - BusinessDetails( - mgdRegNumber = mgdRegNumber, - businessType = None, - currentlyRegistered = 1, - groupReg = false, - dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = Some("bar"), systemDate = LocalDate.of(2024, 4, 21) - ) - case "XYZ00000000010" => - BusinessDetails( - mgdRegNumber = mgdRegNumber, - businessType = Some(BusinessType.UnincorporatedBody), - currentlyRegistered = 2, - groupReg = true, - dateOfRegistration = Some(LocalDate.of(2024, 4, 21)), businessPartnerNumber = Some("bar"), systemDate = LocalDate.of(2024, 4, 21) - ) - case "XYZ00000000012" => - BusinessDetails( - mgdRegNumber = mgdRegNumber, - businessType = Some(BusinessType.SoleProprietor), - currentlyRegistered = 2, - groupReg = true, - dateOfRegistration = Some(LocalDate.of(2023, 4, 21)), businessPartnerNumber = Some("barfoo"), systemDate = LocalDate.of(2023, 4, 21) - ) - case "XYZ00000000021" => - BusinessDetails( - mgdRegNumber = mgdRegNumber, - businessType = Some(BusinessType.Partnership), - currentlyRegistered = 2, - groupReg = false, - dateOfRegistration = Some(LocalDate.of(2024, 1, 21)), businessPartnerNumber = Some("barbar"), systemDate = LocalDate.of(2024, 1, 21) - ) - case "ERR00000000000" => - throw new RuntimeException("Simulated downstream failure") - case _ => - BusinessDetails( - mgdRegNumber = mgdRegNumber, - businessType = Some(BusinessType.Partnership), - currentlyRegistered = 0, - groupReg = false, - dateOfRegistration = Some(LocalDate.of(2026, 4, 22)), businessPartnerNumber = Some("unknown"), systemDate = LocalDate.of(2026, 4, 22) - ) - } -} From 23684d8df2caab1cdcb82a2c81aec7fbca827355 Mon Sep 17 00:00:00 2001 From: AnotherMattWright <270914550+AnotherMattWright@users.noreply.github.com> Date: Thu, 7 May 2026 09:51:58 +0100 Subject: [PATCH 16/16] updated login details, updated endpoints --- conf/app.routes | 5 +---- conf/application.conf | 4 ++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/conf/app.routes b/conf/app.routes index 2c5317a..ecb5eca 100644 --- a/conf/app.routes +++ b/conf/app.routes @@ -36,13 +36,10 @@ GET /charities/organisations/:charityRef uk.gov.hmrc.rdsdatacac #MGD routes GET /gambling/return-summary/:mgdRegNumber uk.gov.hmrc.rdsdatacacheproxy.gambling.controllers.GamblingController.getReturnSummary(mgdRegNumber: String) -GET /gambling/business-details/:mgdRegNumber uk.gov.hmrc.rdsdatacacheproxy.gambling.controllers.GamblingController.getBusinessDetails(mgdRegNumber: String) -GET /gambling/business-name/:mgdRegNumber uk.gov.hmrc.rdsdatacacheproxy.gambling.controllers.GamblingController.getBusinessName(mgdRegNumber: String) -GET /gambling/get-mgd-certificate/:mgdRegNumber uk.gov.hmrc.rdsdatacacheproxy.gambling.controllers.GamblingController.getMgdCertificate(mgdRegNumber: String) - GET /gambling/mgd-certificate/:mgdRegNumber uk.gov.hmrc.rdsdatacacheproxy.gambling.controllers.GamblingController.getMgdCertificate(mgdRegNumber: String) GET /gambling/operator-details/:mgdRegNumber uk.gov.hmrc.rdsdatacacheproxy.gambling.controllers.GamblingController.getOperatorDetails(mgdRegNumber: String) GET /gambling/business-details/:mgdRegNumber uk.gov.hmrc.rdsdatacacheproxy.gambling.controllers.GamblingController.getBusinessDetails(mgdRegNumber: String) +GET /gambling/business-name/:mgdRegNumber uk.gov.hmrc.rdsdatacacheproxy.gambling.controllers.GamblingController.getBusinessName(mgdRegNumber: String) #Gambling Returns routes GET /gambling/returns-submitted/:regime/:regNumber uk.gov.hmrc.rdsdatacacheproxy.gambling.controllers.GamblingReturnsController.getReturnsSubmitted(regime: String, regNumber: String, pageNo: Int ?=1, pageSize: Int ?=10) diff --git a/conf/application.conf b/conf/application.conf index bc947ed..c633984 100644 --- a/conf/application.conf +++ b/conf/application.conf @@ -120,8 +120,8 @@ oracle.gambling { db.host = "localhost" db.port = "1521" dbName = "xe" - username = "GTR_DATA" - password = "GTR_DATA" + username = "mgd_data" + password = "mgd_data" connectionTimeout = 50s validationTimeout = 3s idleTimeout = 10m