Treat both-null entitlements as same scope in stripe-reuse matcher

This commit is contained in:
Owen Greenhalgh
2026-05-12 17:01:46 +01:00
committed by John Yeo
parent b56239b3bb
commit 9f346dca06
2 changed files with 38 additions and 0 deletions

View File

@@ -132,6 +132,41 @@ describe("getPriceStripeReuseLevel", () => {
expect(level).toBe("none");
});
test("returns full when both usage prices share configs and lack paired entitlements", () => {
const orphan = usagePrice({ id: "pr_orphan", entitlement_id: null });
const orphanNew = usagePrice({ id: "pr_orphan_new", entitlement_id: null });
const level = getPriceStripeReuseLevel({
newPrice: orphanNew,
candidatePrice: orphan,
newEntitlements: [],
candidateEntitlements: [],
});
expect(level).toBe("full");
});
test("returns stripeProductOnly when both usage prices lack entitlements but configs differ", () => {
const cheaper = usagePrice({
id: "pr_orphan_cheaper",
entitlement_id: null,
config: {
...usageConfig,
usage_tiers: [{ amount: 0.05, to: TierInfinite }],
},
});
const original = usagePrice({ id: "pr_orphan", entitlement_id: null });
const level = getPriceStripeReuseLevel({
newPrice: cheaper,
candidatePrice: original,
newEntitlements: [],
candidateEntitlements: [],
});
expect(level).toBe("stripeProductOnly");
});
test("returns full for matching fixed prices regardless of paired entitlements", () => {
const fixed: Price = {
id: "pr_base",

View File

@@ -77,6 +77,8 @@ export const getPriceStripeReuseLevel = ({
entitlements: candidateEntitlements,
});
// Both null = same (null) entity scope; both have ents = compare them.
if (!newEnt && !candidateEnt) return "full";
if (!newEnt || !candidateEnt) return "none";
if (entsAreSame(candidateEnt, newEnt)) return "full";
}
@@ -98,6 +100,7 @@ export const getPriceStripeReuseLevel = ({
entitlements: candidateEntitlements,
});
if (!newEnt && !candidateEnt) return "stripeProductOnly";
if (!newEnt || !candidateEnt) return "none";
if (newEnt.entity_feature_id !== candidateEnt.entity_feature_id) {
return "none";