Skip to content
Open
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
106 changes: 52 additions & 54 deletions api/v3/handlers/customers/charges/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func convertFlatFeeChargeToAPI(source flatfee.Charge) (api.BillingChargeFlatFee,
AmountAfterProration: ConvertDecimalToCurrencyAmount(source.ChargeBase.State.AmountAfterProration),
BillingPeriod: ConvertClosedPeriodToAPI(intent.BillingPeriod),
CreatedAt: source.ChargeBase.ManagedResource.ManagedModel.CreatedAt,
Currency: ConvertCurrencyCodeToAPI(source.ChargeBase.Intent.GetCurrency()),
Currency: ConvertCurrencyCodeToAPI(source.ChargeBase.Intent.GetCurrency().GetCode()),
Customer: ConvertCustomerIDToReference(source.ChargeBase.Intent.GetCustomerID()),
DeletedAt: source.ChargeBase.ManagedResource.ManagedModel.DeletedAt,
Description: intent.Description,
Expand Down Expand Up @@ -109,7 +109,7 @@ func convertUsageBasedChargeToAPI(source usagebased.Charge) (api.BillingChargeUs
AdvanceAfter: source.State.AdvanceAfter,
BillingPeriod: ConvertClosedPeriodToAPI(intent.BillingPeriod),
CreatedAt: source.ChargeBase.ManagedResource.ManagedModel.CreatedAt,
Currency: ConvertCurrencyCodeToAPI(source.ChargeBase.Intent.GetCurrency()),
Currency: ConvertCurrencyCodeToAPI(source.ChargeBase.Intent.GetCurrency().GetCode()),
Customer: ConvertCustomerIDToReference(source.ChargeBase.Intent.GetCustomerID()),
DeletedAt: source.ChargeBase.ManagedResource.ManagedModel.DeletedAt,
Description: intent.Description,
Expand Down Expand Up @@ -504,8 +504,8 @@ func convertAPIChargeStatus(s string) (meta.ChargeStatus, error) {
}
}

func convertFlatFeeChargeAPIToIntent(customerID string, flatFee api.CreateChargeFlatFeeRequest) (billingcharges.ChargeIntent, error) {
var zero billingcharges.ChargeIntent
func fromAPICreateChargeFlatFeeRequest(namespace, customerID string, flatFee api.CreateChargeFlatFeeRequest) (billingcharges.CreateCustomerChargeInput, error) {
var zero billingcharges.CreateCustomerChargeInput

taxConfig, err := billingprofiles.FromAPIBillingTaxConfig(flatFee.TaxConfig)
if err != nil {
Expand Down Expand Up @@ -549,37 +549,36 @@ func convertFlatFeeChargeAPIToIntent(customerID string, flatFee api.CreateCharge
}
}

return billingcharges.NewChargeIntent(flatfee.Intent{
Intent: meta.Intent{
ManagedBy: billing.ManuallyManagedLine,
CustomerID: customerID,
Currency: currencyx.Code(flatFee.Currency),
TaxConfig: productcatalog.TaxCodeConfigFrom(taxConfig),
UniqueReferenceID: flatFee.UniqueReferenceId,
Subscription: nil,
},
IntentMutableFields: flatfee.IntentMutableFields{
IntentMutableFields: meta.IntentMutableFields{
Name: flatFee.Name,
Description: flatFee.Description,
Metadata: metadata,
ServicePeriod: timeutil.ClosedPeriod(flatFee.ServicePeriod),
FullServicePeriod: timeutil.ClosedPeriod(lo.FromPtrOr(flatFee.FullServicePeriod, flatFee.ServicePeriod)),
BillingPeriod: timeutil.ClosedPeriod(lo.FromPtrOr(flatFee.BillingPeriod, flatFee.ServicePeriod)),
return billingcharges.CreateCustomerChargeInput{
Namespace: namespace,
CustomerID: customerID,
CurrencyCode: currencyx.Code(flatFee.Currency),
TaxConfig: productcatalog.TaxCodeConfigFrom(taxConfig),
UniqueReferenceID: flatFee.UniqueReferenceId,
FlatFee: &billingcharges.CreateCustomerChargeFlatFeeInput{
IntentMutableFields: flatfee.IntentMutableFields{
IntentMutableFields: meta.IntentMutableFields{
Name: flatFee.Name,
Description: flatFee.Description,
Metadata: metadata,
ServicePeriod: timeutil.ClosedPeriod(flatFee.ServicePeriod),
FullServicePeriod: timeutil.ClosedPeriod(lo.FromPtrOr(flatFee.FullServicePeriod, flatFee.ServicePeriod)),
BillingPeriod: timeutil.ClosedPeriod(lo.FromPtrOr(flatFee.BillingPeriod, flatFee.ServicePeriod)),
},
InvoiceAt: flatFee.InvoiceAt,
PaymentTerm: productcatalog.PaymentTermType(flatFee.PaymentTerm),
PercentageDiscounts: discount,
ProRating: proRating,
AmountBeforeProration: amountBeforeProration,
},
InvoiceAt: flatFee.InvoiceAt,
PaymentTerm: productcatalog.PaymentTermType(flatFee.PaymentTerm),
PercentageDiscounts: discount,
ProRating: proRating,
AmountBeforeProration: amountBeforeProration,
FeatureKey: flatFee.FeatureKey,
SettlementMode: productcatalog.SettlementMode(flatFee.SettlementMode),
},
FeatureKey: flatFee.FeatureKey,
SettlementMode: productcatalog.SettlementMode(flatFee.SettlementMode),
}), nil
}, nil
}

func convertUsageBaseChargeAPIToIntent(customerID string, usageBasedFee api.CreateChargeUsageBasedRequest) (billingcharges.ChargeIntent, error) {
var zero billingcharges.ChargeIntent
func fromAPICreateChargeUsageBasedRequest(namespace, customerID string, usageBasedFee api.CreateChargeUsageBasedRequest) (billingcharges.CreateCustomerChargeInput, error) {
var zero billingcharges.CreateCustomerChargeInput

taxConfig, err := billingprofiles.FromAPIBillingTaxConfig(usageBasedFee.TaxConfig)
if err != nil {
Expand Down Expand Up @@ -618,29 +617,28 @@ func convertUsageBaseChargeAPIToIntent(customerID string, usageBasedFee api.Crea
if err != nil {
return zero, fmt.Errorf("invalid price: %w", err)
}
return billingcharges.NewChargeIntent(usagebased.Intent{
Intent: meta.Intent{
ManagedBy: billing.ManuallyManagedLine,
CustomerID: customerID,
Currency: currencyx.Code(usageBasedFee.Currency),
TaxConfig: productcatalog.TaxCodeConfigFrom(taxConfig),
UniqueReferenceID: usageBasedFee.UniqueReferenceId,
Subscription: nil,
},
IntentMutableFields: usagebased.IntentMutableFields{
IntentMutableFields: meta.IntentMutableFields{
Name: usageBasedFee.Name,
Description: usageBasedFee.Description,
Metadata: metadata,
ServicePeriod: timeutil.ClosedPeriod(usageBasedFee.ServicePeriod),
FullServicePeriod: timeutil.ClosedPeriod(lo.FromPtrOr(usageBasedFee.FullServicePeriod, usageBasedFee.ServicePeriod)),
BillingPeriod: timeutil.ClosedPeriod(lo.FromPtrOr(usageBasedFee.BillingPeriod, usageBasedFee.ServicePeriod)),
return billingcharges.CreateCustomerChargeInput{
Namespace: namespace,
CustomerID: customerID,
CurrencyCode: currencyx.Code(usageBasedFee.Currency),
TaxConfig: productcatalog.TaxCodeConfigFrom(taxConfig),
UniqueReferenceID: usageBasedFee.UniqueReferenceId,
UsageBased: &billingcharges.CreateCustomerChargeUsageBasedInput{
IntentMutableFields: usagebased.IntentMutableFields{
IntentMutableFields: meta.IntentMutableFields{
Name: usageBasedFee.Name,
Description: usageBasedFee.Description,
Metadata: metadata,
ServicePeriod: timeutil.ClosedPeriod(usageBasedFee.ServicePeriod),
FullServicePeriod: timeutil.ClosedPeriod(lo.FromPtrOr(usageBasedFee.FullServicePeriod, usageBasedFee.ServicePeriod)),
BillingPeriod: timeutil.ClosedPeriod(lo.FromPtrOr(usageBasedFee.BillingPeriod, usageBasedFee.ServicePeriod)),
},
InvoiceAt: usageBasedFee.InvoiceAt,
Price: *price,
Discounts: discounts,
},
InvoiceAt: usageBasedFee.InvoiceAt,
Price: *price,
Discounts: discounts,
FeatureKey: usageBasedFee.FeatureKey,
SettlementMode: productcatalog.SettlementMode(usageBasedFee.SettlementMode),
},
FeatureKey: usageBasedFee.FeatureKey,
SettlementMode: productcatalog.SettlementMode(usageBasedFee.SettlementMode),
}), nil
}, nil
}
4 changes: 2 additions & 2 deletions api/v3/handlers/customers/charges/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (
"github.com/openmeterio/openmeter/openmeter/billing"
"github.com/openmeterio/openmeter/openmeter/billing/charges/meta"
"github.com/openmeterio/openmeter/openmeter/billing/charges/usagebased"
currenciestestutils "github.com/openmeterio/openmeter/openmeter/currencies/testutils/currency"
"github.com/openmeterio/openmeter/openmeter/productcatalog"
"github.com/openmeterio/openmeter/pkg/currencyx"
"github.com/openmeterio/openmeter/pkg/timeutil"
)

Expand Down Expand Up @@ -80,7 +80,7 @@ func TestToAPIBillingChargeUsageBasedSystemIntentReturnsUnsupportedBasePriceErro
Intent: meta.Intent{
ManagedBy: billing.SubscriptionManagedLine,
CustomerID: "customer-id",
Currency: currencyx.Code("USD"),
Currency: currenciestestutils.NewFiatCurrency(t, "USD"),
},
IntentMutableFields: usagebased.IntentMutableFields{
IntentMutableFields: meta.IntentMutableFields{
Expand Down
27 changes: 7 additions & 20 deletions api/v3/handlers/customers/charges/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package charges

import (
"context"
"errors"
"fmt"
"net/http"

Expand All @@ -15,7 +14,7 @@ import (
)

type (
CreateCustomerChargesRequest = billingcharges.CreateInput
CreateCustomerChargesRequest = billingcharges.CreateCustomerChargeInput
CreateCustomerChargesResponse = api.BillingCharge
CreateCustomerChargesParams struct {
CustomerID api.ULID
Expand All @@ -31,10 +30,6 @@ func (h *handler) CreateCustomerCharge() CreateCustomerChargesHandler {
return CreateCustomerChargesRequest{}, err
}

input := billingcharges.CreateInput{
Namespace: ns,
}

body := api.CreateCustomerChargesJSONRequestBody{}
if err := request.ParseBody(r, &body); err != nil {
return CreateCustomerChargesRequest{}, err
Expand All @@ -51,6 +46,7 @@ func (h *handler) CreateCustomerCharge() CreateCustomerChargesHandler {
})
}

var input billingcharges.CreateCustomerChargeInput
switch discriminator {
case string(api.BillingChargeFlatFeeTypeFlatFee):
flatFee, err := body.AsCreateChargeFlatFeeRequest()
Expand All @@ -64,7 +60,7 @@ func (h *handler) CreateCustomerCharge() CreateCustomerChargesHandler {
})
}

intent, err := convertFlatFeeChargeAPIToIntent(param.CustomerID, flatFee)
input, err = fromAPICreateChargeFlatFeeRequest(ns, param.CustomerID, flatFee)
if err != nil {
return CreateCustomerChargesRequest{}, apierrors.NewBadRequestError(ctx, err, apierrors.InvalidParameters{
{
Expand All @@ -74,8 +70,6 @@ func (h *handler) CreateCustomerCharge() CreateCustomerChargesHandler {
},
})
}

input.Intents = append(input.Intents, intent)
case string(api.BillingChargeUsageBasedTypeUsageBased):
usageBasedFee, err := body.AsCreateChargeUsageBasedRequest()
if err != nil {
Expand All @@ -88,7 +82,7 @@ func (h *handler) CreateCustomerCharge() CreateCustomerChargesHandler {
})
}

intent, err := convertUsageBaseChargeAPIToIntent(param.CustomerID, usageBasedFee)
input, err = fromAPICreateChargeUsageBasedRequest(ns, param.CustomerID, usageBasedFee)
if err != nil {
return CreateCustomerChargesRequest{}, apierrors.NewBadRequestError(ctx, err, apierrors.InvalidParameters{
{
Expand All @@ -98,8 +92,6 @@ func (h *handler) CreateCustomerCharge() CreateCustomerChargesHandler {
},
})
}

input.Intents = append(input.Intents, intent)
default:
err := fmt.Errorf("invalid charge type: %s", discriminator)
return CreateCustomerChargesRequest{}, apierrors.NewBadRequestError(ctx, err, apierrors.InvalidParameters{
Expand All @@ -124,17 +116,12 @@ func (h *handler) CreateCustomerCharge() CreateCustomerChargesHandler {
return input, nil
},
func(ctx context.Context, request CreateCustomerChargesRequest) (CreateCustomerChargesResponse, error) {
res, err := h.service.Create(ctx, request)
charge, err := h.service.CreateCustomerCharge(ctx, request)
if err != nil {
return CreateCustomerChargesResponse{}, err
}
if len(res) < 1 {
return CreateCustomerChargesResponse{}, errors.New("no charge created")
}
if len(res) > 1 {
return CreateCustomerChargesResponse{}, errors.New("too many results")
}
return convertChargeToAPI(res[0])

return convertChargeToAPI(charge)
},
commonhttp.JSONResponseEncoderWithStatus[CreateCustomerChargesResponse](http.StatusCreated),
httptransport.AppendOptions(
Expand Down
4 changes: 2 additions & 2 deletions api/v3/handlers/customers/charges/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ type Handler interface {

type handler struct {
resolveNamespace func(ctx context.Context) (string, error)
service billingcharges.ChargeService
service billingcharges.Service
options []httptransport.HandlerOption
}

func New(
resolveNamespace func(ctx context.Context) (string, error),
service billingcharges.ChargeService,
service billingcharges.Service,
options ...httptransport.HandlerOption,
) Handler {
return &handler{
Expand Down
18 changes: 3 additions & 15 deletions api/v3/handlers/customers/credits/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func toAPIBillingCreditGrant(charge creditpurchase.Charge) (api.BillingCreditGra
Name: charge.Intent.Name,
Description: charge.Intent.Description,
Amount: charge.Intent.CreditAmount.String(),
Currency: api.BillingCurrencyCode(charge.Intent.Currency),
Currency: api.BillingCurrencyCode(charge.Intent.Currency.GetCode()),
EffectiveAt: charge.Intent.EffectiveAt,
ExpiresAt: charge.Intent.ExpiresAt,
FundingMethod: toAPIBillingCreditFundingMethod(charge.Intent.Settlement),
Expand Down Expand Up @@ -103,13 +103,7 @@ func toAPICreditGrantPurchase(charge creditpurchase.Charge) (*api.BillingCreditG
}

costBasis := inv.CostBasis.String()
currency, err := currencyx.NewCurrencyBuilder(currencyx.CurrencyTypeFiat).
WithCode(charge.Intent.Currency).
Build()
if err != nil {
return nil, fmt.Errorf("getting currency calculator: %w", err)
}
purchaseAmount := currency.RoundToPrecision(charge.Intent.CreditAmount.Mul(inv.CostBasis))
purchaseAmount := charge.Intent.Currency.RoundToPrecision(charge.Intent.CreditAmount.Mul(inv.CostBasis))
settlementStatus := api.BillingCreditPurchasePaymentSettlementStatusPending

if charge.Realizations.InvoiceSettlement != nil {
Expand All @@ -130,13 +124,7 @@ func toAPICreditGrantPurchase(charge creditpurchase.Charge) (*api.BillingCreditG
}

costBasis := ext.CostBasis.String()
currency, err := currencyx.NewCurrencyBuilder(currencyx.CurrencyTypeFiat).
WithCode(charge.Intent.Currency).
Build()
if err != nil {
return nil, fmt.Errorf("getting currency calculator: %w", err)
}
purchaseAmount := currency.RoundToPrecision(charge.Intent.CreditAmount.Mul(ext.CostBasis))
purchaseAmount := charge.Intent.Currency.RoundToPrecision(charge.Intent.CreditAmount.Mul(ext.CostBasis))
availPolicy, err := toAPIBillingCreditAvailabilityPolicy(ext.InitialStatus)
if err != nil {
return nil, fmt.Errorf("converting availability policy: %w", err)
Expand Down
8 changes: 4 additions & 4 deletions api/v3/handlers/customers/credits/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
api "github.com/openmeterio/openmeter/api/v3"
"github.com/openmeterio/openmeter/openmeter/billing/charges/creditpurchase"
"github.com/openmeterio/openmeter/openmeter/billing/charges/meta"
currenciestestutils "github.com/openmeterio/openmeter/openmeter/currencies/testutils/currency"
"github.com/openmeterio/openmeter/pkg/clock"
"github.com/openmeterio/openmeter/pkg/currencyx"
"github.com/openmeterio/openmeter/pkg/models"
)

Expand All @@ -34,7 +34,7 @@ func TestToAPIBillingCreditGrantPromotional(t *testing.T) {
Intent: creditpurchase.Intent{
Intent: meta.Intent{
CustomerID: "cust-1",
Currency: currencyx.Code("USD"),
Currency: currenciestestutils.NewFiatCurrency(t, "USD"),
},
IntentMutableFields: creditpurchase.IntentMutableFields{
IntentMutableFields: meta.IntentMutableFields{
Expand Down Expand Up @@ -79,7 +79,7 @@ func TestToAPIBillingCreditGrantStatusUsesExpiry(t *testing.T) {
Intent: creditpurchase.Intent{
Intent: meta.Intent{
CustomerID: "cust-1",
Currency: currencyx.Code("USD"),
Currency: currenciestestutils.NewFiatCurrency(t, "USD"),
},
IntentMutableFields: creditpurchase.IntentMutableFields{
CreditAmount: alpacadecimal.RequireFromString("25"),
Expand Down Expand Up @@ -151,7 +151,7 @@ func TestToAPIBillingCreditGrantKey(t *testing.T) {
Intent: creditpurchase.Intent{
Intent: meta.Intent{
CustomerID: "cust-1",
Currency: currencyx.Code("USD"),
Currency: currenciestestutils.NewFiatCurrency(t, "USD"),
},
IntentMutableFields: creditpurchase.IntentMutableFields{
IntentMutableFields: meta.IntentMutableFields{
Expand Down
2 changes: 1 addition & 1 deletion api/v3/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ type Config struct {
SubscriptionWorkflowService subscriptionworkflow.Service
TaxCodeService taxcode.Service
CurrencyService currencies.Service
ChargeService billingcharges.ChargeService
ChargeService billingcharges.Service
CostService cost.Service
FeatureConnector feature.FeatureConnector

Expand Down
3 changes: 3 additions & 0 deletions app/common/billing.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
subscriptionsyncadapter "github.com/openmeterio/openmeter/openmeter/billing/worker/subscriptionsync/adapter"
"github.com/openmeterio/openmeter/openmeter/billing/worker/subscriptionsync/reconciler"
subscriptionsyncservice "github.com/openmeterio/openmeter/openmeter/billing/worker/subscriptionsync/service"
"github.com/openmeterio/openmeter/openmeter/currencies"
"github.com/openmeterio/openmeter/openmeter/customer"
entdb "github.com/openmeterio/openmeter/openmeter/ent/db"
"github.com/openmeterio/openmeter/openmeter/ledger"
Expand Down Expand Up @@ -171,6 +172,7 @@ func NewBillingRegistry(
creditsConfig config.CreditsConfiguration,
tracer trace.Tracer,
taxCodeService taxcode.Service,
currencyResolver currencies.CurrencyResolver,
locker *lockr.Locker,
ledgerService ledger.Ledger,
balanceQuerier ledger.BalanceQuerier,
Expand Down Expand Up @@ -223,6 +225,7 @@ func NewBillingRegistry(
accountService,
breakageService,
taxCodeService,
currencyResolver,
fsConfig.NamespaceLockdown,
creditsConfig,
featureGate,
Expand Down
Loading
Loading