Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d6e41d5
DTR-4210 BusinessName first attempt at creating backend call for Busi…
AnotherMattWright Apr 20, 2026
1ed2e46
solved date addition to object
AnotherMattWright Apr 20, 2026
ccef18e
added test case in gambling controller spec for business name
AnotherMattWright Apr 20, 2026
ed94059
test cases completed up to 77.69% coverage
AnotherMattWright Apr 22, 2026
76fc1a0
test coverage complete for 79.78%
AnotherMattWright Apr 23, 2026
44e1e0c
DTR-4218 pulled into DTR-4210
AnotherMattWright Apr 24, 2026
02a73d4
fixed business name model and classes to have correct field types
AnotherMattWright Apr 27, 2026
fa232ca
Merge branch 'main' into DTR-4210-BusinessName
AnotherMattWright Apr 28, 2026
cd8432a
solved faulty merge & conflicts, temp removed test cases for Bus Name…
AnotherMattWright Apr 28, 2026
7687b3d
refactor of models to type fields to optional
AnotherMattWright May 1, 2026
50f16a8
GCSpec reformat
AnotherMattWright May 1, 2026
49b33bf
add empty line
AnotherMattWright May 5, 2026
42ed9f2
Merge branch 'main' into DTR-4210-4218
AnotherMattWright May 6, 2026
9f4f222
merged and refactored across repo for new types
AnotherMattWright May 6, 2026
f535860
Merge branch 'main' into DTR-4210-4218
AnotherMattWright May 6, 2026
3733332
merge from main with integrations
AnotherMattWright May 6, 2026
2677a76
all tests pass at 80% coverage
AnotherMattWright May 6, 2026
7b6626f
remove prev stub
AnotherMattWright May 6, 2026
3c94bd5
Merge branch 'main' into DTR-4210-4218
AnotherMattWright May 6, 2026
23684d8
updated login details, updated endpoints
AnotherMattWright May 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,39 @@ 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][getBusinessName] code=${error.code} mgdRegNumber=$mgdRegNumber"
error match {
case InvalidMgdRegNumber =>
logger.warn(logMessage)
BadRequest(errorResponse(error))
case UnexpectedError =>
logger.error(logMessage)
InternalServerError(errorResponse(error))
}
}
}

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))
}
}
}

def getMgdCertificate(mgdRegNumber: String): Action[AnyContent] = authorise.async { implicit request =>

Expand All @@ -71,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 =>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package uk.gov.hmrc.rdsdatacacheproxy.gambling.models

import play.api.libs.json.{Json, OFormat}

import java.time.LocalDate

final case class BusinessDetails(
Expand Down
Original file line number Diff line number Diff line change
@@ -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

final case class BusinessName(
mgdRegNumber: String,
solePropTitle: Option[String],
solePropFirstName: Option[String],
solePropMidName: Option[String],
solePropLastName: Option[String],
businessName: Option[String],
businessType: Option[BusinessType],
tradingName: Option[String],
systemDate: Option[LocalDate]
)

object BusinessName {
implicit val format: OFormat[BusinessName] = Json.format[BusinessName]
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ import scala.concurrent.{ExecutionContext, Future, blocking}

trait GamblingDataSource {
def getReturnSummary(mgdRegNumber: String): Future[ReturnSummary]
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
Expand Down Expand Up @@ -349,6 +350,66 @@ class GamblingDataCacheRepository @Inject() (
}
})(ec)
}
override def getBusinessName(mgdRegNumber: String): Future[BusinessName] = {

logger.info(s"[GamblingDataCacheRepository][getBusinessName] 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()) {

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")),
solePropFirstName = Option(rs.getString("SOLE_PROP_FIRST_NAME")),
solePropMidName = Option(rs.getString("SOLE_PROP_MIDDLE_NAME")),
solePropLastName = Option(rs.getString("SOLE_PROP_LAST_NAME")),
businessName = Option(rs.getString("BUSINESS_NAME")),
businessType = businessType,
tradingName = Option(rs.getString("TRADING_NAME")),
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)
}

override def getReturnSummary(mgdRegNumber: String): Future[ReturnSummary] = {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,25 @@ class GamblingService @Inject() (
}
}

def getBusinessName(rawMgdRegNumber: String)(implicit hc: HeaderCarrier): Future[Either[GamblingError, BusinessName]] = {

val mgdRegNumber = rawMgdRegNumber.trim.toUpperCase

if (!regNumberPattern.matcher(mgdRegNumber).matches()) {
logger.warn(s"[GamblingService][getBusinessName] 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][getBusinessName] Unexpected error mgdRegNumber=$mgdRegNumber", ex)
Left(UnexpectedError)
}
}
}

def getMgdCertificate(rawMgdRegNumber: String)(implicit hc: HeaderCarrier): Future[Either[GamblingError, MgdCertificate]] = {

val mgdRegNumber = rawMgdRegNumber.trim.toUpperCase
Expand Down
1 change: 1 addition & 0 deletions conf/app.routes
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ GET /gambling/return-summary/:mgdRegNumber uk.gov.hmrc.rdsdataca
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)
4 changes: 2 additions & 2 deletions conf/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,15 @@ import play.api.Application
import play.api.http.Status.*
import play.api.inject.bind
import play.api.inject.guice.GuiceApplicationBuilder
import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.{BusinessDetails, GamblingStubData, MgdCertificate, OperatorDetails}
import uk.gov.hmrc.rdsdatacacheproxy.gambling.models.{BusinessDetails, GamblingStubData, OperatorDetails, MgdCertificate}
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.ExecutionContext.Implicits.global
import java.time.LocalDate
import scala.concurrent.Future

class GamblingControllerISpec extends AnyWordSpec with Matchers with ScalaFutures with IntegrationPatience with ApplicationWithWiremock {
Expand Down Expand Up @@ -77,6 +81,11 @@ class GamblingControllerISpec extends AnyWordSpec with Matchers with ScalaFuture
GamblingStubData.getReturnSummary(mgdRegNumber)
}

override def getBusinessName(mgdRegNumber: String) =
Future {
GamblingStubData.getBusinessName(mgdRegNumber)
}

override def getMgdCertificate(mgdRegNumber: String): Future[MgdCertificate] =
Future.successful(
MgdCertificate(
Expand Down Expand Up @@ -122,6 +131,13 @@ class GamblingControllerISpec extends AnyWordSpec with Matchers with ScalaFuture

private val endpoint = "/gambling/return-summary"

implicit val localDateReads: Reads[LocalDate] =
Reads.localDateReads("yyyy-MM-dd")

implicit val optLocalDateReads: Reads[Option[LocalDate]] =
Reads.optionWithNull[LocalDate]


"GET /gambling/return-summary (stubbed repo, no DB)" should {

"return 200 with correct summary (0,0)" in {
Expand Down
Loading