Add default_plan_ladder_id with a forward data migration and update the runtime to resolve the ladder's rank-0 tier at use-time. Regenerate sqlc, update auto-provisioning, ReapplyDefaultsForPool, operator UI and tests; add GetTierByLadderRank and pool/provision query helpers. Add a CSP-safe confirm-action modal and wire operator actions to it. Close plan-sole-writer safety gaps and serialize IssueGrant with a FOR UPDATE pool lock to prevent ladder races.
475 lines
13 KiB
Go
475 lines
13 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.29.0
|
|
// source: plan_ladders.sql
|
|
|
|
package billing
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"time"
|
|
)
|
|
|
|
const createPlanLadder = `-- name: CreatePlanLadder :one
|
|
INSERT INTO billing.plan_ladders (ladder_key, name, description, is_active)
|
|
VALUES ($1, $2, $3, $4)
|
|
RETURNING plan_ladder_id, ladder_key, name, description, is_active, created_at, updated_at
|
|
`
|
|
|
|
type CreatePlanLadderParams struct {
|
|
LadderKey string `json:"ladder_key"`
|
|
Name string `json:"name"`
|
|
Description sql.NullString `json:"description"`
|
|
IsActive bool `json:"is_active"`
|
|
}
|
|
|
|
func (q *Queries) CreatePlanLadder(ctx context.Context, arg CreatePlanLadderParams) (PlanLadder, error) {
|
|
row := q.db.QueryRowContext(ctx, createPlanLadder,
|
|
arg.LadderKey,
|
|
arg.Name,
|
|
arg.Description,
|
|
arg.IsActive,
|
|
)
|
|
var i PlanLadder
|
|
err := row.Scan(
|
|
&i.PlanLadderID,
|
|
&i.LadderKey,
|
|
&i.Name,
|
|
&i.Description,
|
|
&i.IsActive,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const createPlanLadderTier = `-- name: CreatePlanLadderTier :one
|
|
INSERT INTO billing.plan_ladder_tiers (plan_ladder_id, product_id, rank)
|
|
VALUES ($1, $2, $3)
|
|
RETURNING plan_ladder_id, product_id, rank, created_at, updated_at
|
|
`
|
|
|
|
type CreatePlanLadderTierParams struct {
|
|
PlanLadderID string `json:"plan_ladder_id"`
|
|
ProductID string `json:"product_id"`
|
|
Rank int32 `json:"rank"`
|
|
}
|
|
|
|
func (q *Queries) CreatePlanLadderTier(ctx context.Context, arg CreatePlanLadderTierParams) (PlanLadderTier, error) {
|
|
row := q.db.QueryRowContext(ctx, createPlanLadderTier, arg.PlanLadderID, arg.ProductID, arg.Rank)
|
|
var i PlanLadderTier
|
|
err := row.Scan(
|
|
&i.PlanLadderID,
|
|
&i.ProductID,
|
|
&i.Rank,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const deletePlanLadder = `-- name: DeletePlanLadder :exec
|
|
DELETE FROM billing.plan_ladders
|
|
WHERE plan_ladder_id = $1
|
|
`
|
|
|
|
func (q *Queries) DeletePlanLadder(ctx context.Context, planLadderID string) error {
|
|
_, err := q.db.ExecContext(ctx, deletePlanLadder, planLadderID)
|
|
return err
|
|
}
|
|
|
|
const deleteTier = `-- name: DeleteTier :exec
|
|
DELETE FROM billing.plan_ladder_tiers
|
|
WHERE plan_ladder_id = $1 AND product_id = $2
|
|
`
|
|
|
|
type DeleteTierParams struct {
|
|
PlanLadderID string `json:"plan_ladder_id"`
|
|
ProductID string `json:"product_id"`
|
|
}
|
|
|
|
func (q *Queries) DeleteTier(ctx context.Context, arg DeleteTierParams) error {
|
|
_, err := q.db.ExecContext(ctx, deleteTier, arg.PlanLadderID, arg.ProductID)
|
|
return err
|
|
}
|
|
|
|
const getPlanLadderByID = `-- name: GetPlanLadderByID :one
|
|
SELECT plan_ladder_id, ladder_key, name, description, is_active, created_at, updated_at FROM billing.plan_ladders
|
|
WHERE plan_ladder_id = $1
|
|
`
|
|
|
|
func (q *Queries) GetPlanLadderByID(ctx context.Context, planLadderID string) (PlanLadder, error) {
|
|
row := q.db.QueryRowContext(ctx, getPlanLadderByID, planLadderID)
|
|
var i PlanLadder
|
|
err := row.Scan(
|
|
&i.PlanLadderID,
|
|
&i.LadderKey,
|
|
&i.Name,
|
|
&i.Description,
|
|
&i.IsActive,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getPlanLadderByKey = `-- name: GetPlanLadderByKey :one
|
|
SELECT plan_ladder_id, ladder_key, name, description, is_active, created_at, updated_at FROM billing.plan_ladders
|
|
WHERE ladder_key = $1
|
|
`
|
|
|
|
func (q *Queries) GetPlanLadderByKey(ctx context.Context, ladderKey string) (PlanLadder, error) {
|
|
row := q.db.QueryRowContext(ctx, getPlanLadderByKey, ladderKey)
|
|
var i PlanLadder
|
|
err := row.Scan(
|
|
&i.PlanLadderID,
|
|
&i.LadderKey,
|
|
&i.Name,
|
|
&i.Description,
|
|
&i.IsActive,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getProductKind = `-- name: GetProductKind :one
|
|
SELECT product_kind FROM billing.product_kinds
|
|
WHERE product_id = $1
|
|
`
|
|
|
|
func (q *Queries) GetProductKind(ctx context.Context, productID string) (sql.NullString, error) {
|
|
row := q.db.QueryRowContext(ctx, getProductKind, productID)
|
|
var product_kind sql.NullString
|
|
err := row.Scan(&product_kind)
|
|
return product_kind, err
|
|
}
|
|
|
|
const getTier = `-- name: GetTier :one
|
|
SELECT plan_ladder_id, product_id, rank, created_at, updated_at FROM billing.plan_ladder_tiers
|
|
WHERE plan_ladder_id = $1 AND product_id = $2
|
|
`
|
|
|
|
type GetTierParams struct {
|
|
PlanLadderID string `json:"plan_ladder_id"`
|
|
ProductID string `json:"product_id"`
|
|
}
|
|
|
|
func (q *Queries) GetTier(ctx context.Context, arg GetTierParams) (PlanLadderTier, error) {
|
|
row := q.db.QueryRowContext(ctx, getTier, arg.PlanLadderID, arg.ProductID)
|
|
var i PlanLadderTier
|
|
err := row.Scan(
|
|
&i.PlanLadderID,
|
|
&i.ProductID,
|
|
&i.Rank,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getTierByLadderRank = `-- name: GetTierByLadderRank :one
|
|
SELECT plan_ladder_id, product_id, rank, created_at, updated_at FROM billing.plan_ladder_tiers
|
|
WHERE plan_ladder_id = $1 AND rank = $2
|
|
`
|
|
|
|
type GetTierByLadderRankParams struct {
|
|
PlanLadderID string `json:"plan_ladder_id"`
|
|
Rank int32 `json:"rank"`
|
|
}
|
|
|
|
func (q *Queries) GetTierByLadderRank(ctx context.Context, arg GetTierByLadderRankParams) (PlanLadderTier, error) {
|
|
row := q.db.QueryRowContext(ctx, getTierByLadderRank, arg.PlanLadderID, arg.Rank)
|
|
var i PlanLadderTier
|
|
err := row.Scan(
|
|
&i.PlanLadderID,
|
|
&i.ProductID,
|
|
&i.Rank,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const listLaddersByProduct = `-- name: ListLaddersByProduct :many
|
|
SELECT t.plan_ladder_id, t.product_id, t.rank, t.created_at, t.updated_at, l.ladder_key, l.name AS ladder_name
|
|
FROM billing.plan_ladder_tiers t
|
|
JOIN billing.plan_ladders l ON l.plan_ladder_id = t.plan_ladder_id
|
|
WHERE t.product_id = $1
|
|
ORDER BY l.ladder_key ASC
|
|
`
|
|
|
|
type ListLaddersByProductRow struct {
|
|
PlanLadderID string `json:"plan_ladder_id"`
|
|
ProductID string `json:"product_id"`
|
|
Rank int32 `json:"rank"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
LadderKey string `json:"ladder_key"`
|
|
LadderName string `json:"ladder_name"`
|
|
}
|
|
|
|
func (q *Queries) ListLaddersByProduct(ctx context.Context, productID string) ([]ListLaddersByProductRow, error) {
|
|
rows, err := q.db.QueryContext(ctx, listLaddersByProduct, productID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []ListLaddersByProductRow{}
|
|
for rows.Next() {
|
|
var i ListLaddersByProductRow
|
|
if err := rows.Scan(
|
|
&i.PlanLadderID,
|
|
&i.ProductID,
|
|
&i.Rank,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.LadderKey,
|
|
&i.LadderName,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listPlanLadders = `-- name: ListPlanLadders :many
|
|
SELECT plan_ladder_id, ladder_key, name, description, is_active, created_at, updated_at FROM billing.plan_ladders
|
|
ORDER BY ladder_key ASC
|
|
`
|
|
|
|
func (q *Queries) ListPlanLadders(ctx context.Context) ([]PlanLadder, error) {
|
|
rows, err := q.db.QueryContext(ctx, listPlanLadders)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []PlanLadder{}
|
|
for rows.Next() {
|
|
var i PlanLadder
|
|
if err := rows.Scan(
|
|
&i.PlanLadderID,
|
|
&i.LadderKey,
|
|
&i.Name,
|
|
&i.Description,
|
|
&i.IsActive,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listPlanLaddersWithRankZeroProduct = `-- name: ListPlanLaddersWithRankZeroProduct :many
|
|
SELECT l.plan_ladder_id, l.ladder_key, l.name AS ladder_name, l.is_active,
|
|
t.product_id, p.name AS rank_zero_product_name
|
|
FROM billing.plan_ladders l
|
|
JOIN billing.plan_ladder_tiers t
|
|
ON t.plan_ladder_id = l.plan_ladder_id AND t.rank = 0
|
|
JOIN billing.products p ON p.product_id = t.product_id
|
|
ORDER BY l.ladder_key ASC
|
|
`
|
|
|
|
type ListPlanLaddersWithRankZeroProductRow struct {
|
|
PlanLadderID string `json:"plan_ladder_id"`
|
|
LadderKey string `json:"ladder_key"`
|
|
LadderName string `json:"ladder_name"`
|
|
IsActive bool `json:"is_active"`
|
|
ProductID string `json:"product_id"`
|
|
RankZeroProductName string `json:"rank_zero_product_name"`
|
|
}
|
|
|
|
func (q *Queries) ListPlanLaddersWithRankZeroProduct(ctx context.Context) ([]ListPlanLaddersWithRankZeroProductRow, error) {
|
|
rows, err := q.db.QueryContext(ctx, listPlanLaddersWithRankZeroProduct)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []ListPlanLaddersWithRankZeroProductRow{}
|
|
for rows.Next() {
|
|
var i ListPlanLaddersWithRankZeroProductRow
|
|
if err := rows.Scan(
|
|
&i.PlanLadderID,
|
|
&i.LadderKey,
|
|
&i.LadderName,
|
|
&i.IsActive,
|
|
&i.ProductID,
|
|
&i.RankZeroProductName,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listTiersByLadder = `-- name: ListTiersByLadder :many
|
|
SELECT plan_ladder_id, product_id, rank, created_at, updated_at FROM billing.plan_ladder_tiers
|
|
WHERE plan_ladder_id = $1
|
|
ORDER BY rank ASC
|
|
`
|
|
|
|
func (q *Queries) ListTiersByLadder(ctx context.Context, planLadderID string) ([]PlanLadderTier, error) {
|
|
rows, err := q.db.QueryContext(ctx, listTiersByLadder, planLadderID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []PlanLadderTier{}
|
|
for rows.Next() {
|
|
var i PlanLadderTier
|
|
if err := rows.Scan(
|
|
&i.PlanLadderID,
|
|
&i.ProductID,
|
|
&i.Rank,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listTiersByLadderWithProducts = `-- name: ListTiersByLadderWithProducts :many
|
|
SELECT t.plan_ladder_id, t.product_id, t.rank, t.created_at, t.updated_at,
|
|
p.name AS product_name, p.product_type, p.lifecycle_status
|
|
FROM billing.plan_ladder_tiers t
|
|
JOIN billing.products p ON p.product_id = t.product_id
|
|
WHERE t.plan_ladder_id = $1
|
|
ORDER BY t.rank ASC
|
|
`
|
|
|
|
type ListTiersByLadderWithProductsRow struct {
|
|
PlanLadderID string `json:"plan_ladder_id"`
|
|
ProductID string `json:"product_id"`
|
|
Rank int32 `json:"rank"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
ProductName string `json:"product_name"`
|
|
ProductType sql.NullString `json:"product_type"`
|
|
LifecycleStatus string `json:"lifecycle_status"`
|
|
}
|
|
|
|
func (q *Queries) ListTiersByLadderWithProducts(ctx context.Context, planLadderID string) ([]ListTiersByLadderWithProductsRow, error) {
|
|
rows, err := q.db.QueryContext(ctx, listTiersByLadderWithProducts, planLadderID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []ListTiersByLadderWithProductsRow{}
|
|
for rows.Next() {
|
|
var i ListTiersByLadderWithProductsRow
|
|
if err := rows.Scan(
|
|
&i.PlanLadderID,
|
|
&i.ProductID,
|
|
&i.Rank,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.ProductName,
|
|
&i.ProductType,
|
|
&i.LifecycleStatus,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const updatePlanLadder = `-- name: UpdatePlanLadder :one
|
|
UPDATE billing.plan_ladders
|
|
SET name = $2, description = $3, is_active = $4
|
|
WHERE plan_ladder_id = $1
|
|
RETURNING plan_ladder_id, ladder_key, name, description, is_active, created_at, updated_at
|
|
`
|
|
|
|
type UpdatePlanLadderParams struct {
|
|
PlanLadderID string `json:"plan_ladder_id"`
|
|
Name string `json:"name"`
|
|
Description sql.NullString `json:"description"`
|
|
IsActive bool `json:"is_active"`
|
|
}
|
|
|
|
func (q *Queries) UpdatePlanLadder(ctx context.Context, arg UpdatePlanLadderParams) (PlanLadder, error) {
|
|
row := q.db.QueryRowContext(ctx, updatePlanLadder,
|
|
arg.PlanLadderID,
|
|
arg.Name,
|
|
arg.Description,
|
|
arg.IsActive,
|
|
)
|
|
var i PlanLadder
|
|
err := row.Scan(
|
|
&i.PlanLadderID,
|
|
&i.LadderKey,
|
|
&i.Name,
|
|
&i.Description,
|
|
&i.IsActive,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const updateTierRank = `-- name: UpdateTierRank :one
|
|
UPDATE billing.plan_ladder_tiers
|
|
SET rank = $3
|
|
WHERE plan_ladder_id = $1 AND product_id = $2
|
|
RETURNING plan_ladder_id, product_id, rank, created_at, updated_at
|
|
`
|
|
|
|
type UpdateTierRankParams struct {
|
|
PlanLadderID string `json:"plan_ladder_id"`
|
|
ProductID string `json:"product_id"`
|
|
Rank int32 `json:"rank"`
|
|
}
|
|
|
|
func (q *Queries) UpdateTierRank(ctx context.Context, arg UpdateTierRankParams) (PlanLadderTier, error) {
|
|
row := q.db.QueryRowContext(ctx, updateTierRank, arg.PlanLadderID, arg.ProductID, arg.Rank)
|
|
var i PlanLadderTier
|
|
err := row.Scan(
|
|
&i.PlanLadderID,
|
|
&i.ProductID,
|
|
&i.Rank,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|