get to prod tasks
This commit is contained in:
@@ -8,6 +8,8 @@ import {
|
||||
CancelSubscriptionSchema,
|
||||
ReactivateSubscriptionSchema,
|
||||
ListInvoicesSchema,
|
||||
RequestFeatureTrialSchema,
|
||||
UpgradeFromTrialSchema,
|
||||
} from "../schemas/billing";
|
||||
import {
|
||||
getOrCreateCustomer,
|
||||
@@ -16,18 +18,86 @@ import {
|
||||
cancelSubscription,
|
||||
reactivateSubscription,
|
||||
listInvoices,
|
||||
mapStripeProductToTier,
|
||||
} from "~/server/services/billing.service";
|
||||
import { db } from "~/server/db";
|
||||
import { subscriptions } from "~/server/db/schema/subscription";
|
||||
import { stripe } from "~/server/stripe";
|
||||
import {
|
||||
getEffectiveTier,
|
||||
getActiveTrials,
|
||||
createFeatureTrial,
|
||||
} from "~/server/lib/tier";
|
||||
|
||||
export const billingRouter = createTRPCRouter({
|
||||
getSubscription: protectedProcedure.query(async ({ ctx }) => {
|
||||
const sub = await db.query.subscriptions.findFirst({
|
||||
where: eq(subscriptions.userId, ctx.user.id),
|
||||
});
|
||||
return sub ?? null;
|
||||
if (!sub) return null;
|
||||
const trials = await getActiveTrials(ctx.user.id);
|
||||
return {
|
||||
...sub,
|
||||
effectiveTier: getEffectiveTier(sub.tier as "basic" | "plus" | "premium", sub.status as "active" | "trialing"),
|
||||
isTrialing: sub.status === "trialing",
|
||||
trials,
|
||||
};
|
||||
}),
|
||||
|
||||
requestFeatureTrial: protectedProcedure
|
||||
.input(wrap(RequestFeatureTrialSchema))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const sub = await db.query.subscriptions.findFirst({
|
||||
where: eq(subscriptions.userId, ctx.user.id),
|
||||
});
|
||||
|
||||
if (!sub || sub.status !== "active" || sub.tier !== "basic") {
|
||||
throw new TRPCError({
|
||||
code: "FORBIDDEN",
|
||||
message: "Feature trials are available for active Basic subscribers",
|
||||
});
|
||||
}
|
||||
|
||||
const trial = await createFeatureTrial(ctx.user.id, input.feature, 7);
|
||||
return { trial };
|
||||
}),
|
||||
|
||||
upgradeFromTrial: protectedProcedure
|
||||
.input(wrap(UpgradeFromTrialSchema))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const sub = await db.query.subscriptions.findFirst({
|
||||
where: eq(subscriptions.userId, ctx.user.id),
|
||||
});
|
||||
|
||||
if (!sub || sub.status !== "trialing") {
|
||||
throw new TRPCError({
|
||||
code: "FORBIDDEN",
|
||||
message: "No active trial to upgrade from",
|
||||
});
|
||||
}
|
||||
|
||||
const priceMap: Record<string, string | undefined> = {
|
||||
basic: process.env.STRIPE_PRICE_BASIC,
|
||||
plus: process.env.STRIPE_PRICE_PLUS,
|
||||
premium: process.env.STRIPE_PRICE_PREMIUM,
|
||||
};
|
||||
|
||||
const priceId = priceMap[input.plan];
|
||||
if (!priceId) {
|
||||
throw new TRPCError({ code: "BAD_REQUEST", message: "Invalid plan" });
|
||||
}
|
||||
|
||||
// Cancel current trial subscription
|
||||
await stripe.subscriptions.cancel(sub.stripeId!);
|
||||
|
||||
return createCheckoutSession(
|
||||
ctx.user.id,
|
||||
ctx.user.email,
|
||||
priceId,
|
||||
input.returnUrl,
|
||||
);
|
||||
}),
|
||||
|
||||
createCheckoutSession: protectedProcedure
|
||||
.input(wrap(CreateCheckoutSessionSchema))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
|
||||
@@ -21,3 +21,12 @@ export const ListInvoicesSchema = object({
|
||||
limit: optional(string(), "10"),
|
||||
startingAfter: optional(string()),
|
||||
});
|
||||
|
||||
export const RequestFeatureTrialSchema = object({
|
||||
feature: picklist(["voiceprint", "hometitle", "removebrokers"]),
|
||||
});
|
||||
|
||||
export const UpgradeFromTrialSchema = object({
|
||||
plan: picklist(["basic", "plus", "premium"]),
|
||||
returnUrl: string([url()]),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user