#lexumi_best-practices

1 messages ยท Page 1 of 1 (latest)

knotty juniperBOT
#

๐Ÿ‘‹ Welcome to your new thread!

โฒ๏ธ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.

โฑ๏ธ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.

๐Ÿ”— This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1348749163357274183

๐Ÿ“ Have more to share? Add more details, code, screenshots, videos, etc. below.

manic wave
#

๐Ÿ‘‹

uncut elk
#

Hello :)

manic wave
#

On this update are there different billing periods?

#

Do you have an example I could look at?

uncut elk
#

The addons can only be booked per month

ive tried to set the quantity to 0 for the last item here but it just send the customer.subscription.updated right away

 if (body.length > 0) {
      for (const addon of body) {
        const subscriptionItemId = addon.subscriptionItemId;
        const subscriptionId = addon.subscriptionId;

        if (!subscriptionId || !subscriptionItemId) continue;

        try {
          // Fetch current subscription to get all items
          const subscription = await stripe.subscriptions.retrieve(subscriptionId);

          // Ensure we have valid items
          if (!subscription.items || !subscription.items.data) continue;

          // Modify only the target item (set quantity to 0)
          const updatedItems = subscription.items.data.map((item) => ({
            id: item.id,
            quantity: item.id === subscriptionItemId ? 0 : item.quantity,
          }));

          // Update the subscription with modified items
          await stripe.subscriptions.update(subscriptionId, {
            proration_behavior: "none",
            items: updatedItems,
          });
        } catch (error) {
          console.error("Error updating subscription:", error);
        }
      }
    }
  }

This was my remove addons test function

manic wave
#

Can you share a Subscription ID that you tested with?

The update will always occur immediately, but the customer won't be charged again until the next billing cycle if you aren't changing the billing period here.

uncut elk
#

sub_1R0lCXG63VjhDQbDm1wsJt7j

that would be the sub id of my test account

#

the update would be fin,e but as we are retrieving the addons from the subscription object that is set from customer.subscription.create/update an immdeiate update would result in the user loosing the addon even though he paid at that month for it

manic wave
#

Gotcha then yeah you want to use a Sub Schedule

#

See the link above

uncut elk
#

So something like this?

if (body.length > 0) {
      for (const addon of body) {
        const subscriptionItemId = addon.subscriptionItemId;
        const subscriptionId = addon.subscriptionId; // Ensure this is available

        if (!subscriptionId || !subscriptionItemId) continue;

        try {
          // Fetch the current subscription
          const subscription = await stripe.subscriptions.retrieve(subscriptionId);

          if (!subscription.items || !subscription.items.data) continue;

          // Check if a Subscription Schedule already exists
          let schedule = await stripe.subscriptionSchedules.list({
            customer: typeof subscription.customer == "string" ? subscription.customer : subscription.customer.id,
            limit: 1,
          });

          let scheduleId = schedule.data.length > 0 ? schedule.data[0].id : null;

          if (!scheduleId) {
            // Create a Subscription Schedule if none exists
            console.log("Creating new Subscription Schedule...");
            const newSchedule = await stripe.subscriptionSchedules.create({
              from_subscription: subscriptionId,
              end_behavior: "release", // Keeps the subscription running after the schedule ends
            });

            scheduleId = newSchedule.id;
          }

          // Modify the schedule to remove the item in the next phase
          console.log("Updating Subscription Schedule...");

          const updatedPhases = [
            {
              items: subscription.items.data.map((item) => ({
                price: item.price.id,
                quantity: item.id === subscriptionItemId ? 0 : item.quantity,
              })),
              start_date: subscription.current_period_end,
            },
          ];

          await stripe.subscriptionSchedules.update(scheduleId, {
            phases: updatedPhases,
          });

          console.log("Subscription Schedule updated successfully.");
        } catch (error) {
          console.error("Error updating subscription schedule:", error);
        }
      }
    }
  }
manic wave
#

You'll need to pass the current phase as phase 0 and the new phase as phase 1

uncut elk
#

shouldn i see the schedules on my subscription in the dashboard?

manic wave
#

There should be an indication, yes.

#

Don't recall exactly what it looks like off the top of my head (we focus on the API and don't use the Dashboard much)

uncut elk
#

cause it seems like the subscription has one, but non is shown

manic wave
#

Can you share the Subscription ID?

uncut elk
#

sub_1R0lCXG63VjhDQbDm1wsJt7j still the same

manic wave
#

Yeah the schedule doesn't have any future phases on it.

#

So that's why it doesn't indicate anything in the Dashboard

uncut elk
#
{
   "phases":{
      "0":{
         "items":{
            "0":{
               "price":"price_1QpVljG63VjhDQbDmIGj7qob",
               "quantity":"3"
            },
            "1":{
               "price":"price_1QmYMgG63VjhDQbD6s07laiK",
               "quantity":"3"
            },
            "2":{
               "price":"price_1QpVu2G63VjhDQbDQxlb6d4o",
               "quantity":"1"
            }
         },
         "start_date":"1741531897"
      }
   }

should i have set

            "2":{
               "price":"price_1QpVu2G63VjhDQbDQxlb6d4o",
               "quantity":"0" <- quantity 0
            }

?

manic wave
#

Phase 0 should be the current items on the Subscription and Phase 1 should be what you want to update to

knotty juniperBOT
uncut elk
#

Okay i think ill need some time to correctly implement this ๐Ÿ˜…

hidden helm
#

Sounds good! As my teammate mentioned, the best thing to do is to use test clocks in test mode to play with this

uncut elk
#

yeah im still trying to get the creaton working..

          const subscriptionSchedule = await stripe.subscriptionSchedules.create({
            customer: customerId,
            start_date: subscription.created,
            end_behavior: 'release',
            phases: [
              {
                items: [
                  {
                    price: '',
                    quantity: ,
                  },
                ],
              },
            ],
          });

When creating the subscription schedule, how do i set the subscription its for? and also do i provide all items of the subscription or just the item that should be updated?

hidden helm
uncut elk
#

does the current phase already exist or do i have to create that somehow?

hidden helm
#

Current phase should already exist. You should see it in the response to your create request

uncut elk
#

so something like this?:

try {
          // Fetch the current subscription
          const subscription = await stripe.subscriptions.retrieve(subscriptionId);

          let customerId: string | null = null;

          if (typeof subscription.customer === "string") {
            customerId = subscription.customer;
          } else if (subscription.customer && "id" in subscription.customer) {
            customerId = subscription.customer.id;
          }

          if (!customerId) {
            console.error("No valid customer found for subscription:", subscriptionId);
            continue;
          }

          const subscriptionSchedule = await stripe.subscriptionSchedules.create({
            from_subscription: subscriptionId,
          });
          console.log(subscriptionSchedule);
          const currentItems = subscription.items.data;

          const updatedItems = currentItems.map((item) => ({
            id: item.id,
            plan: item.plan.id,
            price: item.price.id,
            quantity: item.id === subscriptionItemId ? 0 : item.quantity, // Set to 0 if it matches
          }));

          await stripe.subscriptionSchedules.update(subscriptionSchedule.id, {
            phases: [
              { ...(subscriptionSchedule.phases[0] as Stripe.SubscriptionScheduleUpdateParams.Phase) }, // include phase 0?
              { start_date: subscriptionSchedule.phases[0].end_date, items: updatedItems },
            ],
          });
        } catch (err) {
          console.log(err);
        }

what do i set the end_date of phase 1 to?

hidden helm
#

You don't have to set an end_date

#

You can use iterations to define how many times the price interval should occur

hidden helm
#

@uncut elk any other questions? If not, I'll close this thread. Note that you can still return to #help if anything else comes up during your testing that you need clarification on