Skip to content

feat(catalog): create the catalog_plans storage - #6288

Merged
rsempe merged 4 commits into
mainfrom
bil-643
Sep 4, 2026
Merged

feat(catalog): create the catalog_plans storage#6288
rsempe merged 4 commits into
mainfrom
bil-643

Conversation

@rsempe

@rsempe rsempe commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

What this is

The v2 catalog gets its own plan table, so a product-catalog plan stops being a pricing_type: product_catalog row on the shared plans table (carrying nil interval/amount_cents/pay_in_advance).

Changes

  • catalog_plans table — the plan envelope only: name, code, invoice_display_name, description, currency, organization_id, timestamps, deleted_at. No legacy pricing columns, and no self-reference (catalog plans don't use plan parent/child overrides — the dive-in's open question, resolved).
  • CatalogPlan model — paper-trailed, soft-deletable (default_scope { kept }), validates name/code presence and currency inclusion.
  • Partial unique index on (organization_id, code) WHERE deleted_at IS NULL — code unique per org among kept rows.

Not in scope

No product_category_id (plans link to categories through products, not a column) and no pending_deletion yet — added later if the catalog destroy flow needs it.

@lago-claude-ai-agent

Copy link
Copy Markdown
Contributor

Automated pre-review (advisory, not a required check) — verdict: HOLD · CI green

HOLD — duplicate catalog-plan codes bypass model validation and raise ActiveRecord::RecordNotUnique, unlike sibling catalog resources.

  • Add the kept-row, organization-scoped code uniqueness validation and cover same-organization rejection plus cross-organization reuse.
  • Add Organization#catalog_plans and its association spec so this organization-owned resource supports the standard scoped access pattern.

@lago-claude-ai-agent

Copy link
Copy Markdown
Contributor

Automated pre-review (advisory, not a required check) — verdict: PASS · CI green

PASS — The model, migration, live-row uniqueness, soft deletion, organization association, factory, and focused specs are consistent with the existing catalog patterns.

Non-blocking: the existing CatalogPlans GraphQL mutations still use legacy Plan, so this is currently foundation-only. The specs could not be executed here because the required lago command is unavailable.

@tiagolupepic tiagolupepic left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

Comment thread app/models/catalog_plan.rb Outdated
PR 0 of the catalog-plans split (Dive-In 6): the v2 catalog gets its own
plan table so a product-catalog plan is no longer a `pricing_type` row on
the shared `plans` table carrying nil legacy columns. This is additive and
zero-risk — nothing is repointed and the table starts empty.

Add the `catalog_plans` table and `CatalogPlan` model: the plan envelope
only (name, code, invoice_display_name, description, currency), no legacy
pricing columns (interval, amount_cents, pay_in_advance) and no self
reference (catalog plans do not use plan overrides). Code is unique per
organization among kept rows. Soft-deletable, paper-trailed.
## Context

A cold review flagged that CatalogPlan guarded code uniqueness only with
the database partial index, so a duplicate code raised a raw
RecordNotUnique (a 500) rather than a clean validation failure — and the
spec locked in that behaviour.

## Description

Add a model-level uniqueness validation on code scoped to the
organization and to kept rows, matching the sibling plan models. Update the
spec to assert the validation error, that the code is free again once the
holder is discarded, and that another organization may reuse it, while
keeping a database-level guarantee for the concurrency path.
@rsempe
rsempe merged commit a24f3ab into main Sep 4, 2026
12 checks passed
@rsempe
rsempe deleted the bil-643 branch September 4, 2026 15:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants