fix: detect billing plan across all active Stripe subscriptions

getCurrentPlanForUser and getProducts only inspected subscriptions.data[0],
so a customer with more than one active Stripe subscription (e.g. Startup
plus a separately purchased additional server) could have their plan
resolved from the wrong subscription, resulting in currentPlan !== "startup"
and the HubSpot chat bubble not rendering.
This commit is contained in:
Mauricio Siu 2026-08-30 18:08:35 -06:00
parent cabfe2e81e
commit e79239a100
2 changed files with 41 additions and 28 deletions

View File

@ -80,38 +80,52 @@ export const stripeRouter = createTRPCRouter({
let currentPlan: CurrentPlan = "legacy";
let isAnnualCurrent = false;
let currentPriceAmount: number | null = null;
const activeSub = subscriptions.data[0];
if (activeSub) {
const priceIds = activeSub.items.data.map(
(item) => (item.price as Stripe.Price).id,
if (subscriptions.data.length > 0) {
const matchedSub = subscriptions.data.find((sub) =>
sub.items.data.some(
(item) =>
(item.price as Stripe.Price).id === STARTUP_BASE_PRICE_MONTHLY_ID ||
(item.price as Stripe.Price).id === STARTUP_BASE_PRICE_ANNUAL_ID,
),
);
if (
priceIds.some(
(id) =>
id === STARTUP_BASE_PRICE_MONTHLY_ID ||
id === STARTUP_BASE_PRICE_ANNUAL_ID,
)
) {
const hobbySub = subscriptions.data.find((sub) =>
sub.items.data.some(
(item) =>
(item.price as Stripe.Price).id === HOBBY_PRICE_MONTHLY_ID ||
(item.price as Stripe.Price).id === HOBBY_PRICE_ANNUAL_ID,
),
);
const legacySub = subscriptions.data.find((sub) =>
sub.items.data.some((item) =>
LEGACY_PRICE_IDS.includes((item.price as Stripe.Price).id),
),
);
const activeSub = matchedSub ?? hobbySub ?? legacySub;
if (matchedSub) {
currentPlan = "startup";
} else if (
priceIds.some(
(id) => id === HOBBY_PRICE_MONTHLY_ID || id === HOBBY_PRICE_ANNUAL_ID,
)
) {
} else if (hobbySub) {
currentPlan = "hobby";
} else if (priceIds.some((id) => LEGACY_PRICE_IDS.includes(id))) {
} else if (legacySub) {
currentPlan = "legacy";
}
const firstPrice = activeSub.items.data[0]?.price as
const firstPrice = activeSub?.items.data[0]?.price as
| Stripe.Price
| undefined;
isAnnualCurrent = firstPrice?.recurring?.interval === "year";
const totalCents = activeSub.items.data.reduce((sum, item) => {
const price = item.price as Stripe.Price;
const amount = price.unit_amount ?? 0;
const qty = item.quantity ?? 1;
return sum + amount * qty;
}, 0);
const totalCents = subscriptions.data.reduce(
(subTotal, sub) =>
subTotal +
sub.items.data.reduce((sum, item) => {
const price = item.price as Stripe.Price;
const amount = price.unit_amount ?? 0;
const qty = item.quantity ?? 1;
return sum + amount * qty;
}, 0),
0,
);
currentPriceAmount = totalCents / 100;
}

View File

@ -27,11 +27,10 @@ export const getCurrentPlanForUser = async (
status: "active",
expand: ["data.items.data.price"],
});
const activeSub = subscriptions.data[0];
if (!activeSub) return null;
if (subscriptions.data.length === 0) return null;
const priceIds = activeSub.items.data.map(
(item) => (item.price as Stripe.Price).id,
const priceIds = subscriptions.data.flatMap((sub) =>
sub.items.data.map((item) => (item.price as Stripe.Price).id),
);
if (