mirror of
https://github.com/lukevella/rallly.git
synced 2025-04-28 17:56:37 +02:00
♻️ Make user required in subscription model (#1585)
This commit is contained in:
parent
01758f81ae
commit
aebea5a41c
5 changed files with 87 additions and 92 deletions
|
@ -24,26 +24,60 @@ export async function onCustomerSubscriptionCreated(event: Stripe.Event) {
|
|||
throw new Error("Missing user ID");
|
||||
}
|
||||
|
||||
// Create and update user
|
||||
await prisma.user.update({
|
||||
where: {
|
||||
id: res.data.userId,
|
||||
},
|
||||
data: {
|
||||
subscription: {
|
||||
create: {
|
||||
id: subscription.id,
|
||||
active: isActive,
|
||||
priceId,
|
||||
currency,
|
||||
interval,
|
||||
amount,
|
||||
status: subscription.status,
|
||||
createdAt: toDate(subscription.created),
|
||||
periodStart: toDate(subscription.current_period_start),
|
||||
periodEnd: toDate(subscription.current_period_end),
|
||||
const userId = res.data.userId;
|
||||
|
||||
// Check if user already has a subscription
|
||||
const existingUser = await prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
include: { subscription: true },
|
||||
});
|
||||
|
||||
if (!existingUser) {
|
||||
throw new Error(`User with ID ${userId} not found`);
|
||||
}
|
||||
|
||||
// If user already has a subscription, update it or replace it
|
||||
if (existingUser.subscription) {
|
||||
// Update the existing subscription with new data
|
||||
await prisma.subscription.update({
|
||||
where: { id: existingUser.subscription.id },
|
||||
data: {
|
||||
id: subscription.id,
|
||||
active: isActive,
|
||||
priceId,
|
||||
currency,
|
||||
interval,
|
||||
amount,
|
||||
status: subscription.status,
|
||||
createdAt: toDate(subscription.created),
|
||||
periodStart: toDate(subscription.current_period_start),
|
||||
periodEnd: toDate(subscription.current_period_end),
|
||||
cancelAtPeriodEnd: subscription.cancel_at_period_end,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
// Create a new subscription for the user
|
||||
await prisma.user.update({
|
||||
where: {
|
||||
id: userId,
|
||||
},
|
||||
data: {
|
||||
subscription: {
|
||||
create: {
|
||||
id: subscription.id,
|
||||
active: isActive,
|
||||
priceId,
|
||||
currency,
|
||||
interval,
|
||||
amount,
|
||||
status: subscription.status,
|
||||
createdAt: toDate(subscription.created),
|
||||
periodStart: toDate(subscription.current_period_start),
|
||||
periodEnd: toDate(subscription.current_period_end),
|
||||
cancelAtPeriodEnd: subscription.cancel_at_period_end,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
"./*": "./src/*.ts"
|
||||
},
|
||||
"scripts": {
|
||||
"normalize-subscription-metadata": "dotenv -e ../../.env -- tsx ./src/scripts/normalize-metadata.ts",
|
||||
"checkout-expiry": "dotenv -e ../../.env -- tsx ./src/scripts/checkout-expiry.ts",
|
||||
"subscription-data-sync": "dotenv -e ../../.env -- tsx ./src/scripts/subscription-data-sync.ts",
|
||||
"sync-payment-methods": "dotenv -e ../../.env -- tsx ./src/scripts/sync-payment-methods.ts",
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
/* eslint-disable no-console */
|
||||
/**
|
||||
* This script will go through all subscriptions and add the userId to the metadata.
|
||||
*/
|
||||
import { prisma } from "@rallly/database";
|
||||
|
||||
import { stripe } from "../lib/stripe";
|
||||
|
||||
async function getSubscriptionsWithMissingMetadata(
|
||||
starting_after?: string,
|
||||
): Promise<string[]> {
|
||||
const res: string[] = [];
|
||||
|
||||
const subscriptions = await stripe.subscriptions.list({
|
||||
limit: 100,
|
||||
starting_after,
|
||||
});
|
||||
subscriptions.data.forEach((subscription) => {
|
||||
if (!subscription.metadata.userId) {
|
||||
res.push(subscription.id);
|
||||
}
|
||||
});
|
||||
if (subscriptions.has_more) {
|
||||
return [
|
||||
...res,
|
||||
...(await getSubscriptionsWithMissingMetadata(
|
||||
subscriptions.data[subscriptions.data.length - 1].id,
|
||||
)),
|
||||
];
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
async function normalizeSubscriptionMetadata() {
|
||||
const subscriptions = await getSubscriptionsWithMissingMetadata();
|
||||
|
||||
console.log(
|
||||
`Found ${subscriptions.length} subscriptions with missing metadata`,
|
||||
);
|
||||
|
||||
for (const subscriptionId of subscriptions) {
|
||||
const user = await prisma.user.findFirst({
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
where: {
|
||||
subscriptionId: subscriptionId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
console.log("User not found for subscription", subscriptionId);
|
||||
continue;
|
||||
}
|
||||
|
||||
await stripe.subscriptions.update(subscriptionId, {
|
||||
metadata: {
|
||||
userId: user.id,
|
||||
},
|
||||
});
|
||||
|
||||
console.log("Updated subscription", subscriptionId);
|
||||
}
|
||||
}
|
||||
|
||||
normalizeSubscriptionMetadata();
|
|
@ -0,0 +1,30 @@
|
|||
-- DropForeignKey
|
||||
ALTER TABLE "users" DROP CONSTRAINT "users_subscription_id_fkey";
|
||||
|
||||
-- DropIndex
|
||||
DROP INDEX "users_subscription_id_key";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "subscriptions" ADD COLUMN "user_id" TEXT;
|
||||
|
||||
-- Populate user_id in subscriptions table using data from users table
|
||||
UPDATE "subscriptions" s
|
||||
SET "user_id" = u.id
|
||||
FROM "users" u
|
||||
WHERE u."subscription_id" = s.id;
|
||||
|
||||
-- Delete orphaned subscriptions (subscriptions without a corresponding user)
|
||||
DELETE FROM "subscriptions"
|
||||
WHERE "user_id" IS NULL;
|
||||
|
||||
-- Make user_id NOT NULL after populating data
|
||||
ALTER TABLE "subscriptions" ALTER COLUMN "user_id" SET NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "users" DROP COLUMN "subscription_id";
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "subscriptions_user_id_key" ON "subscriptions"("user_id");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "subscriptions" ADD CONSTRAINT "subscriptions_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
@ -49,7 +49,6 @@ model User {
|
|||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime? @updatedAt @map("updated_at")
|
||||
customerId String? @map("customer_id")
|
||||
subscriptionId String? @unique @map("subscription_id")
|
||||
|
||||
comments Comment[]
|
||||
polls Poll[]
|
||||
|
@ -58,8 +57,7 @@ model User {
|
|||
accounts Account[]
|
||||
participants Participant[]
|
||||
paymentMethods PaymentMethod[]
|
||||
|
||||
subscription Subscription? @relation(fields: [subscriptionId], references: [id], onDelete: SetNull)
|
||||
subscription Subscription? @relation("UserToSubscription")
|
||||
|
||||
@@map("users")
|
||||
}
|
||||
|
@ -111,8 +109,9 @@ model Subscription {
|
|||
periodStart DateTime @map("period_start")
|
||||
periodEnd DateTime @map("period_end")
|
||||
cancelAtPeriodEnd Boolean @default(false) @map("cancel_at_period_end")
|
||||
userId String @unique @map("user_id")
|
||||
|
||||
user User?
|
||||
user User @relation("UserToSubscription", fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("subscriptions")
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue