Skip to content

Commit

Permalink
Weekend Voucher holiday-stop-api
Browse files Browse the repository at this point in the history
  • Loading branch information
Mario Galic committed Sep 27, 2019
1 parent b9e4005 commit 7dddd8a
Show file tree
Hide file tree
Showing 12 changed files with 134 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,8 @@ class HandlerTest extends FlatSpec with Matchers {
),
List(
IssueSpecifics(
SundayVoucherIssueSuspensionConstants.firstAvailableDate(LocalDate.now()),
SundayVoucherIssueSuspensionConstants.issueDayOfWeek.getValue
SundayVoucherSuspensionConstants.issueConstants(0).firstAvailableDate(LocalDate.now()),
SundayVoucherSuspensionConstants.issueConstants(0).issueDayOfWeek.getValue
)
),
Some(SundayVoucherSuspensionConstants.annualIssueLimit)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@ package com.gu.holidaystopprocessor
import java.time.LocalDate

import com.gu.effects.RawEffects
import com.gu.holiday_stops.ActionCalculator.{GuardianWeeklyIssueSuspensionConstants, SundayVoucherIssueSuspensionConstants}
import com.gu.holiday_stops.ActionCalculator.GuardianWeeklyIssueSuspensionConstants
import com.gu.salesforce.SalesforceAuthenticate.SFAuthConfig
import com.gu.salesforce.SalesforceClient
import com.gu.salesforce.holiday_stops.SalesforceHolidayStopRequestsDetail
import com.gu.salesforce.holiday_stops.SalesforceHolidayStopRequestsDetail.{ProductRatePlanKey, _}
import com.gu.util.resthttp.JsonHttp
import scalaz.{-\/, \/-}
import com.gu.holiday_stops.{SalesforceHolidayError, SalesforceHolidayResponse}
import com.gu.holiday_stops.{ActionCalculator, SalesforceHolidayError, SalesforceHolidayResponse}

object Salesforce {
def calculateProcessDate(product: Product, processDateOverride: Option[LocalDate]) = {
processDateOverride.getOrElse(LocalDate.now.plusDays {
product match {
case SundayVoucher => SundayVoucherIssueSuspensionConstants.processorRunLeadTimeDays.toLong
case SundayVoucher => ActionCalculator.VoucherProcessorLeadTime
case GuardianWeekly => GuardianWeeklyIssueSuspensionConstants.processorRunLeadTimeDays.toLong
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ object ActionCalculator {
*/
sealed abstract class IssueSuspensionConstants(
val issueDayOfWeek: DayOfWeek,
val processorRunLeadTimeDays: Int,
val processorRunLeadTimeDays: Int
) {
/**
* The first date a holiday can started on for this issue when creating a stop on the supplied date
Expand Down Expand Up @@ -108,19 +108,31 @@ object ActionCalculator {
}
}

val SundayVoucherSuspensionConstants = SuspensionConstants(
annualIssueLimit = 6,
issueConstants = List(SundayVoucherIssueSuspensionConstants)
val SundayVoucherSuspensionConstants = voucherSuspensionConstans(
List(voucherIssueSuspensionConstants(DayOfWeek.SUNDAY))
)

case object SundayVoucherIssueSuspensionConstants extends IssueSuspensionConstants(
issueDayOfWeek = DayOfWeek.SUNDAY,
processorRunLeadTimeDays = 1,
) {
def firstAvailableDate(today: LocalDate): LocalDate = {
today.plus(processorRunLeadTimeDays.toLong, ChronoUnit.DAYS)
val WeekendVoucherSuspensionConstants = voucherSuspensionConstans(
List(
voucherIssueSuspensionConstants(DayOfWeek.SATURDAY),
voucherIssueSuspensionConstants(DayOfWeek.SUNDAY)
)
)

def voucherSuspensionConstans(issueSuspensionConstants: List[IssueSuspensionConstants]) =
SuspensionConstants(issueSuspensionConstants.size * 6, issueSuspensionConstants)

lazy val VoucherProcessorLeadTime: Int = 1

def voucherIssueSuspensionConstants(dayOfWeek: DayOfWeek): IssueSuspensionConstants =
new IssueSuspensionConstants(
issueDayOfWeek = dayOfWeek,
processorRunLeadTimeDays = VoucherProcessorLeadTime
) {
def firstAvailableDate(today: LocalDate): LocalDate = {
today.plus(processorRunLeadTimeDays.toLong, ChronoUnit.DAYS)
}
}
}

// TODO this will likely need to change to return an array of days of week (when we support more than just GW)
def suspensionConstantsByProduct(productNamePrefix: ProductName): SuspensionConstants =
Expand All @@ -134,6 +146,8 @@ object ActionCalculator {
def suspensionConstantsByProductRatePlanKey(
productKey: ProductRatePlanKey
): Either[ActionCalculatorError, SuspensionConstants] = productKey match {
case ProductRatePlanKey(ProductType("Newspaper - Voucher Book"), ProductRatePlanName("Weekend")) =>
Right(WeekendVoucherSuspensionConstants)
case ProductRatePlanKey(ProductType("Newspaper - Voucher Book"), ProductRatePlanName("Sunday")) =>
Right(SundayVoucherSuspensionConstants)
case ProductRatePlanKey(ProductType("Guardian Weekly"), _) =>
Expand All @@ -158,15 +172,15 @@ object ActionCalculator {
): Either[ActionCalculatorError, ProductSpecifics] = {
suspensionConstantsByProductRatePlanKey(productRatePlanChargeId)
.map { constants =>
ProductSpecifics(
constants.annualIssueLimit,
constants.issueConstants.map { issueConstants =>
IssueSpecifics(
issueConstants.firstAvailableDate(today),
issueConstants.issueDayOfWeek.getValue
)
}
)
ProductSpecifics(
constants.annualIssueLimit,
constants.issueConstants.map { issueConstants =>
IssueSpecifics(
issueConstants.firstAvailableDate(today),
issueConstants.issueDayOfWeek.getValue
)
}
)
}
}

Expand Down Expand Up @@ -206,4 +220,4 @@ object ActionCalculator {

}

case class ActionCalculatorError(message: String)
case class ActionCalculatorError(message: String)
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ case class Config(
sfConfig: SFAuthConfig,
holidayCreditProduct: HolidayCreditProduct,
guardianWeeklyConfig: GuardianWeeklyHolidayStopConfig,
sundayVoucherConfig: SundayVoucherHolidayStopConfig
sundayVoucherConfig: SundayVoucherHolidayStopConfig,
weekendVoucherConfig: WeekendVoucherHolidayStopConfig
)

case class ZuoraConfig(
Expand Down Expand Up @@ -58,23 +59,26 @@ object Config {
sfConfig,
HolidayCreditProduct.Prod,
GuardianWeeklyHolidayStopConfig.Prod,
SundayVoucherHolidayStopConfig.Prod
SundayVoucherHolidayStopConfig.Prod,
WeekendVoucherHolidayStopConfig.Prod
)
case "CODE" =>
Config(
zuoraConfig,
sfConfig,
HolidayCreditProduct.Code,
GuardianWeeklyHolidayStopConfig.Code,
SundayVoucherHolidayStopConfig.Code
SundayVoucherHolidayStopConfig.Code,
WeekendVoucherHolidayStopConfig.Code
)
case "DEV" =>
Config(
zuoraConfig,
sfConfig,
HolidayCreditProduct.Dev,
GuardianWeeklyHolidayStopConfig.Dev,
SundayVoucherHolidayStopConfig.Dev
SundayVoucherHolidayStopConfig.Dev,
WeekendVoucherHolidayStopConfig.Dev
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import java.time.LocalDate

import cats.syntax.either._
import com.gu.holiday_stops._
import com.gu.salesforce.holiday_stops.SalesforceHolidayStopRequestsDetail.StoppedPublicationDate
import com.typesafe.scalalogging.LazyLogging
import mouse.all._

Expand All @@ -17,12 +18,25 @@ object Credit extends LazyLogging {
guardianWeeklyCredit(config, stoppedPublicationDate)(subscription)
.orElse(sundayVoucherCredit(config, stoppedPublicationDate)(subscription))
.orElse(Left(ZuoraHolidayError(s"Could not calculate credit for subscription: ${subscription.subscriptionNumber}")))
.orElse {
weekendVoucherCredit(
config.weekendVoucherConfig.productRatePlanId,
stoppedPublicationDate
)(subscription)
}
.<| (logger.error("Failed to calculate holiday stop credits", _))

def guardianWeeklyCredit(config: Config, stoppedPublicationDate: LocalDate)(subscription: Subscription): Either[ZuoraHolidayError, Double] =
CurrentGuardianWeeklySubscription(subscription, config).map(GuardianWeeklyHolidayCredit(_, stoppedPublicationDate))

def sundayVoucherCredit(config: Config, stoppedPublicationDate: LocalDate)(subscription: Subscription): Either[ZuoraHolidayError, Double] =
CurrentSundayVoucherSubscription(subscription, config).map(SundayVoucherHolidayCredit(_, stoppedPublicationDate))

}
CurrentSundayVoucherSubscription(subscription, config).map(VoucherHolidayCredit(_))

def weekendVoucherCredit(sundayVoucherRatePlanId: String, stoppedPublicationDate: LocalDate)(subscription: Subscription) = {
CurrentWeekendVoucherSubscription(
subscription,
sundayVoucherRatePlanId,
StoppedPublicationDate(stoppedPublicationDate)
).map(VoucherHolidayCredit(_))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ case class CurrentSundayVoucherSubscription(
ratePlanId: String,
productRatePlanId: String,
productRatePlanChargeId: String // unique identifier of product
)
) extends CurrentVoucherSubscription

object CurrentSundayVoucherSubscription {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.gu.holiday_stops.subscription

trait CurrentVoucherSubscription {
def price: Double
def billingPeriod: String
def subscriptionNumber: String
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ case class CurrentWeekendVoucherSubscription(
ratePlanId: String,
productRatePlanId: String,
dayOfWeek: VoucherDayOfWeek
)
) extends CurrentVoucherSubscription


sealed trait VoucherDayOfWeek extends EnumEntry
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
package com.gu.holiday_stops.subscription

import java.time.LocalDate
package com.gu.holiday_stops.subscription

import com.gu.holiday_stops.BillingPeriodToApproxWeekCount

import scala.math.BigDecimal.RoundingMode

object SundayVoucherHolidayCredit {
def apply(sundayVoucherSubscription: CurrentSundayVoucherSubscription, stoppedPublicationDate: LocalDate): Double = {
val recurringPrice = sundayVoucherSubscription.price
object VoucherHolidayCredit {
def apply(voucherSubscription: CurrentVoucherSubscription): Double = {
val recurringPrice = voucherSubscription.price
val numPublicationsInPeriod =
BillingPeriodToApproxWeekCount(
subscriptionNumber = sundayVoucherSubscription.subscriptionNumber,
billingPeriod = sundayVoucherSubscription.billingPeriod
subscriptionNumber = voucherSubscription.subscriptionNumber,
billingPeriod = voucherSubscription.billingPeriod
)
-roundUp(recurringPrice / numPublicationsInPeriod)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,42 @@ class ActionCalculatorTest extends FlatSpec with Matchers with EitherValues {
LocalDate.of(2019, 6, 23)
))
}
it should "correctly list the action dates for Weekend Voucher" in {
val weekendVoucherProductRatePlanKey =
ProductRatePlanKey(ProductType("Newspaper - Voucher Book"), ProductRatePlanName("Weekend"))

ActionCalculator.publicationDatesToBeStopped(
fromInclusive = LocalDate.of(2019, 5, 20),
toInclusive = LocalDate.of(2019, 6, 21),
productRatePlanKey = weekendVoucherProductRatePlanKey
) shouldEqual Right(List(
LocalDate.of(2019, 5, 25),
LocalDate.of(2019, 5, 26),
LocalDate.of(2019, 6, 1),
LocalDate.of(2019, 6, 2),
LocalDate.of(2019, 6, 8),
LocalDate.of(2019, 6, 9),
LocalDate.of(2019, 6, 15),
LocalDate.of(2019, 6, 16)
))

ActionCalculator.publicationDatesToBeStopped(
fromInclusive = LocalDate.of(2019, 5, 20),
toInclusive = LocalDate.of(2019, 6, 23),
productRatePlanKey = weekendVoucherProductRatePlanKey
) shouldEqual Right(List(
LocalDate.of(2019, 5, 25),
LocalDate.of(2019, 5, 26),
LocalDate.of(2019, 6, 1),
LocalDate.of(2019, 6, 2),
LocalDate.of(2019, 6, 8),
LocalDate.of(2019, 6, 9),
LocalDate.of(2019, 6, 15),
LocalDate.of(2019, 6, 16),
LocalDate.of(2019, 6, 22),
LocalDate.of(2019, 6, 23)
))
}
it should "return an error for an unsupported product rate plan" in {
val unsupportedProductRatePlanKey =
ProductRatePlanKey(ProductType("not supported"), ProductRatePlanName("not supported"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ object Fixtures {
sfConfig = SFAuthConfig("", "", "", "", "", ""),
HolidayCreditProduct.Dev,
guardianWeeklyConfig = GuardianWeeklyHolidayStopConfig.Dev,
sundayVoucherConfig = SundayVoucherHolidayStopConfig.Dev
sundayVoucherConfig = SundayVoucherHolidayStopConfig.Dev,
weekendVoucherConfig = WeekendVoucherHolidayStopConfig.Dev
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@ class CreditCalculatorSpec extends FlatSpec with Matchers with EitherValues {
)
}

it should "calculate credit for weekend vouchers saturday issue" in {
checkCreditCalculation(
zuoraSubscriptionData = "WeekendVoucherSubscription.json",
stopDate = LocalDate.of(2019, 11, 16),
expectedCredit = -2.64
)
}

it should "calculate credit for weekend vouchers for a sunday issue" in {
checkCreditCalculation(
zuoraSubscriptionData = "WeekendVoucherSubscription.json",
stopDate = LocalDate.of(2019, 11, 17),
expectedCredit = -2.55
)
}

private def checkCreditCalculation(zuoraSubscriptionData: String, stopDate: LocalDate, expectedCredit: Double) = {
val subscriptionRaw = Source.fromResource(zuoraSubscriptionData).mkString
val subscription = decode[Subscription](subscriptionRaw).getOrElse(fail(s"Could not decode $zuoraSubscriptionData"))
Expand Down

0 comments on commit 7dddd8a

Please sign in to comment.