Skip to content

Commit

Permalink
ADR-1498 show quarterly spirits declaration on check and submit (#212)
Browse files Browse the repository at this point in the history
* ADR-1227 Fix test data

* ADR-1498 show quarterly spirits declaration on check and submit

* ADR-1498 Fix test naming

* Fix format
  • Loading branch information
davidfes authored Nov 19, 2024
1 parent ce31080 commit e086b98
Show file tree
Hide file tree
Showing 7 changed files with 359 additions and 132 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class DutyDueForThisReturnController @Inject() (

def onPageLoad(): Action[AnyContent] = (identify andThen getData andThen requireData).async { implicit request =>
dutyDueForThisReturnHelper
.getDutyDueViewModel(request.userAnswers)
.getDutyDueViewModel(request.userAnswers, request.returnPeriod)
.foldF(
error => {
logger.warn(error)
Expand Down
34 changes: 18 additions & 16 deletions app/services/checkAndSubmit/AdrReturnSubmissionService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,13 @@ class AdrReturnSubmissionServiceImpl @Inject() (
dutyDeclared <- getDutyDeclared(userAnswers)
adjustments <- getAdjustments(userAnswers)
dutySuspended <- getDutySuspended(userAnswers)
spirits <-
if (
userAnswers.regimes.hasSpirits() && returnPeriod.hasQuarterlySpirits && appConfig.spiritsAndIngredientsEnabled
) getSpirits(userAnswers)
else EitherT.rightT[Future, String](None)
maybeSpirits <- getSpirits(userAnswers, returnPeriod)
totals <- getTotals(userAnswers)
} yield AdrReturnSubmission(
dutyDeclared = dutyDeclared,
adjustments = adjustments,
dutySuspended = dutySuspended,
spirits = spirits,
spirits = maybeSpirits,
totals = totals
)

Expand Down Expand Up @@ -330,16 +326,22 @@ class AdrReturnSubmissionServiceImpl @Inject() (
otherFermentedDutySuspended
).flatten

def getSpirits(userAnswers: UserAnswers): EitherT[Future, String, Option[AdrSpirits]] =
for {
declared <- getValue(userAnswers, DeclareQuarterlySpiritsPage)
spiritsProduced <- if (declared) getSpiritProduced(userAnswers) else EitherT.rightT[Future, String](None)
} yield Some(
AdrSpirits(
declared,
spiritsProduced
def getSpirits(userAnswers: UserAnswers, returnPeriod: ReturnPeriod): EitherT[Future, String, Option[AdrSpirits]] =
if (
userAnswers.regimes.hasSpirits() && returnPeriod.hasQuarterlySpirits && appConfig.spiritsAndIngredientsEnabled
) {
for {
declared <- getValue(userAnswers, DeclareQuarterlySpiritsPage)
spiritsProduced <- if (declared) getSpiritProduced(userAnswers) else EitherT.rightT[Future, String](None)
} yield Some(
AdrSpirits(
declared,
spiritsProduced
)
)
)
} else {
EitherT.rightT[Future, String](None)
}

private def getSpiritProduced(userAnswers: UserAnswers): EitherT[Future, String, Option[AdrSpiritsProduced]] =
for {
Expand Down Expand Up @@ -506,7 +508,7 @@ trait AdrReturnSubmissionService {

def getDutyDeclared(userAnswers: UserAnswers): EitherT[Future, String, AdrDutyDeclared]
def getAdjustments(userAnswers: UserAnswers): EitherT[Future, String, AdrAdjustments]
def getSpirits(userAnswers: UserAnswers): EitherT[Future, String, Option[AdrSpirits]]
def getDutySuspended(userAnswers: UserAnswers): EitherT[Future, String, AdrDutySuspended]
def getSpirits(userAnswers: UserAnswers, returnPeriod: ReturnPeriod): EitherT[Future, String, Option[AdrSpirits]]
def getTotals(userAnswers: UserAnswers)(implicit hc: HeaderCarrier): EitherT[Future, String, AdrTotals]
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ import cats.data.EitherT
import config.Constants.Css
import connectors.AlcoholDutyCalculatorConnector
import models.AlcoholRegime.{Beer, Cider, OtherFermentedProduct, Spirits, Wine}
import models.checkAndSubmit.AdrDutySuspended
import models.checkAndSubmit.{AdrDutySuspended, AdrSpirits}
import models.declareDuty.AlcoholDuty
import models.{AlcoholRegime, NormalMode, UserAnswers}
import models.{AlcoholRegime, NormalMode, ReturnPeriod, UserAnswers}
import pages.adjustment.{AdjustmentTotalPage, DeclareAdjustmentQuestionPage}
import pages.declareDuty.{AlcoholDutyPage, DeclareAlcoholDutyQuestionPage}
import play.api.Logging
Expand Down Expand Up @@ -51,15 +51,17 @@ class DutyDueForThisReturnHelper @Inject() (
private val dutyDueOrder = Seq(Beer, Cider, Wine, Spirits, OtherFermentedProduct)

def getDutyDueViewModel(
userAnswers: UserAnswers
userAnswers: UserAnswers,
returnPeriod: ReturnPeriod
)(implicit hc: HeaderCarrier, messages: Messages): EitherT[Future, String, DutyDueForThisReturnViewModel] =
for {
dutiesByRegime <- getDutiesByAlcoholRegime(userAnswers)
totalAdjustment <- getTotalAdjustment(userAnswers)
total <- calculateTotal(dutiesByRegime, totalAdjustment)
dutiesBreakdownViewModel <- createTableViewModel(dutiesByRegime, totalAdjustment)
dutySuspended <- adrReturnSubmissionService.getDutySuspended(userAnswers)
youveAlsoAnsweredViewModel <- createYouveAlsoAnsweredTableViewModel(dutySuspended)
maybeSpirits <- adrReturnSubmissionService.getSpirits(userAnswers, returnPeriod)
youveAlsoAnsweredViewModel <- createYouveAlsoAnsweredTableViewModel(dutySuspended, maybeSpirits)
} yield DutyDueForThisReturnViewModel(
dutiesBreakdownViewModel,
youveAlsoAnsweredViewModel,
Expand Down Expand Up @@ -106,14 +108,15 @@ class DutyDueForThisReturnHelper @Inject() (
)
}

private def createYouveAlsoAnsweredTableViewModel(dutySuspended: AdrDutySuspended)(implicit
messages: Messages
private def createYouveAlsoAnsweredTableViewModel(dutySuspended: AdrDutySuspended, maybeSpirits: Option[AdrSpirits])(
implicit messages: Messages
): EitherT[Future, String, TableViewModel] = {
val returnDutiesRow = createDutySuspendedRow(dutySuspended.declared)
val maybeSpiritsRow = maybeSpirits.map(spirits => createSpiritsRow(spirits.spiritsDeclared))
EitherT.rightT[Future, String](
TableViewModel(
head = Seq.empty,
rows = returnDutiesRow
rows = maybeSpiritsRow.fold(returnDutiesRow)(returnDutiesRow ++ _)
)
)
}
Expand Down Expand Up @@ -177,7 +180,7 @@ class DutyDueForThisReturnHelper @Inject() (
),
actions = Seq(
TableRowActionViewModel(
label = "Change",
label = messages("site.change"),
href = controllers.dutySuspended.routes.CheckYourAnswersDutySuspendedDeliveriesController
.onPageLoad()
)
Expand All @@ -199,7 +202,7 @@ class DutyDueForThisReturnHelper @Inject() (
),
actions = Seq(
TableRowActionViewModel(
label = "Change",
label = messages("site.change"),
href =
controllers.dutySuspended.routes.DeclareDutySuspendedDeliveriesQuestionController.onPageLoad(NormalMode)
)
Expand All @@ -208,6 +211,54 @@ class DutyDueForThisReturnHelper @Inject() (
)
}

private def createSpiritsRow(
hasSpirits: Boolean
)(implicit messages: Messages): Seq[TableRowViewModel] =
if (hasSpirits) {
Seq(
TableRowViewModel(
cells = Seq(
TableRow(
content = Text(messages("dutyDueForThisReturn.spirits.production")),
classes = s"${Css.boldFontCssClass} ${Css.summaryListKeyCssClass}"
),
TableRow(
Text(messages("dutyDueForThisReturn.spirits.declared")),
classes = Css.summaryListValueCssClass
)
),
actions = Seq(
TableRowActionViewModel(
label = messages("site.change"),
href = controllers.spiritsQuestions.routes.CheckYourAnswersController
.onPageLoad()
)
)
)
)
} else {
Seq(
TableRowViewModel(
cells = Seq(
TableRow(
content = Text(messages("dutyDueForThisReturn.spirits.production")),
classes = s"${Css.boldFontCssClass} ${Css.summaryListKeyCssClass}"
),
TableRow(
Text(messages("dutyDueForThisReturn.spirits.nothingToDeclare")),
classes = Css.summaryListValueCssClass
)
),
actions = Seq(
TableRowActionViewModel(
label = messages("site.change"),
href = controllers.spiritsQuestions.routes.DeclareQuarterlySpiritsController.onPageLoad(NormalMode)
)
)
)
)
}

private def createAdjustmentRow(totalAdjustment: BigDecimal)(implicit messages: Messages): TableRowViewModel =
if (totalAdjustment == 0) {
TableRowViewModel(
Expand Down
3 changes: 3 additions & 0 deletions conf/messages.en
Original file line number Diff line number Diff line change
Expand Up @@ -1074,6 +1074,9 @@ dutyDueForThisReturn.youveAlsoAnswered.p = The below answers will not affect how
dutyDueForThisReturn.dutySuspended.alcohol = Duty suspended alcohol
dutyDueForThisReturn.dutySuspended.declared = Declared
dutyDueForThisReturn.dutySuspended.nothingToDeclare = Nothing to declare
dutyDueForThisReturn.spirits.production = Spirits production
dutyDueForThisReturn.spirits.declared = Declared
dutyDueForThisReturn.spirits.nothingToDeclare = Nothing to declare

returnSubmitted.title = Return sent
returnSubmitted.heading = Return sent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class DutyDueForThisReturnControllerSpec extends SpecBase {
"DutyDueForThisReturn Controller" - {

"must return OK and the correct view for a GET if Yes is selected and there is alcohol to declare" in {
when(dutyDueForThisReturnHelper.getDutyDueViewModel(any())(any(), any())).thenReturn(
when(dutyDueForThisReturnHelper.getDutyDueViewModel(any(), any())(any(), any())).thenReturn(
EitherT.rightT(viewModel)
)

Expand All @@ -78,7 +78,7 @@ class DutyDueForThisReturnControllerSpec extends SpecBase {
}

"must redirect in the Journey Recovery screen if the dutyDueForThisReturnHelper return an error" in {
when(dutyDueForThisReturnHelper.getDutyDueViewModel(any())(any(), any())).thenReturn(
when(dutyDueForThisReturnHelper.getDutyDueViewModel(any(), any())(any(), any())).thenReturn(
EitherT.leftT("Error message")
)

Expand Down Expand Up @@ -145,7 +145,7 @@ class DutyDueForThisReturnControllerSpec extends SpecBase {
}
}

"must redirect to the Journey Recover page if mapping from UserAnswer to AdrReturnSubmission return an error" in {
"must redirect to the Journey Recovery page if mapping from UserAnswer to AdrReturnSubmission return an error" in {
val adrReturnSubmissionService = mock[AdrReturnSubmissionService]
val alcoholDutyReturnsConnector = mock[AlcoholDutyReturnsConnector]
val auditService = mock[AuditService]
Expand Down Expand Up @@ -173,7 +173,7 @@ class DutyDueForThisReturnControllerSpec extends SpecBase {
}
}

"must redirect to the Journey Recover page if the submission is not successful" in {
"must redirect to the Journey Recovery page if the submission is not successful" in {
val adrReturnSubmission = mock[AdrReturnSubmission]
val adrReturnSubmissionService = mock[AdrReturnSubmissionService]
val alcoholDutyReturnsConnector = mock[AlcoholDutyReturnsConnector]
Expand Down Expand Up @@ -205,6 +205,5 @@ class DutyDueForThisReturnControllerSpec extends SpecBase {
verify(auditService, times(0)).audit(any())(any(), any())
}
}

}
}
83 changes: 45 additions & 38 deletions test/services/checkAndSubmit/AdrReturnSubmissionServiceSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -83,34 +83,6 @@ class AdrReturnSubmissionServiceSpec extends SpecBase with TestData {
}

"Full return" - {
"must return the valid return submission when for a return is passed" in new SetUp {
whenReady(
adrReturnSubmissionService.getAdrReturnSubmission(fullUserAnswers, quarterlySpiritsReturnPeriod).value
) { result =>
result mustBe Right(fullReturn)
}
}

"must return the valid return submission without Spirits if the return period is not a quarter return" in new SetUp {
val expectedReturn = fullReturn.copy(spirits = None)

whenReady(
adrReturnSubmissionService.getAdrReturnSubmission(fullUserAnswers, notQuarterlySpiritsReturnPeriod).value
) { result =>
result mustBe Right(expectedReturn)
}
}

"must return the valid return submission without Spirits if the feature toggle is off" in new SetUp(false) {
val expectedReturn = fullReturn.copy(spirits = None)

whenReady(
adrReturnSubmissionService.getAdrReturnSubmission(fullUserAnswers, quarterlySpiritsReturnPeriod).value
) { result =>
result mustBe Right(expectedReturn)
}
}

"must return the valid return submission if one adjustment type is not filled" in new SetUp {
val drawbackAdjustmentIndex = 5
val userAnswers =
Expand Down Expand Up @@ -397,16 +369,51 @@ class AdrReturnSubmissionServiceSpec extends SpecBase with TestData {
}

"Spirits section" - {
Seq(
DeclareQuarterlySpiritsPage
).foreach { page =>
s"must return Left if $page is not present" in new SetUp {
val userAnswers = fullUserAnswers.remove(page).success.value
whenReady(
adrReturnSubmissionService.getAdrReturnSubmission(userAnswers, quarterlySpiritsReturnPeriod).value
) { result =>
result mustBe Left(s"Value not found for page: $page")
}
"must return no spirits if the user doesn't have the spirits regime" in new SetUp {
whenReady(
adrReturnSubmissionService
.getAdrReturnSubmission(
fullUserAnswers.copy(regimes = AlcoholRegimes(Set(Beer, Cider, Wine, OtherFermentedProduct))),
quarterlySpiritsReturnPeriod
)
.value
) { result =>
result.toOption.get.spirits mustBe None
}
}

"must return no spirits if not a spirits quarter" in new SetUp {
whenReady(
adrReturnSubmissionService.getAdrReturnSubmission(fullUserAnswers, notQuarterlySpiritsReturnPeriod).value
) { result =>
result.toOption.get.spirits mustBe None
}
}

"must return no spirits if the feature toggle is off" in new SetUp(false) {
whenReady(
adrReturnSubmissionService.getAdrReturnSubmission(fullUserAnswers, quarterlySpiritsReturnPeriod).value
) { result =>
result.toOption.get.spirits mustBe None
}
}

"must return an error if DeclareQuarterlySpiritsPage is not present" in new SetUp {
val userAnswers = fullUserAnswers.remove(DeclareQuarterlySpiritsPage).success.value
whenReady(
adrReturnSubmissionService.getAdrReturnSubmission(userAnswers, quarterlySpiritsReturnPeriod).value
) { result =>
result mustBe Left(s"Value not found for page: $DeclareQuarterlySpiritsPage")
}
}

"must return spirits otherwise" in new SetUp {
whenReady(
adrReturnSubmissionService.getAdrReturnSubmission(fullUserAnswers, quarterlySpiritsReturnPeriod).value
) { result =>
result.toOption.get.spirits.nonEmpty mustBe true
result.toOption.get.spirits.get.spiritsDeclared mustBe true
result.toOption.get.spirits.get.spiritsProduced.nonEmpty mustBe true
}
}
}
Expand Down
Loading

0 comments on commit e086b98

Please sign in to comment.