Skip to content

Commit

Permalink
billing: added api to migrate Pro users to hacker plan + pay as you go
Browse files Browse the repository at this point in the history
  • Loading branch information
gioelecerati committed Jul 7, 2023
1 parent 49f0aae commit 2f19f6b
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 19 deletions.
145 changes: 143 additions & 2 deletions packages/api/src/controllers/stripe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,21 @@ export const reportUsage = async (req, adminToken) => {
}
);

const [oldProPlanUsers] = await db.user.find(
[
sql`users.data->>'oldProPlan' = true AND users.data->>'stripeProductId' IN ('hacker_1','prod_O9XuIjn7EqYRVW')`,
],
{
limit: 9999999999,
useReplica: true,
}
);

// Join oldProPlanUsers and users
const payAsYouGoUsers = [...users, ...oldProPlanUsers];

let updatedUsers = [];
for (const user of users) {
for (const user of payAsYouGoUsers) {
const userSubscription = await req.stripe.subscriptions.retrieve(
user.stripeCustomerSubscriptionId
);
Expand Down Expand Up @@ -425,7 +438,135 @@ app.post("/migrate-personal-users", async (req, res) => {
stripeCustomerId: user.stripeCustomerId,
stripeProductId: "prod_O9XuIjn7EqYRVW",
stripeCustomerSubscriptionId: subscription.id,
stripeCustomerPaymentMethodId: null,
});

migratedUsers.push(user.email);

await sleep(200);
}
}
}

cursor = newCursor;
}

res.json(migratedUsers);
});

// Migrate Pro users to hacker with pay as you go
app.post("/migrate-pro-users", async (req, res) => {
if (req.config.stripeSecretKey != req.body.stripeSecretKey) {
res.status(403);
return res.json({ errors: ["unauthorized"] });
}

const batchSize = 100;
let cursor = null;
let users = [];
let keepGoing = true;

let migratedUsers = [];

while (keepGoing) {
const [currentUsers, newCursor] = await db.user.find(
[sql`users.data->>'stripeProductId' = 'prod_1'`],
{
cursor: cursor,
limit: batchSize,
useReplica: false,
}
);

if (currentUsers.length === 0) {
keepGoing = false;
continue;
}

users = users.concat(currentUsers);

for (let index = 0; index < currentUsers.length; index++) {
let user = currentUsers[index];

const { data } = await req.stripe.customers.list({
email: user.email,
});

if (data.length > 0) {
if (
user.stripeProductId === "prod_1" &&
user.newStripeProductId !== "growth_1" &&
user.newStripeProductId !== "scale_1"
) {
const items = await req.stripe.prices.list({
lookup_keys: products["prod_O9XuIjn7EqYRVW"].lookupKeys,
});
let subscription;

try {
subscription = await req.stripe.subscriptions.retrieve(
user.stripeCustomerSubscriptionId
);
} catch (e) {
console.log(`
Unable to migrate pro user - subscription not found for user=${user.id} email=${user.email} subscriptionId=${user.stripeCustomerSubscriptionId}
`);
continue;
}

if (subscription.status != "active") {
console.log(`
Unable to migrate pro user - user=${user.id} has a status=${subscription.status} subscription
`);
continue;
}

const subscriptionItems = await req.stripe.subscriptionItems.list({
subscription: user.stripeCustomerSubscriptionId,
});

let payAsYouGoItems = [];
if (products[user.stripeProductId].payAsYouGo) {
// Get the prices for the pay as you go product
const payAsYouGoPrices = await req.stripe.prices.list({
lookup_keys: products["pay_as_you_go_1"].lookupKeys,
});

// Map the prices to the additional items array
payAsYouGoItems = payAsYouGoPrices.data.map((item) => ({
price: item.id,
}));
}

subscription = await req.stripe.subscriptions.update(
user.stripeCustomerSubscriptionId,
{
billing_cycle_anchor: "now",
cancel_at_period_end: false,
items: [
...subscriptionItems.data.map((item) => {
// Check if the item is metered
const isMetered =
item.price.recurring.usage_type === "metered";
return {
id: item.id,
deleted: true,
clear_usage: isMetered ? true : undefined, // If metered, clear usage
price: item.price.id,
};
}),
...items.data.map((item) => ({
price: item.id,
})),
...payAsYouGoItems,
],
}
);

await db.user.update(user.id, {
stripeCustomerId: user.stripeCustomerId,
stripeProductId: "prod_O9XuIjn7EqYRVW",
stripeCustomerSubscriptionId: subscription.id,
oldProPlan: true,
});

migratedUsers.push(user.email);
Expand Down
3 changes: 3 additions & 0 deletions packages/api/src/schema/db-schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1068,6 +1068,9 @@ components:
- prod_O9XtHhI6rbTT1B
- prod_O9XtcfOSMjSD5L
- prod_O9XuWMU1Up6QKf
oldProPlan:
type: boolean
default: false
stripeCustomerId:
type: string
example: cus_Jv6KvgT0DCH8HU
Expand Down
34 changes: 17 additions & 17 deletions packages/www/public/sitemap-0.xml
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
<url><loc>https://livepeer.studio</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-06T17:50:33.992Z</lastmod></url>
<url><loc>https://livepeer.studio/contact</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-06T17:50:33.992Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-06T17:50:33.992Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard/assets</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-06T17:50:33.992Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard/billing</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-06T17:50:33.992Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard/billing/plans</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-06T17:50:33.992Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard/developers/api-keys</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-06T17:50:33.992Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard/developers/signing-keys</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-06T17:50:33.992Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard/developers/webhooks</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-06T17:50:33.992Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard/sessions</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-06T17:50:33.992Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard/stream-health</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-06T17:50:33.992Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard/streams</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-06T17:50:33.992Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard/usage</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-06T17:50:33.992Z</lastmod></url>
<url><loc>https://livepeer.studio/forgot-password</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-06T17:50:33.992Z</lastmod></url>
<url><loc>https://livepeer.studio/register</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-06T17:50:33.992Z</lastmod></url>
<url><loc>https://livepeer.studio/reset-password</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-06T17:50:33.992Z</lastmod></url>
<url><loc>https://livepeer.studio/verify</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-06T17:50:33.992Z</lastmod></url>
<url><loc>https://livepeer.studio</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-07T16:37:14.836Z</lastmod></url>
<url><loc>https://livepeer.studio/contact</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-07T16:37:14.836Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-07T16:37:14.836Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard/assets</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-07T16:37:14.836Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard/billing</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-07T16:37:14.836Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard/billing/plans</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-07T16:37:14.836Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard/developers/api-keys</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-07T16:37:14.836Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard/developers/signing-keys</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-07T16:37:14.836Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard/developers/webhooks</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-07T16:37:14.836Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard/sessions</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-07T16:37:14.836Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard/stream-health</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-07T16:37:14.836Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard/streams</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-07T16:37:14.836Z</lastmod></url>
<url><loc>https://livepeer.studio/dashboard/usage</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-07T16:37:14.836Z</lastmod></url>
<url><loc>https://livepeer.studio/forgot-password</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-07T16:37:14.836Z</lastmod></url>
<url><loc>https://livepeer.studio/register</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-07T16:37:14.836Z</lastmod></url>
<url><loc>https://livepeer.studio/reset-password</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-07T16:37:14.836Z</lastmod></url>
<url><loc>https://livepeer.studio/verify</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2023-07-07T16:37:14.836Z</lastmod></url>
</urlset>

0 comments on commit 2f19f6b

Please sign in to comment.