Skip to content

Commit

Permalink
Add plan, price, and subscription models
Browse files Browse the repository at this point in the history
  • Loading branch information
ukrocks007 committed Jan 17, 2024
1 parent a2248b5 commit 5d4a7a3
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 145 deletions.
6 changes: 6 additions & 0 deletions models/plan.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { prisma } from '@/lib/prisma';

export const getAllPlans = async () => {
const plans = await prisma.plan.findMany({});
return plans;
};
2 changes: 1 addition & 1 deletion models/stripePrice.ts → models/price.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { prisma } from '@/lib/prisma';

export const getAllPrices = async () => {
const prices = await prisma.stripePrice.findMany({});
const prices = await prisma.price.findMany({});
return prices;
};
6 changes: 0 additions & 6 deletions models/stripeProduct.ts

This file was deleted.

53 changes: 0 additions & 53 deletions models/stripeSubscription.ts

This file was deleted.

50 changes: 50 additions & 0 deletions models/subscription.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { prisma } from '@/lib/prisma';

export const createStripeSubscription = async (
customerId: string,
id: string,
active: boolean,
startDate: Date,
endDate: Date,
priceId: string
) => {
const subscription = await prisma.subscription.create({
data: {
customerId,
id,
active,
startDate,
endDate,
priceId,
},
});
return subscription;
};

export const deleteStripeSubscription = async (id: string) => {
const subscription = await prisma.subscription.deleteMany({
where: {
id,
},
});
return subscription;
};

export const updateStripeSubscription = async (id: string, data: any) => {
const subscription = await prisma.subscription.updateMany({
where: {
id,
},
data,
});
return subscription;
};

export const getByCustomerId = async (customerId: string) => {
const subscription = await prisma.subscription.findMany({
where: {
customerId,
},
});
return subscription;
};
12 changes: 6 additions & 6 deletions pages/api/teams/[slug]/payments/products.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { NextApiRequest, NextApiResponse } from 'next';
import { getStripeCustomerId } from '@/lib/stripe';
import { getSession } from '@/lib/session';
import { throwIfNoTeamAccess } from 'models/team';
import { getAllProducts } from 'models/stripeProduct';
import { getAllPrices } from 'models/stripePrice';
import { getByCustomerId } from 'models/stripeSubscription';
import { getAllPlans } from 'models/plan';
import { getAllPrices } from 'models/price';
import { getByCustomerId } from 'models/subscription';

export default async function handler(
req: NextApiRequest,
Expand Down Expand Up @@ -37,21 +37,21 @@ const handleGET = async (req: NextApiRequest, res: NextApiResponse) => {

const [subscriptions, products, prices] = await Promise.all([
getByCustomerId(customerId),
getAllProducts(),
getAllPlans(),
getAllPrices(),
]);

// create a unified object with prices associated with the product
const productsWithPrices = products.map((product: any) => {
product.prices = prices.filter((price) => price.productId === product.id);
product.prices = prices.filter((price) => price.planId === product.id);
return product;
});

// Subscriptions with product and price
const _subscriptions: any[] = subscriptions.map((subscription: any) => {
const _price = prices.find((p) => p.id === subscription.priceId);
if (!_price) return undefined;
const subscriptionProduct = products.find((p) => p.id === _price.productId);
const subscriptionProduct = products.find((p) => p.id === _price.planId);

return {
...subscription,
Expand Down
2 changes: 1 addition & 1 deletion pages/api/webhooks/stripe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
createStripeSubscription,
deleteStripeSubscription,
updateStripeSubscription,
} from 'models/stripeSubscription';
} from 'models/subscription';

export const config = {
api: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,60 +2,47 @@
ALTER TABLE "Team" ADD COLUMN "stripeCustomerId" TEXT;

-- CreateTable
CREATE TABLE "StripeSubscription" (
CREATE TABLE "Subscription" (
"id" TEXT NOT NULL,
"subscriptionId" TEXT NOT NULL,
"customerId" TEXT NOT NULL,
"priceId" TEXT NOT NULL,
"active" BOOLEAN NOT NULL DEFAULT false,
"startDate" TIMESTAMP(3) NOT NULL,
"endDate" TIMESTAMP(3) NOT NULL,
"cancelAt" TIMESTAMP(3),
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

CONSTRAINT "StripeSubscription_pkey" PRIMARY KEY ("id")
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- CreateTable
CREATE TABLE "StripeProduct" (
CREATE TABLE "Plan" (
"id" TEXT NOT NULL,
"description" TEXT NOT NULL,
"features" TEXT[],
"image" TEXT NOT NULL,
"metadata" JSONB NOT NULL,
"name" TEXT NOT NULL,
"unitLabel" TEXT,
"created" TIMESTAMP(3) NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

CONSTRAINT "StripeProduct_pkey" PRIMARY KEY ("id")
CONSTRAINT "Plan_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "StripePrice" (
CREATE TABLE "Price" (
"id" TEXT NOT NULL,
"billingScheme" TEXT NOT NULL,
"created" TIMESTAMP(3) NOT NULL,
"currency" TEXT NOT NULL,
"customUnitAmount" TEXT,
"livemode" BOOLEAN NOT NULL,
"lookupKey" TEXT,
"metadata" JSONB NOT NULL,
"nickname" TEXT,
"productId" TEXT NOT NULL,
"planId" TEXT NOT NULL,
"recurring" JSONB NOT NULL,
"tiersMode" TEXT NOT NULL,
"type" TEXT NOT NULL,
"unitAmount" TEXT,
"unitAmountDecimal" TEXT,
"created" TIMESTAMP(3) NOT NULL,

CONSTRAINT "StripePrice_pkey" PRIMARY KEY ("id")
CONSTRAINT "Price_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "StripeSubscription_subscriptionId_key" ON "StripeSubscription"("subscriptionId");
CREATE UNIQUE INDEX "Subscription_id_key" ON "Subscription"("id");

-- AddForeignKey
ALTER TABLE "StripePrice" ADD CONSTRAINT "StripePrice_productId_fkey" FOREIGN KEY ("productId") REFERENCES "StripeProduct"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "Price" ADD CONSTRAINT "Price_planId_fkey" FOREIGN KEY ("planId") REFERENCES "Plan"("id") ON DELETE CASCADE ON UPDATE CASCADE;
59 changes: 24 additions & 35 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -137,49 +137,38 @@ model ApiKey {
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
}

model StripeSubscription {
id String @id @default(uuid())
subscriptionId String @unique
customerId String
priceId String
active Boolean @default(false)
startDate DateTime
endDate DateTime
cancelAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @default(now())
model Subscription {
id String @unique
customerId String
priceId String
active Boolean @default(false)
startDate DateTime
endDate DateTime
cancelAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @default(now())
}

model StripeProduct {
id String @id @default(uuid())
model Plan {
id String @id @default(uuid())
description String
features String[]
image String
metadata Json
name String
unitLabel String?
created DateTime
createdAt DateTime @default(now())
updatedAt DateTime @default(now())
StripePrice StripePrice[]
createdAt DateTime @default(now())
updatedAt DateTime @default(now())
Price Price[]
}

model StripePrice {
id String @id @default(uuid())
billingScheme String
created DateTime
currency String
customUnitAmount String?
livemode Boolean
lookupKey String?
metadata Json
nickname String?
productId String
recurring Json
tiersMode String
type String
unitAmount String?
unitAmountDecimal String?
model Price {
id String @id @default(uuid())
billingScheme String
currency String
planId String
recurring Json
type String
created DateTime
product StripeProduct @relation(fields: [productId], references: [id], onDelete: Cascade)
plan Plan @relation(fields: [planId], references: [id], onDelete: Cascade)
}
28 changes: 8 additions & 20 deletions syncStripe.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ process.on('uncaughtException', (error) => {

async function printStats(prisma) {
const [productCount, priceCount] = await Promise.all([
prisma.stripeProduct.count(),
prisma.stripePrice.count(),
prisma.plan.count(),
prisma.price.count(),
]);

console.log('Products synced:', productCount);
Expand All @@ -63,9 +63,9 @@ async function printStats(prisma) {

async function cleanup(prisma) {
// delete all prices from the database
await prisma.stripePrice.deleteMany({});
await prisma.price.deleteMany({});
// Delete all products and prices from the database
await prisma.stripeProduct.deleteMany({});
await prisma.plan.deleteMany({});
}

function getStripeInstance() {
Expand All @@ -86,25 +86,15 @@ function getStripeInstance() {
async function seedPrices(prices, prisma) {
for (const data of prices) {
try {
await prisma.stripePrice.create({
await prisma.price.create({
data: {
id: data.id,
billingScheme: data.billing_scheme,
created: new Date(data.created * 1000),
currency: data.currency,
customUnitAmount: data.custom_unit_amount
? data.custom_unit_amount.toString()
: null,
livemode: data.livemode,
lookupKey: data.lookup_key,
metadata: data.metadata,
nickname: data.nickname,
productId: data.product,
planId: data.product,
recurring: data.recurring,
tiersMode: data.tiers_mode ? data.tiers_mode.toString() : '',
type: data.type,
unitAmount: data.unit_amount ? data.unit_amount.toString() : null,
unitAmountDecimal: data.unit_amount_decimal,
created: new Date(data.created * 1000),
},
});
} catch (error) {
Expand All @@ -116,15 +106,13 @@ async function seedPrices(prices, prisma) {
async function seedProducts(products, prisma) {
for (const data of products) {
try {
await prisma.stripeProduct.create({
await prisma.plan.create({
data: {
id: data.id,
description: data.description || '',
features: (data.features || []).map((a) => a.name),
image: data.images.length > 0 ? data.images[0] : '',
metadata: data.metadata,
name: data.name,
unitLabel: data.unit_label,
created: new Date(data.created * 1000),
},
});
Expand Down

0 comments on commit 5d4a7a3

Please sign in to comment.