Skip to content

Commit

Permalink
Merge pull request #405 from guardian/handle-guardian-weekly-with-n-f…
Browse files Browse the repository at this point in the history
…or-n-intro-plan

Holiday stop for Guardian Weekly with N-for-N scenario
  • Loading branch information
Mario Galic committed Sep 6, 2019
2 parents c7ff2c5 + 578890b commit 867ef7e
Show file tree
Hide file tree
Showing 12 changed files with 272 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ object HolidayStopProcess {
processHolidayStops(
config.holidayCreditProduct,
guardianWeeklyProductRatePlanIds = config.guardianWeeklyProductRatePlanIds,
gwNforNProductRatePlanIds = config.gwNforNProductRatePlanIds,
getHolidayStopRequestsFromSalesforce = Salesforce.holidayStopRequests(config.sfConfig, processDateOverride),
getSubscription = Zuora.subscriptionGetResponse(config, zuoraAccessToken),
updateSubscription = Zuora.subscriptionUpdateResponse(config, zuoraAccessToken),
Expand All @@ -27,6 +28,7 @@ object HolidayStopProcess {
def processHolidayStops(
holidayCreditProduct: HolidayCreditProduct,
guardianWeeklyProductRatePlanIds: List[String],
gwNforNProductRatePlanIds: List[String],
getHolidayStopRequestsFromSalesforce: ProductName => Either[OverallFailure, List[HolidayStopRequestsDetail]],
getSubscription: SubscriptionName => Either[ZuoraHolidayWriteError, Subscription],
updateSubscription: (Subscription, HolidayCreditUpdate) => Either[ZuoraHolidayWriteError, Unit],
Expand All @@ -39,7 +41,7 @@ object HolidayStopProcess {
case Right(holidayStopRequestsFromSalesforce) =>
val holidayStops = holidayStopRequestsFromSalesforce.distinct.map(HolidayStop(_))
val alreadyActionedHolidayStops = holidayStopRequestsFromSalesforce.flatMap(_.Charge_Code__c).distinct
val allZuoraHolidayStopResponses = holidayStops.map(writeHolidayStopToZuora(holidayCreditProduct, guardianWeeklyProductRatePlanIds, getSubscription, updateSubscription))
val allZuoraHolidayStopResponses = holidayStops.map(writeHolidayStopToZuora(holidayCreditProduct, guardianWeeklyProductRatePlanIds, gwNforNProductRatePlanIds, getSubscription, updateSubscription))
val (failedZuoraResponses, successfulZuoraResponses) = allZuoraHolidayStopResponses.separate
val notAlreadyActionedHolidays = successfulZuoraResponses.filterNot(v => alreadyActionedHolidayStops.contains(v.chargeCode))
val salesforceExportResult = writeHolidayStopsToSalesforce(notAlreadyActionedHolidays)
Expand All @@ -58,16 +60,18 @@ object HolidayStopProcess {
def writeHolidayStopToZuora(
holidayCreditProduct: HolidayCreditProduct,
guardianWeeklyProductRatePlanIds: List[String],
gwNforNProductRatePlanIds: List[String],
getSubscription: SubscriptionName => Either[ZuoraHolidayWriteError, Subscription],
updateSubscription: (Subscription, HolidayCreditUpdate) => Either[ZuoraHolidayWriteError, Unit]
)(stop: HolidayStop): Either[ZuoraHolidayWriteError, HolidayStopResponse] =
for {
subscription <- getSubscription(stop.subscriptionName)
_ <- if (subscription.autoRenew) Right(()) else Left(ZuoraHolidayWriteError("Cannot currently process non-auto-renewing subscription"))
currentGuardianWeeklySubscription <- CurrentGuardianWeeklySubscription(subscription, guardianWeeklyProductRatePlanIds)
currentGuardianWeeklySubscription <- CurrentGuardianWeeklySubscription(subscription, guardianWeeklyProductRatePlanIds, gwNforNProductRatePlanIds)
_ <- if (currentGuardianWeeklySubscription.introNforNMode && stop.stoppedPublicationDate.isBefore(currentGuardianWeeklySubscription.invoicedPeriod.startDateIncluding)) Left(ZuoraHolidayWriteError("Holiday within intro N-for-N plan is not currently supported.")) else Right(())
nextInvoiceStartDate = NextBillingPeriodStartDate(currentGuardianWeeklySubscription)
maybeExtendedTerm = ExtendedTerm(nextInvoiceStartDate, subscription)
holidayCredit <- CreditCalculator.guardianWeeklyCredit(guardianWeeklyProductRatePlanIds)(subscription)
holidayCredit <- CreditCalculator.guardianWeeklyCredit(guardianWeeklyProductRatePlanIds, gwNforNProductRatePlanIds)(subscription)
holidayCreditUpdate <- HolidayCreditUpdate(holidayCreditProduct, subscription, stop.stoppedPublicationDate, nextInvoiceStartDate, maybeExtendedTerm, holidayCredit)
_ <- if (subscription.hasHolidayStop(stop)) Right(()) else updateSubscription(subscription, holidayCreditUpdate)
updatedSubscription <- getSubscription(stop.subscriptionName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class ErrorHandlingSpec extends FlatSpec with Matchers with OptionValues {
val result = HolidayStopProcess.processHolidayStops(
config.holidayCreditProduct,
config.guardianWeeklyProductRatePlanIds,
Nil,
getHolidayStopRequestsFromSalesforce,
getSubscription,
updateSubscription,
Expand Down Expand Up @@ -68,6 +69,7 @@ class ErrorHandlingSpec extends FlatSpec with Matchers with OptionValues {
val result = HolidayStopProcess.processHolidayStops(
config.holidayCreditProduct,
config.guardianWeeklyProductRatePlanIds,
Nil,
getHolidayStopRequestsFromSalesforce,
getSubscription,
updateSubscription,
Expand Down Expand Up @@ -96,6 +98,7 @@ class ErrorHandlingSpec extends FlatSpec with Matchers with OptionValues {
val result = HolidayStopProcess.processHolidayStops(
config.holidayCreditProduct,
config.guardianWeeklyProductRatePlanIds,
Nil,
getHolidayStopRequestsFromSalesforce,
getSubscription,
updateSubscription,
Expand Down Expand Up @@ -123,6 +126,7 @@ class ErrorHandlingSpec extends FlatSpec with Matchers with OptionValues {
val result = HolidayStopProcess.processHolidayStops(
config.holidayCreditProduct,
config.guardianWeeklyProductRatePlanIds,
Nil,
getHolidayStopRequestsFromSalesforce,
getSubscription,
updateSubscription,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class HolidayCreditUpdateTest extends FlatSpec with Matchers with EitherValues {
billingPeriod = "Quarter",
chargedThroughDate = Some(LocalDate.of(2019, 9, 12))
)
val currentGuardianWeeklySubscription = CurrentGuardianWeeklySubscription(subscription, guardianWeeklyProductRatePlanIds)
val currentGuardianWeeklySubscription = CurrentGuardianWeeklySubscription(subscription, guardianWeeklyProductRatePlanIds, Nil)
val nextInvoiceStartDate = NextBillingPeriodStartDate(currentGuardianWeeklySubscription.right.value)
val maybeExtendedTerm = ExtendedTerm(nextInvoiceStartDate, subscription)
val holidayCredit = HolidayCredit(currentGuardianWeeklySubscription.right.value)
Expand Down Expand Up @@ -61,7 +61,7 @@ class HolidayCreditUpdateTest extends FlatSpec with Matchers with EitherValues {
billingPeriod = "Quarter",
chargedThroughDate = None
)
CurrentGuardianWeeklySubscription(subscription, guardianWeeklyProductRatePlanIds).left.value shouldBe a[ZuoraHolidayWriteError]
CurrentGuardianWeeklySubscription(subscription, guardianWeeklyProductRatePlanIds, Nil).left.value shouldBe a[ZuoraHolidayWriteError]
}

it should "generate an update with an extended term when charged-through date of subscription is after its term-end date" in {
Expand All @@ -72,7 +72,7 @@ class HolidayCreditUpdateTest extends FlatSpec with Matchers with EitherValues {
billingPeriod = "Annual",
chargedThroughDate = Some(LocalDate.of(2020, 8, 2))
)
val currentGuardianWeeklySubscription = CurrentGuardianWeeklySubscription(subscription, guardianWeeklyProductRatePlanIds)
val currentGuardianWeeklySubscription = CurrentGuardianWeeklySubscription(subscription, guardianWeeklyProductRatePlanIds, Nil)
val nextInvoiceStartDate = NextBillingPeriodStartDate(currentGuardianWeeklySubscription.right.value)
val maybeExtendedTerm = ExtendedTerm(nextInvoiceStartDate, subscription)
val holidayCredit = HolidayCredit(currentGuardianWeeklySubscription.right.value)
Expand Down Expand Up @@ -112,7 +112,7 @@ class HolidayCreditUpdateTest extends FlatSpec with Matchers with EitherValues {
billingPeriod = "Annual",
chargedThroughDate = Some(LocalDate.of(2020, 7, 23))
)
val currentGuardianWeeklySubscription = CurrentGuardianWeeklySubscription(subscription, guardianWeeklyProductRatePlanIds)
val currentGuardianWeeklySubscription = CurrentGuardianWeeklySubscription(subscription, guardianWeeklyProductRatePlanIds, Nil)
val nextInvoiceStartDate = NextBillingPeriodStartDate(currentGuardianWeeklySubscription.right.value)
val maybeExtendedTerm = ExtendedTerm(nextInvoiceStartDate, subscription)
val holidayCredit = HolidayCredit(currentGuardianWeeklySubscription.right.value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class HolidayStopProcessTest extends FlatSpec with Matchers with EitherValues wi
val response = HolidayStopProcess.writeHolidayStopToZuora(
config.holidayCreditProduct,
config.guardianWeeklyProductRatePlanIds,
Nil,
getSubscription(Right(Fixtures.mkSubscriptionWithHolidayStops())),
updateSubscription(Right(()))
)(holidayStop)
Expand All @@ -63,6 +64,7 @@ class HolidayStopProcessTest extends FlatSpec with Matchers with EitherValues wi
val response = HolidayStopProcess.writeHolidayStopToZuora(
config.holidayCreditProduct,
config.guardianWeeklyProductRatePlanIds,
Nil,
getSubscription(Right(subscription)),
updateSubscription(Left(ZuoraHolidayWriteError("update went wrong")))
)(holidayStop)
Expand All @@ -73,6 +75,7 @@ class HolidayStopProcessTest extends FlatSpec with Matchers with EitherValues wi
val response = HolidayStopProcess.writeHolidayStopToZuora(
config.holidayCreditProduct,
config.guardianWeeklyProductRatePlanIds,
Nil,
getSubscription(Left(ZuoraHolidayWriteError("get went wrong"))),
updateSubscription(Right(()))
)(holidayStop)
Expand All @@ -83,6 +86,7 @@ class HolidayStopProcessTest extends FlatSpec with Matchers with EitherValues wi
val response = HolidayStopProcess.writeHolidayStopToZuora(
config.holidayCreditProduct,
config.guardianWeeklyProductRatePlanIds,
Nil,
getSubscription(Right(subscription.copy(autoRenew = false))),
updateSubscription(Right(()))
)(holidayStop)
Expand All @@ -94,6 +98,7 @@ class HolidayStopProcessTest extends FlatSpec with Matchers with EitherValues wi
val response = HolidayStopProcess.writeHolidayStopToZuora(
config.holidayCreditProduct,
config.guardianWeeklyProductRatePlanIds,
Nil,
getSubscription(Right(Fixtures.mkSubscriptionWithHolidayStops())),
updateSubscription(Left(ZuoraHolidayWriteError("shouldn't need to apply an update")))
)(holidayStop)
Expand All @@ -112,6 +117,7 @@ class HolidayStopProcessTest extends FlatSpec with Matchers with EitherValues wi
val response = HolidayStopProcess.writeHolidayStopToZuora(
config.holidayCreditProduct,
config.guardianWeeklyProductRatePlanIds,
Nil,
getSubscription(Right(subscription)),
updateSubscription(Left(ZuoraHolidayWriteError("shouldn't need to apply an update")))
)(holidayStop)
Expand All @@ -122,6 +128,7 @@ class HolidayStopProcessTest extends FlatSpec with Matchers with EitherValues wi
val responses = HolidayStopProcess.processHolidayStops(
config.holidayCreditProduct,
config.guardianWeeklyProductRatePlanIds,
Nil,
getHolidayStopRequestsFromSalesforce(Right(List(
Fixtures.mkHolidayStopRequestDetails(Fixtures.mkHolidayStopRequest("R1", LocalDate.of(2019, 8, 2)), "C1"),
Fixtures.mkHolidayStopRequestDetails(Fixtures.mkHolidayStopRequest("R2", LocalDate.of(2019, 9, 1)), "C3"),
Expand Down Expand Up @@ -155,6 +162,7 @@ class HolidayStopProcessTest extends FlatSpec with Matchers with EitherValues wi
val responses = HolidayStopProcess.processHolidayStops(
config.holidayCreditProduct,
config.guardianWeeklyProductRatePlanIds,
Nil,
getHolidayStopRequestsFromSalesforce(Right(List(
Fixtures.mkHolidayStopRequestDetails(Fixtures.mkHolidayStopRequest("R1", LocalDate.of(2019, 8, 2)), "C2"),
Fixtures.mkHolidayStopRequestDetails(Fixtures.mkHolidayStopRequest("R2", LocalDate.of(2019, 9, 1)), "C5"),
Expand All @@ -181,6 +189,7 @@ class HolidayStopProcessTest extends FlatSpec with Matchers with EitherValues wi
val responses = HolidayStopProcess.processHolidayStops(
config.holidayCreditProduct,
config.guardianWeeklyProductRatePlanIds,
Nil,
getHolidayStopRequestsFromSalesforce(Right(List(
Fixtures.mkHolidayStopRequestDetails(Fixtures.mkHolidayStopRequest("r1"), ""),
Fixtures.mkHolidayStopRequestDetails(Fixtures.mkHolidayStopRequest("r2"), ""),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.gu.holidaystopprocessor

import java.time.LocalDate

import com.gu.holiday_stops._
import org.scalatest._

class PredictedInvoicedPeriodSpec extends FlatSpec with Matchers with OptionValues {

val gwRatePlanCharge = RatePlanCharge(
name = "GW Oct 18 - Quarterly - Domestic",
number = "C-01646726",
price = 37.5,
billingPeriod = Some("Quarter"),
effectiveStartDate = LocalDate.of(2019, 9, 13),
chargedThroughDate = None,
HolidayStart__c = None,
HolidayEnd__c = None,
processedThroughDate = None
)

val gwNForNRatePlanCharge = RatePlanCharge(
name = "GW Oct 18 - First 6 issues - Domestic",
number = "C-01646725",
price = 6,
billingPeriod = None,
effectiveStartDate = LocalDate.of(2019, 8, 2),
chargedThroughDate = Some(LocalDate.of(2019, 9, 13)),
HolidayStart__c = None,
HolidayEnd__c = None,
processedThroughDate = Some(LocalDate.of(2019, 8, 2))
)

val guardianWeeklyWithoutInvoice = RatePlan(
productName = "",
ratePlanCharges = List(gwRatePlanCharge),
productRatePlanId = "",
id = ""
)

val gwNForN = RatePlan(
productName = "",
ratePlanCharges = List(gwNForNRatePlanCharge),
productRatePlanId = "",
id = ""
)

"PredictedInvoicedPeriod" should "predict quarterly invoiced period for GW+N-for-N scenario" in {
PredictedInvoicedPeriod(guardianWeeklyWithoutInvoice, gwNForN)
.value should be(CurrentInvoicedPeriod(LocalDate.of(2019, 9, 13), LocalDate.of(2019, 12, 13)))
}

it should "predict annual invoiced period for GW+N-for-N scenario" in {
val annualGwWithoutInvoice = gwRatePlanCharge.copy(billingPeriod = Some("Annual"))
PredictedInvoicedPeriod(guardianWeeklyWithoutInvoice.copy(ratePlanCharges = List(annualGwWithoutInvoice)), gwNForN)
.value should be(CurrentInvoicedPeriod(LocalDate.of(2019, 9, 13), LocalDate.of(2020, 9, 13)))
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ object SFTestEffects {
"client_id=clientsfclient&client_secret=clientsecretsfsecret&username=usernamesf" +
"&password=passSFpasswordtokentokenSFtoken&grant_type=password"
),
HTTPResponse(200, authSuccessResponseBody)
HTTPResponse(200, authSuccessResponseBody)
)
}
51 changes: 47 additions & 4 deletions lib/holiday-stops/src/main/scala/com/gu/holiday_stops/Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ case class Config(
zuoraConfig: ZuoraConfig,
sfConfig: SFAuthConfig,
holidayCreditProduct: HolidayCreditProduct,
guardianWeeklyProductRatePlanIds: List[String]
guardianWeeklyProductRatePlanIds: List[String],
gwNforNProductRatePlanIds: List[String]
)

/**
Expand Down Expand Up @@ -113,6 +114,45 @@ object Config {
"2c92c0f858aa38af0158da325d2f0b3d", // "name":"Guardian Weekly Annual"
)

val gwNforNProductRatePlanIdsDEV = List(
"2c92c0f85a2190ae015a22bbb6194518", // "name":"Guardian Weekly 6 Issues"}
"2c92c0f85a6b1352015a80a093f21fe0", // "name":"Guardian Weekly 12 Issues"}
"2c92c0f95a246217015a388eaa8c2e2d", // "name":"Guardian Weekly 6 Issues"}
"2c92c0f95a4b4895015a5b02241d6a0b", // "name":"Guardian Weekly 12 Issues"}
"2c92c0f95a4b4895015a5bafe0427948", // "name":"Guardian Weekly 12 Issues"}
"2c92c0f95a4b489a015a5b85958b348f", // "name":"Guardian Weekly 6 Issues"}

"2c92c0f965f212210165f69b94c92d66", // "name":"GW Oct 18 - Six for Six - Domestic"}
"2c92c0f965f2122101660fbc75a16c38", // "name":"GW Oct 18 - Six for Six - ROW"}
)


val gwNforNProductRatePlanIdsUAT = List(
"2c92c0f858aa39000158bf48c5147ddd", // "name":"6 for 6 Issues - OLD"}
"2c92c0f85a4b3a23015a5bd1923d4396", // "name":"Guardian Weekly 12 Issues"}
"2c92c0f85a4b3a7b015a5be6e4e93937", // "name":"Guardian Weekly 6 Issues"}
"2c92c0f85a6b139f015a80a6d5ed2fcd", // "name":"Guardian Weekly 12 Issues"}
"2c92c0f95a24621b015a3d6ce9e32057", // "name":"Guardian Weekly 6 Issues"}
"2c92c0f95a246220015a3d680fe1680d", // "name":"Guardian Weekly 6 Issues"}
"2c92c0f95a4b489a015a5be867ae7445", // "name":"Guardian Weekly 12 Issues"}

"2c92c0f8660fb5dd016610858eb90658", // "name":"GW Oct 18 - Six for Six - Domestic"}
"2c92c0f9660fc4c70166109dfd08092c", // "name":"GW Oct 18 - Six for Six - ROW"}

)

val gwNforNProductRatePlanIdsPROD = List(
"2c92a0fc5a2a49f0015a41f473da233a", // "name":"Guardian Weekly 6 Issues"}
"2c92a0fd5a5adc8b015a5c690d0d1ec6", // "name":"Guardian Weekly 12 Issues"}
"2c92a0fe5a5ad344015a5c67b1144250", // "name":"Guardian Weekly 6 Issues"}
"2c92a0ff59d9d540015a41a40b3e07d3", // "name":"Guardian Weekly 6 Issues"}
"2c92a0ff5a4b85e7015a4cf95d352a07", // "name":"Guardian Weekly 12 Issues"}
"2c92a0ff5a84040f015a855a7afa3f5c", // "name":"Guardian Weekly 12 Issues"}

"2c92a0086619bf8901661aaac94257fe", // "name":"GW Oct 18 - Six for Six - Domestic"}
"2c92a0086619bf8901661ab545f51b21", // "name":"GW Oct 18 - Six for Six - ROW"}
)

private def zuoraCredentials(stage: String): Either[OverallFailure, ZuoraConfig] =
credentials[ZuoraConfig](stage, "zuoraRest")

Expand Down Expand Up @@ -156,7 +196,8 @@ object Config {
productRatePlanId = "2c92a0076ae9189c016b080c930a6186",
productRatePlanChargeId = "2c92a0086ae928d7016b080f638477a6"
),
guardianWeeklyProductRatePlanIdsPROD
guardianWeeklyProductRatePlanIdsPROD,
gwNforNProductRatePlanIdsPROD,
)
case "CODE" =>
Config(
Expand All @@ -166,7 +207,8 @@ object Config {
productRatePlanId = "2c92c0f86b0378b0016b08112e870d0a",
productRatePlanChargeId = "2c92c0f86b0378b0016b08112ec70d14"
),
guardianWeeklyProductRatePlanIdsUAT
guardianWeeklyProductRatePlanIdsUAT,
gwNforNProductRatePlanIdsUAT
)
case "DEV" =>
Config(
Expand All @@ -176,7 +218,8 @@ object Config {
productRatePlanId = "2c92c0f96b03800b016b081fc04f1ba2",
productRatePlanChargeId = "2c92c0f96b03800b016b081fc0f41bb4"
),
guardianWeeklyProductRatePlanIdsDEV
guardianWeeklyProductRatePlanIdsDEV,
gwNforNProductRatePlanIdsDEV
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ object CreditCalculator {
config <- Config()
accessToken <- Zuora.accessTokenGetResponse(config.zuoraConfig)
subscription <- Zuora.subscriptionGetResponse(config, accessToken)(subscriptionName)
credit <- guardianWeeklyCredit(config.guardianWeeklyProductRatePlanIds)(subscription)
credit <- guardianWeeklyCredit(config.guardianWeeklyProductRatePlanIds, config.gwNforNProductRatePlanIds)(subscription)
} yield credit

def guardianWeeklyCredit(guardianWeeklyProductRatePlanIds: List[String])(subscription: Subscription): Either[ZuoraHolidayWriteError, Double] =
CurrentGuardianWeeklySubscription(subscription, guardianWeeklyProductRatePlanIds).map(HolidayCredit(_))
def guardianWeeklyCredit(guardianWeeklyProductRatePlanIds: List[String], gwNforNProductRatePlanIds: List[String])(subscription: Subscription): Either[ZuoraHolidayWriteError, Double] =
CurrentGuardianWeeklySubscription(subscription, guardianWeeklyProductRatePlanIds, gwNforNProductRatePlanIds).map(HolidayCredit(_))
}
Loading

0 comments on commit 867ef7e

Please sign in to comment.