Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions api/spec/src/v3/currencies/currency.tsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import "../shared/index.tsp";

namespace Currencies;

/**
* Currency describes a currency supported by the billing system.
*/
@friendlyName("BillingCurrency")
model Currency {
/**
* Standard ISO 4217 code.
*/
@visibility(Lifecycle.Read)
code: Shared.CurrencyCode;

/**
* English name of the currency.
*/
@visibility(Lifecycle.Read)
name: string;

/**
* Symbol representation of the currency.
*/
@visibility(Lifecycle.Read)
symbol: string;

/**
* Disambiguation symbol for the currency.
*/
@visibility(Lifecycle.Read)
disambiguate_symbol: string;

/**
* Number of subunits in the currency.
*/
@visibility(Lifecycle.Read)
subunits: uint32;

/**
* Smallest denomination of the currency.
*/
@visibility(Lifecycle.Read)
smallest_denomination: uint8;
}
2 changes: 2 additions & 0 deletions api/spec/src/v3/currencies/index.tsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import "./currency.tsp";
import "./operations.tsp";
44 changes: 44 additions & 0 deletions api/spec/src/v3/currencies/operations.tsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import "@typespec/http";
import "@typespec/rest";
import "@typespec/openapi";
import "@typespec/openapi3";
import "../common/error.tsp";
import "../common/parameters.tsp";
import "../shared/index.tsp";
import "./currency.tsp";

using TypeSpec.Http;
using TypeSpec.OpenAPI;

namespace Currencies;

/**
* Filter options for listing currencies.
*/
@friendlyName("ListCurrenciesParamsFilter")
model ListCurrenciesParamsFilter {
/**
* Filter currencies by code.
*/
}

/**
* List currencies response.
*/
@friendlyName("CurrenciesResponse")
model CurrenciesResponse {
@Http.statusCode _: 200;

@pageItems
data: Currency[];
}

interface CurrenciesOperations {
/**
* List all supported currencies.
*/
@get
@operationId("list-currencies")
@summary("List currencies")
list(): CurrenciesResponse | Common.ErrorResponses;
}
4 changes: 4 additions & 0 deletions api/spec/src/v3/konnect.tsp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ interface AppsEndpoints extends Apps.AppsOperations {}
@tag(Shared.BillingTag)
interface BillingProfilesEndpoints extends Billing.BillingProfilesOperations {}

@route("/openmeter/currencies")
@tag(Shared.BillingTag)
interface CurrenciesEndpoints extends Currencies.CurrenciesOperations {}

/**
* The system account access token is meant for automations and integrations that are not directly associated with a human identity.
*/
Expand Down
5 changes: 5 additions & 0 deletions api/spec/src/v3/openmeter.tsp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import "./customers/index.tsp";
import "./subscriptions/index.tsp";
import "./apps/index.tsp";
import "./billing/index.tsp";
import "./currencies/index.tsp";

using TypeSpec.Http;
using TypeSpec.OpenAPI;
Expand Down Expand Up @@ -76,3 +77,7 @@ interface AppsEndpoints extends Apps.AppsOperations {}
@route("/openmeter/profiles")
@tag(Shared.BillingTag)
interface BillingProfilesEndpoints extends Billing.BillingProfilesOperations {}

@route("/openmeter/currencies")
@tag(Shared.BillingTag)
interface CurrenciesEndpoints extends Currencies.CurrenciesOperations {}
584 changes: 320 additions & 264 deletions api/v3/api.gen.go

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions api/v3/handlers/currencies/convert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package currencies

import (
"github.com/invopop/gobl/currency"
v3 "github.com/openmeterio/openmeter/api/v3"
)

func MapCurrencyToAPI(currency *currency.Def) v3.BillingCurrency {
return v3.BillingCurrency{
Code: v3.CurrencyCode(currency.ISOCode),
DisambiguateSymbol: currency.DisambiguateSymbol,
Name: currency.Name,
SmallestDenomination: uint8(currency.SmallestDenomination),
Subunits: currency.Subunits,
Symbol: currency.Symbol,
}
}
22 changes: 22 additions & 0 deletions api/v3/handlers/currencies/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package currencies

import (
"github.com/openmeterio/openmeter/openmeter/currencies"
"github.com/openmeterio/openmeter/pkg/framework/transport/httptransport"
)

type Handler interface {
ListCurrencies() ListCurrenciesHandler
}

type handler struct {
options []httptransport.HandlerOption
currencyService currencies.CurrencyService
}

func New(currencyService currencies.CurrencyService, options ...httptransport.HandlerOption) Handler {
return &handler{
options: options,
currencyService: currencyService,
}
}
41 changes: 41 additions & 0 deletions api/v3/handlers/currencies/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package currencies

import (
"context"
"net/http"

"github.com/invopop/gobl/currency"
v3 "github.com/openmeterio/openmeter/api/v3"
"github.com/openmeterio/openmeter/pkg/framework/commonhttp"
"github.com/openmeterio/openmeter/pkg/framework/transport/httptransport"
"github.com/samber/lo"
)

type (
ListCurrenciesRequest struct{}
ListCurrenciesResponse []v3.BillingCurrency
ListCurrenciesHandler httptransport.Handler[ListCurrenciesRequest, ListCurrenciesResponse]
)

func (h *handler) ListCurrencies() ListCurrenciesHandler {
return httptransport.NewHandler(
func(ctx context.Context, r *http.Request) (ListCurrenciesRequest, error) {
return ListCurrenciesRequest{}, nil
},
func(ctx context.Context, request ListCurrenciesRequest) (ListCurrenciesResponse, error) {
defs, err := h.currencyService.ListCurrencies()
if err != nil {
return nil, err
}

return lo.Map(defs, func(def *currency.Def, _ int) v3.BillingCurrency {
return MapCurrencyToAPI(def)
}), nil
},
commonhttp.JSONResponseEncoderWithStatus[ListCurrenciesResponse](http.StatusOK),
httptransport.AppendOptions(
h.options,
httptransport.WithOperationName("listCurrencies"),
)...,
)
}
68 changes: 68 additions & 0 deletions api/v3/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,26 @@ paths:
$ref: '#/components/responses/NotFound'
tags:
- OpenMeter Apps
/openmeter/currencies:
get:
operationId: list-currencies
summary: List currencies
description: List all supported currencies.
responses:
'200':
description: List currencies response.
content:
application/json:
schema:
$ref: '#/components/schemas/CurrenciesResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
tags:
- OpenMeter Billing
/openmeter/customers:
post:
operationId: create-customer
Expand Down Expand Up @@ -1798,6 +1818,44 @@ components:
- stripe
- external_invoicing
description: The type of the app.
BillingCurrency:
type: object
required:
- code
- name
- symbol
- disambiguate_symbol
- subunits
- smallest_denomination
properties:
code:
allOf:
- $ref: '#/components/schemas/CurrencyCode'
description: Standard ISO 4217 code.
readOnly: true
name:
type: string
description: English name of the currency.
readOnly: true
symbol:
type: string
description: Symbol representation of the currency.
readOnly: true
disambiguate_symbol:
type: string
description: Disambiguation symbol for the currency.
readOnly: true
subunits:
type: integer
format: uint32
description: Number of subunits in the currency.
readOnly: true
smallest_denomination:
type: integer
format: uint8
description: Smallest denomination of the currency.
readOnly: true
description: Currency describes a currency supported by the billing system.
BillingCustomer:
type: object
required:
Expand Down Expand Up @@ -2786,6 +2844,16 @@ components:
example:
type: $.type
description: Meter create request.
CurrenciesResponse:
type: object
required:
- data
properties:
data:
type: array
items:
$ref: '#/components/schemas/BillingCurrency'
description: List currencies response.
CurrencyCode:
type: string
minLength: 3
Expand Down
6 changes: 6 additions & 0 deletions api/v3/server/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,9 @@ func (s *Server) CreateCustomerStripeCheckoutSession(w http.ResponseWriter, r *h
func (s *Server) CreateCustomerStripePortalSession(w http.ResponseWriter, r *http.Request, customerId api.ULID) {
s.customersBillingHandler.CreateCustomerStripePortalSession().With(customerId).ServeHTTP(w, r)
}

// Currencies

func (s *Server) ListCurrencies(w http.ResponseWriter, r *http.Request) {
s.currenciesHandler.ListCurrencies().ServeHTTP(w, r)
}
10 changes: 10 additions & 0 deletions api/v3/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/openmeterio/openmeter/api/v3/apierrors"
appshandler "github.com/openmeterio/openmeter/api/v3/handlers/apps"
billingprofileshandler "github.com/openmeterio/openmeter/api/v3/handlers/billingprofiles"
currencieshandler "github.com/openmeterio/openmeter/api/v3/handlers/currencies"
customershandler "github.com/openmeterio/openmeter/api/v3/handlers/customers"
customersbillinghandler "github.com/openmeterio/openmeter/api/v3/handlers/customers/billing"
customersentitlementhandler "github.com/openmeterio/openmeter/api/v3/handlers/customers/entitlementaccess"
Expand All @@ -27,6 +28,7 @@ import (
"github.com/openmeterio/openmeter/openmeter/app"
appstripe "github.com/openmeterio/openmeter/openmeter/app/stripe"
"github.com/openmeterio/openmeter/openmeter/billing"
"github.com/openmeterio/openmeter/openmeter/currencies"
"github.com/openmeterio/openmeter/openmeter/customer"
"github.com/openmeterio/openmeter/openmeter/entitlement"
"github.com/openmeterio/openmeter/openmeter/ingest"
Expand Down Expand Up @@ -58,6 +60,7 @@ type Config struct {
PlanSubscriptionService plansubscription.PlanSubscriptionService
StripeService appstripe.Service
SubscriptionService subscription.Service
CurrencyService currencies.CurrencyService
}

func (c *Config) Validate() error {
Expand Down Expand Up @@ -115,6 +118,10 @@ func (c *Config) Validate() error {
errs = append(errs, errors.New("subscription service is required"))
}

if c.CurrencyService == nil {
errs = append(errs, errors.New("currency service is required"))
}

return errors.Join(errs...)
}

Expand All @@ -132,6 +139,7 @@ type Server struct {
metersHandler metershandler.Handler
subscriptionsHandler subscriptionshandler.Handler
billingProfilesHandler billingprofileshandler.Handler
currenciesHandler currencieshandler.Handler
}

// Make sure we conform to ServerInterface
Expand Down Expand Up @@ -173,6 +181,7 @@ func NewServer(config *Config) (*Server, error) {
metersHandler := metershandler.New(resolveNamespace, config.MeterService, httptransport.WithErrorHandler(config.ErrorHandler))
subscriptionsHandler := subscriptionshandler.New(resolveNamespace, config.CustomerService, config.PlanService, config.PlanSubscriptionService, config.SubscriptionService, httptransport.WithErrorHandler(config.ErrorHandler))
billingProfilesHandler := billingprofileshandler.New(resolveNamespace, config.BillingService, httptransport.WithErrorHandler(config.ErrorHandler))
currenciesHandler := currencieshandler.New(config.CurrencyService, httptransport.WithErrorHandler(config.ErrorHandler))

return &Server{
Config: config,
Expand All @@ -185,6 +194,7 @@ func NewServer(config *Config) (*Server, error) {
metersHandler: metersHandler,
subscriptionsHandler: subscriptionsHandler,
billingProfilesHandler: billingProfilesHandler,
currenciesHandler: currenciesHandler,
}, nil
}

Expand Down
15 changes: 15 additions & 0 deletions app/common/currency.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package common

import (
"github.com/google/wire"
"github.com/openmeterio/openmeter/openmeter/currencies"
"github.com/openmeterio/openmeter/openmeter/currencies/service"
)

var Currency = wire.NewSet(
NewCurrencyService,
)

func NewCurrencyService() currencies.CurrencyService {
return service.New()
}
1 change: 1 addition & 0 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ func main() {
AppCustomInvoicing: app.AppRegistry.CustomInvoicing,
Billing: app.Billing,
BillingFeatureSwitches: conf.Billing.FeatureSwitches,
CurrencyService: app.CurrencyService,
Customer: app.Customer,
DebugConnector: debugConnector,
ErrorHandler: errorsx.NewSlogHandler(logger),
Expand Down
Loading
Loading