Skip to content

bug(billing): ListAllPlans and ListPlans omit plans that have no products #1832

Description

@rohilsurana

What

BillingPlanRepository.ListWithProducts (internal/store/postgres/billing_plan_repository.go, the join near line 357) INNER JOINs billing_products on plan.id = ANY(product.plan_ids). A plan with no products never appears in the result. UpsertPlans allows creating a plan with an empty product set, so such plans can exist.

This affects both FrontierService.ListPlans and the new AdminService.ListAllPlans. The point of ListAllPlans (and the future BillingPlan reconcile export) is to surface every plan, including misconfigured or product-less ones, so this is a correctness gap for that endpoint.

Fix

Change the INNER JOIN to a LEFT JOIN and tolerate NULL product columns:

  • PlanProductRow's product fields are non-nullable today (string, time.Time, BehaviorConfig, pq.StringArray), so scanning NULLs from a LEFT JOIN fails. The fields need to become nullable, or the SELECT needs COALESCE, and the row loop must skip appending an empty product.
  • This is a shared read path used by ListPlans too, so its behavior changes as well (product-less active plans start appearing).
  • Ship it with a Postgres/integration test for a product-less plan. No seed today creates one.

Context

Deferred from the #1830 review to keep that PR focused and low-risk. The rework touches shared read code and cannot be unit-tested without Postgres, and the BillingPlan reconciler that needs this does not exist yet.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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