From 0e048c03b1311b6cd1d71422df15a4e6371b16ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yusuf=20To=CC=88r?= <3296904+yusuftor@users.noreply.github.com> Date: Wed, 25 Feb 2026 15:01:25 +0100 Subject: [PATCH 1/4] Align iOS pricing calculations with editor behavior --- .../Discount/StoreProductDiscount.swift | 20 ++++----- .../StoreProduct/SK2StoreProduct.swift | 27 +++++++----- .../StoreProduct/StripeProductType.swift | 31 ++++++++----- .../StoreProduct/SubscriptionPeriod.swift | 18 ++++---- .../StoreProduct/TestStoreProduct.swift | 31 ++++++++----- .../SubscriptionPeriodPriceTests.swift | 43 ++++++++++++++----- 6 files changed, 107 insertions(+), 63 deletions(-) diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/Discount/StoreProductDiscount.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/Discount/StoreProductDiscount.swift index 64738f3e60..707b32e86e 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/Discount/StoreProductDiscount.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/Discount/StoreProductDiscount.swift @@ -130,29 +130,29 @@ extension StoreProductDiscount { case .day: switch subscriptionPeriod.unit { case .day: return 1 - case .week: return 7 - case .month: return 30 + case .week: return Decimal(365) / Decimal(52) + case .month: return Decimal(365) / Decimal(12) case .year: return 365 } case .week: switch subscriptionPeriod.unit { - case .day: return 1 / 7 + case .day: return Decimal(52) / Decimal(365) case .week: return 1 - case .month: return 4 - case .year: return 52 + case .month: return Decimal(52) / Decimal(12) + case .year: return Decimal(365) / Decimal(7) } case .month: switch subscriptionPeriod.unit { - case .day: return 1 / 30 - case .week: return 1 / 4 + case .day: return Decimal(12) / Decimal(365) + case .week: return Decimal(12) / Decimal(52) case .month: return 1 case .year: return 12 } case .year: switch subscriptionPeriod.unit { - case .day: return 1 / 365 - case .week: return 1 / 52 - case .month: return 1 / 12 + case .day: return Decimal(1) / Decimal(365) + case .week: return Decimal(1) / Decimal(52) + case .month: return Decimal(1) / Decimal(12) case .year: return 1 } } diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift index 8f3e620ed4..abb9afe322 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift @@ -251,6 +251,11 @@ struct SK2StoreProduct: StoreProductType { return "\(periodDays)" } + private func roundedPrice(_ amount: Decimal) -> Decimal { + (amount as NSDecimalNumber) + .rounding(accordingToBehavior: SubscriptionPeriod.roundingBehavior) as Decimal + } + var dailyPrice: String { guard let subscriptionPeriod = underlyingSK2Product.subscription?.subscriptionPeriod else { return "n/a" @@ -264,16 +269,16 @@ struct SK2StoreProduct: StoreProductType { case .year: periods = Decimal(365 * numberOfUnits) case .month: - periods = Decimal(30 * numberOfUnits) + periods = Decimal(365) / Decimal(12) * Decimal(numberOfUnits) case .week: - periods = Decimal(7 * numberOfUnits) + periods = Decimal(365) / Decimal(52) * Decimal(numberOfUnits) case .day: periods = Decimal(numberOfUnits) @unknown default: periods = Decimal(numberOfUnits) } - return (inputPrice / periods).formatted(underlyingSK2Product.priceFormatStyle) + return roundedPrice(inputPrice / periods).formatted(underlyingSK2Product.priceFormatStyle) } var weeklyPrice: String { @@ -287,18 +292,18 @@ struct SK2StoreProduct: StoreProductType { switch subscriptionPeriod.unit { case .year: - periods = Decimal(52 * numberOfUnits) + periods = Decimal(365) / Decimal(7) * Decimal(numberOfUnits) case .month: - periods = Decimal(4 * numberOfUnits) + periods = Decimal(52) / Decimal(12) * Decimal(numberOfUnits) case .week: periods = Decimal(numberOfUnits) case .day: - periods = Decimal(numberOfUnits) / Decimal(7) + periods = Decimal(numberOfUnits) * Decimal(52) / Decimal(365) @unknown default: periods = Decimal(numberOfUnits) } - return (inputPrice / periods).formatted(underlyingSK2Product.priceFormatStyle) + return roundedPrice(inputPrice / periods).formatted(underlyingSK2Product.priceFormatStyle) } var monthlyPrice: String { @@ -316,14 +321,14 @@ struct SK2StoreProduct: StoreProductType { case .month: periods = Decimal(1 * numberOfUnits) case .week: - periods = Decimal(numberOfUnits) / Decimal(4) + periods = Decimal(numberOfUnits) * Decimal(12) / Decimal(52) case .day: - periods = Decimal(numberOfUnits) / Decimal(30) + periods = Decimal(numberOfUnits) * Decimal(12) / Decimal(365) @unknown default: periods = Decimal(numberOfUnits) } - return (inputPrice / periods).formatted(underlyingSK2Product.priceFormatStyle) + return roundedPrice(inputPrice / periods).formatted(underlyingSK2Product.priceFormatStyle) } var yearlyPrice: String { @@ -348,7 +353,7 @@ struct SK2StoreProduct: StoreProductType { periods = Decimal(numberOfUnits) } - return (inputPrice / periods).formatted(underlyingSK2Product.priceFormatStyle) + return roundedPrice(inputPrice / periods).formatted(underlyingSK2Product.priceFormatStyle) } var hasFreeTrial: Bool { diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StripeProductType.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StripeProductType.swift index 243242f14f..b557eaeeb0 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StripeProductType.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StripeProductType.swift @@ -274,6 +274,11 @@ struct StripeProductType: StoreProductType { return "\(periodDays)" } + private func roundedPrice(_ amount: Decimal) -> Decimal { + (amount as NSDecimalNumber) + .rounding(accordingToBehavior: SubscriptionPeriod.roundingBehavior) as Decimal + } + var dailyPrice: String { if price == 0.00 { return "$0.00" @@ -295,18 +300,19 @@ struct StripeProductType: StoreProductType { } if subscriptionPeriod.unit == .month { - periods = Decimal(30 * numberOfUnits) + periods = Decimal(365) / Decimal(12) * Decimal(numberOfUnits) } if subscriptionPeriod.unit == .week { - periods = Decimal(numberOfUnits) / Decimal(7) + periods = Decimal(365) / Decimal(52) * Decimal(numberOfUnits) } if subscriptionPeriod.unit == .day { periods = Decimal(numberOfUnits) / Decimal(1) } - return numberFormatter.string(from: NSDecimalNumber(decimal: inputPrice / periods)) ?? "n/a" + let rounded = roundedPrice(inputPrice / periods) + return numberFormatter.string(from: NSDecimalNumber(decimal: rounded)) ?? "n/a" } var weeklyPrice: String { @@ -325,11 +331,11 @@ struct StripeProductType: StoreProductType { var periods: Decimal = 1.0 if subscriptionPeriod.unit == .year { - periods = Decimal(52 * numberOfUnits) + periods = Decimal(365) / Decimal(7) * Decimal(numberOfUnits) } if subscriptionPeriod.unit == .month { - periods = Decimal(4 * numberOfUnits) + periods = Decimal(52) / Decimal(12) * Decimal(numberOfUnits) } if subscriptionPeriod.unit == .week { @@ -337,10 +343,11 @@ struct StripeProductType: StoreProductType { } if subscriptionPeriod.unit == .day { - periods = Decimal(numberOfUnits) / Decimal(7) + periods = Decimal(numberOfUnits) * Decimal(52) / Decimal(365) } - return numberFormatter.string(from: NSDecimalNumber(decimal: price / periods)) ?? "n/a" + let rounded = roundedPrice(price / periods) + return numberFormatter.string(from: NSDecimalNumber(decimal: rounded)) ?? "n/a" } var monthlyPrice: String { @@ -368,14 +375,15 @@ struct StripeProductType: StoreProductType { } if subscriptionPeriod.unit == .week { - periods = Decimal(numberOfUnits) / Decimal(4) + periods = Decimal(numberOfUnits) * Decimal(12) / Decimal(52) } if subscriptionPeriod.unit == .day { - periods = Decimal(numberOfUnits) / Decimal(30) + periods = Decimal(numberOfUnits) * Decimal(12) / Decimal(365) } - return numberFormatter.string(from: NSDecimalNumber(decimal: price / periods)) ?? "n/a" + let rounded = roundedPrice(price / periods) + return numberFormatter.string(from: NSDecimalNumber(decimal: rounded)) ?? "n/a" } var yearlyPrice: String { @@ -410,7 +418,8 @@ struct StripeProductType: StoreProductType { periods = Decimal(numberOfUnits) / Decimal(365) } - return numberFormatter.string(from: NSDecimalNumber(decimal: price / periods)) ?? "n/a" + let rounded = roundedPrice(price / periods) + return numberFormatter.string(from: NSDecimalNumber(decimal: rounded)) ?? "n/a" } var hasFreeTrial: Bool { diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SubscriptionPeriod.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SubscriptionPeriod.swift index 901c5b94cd..ef39e8c3e5 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SubscriptionPeriod.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SubscriptionPeriod.swift @@ -131,8 +131,8 @@ extension SubscriptionPeriod { let periodsPerDay: Decimal = { switch self.unit { case .day: return 1 - case .week: return 7 - case .month: return 30 + case .week: return Decimal(365) / Decimal(52) + case .month: return Decimal(365) / Decimal(12) case .year: return 365 } }() * Decimal(value) @@ -143,25 +143,25 @@ extension SubscriptionPeriod { } func pricePerWeek(withTotalPrice price: Decimal) -> Decimal { - let periodsPerDay: Decimal = { + let periodsPerWeek: Decimal = { switch self.unit { - case .day: return 1 / 7 + case .day: return Decimal(52) / Decimal(365) case .week: return 1 - case .month: return 4 - case .year: return 52 + case .month: return Decimal(52) / Decimal(12) + case .year: return Decimal(365) / Decimal(7) } }() * Decimal(value) return (price as NSDecimalNumber) - .dividing(by: periodsPerDay as NSDecimalNumber, + .dividing(by: periodsPerWeek as NSDecimalNumber, withBehavior: Self.roundingBehavior) as Decimal } func pricePerMonth(withTotalPrice price: Decimal) -> Decimal { let periodsPerMonth: Decimal = { switch self.unit { - case .day: return 1 / 30 - case .week: return 1 / 4 + case .day: return Decimal(12) / Decimal(365) + case .week: return Decimal(12) / Decimal(52) case .month: return 1 case .year: return 12 } diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/TestStoreProduct.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/TestStoreProduct.swift index bf630f5926..be1b768150 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/TestStoreProduct.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/TestStoreProduct.swift @@ -174,6 +174,11 @@ struct TestStoreProduct: StoreProductType { return formatter } + private func roundedPrice(_ amount: Decimal) -> Decimal { + (amount as NSDecimalNumber) + .rounding(accordingToBehavior: SubscriptionPeriod.roundingBehavior) as Decimal + } + var dailyPrice: String { guard price != 0, let unit = subscriptionUnit else { return priceFormatter.string(from: 0) ?? "$0.00" @@ -181,12 +186,13 @@ struct TestStoreProduct: StoreProductType { let days: Decimal switch unit { case .day: days = Decimal(subscriptionValue) - case .week: days = Decimal(7 * subscriptionValue) - case .month: days = Decimal(30 * subscriptionValue) + case .week: days = Decimal(365) / Decimal(52) * Decimal(subscriptionValue) + case .month: days = Decimal(365) / Decimal(12) * Decimal(subscriptionValue) case .year: days = Decimal(365 * subscriptionValue) @unknown default: days = 1 } - return priceFormatter.string(from: NSDecimalNumber(decimal: price / days)) ?? "n/a" + let rounded = roundedPrice(price / days) + return priceFormatter.string(from: NSDecimalNumber(decimal: rounded)) ?? "n/a" } var weeklyPrice: String { @@ -195,13 +201,14 @@ struct TestStoreProduct: StoreProductType { } let weeks: Decimal switch unit { - case .day: weeks = Decimal(subscriptionValue) / 7 + case .day: weeks = Decimal(subscriptionValue) * Decimal(52) / Decimal(365) case .week: weeks = Decimal(subscriptionValue) - case .month: weeks = Decimal(4 * subscriptionValue) - case .year: weeks = Decimal(52 * subscriptionValue) + case .month: weeks = Decimal(52) / Decimal(12) * Decimal(subscriptionValue) + case .year: weeks = Decimal(365) / Decimal(7) * Decimal(subscriptionValue) @unknown default: weeks = 1 } - return priceFormatter.string(from: NSDecimalNumber(decimal: price / weeks)) ?? "n/a" + let rounded = roundedPrice(price / weeks) + return priceFormatter.string(from: NSDecimalNumber(decimal: rounded)) ?? "n/a" } var monthlyPrice: String { @@ -210,13 +217,14 @@ struct TestStoreProduct: StoreProductType { } let months: Decimal switch unit { - case .day: months = Decimal(subscriptionValue) / 30 - case .week: months = Decimal(subscriptionValue) / 4 + case .day: months = Decimal(subscriptionValue) * Decimal(12) / Decimal(365) + case .week: months = Decimal(subscriptionValue) * Decimal(12) / Decimal(52) case .month: months = Decimal(subscriptionValue) case .year: months = Decimal(12 * subscriptionValue) @unknown default: months = 1 } - return priceFormatter.string(from: NSDecimalNumber(decimal: price / months)) ?? "n/a" + let rounded = roundedPrice(price / months) + return priceFormatter.string(from: NSDecimalNumber(decimal: rounded)) ?? "n/a" } var yearlyPrice: String { @@ -231,7 +239,8 @@ struct TestStoreProduct: StoreProductType { case .year: years = Decimal(subscriptionValue) @unknown default: years = 1 } - return priceFormatter.string(from: NSDecimalNumber(decimal: price / years)) ?? "n/a" + let rounded = roundedPrice(price / years) + return priceFormatter.string(from: NSDecimalNumber(decimal: rounded)) ?? "n/a" } // MARK: - Trial diff --git a/Tests/SuperwallKitTests/StoreKit/Products/StoreProduct/SubscriptionPeriodPriceTests.swift b/Tests/SuperwallKitTests/StoreKit/Products/StoreProduct/SubscriptionPeriodPriceTests.swift index f31f0c7eaa..9b20019ec9 100644 --- a/Tests/SuperwallKitTests/StoreKit/Products/StoreProduct/SubscriptionPeriodPriceTests.swift +++ b/Tests/SuperwallKitTests/StoreKit/Products/StoreProduct/SubscriptionPeriodPriceTests.swift @@ -30,12 +30,12 @@ struct SubscriptionPeriodPriceTests { @Test("Daily price for monthly subscription") func testDailyPriceForMonthlySubscription() { - // $9.99/month should be ~$0.33/day (9.99 / 30) + // $9.99/month should be ~$0.32/day ((9.99 * 12) / 365) let period = SubscriptionPeriod(value: 1, unit: .month) let dailyPrice = period.pricePerDay(withTotalPrice: Decimal(9.99)) - // 9.99 / 30 = 0.333 rounds down to 0.33 - #expect(dailyPrice == Decimal(string: "0.33")) + // (9.99 * 12) / 365 = 0.328... rounds down to 0.32 + #expect(dailyPrice == Decimal(string: "0.32")) } @Test("Daily price for weekly subscription") @@ -44,7 +44,7 @@ struct SubscriptionPeriodPriceTests { let period = SubscriptionPeriod(value: 1, unit: .week) let dailyPrice = period.pricePerDay(withTotalPrice: Decimal(4.99)) - // 4.99 / 7 = 0.712... rounds down to 0.71 + // 4.99 / (365/52) = 0.710... rounds down to 0.71 #expect(dailyPrice == Decimal(string: "0.71")) } @@ -63,7 +63,7 @@ struct SubscriptionPeriodPriceTests { let period = SubscriptionPeriod(value: 3, unit: .month) let dailyPrice = period.pricePerDay(withTotalPrice: Decimal(24.99)) - // 24.99 / 90 = 0.2776... rounds down to 0.27 + // 24.99 / 91.25 = 0.2738... rounds down to 0.27 #expect(dailyPrice == Decimal(string: "0.27")) } @@ -71,22 +71,43 @@ struct SubscriptionPeriodPriceTests { @Test("Weekly price for yearly subscription") func testWeeklyPriceForYearlySubscription() { - // $99.99/year should be ~$1.92/week (99.99 / 52) + // $99.99/year should be ~$1.91/week (99.99 / (365/7)) let period = SubscriptionPeriod(value: 1, unit: .year) let weeklyPrice = period.pricePerWeek(withTotalPrice: Decimal(99.99)) - // 99.99 / 52 = 1.923... rounds down to 1.92 - #expect(weeklyPrice == Decimal(string: "1.92")) + // 99.99 / (365/7) = 1.917... rounds down to 1.91 + #expect(weeklyPrice == Decimal(string: "1.91")) + } + + @Test("Yearly plan weekly and monthly prices match editor rounding") + func testYearlyPlanEditorParity() { + let period = SubscriptionPeriod(value: 1, unit: .year) + + let weeklyPrice = period.pricePerWeek(withTotalPrice: Decimal(89.99)) + let monthlyPrice = period.pricePerMonth(withTotalPrice: Decimal(89.99)) + + #expect(weeklyPrice == Decimal(string: "1.72")) + #expect(monthlyPrice == Decimal(string: "7.49")) } @Test("Weekly price for monthly subscription") func testWeeklyPriceForMonthlySubscription() { - // $9.99/month should be ~$2.49/week (9.99 / 4) + // $9.99/month should be ~$2.30/week ((9.99 * 12) / 52) let period = SubscriptionPeriod(value: 1, unit: .month) let weeklyPrice = period.pricePerWeek(withTotalPrice: Decimal(9.99)) - // 9.99 / 4 = 2.4975 rounds down to 2.49 - #expect(weeklyPrice == Decimal(string: "2.49")) + // (9.99 * 12) / 52 = 2.305... rounds down to 2.30 + #expect(weeklyPrice == Decimal(string: "2.30")) + } + + @Test("Weekly price annualizes monthly products before dividing by 52") + func testWeeklyPriceAnnualizedFromMonthlySubscription() { + // $29.99/month should be ~$6.92/week ((29.99 * 12) / 52) + let period = SubscriptionPeriod(value: 1, unit: .month) + let weeklyPrice = period.pricePerWeek(withTotalPrice: Decimal(29.99)) + + // (29.99 * 12) / 52 = 6.920... rounds down to 6.92 + #expect(weeklyPrice == Decimal(string: "6.92")) } @Test("Weekly price for weekly subscription") From 7fe2f37c647e246bcd23cfe7ae49bcbde2ce9bbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yusuf=20To=CC=88r?= <3296904+yusuftor@users.noreply.github.com> Date: Wed, 25 Feb 2026 15:01:25 +0100 Subject: [PATCH 2/4] Fix weekly/daily/monthly price conversions to annualize first MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously the SDK used simple divisors for cross-period price conversions (e.g. month→week divided by 4), which produced different results than the paywall editor which annualizes first then divides. For example, $29.99/month weekly price: - Before: $29.99 ÷ 4 = $7.49 - After: $29.99 × 12 ÷ 52 = $6.92 (matches editor) Updated conversion factors across SK1, SK2, Stripe, and Test product types, plus trial period discount calculations. Added consistent rounding behavior using NSDecimalNumberHandler. Co-Authored-By: Claude Opus 4.6 --- .../Discount/StoreProductDiscount.swift | 20 ++++----- .../StoreProduct/SK2StoreProduct.swift | 27 +++++++----- .../StoreProduct/StripeProductType.swift | 31 ++++++++----- .../StoreProduct/SubscriptionPeriod.swift | 18 ++++---- .../StoreProduct/TestStoreProduct.swift | 31 ++++++++----- .../SubscriptionPeriodPriceTests.swift | 43 ++++++++++++++----- 6 files changed, 107 insertions(+), 63 deletions(-) diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/Discount/StoreProductDiscount.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/Discount/StoreProductDiscount.swift index 64738f3e60..707b32e86e 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/Discount/StoreProductDiscount.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/Discount/StoreProductDiscount.swift @@ -130,29 +130,29 @@ extension StoreProductDiscount { case .day: switch subscriptionPeriod.unit { case .day: return 1 - case .week: return 7 - case .month: return 30 + case .week: return Decimal(365) / Decimal(52) + case .month: return Decimal(365) / Decimal(12) case .year: return 365 } case .week: switch subscriptionPeriod.unit { - case .day: return 1 / 7 + case .day: return Decimal(52) / Decimal(365) case .week: return 1 - case .month: return 4 - case .year: return 52 + case .month: return Decimal(52) / Decimal(12) + case .year: return Decimal(365) / Decimal(7) } case .month: switch subscriptionPeriod.unit { - case .day: return 1 / 30 - case .week: return 1 / 4 + case .day: return Decimal(12) / Decimal(365) + case .week: return Decimal(12) / Decimal(52) case .month: return 1 case .year: return 12 } case .year: switch subscriptionPeriod.unit { - case .day: return 1 / 365 - case .week: return 1 / 52 - case .month: return 1 / 12 + case .day: return Decimal(1) / Decimal(365) + case .week: return Decimal(1) / Decimal(52) + case .month: return Decimal(1) / Decimal(12) case .year: return 1 } } diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift index 8f3e620ed4..abb9afe322 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift @@ -251,6 +251,11 @@ struct SK2StoreProduct: StoreProductType { return "\(periodDays)" } + private func roundedPrice(_ amount: Decimal) -> Decimal { + (amount as NSDecimalNumber) + .rounding(accordingToBehavior: SubscriptionPeriod.roundingBehavior) as Decimal + } + var dailyPrice: String { guard let subscriptionPeriod = underlyingSK2Product.subscription?.subscriptionPeriod else { return "n/a" @@ -264,16 +269,16 @@ struct SK2StoreProduct: StoreProductType { case .year: periods = Decimal(365 * numberOfUnits) case .month: - periods = Decimal(30 * numberOfUnits) + periods = Decimal(365) / Decimal(12) * Decimal(numberOfUnits) case .week: - periods = Decimal(7 * numberOfUnits) + periods = Decimal(365) / Decimal(52) * Decimal(numberOfUnits) case .day: periods = Decimal(numberOfUnits) @unknown default: periods = Decimal(numberOfUnits) } - return (inputPrice / periods).formatted(underlyingSK2Product.priceFormatStyle) + return roundedPrice(inputPrice / periods).formatted(underlyingSK2Product.priceFormatStyle) } var weeklyPrice: String { @@ -287,18 +292,18 @@ struct SK2StoreProduct: StoreProductType { switch subscriptionPeriod.unit { case .year: - periods = Decimal(52 * numberOfUnits) + periods = Decimal(365) / Decimal(7) * Decimal(numberOfUnits) case .month: - periods = Decimal(4 * numberOfUnits) + periods = Decimal(52) / Decimal(12) * Decimal(numberOfUnits) case .week: periods = Decimal(numberOfUnits) case .day: - periods = Decimal(numberOfUnits) / Decimal(7) + periods = Decimal(numberOfUnits) * Decimal(52) / Decimal(365) @unknown default: periods = Decimal(numberOfUnits) } - return (inputPrice / periods).formatted(underlyingSK2Product.priceFormatStyle) + return roundedPrice(inputPrice / periods).formatted(underlyingSK2Product.priceFormatStyle) } var monthlyPrice: String { @@ -316,14 +321,14 @@ struct SK2StoreProduct: StoreProductType { case .month: periods = Decimal(1 * numberOfUnits) case .week: - periods = Decimal(numberOfUnits) / Decimal(4) + periods = Decimal(numberOfUnits) * Decimal(12) / Decimal(52) case .day: - periods = Decimal(numberOfUnits) / Decimal(30) + periods = Decimal(numberOfUnits) * Decimal(12) / Decimal(365) @unknown default: periods = Decimal(numberOfUnits) } - return (inputPrice / periods).formatted(underlyingSK2Product.priceFormatStyle) + return roundedPrice(inputPrice / periods).formatted(underlyingSK2Product.priceFormatStyle) } var yearlyPrice: String { @@ -348,7 +353,7 @@ struct SK2StoreProduct: StoreProductType { periods = Decimal(numberOfUnits) } - return (inputPrice / periods).formatted(underlyingSK2Product.priceFormatStyle) + return roundedPrice(inputPrice / periods).formatted(underlyingSK2Product.priceFormatStyle) } var hasFreeTrial: Bool { diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StripeProductType.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StripeProductType.swift index 243242f14f..b557eaeeb0 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StripeProductType.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StripeProductType.swift @@ -274,6 +274,11 @@ struct StripeProductType: StoreProductType { return "\(periodDays)" } + private func roundedPrice(_ amount: Decimal) -> Decimal { + (amount as NSDecimalNumber) + .rounding(accordingToBehavior: SubscriptionPeriod.roundingBehavior) as Decimal + } + var dailyPrice: String { if price == 0.00 { return "$0.00" @@ -295,18 +300,19 @@ struct StripeProductType: StoreProductType { } if subscriptionPeriod.unit == .month { - periods = Decimal(30 * numberOfUnits) + periods = Decimal(365) / Decimal(12) * Decimal(numberOfUnits) } if subscriptionPeriod.unit == .week { - periods = Decimal(numberOfUnits) / Decimal(7) + periods = Decimal(365) / Decimal(52) * Decimal(numberOfUnits) } if subscriptionPeriod.unit == .day { periods = Decimal(numberOfUnits) / Decimal(1) } - return numberFormatter.string(from: NSDecimalNumber(decimal: inputPrice / periods)) ?? "n/a" + let rounded = roundedPrice(inputPrice / periods) + return numberFormatter.string(from: NSDecimalNumber(decimal: rounded)) ?? "n/a" } var weeklyPrice: String { @@ -325,11 +331,11 @@ struct StripeProductType: StoreProductType { var periods: Decimal = 1.0 if subscriptionPeriod.unit == .year { - periods = Decimal(52 * numberOfUnits) + periods = Decimal(365) / Decimal(7) * Decimal(numberOfUnits) } if subscriptionPeriod.unit == .month { - periods = Decimal(4 * numberOfUnits) + periods = Decimal(52) / Decimal(12) * Decimal(numberOfUnits) } if subscriptionPeriod.unit == .week { @@ -337,10 +343,11 @@ struct StripeProductType: StoreProductType { } if subscriptionPeriod.unit == .day { - periods = Decimal(numberOfUnits) / Decimal(7) + periods = Decimal(numberOfUnits) * Decimal(52) / Decimal(365) } - return numberFormatter.string(from: NSDecimalNumber(decimal: price / periods)) ?? "n/a" + let rounded = roundedPrice(price / periods) + return numberFormatter.string(from: NSDecimalNumber(decimal: rounded)) ?? "n/a" } var monthlyPrice: String { @@ -368,14 +375,15 @@ struct StripeProductType: StoreProductType { } if subscriptionPeriod.unit == .week { - periods = Decimal(numberOfUnits) / Decimal(4) + periods = Decimal(numberOfUnits) * Decimal(12) / Decimal(52) } if subscriptionPeriod.unit == .day { - periods = Decimal(numberOfUnits) / Decimal(30) + periods = Decimal(numberOfUnits) * Decimal(12) / Decimal(365) } - return numberFormatter.string(from: NSDecimalNumber(decimal: price / periods)) ?? "n/a" + let rounded = roundedPrice(price / periods) + return numberFormatter.string(from: NSDecimalNumber(decimal: rounded)) ?? "n/a" } var yearlyPrice: String { @@ -410,7 +418,8 @@ struct StripeProductType: StoreProductType { periods = Decimal(numberOfUnits) / Decimal(365) } - return numberFormatter.string(from: NSDecimalNumber(decimal: price / periods)) ?? "n/a" + let rounded = roundedPrice(price / periods) + return numberFormatter.string(from: NSDecimalNumber(decimal: rounded)) ?? "n/a" } var hasFreeTrial: Bool { diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SubscriptionPeriod.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SubscriptionPeriod.swift index 901c5b94cd..ef39e8c3e5 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SubscriptionPeriod.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SubscriptionPeriod.swift @@ -131,8 +131,8 @@ extension SubscriptionPeriod { let periodsPerDay: Decimal = { switch self.unit { case .day: return 1 - case .week: return 7 - case .month: return 30 + case .week: return Decimal(365) / Decimal(52) + case .month: return Decimal(365) / Decimal(12) case .year: return 365 } }() * Decimal(value) @@ -143,25 +143,25 @@ extension SubscriptionPeriod { } func pricePerWeek(withTotalPrice price: Decimal) -> Decimal { - let periodsPerDay: Decimal = { + let periodsPerWeek: Decimal = { switch self.unit { - case .day: return 1 / 7 + case .day: return Decimal(52) / Decimal(365) case .week: return 1 - case .month: return 4 - case .year: return 52 + case .month: return Decimal(52) / Decimal(12) + case .year: return Decimal(365) / Decimal(7) } }() * Decimal(value) return (price as NSDecimalNumber) - .dividing(by: periodsPerDay as NSDecimalNumber, + .dividing(by: periodsPerWeek as NSDecimalNumber, withBehavior: Self.roundingBehavior) as Decimal } func pricePerMonth(withTotalPrice price: Decimal) -> Decimal { let periodsPerMonth: Decimal = { switch self.unit { - case .day: return 1 / 30 - case .week: return 1 / 4 + case .day: return Decimal(12) / Decimal(365) + case .week: return Decimal(12) / Decimal(52) case .month: return 1 case .year: return 12 } diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/TestStoreProduct.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/TestStoreProduct.swift index bf630f5926..be1b768150 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/TestStoreProduct.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/TestStoreProduct.swift @@ -174,6 +174,11 @@ struct TestStoreProduct: StoreProductType { return formatter } + private func roundedPrice(_ amount: Decimal) -> Decimal { + (amount as NSDecimalNumber) + .rounding(accordingToBehavior: SubscriptionPeriod.roundingBehavior) as Decimal + } + var dailyPrice: String { guard price != 0, let unit = subscriptionUnit else { return priceFormatter.string(from: 0) ?? "$0.00" @@ -181,12 +186,13 @@ struct TestStoreProduct: StoreProductType { let days: Decimal switch unit { case .day: days = Decimal(subscriptionValue) - case .week: days = Decimal(7 * subscriptionValue) - case .month: days = Decimal(30 * subscriptionValue) + case .week: days = Decimal(365) / Decimal(52) * Decimal(subscriptionValue) + case .month: days = Decimal(365) / Decimal(12) * Decimal(subscriptionValue) case .year: days = Decimal(365 * subscriptionValue) @unknown default: days = 1 } - return priceFormatter.string(from: NSDecimalNumber(decimal: price / days)) ?? "n/a" + let rounded = roundedPrice(price / days) + return priceFormatter.string(from: NSDecimalNumber(decimal: rounded)) ?? "n/a" } var weeklyPrice: String { @@ -195,13 +201,14 @@ struct TestStoreProduct: StoreProductType { } let weeks: Decimal switch unit { - case .day: weeks = Decimal(subscriptionValue) / 7 + case .day: weeks = Decimal(subscriptionValue) * Decimal(52) / Decimal(365) case .week: weeks = Decimal(subscriptionValue) - case .month: weeks = Decimal(4 * subscriptionValue) - case .year: weeks = Decimal(52 * subscriptionValue) + case .month: weeks = Decimal(52) / Decimal(12) * Decimal(subscriptionValue) + case .year: weeks = Decimal(365) / Decimal(7) * Decimal(subscriptionValue) @unknown default: weeks = 1 } - return priceFormatter.string(from: NSDecimalNumber(decimal: price / weeks)) ?? "n/a" + let rounded = roundedPrice(price / weeks) + return priceFormatter.string(from: NSDecimalNumber(decimal: rounded)) ?? "n/a" } var monthlyPrice: String { @@ -210,13 +217,14 @@ struct TestStoreProduct: StoreProductType { } let months: Decimal switch unit { - case .day: months = Decimal(subscriptionValue) / 30 - case .week: months = Decimal(subscriptionValue) / 4 + case .day: months = Decimal(subscriptionValue) * Decimal(12) / Decimal(365) + case .week: months = Decimal(subscriptionValue) * Decimal(12) / Decimal(52) case .month: months = Decimal(subscriptionValue) case .year: months = Decimal(12 * subscriptionValue) @unknown default: months = 1 } - return priceFormatter.string(from: NSDecimalNumber(decimal: price / months)) ?? "n/a" + let rounded = roundedPrice(price / months) + return priceFormatter.string(from: NSDecimalNumber(decimal: rounded)) ?? "n/a" } var yearlyPrice: String { @@ -231,7 +239,8 @@ struct TestStoreProduct: StoreProductType { case .year: years = Decimal(subscriptionValue) @unknown default: years = 1 } - return priceFormatter.string(from: NSDecimalNumber(decimal: price / years)) ?? "n/a" + let rounded = roundedPrice(price / years) + return priceFormatter.string(from: NSDecimalNumber(decimal: rounded)) ?? "n/a" } // MARK: - Trial diff --git a/Tests/SuperwallKitTests/StoreKit/Products/StoreProduct/SubscriptionPeriodPriceTests.swift b/Tests/SuperwallKitTests/StoreKit/Products/StoreProduct/SubscriptionPeriodPriceTests.swift index f31f0c7eaa..9b20019ec9 100644 --- a/Tests/SuperwallKitTests/StoreKit/Products/StoreProduct/SubscriptionPeriodPriceTests.swift +++ b/Tests/SuperwallKitTests/StoreKit/Products/StoreProduct/SubscriptionPeriodPriceTests.swift @@ -30,12 +30,12 @@ struct SubscriptionPeriodPriceTests { @Test("Daily price for monthly subscription") func testDailyPriceForMonthlySubscription() { - // $9.99/month should be ~$0.33/day (9.99 / 30) + // $9.99/month should be ~$0.32/day ((9.99 * 12) / 365) let period = SubscriptionPeriod(value: 1, unit: .month) let dailyPrice = period.pricePerDay(withTotalPrice: Decimal(9.99)) - // 9.99 / 30 = 0.333 rounds down to 0.33 - #expect(dailyPrice == Decimal(string: "0.33")) + // (9.99 * 12) / 365 = 0.328... rounds down to 0.32 + #expect(dailyPrice == Decimal(string: "0.32")) } @Test("Daily price for weekly subscription") @@ -44,7 +44,7 @@ struct SubscriptionPeriodPriceTests { let period = SubscriptionPeriod(value: 1, unit: .week) let dailyPrice = period.pricePerDay(withTotalPrice: Decimal(4.99)) - // 4.99 / 7 = 0.712... rounds down to 0.71 + // 4.99 / (365/52) = 0.710... rounds down to 0.71 #expect(dailyPrice == Decimal(string: "0.71")) } @@ -63,7 +63,7 @@ struct SubscriptionPeriodPriceTests { let period = SubscriptionPeriod(value: 3, unit: .month) let dailyPrice = period.pricePerDay(withTotalPrice: Decimal(24.99)) - // 24.99 / 90 = 0.2776... rounds down to 0.27 + // 24.99 / 91.25 = 0.2738... rounds down to 0.27 #expect(dailyPrice == Decimal(string: "0.27")) } @@ -71,22 +71,43 @@ struct SubscriptionPeriodPriceTests { @Test("Weekly price for yearly subscription") func testWeeklyPriceForYearlySubscription() { - // $99.99/year should be ~$1.92/week (99.99 / 52) + // $99.99/year should be ~$1.91/week (99.99 / (365/7)) let period = SubscriptionPeriod(value: 1, unit: .year) let weeklyPrice = period.pricePerWeek(withTotalPrice: Decimal(99.99)) - // 99.99 / 52 = 1.923... rounds down to 1.92 - #expect(weeklyPrice == Decimal(string: "1.92")) + // 99.99 / (365/7) = 1.917... rounds down to 1.91 + #expect(weeklyPrice == Decimal(string: "1.91")) + } + + @Test("Yearly plan weekly and monthly prices match editor rounding") + func testYearlyPlanEditorParity() { + let period = SubscriptionPeriod(value: 1, unit: .year) + + let weeklyPrice = period.pricePerWeek(withTotalPrice: Decimal(89.99)) + let monthlyPrice = period.pricePerMonth(withTotalPrice: Decimal(89.99)) + + #expect(weeklyPrice == Decimal(string: "1.72")) + #expect(monthlyPrice == Decimal(string: "7.49")) } @Test("Weekly price for monthly subscription") func testWeeklyPriceForMonthlySubscription() { - // $9.99/month should be ~$2.49/week (9.99 / 4) + // $9.99/month should be ~$2.30/week ((9.99 * 12) / 52) let period = SubscriptionPeriod(value: 1, unit: .month) let weeklyPrice = period.pricePerWeek(withTotalPrice: Decimal(9.99)) - // 9.99 / 4 = 2.4975 rounds down to 2.49 - #expect(weeklyPrice == Decimal(string: "2.49")) + // (9.99 * 12) / 52 = 2.305... rounds down to 2.30 + #expect(weeklyPrice == Decimal(string: "2.30")) + } + + @Test("Weekly price annualizes monthly products before dividing by 52") + func testWeeklyPriceAnnualizedFromMonthlySubscription() { + // $29.99/month should be ~$6.92/week ((29.99 * 12) / 52) + let period = SubscriptionPeriod(value: 1, unit: .month) + let weeklyPrice = period.pricePerWeek(withTotalPrice: Decimal(29.99)) + + // (29.99 * 12) / 52 = 6.920... rounds down to 6.92 + #expect(weeklyPrice == Decimal(string: "6.92")) } @Test("Weekly price for weekly subscription") From 27e37cfb5828d36947c611ffb1ad4d9b6c2fe148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yusuf=20To=CC=88r?= <3296904+yusuftor@users.noreply.github.com> Date: Wed, 25 Feb 2026 16:09:14 +0100 Subject: [PATCH 3/4] Make sure original price is matched --- .../StoreProduct/Discount/StoreProductDiscount.swift | 2 +- .../Products/StoreProduct/SK2StoreProduct.swift | 2 +- .../Products/StoreProduct/StripeProductType.swift | 2 +- .../Products/StoreProduct/SubscriptionPeriod.swift | 2 +- .../Products/StoreProduct/TestStoreProduct.swift | 2 +- .../StoreProduct/SubscriptionPeriodPriceTests.swift | 12 ++++++------ 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/Discount/StoreProductDiscount.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/Discount/StoreProductDiscount.swift index 707b32e86e..e9c9d7cb90 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/Discount/StoreProductDiscount.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/Discount/StoreProductDiscount.swift @@ -139,7 +139,7 @@ extension StoreProductDiscount { case .day: return Decimal(52) / Decimal(365) case .week: return 1 case .month: return Decimal(52) / Decimal(12) - case .year: return Decimal(365) / Decimal(7) + case .year: return 52 } case .month: switch subscriptionPeriod.unit { diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift index abb9afe322..15c324b545 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift @@ -292,7 +292,7 @@ struct SK2StoreProduct: StoreProductType { switch subscriptionPeriod.unit { case .year: - periods = Decimal(365) / Decimal(7) * Decimal(numberOfUnits) + periods = Decimal(52 * numberOfUnits) case .month: periods = Decimal(52) / Decimal(12) * Decimal(numberOfUnits) case .week: diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StripeProductType.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StripeProductType.swift index b557eaeeb0..b033095383 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StripeProductType.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StripeProductType.swift @@ -331,7 +331,7 @@ struct StripeProductType: StoreProductType { var periods: Decimal = 1.0 if subscriptionPeriod.unit == .year { - periods = Decimal(365) / Decimal(7) * Decimal(numberOfUnits) + periods = Decimal(52 * numberOfUnits) } if subscriptionPeriod.unit == .month { diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SubscriptionPeriod.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SubscriptionPeriod.swift index ef39e8c3e5..25fc9e1bb0 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SubscriptionPeriod.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SubscriptionPeriod.swift @@ -148,7 +148,7 @@ extension SubscriptionPeriod { case .day: return Decimal(52) / Decimal(365) case .week: return 1 case .month: return Decimal(52) / Decimal(12) - case .year: return Decimal(365) / Decimal(7) + case .year: return 52 } }() * Decimal(value) diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/TestStoreProduct.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/TestStoreProduct.swift index be1b768150..61055b8b94 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/TestStoreProduct.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/TestStoreProduct.swift @@ -204,7 +204,7 @@ struct TestStoreProduct: StoreProductType { case .day: weeks = Decimal(subscriptionValue) * Decimal(52) / Decimal(365) case .week: weeks = Decimal(subscriptionValue) case .month: weeks = Decimal(52) / Decimal(12) * Decimal(subscriptionValue) - case .year: weeks = Decimal(365) / Decimal(7) * Decimal(subscriptionValue) + case .year: weeks = Decimal(52 * subscriptionValue) @unknown default: weeks = 1 } let rounded = roundedPrice(price / weeks) diff --git a/Tests/SuperwallKitTests/StoreKit/Products/StoreProduct/SubscriptionPeriodPriceTests.swift b/Tests/SuperwallKitTests/StoreKit/Products/StoreProduct/SubscriptionPeriodPriceTests.swift index 9b20019ec9..622ff7b8ba 100644 --- a/Tests/SuperwallKitTests/StoreKit/Products/StoreProduct/SubscriptionPeriodPriceTests.swift +++ b/Tests/SuperwallKitTests/StoreKit/Products/StoreProduct/SubscriptionPeriodPriceTests.swift @@ -71,22 +71,22 @@ struct SubscriptionPeriodPriceTests { @Test("Weekly price for yearly subscription") func testWeeklyPriceForYearlySubscription() { - // $99.99/year should be ~$1.91/week (99.99 / (365/7)) + // $99.99/year should be ~$1.92/week (99.99 / 52) let period = SubscriptionPeriod(value: 1, unit: .year) let weeklyPrice = period.pricePerWeek(withTotalPrice: Decimal(99.99)) - // 99.99 / (365/7) = 1.917... rounds down to 1.91 - #expect(weeklyPrice == Decimal(string: "1.91")) + // 99.99 / 52 = 1.923... rounds to 1.92 + #expect(weeklyPrice == Decimal(string: "1.92")) } - @Test("Yearly plan weekly and monthly prices match editor rounding") - func testYearlyPlanEditorParity() { + @Test("Yearly plan weekly and monthly prices use annualized conversion") + func testYearlyPlanAnnualizedConversion() { let period = SubscriptionPeriod(value: 1, unit: .year) let weeklyPrice = period.pricePerWeek(withTotalPrice: Decimal(89.99)) let monthlyPrice = period.pricePerMonth(withTotalPrice: Decimal(89.99)) - #expect(weeklyPrice == Decimal(string: "1.72")) + #expect(weeklyPrice == Decimal(string: "1.73")) #expect(monthlyPrice == Decimal(string: "7.49")) } From 4d61ad86013e5f582701979d53576b6efa165e66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yusuf=20To=CC=88r?= <3296904+yusuftor@users.noreply.github.com> Date: Wed, 25 Feb 2026 16:46:10 +0100 Subject: [PATCH 4/4] Align weekly yearly conversion with editor --- .../StoreKit/Products/StoreProduct/SK2StoreProduct.swift | 2 +- .../StoreKit/Products/StoreProduct/StripeProductType.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift index abb9afe322..15c324b545 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift @@ -292,7 +292,7 @@ struct SK2StoreProduct: StoreProductType { switch subscriptionPeriod.unit { case .year: - periods = Decimal(365) / Decimal(7) * Decimal(numberOfUnits) + periods = Decimal(52 * numberOfUnits) case .month: periods = Decimal(52) / Decimal(12) * Decimal(numberOfUnits) case .week: diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StripeProductType.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StripeProductType.swift index b557eaeeb0..b033095383 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StripeProductType.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StripeProductType.swift @@ -331,7 +331,7 @@ struct StripeProductType: StoreProductType { var periods: Decimal = 1.0 if subscriptionPeriod.unit == .year { - periods = Decimal(365) / Decimal(7) * Decimal(numberOfUnits) + periods = Decimal(52 * numberOfUnits) } if subscriptionPeriod.unit == .month {