Skip to content

Add listSubscriptionsByOrgId query #10

@joacoiannuzzi

Description

@joacoiannuzzi

Summary

The component has getSubscriptionByOrgId which returns a single subscription, but there's no listSubscriptionsByOrgId to return all subscriptions for an organization.

This is problematic because getSubscriptionByOrgId uses .first() which returns subscriptions in creation order. If an org has both a canceled subscription (created first) and an active subscription (created later), the query returns the canceled one instead of the active one.

Current API

// Returns first subscription found (by creation time), regardless of status
export const getSubscriptionByOrgId = query({
  args: { orgId: v.string() },
  returns: v.union(subscriptionValidator, v.null()),
  handler: async (ctx, args) => {
    const subscription = await ctx.db
      .query("subscriptions")
      .withIndex("by_org_id", (q) => q.eq("orgId", args.orgId))
      .first();  // <-- Returns first, could be canceled
    // ...
  },
});

Requested Addition

Add listSubscriptionsByOrgId (similar to listSubscriptionsByUserId):

export const listSubscriptionsByOrgId = query({
  args: { orgId: v.string() },
  returns: v.array(subscriptionValidator),
  handler: async (ctx, args) => {
    const subscriptions = await ctx.db
      .query("subscriptions")
      .withIndex("by_org_id", (q) => q.eq("orgId", args.orgId))
      .collect();
    return subscriptions.map(({ _id, _creationTime, ...data }) => data);
  },
});

Use Case

When building organization-based billing, you need to find the active subscription for an org, not just the first one created. With listSubscriptionsByOrgId, we can filter by status:

const allOrgSubscriptions = await ctx.runQuery(
  components.stripe.public.listSubscriptionsByOrgId,
  { orgId }
);
const activeSubscription = allOrgSubscriptions.find(
  (sub) => ["active", "trialing", "past_due"].includes(sub.status)
);

Current Workaround

We have to:

  1. Call getSubscriptionByOrgId to get any subscription
  2. If it's not active, use its stripeCustomerId to call listSubscriptions
  3. Filter by orgId and status manually

This is inefficient and error-prone.

Environment

  • @convex-dev/stripe version: 0.1.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions