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.

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