Activating workspace...
diff --git a/app/routes/_layout+/settings.subscription.tsx b/app/routes/_layout+/settings.subscription.tsx index 3847bdecf..34d55c1bb 100644 --- a/app/routes/_layout+/settings.subscription.tsx +++ b/app/routes/_layout+/settings.subscription.tsx @@ -19,7 +19,7 @@ import { Prices } from "~/components/subscription/prices"; import SuccessfulSubscriptionModal from "~/components/subscription/successful-subscription-modal"; import { db } from "~/database/db.server"; -import { getUserByID } from "~/modules/user/service.server"; +import { getUserByID, updateUser } from "~/modules/user/service.server"; import { appendToMetaTitle } from "~/utils/append-to-meta-title"; import { ENABLE_PREMIUM_FEATURES } from "~/utils/env"; import { ShelfError, makeShelfError } from "~/utils/error"; @@ -39,7 +39,6 @@ import { getStripeCustomer, getActiveProduct, getCustomerActiveSubscription, - getCustomerTrialSubscription, } from "~/utils/stripe.server"; export async function loader({ context, request }: LoaderFunctionArgs) { @@ -67,24 +66,19 @@ export async function loader({ context, request }: LoaderFunctionArgs) { )) as CustomerWithSubscriptions) : null; - /** Get the trial subscription */ - const trialSubscription = getCustomerTrialSubscription({ customer }); - /** Get a normal subscription */ const subscription = getCustomerActiveSubscription({ customer }); - const activeSubscription = subscription || trialSubscription; - /* Get the prices and products from Stripe */ const prices = await getStripePricesAndProducts(); let activeProduct = null; - if (customer && activeSubscription) { + if (customer && subscription) { /** Get the active subscription ID */ activeProduct = getActiveProduct({ prices, - priceId: activeSubscription?.items.data[0].plan.id || null, + priceId: subscription?.items.data[0].plan.id || null, }); } @@ -94,17 +88,18 @@ export async function loader({ context, request }: LoaderFunctionArgs) { subTitle: "Pick an account plan that fits your workflow.", prices, customer, - subscription: activeSubscription, + subscription: subscription, activeProduct, + usedFreeTrial: user.usedFreeTrial, expiration: { date: new Date( - (activeSubscription?.current_period_end as number) * 1000 + (subscription?.current_period_end as number) * 1000 ).toLocaleDateString(), time: new Date( - (activeSubscription?.current_period_end as number) * 1000 + (subscription?.current_period_end as number) * 1000 ).toLocaleTimeString(), }, - isTrialSubscription: !!activeSubscription?.trial_end, + isTrialSubscription: !!subscription?.trial_end, }) ); } catch (cause) { @@ -125,9 +120,13 @@ export async function action({ context, request }: ActionFunctionArgs) { action: PermissionAction.update, }); - const { priceId } = parseData( + const { priceId, intent, shelfTier } = parseData( await request.formData(), - z.object({ priceId: z.string() }) + z.object({ + priceId: z.string(), + intent: z.enum(["trial", "subscribe"]), + shelfTier: z.enum(["tier_1", "tier_2"]), + }) ); const user = await db.user @@ -170,8 +169,15 @@ export async function action({ context, request }: ActionFunctionArgs) { priceId, domainUrl: getDomainUrl(request), customerId: customerId, + intent, + shelfTier, }); + /** Update the user flag to mark them for having a trial */ + if (intent === "trial" && stripeRedirectUrl) { + await updateUser({ id: userId, usedFreeTrial: true }); + } + return redirect(stripeRedirectUrl); } catch (cause) { const reason = makeShelfError(cause, { userId }); diff --git a/app/routes/api+/stripe-webhook.ts b/app/routes/api+/stripe-webhook.ts index 8942f0264..f00128021 100644 --- a/app/routes/api+/stripe-webhook.ts +++ b/app/routes/api+/stripe-webhook.ts @@ -40,6 +40,7 @@ export async function action({ request }: ActionFunctionArgs) { message: "No subscription ID found", additionalData: { event }, label: "Stripe webhook", + status: 500, }); } @@ -62,6 +63,7 @@ export async function action({ request }: ActionFunctionArgs) { message: "No tier ID found", additionalData: { event, subscription }, label: "Stripe webhook", + status: 500, }); } @@ -79,6 +81,7 @@ export async function action({ request }: ActionFunctionArgs) { message: "Failed to update user tier", additionalData: { customerId, tierId, event }, label: "Stripe webhook", + status: 500, }); }); @@ -95,6 +98,7 @@ export async function action({ request }: ActionFunctionArgs) { message: "No tier ID found", additionalData: { event, subscription }, label: "Stripe webhook", + status: 500, }); } @@ -117,6 +121,7 @@ export async function action({ request }: ActionFunctionArgs) { message: "Failed to update user tier", additionalData: { customerId, tierId, event }, label: "Stripe webhook", + status: 500, }); }); } @@ -135,6 +140,7 @@ export async function action({ request }: ActionFunctionArgs) { message: "No tier ID found", additionalData: { event, subscription }, label: "Stripe webhook", + status: 500, }); } @@ -155,6 +161,7 @@ export async function action({ request }: ActionFunctionArgs) { message: "Failed to update user tier", additionalData: { customerId, tierId, event }, label: "Stripe webhook", + status: 500, }); }); } @@ -163,7 +170,8 @@ export async function action({ request }: ActionFunctionArgs) { } case "customer.subscription.updated": { - const { customerId, tierId } = await getDataFromStripeEvent(event); + const { subscription, customerId, tierId } = + await getDataFromStripeEvent(event); if (!tierId) { throw new ShelfError({ @@ -171,25 +179,36 @@ export async function action({ request }: ActionFunctionArgs) { message: "No tier ID found", additionalData: { event }, label: "Stripe webhook", + status: 500, }); } - /** Update the user's tier in the database */ - await db.user - .update({ - where: { customerId }, - data: { - tierId: tierId as TierId, - }, - }) - .catch((cause) => { - throw new ShelfError({ - cause, - message: "Failed to update user tier", - additionalData: { customerId, tierId, event }, - label: "Stripe webhook", + console.log("subscription", subscription); + + /** Update the user's tier in the database + * + * We only update the tier if the subscription is not paused + * We only do it if the subscription is active because this event gets triggered when cancelling or pausing for example + */ + if (subscription.status === "active") { + console.log("SUBSCRIPTION IS ACTIVE"); + await db.user + .update({ + where: { customerId }, + data: { + tierId: tierId as TierId, + }, + }) + .catch((cause) => { + throw new ShelfError({ + cause, + message: "Failed to update user tier", + additionalData: { customerId, tierId, event }, + label: "Stripe webhook", + status: 500, + }); }); - }); + } return new Response(null, { status: 200 }); } @@ -212,6 +231,7 @@ export async function action({ request }: ActionFunctionArgs) { message: "Failed to delete user subscription", additionalData: { customerId, event }, label: "Stripe webhook", + status: 500, }); }); @@ -229,6 +249,7 @@ export async function action({ request }: ActionFunctionArgs) { message: "No tier ID found", additionalData: { event, subscription }, label: "Stripe webhook", + status: 500, }); } /** Check if its a trial subscription */ @@ -246,6 +267,7 @@ export async function action({ request }: ActionFunctionArgs) { message: "No user found", additionalData: { customerId }, label: "Stripe webhook", + status: 500, }); }); @@ -273,7 +295,7 @@ export async function action({ request }: ActionFunctionArgs) { "Unhandled event. Maybe you forgot to handle this event type? Check the Stripe dashboard.", additionalData: { event }, label: "Stripe webhook", - status: 400, + status: 500, shouldBeCaptured: false, }); } diff --git a/app/routes/qr+/$qrId.tsx b/app/routes/qr+/$qrId.tsx index 319d970d6..0aee50cb2 100644 --- a/app/routes/qr+/$qrId.tsx +++ b/app/routes/qr+/$qrId.tsx @@ -88,7 +88,7 @@ export async function loader({ context, request, params }: LoaderFunctionArgs) { const userOrganizationIds = userOrganizations.map((org) => org.id); const personalOrganization = userOrganizations.find( (org) => org.type === "PERSONAL" - ) as Organization; + ) as Pick