Skip to content

Commit 9ec1c99

Browse files
committed
feat(api): added listing handler without filtering and package and dynamic prices filtered out
1 parent 489309d commit 9ec1c99

4 files changed

Lines changed: 114 additions & 1 deletion

File tree

api/v3/handlers/plans/convert.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,28 @@ import (
1616
"github.com/openmeterio/openmeter/pkg/models"
1717
)
1818

19+
var unsupportedV3PriceTypes = map[productcatalog.PriceType]struct{}{
20+
productcatalog.DynamicPriceType: {},
21+
productcatalog.PackagePriceType: {},
22+
}
23+
24+
func hasUnsupportedV3Price(p plan.Plan) bool {
25+
for _, phase := range p.Phases {
26+
for _, rc := range phase.RateCards {
27+
price := rc.AsMeta().Price
28+
if price == nil {
29+
continue
30+
}
31+
32+
if _, unsupported := unsupportedV3PriceTypes[price.Type()]; unsupported {
33+
return true
34+
}
35+
}
36+
}
37+
38+
return false
39+
}
40+
1941
func FromPlan(p plan.Plan) (api.BillingPlan, error) {
2042
validationIssues, _ := p.AsProductCatalogPlan().ValidationErrors()
2143

api/v3/handlers/plans/handler.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
)
99

1010
type Handler interface {
11+
ListPlans() ListPlansHandler
1112
GetPlan() GetPlanHandler
1213
CreatePlan() CreatePlanHandler
1314
UpdatePlan() UpdatePlanHandler

api/v3/handlers/plans/list.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package plans
2+
3+
import (
4+
"context"
5+
"net/http"
6+
7+
"github.com/samber/lo"
8+
9+
api "github.com/openmeterio/openmeter/api/v3"
10+
"github.com/openmeterio/openmeter/api/v3/apierrors"
11+
"github.com/openmeterio/openmeter/api/v3/response"
12+
"github.com/openmeterio/openmeter/openmeter/productcatalog/plan"
13+
"github.com/openmeterio/openmeter/pkg/framework/commonhttp"
14+
"github.com/openmeterio/openmeter/pkg/framework/transport/httptransport"
15+
"github.com/openmeterio/openmeter/pkg/pagination"
16+
)
17+
18+
type (
19+
ListPlansRequest = plan.ListPlansInput
20+
ListPlansResponse = response.PagePaginationResponse[api.BillingPlan]
21+
ListPlansParams = api.ListPlansParams
22+
ListPlansHandler httptransport.HandlerWithArgs[ListPlansRequest, ListPlansResponse, ListPlansParams]
23+
)
24+
25+
func (h *handler) ListPlans() ListPlansHandler {
26+
return httptransport.NewHandlerWithArgs(
27+
func(ctx context.Context, r *http.Request, params ListPlansParams) (ListPlansRequest, error) {
28+
ns, err := h.resolveNamespace(ctx)
29+
if err != nil {
30+
return ListPlansRequest{}, err
31+
}
32+
33+
page := pagination.NewPage(1, 20)
34+
if params.Page != nil {
35+
page = pagination.NewPage(
36+
lo.FromPtrOr(params.Page.Number, 1),
37+
lo.FromPtrOr(params.Page.Size, 20),
38+
)
39+
}
40+
41+
if err := page.Validate(); err != nil {
42+
return ListPlansRequest{}, apierrors.NewBadRequestError(ctx, err, apierrors.InvalidParameters{
43+
apierrors.InvalidParameter{
44+
Field: "page",
45+
Reason: err.Error(),
46+
Source: apierrors.InvalidParamSourceQuery,
47+
},
48+
})
49+
}
50+
51+
return ListPlansRequest{
52+
Namespaces: []string{ns},
53+
Page: page,
54+
}, nil
55+
},
56+
func(ctx context.Context, req ListPlansRequest) (ListPlansResponse, error) {
57+
result, err := h.service.ListPlans(ctx, req)
58+
if err != nil {
59+
return ListPlansResponse{}, err
60+
}
61+
62+
items := make([]api.BillingPlan, 0, len(result.Items))
63+
for _, p := range result.Items {
64+
// FIXME: For now we skip plans containing price types not representable in v3 (e.g., package, dynamic). We'll add full bidirectional transform later on.
65+
if hasUnsupportedV3Price(p) {
66+
continue
67+
}
68+
69+
billingPlan, err := FromPlan(p)
70+
if err != nil {
71+
return ListPlansResponse{}, err
72+
}
73+
74+
items = append(items, billingPlan)
75+
}
76+
77+
return response.NewPagePaginationResponse(items, response.PageMetaPage{
78+
Size: req.Page.PageSize,
79+
Number: req.Page.PageNumber,
80+
Total: lo.ToPtr(result.TotalCount),
81+
}), nil
82+
},
83+
commonhttp.JSONResponseEncoderWithStatus[ListPlansResponse](http.StatusOK),
84+
httptransport.AppendOptions(
85+
h.options,
86+
httptransport.WithOperationName("list-plans"),
87+
httptransport.WithErrorEncoder(apierrors.GenericErrorEncoder()),
88+
)...,
89+
)
90+
}

api/v3/server/routes.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ func (s *Server) DeleteLlmCostOverride(w http.ResponseWriter, r *http.Request, p
239239
// Plans
240240

241241
func (s *Server) ListPlans(w http.ResponseWriter, r *http.Request, params api.ListPlansParams) {
242-
unimplemented.ListPlans(w, r, params)
242+
s.plansHandler.ListPlans().With(params).ServeHTTP(w, r)
243243
}
244244

245245
func (s *Server) CreatePlan(w http.ResponseWriter, r *http.Request) {

0 commit comments

Comments
 (0)