Skip to content

Commit 8ae6eea

Browse files
committed
feat: implement featurefilters for transaction listing
1 parent 90e752f commit 8ae6eea

32 files changed

Lines changed: 1465 additions & 333 deletions

api/spec/packages/aip-client-javascript/src/models/schemas.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2735,6 +2735,7 @@ export const listCreditTransactionsParamsFilter = z
27352735
.object({
27362736
type: creditTransactionType.optional(),
27372737
currency: billingCurrencyCode.optional(),
2738+
feature_key: stringFieldFilter.optional(),
27382739
})
27392740
.describe('Filter options for listing credit transactions.')
27402741

api/spec/packages/aip-client-javascript/src/models/types.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,6 +1533,21 @@ export interface ListCreditTransactionsParamsFilter {
15331533
type?: 'funded' | 'consumed' | 'expired'
15341534
/** Filter credit transactions by currency. */
15351535
currency?: string
1536+
/** Filter credit transactions by feature key. Omit to return all credit transactions. Use `exists=false` to return only unrestricted credit transactions. */
1537+
feature_key?:
1538+
| string
1539+
| {
1540+
eq?: string
1541+
neq?: string
1542+
contains?: string
1543+
ocontains?: string[]
1544+
oeq?: string[]
1545+
gt?: string
1546+
gte?: string
1547+
lt?: string
1548+
lte?: string
1549+
exists?: boolean
1550+
}
15361551
}
15371552

15381553
/** A credit transaction represents a single credit movement on the customer's balance. Credit transactions are immutable. */

api/spec/packages/aip/src/customers/credits/operations.tsp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,13 @@ model ListCreditTransactionsParamsFilter {
204204
*/
205205
currency?: Currencies.CurrencyCode;
206206

207+
/**
208+
* Filter credit transactions by feature key. Omit to return all credit
209+
* transactions. Use `exists=false` to return only unrestricted credit
210+
* transactions.
211+
*/
212+
feature_key?: Common.StringFieldFilter;
213+
207214
// TODO: add date filters for created_at and booked_at
208215
}
209216

api/v3/api.gen.go

Lines changed: 241 additions & 236 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/v3/handlers/customers/credits/get_balance_filter.go renamed to api/v3/handlers/customers/credits/feature_filter.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
"github.com/openmeterio/openmeter/openmeter/ledger/customerbalance"
1414
)
1515

16-
func fromAPICreditBalanceFeatureFilter(f *api.StringFieldFilter) (mo.Option[creditpurchase.FeatureFilters], error) {
16+
func fromAPICustomerCreditFeatureFilter(f *api.StringFieldFilter) (mo.Option[creditpurchase.FeatureFilters], error) {
1717
if f == nil {
1818
return customerbalance.AllFeatureFilter(), nil
1919
}
@@ -26,7 +26,7 @@ func fromAPICreditBalanceFeatureFilter(f *api.StringFieldFilter) (mo.Option[cred
2626
return customerbalance.AllFeatureFilter(), errors.New("exists=true operator is not supported")
2727
}
2828

29-
if op := unsupportedCreditBalanceFeatureKeyOperator(f); op != "" {
29+
if op := unsupportedCustomerCreditFeatureKeyOperator(f); op != "" {
3030
return customerbalance.AllFeatureFilter(), fmt.Errorf("%s operator is not supported", op)
3131
}
3232

@@ -48,7 +48,7 @@ func fromAPICreditBalanceFeatureFilter(f *api.StringFieldFilter) (mo.Option[cred
4848
return featureFilter, nil
4949
}
5050

51-
func unsupportedCreditBalanceFeatureKeyOperator(f *api.StringFieldFilter) string {
51+
func unsupportedCustomerCreditFeatureKeyOperator(f *api.StringFieldFilter) string {
5252
switch {
5353
case f.Neq != nil:
5454
return "neq"

api/v3/handlers/customers/credits/get_balance_test.go renamed to api/v3/handlers/customers/credits/feature_filter_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"github.com/openmeterio/openmeter/openmeter/ledger/customerbalance"
1313
)
1414

15-
func TestParseCreditBalanceFeatureFilter(t *testing.T) {
15+
func TestFromAPICustomerCreditFeatureFilter(t *testing.T) {
1616
tests := []struct {
1717
name string
1818
filter *api.StringFieldFilter
@@ -62,7 +62,7 @@ func TestParseCreditBalanceFeatureFilter(t *testing.T) {
6262

6363
for _, tt := range tests {
6464
t.Run(tt.name, func(t *testing.T) {
65-
got, err := fromAPICreditBalanceFeatureFilter(tt.filter)
65+
got, err := fromAPICustomerCreditFeatureFilter(tt.filter)
6666
if tt.wantErr {
6767
require.Error(t, err)
6868
return

api/v3/handlers/customers/credits/get_balance.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func (h *handler) GetCustomerCreditBalance() GetCustomerCreditBalanceHandler {
8181
}
8282

8383
if args.Params.Filter != nil {
84-
featureFilter, err := fromAPICreditBalanceFeatureFilter(args.Params.Filter.FeatureKey)
84+
featureFilter, err := fromAPICustomerCreditFeatureFilter(args.Params.Filter.FeatureKey)
8585
if err != nil {
8686
return GetCustomerCreditBalanceRequest{}, newFeatureKeyFilterBadRequest(ctx, err)
8787
}

api/v3/handlers/customers/credits/list_transactions.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ func (h *handler) ListCreditTransactions() ListCreditTransactionsHandler {
9898
currency := currencyx.Code(*args.Params.Filter.Currency)
9999
req.Currency = &currency
100100
}
101+
102+
featureFilter, err := fromAPICustomerCreditFeatureFilter(args.Params.Filter.FeatureKey)
103+
if err != nil {
104+
return ListCreditTransactionsRequest{}, newFeatureKeyFilterBadRequest(ctx, err)
105+
}
106+
107+
req.FeatureFilter = featureFilter
101108
}
102109

103110
return req, nil

api/v3/openapi.yaml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8190,8 +8190,8 @@ components:
81908190
allOf:
81918191
- $ref: '#/components/schemas/StringFieldFilter'
81928192
description: |-
8193-
Filter credit balance by feature key. Omit to return the total portfolio
8194-
value. Use `exists=false` to return only unrestricted balance.
8193+
Filter credit balance by feature key. Omit to return the total portfolio value.
8194+
Use `exists=false` to return only unrestricted balance.
81958195
additionalProperties: false
81968196
description: Filter options for getting a credit balance.
81978197
GovernanceFeatureAccess:
@@ -8687,6 +8687,12 @@ components:
86878687
allOf:
86888688
- $ref: '#/components/schemas/BillingCurrencyCode'
86898689
description: Filter credit transactions by currency.
8690+
feature_key:
8691+
allOf:
8692+
- $ref: '#/components/schemas/StringFieldFilter'
8693+
description: |-
8694+
Filter credit transactions by feature key. Omit to return all credit transactions.
8695+
Use `exists=false` to return only unrestricted credit transactions.
86908696
additionalProperties: false
86918697
description: Filter options for listing credit transactions.
86928698
ListCurrenciesParamsFilter:

openmeter/billing/charges/creditpurchase/adapter/funded_credit_activity.go

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"slices"
77

88
"entgo.io/ent/dialect/sql"
9+
"github.com/lib/pq"
10+
"github.com/samber/mo"
911

1012
"github.com/openmeterio/openmeter/openmeter/billing/charges/creditpurchase"
1113
"github.com/openmeterio/openmeter/openmeter/billing/charges/meta"
@@ -20,15 +22,20 @@ func (a *adapter) ListFundedCreditActivities(ctx context.Context, input creditpu
2022
}
2123

2224
func ListFundedCreditActivities(ctx context.Context, dbClient *db.Client, input creditpurchase.ListFundedCreditActivitiesInput) (creditpurchase.ListFundedCreditActivitiesResult, error) {
25+
creditPurchasePredicates := []predicate.ChargeCreditPurchase{
26+
dbchargecreditpurchase.Namespace(input.Customer.Namespace),
27+
dbchargecreditpurchase.CustomerIDEQ(input.Customer.ID),
28+
dbchargecreditpurchase.DeletedAtIsNil(),
29+
}
30+
if featurePredicate := fundedCreditActivityFeatureFilterPredicate(input.FeatureFilter); featurePredicate != nil {
31+
creditPurchasePredicates = append(creditPurchasePredicates, featurePredicate)
32+
}
33+
2334
query := dbClient.ChargeCreditPurchaseCreditGrant.Query().
2435
Where(
2536
dbchargecreditpurchasecreditgrant.Namespace(input.Customer.Namespace),
2637
dbchargecreditpurchasecreditgrant.DeletedAtIsNil(),
27-
dbchargecreditpurchasecreditgrant.HasCreditPurchaseWith(
28-
dbchargecreditpurchase.Namespace(input.Customer.Namespace),
29-
dbchargecreditpurchase.CustomerIDEQ(input.Customer.ID),
30-
dbchargecreditpurchase.DeletedAtIsNil(),
31-
),
38+
dbchargecreditpurchasecreditgrant.HasCreditPurchaseWith(creditPurchasePredicates...),
3239
).
3340
WithCreditPurchase(func(q *db.ChargeCreditPurchaseQuery) {
3441
q.Where(
@@ -53,11 +60,7 @@ func ListFundedCreditActivities(ctx context.Context, dbClient *db.Client, input
5360
}
5461

5562
if input.Currency != nil {
56-
query = query.Where(
57-
dbchargecreditpurchasecreditgrant.HasCreditPurchaseWith(
58-
dbchargecreditpurchase.CurrencyEQ(*input.Currency),
59-
),
60-
)
63+
query = query.Where(dbchargecreditpurchasecreditgrant.HasCreditPurchaseWith(dbchargecreditpurchase.CurrencyEQ(*input.Currency)))
6164
}
6265

6366
if input.AsOf != nil {
@@ -130,6 +133,27 @@ func ListFundedCreditActivities(ctx context.Context, dbClient *db.Client, input
130133
}, nil
131134
}
132135

136+
func fundedCreditActivityFeatureFilterPredicate(filter mo.Option[creditpurchase.FeatureFilters]) predicate.ChargeCreditPurchase {
137+
if filter.IsAbsent() {
138+
return nil
139+
}
140+
141+
features := filter.OrEmpty()
142+
if features == nil {
143+
return dbchargecreditpurchase.FeatureFiltersIsNil()
144+
}
145+
features = features.Normalize()
146+
147+
return dbchargecreditpurchase.Or(
148+
dbchargecreditpurchase.FeatureFiltersIsNil(),
149+
func(s *sql.Selector) {
150+
s.Where(sql.P(func(b *sql.Builder) {
151+
b.Ident(s.C(dbchargecreditpurchase.FieldFeatureFilters)).WriteString(" @> ").Arg(pq.StringArray{features[0]})
152+
}))
153+
},
154+
)
155+
}
156+
133157
func fundedCreditActivityAfterPredicate(cursor creditpurchase.FundedCreditActivityCursor) predicate.ChargeCreditPurchaseCreditGrant {
134158
return dbchargecreditpurchasecreditgrant.Or(
135159
dbchargecreditpurchasecreditgrant.GrantedAtLT(cursor.FundedAt),

0 commit comments

Comments
 (0)