diff --git a/lambda/src/main/scala/pricemigrationengine/handlers/AmendmentHandler.scala b/lambda/src/main/scala/pricemigrationengine/handlers/AmendmentHandler.scala index fa0fc896..13dcb07a 100644 --- a/lambda/src/main/scala/pricemigrationengine/handlers/AmendmentHandler.scala +++ b/lambda/src/main/scala/pricemigrationengine/handlers/AmendmentHandler.scala @@ -200,7 +200,10 @@ object AmendmentHandler extends CohortHandler { ZIO.fromEither( SupporterPlus2024Migration.zuoraUpdate( subscriptionBeforeUpdate, - startDate + startDate, + oldPrice, + estimatedNewPrice, + SupporterPlus2024Migration.priceCap ) ) case Legacy => diff --git a/lambda/src/main/scala/pricemigrationengine/migrations/SupporterPlus2024Migration.scala b/lambda/src/main/scala/pricemigrationengine/migrations/SupporterPlus2024Migration.scala index 6726a006..523202d7 100644 --- a/lambda/src/main/scala/pricemigrationengine/migrations/SupporterPlus2024Migration.scala +++ b/lambda/src/main/scala/pricemigrationengine/migrations/SupporterPlus2024Migration.scala @@ -10,6 +10,8 @@ object SupporterPlus2024Migration { // Static Data // ------------------------------------------------ + val priceCap = 1.27 + val maxLeadTime = 33 val minLeadTime = 31 @@ -101,7 +103,7 @@ object SupporterPlus2024Migration { // ------------------------------------------------ // Subscription Data - def supporterPlusV2RatePlan(subscription: ZuoraSubscription): Either[AmendmentDataFailure, ZuoraRatePlan] = { + def getSupporterPlusV2RatePlan(subscription: ZuoraSubscription): Either[AmendmentDataFailure, ZuoraRatePlan] = { subscription.ratePlans.find(rp => rp.ratePlanName.contains("Supporter Plus V2") && !rp.lastChangeType.contains("Remove") ) match { @@ -115,7 +117,7 @@ object SupporterPlus2024Migration { } } - def supporterPlusBaseRatePlanCharge( + def getSupporterPlusBaseRatePlanCharge( subscriptionNumber: String, ratePlan: ZuoraRatePlan ): Either[AmendmentDataFailure, ZuoraRatePlanCharge] = { @@ -157,16 +159,16 @@ object SupporterPlus2024Migration { def previousBaseAmount(subscription: ZuoraSubscription): Either[Failure, Option[BigDecimal]] = { for { - ratePlan <- supporterPlusV2RatePlan(subscription) - ratePlanCharge <- supporterPlusBaseRatePlanCharge(subscription.subscriptionNumber, ratePlan) + ratePlan <- getSupporterPlusV2RatePlan(subscription) + ratePlanCharge <- getSupporterPlusBaseRatePlanCharge(subscription.subscriptionNumber, ratePlan) } yield ratePlanCharge.price } def newBaseAmount(subscription: ZuoraSubscription): Either[Failure, Option[BigDecimal]] = { for { - ratePlan <- supporterPlusV2RatePlan(subscription) + ratePlan <- getSupporterPlusV2RatePlan(subscription) billingPeriod <- ZuoraRatePlan.ratePlanToBillingPeriod(ratePlan).toRight(AmendmentDataFailure("")) - ratePlanCharge <- supporterPlusBaseRatePlanCharge(subscription.subscriptionNumber, ratePlan) + ratePlanCharge <- getSupporterPlusBaseRatePlanCharge(subscription.subscriptionNumber, ratePlan) currency = ratePlanCharge.currency oldBaseAmountOpt <- previousBaseAmount(subscription) oldBaseAmount <- oldBaseAmountOpt.toRight( @@ -188,7 +190,7 @@ object SupporterPlus2024Migration { def contributionAmount(subscription: ZuoraSubscription): Either[Failure, Option[BigDecimal]] = { for { - ratePlan <- supporterPlusV2RatePlan(subscription) + ratePlan <- getSupporterPlusV2RatePlan(subscription) ratePlanCharge <- supporterPlusContributionRatePlanCharge(subscription.subscriptionNumber, ratePlan) } yield ratePlanCharge.price } @@ -251,9 +253,9 @@ object SupporterPlus2024Migration { subscription: ZuoraSubscription ): Either[AmendmentDataFailure, PriceData] = { for { - ratePlan <- supporterPlusV2RatePlan(subscription) + ratePlan <- getSupporterPlusV2RatePlan(subscription) billingPeriod <- ZuoraRatePlan.ratePlanToBillingPeriod(ratePlan).toRight(AmendmentDataFailure("")) - ratePlanCharge <- supporterPlusBaseRatePlanCharge(subscription.subscriptionNumber, ratePlan) + ratePlanCharge <- getSupporterPlusBaseRatePlanCharge(subscription.subscriptionNumber, ratePlan) currency = ratePlanCharge.currency oldPrice <- ratePlanCharge.price.toRight(AmendmentDataFailure("")) newPrice <- getNewPrice(billingPeriod, currency).toRight(AmendmentDataFailure("")) @@ -263,10 +265,13 @@ object SupporterPlus2024Migration { def zuoraUpdate( subscription: ZuoraSubscription, effectiveDate: LocalDate, + oldPrice: BigDecimal, + estimatedNewPrice: BigDecimal, + priceCap: BigDecimal ): Either[AmendmentDataFailure, ZuoraSubscriptionUpdate] = { for { - existingRatePlan <- supporterPlusV2RatePlan(subscription) - existingBaseRatePlanCharge <- supporterPlusBaseRatePlanCharge( + existingRatePlan <- getSupporterPlusV2RatePlan(subscription) + existingBaseRatePlanCharge <- getSupporterPlusBaseRatePlanCharge( subscription.subscriptionNumber, existingRatePlan ) @@ -287,7 +292,7 @@ object SupporterPlus2024Migration { ChargeOverride( productRatePlanChargeId = existingBaseRatePlanCharge.productRatePlanChargeId, billingPeriod = BillingPeriod.toString(billingPeriod), - price = 120.0 + price = PriceCap.priceCapForNotification(oldPrice, estimatedNewPrice, priceCap) ) ) ) diff --git a/lambda/src/test/scala/pricemigrationengine/migrations/SupporterPlus2024MigrationTest.scala b/lambda/src/test/scala/pricemigrationengine/migrations/SupporterPlus2024MigrationTest.scala index 9e7b1712..319feb0f 100644 --- a/lambda/src/test/scala/pricemigrationengine/migrations/SupporterPlus2024MigrationTest.scala +++ b/lambda/src/test/scala/pricemigrationengine/migrations/SupporterPlus2024MigrationTest.scala @@ -122,7 +122,7 @@ class SupporterPlus2024MigrationTest extends munit.FunSuite { effectiveEndDate = Some(LocalDate.of(2025, 2, 27)) ) assertEquals( - SupporterPlus2024Migration.supporterPlusV2RatePlan(subscription), + SupporterPlus2024Migration.getSupporterPlusV2RatePlan(subscription), Right( ZuoraRatePlan( id = "8a12908b8dd07f56018de8f4950923b8", @@ -184,7 +184,7 @@ class SupporterPlus2024MigrationTest extends munit.FunSuite { effectiveEndDate = Some(LocalDate.of(2024, 11, 11)) ) assertEquals( - SupporterPlus2024Migration.supporterPlusV2RatePlan(subscription), + SupporterPlus2024Migration.getSupporterPlusV2RatePlan(subscription), Right( ZuoraRatePlan( id = "8a12820a8c0ff963018c2504ba045b2f", @@ -247,7 +247,7 @@ class SupporterPlus2024MigrationTest extends munit.FunSuite { effectiveEndDate = Some(LocalDate.of(2025, 4, 5)) ) assertEquals( - SupporterPlus2024Migration.supporterPlusV2RatePlan(subscription), + SupporterPlus2024Migration.getSupporterPlusV2RatePlan(subscription), Right( ZuoraRatePlan( id = "8a12838d8ea33f0f018eaf3a06bd27ea", @@ -264,9 +264,9 @@ class SupporterPlus2024MigrationTest extends munit.FunSuite { test("extracting `Supporter Plus V2` rate plan base charge (monthly)") { val subscription = Fixtures.subscriptionFromJson("Migrations/SupporterPlus2024/monthly/subscription.json") assertEquals( - SupporterPlus2024Migration.supporterPlusBaseRatePlanCharge( + SupporterPlus2024Migration.getSupporterPlusBaseRatePlanCharge( subscription.subscriptionNumber, - SupporterPlus2024Migration.supporterPlusV2RatePlan(subscription).toOption.get + SupporterPlus2024Migration.getSupporterPlusV2RatePlan(subscription).toOption.get ), Right( ZuoraRatePlanCharge( @@ -299,9 +299,9 @@ class SupporterPlus2024MigrationTest extends munit.FunSuite { // read the right price from the subscription. val subscription = Fixtures.subscriptionFromJson("Migrations/SupporterPlus2024/annual/subscription.json") assertEquals( - SupporterPlus2024Migration.supporterPlusBaseRatePlanCharge( + SupporterPlus2024Migration.getSupporterPlusBaseRatePlanCharge( subscription.subscriptionNumber, - SupporterPlus2024Migration.supporterPlusV2RatePlan(subscription).toOption.get + SupporterPlus2024Migration.getSupporterPlusV2RatePlan(subscription).toOption.get ), Right( ZuoraRatePlanCharge( @@ -336,9 +336,9 @@ class SupporterPlus2024MigrationTest extends munit.FunSuite { val subscription = Fixtures.subscriptionFromJson("Migrations/SupporterPlus2024/sub-without-LastChangeType/subscription.json") assertEquals( - SupporterPlus2024Migration.supporterPlusBaseRatePlanCharge( + SupporterPlus2024Migration.getSupporterPlusBaseRatePlanCharge( subscription.subscriptionNumber, - SupporterPlus2024Migration.supporterPlusV2RatePlan(subscription).toOption.get + SupporterPlus2024Migration.getSupporterPlusV2RatePlan(subscription).toOption.get ), Right( ZuoraRatePlanCharge( @@ -371,7 +371,7 @@ class SupporterPlus2024MigrationTest extends munit.FunSuite { assertEquals( SupporterPlus2024Migration.supporterPlusContributionRatePlanCharge( subscription.subscriptionNumber, - SupporterPlus2024Migration.supporterPlusV2RatePlan(subscription).toOption.get + SupporterPlus2024Migration.getSupporterPlusV2RatePlan(subscription).toOption.get ), Right( ZuoraRatePlanCharge( @@ -406,7 +406,7 @@ class SupporterPlus2024MigrationTest extends munit.FunSuite { assertEquals( SupporterPlus2024Migration.supporterPlusContributionRatePlanCharge( subscription.subscriptionNumber, - SupporterPlus2024Migration.supporterPlusV2RatePlan(subscription).toOption.get + SupporterPlus2024Migration.getSupporterPlusV2RatePlan(subscription).toOption.get ), Right( ZuoraRatePlanCharge( @@ -443,7 +443,7 @@ class SupporterPlus2024MigrationTest extends munit.FunSuite { assertEquals( SupporterPlus2024Migration.supporterPlusContributionRatePlanCharge( subscription.subscriptionNumber, - SupporterPlus2024Migration.supporterPlusV2RatePlan(subscription).toOption.get + SupporterPlus2024Migration.getSupporterPlusV2RatePlan(subscription).toOption.get ), Right( ZuoraRatePlanCharge( @@ -732,7 +732,7 @@ class SupporterPlus2024MigrationTest extends munit.FunSuite { test("zuoraUpdate (monthly)") { val subscription = Fixtures.subscriptionFromJson("Migrations/SupporterPlus2024/monthly/subscription.json") assertEquals( - SupporterPlus2024Migration.zuoraUpdate(subscription, LocalDate.of(2024, 9, 9)), + SupporterPlus2024Migration.zuoraUpdate(subscription, LocalDate.of(2024, 9, 9), 10, 12, 1.27), Right( ZuoraSubscriptionUpdate( add = List( @@ -743,7 +743,7 @@ class SupporterPlus2024MigrationTest extends munit.FunSuite { ChargeOverride( productRatePlanChargeId = "8a128ed885fc6ded018602296af13eba", // base plan charge Id billingPeriod = "Month", - price = 120.0 + price = 12.0 ) ) ) @@ -760,10 +760,10 @@ class SupporterPlus2024MigrationTest extends munit.FunSuite { ) ) } - test("zuoraUpdate (annual)") { + test("zuoraUpdate (annual, without capping)") { val subscription = Fixtures.subscriptionFromJson("Migrations/SupporterPlus2024/annual/subscription.json") assertEquals( - SupporterPlus2024Migration.zuoraUpdate(subscription, LocalDate.of(2024, 9, 9)), + SupporterPlus2024Migration.zuoraUpdate(subscription, LocalDate.of(2024, 9, 9), 160, 200, 1.27), Right( ZuoraSubscriptionUpdate( add = List( @@ -774,7 +774,38 @@ class SupporterPlus2024MigrationTest extends munit.FunSuite { ChargeOverride( productRatePlanChargeId = "8a128ed885fc6ded01860228f7cb3d5f", billingPeriod = "Annual", - price = 120.0 + price = 200.0 + ) + ) + ) + ), + remove = List( + RemoveZuoraRatePlan( + ratePlanId = "8a12820a8c0ff963018c2504ba045b2f", + contractEffectiveDate = LocalDate.of(2024, 9, 9) + ) + ), + currentTerm = None, + currentTermPeriodType = None + ) + ) + ) + } + test("zuoraUpdate (annual, with capping)") { + val subscription = Fixtures.subscriptionFromJson("Migrations/SupporterPlus2024/annual/subscription.json") + assertEquals( + SupporterPlus2024Migration.zuoraUpdate(subscription, LocalDate.of(2024, 9, 9), 150, 200, 1.27), + Right( + ZuoraSubscriptionUpdate( + add = List( + AddZuoraRatePlan( + productRatePlanId = "8a128ed885fc6ded01860228f77e3d5a", + contractEffectiveDate = LocalDate.of(2024, 9, 9), + chargeOverrides = List( + ChargeOverride( + productRatePlanChargeId = "8a128ed885fc6ded01860228f7cb3d5f", + billingPeriod = "Annual", + price = 190.5 ) ) )