Skip to content
Merged
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
6 changes: 2 additions & 4 deletions openmeter/app/stripe/calculator.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ import (
)

// NewStripeCalculator creates a new StripeCalculator.
func NewStripeCalculator(currencyCode currencyx.Code) (StripeCalculator, error) {
currency, err := currencyx.NewCurrencyBuilder(currencyx.CurrencyTypeFiat).
WithCode(currencyCode).
Build()
func NewStripeCalculator(currencyCode currencyx.FiatCode) (StripeCalculator, error) {
currency, err := currencyCode.AsFiatCurrency()
if err != nil {
return StripeCalculator{}, fmt.Errorf("failed to get stripe calculator: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion openmeter/app/stripe/client/invoice.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ type CreateInvoiceInput struct {
InvoiceID string
AutomaticTaxEnabled bool
CollectionMethod billing.CollectionMethod
Currency currencyx.Code
Currency currencyx.FiatCode
DaysUntilDue *int64
StatementDescriptor *string
StripeCustomerID string
Expand Down
7 changes: 3 additions & 4 deletions openmeter/billing/charges/creditpurchase/service/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,8 @@ func (s *service) buildInvoiceCreditPurchaseGatheringLine(charge creditpurchase.

// Total cost = credit amount * cost basis (e.g., 100 credits * $0.5 = $50)
totalCost := intent.CreditAmount.Mul(invoiceSettlement.CostBasis)
calc, err := currencyx.NewCurrencyBuilder(currencyx.CurrencyTypeFiat).
WithCode(invoiceSettlement.Currency).
Build()
invoiceCurrency := currencyx.FiatCode(invoiceSettlement.Currency)
calc, err := invoiceCurrency.AsFiatCurrency()
if err != nil {
return billing.GatheringLine{}, fmt.Errorf("creating currency calculator: %w", err)
}
Expand Down Expand Up @@ -134,7 +133,7 @@ func (s *service) buildInvoiceCreditPurchaseGatheringLine(charge creditpurchase.
},
),
),
Currency: invoiceSettlement.Currency,
Currency: invoiceCurrency,
ServicePeriod: intent.ServicePeriod,
InvoiceAt: intent.CalculateEffectiveAt(),
TaxConfig: lo.ToPtr(intent.TaxConfig.ToTaxConfig()),
Expand Down
20 changes: 20 additions & 0 deletions openmeter/billing/charges/flatfee/charge.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/openmeterio/openmeter/openmeter/currencies"
"github.com/openmeterio/openmeter/openmeter/customer"
"github.com/openmeterio/openmeter/openmeter/productcatalog"
"github.com/openmeterio/openmeter/pkg/currencyx"
"github.com/openmeterio/openmeter/pkg/models"
"github.com/openmeterio/openmeter/pkg/timeutil"
)
Expand Down Expand Up @@ -81,6 +82,25 @@ func (c ChargeBase) GetCurrency() currencies.Currency {
return c.Intent.GetCurrency()
}

func (c ChargeBase) GetInvoiceCurrency() (currencyx.FiatCode, error) {
currency := c.GetCurrency()
if currency.IsFiat() {
return currencyx.FiatCode(currency.GetCode()), nil
}

costBasisIntent := c.Intent.GetCostBasisIntent()
if costBasisIntent == nil {
return "", errors.New("cost basis intent is required for a custom-currency invoice")
}

fiatCurrency, err := costBasisIntent.GetFiatCurrency()
if err != nil {
return "", fmt.Errorf("getting cost basis fiat currency: %w", err)
}

return fiatCurrency.GetFiatCode(), nil
}

func (c ChargeBase) ErrorAttributes() models.Attributes {
return models.Attributes{
"charge_id": c.ID,
Expand Down
7 changes: 6 additions & 1 deletion openmeter/billing/charges/flatfee/service/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ func buildFlatFeeGatheringLine(input buildFlatFeeGatheringLineInput) (billing.Ga
managedBy = billing.ManuallyManagedLine
}

invoiceCurrency, err := flatFee.GetInvoiceCurrency()
if err != nil {
return billing.GatheringLine{}, fmt.Errorf("getting invoice currency: %w", err)
}

gatheringLine := billing.GatheringLine{
GatheringLineBase: billing.GatheringLineBase{
ManagedResource: models.NewManagedResource(models.ManagedResourceInput{
Expand All @@ -217,7 +222,7 @@ func buildFlatFeeGatheringLine(input buildFlatFeeGatheringLineInput) (billing.Ga
),
FeatureKey: lo.FromPtr(lineIntent.FeatureKey),

Currency: lineIntent.Currency.GetCode(),
Currency: invoiceCurrency,
ServicePeriod: lineIntent.ServicePeriod,
InvoiceAt: lineIntent.InvoiceAt,

Expand Down
5 changes: 1 addition & 4 deletions openmeter/billing/charges/flatfee/service/linemapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,10 @@ import (

"github.com/openmeterio/openmeter/openmeter/billing"
"github.com/openmeterio/openmeter/openmeter/billing/charges/flatfee"
"github.com/openmeterio/openmeter/pkg/currencyx"
)

func populateFlatFeeStandardLineFromRun(stdLine *billing.StandardLine, run flatfee.RealizationRun) error {
currency, err := currencyx.NewCurrencyBuilder(currencyx.CurrencyTypeFiat).
WithCode(stdLine.Currency).
Build()
currency, err := stdLine.Currency.AsFiatCurrency()
if err != nil {
return fmt.Errorf("creating currency calculator: %w", err)
}
Expand Down
3 changes: 2 additions & 1 deletion openmeter/billing/charges/flatfee/service/manualedit.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,11 @@ func intentFromManualCreatedLine(
return flatfee.Intent{}, fmt.Errorf("line id is required")
}

currency, err := currencies.NewFiatCurrency(line.GetCurrency())
fiatCurrency, err := line.GetCurrency().AsFiatCurrency()
if err != nil {
return flatfee.Intent{}, fmt.Errorf("resolving fiat currency %q: %w", line.GetCurrency(), err)
}
currency := currencies.Currency{Currency: fiatCurrency}

if chargeID := line.GetChargeID(); chargeID != nil && *chargeID != "" {
return flatfee.Intent{}, fmt.Errorf("line[%s]: charge id must be empty for manual create", line.GetID())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ func (u *updater) provisionUpcomingLines(ctx context.Context, customerID custome
return nil
}

linesByCurrency := lo.GroupBy(lines, func(l billing.GatheringLine) currencyx.Code {
linesByCurrency := lo.GroupBy(lines, func(l billing.GatheringLine) currencyx.FiatCode {
return l.Currency
})

Expand Down
30 changes: 30 additions & 0 deletions openmeter/billing/charges/models/costbasis/intent.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,36 @@ func (i Intent) AsDynamic() (DynamicIntent, error) {
return *i.dynamic, nil
}

// GetFiatCurrency returns the fiat currency in which the custom-currency cost
// basis is expressed, regardless of the selected resolution mode.
func (i Intent) GetFiatCurrency() (*currencyx.FiatCurrency, error) {
switch i.kind {
case ModeDynamic:
intent, err := i.AsDynamic()
if err != nil {
return nil, err
}

return intent.FiatCurrency, nil
case ModePinned:
intent, err := i.AsPinned()
if err != nil {
return nil, err
}

return intent.FiatCurrency, nil
case ModeManual:
intent, err := i.AsManual()
if err != nil {
return nil, err
}

return intent.FiatCurrency, nil
default:
return nil, models.NewGenericValidationError(fmt.Errorf("invalid intent kind: %s", i.kind))
}
Comment on lines +133 to +160

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files matching intent/costbasis:"
git ls-files | rg '(^|/)openmeter/billing/charges/models/costbasis/intent\.go$|costbasis' || true

echo
echo "Relevant intent outline:"
ast-grep outline openmeter/billing/charges/models/costbasis/intent.go --view expanded || true

echo
echo "Interest locations in intent.go:"
sed -n '1,240p' openmeter/billing/charges/models/costbasis/intent.go

echo
echo "Search GetFiatCurrency/getFiatCode/get invoicesCurrency:"
rg -n "GetFiatCurrency|GetFiatCode|GetInvoiceCurrency|fiatCurrency|FiatCurrency" openmeter/billing/charges -S

Repository: openmeterio/openmeter

Length of output: 23791


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Search GetFiatCurrency/getFiatCode/get InvoiceCurrency:"
rg -n "GetFiatCurrency|GetFiatCode|GetInvoiceCurrency|fiatCurrency|FiatCurrency" openmeter/billing/charges -S

echo
echo "Search all repository usages:"
rg -n "GetFiatCurrency|GetFiatCode|GetInvoiceCurrency" . -S

Repository: openmeterio/openmeter

Length of output: 18434


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "costbasis model relevant sections:"
sed -n '1,280p' openmeter/billing/charges/models/costbasis/model.go

echo
echo "currencyx fiat validation relevant sections:"
sed -n '1,260p' pkg/currencyx/costbasis.go
sed -n '150,210p' pkg/currencyx/currency.go

echo
echo "flatfee charge invoice path:"
sed -n '75,110p' openmeter/billing/charges/flatfee/charge.go

echo
echo "usagebased charge invoice path:"
sed -n '80,110p' openmeter/billing/charges/usagebased/charge.go

echo
echo "read-only nil-pointer behavior probe:"
cat > /tmp/probe.go <<'GO'
package main

type FiatCode string
type FiatCurrency struct{ code FiatCode }

func (f *FiatCurrency) GetFiatCode() FiatCode { return f.code }

type Mode string
type DynamicIntent struct{ FiatCurrency *FiatCurrency }
type PinnedIntent struct{ FiatCurrency *FiatCurrency }
type ManualIntent struct{ FiatCurrency *FiatCurrency }
type Intent struct{ kind Mode; dynamic *DynamicIntent; pinned *PinnedIntent; manual *ManualIntent }

func (i Intent) AsDynamic() (DynamicIntent, error) {
	if i.dynamic == nil { return DynamicIntent{}, nil }
	return *i.dynamic, nil
}
func (i Intent) AsPinned() (PinnedIntent, error) {
	if i.pinned == nil { return PinnedIntent{}, nil }
	return *i.pinned, nil
}
func (i Intent) AsManual() (ManualIntent, error) {
	if i.manual == nil { return ManualIntent{}, nil }
	return *i.manual, nil
}
func (i Intent) GetFiatCurrency() (*FiatCurrency, error) {
	switch i.kind {
	case "dynamic":
		intent, err := i.AsDynamic()
		if err != nil { return nil, err }
		return intent.FiatCurrency, nil
	case "pinned":
		intent, err := i.AsPinned()
		if err != nil { return nil, err }
		return intent.FiatCurrency, nil
	case "manual":
		intent, err := i.AsManual()
		if err != nil { return nil, err }
		return intent.FiatCurrency, nil
	default:
		return nil, nil
	}
}
func GetInvoiceCurrency(i Intent) (FiatCode, string) {
	costBasisIntent, err := i.GetFiatCurrency()
	if err != nil { return "", "error" }
	return costBasisIntent.GetFiatCode(), "ok"
}
func main() {
	code, status := GetInvoiceCurrency(Intent{kind: "dynamic"})
	println("code=", string(code), "status=", status)
	_ = GetInvoiceCurrency(Intent{kind: "dynamic"}) // this could panic
}
GO
run_go="$(command -v go || true)"
if [ -n "$run_go" ]; then
  go test /tmp/probe.go
else
  cat /tmp/probe.go
fi

Repository: openmeterio/openmeter

Length of output: 11902


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Intent currency accessor implementations:"
rg -n "func \\(i Intent\\) (GetCurrency|GetCostBasisIntent|GetCode|FiatCurrency|CostBasisIntent)|AsCurrency|costBasisIntent" openmeter/billing/charges/models/costbasis openmeter/billing/charges/currencies -S || true

echo
echo "Models/costbasis remaining outline:"
ast-grep outline openmeter/billing/charges/models/costbasis/*.go --view expanded || true

echo
echo "CostBasisIntent definition usages:"
rg -n "type CostBasisIntent|CostBasisIntent" openmeter/billing/charges/models openmeter/billing/charges/currencies -S || true

echo
echo "Read-only nil-pointer behavior probe:"
cat > /tmp/probe.go <<'GO'
package main

import (
	"errors"
	"fmt"
)

type FiatCode string
type FiatCurrency struct{ code FiatCode }
type Mode string

func main() {
	var ptr *FiatCurrency
	fmt.Printf("value %#v error=%v panic=%v\n", nil)
	_, err := fmt.Sprint(ptr)
	fmt.Println("print err:", err != nil && errors.Is(err, (*runtime.Error)(nil).Error()) || err != nil)
}
GO
run_go="$(command -v go || true)"
if [ -n "$run_go" ]; then
  go build -o /tmp/probe /tmp/probe.go && /tmp/probe
else
  go doc fmt.Sprint
fi

Repository: openmeterio/openmeter

Length of output: 5354


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Intent methods/usages beyond current files:"
rg -n "\.GetFiatCurrency\(|GetFiatCurrency\(|FiatCurrency\." openmeter -S --glob '*.go'
echo
rg -n "type Intent|func \(i Intent\)|func \(c ChargeBase\)" openmeter -S --glob 'openmeter/billing/charges/**/*.go' || true

echo
echo "ChargeBase methods in relevant charge files:"
sed -n '1,130p' openmeter/billing/charges/flatfee/charge.go
echo "----"
sed -n '1,130p' openmeter/billing/charges/usagebased/charge.go

Repository: openmeterio/openmeter

Length of output: 14491


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Cost model fiat code schema:"
rg -n "FiatCurrency|fiatCurrency|FiatCurrencyValidator" openmeter/ent openmeter/billing/charges -S --glob '*.go' | head -n 220

echo
echo "Schema files:"
for f in $(rg -l "FiatCurrency" openmeter/ent/schema -S --glob '*.go'); do
  echo "--- $f"
  sed -n '1,220p' "$f"
done

echo
echo "Read-only nil validation behavior probe:"
cat > /tmp/probe.go <<'GO'
package main

import (
	"errors"
	"fmt"
)

func Validate(f interface{}) error {
	if f == nil {
		return errors.New("fiat currency is not initialized")
	}
	return nil
}

func main() {
	var ptr *struct{}
	if err := Validate(ptr); err != nil {
		fmt.Println("nil Validate result:", err)
	}
	fmt.Println("done")
}
GO
run_go="$(command -v go || true)"
if [ -n "$run_go" ]; then
  go run /tmp/probe.go || true
else
  cat /tmp/probe.go
fi

Repository: openmeterio/openmeter

Length of output: 28755


Guard the fiat-c currency pointer before dereferencing it.

GetFiatCurrency() can return (nil, nil) for malformed intent data, while the invoice-currency paths call fiatCurrency.GetFiatCode() immediately. Either reject a nil fiat currency here in one place or make the non-nil invariant explicit at construction/persistence and guarded at this accessor.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openmeter/billing/charges/models/costbasis/intent.go` around lines 133 - 160,
Update GetFiatCurrency to validate the FiatCurrency pointer returned by the
ModeDynamic, ModePinned, and ModeManual intent variants before returning
success; return an appropriate validation error when it is nil, while preserving
existing conversion errors and valid non-nil results.

}

type DynamicIntent struct {
FiatCurrency *currencyx.FiatCurrency
}
Expand Down
2 changes: 1 addition & 1 deletion openmeter/billing/charges/service/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ type currencyAndCustomerID struct {
}

type currencyCodeAndCustomerID struct {
currency currencyx.Code
currency currencyx.FiatCode
customerID customer.CustomerID
}

Expand Down
2 changes: 1 addition & 1 deletion openmeter/billing/charges/service/creditpurchase_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -826,7 +826,7 @@ func (s *CreditPurchaseTestSuite) TestStandardInvoiceCreditPurchase() {
s.Require().Len(lines, 1)

line := lines[0]
s.Equal(USD, line.Currency)
s.Equal(currencyx.FiatCode(USD), line.Currency)
s.Equal(timeutil.ClosedPeriod{
From: datetime.MustParseTimeInLocation(s.T(), "2026-01-01T00:00:00Z", time.UTC).AsTime(),
To: datetime.MustParseTimeInLocation(s.T(), "2026-02-01T00:00:00Z", time.UTC).AsTime(),
Expand Down
2 changes: 2 additions & 0 deletions openmeter/billing/charges/service/flatfee_costbasis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ func (s *FlatFeeCostBasisCreateSuite) TestCreatePersistsManualPinnedAndDynamicCo

seenCostBasisIDs := map[string]struct{}{}
for idx, result := range created {
s.Require().NotNil(result.GatheringLineToCreate, "charge index %d", idx)
s.Require().Equal(currencyx.FiatCode("USD"), result.GatheringLineToCreate.Currency, "charge index %d", idx)
s.Require().NotNil(result.Charge.State.CostBasisID, "charge index %d", idx)

reloaded, err := s.mustGetChargeByID(result.Charge.GetChargeID()).AsFlatFeeCharge()
Expand Down
6 changes: 3 additions & 3 deletions openmeter/billing/charges/service/invoicable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ func (s *InvoicableChargesTestSuite) TestFlatFeePartialCreditRealizations() {
gatheringInvoices, err := s.BillingService.ListGatheringInvoices(ctx, billing.ListGatheringInvoicesInput{
Namespaces: []string{ns},
Customers: []string{cust.ID},
Currencies: []currencyx.Code{currencyx.Code(currency.USD)},
Currencies: []currencyx.FiatCode{currencyx.FiatCode(currency.USD)},
Expand: []billing.GatheringInvoiceExpand{billing.GatheringInvoiceExpandLines},
})
s.NoError(err)
Expand Down Expand Up @@ -1363,7 +1363,7 @@ func (s *InvoicableChargesTestSuite) TestUsageBasedCreditOnlyLifecycle() {
gatheringInvoices, err := s.BillingService.ListGatheringInvoices(ctx, billing.ListGatheringInvoicesInput{
Namespaces: []string{ns},
Customers: []string{cust.ID},
Currencies: []currencyx.Code{currencyx.Code(currency.USD)},
Currencies: []currencyx.FiatCode{currencyx.FiatCode(currency.USD)},
Expand: []billing.GatheringInvoiceExpand{billing.GatheringInvoiceExpandLines},
})
s.NoError(err)
Expand Down Expand Up @@ -2759,7 +2759,7 @@ func (s *InvoicableChargesTestSuite) TestFlatFeeCreditOnlyLifecycle() {
gatheringInvoices, err := s.BillingService.ListGatheringInvoices(ctx, billing.ListGatheringInvoicesInput{
Namespaces: []string{ns},
Customers: []string{cust.ID},
Currencies: []currencyx.Code{currencyx.Code(currency.USD)},
Currencies: []currencyx.FiatCode{currencyx.FiatCode(currency.USD)},
Expand: []billing.GatheringInvoiceExpand{billing.GatheringInvoiceExpandLines},
})
s.NoError(err)
Expand Down
3 changes: 2 additions & 1 deletion openmeter/billing/charges/service/invoice.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,11 @@ func (s *service) handleStandardInvoiceUpdate(ctx context.Context, invoice billi
return err
}

currency, err := currencies.NewFiatCurrency(invoice.Currency)
fiatCurrency, err := invoice.Currency.AsFiatCurrency()
if err != nil {
return fmt.Errorf("resolving fiat invoice currency %q: %w", invoice.Currency, err)
}
currency := currencies.Currency{Currency: fiatCurrency}

return s.recognizeCustomerEarnings(ctx, invoice.CustomerID(), currency)
}
Expand Down
5 changes: 1 addition & 4 deletions openmeter/billing/charges/service/pendinglines.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"github.com/openmeterio/openmeter/openmeter/billing/charges/usagebased"
"github.com/openmeterio/openmeter/openmeter/currencies"
"github.com/openmeterio/openmeter/openmeter/productcatalog"
"github.com/openmeterio/openmeter/pkg/currencyx"
"github.com/openmeterio/openmeter/pkg/framework/transaction"
"github.com/openmeterio/openmeter/pkg/slicesx"
)
Expand Down Expand Up @@ -112,9 +111,7 @@ func validateChargePendingInvoiceLinesInput(input charges.CreatePendingInvoiceLi
}

func mapPendingInvoiceLinesToChargeIntents(input charges.CreatePendingInvoiceLinesInput) (charges.ChargeIntents, error) {
currency, err := currencyx.NewCurrencyBuilder(currencyx.CurrencyTypeFiat).
WithCode(input.Currency).
Build()
currency, err := input.Currency.AsFiatCurrency()
if err != nil {
return nil, fmt.Errorf("resolving fiat currency %q: %w", input.Currency, err)
}
Expand Down
25 changes: 13 additions & 12 deletions openmeter/billing/charges/service/pendinglines_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/openmeterio/openmeter/openmeter/billing/charges"
"github.com/openmeterio/openmeter/openmeter/billing/charges/meta"
"github.com/openmeterio/openmeter/openmeter/productcatalog"
"github.com/openmeterio/openmeter/pkg/currencyx"
"github.com/openmeterio/openmeter/pkg/datetime"
"github.com/openmeterio/openmeter/pkg/models"
"github.com/openmeterio/openmeter/pkg/timeutil"
Expand Down Expand Up @@ -46,7 +47,7 @@ func (s *InvoicableChargesTestSuite) TestCreatePendingInvoiceLinesCreatesChargeB
}),
ManagedBy: billing.ManuallyManagedLine,
Engine: billing.LineEngineTypeInvoice,
Currency: USD,
Currency: currencyx.FiatCode(USD),
ServicePeriod: servicePeriod,
InvoiceAt: servicePeriod.To,
Price: lo.FromPtr(productcatalog.NewPriceFrom(productcatalog.UnitPrice{
Expand All @@ -70,7 +71,7 @@ func (s *InvoicableChargesTestSuite) TestCreatePendingInvoiceLinesCreatesChargeB
InvoiceAt: servicePeriod.From,
ManagedBy: billing.ManuallyManagedLine,
Name: "manual flat",
Currency: USD,
Currency: currencyx.FiatCode(USD),
PerUnitAmount: alpacadecimal.NewFromInt(10),
PaymentTerm: productcatalog.InAdvancePaymentTerm,
RateCardDiscounts: billing.Discounts{
Expand All @@ -86,7 +87,7 @@ func (s *InvoicableChargesTestSuite) TestCreatePendingInvoiceLinesCreatesChargeB

result, err := s.Charges.CreatePendingInvoiceLines(ctx, charges.CreatePendingInvoiceLinesInput{
Customer: cust.GetID(),
Currency: USD,
Currency: currencyx.FiatCode(USD),
Lines: []billing.GatheringLine{
usageLine,
flatLine,
Expand Down Expand Up @@ -154,7 +155,7 @@ func (s *InvoicableChargesTestSuite) TestCreatePendingInvoiceLinesRollsBackCreat
InvoiceAt: servicePeriod.From,
ManagedBy: billing.ManuallyManagedLine,
Name: "manual zero flat",
Currency: USD,
Currency: currencyx.FiatCode(USD),
PerUnitAmount: alpacadecimal.Zero,
PaymentTerm: productcatalog.InAdvancePaymentTerm,
})
Expand All @@ -163,7 +164,7 @@ func (s *InvoicableChargesTestSuite) TestCreatePendingInvoiceLinesRollsBackCreat

result, err := s.Charges.CreatePendingInvoiceLines(ctx, charges.CreatePendingInvoiceLinesInput{
Customer: cust.GetID(),
Currency: USD,
Currency: currencyx.FiatCode(USD),
Lines: []billing.GatheringLine{
zeroFlatLine,
},
Expand Down Expand Up @@ -198,14 +199,14 @@ func (s *InvoicableChargesTestSuite) TestCreatePendingInvoiceLinesRejectsNonManu
InvoiceAt: servicePeriod.From,
ManagedBy: billing.SystemManagedLine,
Name: "system flat",
Currency: USD,
Currency: currencyx.FiatCode(USD),
PerUnitAmount: alpacadecimal.NewFromInt(10),
PaymentTerm: productcatalog.InAdvancePaymentTerm,
})

_, err := s.Charges.CreatePendingInvoiceLines(ctx, charges.CreatePendingInvoiceLinesInput{
Customer: cust.GetID(),
Currency: USD,
Currency: currencyx.FiatCode(USD),
Lines: []billing.GatheringLine{
systemLine,
},
Expand All @@ -219,7 +220,7 @@ func (s *InvoicableChargesTestSuite) TestCreatePendingInvoiceLinesRejectsNonManu
InvoiceAt: servicePeriod.From,
ManagedBy: billing.ManuallyManagedLine,
Name: "subscription flat",
Currency: USD,
Currency: currencyx.FiatCode(USD),
PerUnitAmount: alpacadecimal.NewFromInt(10),
PaymentTerm: productcatalog.InAdvancePaymentTerm,
})
Expand All @@ -232,7 +233,7 @@ func (s *InvoicableChargesTestSuite) TestCreatePendingInvoiceLinesRejectsNonManu

_, err = s.Charges.CreatePendingInvoiceLines(ctx, charges.CreatePendingInvoiceLinesInput{
Customer: cust.GetID(),
Currency: USD,
Currency: currencyx.FiatCode(USD),
Lines: []billing.GatheringLine{
subscriptionLine,
},
Expand Down Expand Up @@ -270,7 +271,7 @@ func (s *InvoicableChargesTestSuite) TestCreatePendingInvoiceLinesRollsBackParti
}),
ManagedBy: billing.ManuallyManagedLine,
Engine: billing.LineEngineTypeInvoice,
Currency: USD,
Currency: currencyx.FiatCode(USD),
ServicePeriod: servicePeriod,
InvoiceAt: servicePeriod.To,
Price: lo.FromPtr(productcatalog.NewPriceFrom(productcatalog.UnitPrice{
Expand All @@ -286,15 +287,15 @@ func (s *InvoicableChargesTestSuite) TestCreatePendingInvoiceLinesRollsBackParti
InvoiceAt: servicePeriod.From,
ManagedBy: billing.ManuallyManagedLine,
Name: "manual zero flat",
Currency: USD,
Currency: currencyx.FiatCode(USD),
PerUnitAmount: alpacadecimal.Zero,
PaymentTerm: productcatalog.InAdvancePaymentTerm,
})
zeroFlatLine.Engine = billing.LineEngineTypeInvoice

result, err := s.Charges.CreatePendingInvoiceLines(ctx, charges.CreatePendingInvoiceLinesInput{
Customer: cust.GetID(),
Currency: USD,
Currency: currencyx.FiatCode(USD),
Lines: []billing.GatheringLine{
usageLine,
zeroFlatLine,
Expand Down
Loading
Loading