Fix day↔week price conversion#409
Open
yusuftor wants to merge 2 commits into
Open
Conversation
SubscriptionPeriod converted between days and weeks via a 52/365 factor. But 52 weeks is only 364 days, so a 7-day period resolved to ~0.997 weeks instead of exactly 1 — inflating a 7-day product's weekly price and skewing a week product's daily price (e.g. a $7.00/week product reported $0.99/day instead of the exact $1.00). 7 days is exactly 1 week. Use the exact ratio in both directions: - SubscriptionPeriod.pricePerDay .week: 365/52 -> 7 - SubscriptionPeriod.pricePerWeek .day: 52/365 -> 1/7 - RawStoreProduct.periodsPerUnit (trial path): the same two day↔week entries. Month↔year was already exact (12); week/month and week/year stay as conventional approximations — those aren't whole-number relationships. Mirrors the same fix in the iOS SDK and the web editor so all three agree. Adds two regression tests (a 7-day period's weekly price equals the price; a weekly product's daily price divides by exactly 7) in the active test region — the existing period-price tests are still inside the disabled "TODO: Re-enable in CI" block. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two issues in the new regression tests: - BigDecimal(6.99) calls the double constructor, which stores the inexact IEEE-754 value rather than exactly 6.99 — the two sides of the comparison could resolve to different values. Use the String constructor for exact decimals. - Kotlin's assert() is compiled to a no-op unless the JVM runs with -ea, so the tests could silently pass even on a regression. Switch to JUnit's assertEquals, which always evaluates. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Android counterpart to the iOS SDK fix (superwall/Superwall-iOS#473) and the editor fix (superwall/paywall-next#3178).
SubscriptionPeriodconverted between days and weeks via a52/365factor — but 52 weeks is only 364 days, so a 7-day period resolved to ~0.997 weeks instead of exactly 1. That inflates a 7-day product's weekly price and skews a week product's daily price (e.g. a$7.00/weekproduct reports$0.99/dayinstead of the exact$1.00).7 days is exactly 1 week, so the conversion should be exact.
Scope note
Android does not have the iOS variant of the bug where the price getters bypassed
normalized()— Android'sRawStoreProductprice getters already compute off the normalizedSubscriptionPeriod, andSubscriptionPeriod.from()collapses whole-week day-counts to weeks. So the most visible symptom (weeklyPriceof a weekly product) does not reproduce on Android. What this fixes is the residual error:dailyPriceof weekly products, odd day-count products, and trial per-unit prices — all of which would otherwise disagree with the now-fixed iOS SDK and editor.Changes
SubscriptionPeriod.kt—pricePerDay.week:365/52→7;pricePerWeek.day:52/365→1/7.RawStoreProduct.kt—periodsPerUnit(trial-price path): the same two day↔week entries.12); week↔month / week↔year stay as conventional approximations.Tests
Added two regression tests to the active test region of
SubscriptionPeriodUnitTest:pricePerWeekequals the price;pricePerDaydivides by exactly 7 ($7.00/week→$1.00/day, which the old365/52got wrong as$0.99).Note: the existing
singleDaily/multiDaily/… period-price tests are still inside the pre-existing/* TODO: Re-enable these in CI */block — left untouched (some of them also carry unrelated stale month↔week expectations). 3 tests run, 0 failures.🤖 Generated with Claude Code
Greptile Summary
This PR fixes the day↔week conversion factor in
SubscriptionPeriod.pricePerDay/pricePerWeekand inRawStoreProduct.periodsPerUnit, replacing the approximate365/52(≈7.019) and52/365(≈0.1425) factors with the exact7and1/7.SubscriptionPeriod.kt:pricePerDayfor a weekly product now usesBigDecimal(7)(days per week);pricePerWeekfor a daily product now uses1/7(weeks per day).RawStoreProduct.kt: The same two day↔week entries inperiodsPerUnitare updated to match.SubscriptionPeriodUnitTest.kt: Two new regression tests useBigDecimal(String)andassertEqualscorrectly and are placed in the active (non-commented) test region.Confidence Score: 5/5
Safe to merge — the change is a narrow, well-scoped arithmetic correction with no side effects on unrelated paths.
The two changed constants (365/52 → 7 and 52/365 → 1/7) are mathematically exact, applied consistently in both SubscriptionPeriod and RawStoreProduct, and directly verified by two new regression tests that use the correct BigDecimal(String) constructor and assertEquals. Month↔year and week↔month conversions are left untouched as documented conventional approximations.
No files require special attention.
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A[SubscriptionPeriod] --> B{pricePerDay} A --> C{pricePerWeek} B -->|unit = day| D["÷ 1 × value"] B -->|unit = week| E["÷ 7 × value ✅ was: 365÷52"] B -->|unit = month| F["÷ 365÷12 × value"] B -->|unit = year| G["÷ 365 × value"] C -->|unit = day| H["÷ 1÷7 × value ✅ was: 52÷365"] C -->|unit = week| I["÷ 1 × value"] C -->|unit = month| J["÷ 52÷12 × value"] C -->|unit = year| K["÷ 52 × value"] L[RawStoreProduct.periodsPerUnit] --> M{outer unit} M -->|day| N{trial unit} M -->|week| O{trial unit} N -->|week| P["7 ✅ was: 365÷52"] O -->|day| Q["1÷7 ✅ was: 52÷365"]Reviews (2): Last reviewed commit: "Use exact BigDecimal and assertEquals in..." | Re-trigger Greptile