billing

package
v1.0.0-beta.227 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 12, 2026 License: Apache-2.0 Imports: 29 Imported by: 0

README

Billing

This package contains the implementation for the billing stack (invoicing, tax and payments).

The package has the following main entities:

BillingProfile

Captures all the billing details, two main information is stored inside:

  • The billing workflow (when to invoice, due periods etc)
  • References to the apps responsible for tax, invoicing and payments (Sandbox or Stripe for now)

Only one default billing profile can exist per namespace.

CustomerOverride

Contains customer specific overrides for billing pruposes. It can reference a billing profile other than the default (e.g. when different apps or lifecycle should be used) and allows to override the billing workflow.

Invoice

Invoices are used to store the data required by tax, invoicing and payment app's master copy at OpenMeter side.

Upon creation all the data required to generate invoices are snapshotted into the invoice entity, so that no updates to entities like Customer, BillingProfile, CustomerOverride change an invoice retrospectively.

Gathering invoices

There are two general kinds of invoices (Invoice.Status) gathering invoices are used to collect upcoming lines that are to be added to future invoices. gathering invocie's state never changes: when upcoming line items become due, they are just assigned to a new invoice, so that we clone the data required afresh.

Each customer can have one gathering issue per currency.

For example, if the customer has upcoming charges in USD and HUF, then there will be one gathering invoice for HUF and one for USD.

If there are no upcoming items, the gathering invoices are (soft) deleted.

Collection

TODO: document when implemented

Invoices

The invoices are governed by the invoice state machine.

Invoices are composed of lines. Each invoice can only have lines from the same currency.

The lines can be of different types:

  • Fee: one time charge
  • UsageBased: usage-based charge (can be used to charge additional usage-based prices without the product catalog features)

Each line has a period (start, end) and an invoiceAt property. The period specifies which period of time the line is referring to (in case of usage-based pricing, the underlying meter will be queried for this time-period). invoiceAt specifies the time when it is expected to create an invoice that contains this line. The invoice's collection settings can defer this.

Invoices are always created by collecting one or more line from the gathering invoices. The /v1/api/billing/invoices/lines endpoint can be used to create new future line items. A new invoice can be created any time. In such case, the gathering items to be invoiced (invoiceAt) are already added to the invoice. Any usage-based line, that we can bill early is also added to the invoice for the period between the period.start of the line and the time of invoice creation.

Line splitting

To achieve the behavior described above, we are using line splitting. By default we would have one line per billing period that would eventually be part of an invoice:

 period.start                                              period.end
Line1 [status=valid] |--------------------------------------------------------|

When the usage-based line can be billed mid-period, we split the line into two:

 period.start              asOf                              period.end
Line1 [status=split]         |--------------------------------------------------------|
SplitLine1 [status=valid]    |------------------|
SplitLine2 [status=valid]                       |-------------------------------------|

As visible:

  • Line1's status changes from valid to split: it will be ignored in any calculation, it becomes a grouping line between invoices
  • SplitLine1 is created with a period between period.start and asof (time of invoicing): it will be addedd to the freshly created invoice
  • SplitLine2 is created with a period between asof and period.end: it will be pushed to the gathering invoice

When creating a new invoice between asof and period.end the same logic continues, but without marking SplitLine2 split, instead the new line is added to the original line's parent line:

 period.start              asOf1          asof2                period.end
Line1 [status=split]         |--------------------------------------------------------|
SplitLine1 [status=valid]    |------------------|
SplitLine2 [status=valid]                       |---------------|
SplitLine3 [status=valid]                                       |---------------------|

This flattening approach allows us not to have to recursively traverse lines in the database.

Usage-based quantity

When a line is created for an invoice, the quantity of the underlying meter is captured into the line's qty field. This information is never updated, so late events will have to create new invoice lines when needed.

Detailed Lines

Each (valid) line can have one or more detailed lines (children). These lines represent the actual sub-charges that are caused by the parent line.

Example:

If a line has:

  • Usage of 200 units
  • Tiered pricing:
  • Tier1: 1 - 50 units cost flat $300
  • Tier2: 51 - 100 units cost flat $400
  • Tier3: 100 - 150 units cost flat $400 + $1/unit
  • Tier4: more than 150 units cost $15/unit

This would yield the following lines:

  • Line with quantity=200
    • Line quantity=1 per_unit_amount=300 total=300 (Tier1)
    • Line quantity=1 per_unit_amount=400 total=400 (Tier2)
    • Line quantity=1 per_unit_amount=400 total=400 (Tier3, flat component)
    • Line quantity=50 per_unit_amount=1 total=50 (Tier3, per unit price)
    • Line quantity=50 per_unit_amount=15 total=759 (Tier4)

Apps can choose to synchronize the original line (if the upstream system understands our pricing model) or can use the sublines to synchronize individual lines without having to understand billing details.

Detailed Lines vs Splitting

When we are dealing with a split line, the calculation of the quantity is by taking the meter's quantity for the whole line period ([parent.period.start, splitline.period.end]) and the amount before the period (parent.period.start, splitline.period.start).

When substracting the two we get the delta for the period (this gets the delta for all supported meter types except of Min and Avg).

We execute the pricing logic (e.g. tiered pricing) for the line qty, while considering the before usage, as it reflects the already billed for items.

Corner cases:

  • Graduating tiered prices cannot be billed mid-billing period (always arrears, as the calculation cannot be split into multiple items)
  • Min, Avg meters are always billed arrears as we cannot calculate the delta.
Detailed line persisting

In order for the calculation logic, to not to have to deal with the contents of the database, it is (mostly) the adapter layer's responsibility to understand what have changed and persist only that data to the database.

In practice the high level rules are the following (see adapter/invoicelinediff_test.go for examples):

  • If an entity has an ID then it will be updated
  • If an entity has changed compared to the database fetch, it will be updated
  • If a child line, discount gets removed, it will be removed from the database (in case of lines with all sub-entities)
  • If an entity doesn't have an ID a new entity will be generated by the database

For idempotent entity sources (detailed lines and discounts for now), we have also added a field called ChildUniqueReferenceID which can be used to detect entities serving the same purpose.

ChildUniqueReferenceID example

Let's say we have an usage-based line whose detailed lines are persisted to the database, but then we would want to change the quantity of the line.

First we load the existing detailed lines from the database, and save the database versions of the entities in memory.

We execute the calculation for the new quantity that yields new detailed lines without database IDs.

The entity's ChildrenWithIDReuse call can be used to facilitate the line reuse by assigning the known IDs to the yielded lines where the ChildUniqueReferenceID is set.

Then the adapter layer will use those IDs to make decisions if they want to persist or recreate the records.

We could do the same logic in the adapter layer, but this approach makes it more flexible on the calculation layer if we want to generate new lines or not. If this becomes a burden we can do the same matching logic as part of the upsert logic in adapter.

Subscription adapter

The subscription adapter is responsible for feeding the billing with line items during the subscription's lifecycle. The generation of items is event-driven, new items are yielded when:

  • A subscription is created
  • A new invoice is created
  • A subscription is modified
  • Upgrade/Downgrade is handled as a subscription create/cancel

Documentation

Index

Constants

View Source
const (
	// AnnotationSubscriptionSyncIgnore is used to mark a line or hierarchy as ignored in subscription syncing.
	// Should be used in case there is a breaking change in the subscription synchronization process, preventing billing
	// from issuing credit notes for the past periods.
	AnnotationSubscriptionSyncIgnore = "billing.subscription.sync.ignore"

	// AnnotationSubscriptionSyncForceContinuousLines is used to force the creation of continuous subscription item lines.
	// If the sync process finds a previously existing line with this annotation, and the next line generated will not start at the end of the previously
	// found line, the sync process will adjust the start of the next line to the end of the previously found line, so that we don't have gaps in the
	// invoices.
	AnnotationSubscriptionSyncForceContinuousLines = "billing.subscription.sync.force-continuous-lines"
)
View Source
const (
	EntityCustomerOverride = "BillingCustomerOverride"
	EntityCustomer         = "Customer"
	EntityDefaultProfile   = "DefaultBillingProfile"
	EntityInvoice          = "Invoice"
	EntityInvoiceLine      = "InvoiceLine"
)
View Source
const (
	CustomerUsageAttributionTypeVersionV1 = "customer_usage_attribution.v1"
	CustomerUsageAttributionTypeVersionV2 = "customer_usage_attribution.v2"
)
View Source
const (
	ValidationIssueSeverityCritical ValidationIssueSeverity = "critical"
	ValidationIssueSeverityWarning  ValidationIssueSeverity = "warning"

	ValidationComponentOpenMeter         = "openmeter"
	ValidationComponentOpenMeterMetering = "openmeter.metering"
)
View Source
const (
	EventSubsystem metadata.EventSubsystem = "billing"
)
View Source
const (
	ImmutableInvoiceHandlingNotSupportedErrorCode = "immutable_invoice_handling_not_supported"
)
View Source
const (
	// LineMaximumSpendReferenceID is a discount applied due to maximum spend.
	LineMaximumSpendReferenceID = "line_maximum_spend"
)

Variables

View Source
var (
	ErrDefaultProfileNotFound        = NewValidationError("default_profile_not_found", "default profile not found")
	ErrProfileNotFound               = NewValidationError("profile_not_found", "profile not found")
	ErrProfileAlreadyDeleted         = NewValidationError("profile_already_deleted", "profile already deleted")
	ErrProfileReferencedByOverrides  = NewValidationError("profile_referenced", "profile is referenced by customer overrides")
	ErrDefaultProfileCannotBeDeleted = NewValidationError("default_profile_cannot_be_deleted", "default profile cannot be deleted")
	ErrDefaultProfileCannotBeUnset   = NewValidationError("default_profile_cannot_be_unset", "default profile cannot be unset")

	ErrCustomerOverrideNotFound       = NewValidationError("customer_override_not_found", "customer override not found")
	ErrCustomerOverrideAlreadyDeleted = NewValidationError("customer_override_deleted", "customer override already deleted")
	ErrCustomerNotFound               = NewValidationError("customer_not_found", "customer not found")
	ErrCustomerDeleted                = NewValidationError("customer_deleted", "customer has been deleted")

	ErrFieldRequired             = NewValidationError("field_required", "field is required")
	ErrFieldMustBePositive       = NewValidationError("field_must_be_positive", "field must be positive")
	ErrFieldMustBePositiveOrZero = NewValidationError("field_must_be_positive_or_zero", "field must be positive or zero")

	ErrInvoiceCannotAdvance                  = NewValidationError("invoice_cannot_advance", "invoice cannot advance")
	ErrInvoiceCannotBeEdited                 = NewValidationError("invoice_cannot_be_edited", "invoice cannot be edited in the current state")
	ErrInvoiceActionNotAvailable             = NewValidationError("invoice_action_not_available", "invoice action not available")
	ErrInvoiceProgressiveBillingNotSupported = NewValidationError("invoice_progressive_billing_not_supported", "progressive billing is not supported")
	ErrInvoiceLinesNotBillable               = NewValidationError("invoice_lines_not_billable", "invoice lines are not billable")
	ErrInvoiceEmpty                          = NewValidationError("invoice_empty", "invoice is empty")
	ErrInvoiceNotFound                       = NewValidationError("invoice_not_found", "invoice not found")
	ErrInvoiceDeleteFailed                   = NewValidationError("invoice_delete_failed", "invoice delete failed")
	ErrInvoiceCannotDeleteGathering          = NewValidationError("invoice_cannot_delete_gathering", "gathering invoices cannot be deleted, please delete the upcoming lines instead")

	ErrInvoiceLineFeatureHasNoMeters                             = NewValidationError("invoice_line_feature_has_no_meters", "usage based invoice line: feature has no meters")
	ErrInvoiceLineVolumeSplitNotSupported                        = NewValidationError("invoice_line_graduated_split_not_supported", "graduated tiered pricing is not supported for split periods")
	ErrInvoiceLineNoTiers                                        = NewValidationError("invoice_line_no_tiers", "usage based invoice line: no tiers found")
	ErrInvoiceLineMissingOpenEndedTier                           = NewValidationError("invoice_line_missing_open_ended_tier", "usage based invoice line: missing open ended tier")
	ErrInvoiceLineDeleteInvalidStatus                            = NewValidationError("invoice_line_delete_invalid_status", "invoice line cannot be deleted in the current state (only valid lines can be deleted)")
	ErrInvoiceLineNoPeriodChangeForSplitLine                     = NewValidationError("invoice_line_no_period_change_for_split_line", "invoice line period cannot be changed for split lines")
	ErrInvoiceLineProgressiveBillingUsageDiscountUpdateForbidden = NewValidationError("invoice_line_progressive_billing_usage_discount_update_forbidden", "usage discount cannot be updated on a partially invoiced line")
	ErrInvoiceCreateNoLines                                      = NewValidationError("invoice_create_no_lines", "the new invoice would have no lines")
	ErrInvoiceCreateUBPLineCustomerUsageAttributionInvalid       = NewValidationError("invoice_create_ubp_line_customer_has_no_subjects", "creating an usage based line: customer usage attribution is invalid")
	ErrInvoiceCreateUBPLinePeriodIsEmpty                         = NewValidationError("invoice_create_ubp_line_period_is_empty", "creating an usage based line: truncated period is empty")
	ErrInvoiceLineCurrencyMismatch                               = NewValidationError("invoice_line_currency_mismatch", "invoice line currency mismatch")
	ErrInvoiceLineSnapshotFailed                                 = NewValidationError("invoice_line_snapshot_failed", "invoice line snapshot failed")

	ErrInvoiceDiscountInvalidLineReference                  = NewValidationError("invoice_discount_invalid_line_reference", "invoice discount references non-existing line")
	ErrInvoiceDiscountNoWildcardDiscountOnGatheringInvoices = NewValidationError("invoice_discount_no_wildcard_discount_on_gathering_invoices", "wildcard discount on gathering invoices is not allowed")

	ErrNamespaceLocked = NewValidationError("namespace_locked", "namespace is locked")
)
View Source
var (
	GatheringInvoiceSequenceNumber = SequenceDefinition{
		Prefix:         "GATHER",
		SuffixTemplate: "{{.CustomerPrefix}}-{{.Currency}}-{{.NextSequenceNumber}}",
		Scope:          "invoices/gathering",
	}
	DraftInvoiceSequenceNumber = SequenceDefinition{
		Prefix:         "DRAFT",
		SuffixTemplate: "{{.CustomerPrefix}}-{{.NextSequenceNumber}}",
		Scope:          "invoices/draft",
	}
)
View Source
var CustomerOverrideExpandAll = CustomerOverrideExpand{
	Apps:     true,
	Customer: true,
}
View Source
var DefaultWorkflowConfig = WorkflowConfig{
	Collection: CollectionConfig{
		Alignment: AlignmentKindSubscription,
		Interval:  lo.Must(datetime.ISODurationString("PT1H").Parse()),
	},
	Invoicing: InvoicingConfig{
		AutoAdvance:        true,
		DraftPeriod:        lo.Must(datetime.ISODurationString("P0D").Parse()),
		DueAfter:           lo.Must(datetime.ISODurationString("P30D").Parse()),
		ProgressiveBilling: true,
		DefaultTaxConfig:   nil,
	},
	Payment: PaymentConfig{
		CollectionMethod: CollectionMethodChargeAutomatically,
	},
	Tax: WorkflowTaxConfig{

		Enabled: true,

		Enforced: false,
	},
}
View Source
var InvoiceExpandAll = InvoiceExpand{
	Preceding:    true,
	Lines:        true,
	DeletedLines: false,
}
View Source
var ProfileExpandAll = ProfileExpand{
	Apps: true,
}

Functions

func EncodeValidationIssues

func EncodeValidationIssues[T error](err T) map[string]interface{}

func ReuseIDsFrom

func ReuseIDsFrom[T entityWithReusableIDs[T]](currentItems []T, dbExistingItems []T) []T

ReuseIDsFrom reuses the IDs of the existing discounts by child unique reference ID.

func ValidationWithComponent

func ValidationWithComponent(component ComponentName, err error) error

ValidationWithComponent wraps an error with a component name, if error is nil, it returns nil This can be used to add context to an error when we are crossing service boundaries.

func ValidationWithFieldPrefix

func ValidationWithFieldPrefix(prefix string, err error) error

ValidationWithFieldPrefix wraps an error with a field prefix, if error is nil, it returns nil This can be used to delegate validation duties to a sub-entity. (e.g. lines don't need to know about the path in the invoice they are residing at)

func WithFeatureKey

func WithFeatureKey(fk string) usageBasedLineOption

Types

type AdapterGetProfileResponse

type AdapterGetProfileResponse struct {
	BaseProfile

	WorkflowConfigID string `json:"workflowConfigId"`
}

func (*AdapterGetProfileResponse) BaseProfileOrEmpty

func (r *AdapterGetProfileResponse) BaseProfileOrEmpty() *BaseProfile

type AdvanceInvoiceInput

type AdvanceInvoiceInput = InvoiceID

type AdvanceStandardInvoiceEvent

type AdvanceStandardInvoiceEvent struct {
	Invoice    InvoiceID `json:"invoice"`
	CustomerID string    `json:"customer_id"`
}

func (AdvanceStandardInvoiceEvent) EventMetadata

func (AdvanceStandardInvoiceEvent) EventName

func (e AdvanceStandardInvoiceEvent) EventName() string

func (AdvanceStandardInvoiceEvent) Validate

func (e AdvanceStandardInvoiceEvent) Validate() error

type AdvancementStrategy

type AdvancementStrategy string
const (
	// ForgegroundAdvancementStrategy is the strategy where the invoice is advanced immediately as part
	// of the same transaction. Should be used in workers as advancement might take long time and we don't want
	// to block a HTTP request for that long.
	ForegroundAdvancementStrategy AdvancementStrategy = "foreground"
	// QueuedAdvancementStrategy is the strategy where the invoice is advanced in a separate worker (billing-worker).
	// This is useful for cases where the advancement might take a long time and we don't want to block the current
	// HTTP request.
	QueuedAdvancementStrategy AdvancementStrategy = "queued"
)

func (AdvancementStrategy) Validate

func (s AdvancementStrategy) Validate() error

type AlignmentKind

type AlignmentKind string

AlignmentKind specifies what governs when an invoice is issued

const (
	// AlignmentKindSubscription specifies that the invoice is issued based on the subscription period (
	// e.g. whenever a due line item is added, it will trigger an invoice generation after the collection period)
	AlignmentKindSubscription AlignmentKind = "subscription"

	// AlignmentKindAnchored specifies that the invoice is issued based on the cadence detail.
	// Using this mode results in separate invoices for each invoicable batch of lines.
	AlignmentKindAnchored AlignmentKind = "anchored"

	// THIS IS NOT YET SUPPORTED (this will enable single-invoice mode in effect)
	// AlignmentKindAnchoredBatch specifies that the invoice is issued based on the cadence detail.
	// Using this mode results in all lines added to the gathering invoice in the period
	// until the next recurrence will be invoiced in a single batch at the next recurrence of the anchor.
	AlignmentKindAnchoredBatch AlignmentKind = "anchored_batch"
)

func (AlignmentKind) Validate

func (k AlignmentKind) Validate() error

func (AlignmentKind) Values

func (k AlignmentKind) Values() []string

type AmountLineDiscount

type AmountLineDiscount struct {
	LineDiscountBase `json:",inline"`

	Amount alpacadecimal.Decimal `json:"amount"`

	// RoundingAmount is a correction value, to ensure that if multiple discounts are applied,
	// then sum of discount amounts equals the total * sum(discount percentages).
	RoundingAmount alpacadecimal.Decimal `json:"roundingAmount"`
}

func (AmountLineDiscount) Clone

func (AmountLineDiscount) Equal

func (AmountLineDiscount) Validate

func (i AmountLineDiscount) Validate() error

type AmountLineDiscountManaged

type AmountLineDiscountManaged struct {
	models.ManagedModelWithID `json:",inline"`
	AmountLineDiscount        `json:",inline"`
}

func (AmountLineDiscountManaged) Clone

func (AmountLineDiscountManaged) ContentsEqual

func (AmountLineDiscountManaged) Equal

func (AmountLineDiscountManaged) GetManagedFieldsWithID

func (i AmountLineDiscountManaged) GetManagedFieldsWithID() models.ManagedModelWithID

func (AmountLineDiscountManaged) Validate

func (i AmountLineDiscountManaged) Validate() error

func (AmountLineDiscountManaged) WithManagedFieldsWithID

type AmountLineDiscountsManaged

type AmountLineDiscountsManaged []AmountLineDiscountManaged

func (AmountLineDiscountsManaged) Clone

func (AmountLineDiscountsManaged) GetByID

func (AmountLineDiscountsManaged) GetDiscountByChildUniqueReferenceID

func (i AmountLineDiscountsManaged) GetDiscountByChildUniqueReferenceID(childUniqueReferenceID string) (AmountLineDiscountManaged, bool)

func (AmountLineDiscountsManaged) Mutate

func (AmountLineDiscountsManaged) ReuseIDsFrom

func (AmountLineDiscountsManaged) SumAmount

func (AmountLineDiscountsManaged) Validate

func (i AmountLineDiscountsManaged) Validate() error

type AnchoredAlignmentDetail

type AnchoredAlignmentDetail struct {
	Interval datetime.ISODuration `json:"interval"`
	Anchor   time.Time            `json:"anchor"`
}

func (*AnchoredAlignmentDetail) Validate

func (a *AnchoredAlignmentDetail) Validate() error

type AppError

type AppError struct {
	AppID   app.AppID
	AppType app.AppType
	Err     error
}

func (AppError) Error

func (e AppError) Error() string

type ApproveInvoiceInput

type ApproveInvoiceInput = InvoiceID

type AssociatedLineCountsAdapterInput

type AssociatedLineCountsAdapterInput = genericMultiInvoiceInput

type AssociatedLineCountsAdapterResponse

type AssociatedLineCountsAdapterResponse struct {
	Counts map[InvoiceID]int64
}

type BaseProfile

type BaseProfile struct {
	ID        string `json:"id"`
	Namespace string `json:"namespace"`

	Name        string  `json:"name"`
	Description *string `json:"description,omitempty"`

	CreatedAt time.Time  `json:"createdAt"`
	UpdatedAt time.Time  `json:"updatedAt"`
	DeletedAt *time.Time `json:"deletedAt,omitempty"`

	WorkflowConfig WorkflowConfig `json:"workflow"`

	Supplier SupplierContact `json:"supplier"`

	Default  bool     `json:"default"`
	Metadata Metadata `json:"metadata"`

	AppReferences *ProfileAppReferences `json:"appReferences,omitempty"`
}

func (BaseProfile) ProfileID

func (p BaseProfile) ProfileID() ProfileID

func (BaseProfile) Validate

func (p BaseProfile) Validate() error

type BulkAssignCustomersToProfileInput

type BulkAssignCustomersToProfileInput struct {
	ProfileID   ProfileID
	CustomerIDs []customer.CustomerID
}

func (BulkAssignCustomersToProfileInput) Validate

type CollectionConfig

type CollectionConfig struct {
	Alignment               AlignmentKind            `json:"alignment"`
	AnchoredAlignmentDetail *AnchoredAlignmentDetail `json:"anchoredAlignmentDetail,omitempty"`
	Interval                datetime.ISODuration     `json:"period,omitempty"`
}

CollectionConfig groups fields related to item collection.

func (*CollectionConfig) Validate

func (c *CollectionConfig) Validate() error

type CollectionMethod

type CollectionMethod string
const (
	// CollectionMethodChargeAutomatically charges the customer automatically based on previously saved card data
	CollectionMethodChargeAutomatically CollectionMethod = "charge_automatically"
	// CollectionMethodSendInvoice sends an invoice to the customer along with the payment instructions/links
	CollectionMethodSendInvoice CollectionMethod = "send_invoice"
)

func (CollectionMethod) Values

func (c CollectionMethod) Values() []string

type CollectionOverrideConfig

type CollectionOverrideConfig struct {
	Alignment               *AlignmentKind           `json:"alignment,omitempty"`
	AnchoredAlignmentDetail *AnchoredAlignmentDetail `json:"anchoredAlignmentDetail,omitempty"`
	Interval                *datetime.ISODuration    `json:"interval,omitempty"`
}

func (*CollectionOverrideConfig) Validate

func (c *CollectionOverrideConfig) Validate() error

type ComponentName

type ComponentName string

func AppTypeCapabilityToComponent

func AppTypeCapabilityToComponent(appType app.AppType, cap app.CapabilityType, op string) ComponentName

type ConfigService

type ConfigService interface {
	GetAdvancementStrategy() AdvancementStrategy
	WithAdvancementStrategy(strategy AdvancementStrategy) Service
	WithLockedNamespaces(namespaces []string) Service
}

type CreateCustomerOverrideAdapterInput

type CreateCustomerOverrideAdapterInput = UpdateCustomerOverrideAdapterInput

type CreateGatheringInvoiceAdapterInput

type CreateGatheringInvoiceAdapterInput struct {
	Namespace string
	Number    string
	Currency  currencyx.Code
	Metadata  map[string]string

	Description      *string
	NextCollectionAt *time.Time

	// TODO[later]: This should be just a CustomerID once we have split the invoices table
	Customer      customer.Customer
	MergedProfile Profile
}

func (CreateGatheringInvoiceAdapterInput) Validate

type CreateInvoiceAdapterInput

type CreateInvoiceAdapterInput struct {
	Namespace string
	Customer  customer.Customer
	Profile   Profile
	Number    string
	Currency  currencyx.Code
	Status    StandardInvoiceStatus
	Metadata  map[string]string
	IssuedAt  time.Time

	Type         InvoiceType
	Description  *string
	DueAt        *time.Time
	CollectionAt *time.Time

	Totals Totals
}

func (CreateInvoiceAdapterInput) Validate

func (c CreateInvoiceAdapterInput) Validate() error

type CreateInvoiceAdapterRespone

type CreateInvoiceAdapterRespone = StandardInvoice

type CreatePendingInvoiceLinesInput

type CreatePendingInvoiceLinesInput struct {
	Customer customer.CustomerID `json:"customer"`
	Currency currencyx.Code      `json:"currency"`

	Lines []GatheringLine `json:"lines"`
}

func (CreatePendingInvoiceLinesInput) Validate

type CreatePendingInvoiceLinesResult

type CreatePendingInvoiceLinesResult struct {
	Lines        []GatheringLine
	Invoice      GatheringInvoice
	IsInvoiceNew bool
}

type CreateProfileAppsInput

type CreateProfileAppsInput = ProfileAppReferences

type CreateProfileInput

type CreateProfileInput struct {
	Namespace   string            `json:"namespace"`
	Name        string            `json:"name"`
	Description *string           `json:"description,omitempty"`
	Metadata    map[string]string `json:"metadata"`
	Supplier    SupplierContact   `json:"supplier"`
	Default     bool              `json:"default"`

	WorkflowConfig WorkflowConfig         `json:"workflowConfig"`
	Apps           CreateProfileAppsInput `json:"apps"`
}

func (CreateProfileInput) Validate

func (i CreateProfileInput) Validate() error

type CreateSplitLineGroupAdapterInput

type CreateSplitLineGroupAdapterInput = SplitLineGroupCreate

Adapter

type CreateWorkflowConfigInput

type CreateWorkflowConfigInput struct {
	WorkflowConfig
}

type CustomerMetadata

type CustomerMetadata struct {
	Name string `json:"name"`
}

type CustomerOverride

type CustomerOverride struct {
	Namespace string `json:"namespace"`
	ID        string `json:"id"`

	CreatedAt time.Time  `json:"createdAt"`
	UpdatedAt time.Time  `json:"updatedAt"`
	DeletedAt *time.Time `json:"deletedAt,omitempty"`

	CustomerID string   `json:"customerID"`
	Profile    *Profile `json:"billingProfile,omitempty"`

	Collection CollectionOverrideConfig `json:"collection"`
	Invoicing  InvoicingOverrideConfig  `json:"invoicing"`
	Payment    PaymentOverrideConfig    `json:"payment"`
}

func (CustomerOverride) Validate

func (c CustomerOverride) Validate() error

type CustomerOverrideAdapter

type CustomerOverrideAdapter interface {
	CreateCustomerOverride(ctx context.Context, input UpdateCustomerOverrideAdapterInput) (*CustomerOverride, error)
	GetCustomerOverride(ctx context.Context, input GetCustomerOverrideAdapterInput) (*CustomerOverride, error)
	UpdateCustomerOverride(ctx context.Context, input UpdateCustomerOverrideAdapterInput) (*CustomerOverride, error)
	DeleteCustomerOverride(ctx context.Context, input DeleteCustomerOverrideInput) error
	ListCustomerOverrides(ctx context.Context, input ListCustomerOverridesInput) (ListCustomerOverridesAdapterResult, error)

	BulkAssignCustomersToProfile(ctx context.Context, input BulkAssignCustomersToProfileInput) error

	GetCustomerOverrideReferencingProfile(ctx context.Context, input HasCustomerOverrideReferencingProfileAdapterInput) ([]customer.CustomerID, error)
}

type CustomerOverrideExpand

type CustomerOverrideExpand struct {
	// Apps specifies if the merged profile should include the apps
	Apps bool `json:"apps,omitempty"`

	// Customer specifies if the customer should be included in the response
	Customer bool `json:"customer,omitempty"`
}

type CustomerOverrideOrderBy

type CustomerOverrideOrderBy string
const (
	CustomerOverrideOrderByCustomerID           CustomerOverrideOrderBy = "customerId"
	CustomerOverrideOrderByCustomerName         CustomerOverrideOrderBy = "customerName"
	CustomerOverrideOrderByCustomerKey          CustomerOverrideOrderBy = "customerKey"
	CustomerOverrideOrderByCustomerPrimaryEmail CustomerOverrideOrderBy = "customerPrimaryEmail"
	CustomerOverrideOrderByCustomerCreatedAt    CustomerOverrideOrderBy = "customerCreatedAt"

	DefaultCustomerOverrideOrderBy CustomerOverrideOrderBy = CustomerOverrideOrderByCustomerID
)

func (CustomerOverrideOrderBy) Validate

func (o CustomerOverrideOrderBy) Validate() error

type CustomerOverrideService

type CustomerOverrideService interface {
	UpsertCustomerOverride(ctx context.Context, input UpsertCustomerOverrideInput) (CustomerOverrideWithDetails, error)
	DeleteCustomerOverride(ctx context.Context, input DeleteCustomerOverrideInput) error

	GetCustomerOverride(ctx context.Context, input GetCustomerOverrideInput) (CustomerOverrideWithDetails, error)
	GetCustomerApp(ctx context.Context, input GetCustomerAppInput) (app.App, error)
	ListCustomerOverrides(ctx context.Context, input ListCustomerOverridesInput) (ListCustomerOverridesResult, error)
}

type CustomerOverrideWithAdapterProfile

type CustomerOverrideWithAdapterProfile struct {
	CustomerOverride `json:",inline"`

	DefaultProfile *AdapterGetProfileResponse `json:"billingProfile,omitempty"`
}

type CustomerOverrideWithCustomerID

type CustomerOverrideWithCustomerID struct {
	*CustomerOverride `json:",inline"`

	CustomerID customer.CustomerID `json:"customerID,omitempty"`
}

type CustomerOverrideWithDetails

type CustomerOverrideWithDetails struct {
	CustomerOverride *CustomerOverride `json:",inline"`
	MergedProfile    Profile           `json:"mergedProfile,omitempty"`

	// Expanded fields
	Expand   CustomerOverrideExpand `json:"expand,omitempty"`
	Customer *customer.Customer     `json:"customer,omitempty"`
}

type CustomerSynchronizationAdapter

type CustomerSynchronizationAdapter interface {
	// UpsertCustomerOverride upserts a customer override ignoring the transactional context, the override
	// will be empty.
	UpsertCustomerLock(ctx context.Context, input UpsertCustomerLockAdapterInput) error
	LockCustomerForUpdate(ctx context.Context, input LockCustomerForUpdateAdapterInput) error
}

type DeleteCustomerOverrideInput

type DeleteCustomerOverrideInput struct {
	Customer customer.CustomerID
}

func (DeleteCustomerOverrideInput) Validate

func (d DeleteCustomerOverrideInput) Validate() error

type DeleteGatheringInvoiceAdapterInput

type DeleteGatheringInvoiceAdapterInput = InvoiceID

type DeleteGatheringInvoicesInput

type DeleteGatheringInvoicesInput = genericMultiInvoiceInput

type DeleteInvoiceInput

type DeleteInvoiceInput = InvoiceID

type DeleteInvoiceLineInput

type DeleteInvoiceLineInput = LineID

type DeleteProfileInput

type DeleteProfileInput = ProfileID

type DeleteSplitLineGroupInput

type DeleteSplitLineGroupInput = models.NamespacedID

Adapter

type DetailedLine

type DetailedLine struct {
	DetailedLineBase

	// Discounts
	AmountDiscounts AmountLineDiscountsManaged `json:"discounts,omitempty"`
}

func (DetailedLine) Clone

func (l DetailedLine) Clone() DetailedLine

func (DetailedLine) SetDiscountExternalIDs

func (l DetailedLine) SetDiscountExternalIDs(externalIDs map[string]string) []string

func (DetailedLine) Validate

func (l DetailedLine) Validate() error

type DetailedLineBase

type DetailedLineBase struct {
	models.ManagedResource

	// Relationships
	InvoiceID string `json:"invoiceID"`

	// Line details
	Category               FlatFeeCategory                `json:"category"`
	ChildUniqueReferenceID *string                        `json:"childUniqueReferenceID,omitempty"`
	Index                  *int                           `json:"index,omitempty"`
	PaymentTerm            productcatalog.PaymentTermType `json:"paymentTerm"`
	ServicePeriod          Period                         `json:"servicePeriod"`

	// Line amount
	Currency      currencyx.Code        `json:"currency"`
	PerUnitAmount alpacadecimal.Decimal `json:"perUnitAmount"`
	Quantity      alpacadecimal.Decimal `json:"quantity"`
	Totals        Totals                `json:"totals"`

	// Apps
	TaxConfig   *productcatalog.TaxConfig `json:"taxConfig,omitempty"`
	ExternalIDs LineExternalIDs           `json:"externalIDs,omitempty"`

	// FeeLineConfigID contains the ID of the fee configuration in the DB, this should go away
	// as soon as we split the ubp/flatfee db parts
	FeeLineConfigID string `json:"feeLineConfigID,omitempty"`
}

func (DetailedLineBase) Clone

TODO: Is this even needed?

func (DetailedLineBase) Equal

func (l DetailedLineBase) Equal(other DetailedLineBase) bool

func (DetailedLineBase) Validate

func (l DetailedLineBase) Validate() error

type DetailedLines

type DetailedLines []DetailedLine

func (DetailedLines) Clone

func (l DetailedLines) Clone() DetailedLines

func (DetailedLines) GetByChildUniqueReferenceID

func (l DetailedLines) GetByChildUniqueReferenceID(id string) *DetailedLine

func (DetailedLines) Map

func (DetailedLines) Validate

func (l DetailedLines) Validate() error

type DiscountReason

type DiscountReason struct {
	// contains filtered or unexported fields
}

func (*DiscountReason) AsMaximumSpend

func (d *DiscountReason) AsMaximumSpend() (MaximumSpendDiscount, error)

func (*DiscountReason) AsRatecardPercentage

func (d *DiscountReason) AsRatecardPercentage() (PercentageDiscount, error)

func (*DiscountReason) AsRatecardUsage

func (d *DiscountReason) AsRatecardUsage() (UsageDiscount, error)

func (*DiscountReason) MarshalJSON

func (d *DiscountReason) MarshalJSON() ([]byte, error)

func (*DiscountReason) Type

func (*DiscountReason) UnmarshalJSON

func (d *DiscountReason) UnmarshalJSON(bytes []byte) error

func (*DiscountReason) Validate

func (d *DiscountReason) Validate() error

type DiscountReasonType

type DiscountReasonType string
const (
	MaximumSpendDiscountReason       DiscountReasonType = "maximum_spend"
	RatecardPercentageDiscountReason DiscountReasonType = "ratecard_percentage"
	RatecardUsageDiscountReason      DiscountReasonType = "ratecard_usage"
)

func (DiscountReasonType) Values

func (DiscountReasonType) Values() []string

type Discounts

type Discounts struct {
	Percentage *PercentageDiscount `json:"percentage,omitempty"`
	Usage      *UsageDiscount      `json:"usage,omitempty"`
}

func (Discounts) Clone

func (d Discounts) Clone() Discounts

func (Discounts) IsEmpty

func (d Discounts) IsEmpty() bool

func (Discounts) ValidateForPrice

func (d Discounts) ValidateForPrice(price *productcatalog.Price) error

type ErrSnapshotInvalidDatabaseState

type ErrSnapshotInvalidDatabaseState struct {
	Err error
}

ErrSnapshotInvalidDatabaseState is returned when the database state is invalid for snapshotting the line quantity. This can happen if the feature or meter is not found. In such cases we should transition the invoice to draft.invalid state.

func (ErrSnapshotInvalidDatabaseState) Error

func (ErrSnapshotInvalidDatabaseState) Unwrap

type EventStandardInvoice

type EventStandardInvoice struct {
	Invoice StandardInvoice `json:"invoice"`
	Apps    InvoiceApps     `json:"apps,omitempty"`
}

func NewEventStandardInvoice

func NewEventStandardInvoice(invoice StandardInvoice) (EventStandardInvoice, error)

func (EventStandardInvoice) Validate

func (e EventStandardInvoice) Validate() error

type ExternalIDType

type ExternalIDType string
const (
	InvoicingExternalIDType ExternalIDType = "invoicing"
	PaymentExternalIDType   ExternalIDType = "payment"
	TaxExternalIDType       ExternalIDType = "tax"
)

func (ExternalIDType) Validate

func (t ExternalIDType) Validate() error

type FeatureMeter

type FeatureMeter struct {
	Feature feature.Feature
	Meter   *meter.Meter
}

type FeatureMeters

type FeatureMeters map[string]FeatureMeter

func (FeatureMeters) Get

func (f FeatureMeters) Get(featureKey string, dependsOnMeteredQuantity bool) (FeatureMeter, error)

type FinalizeStandardInvoiceResult

type FinalizeStandardInvoiceResult struct {
	// contains filtered or unexported fields
}

func NewFinalizeStandardInvoiceResult

func NewFinalizeStandardInvoiceResult() *FinalizeStandardInvoiceResult

func (*FinalizeStandardInvoiceResult) GetInvoiceNumber

func (u *FinalizeStandardInvoiceResult) GetInvoiceNumber() (string, bool)

func (*FinalizeStandardInvoiceResult) GetPaymentExternalID

func (f *FinalizeStandardInvoiceResult) GetPaymentExternalID() (string, bool)

func (*FinalizeStandardInvoiceResult) GetSentToCustomerAt

func (f *FinalizeStandardInvoiceResult) GetSentToCustomerAt() (time.Time, bool)

func (*FinalizeStandardInvoiceResult) MergeIntoInvoice

func (f *FinalizeStandardInvoiceResult) MergeIntoInvoice(invoice *StandardInvoice) error

func (*FinalizeStandardInvoiceResult) SetInvoiceNumber

func (f *FinalizeStandardInvoiceResult) SetInvoiceNumber(invoiceNumber string) *FinalizeStandardInvoiceResult

func (*FinalizeStandardInvoiceResult) SetPaymentExternalID

func (f *FinalizeStandardInvoiceResult) SetPaymentExternalID(paymentExternalID string) *FinalizeStandardInvoiceResult

func (*FinalizeStandardInvoiceResult) SetSentToCustomerAt

func (f *FinalizeStandardInvoiceResult) SetSentToCustomerAt(sentToCustomerAt time.Time) *FinalizeStandardInvoiceResult

type FlatFeeCategory

type FlatFeeCategory string

TODO: Rename to DetailedLineCostCategory (separate PR)

const (
	// FlatFeeCategoryRegular is a regular flat fee, that is based on the usage or a subscription.
	FlatFeeCategoryRegular FlatFeeCategory = "regular"
	// FlatFeeCategoryCommitment is a flat fee that is based on a commitment such as min spend.
	FlatFeeCategoryCommitment FlatFeeCategory = "commitment"
)

func (FlatFeeCategory) Validate

func (c FlatFeeCategory) Validate() error

func (FlatFeeCategory) Values

func (FlatFeeCategory) Values() []string

type ForEachChildInput

type ForEachChildInput struct {
	PeriodEndLTE time.Time
	Callback     func(child LineWithInvoiceHeader) error
}

type GatheringInvoice

type GatheringInvoice struct {
	GatheringInvoiceBase `json:",inline"`

	// Entities external to the invoice entity
	Lines GatheringInvoiceLines `json:"lines,omitempty"`

	// TODO[later]: implement this once we have a lineservice capable of operating on
	// these lines too.
	AvailableActions *GatheringInvoiceAvailableActions `json:"availableActions,omitempty"`
}

func (GatheringInvoice) AsInvoice

func (g GatheringInvoice) AsInvoice() Invoice

func (GatheringInvoice) Clone

func (GatheringInvoice) GetCustomerID

func (g GatheringInvoice) GetCustomerID() customer.CustomerID

func (GatheringInvoice) GetDeletedAt

func (g GatheringInvoice) GetDeletedAt() *time.Time

func (GatheringInvoice) GetGenericLines

func (g GatheringInvoice) GetGenericLines() mo.Option[[]GenericInvoiceLine]

func (GatheringInvoice) GetID

func (g GatheringInvoice) GetID() string

func (GatheringInvoice) GetInvoiceID

func (g GatheringInvoice) GetInvoiceID() InvoiceID

func (*GatheringInvoice) SetLines

func (g *GatheringInvoice) SetLines(lines []GenericInvoiceLine) error

func (*GatheringInvoice) SortLines

func (g *GatheringInvoice) SortLines()

func (GatheringInvoice) Validate

func (g GatheringInvoice) Validate() error

func (GatheringInvoice) WithoutDBState

func (g GatheringInvoice) WithoutDBState() (GatheringInvoice, error)

type GatheringInvoiceAdapter

type GatheringInvoiceAdapter interface {
	CreateGatheringInvoice(ctx context.Context, input CreateGatheringInvoiceAdapterInput) (GatheringInvoice, error)
	UpdateGatheringInvoice(ctx context.Context, input UpdateGatheringInvoiceAdapterInput) error
	DeleteGatheringInvoice(ctx context.Context, input DeleteGatheringInvoiceAdapterInput) error
	GetGatheringInvoiceById(ctx context.Context, input GetGatheringInvoiceByIdInput) (GatheringInvoice, error)
	ListGatheringInvoices(ctx context.Context, input ListGatheringInvoicesInput) (pagination.Result[GatheringInvoice], error)

	HardDeleteGatheringInvoiceLines(ctx context.Context, invoiceID InvoiceID, lineIDs []string) error
}

type GatheringInvoiceAvailableActions

type GatheringInvoiceAvailableActions struct {
	CanBeInvoiced bool `json:"canBeInvoiced"`
}

type GatheringInvoiceBase

type GatheringInvoiceBase struct {
	models.ManagedResource

	Metadata models.Metadata `json:"metadata"`

	Number        string                `json:"number"`
	CustomerID    string                `json:"customerID"`
	Currency      currencyx.Code        `json:"currency"`
	ServicePeriod timeutil.ClosedPeriod `json:"servicePeriod"`

	NextCollectionAt time.Time `json:"nextCollectionAt"`

	SchemaLevel int `json:"schemaLevel"`
}

func (GatheringInvoiceBase) Validate

func (g GatheringInvoiceBase) Validate() error

type GatheringInvoiceCreatedEvent

type GatheringInvoiceCreatedEvent struct {
	Invoice GatheringInvoice `json:"gatheringInvoice"`
}

func NewGatheringInvoiceCreatedEvent

func NewGatheringInvoiceCreatedEvent(invoice GatheringInvoice) GatheringInvoiceCreatedEvent

func (GatheringInvoiceCreatedEvent) EventMetadata

func (GatheringInvoiceCreatedEvent) EventName

func (e GatheringInvoiceCreatedEvent) EventName() string

func (GatheringInvoiceCreatedEvent) Validate

func (e GatheringInvoiceCreatedEvent) Validate() error

type GatheringInvoiceExpand

type GatheringInvoiceExpand string
const (
	GatheringInvoiceExpandLines            GatheringInvoiceExpand = "lines"
	GatheringInvoiceExpandDeletedLines     GatheringInvoiceExpand = "deletedLines"
	GatheringInvoiceExpandAvailableActions GatheringInvoiceExpand = "availableActions"
)

func (GatheringInvoiceExpand) Validate

func (e GatheringInvoiceExpand) Validate() error

type GatheringInvoiceExpands

type GatheringInvoiceExpands []GatheringInvoiceExpand

func (GatheringInvoiceExpands) Has

func (GatheringInvoiceExpands) Validate

func (e GatheringInvoiceExpands) Validate() error

func (GatheringInvoiceExpands) With

type GatheringInvoiceLines

type GatheringInvoiceLines struct {
	mo.Option[GatheringLines]
}

func NewGatheringInvoiceLines

func NewGatheringInvoiceLines(children []GatheringLine) GatheringInvoiceLines

func (*GatheringInvoiceLines) Append

func (l *GatheringInvoiceLines) Append(lines ...GatheringLine)

func (GatheringInvoiceLines) GetByID

func (GatheringInvoiceLines) GetReferencedFeatureKeys

func (l GatheringInvoiceLines) GetReferencedFeatureKeys() ([]string, error)

func (GatheringInvoiceLines) Map

func (GatheringInvoiceLines) MapWithErr

func (GatheringInvoiceLines) NonDeletedLineCount

func (l GatheringInvoiceLines) NonDeletedLineCount() int

func (*GatheringInvoiceLines) ReplaceByID

func (l *GatheringInvoiceLines) ReplaceByID(line GatheringLine) error

func (*GatheringInvoiceLines) Sort

func (l *GatheringInvoiceLines) Sort()

func (GatheringInvoiceLines) Validate

func (l GatheringInvoiceLines) Validate() error

func (GatheringInvoiceLines) WithNormalizedValues

func (l GatheringInvoiceLines) WithNormalizedValues() (GatheringInvoiceLines, error)

type GatheringInvoiceService

type GatheringInvoiceService interface {
	// CreatePendingInvoiceLines creates pending invoice lines for a customer, if the lines are zero valued, the response is nil
	CreatePendingInvoiceLines(ctx context.Context, input CreatePendingInvoiceLinesInput) (*CreatePendingInvoiceLinesResult, error)

	ListGatheringInvoices(ctx context.Context, input ListGatheringInvoicesInput) (pagination.Result[GatheringInvoice], error)
	GetGatheringInvoiceById(ctx context.Context, input GetGatheringInvoiceByIdInput) (GatheringInvoice, error)
	UpdateGatheringInvoice(ctx context.Context, input UpdateGatheringInvoiceInput) error
}

type GatheringLine

type GatheringLine struct {
	GatheringLineBase `json:",inline"`

	DBState *GatheringLine `json:"-"`
}

func NewFlatFeeGatheringLine

func NewFlatFeeGatheringLine(input NewFlatFeeLineInput, opts ...usageBasedLineOption) GatheringLine

func (GatheringLine) AsInvoiceLine

func (g GatheringLine) AsInvoiceLine() InvoiceLine

func (GatheringLine) Clone

func (g GatheringLine) Clone() (GatheringLine, error)

func (GatheringLine) CloneForCreate

func (i GatheringLine) CloneForCreate(edits ...func(*GatheringLine)) (GatheringLine, error)

func (GatheringLine) Equal

func (g GatheringLine) Equal(other GatheringLine) bool

func (GatheringLine) RemoveMetaForCompare

func (g GatheringLine) RemoveMetaForCompare() (GatheringLine, error)

func (GatheringLine) WithNormalizedValues

func (g GatheringLine) WithNormalizedValues() (GatheringLine, error)

func (GatheringLine) WithoutDBState

func (g GatheringLine) WithoutDBState() (GatheringLine, error)

type GatheringLineBase

type GatheringLineBase struct {
	models.ManagedResource

	Metadata    models.Metadata      `json:"metadata"`
	Annotations models.Annotations   `json:"annotations"`
	ManagedBy   InvoiceLineManagedBy `json:"managedBy"`
	InvoiceID   string               `json:"invoiceID"`

	Currency      currencyx.Code        `json:"currency"`
	ServicePeriod timeutil.ClosedPeriod `json:"period"`
	InvoiceAt     time.Time             `json:"invoiceAt"`
	Price         productcatalog.Price  `json:"price"`
	FeatureKey    string                `json:"featureKey"`

	TaxConfig         *productcatalog.TaxConfig `json:"taxOverrides,omitempty"`
	RateCardDiscounts Discounts                 `json:"rateCardDiscounts,omitempty"`

	ChildUniqueReferenceID *string                `json:"childUniqueReferenceID,omitempty"`
	Subscription           *SubscriptionReference `json:"subscription,omitempty"`
	SplitLineGroupID       *string                `json:"splitLineGroupID,omitempty"`

	// TODO: Remove once we have dedicated db field for gathering invoice lines
	UBPConfigID string `json:"ubpConfigID"`
}

func (GatheringLineBase) Clone

func (GatheringLineBase) Equal

func (g GatheringLineBase) Equal(other GatheringLineBase) bool

func (GatheringLineBase) GetAnnotations

func (g GatheringLineBase) GetAnnotations() models.Annotations

func (GatheringLineBase) GetChildUniqueReferenceID

func (i GatheringLineBase) GetChildUniqueReferenceID() *string

func (GatheringLineBase) GetFeatureKey

func (i GatheringLineBase) GetFeatureKey() string

func (GatheringLineBase) GetID

func (i GatheringLineBase) GetID() string

func (GatheringLineBase) GetInvoiceAt

func (i GatheringLineBase) GetInvoiceAt() time.Time

func (GatheringLineBase) GetInvoiceID

func (g GatheringLineBase) GetInvoiceID() string

func (GatheringLineBase) GetLineID

func (g GatheringLineBase) GetLineID() LineID

func (GatheringLineBase) GetManagedBy

func (g GatheringLineBase) GetManagedBy() InvoiceLineManagedBy

func (GatheringLineBase) GetPrice

func (i GatheringLineBase) GetPrice() *productcatalog.Price

func (GatheringLineBase) GetRateCardDiscounts

func (g GatheringLineBase) GetRateCardDiscounts() Discounts

func (GatheringLineBase) GetServicePeriod

func (i GatheringLineBase) GetServicePeriod() timeutil.ClosedPeriod

func (GatheringLineBase) GetSplitLineGroupID

func (i GatheringLineBase) GetSplitLineGroupID() *string

func (GatheringLineBase) GetSubscriptionReference

func (g GatheringLineBase) GetSubscriptionReference() *SubscriptionReference

func (*GatheringLineBase) NormalizeValues

func (i *GatheringLineBase) NormalizeValues() error

func (*GatheringLineBase) SetChildUniqueReferenceID

func (i *GatheringLineBase) SetChildUniqueReferenceID(id *string)

func (*GatheringLineBase) SetDeletedAt

func (g *GatheringLineBase) SetDeletedAt(at *time.Time)

func (*GatheringLineBase) SetInvoiceAt

func (g *GatheringLineBase) SetInvoiceAt(at time.Time)

func (*GatheringLineBase) SetPrice

func (i *GatheringLineBase) SetPrice(price productcatalog.Price)

func (*GatheringLineBase) UpdateServicePeriod

func (g *GatheringLineBase) UpdateServicePeriod(fn func(p *timeutil.ClosedPeriod))

func (GatheringLineBase) Validate

func (i GatheringLineBase) Validate() error

type GatheringLineWithInvoiceHeader

type GatheringLineWithInvoiceHeader struct {
	Line    GatheringLine
	Invoice GatheringInvoice
}

type GatheringLines

type GatheringLines []GatheringLine

func (GatheringLines) Validate

func (l GatheringLines) Validate() error

type GenericInvoice

type GenericInvoice interface {
	GenericInvoiceReader

	SetLines(lines []GenericInvoiceLine) error
}

type GenericInvoiceLine

type GenericInvoiceLine interface {
	GenericInvoiceLineReader

	Clone() (GenericInvoiceLine, error)
	CloneWithoutChildren() (GenericInvoiceLine, error)

	SetDeletedAt(at *time.Time)
	SetPrice(price productcatalog.Price)
	UpdateServicePeriod(func(p *timeutil.ClosedPeriod))
	SetChildUniqueReferenceID(id *string)
}

type GenericInvoiceLineReader

type GenericInvoiceLineReader interface {
	GetDeletedAt() *time.Time
	GetID() string
	GetLineID() LineID
	GetManagedBy() InvoiceLineManagedBy
	GetAnnotations() models.Annotations
	GetInvoiceID() string
	GetPrice() *productcatalog.Price
	GetServicePeriod() timeutil.ClosedPeriod
	GetChildUniqueReferenceID() *string
	GetFeatureKey() string

	Validate() error
	AsInvoiceLine() InvoiceLine
	GetRateCardDiscounts() Discounts
	GetSubscriptionReference() *SubscriptionReference
	GetSplitLineGroupID() *string
}

GenericInvoiceLineReader is an interface that provides access to the generic invoice fields.

type GenericInvoiceReader

type GenericInvoiceReader interface {
	GetDeletedAt() *time.Time
	GetID() string
	GetInvoiceID() InvoiceID
	GetCustomerID() customer.CustomerID

	// GetGenericLines returns the lines of the invoice as generic lines.
	GetGenericLines() mo.Option[[]GenericInvoiceLine]

	AsInvoice() Invoice
}

type GetCustomerAppInput

type GetCustomerAppInput struct {
	CustomerID customer.CustomerID
	AppType    app.AppType
}

GetCustomerAppInput is used to get a customer app from a customer override

func (GetCustomerAppInput) Validate

func (g GetCustomerAppInput) Validate() error

Validate validates the input

type GetCustomerOverrideAdapterInput

type GetCustomerOverrideAdapterInput struct {
	Customer customer.CustomerID

	IncludeDeleted bool
}

func (GetCustomerOverrideAdapterInput) Validate

type GetCustomerOverrideInput

type GetCustomerOverrideInput struct {
	Customer customer.CustomerID    `json:"customerID"`
	Expand   CustomerOverrideExpand `json:"expand,omitempty"`
}

func (GetCustomerOverrideInput) Validate

func (g GetCustomerOverrideInput) Validate() error

type GetDefaultProfileInput

type GetDefaultProfileInput struct {
	Namespace string
}

func (GetDefaultProfileInput) Validate

func (i GetDefaultProfileInput) Validate() error

type GetGatheringInvoiceByIdInput

type GetGatheringInvoiceByIdInput struct {
	Invoice InvoiceID
	Expand  GatheringInvoiceExpands
}

func (GetGatheringInvoiceByIdInput) Validate

func (i GetGatheringInvoiceByIdInput) Validate() error

type GetInvoiceByIdInput

type GetInvoiceByIdInput struct {
	Invoice InvoiceID
	Expand  InvoiceExpand
}

func (GetInvoiceByIdInput) Validate

func (i GetInvoiceByIdInput) Validate() error

type GetInvoiceLineAdapterInput

type GetInvoiceLineAdapterInput = LineID

type GetInvoiceLineInput

type GetInvoiceLineInput = LineID

type GetInvoiceLineOwnershipAdapterInput

type GetInvoiceLineOwnershipAdapterInput = LineID

type GetInvoiceOwnershipAdapterInput

type GetInvoiceOwnershipAdapterInput = InvoiceID

type GetInvoiceTypeAdapterInput

type GetInvoiceTypeAdapterInput = InvoiceID

type GetLinesForSubscriptionInput

type GetLinesForSubscriptionInput struct {
	Namespace      string
	SubscriptionID string
	CustomerID     string
}

func (GetLinesForSubscriptionInput) Validate

func (i GetLinesForSubscriptionInput) Validate() error

type GetOwnershipAdapterResponse

type GetOwnershipAdapterResponse struct {
	Namespace  string
	InvoiceID  string
	CustomerID string
}

type GetProfileInput

type GetProfileInput struct {
	Profile ProfileID
	Expand  ProfileExpand
}

func (GetProfileInput) Validate

func (i GetProfileInput) Validate() error

type GetProfileWithCustomerOverrideInput

type GetProfileWithCustomerOverrideInput struct {
	Customer customer.CustomerID
}

func (GetProfileWithCustomerOverrideInput) Validate

type GetSplitLineGroupHeadersInput

type GetSplitLineGroupHeadersInput struct {
	Namespace         string
	SplitLineGroupIDs []string
}

func (GetSplitLineGroupHeadersInput) Validate

func (i GetSplitLineGroupHeadersInput) Validate() error

type GetSplitLineGroupInput

type GetSplitLineGroupInput = models.NamespacedID

Adapter

type GetUnpinnedCustomerIDsWithPaidSubscriptionInput

type GetUnpinnedCustomerIDsWithPaidSubscriptionInput struct {
	Namespace string
}

func (GetUnpinnedCustomerIDsWithPaidSubscriptionInput) Validate

type GranularityResolution

type GranularityResolution string
const (
	// GranularityResolutionDay provides line items for metered data per day
	GranularityResolutionDay GranularityResolution = "day"
	// GranularityResolutionPeriod provides one line item per period
	GranularityResolutionPeriod GranularityResolution = "period"
)

func (GranularityResolution) Values

func (r GranularityResolution) Values() []string

type HasCustomerOverrideReferencingProfileAdapterInput

type HasCustomerOverrideReferencingProfileAdapterInput = ProfileID

type Invoice

type Invoice struct {
	// contains filtered or unexported fields
}

func NewInvoice

func NewInvoice[T StandardInvoice | GatheringInvoice](invoice T) Invoice

func (Invoice) AsGatheringInvoice

func (i Invoice) AsGatheringInvoice() (GatheringInvoice, error)

func (Invoice) AsGenericInvoice

func (i Invoice) AsGenericInvoice() (GenericInvoice, error)

func (Invoice) AsStandardInvoice

func (i Invoice) AsStandardInvoice() (StandardInvoice, error)

func (Invoice) Type

func (i Invoice) Type() InvoiceType

func (Invoice) Validate

func (i Invoice) Validate() error

type InvoiceAppAdapter

type InvoiceAppAdapter interface {
	UpdateInvoiceFields(ctx context.Context, input UpdateInvoiceFieldsInput) error
}

type InvoiceAppService

type InvoiceAppService interface {
	// TriggerInvoice triggers the invoice state machine to start processing the invoice
	TriggerInvoice(ctx context.Context, input InvoiceTriggerServiceInput) error

	// UpdateInvoiceFields updates the fields of an invoice which are not managed by the state machine
	// These are usually metadata fields settable after the invoice has been finalized
	UpdateInvoiceFields(ctx context.Context, input UpdateInvoiceFieldsInput) error

	// Async sync support
	SyncDraftInvoice(ctx context.Context, input SyncDraftStandardInvoiceInput) (StandardInvoice, error)
	SyncIssuingInvoice(ctx context.Context, input SyncIssuingStandardInvoiceInput) (StandardInvoice, error)
}

type InvoiceApps

type InvoiceApps struct {
	Tax       app.EventApp `json:"tax"`
	Payment   app.EventApp `json:"payment"`
	Invoicing app.EventApp `json:"invoicing"`
}

func (InvoiceApps) Validate

func (a InvoiceApps) Validate() error

type InvoiceAtAccessor

type InvoiceAtAccessor interface {
	GetInvoiceAt() time.Time
	SetInvoiceAt(at time.Time)
}

type InvoiceAvailableActionsFilter

type InvoiceAvailableActionsFilter string
const (
	InvoiceAvailableActionsFilterAdvance InvoiceAvailableActionsFilter = "advance"
	InvoiceAvailableActionsFilterApprove InvoiceAvailableActionsFilter = "approve"
)

func (InvoiceAvailableActionsFilter) Validate

func (f InvoiceAvailableActionsFilter) Validate() error

func (InvoiceAvailableActionsFilter) Values

type InvoiceCustomer

type InvoiceCustomer struct {
	Key              *string                             `json:"key,omitempty"`
	CustomerID       string                              `json:"customerId,omitempty"`
	Name             string                              `json:"name"`
	BillingAddress   *models.Address                     `json:"billingAddress,omitempty"`
	UsageAttribution *streaming.CustomerUsageAttribution `json:"usageAttribution,omitempty"`
}

InvoiceCustomer represents a customer that is used in an invoice We use a specific model as we snapshot the customer at the time of invoice creation, and we don't want to modify the customer entity after it has been sent to the customer.

func NewInvoiceCustomer

func NewInvoiceCustomer(cust customer.Customer) InvoiceCustomer

NewInvoiceCustomer creates a new InvoiceCustomer from a customer.Customer

func (InvoiceCustomer) GetUsageAttribution

func (c InvoiceCustomer) GetUsageAttribution() streaming.CustomerUsageAttribution

GetUsageAttribution returns the customer usage attribution implementing the streaming.CustomerUsageAttribution interface

func (*InvoiceCustomer) Validate

func (i *InvoiceCustomer) Validate() error

Validate validates the invoice customer

type InvoiceExpand

type InvoiceExpand struct {
	Preceding bool

	Lines        bool
	DeletedLines bool

	// RecalculateGatheringInvoice is used to calculate the totals and status details of the invoice when gathering,
	// this is temporary until we implement the full progressive billing stack, including gathering invoice recalculations.
	RecalculateGatheringInvoice bool
}

func (InvoiceExpand) SetDeletedLines

func (e InvoiceExpand) SetDeletedLines(v bool) InvoiceExpand

func (InvoiceExpand) SetLines

func (e InvoiceExpand) SetLines(v bool) InvoiceExpand

func (InvoiceExpand) SetRecalculateGatheringInvoice

func (e InvoiceExpand) SetRecalculateGatheringInvoice(v bool) InvoiceExpand

func (InvoiceExpand) Validate

func (e InvoiceExpand) Validate() error

type InvoiceExternalIDs

type InvoiceExternalIDs struct {
	Invoicing string `json:"invoicing,omitempty"`
	Payment   string `json:"payment,omitempty"`
}

func (*InvoiceExternalIDs) GetInvoicingOrEmpty

func (i *InvoiceExternalIDs) GetInvoicingOrEmpty() string

type InvoiceID

type InvoiceID models.NamespacedID

func (InvoiceID) Validate

func (i InvoiceID) Validate() error

type InvoiceLine

type InvoiceLine struct {
	// contains filtered or unexported fields
}

func (InvoiceLine) AsGatheringLine

func (i InvoiceLine) AsGatheringLine() (GatheringLine, error)

func (InvoiceLine) AsGenericLine

func (i InvoiceLine) AsGenericLine() (GenericInvoiceLine, error)

func (InvoiceLine) AsStandardLine

func (i InvoiceLine) AsStandardLine() (StandardLine, error)

func (InvoiceLine) Type

func (i InvoiceLine) Type() InvoiceLineType

func (InvoiceLine) Validate

func (i InvoiceLine) Validate() error

type InvoiceLineAdapter

type InvoiceLineAdapter interface {
	UpsertInvoiceLines(ctx context.Context, input UpsertInvoiceLinesAdapterInput) ([]*StandardLine, error)
	ListInvoiceLines(ctx context.Context, input ListInvoiceLinesAdapterInput) ([]*StandardLine, error)
	GetLinesForSubscription(ctx context.Context, input GetLinesForSubscriptionInput) ([]LineOrHierarchy, error)
}

type InvoiceLineAdapterType

type InvoiceLineAdapterType string

TODO: Deprecated: remove in the next PR

const (
	// InvoiceLineTypeFee is an item that represents a single charge without meter backing.
	InvoiceLineAdapterTypeFee InvoiceLineAdapterType = "flat_fee"
	// InvoiceLineTypeUsageBased is an item that is added to the invoice and is usage based.
	InvoiceLineAdapterTypeUsageBased InvoiceLineAdapterType = "usage_based"
)

func (InvoiceLineAdapterType) Values

func (InvoiceLineAdapterType) Values() []string

type InvoiceLineManagedBy

type InvoiceLineManagedBy string
const (
	// SubscriptionManagedLine is a line that is managed by a subscription.
	SubscriptionManagedLine InvoiceLineManagedBy = "subscription"
	// SystemManagedLine is a line that is managed by the system (non editable, detailed lines)
	SystemManagedLine InvoiceLineManagedBy = "system"
	// ManuallyManagedLine is a line that is managed manually (e.g. overridden by our API users)
	ManuallyManagedLine InvoiceLineManagedBy = "manual"
)

func (InvoiceLineManagedBy) Values

func (InvoiceLineManagedBy) Values() []string

type InvoiceLineService

type InvoiceLineService interface {
	GetLinesForSubscription(ctx context.Context, input GetLinesForSubscriptionInput) ([]LineOrHierarchy, error)
	// SnapshotLineQuantity returns an updated line with the quantity snapshoted from meters
	// the invoice is used as contextual information to the call.
	SnapshotLineQuantity(ctx context.Context, input SnapshotLineQuantityInput) (*StandardLine, error)
}

type InvoiceLineStatus

type InvoiceLineStatus string

TODO: Deprecated: remove in the next PR

const (
	// InvoiceLineStatusValid is a valid invoice line.
	InvoiceLineStatusValid InvoiceLineStatus = "valid"
	// InvoiceLineStatusDetailed is a detailed invoice line.
	InvoiceLineStatusDetailed InvoiceLineStatus = "detailed"
)

func (InvoiceLineStatus) Values

func (InvoiceLineStatus) Values() []string

type InvoiceLineType

type InvoiceLineType string
const (
	InvoiceLineTypeStandard  InvoiceLineType = "standard"
	InvoiceLineTypeGathering InvoiceLineType = "gathering"
)

func (InvoiceLineType) Validate

func (t InvoiceLineType) Validate() error

type InvoicePendingLinesInput

type InvoicePendingLinesInput struct {
	Customer customer.CustomerID

	IncludePendingLines mo.Option[[]string]
	AsOf                *time.Time

	// ProgressiveBillingOverride allows to override the progressive billing setting of the customer.
	// This is used to make sure that system collection does not use progressive billing.
	ProgressiveBillingOverride *bool
}

func (InvoicePendingLinesInput) Validate

func (i InvoicePendingLinesInput) Validate() error

type InvoiceService

type InvoiceService interface {
	ListInvoices(ctx context.Context, input ListInvoicesInput) (ListInvoicesResponse, error)
	GetInvoiceByID(ctx context.Context, input GetInvoiceByIdInput) (StandardInvoice, error)
	InvoicePendingLines(ctx context.Context, input InvoicePendingLinesInput) ([]StandardInvoice, error)
	// AdvanceInvoice advances the invoice to the next stage, the advancement is stopped until:
	// - an error is occurred
	// - the invoice is in a state that cannot be advanced (e.g. waiting for draft period to expire)
	// - the invoice is advanced to the final state
	AdvanceInvoice(ctx context.Context, input AdvanceInvoiceInput) (StandardInvoice, error)
	SnapshotQuantities(ctx context.Context, input SnapshotQuantitiesInput) (StandardInvoice, error)
	ApproveInvoice(ctx context.Context, input ApproveInvoiceInput) (StandardInvoice, error)
	RetryInvoice(ctx context.Context, input RetryInvoiceInput) (StandardInvoice, error)
	DeleteInvoice(ctx context.Context, input DeleteInvoiceInput) (StandardInvoice, error)
	UpdateInvoice(ctx context.Context, input UpdateInvoiceInput) (Invoice, error)

	// SimulateInvoice generates an invoice based on the provided input, but does not persist it
	// can be used to execute the invoice generation logic without actually creating an invoice in the database
	SimulateInvoice(ctx context.Context, input SimulateInvoiceInput) (StandardInvoice, error)
	// UpsertValidationIssues upserts validation errors to the invoice bypassing the state machine, can only be
	// used on invoices in immutable state.
	UpsertValidationIssues(ctx context.Context, input UpsertValidationIssuesInput) error

	// RecalculateGatheringInvoices recalculates the gathering invoices for a given customer, updating the
	// collection_at attribute and deleting the gathering invoice if it has no lines.
	RecalculateGatheringInvoices(ctx context.Context, input RecalculateGatheringInvoicesInput) error
}

type InvoiceSplitLineGroupAdapter

type InvoiceSplitLineGroupAdapter interface {
	CreateSplitLineGroup(ctx context.Context, input CreateSplitLineGroupAdapterInput) (SplitLineGroup, error)
	UpdateSplitLineGroup(ctx context.Context, input UpdateSplitLineGroupInput) (SplitLineGroup, error)
	DeleteSplitLineGroup(ctx context.Context, input DeleteSplitLineGroupInput) error
	GetSplitLineGroup(ctx context.Context, input GetSplitLineGroupInput) (SplitLineHierarchy, error)
	GetSplitLineGroupHeaders(ctx context.Context, input GetSplitLineGroupHeadersInput) (SplitLineGroupHeaders, error)
}

type InvoiceTrigger

type InvoiceTrigger = stateless.Trigger
var (
	// TriggerRetry is used to retry a state transition that failed, used by the end user to invoke it manually
	TriggerRetry InvoiceTrigger = "trigger_retry"
	// TriggerApprove is used to approve a state manually
	TriggerApprove InvoiceTrigger = "trigger_approve"
	// TriggerNext is used to advance the invoice to the next state if automatically possible
	TriggerNext InvoiceTrigger = "trigger_next"
	// TriggerFailed is used to trigger the failure state transition associated with the current state
	TriggerFailed InvoiceTrigger = "trigger_failed"
	// TriggerUpdated is used to trigger a change in the invoice (we are using this to calculate the immutable states
	// and trigger re-validation)
	TriggerUpdated InvoiceTrigger = "trigger_updated"
	// TriggerSnapshotQuantities is used to snapshot the quantities for usage based line items
	TriggerSnapshotQuantities InvoiceTrigger = "trigger_snapshot_quantities"
	// triggerDelete is used to delete the invoice
	TriggerDelete InvoiceTrigger = "trigger_delete"

	// TriggerPaid is used to signify that the invoice has been paid
	TriggerPaid InvoiceTrigger = "trigger_paid"
	// TriggerActionRequired is used to signify that the invoice requires action
	TriggerActionRequired InvoiceTrigger = "trigger_action_required"

	// TriggerPaymentUncollectible is used to signify that the invoice is uncollectible
	TriggerPaymentUncollectible InvoiceTrigger = "trigger_payment_uncollectible"
	// TriggerPaymentOverdue is used to signify that the invoice is overdue
	TriggerPaymentOverdue InvoiceTrigger = "trigger_payment_overdue"

	// TriggerVoid is used to signify that the invoice has been voided (e.g. created by mistake)
	TriggerVoid InvoiceTrigger = "trigger_void"
)

type InvoiceTriggerInput

type InvoiceTriggerInput struct {
	Invoice InvoiceID
	// Trigger specifies the trigger that caused the invoice to be changed, only triggerPaid and triggerPayment* are allowed
	Trigger InvoiceTrigger

	ValidationErrors *InvoiceTriggerValidationInput
}

func (InvoiceTriggerInput) Validate

func (i InvoiceTriggerInput) Validate() error

type InvoiceTriggerServiceInput

type InvoiceTriggerServiceInput struct {
	InvoiceTriggerInput

	// AppType is the type of the app that triggered the invoice
	AppType app.AppType
	// Capability is the capability of the app that was processing this trigger
	Capability app.CapabilityType
}

func (InvoiceTriggerServiceInput) Validate

func (i InvoiceTriggerServiceInput) Validate() error

type InvoiceTriggerValidationInput

type InvoiceTriggerValidationInput struct {
	// Operation specifies the operation that yielded the validation errors
	// previous validation errors from this operation will be replaced by this one
	Operation StandardInvoiceOperation
	Errors    []error
}

func (InvoiceTriggerValidationInput) Validate

func (i InvoiceTriggerValidationInput) Validate() error

type InvoiceType

type InvoiceType string
const (
	InvoiceTypeStandard  InvoiceType = InvoiceType("standard")
	InvoiceTypeGathering InvoiceType = InvoiceType("gathering")
)

func (InvoiceType) Validate

func (t InvoiceType) Validate() error

func (InvoiceType) Values

func (t InvoiceType) Values() []string

type InvoiceWorkflow

type InvoiceWorkflow struct {
	AppReferences          ProfileAppReferences `json:"appReferences"`
	Apps                   *ProfileApps         `json:"apps,omitempty"`
	SourceBillingProfileID string               `json:"sourceBillingProfileId,omitempty"`
	Config                 WorkflowConfig       `json:"config"`
}

type InvoicingApp

type InvoicingApp interface {
	// ValidateStandardInvoice validates if the app can run for the given invoice
	ValidateStandardInvoice(ctx context.Context, invoice StandardInvoice) error

	// UpsertStandardInvoice upserts the invoice on the remote system, the invoice is read-only, the app should not modify it
	// the recommended behavior is that the invoices FlattenLinesByID is used to get all lines, then the app should
	// synchronize all the fee lines and store the external IDs in the result.
	UpsertStandardInvoice(ctx context.Context, invoice StandardInvoice) (*UpsertStandardInvoiceResult, error)

	// FinalizeStandardInvoice finalizes the invoice on the remote system, starts the payment flow. It is safe to assume
	// that the state machine have already performed an upsert as part of this state transition.
	//
	// If the payment is handled by a decoupled implementation (different app or app has strict separation of concerns)
	// then the payment app will be called with FinalizePayment and that should return the external ID of the payment. (later)
	FinalizeStandardInvoice(ctx context.Context, invoice StandardInvoice) (*FinalizeStandardInvoiceResult, error)

	// DeleteStandardInvoice deletes the invoice on the remote system, the invoice is read-only, the app should not modify it
	// the invoice deletion is only invoked for non-finalized invoices.
	DeleteStandardInvoice(ctx context.Context, invoice StandardInvoice) error
}

Warning: The received invoice is

  • read-only (e.g. any changes made to it are lost to prevent manipulation of the invoice state)
  • reflects the current in memory state of the invoice, thus if you fetched from the db an earlier version of the invoice will be passed, thus do not call any billingService methods from these callbacks.

func GetApp

func GetApp(app app.App) (InvoicingApp, error)

GetApp returns the app from the app entity

type InvoicingAppAsyncSyncer

type InvoicingAppAsyncSyncer interface {
	CanDraftSyncAdvance(invoice StandardInvoice) (bool, error)
	CanIssuingSyncAdvance(invoice StandardInvoice) (bool, error)
}

InvoicingAppAsyncSyncer is an optional interface that can be implemented by the app to support asynchronous syncing of the invoice (e.g. when we are receiving the payload such as with custominvoicing app)

type InvoicingAppPostAdvanceHook

type InvoicingAppPostAdvanceHook interface {
	// PostAdvanceInvoiceHook is called after the invoice has been advanced to the next stable state
	// (e.g. no next trigger is available)
	//
	// Can be used by the app to perform additional actions in case there are some post-processing steps
	// required on the invoice.
	PostAdvanceStandardInvoiceHook(ctx context.Context, invoice StandardInvoice) (*PostAdvanceHookResult, error)
}

type InvoicingConfig

type InvoicingConfig struct {
	AutoAdvance        bool                      `json:"autoAdvance,omitempty"`
	DraftPeriod        datetime.ISODuration      `json:"draftPeriod,omitempty"`
	DueAfter           datetime.ISODuration      `json:"dueAfter,omitempty"`
	ProgressiveBilling bool                      `json:"progressiveBilling,omitempty"`
	DefaultTaxConfig   *productcatalog.TaxConfig `json:"defaultTaxConfig,omitempty"`
}

InvoiceConfig groups fields related to invoice settings.

func (*InvoicingConfig) Validate

func (c *InvoicingConfig) Validate() error

type InvoicingOverrideConfig

type InvoicingOverrideConfig struct {
	AutoAdvance        *bool                     `json:"autoAdvance,omitempty"`
	DraftPeriod        *datetime.ISODuration     `json:"draftPeriod,omitempty"`
	DueAfter           *datetime.ISODuration     `json:"dueAfter,omitempty"`
	ProgressiveBilling *bool                     `json:"progressiveBilling,omitempty"`
	DefaultTaxConfig   *productcatalog.TaxConfig `json:"defaultTaxConfig,omitempty"`
}

func (*InvoicingOverrideConfig) Validate

func (c *InvoicingOverrideConfig) Validate() error

type LineDiscountBase

type LineDiscountBase struct {
	Description            *string         `json:"description,omitempty"`
	ChildUniqueReferenceID *string         `json:"childUniqueReferenceId,omitempty"`
	ExternalIDs            LineExternalIDs `json:"externalIDs,omitempty"`
	Reason                 DiscountReason  `json:"reason,omitempty"`
}

func (LineDiscountBase) Clone

func (LineDiscountBase) Equal

func (i LineDiscountBase) Equal(other LineDiscountBase) bool

func (LineDiscountBase) GetChildUniqueReferenceID

func (i LineDiscountBase) GetChildUniqueReferenceID() *string

func (LineDiscountBase) GetDescription

func (i LineDiscountBase) GetDescription() *string

func (LineDiscountBase) Validate

func (i LineDiscountBase) Validate() error

type LineDiscountBaseManaged

type LineDiscountBaseManaged struct {
	models.ManagedModelWithID `json:",inline"`
	LineDiscountBase          `json:",inline"`
}

type LineDiscounts

type LineDiscounts struct {
	Amount AmountLineDiscountsManaged `json:"amount,omitempty"`
	Usage  UsageLineDiscountsManaged  `json:"usage,omitempty"`
}

func (LineDiscounts) Clone

func (i LineDiscounts) Clone() LineDiscounts

func (LineDiscounts) IsEmpty

func (i LineDiscounts) IsEmpty() bool

func (LineDiscounts) ReuseIDsFrom

func (i LineDiscounts) ReuseIDsFrom(existingItems LineDiscounts) LineDiscounts

func (LineDiscounts) Validate

func (i LineDiscounts) Validate() error

type LineExternalIDs

type LineExternalIDs struct {
	Invoicing string `json:"invoicing,omitempty"`
}

func (LineExternalIDs) Equal

func (i LineExternalIDs) Equal(other LineExternalIDs) bool

type LineID

type LineID models.NamespacedID

func (LineID) Validate

func (i LineID) Validate() error

type LineOrHierarchy

type LineOrHierarchy struct {
	// contains filtered or unexported fields
}

func NewLineOrHierarchy

func NewLineOrHierarchy[T *StandardLine | GatheringLine | *SplitLineHierarchy](line T) LineOrHierarchy

func (LineOrHierarchy) AsGenericLine

func (i LineOrHierarchy) AsGenericLine() (GenericInvoiceLine, error)

func (LineOrHierarchy) AsHierarchy

func (i LineOrHierarchy) AsHierarchy() (*SplitLineHierarchy, error)

func (LineOrHierarchy) ChildUniqueReferenceID

func (i LineOrHierarchy) ChildUniqueReferenceID() *string

func (LineOrHierarchy) ServicePeriod

func (i LineOrHierarchy) ServicePeriod() timeutil.ClosedPeriod

func (LineOrHierarchy) Type

type LineOrHierarchyType

type LineOrHierarchyType string
const (
	LineOrHierarchyTypeLine      LineOrHierarchyType = "line"
	LineOrHierarchyTypeHierarchy LineOrHierarchyType = "hierarchy"
)

type LineWithInvoiceHeader

type LineWithInvoiceHeader struct {
	Line    GenericInvoiceLine
	Invoice GenericInvoiceReader
}

type LinesWithInvoiceHeaders

type LinesWithInvoiceHeaders []LineWithInvoiceHeader

func (LinesWithInvoiceHeaders) Lines

type ListCustomerOverridesInput

type ListCustomerOverridesInput struct {
	pagination.Page

	// Warning: We only support a single namespace for now as the default profile handling
	// complicates things. If we need multiple namespace support, I would recommend a different
	// endpoint that doesn't take default namespace into account.
	Namespace                     string                 `json:"namespace"`
	BillingProfiles               []string               `json:"billingProfile,omitempty"`
	CustomersWithoutPinnedProfile bool                   `json:"customersWithoutPinnedProfile,omitempty"`
	Expand                        CustomerOverrideExpand `json:"expand,omitempty"`

	IncludeAllCustomers  bool     `json:"includeAllCustomers,omitempty"`
	CustomerIDs          []string `json:"customerID,omitempty"`
	CustomerName         string   `json:"customerName,omitempty"`
	CustomerKey          string   `json:"customerKey,omitempty"`
	CustomerPrimaryEmail string   `json:"customerPrimaryEmail,omitempty"`

	OrderBy CustomerOverrideOrderBy
	Order   sortx.Order
}

func (ListCustomerOverridesInput) Validate

func (l ListCustomerOverridesInput) Validate() error

type ListGatheringInvoicesInput

type ListGatheringInvoicesInput struct {
	pagination.Page

	Namespaces     []string
	Customers      []string
	Currencies     []currencyx.Code
	OrderBy        api.InvoiceOrderBy
	Order          sortx.Order
	IncludeDeleted bool
	Expand         GatheringInvoiceExpands
}

func (ListGatheringInvoicesInput) Validate

func (i ListGatheringInvoicesInput) Validate() error

type ListInvoiceLinesAdapterInput

type ListInvoiceLinesAdapterInput struct {
	Namespace string

	CustomerID      string
	InvoiceIDs      []string
	InvoiceStatuses []StandardInvoiceStatus
	IncludeDeleted  bool
	Statuses        []InvoiceLineStatus

	LineIDs []string
}

func (ListInvoiceLinesAdapterInput) Validate

func (g ListInvoiceLinesAdapterInput) Validate() error

type ListInvoicesExternalIDFilter

type ListInvoicesExternalIDFilter struct {
	Type ExternalIDType
	IDs  []string
}

func (ListInvoicesExternalIDFilter) Validate

func (f ListInvoicesExternalIDFilter) Validate() error

type ListInvoicesInput

type ListInvoicesInput struct {
	pagination.Page

	Namespaces []string
	IDs        []string
	Customers  []string
	// Statuses searches by short InvoiceStatus (e.g. draft, issued)
	Statuses []string

	HasAvailableAction []InvoiceAvailableActionsFilter

	// ExtendedStatuses searches by exact InvoiceStatus
	ExtendedStatuses []StandardInvoiceStatus
	Currencies       []currencyx.Code

	IssuedAfter  *time.Time
	IssuedBefore *time.Time

	PeriodStartAfter  *time.Time
	PeriodStartBefore *time.Time

	// Filter by invoice creation time
	CreatedAfter  *time.Time
	CreatedBefore *time.Time

	IncludeDeleted bool

	// DraftUtil allows to filter invoices which have their draft state expired based on the provided time.
	// Invoice is expired if the time defined by Invoice.DraftUntil is in the past compared to ListInvoicesInput.DraftUntil.
	DraftUntil *time.Time

	// CollectionAt allows to filter invoices which have their collection_at attribute is in the past compared
	// to the time provided in CollectionAt parameter.
	CollectionAt *time.Time

	Expand InvoiceExpand

	ExternalIDs *ListInvoicesExternalIDFilter

	OrderBy api.InvoiceOrderBy
	Order   sortx.Order
}

func (ListInvoicesInput) Validate

func (i ListInvoicesInput) Validate() error

type ListInvoicesResponse

type ListInvoicesResponse = pagination.Result[StandardInvoice]

type ListProfilesInput

type ListProfilesInput struct {
	pagination.Page

	Expand ProfileExpand

	Namespace       string
	IncludeArchived bool
	OrderBy         api.BillingProfileOrderBy
	Order           sortx.Order
}

func (ListProfilesInput) Validate

func (i ListProfilesInput) Validate() error

type ListProfilesResult

type ListProfilesResult = pagination.Result[Profile]

type LockCustomerForUpdateAdapterInput

type LockCustomerForUpdateAdapterInput = customer.CustomerID

type LockInvoicesForUpdateInput

type LockInvoicesForUpdateInput = genericMultiInvoiceInput

type LockableService

type LockableService interface {
	WithLock(ctx context.Context, customerID customer.CustomerID, fn func(ctx context.Context) error) error
}

type MaximumSpendDiscount

type MaximumSpendDiscount struct{}

MaximumSpendDiscount contains information about the maximum spend induced discounts

type Metadata

type Metadata map[string]string

type NewFlatFeeLineInput

type NewFlatFeeLineInput struct {
	ID        string
	CreatedAt time.Time
	UpdatedAt time.Time

	Namespace string
	Period    Period
	InvoiceAt time.Time

	InvoiceID string

	Name        string
	Metadata    map[string]string
	Annotations models.Annotations
	Description *string

	Currency currencyx.Code

	ManagedBy InvoiceLineManagedBy

	PerUnitAmount alpacadecimal.Decimal
	PaymentTerm   productcatalog.PaymentTermType

	RateCardDiscounts Discounts
}

helper functions for generating new lines

type NextSequenceNumberInput

type NextSequenceNumberInput struct {
	Namespace string
	Scope     string
}

func (NextSequenceNumberInput) Validate

func (n NextSequenceNumberInput) Validate() error

type NotFoundError

type NotFoundError struct {
	ID     string
	Entity string
	Err    error
}

func (NotFoundError) Error

func (e NotFoundError) Error() string

func (NotFoundError) Unwrap

func (e NotFoundError) Unwrap() error

type PaymentConfig

type PaymentConfig struct {
	CollectionMethod CollectionMethod `json:"collectionMethod"`
}

func (*PaymentConfig) Validate

func (c *PaymentConfig) Validate() error

type PaymentOverrideConfig

type PaymentOverrideConfig struct {
	CollectionMethod *CollectionMethod
}

func (*PaymentOverrideConfig) Validate

func (c *PaymentOverrideConfig) Validate() error

type PercentageDiscount

type PercentageDiscount struct {
	productcatalog.PercentageDiscount `json:",inline"`

	CorrelationID string `json:"correlationID"`
}

func (PercentageDiscount) Clone

func (PercentageDiscount) Equal

type Period

type Period struct {
	Start time.Time `json:"start"`
	End   time.Time `json:"end"`
}

Period represents a time period, in billing the time period is always interpreted as [from, to) (i.e. from is inclusive, to is exclusive). TODO: Lets merge this with recurrence.Period

func (Period) Contains

func (p Period) Contains(t time.Time) bool

func (Period) Duration

func (p Period) Duration() time.Duration

func (Period) Equal

func (p Period) Equal(other Period) bool

func (Period) IsEmpty

func (p Period) IsEmpty() bool

func (Period) ToClosedPeriod

func (p Period) ToClosedPeriod() timeutil.ClosedPeriod

func (Period) Truncate

func (p Period) Truncate(resolution time.Duration) Period

func (Period) Validate

func (p Period) Validate() error

type PostAdvanceHookResult

type PostAdvanceHookResult struct {
	// contains filtered or unexported fields
}

func NewPostAdvanceHookResult

func NewPostAdvanceHookResult() *PostAdvanceHookResult

func (*PostAdvanceHookResult) GetTriggerToInvoke

func (p *PostAdvanceHookResult) GetTriggerToInvoke() *InvoiceTriggerInput

func (*PostAdvanceHookResult) InvokeTrigger

type Profile

type Profile struct {
	BaseProfile

	// Optionaly expanded fields
	Apps *ProfileApps `json:"-"`
}

func (Profile) Merge

func (p Profile) Merge(o *CustomerOverride) Profile

func (Profile) Validate

func (p Profile) Validate() error

type ProfileAdapter

type ProfileAdapter interface {
	CreateProfile(ctx context.Context, input CreateProfileInput) (*BaseProfile, error)
	ListProfiles(ctx context.Context, input ListProfilesInput) (pagination.Result[BaseProfile], error)
	GetProfile(ctx context.Context, input GetProfileInput) (*AdapterGetProfileResponse, error)
	GetDefaultProfile(ctx context.Context, input GetDefaultProfileInput) (*AdapterGetProfileResponse, error)
	DeleteProfile(ctx context.Context, input DeleteProfileInput) error
	UpdateProfile(ctx context.Context, input UpdateProfileAdapterInput) (*BaseProfile, error)

	IsAppUsed(ctx context.Context, appID app.AppID) error

	GetUnpinnedCustomerIDsWithPaidSubscription(ctx context.Context, input GetUnpinnedCustomerIDsWithPaidSubscriptionInput) ([]customer.CustomerID, error)
}

type ProfileAppReferences

type ProfileAppReferences struct {
	Tax       app.AppID `json:"tax"`
	Invoicing app.AppID `json:"invoicing"`
	Payment   app.AppID `json:"payment"`
}

func (ProfileAppReferences) Validate

func (i ProfileAppReferences) Validate() error

type ProfileApps

type ProfileApps struct {
	Tax       app.App `json:"tax"`
	Invoicing app.App `json:"invoicing"`
	Payment   app.App `json:"payment"`
}

type ProfileExpand

type ProfileExpand struct {
	Apps bool
}

func (ProfileExpand) Validate

func (e ProfileExpand) Validate() error

type ProfileID

type ProfileID models.NamespacedID

func (ProfileID) Validate

func (p ProfileID) Validate() error

type ProfileService

type ProfileService interface {
	CreateProfile(ctx context.Context, param CreateProfileInput) (*Profile, error)
	GetDefaultProfile(ctx context.Context, input GetDefaultProfileInput) (*Profile, error)
	GetProfile(ctx context.Context, input GetProfileInput) (*Profile, error)
	ListProfiles(ctx context.Context, input ListProfilesInput) (ListProfilesResult, error)
	DeleteProfile(ctx context.Context, input DeleteProfileInput) error
	UpdateProfile(ctx context.Context, input UpdateProfileInput) (*Profile, error)
	ProvisionDefaultBillingProfile(ctx context.Context, namespace string) error
	IsAppUsed(ctx context.Context, appID app.AppID) error
	ResolveStripeAppIDFromBillingProfile(ctx context.Context, namespace string, customerId *customer.CustomerID) (app.AppID, error)
}

type QuantityAccessor

type QuantityAccessor interface {
	GetQuantity() *alpacadecimal.Decimal
}

type RecalculateGatheringInvoicesInput

type RecalculateGatheringInvoicesInput = customer.CustomerID

type RetryInvoiceInput

type RetryInvoiceInput = InvoiceID

type SchemaLevelAdapter

type SchemaLevelAdapter interface {
	// GetInvoiceDefaultSchemaLevel returns the current default schema level for invoices.
	GetInvoiceDefaultSchemaLevel(ctx context.Context) (int, error)
	// SetInvoiceDefaultSchemaLevel sets the current default schema level for invoices.
	SetInvoiceDefaultSchemaLevel(ctx context.Context, level int) error
}

type SequenceAdapter

type SequenceAdapter interface {
	NextSequenceNumber(ctx context.Context, input NextSequenceNumberInput) (alpacadecimal.Decimal, error)
}

type SequenceDefinition

type SequenceDefinition struct {
	Prefix         string
	SuffixTemplate string
	Scope          string
}

func (SequenceDefinition) PrefixMatches

func (d SequenceDefinition) PrefixMatches(s string) bool

func (SequenceDefinition) Validate

func (d SequenceDefinition) Validate() error

type SequenceGenerationInput

type SequenceGenerationInput struct {
	Namespace    string
	CustomerName string
	Currency     currencyx.Code
}

func (SequenceGenerationInput) Validate

func (i SequenceGenerationInput) Validate() error

type SequenceService

type SequenceService interface {
	GenerateInvoiceSequenceNumber(ctx context.Context, in SequenceGenerationInput, def SequenceDefinition) (string, error)
}

type SimulateInvoiceInput

type SimulateInvoiceInput struct {
	Namespace  string
	CustomerID *string
	Customer   *customer.Customer

	Number   *string
	Currency currencyx.Code
	Lines    StandardInvoiceLines
}

func (SimulateInvoiceInput) Validate

func (i SimulateInvoiceInput) Validate() error

type SnapshotLineQuantityInput

type SnapshotLineQuantityInput struct {
	Invoice *StandardInvoice
	Line    *StandardLine
}

func (SnapshotLineQuantityInput) Validate

func (i SnapshotLineQuantityInput) Validate() error

type SnapshotQuantitiesInput

type SnapshotQuantitiesInput = InvoiceID

type SplitLineGroup

type SplitLineGroup struct {
	models.ManagedModel         `json:",inline"`
	models.NamespacedID         `json:",inline"`
	SplitLineGroupMutableFields `json:",inline"`

	Price             *productcatalog.Price  `json:"price"`
	FeatureKey        *string                `json:"featureKey,omitempty"`
	Subscription      *SubscriptionReference `json:"subscription,omitempty"`
	Currency          currencyx.Code         `json:"currency"`
	UniqueReferenceID *string                `json:"childUniqueReferenceId,omitempty"`
}

func (SplitLineGroup) Clone

func (i SplitLineGroup) Clone() SplitLineGroup

func (SplitLineGroup) ToUpdate

func (i SplitLineGroup) ToUpdate() SplitLineGroupUpdate

func (SplitLineGroup) Validate

func (i SplitLineGroup) Validate() error

type SplitLineGroupCreate

type SplitLineGroupCreate struct {
	Namespace string `json:"namespace"`

	SplitLineGroupMutableFields `json:",inline"`

	Price             *productcatalog.Price  `json:"price"`
	FeatureKey        *string                `json:"featureKey,omitempty"`
	Subscription      *SubscriptionReference `json:"subscription,omitempty"`
	Currency          currencyx.Code         `json:"currency"`
	UniqueReferenceID *string                `json:"childUniqueReferenceId,omitempty"`
}

func (SplitLineGroupCreate) Validate

func (i SplitLineGroupCreate) Validate() error

type SplitLineGroupHeaders

type SplitLineGroupHeaders = []SplitLineGroup

type SplitLineGroupMutableFields

type SplitLineGroupMutableFields struct {
	Name        string          `json:"name"`
	Description *string         `json:"description,omitempty"`
	Metadata    models.Metadata `json:"metadata,omitempty"`

	ServicePeriod Period `json:"period"`

	RatecardDiscounts Discounts                 `json:"ratecardDiscounts"`
	TaxConfig         *productcatalog.TaxConfig `json:"taxConfig,omitempty"`
}

func (SplitLineGroupMutableFields) Clone

func (SplitLineGroupMutableFields) ValidateForPrice

func (i SplitLineGroupMutableFields) ValidateForPrice(price *productcatalog.Price) error

type SplitLineGroupService

type SplitLineGroupService interface {
	DeleteSplitLineGroup(ctx context.Context, input DeleteSplitLineGroupInput) error
	UpdateSplitLineGroup(ctx context.Context, input UpdateSplitLineGroupInput) (SplitLineGroup, error)
}

type SplitLineGroupUpdate

type SplitLineGroupUpdate struct {
	models.NamespacedID `json:",inline"`

	SplitLineGroupMutableFields `json:",inline"`
}

func (SplitLineGroupUpdate) ValidateWithPrice

func (i SplitLineGroupUpdate) ValidateWithPrice(price *productcatalog.Price) error

type SplitLineHierarchy

type SplitLineHierarchy struct {
	Group SplitLineGroup
	Lines LinesWithInvoiceHeaders
}

func (*SplitLineHierarchy) Clone

func (*SplitLineHierarchy) ForEachChild

func (h *SplitLineHierarchy) ForEachChild(in ForEachChildInput) error

func (*SplitLineHierarchy) SumNetAmount

SumNetAmount returns the sum of the net amount (pre-tax) of the progressive billed line and its children containing the values for all lines whose period's end is <= in.UpTo and are not deleted or not part of an invoice that has been deleted. As gathering lines do not represent any kind of actual charge, they are not included in the sum.

type StandardInvoice

type StandardInvoice struct {
	StandardInvoiceBase `json:",inline"`

	// Entities external to the invoice itself
	Lines            StandardInvoiceLines `json:"lines,omitempty"`
	ValidationIssues ValidationIssues     `json:"validationIssues,omitempty"`

	Totals Totals `json:"totals"`

	// private fields required by the service
	ExpandedFields InvoiceExpand `json:"-"`
}

func (StandardInvoice) AsInvoice

func (i StandardInvoice) AsInvoice() Invoice

func (StandardInvoice) Clone

func (i StandardInvoice) Clone() (StandardInvoice, error)

func (StandardInvoice) CustomerID

func (i StandardInvoice) CustomerID() customer.CustomerID

func (StandardInvoice) GetGenericLines

func (i StandardInvoice) GetGenericLines() mo.Option[[]GenericInvoiceLine]

func (*StandardInvoice) GetLeafLinesWithConsolidatedTaxBehavior

func (i *StandardInvoice) GetLeafLinesWithConsolidatedTaxBehavior() DetailedLines

GetLeafLinesWithConsolidatedTaxBehavior returns the leaf lines with the tax behavior set to the invoice's tax behavior unless the line already has a tax behavior set.

func (*StandardInvoice) HasCriticalValidationIssues

func (i *StandardInvoice) HasCriticalValidationIssues() bool

func (StandardInvoice) InvoiceID

func (i StandardInvoice) InvoiceID() InvoiceID

InvoiceID returns the invoice ID. Deprecated: use GetInvoiceID instead TODO[later]: remove this method

func (*StandardInvoice) MergeValidationIssues

func (i *StandardInvoice) MergeValidationIssues(errIn error, reportingComponent ComponentName) error

func (StandardInvoice) RemoveCircularReferences

func (i StandardInvoice) RemoveCircularReferences() (StandardInvoice, error)

func (StandardInvoice) RemoveMetaForCompare

func (i StandardInvoice) RemoveMetaForCompare() (StandardInvoice, error)

RemoveMetaForCompare returns a copy of the invoice without the fields that are not relevant for higher level tests that compare invoices. What gets removed: - Line's DB state - Line's dependencies are marked as resolved - Parent pointers are removed

func (*StandardInvoice) SetLines

func (i *StandardInvoice) SetLines(lines []GenericInvoiceLine) error

func (*StandardInvoice) SortLines

func (i *StandardInvoice) SortLines()

func (StandardInvoice) Validate

func (i StandardInvoice) Validate() error

type StandardInvoiceAvailableActionDetails

type StandardInvoiceAvailableActionDetails struct {
	ResultingState StandardInvoiceStatus `json:"resultingState"`
}

type StandardInvoiceAvailableActionInvoiceDetails

type StandardInvoiceAvailableActionInvoiceDetails struct{}

type StandardInvoiceAvailableActions

type StandardInvoiceAvailableActions struct {
	Advance            *StandardInvoiceAvailableActionDetails `json:"advance,omitempty"`
	Approve            *StandardInvoiceAvailableActionDetails `json:"approve,omitempty"`
	Delete             *StandardInvoiceAvailableActionDetails `json:"delete,omitempty"`
	Retry              *StandardInvoiceAvailableActionDetails `json:"retry,omitempty"`
	Void               *StandardInvoiceAvailableActionDetails `json:"void,omitempty"`
	SnapshotQuantities *StandardInvoiceAvailableActionDetails `json:"snapshotQuantities,omitempty"`

	Invoice *StandardInvoiceAvailableActionInvoiceDetails `json:"invoice,omitempty"`
}

type StandardInvoiceBase

type StandardInvoiceBase struct {
	Namespace string `json:"namespace"`
	ID        string `json:"id"`

	Number      string  `json:"number"`
	Description *string `json:"description,omitempty"`

	Type InvoiceType `json:"type"`

	Metadata map[string]string `json:"metadata"`

	Currency      currencyx.Code               `json:"currency,omitempty"`
	Status        StandardInvoiceStatus        `json:"status"`
	StatusDetails StandardInvoiceStatusDetails `json:"statusDetail,omitempty"`

	Period *Period `json:"period,omitempty"`

	DueAt *time.Time `json:"dueDate,omitempty"`

	CreatedAt            time.Time  `json:"createdAt"`
	UpdatedAt            time.Time  `json:"updatedAt"`
	VoidedAt             *time.Time `json:"voidedAt,omitempty"`
	DraftUntil           *time.Time `json:"draftUntil,omitempty"`
	IssuedAt             *time.Time `json:"issuedAt,omitempty"`
	DeletedAt            *time.Time `json:"deletedAt,omitempty"`
	SentToCustomerAt     *time.Time `json:"sentToCustomerAt,omitempty"`
	QuantitySnapshotedAt *time.Time `json:"quantitySnapshotedAt,omitempty"`

	CollectionAt *time.Time `json:"collectionAt,omitempty"`
	// PaymentProcessingEnteredAt stores when the invoice first entered payment processing
	PaymentProcessingEnteredAt *time.Time `json:"paymentProcessingEnteredAt,omitempty"`

	// Customer is either a snapshot of the contact information of the customer at the time of invoice being sent
	// or the data from the customer entity (draft state)
	// This is required so that we are not modifying the invoice after it has been sent to the customer.
	Customer InvoiceCustomer `json:"customer"`
	Supplier SupplierContact `json:"supplier"`
	Workflow InvoiceWorkflow `json:"workflow,omitempty"`

	ExternalIDs InvoiceExternalIDs `json:"externalIds,omitempty"`

	SchemaLevel int `json:"schemaLevel"`
}

func (StandardInvoiceBase) DefaultCollectionAtForStandardInvoice

func (i StandardInvoiceBase) DefaultCollectionAtForStandardInvoice() time.Time

func (StandardInvoiceBase) GetCustomerID

func (i StandardInvoiceBase) GetCustomerID() customer.CustomerID

func (StandardInvoiceBase) GetDeletedAt

func (i StandardInvoiceBase) GetDeletedAt() *time.Time

func (StandardInvoiceBase) GetID

func (i StandardInvoiceBase) GetID() string

func (StandardInvoiceBase) GetInvoiceID

func (i StandardInvoiceBase) GetInvoiceID() InvoiceID

func (StandardInvoiceBase) Validate

func (i StandardInvoiceBase) Validate() error

type StandardInvoiceCreatedEvent

type StandardInvoiceCreatedEvent struct {
	EventStandardInvoice `json:",inline"`
}

func NewStandardInvoiceCreatedEvent

func NewStandardInvoiceCreatedEvent(invoice StandardInvoice) (StandardInvoiceCreatedEvent, error)

func (StandardInvoiceCreatedEvent) EventMetadata

func (StandardInvoiceCreatedEvent) EventName

func (e StandardInvoiceCreatedEvent) EventName() string

func (StandardInvoiceCreatedEvent) Validate

func (e StandardInvoiceCreatedEvent) Validate() error

type StandardInvoiceLines

type StandardInvoiceLines struct {
	mo.Option[StandardLines]
}

func NewStandardInvoiceLines

func NewStandardInvoiceLines(children []*StandardLine) StandardInvoiceLines

func (*StandardInvoiceLines) Append

func (c *StandardInvoiceLines) Append(l ...*StandardLine)

func (StandardInvoiceLines) Clone

func (StandardInvoiceLines) GetByID

func (c StandardInvoiceLines) GetByID(id string) *StandardLine

func (StandardInvoiceLines) GetReferencedFeatureKeys

func (c StandardInvoiceLines) GetReferencedFeatureKeys() ([]string, error)

func (StandardInvoiceLines) Map

func (StandardInvoiceLines) MapWithErr

func (StandardInvoiceLines) NonDeletedLineCount

func (c StandardInvoiceLines) NonDeletedLineCount() int

NonDeletedLineCount returns the number of lines that are not deleted and have a valid status (e.g. we are ignoring split lines)

func (*StandardInvoiceLines) RemoveByID

func (c *StandardInvoiceLines) RemoveByID(id string) bool

func (*StandardInvoiceLines) ReplaceByID

func (c *StandardInvoiceLines) ReplaceByID(id string, newLine *StandardLine) bool

func (*StandardInvoiceLines) Sort

func (c *StandardInvoiceLines) Sort()

func (StandardInvoiceLines) Validate

func (i StandardInvoiceLines) Validate() error

func (StandardInvoiceLines) WithNormalizedValues

func (c StandardInvoiceLines) WithNormalizedValues() (StandardInvoiceLines, error)

type StandardInvoiceOperation

type StandardInvoiceOperation string
const (
	StandardInvoiceOpValidate        StandardInvoiceOperation = "validate"
	StandardInvoiceOpSync            StandardInvoiceOperation = "sync"
	StandardInvoiceOpDelete          StandardInvoiceOperation = "delete"
	StandardInvoiceOpFinalize        StandardInvoiceOperation = "finalize"
	StandardInvoiceOpInitiatePayment StandardInvoiceOperation = "initiate_payment"

	StandardInvoiceOpPostAdvanceHook StandardInvoiceOperation = "post_advance_hook"
	StandardInvoiceOpTriggerInvoice  StandardInvoiceOperation = "trigger_invoice"
)

func (StandardInvoiceOperation) Validate

func (o StandardInvoiceOperation) Validate() error

type StandardInvoiceService

type StandardInvoiceService interface {
	// UpdateStandardInvoice updates a standard invoice as a whole
	UpdateStandardInvoice(ctx context.Context, input UpdateStandardInvoiceInput) (StandardInvoice, error)
}

type StandardInvoiceStatus

type StandardInvoiceStatus string
const (
	// StandardInvoiceStatusGathering is the status of an invoice that is gathering the items to be invoiced.
	StandardInvoiceStatusGathering StandardInvoiceStatus = "gathering"

	StandardInvoiceStatusDraftCreated StandardInvoiceStatus = "draft.created"
	// StandardInvoiceStatusDraftWaitingForCollection is the status of an invoice that is waiting for the collection to be possible (e.g. collection period has passed)
	StandardInvoiceStatusDraftWaitingForCollection StandardInvoiceStatus = "draft.waiting_for_collection"
	// StandardInvoiceStatusDraftCollecting is the status of an invoice that is collecting the items to be invoiced.
	StandardInvoiceStatusDraftCollecting           StandardInvoiceStatus = "draft.collecting"
	StandardInvoiceStatusDraftUpdating             StandardInvoiceStatus = "draft.updating"
	StandardInvoiceStatusDraftManualApprovalNeeded StandardInvoiceStatus = "draft.manual_approval_needed"
	StandardInvoiceStatusDraftValidating           StandardInvoiceStatus = "draft.validating"
	StandardInvoiceStatusDraftInvalid              StandardInvoiceStatus = "draft.invalid"
	StandardInvoiceStatusDraftSyncing              StandardInvoiceStatus = "draft.syncing"
	StandardInvoiceStatusDraftSyncFailed           StandardInvoiceStatus = "draft.sync_failed"
	StandardInvoiceStatusDraftWaitingAutoApproval  StandardInvoiceStatus = "draft.waiting_auto_approval"
	StandardInvoiceStatusDraftReadyToIssue         StandardInvoiceStatus = "draft.ready_to_issue"

	StandardInvoiceStatusDeleteInProgress StandardInvoiceStatus = "delete.in_progress"
	StandardInvoiceStatusDeleteSyncing    StandardInvoiceStatus = "delete.syncing"
	StandardInvoiceStatusDeleteFailed     StandardInvoiceStatus = "delete.failed"
	StandardInvoiceStatusDeleted          StandardInvoiceStatus = "deleted"

	StandardInvoiceStatusIssuingSyncing    StandardInvoiceStatus = "issuing.syncing"
	StandardInvoiceStatusIssuingSyncFailed StandardInvoiceStatus = "issuing.failed"

	StandardInvoiceStatusIssued StandardInvoiceStatus = "issued"

	StandardInvoiceStatusPaymentProcessingPending        StandardInvoiceStatus = "payment_processing.pending"
	StandardInvoiceStatusPaymentProcessingFailed         StandardInvoiceStatus = "payment_processing.failed"
	StandardInvoiceStatusPaymentProcessingActionRequired StandardInvoiceStatus = "payment_processing.action_required"

	StandardInvoiceStatusOverdue StandardInvoiceStatus = "overdue"

	StandardInvoiceStatusPaid StandardInvoiceStatus = "paid"

	StandardInvoiceStatusUncollectible StandardInvoiceStatus = "uncollectible"

	StandardInvoiceStatusVoided StandardInvoiceStatus = "voided"
)

func (StandardInvoiceStatus) IsFailed

func (s StandardInvoiceStatus) IsFailed() bool

func (StandardInvoiceStatus) IsFinal

func (s StandardInvoiceStatus) IsFinal() bool

func (StandardInvoiceStatus) Matches

func (StandardInvoiceStatus) MatchesInvoiceStatus

func (s StandardInvoiceStatus) MatchesInvoiceStatus(status StandardInvoiceStatus) bool

func (StandardInvoiceStatus) ShortStatus

func (s StandardInvoiceStatus) ShortStatus() string

func (StandardInvoiceStatus) Validate

func (s StandardInvoiceStatus) Validate() error

func (StandardInvoiceStatus) Values

func (s StandardInvoiceStatus) Values() []string

type StandardInvoiceStatusCategory

type StandardInvoiceStatusCategory string
const (
	StandardInvoiceStatusCategoryGathering         StandardInvoiceStatusCategory = "gathering"
	StandardInvoiceStatusCategoryDraft             StandardInvoiceStatusCategory = "draft"
	StandardInvoiceStatusCategoryDelete            StandardInvoiceStatusCategory = "delete"
	StandardInvoiceStatusCategoryDeleted           StandardInvoiceStatusCategory = "deleted"
	StandardInvoiceStatusCategoryIssuing           StandardInvoiceStatusCategory = "issuing"
	StandardInvoiceStatusCategoryIssued            StandardInvoiceStatusCategory = "issued"
	StandardInvoiceStatusCategoryPaymentProcessing StandardInvoiceStatusCategory = "payment_processing"
	StandardInvoiceStatusCategoryOverdue           StandardInvoiceStatusCategory = "overdue"
	StandardInvoiceStatusCategoryPaid              StandardInvoiceStatusCategory = "paid"
	StandardInvoiceStatusCategoryUncollectible     StandardInvoiceStatusCategory = "uncollectible"
	StandardInvoiceStatusCategoryVoided            StandardInvoiceStatusCategory = "voided"
)

func (StandardInvoiceStatusCategory) MatchesInvoiceStatus

func (s StandardInvoiceStatusCategory) MatchesInvoiceStatus(status StandardInvoiceStatus) bool

type StandardInvoiceStatusDetails

type StandardInvoiceStatusDetails struct {
	Immutable        bool                            `json:"immutable"`
	Failed           bool                            `json:"failed"`
	AvailableActions StandardInvoiceAvailableActions `json:"availableActions"`
}

type StandardInvoiceStatusMatcher

type StandardInvoiceStatusMatcher interface {
	MatchesInvoiceStatus(StandardInvoiceStatus) bool
}

type StandardInvoiceUpdatedEvent

type StandardInvoiceUpdatedEvent struct {
	Old EventStandardInvoice `json:"old"`
	New EventStandardInvoice `json:"new"`
}

func (StandardInvoiceUpdatedEvent) EventMetadata

func (StandardInvoiceUpdatedEvent) EventName

func (e StandardInvoiceUpdatedEvent) EventName() string

func (StandardInvoiceUpdatedEvent) Validate

func (e StandardInvoiceUpdatedEvent) Validate() error

type StandardLine

type StandardLine struct {
	StandardLineBase `json:",inline"`

	UsageBased *UsageBasedLine `json:"usageBased,omitempty"`

	DetailedLines      DetailedLines       `json:"detailedLines,omitempty"`
	SplitLineHierarchy *SplitLineHierarchy `json:"progressiveLineHierarchy,omitempty"`

	Discounts LineDiscounts `json:"discounts,omitempty"`

	DBState *StandardLine `json:"-"`
}

func NewFlatFeeLine

func NewFlatFeeLine(input NewFlatFeeLineInput, opts ...usageBasedLineOption) *StandardLine

NewFlatFeeLine creates a new invoice-level flat fee line.

func (StandardLine) AsInvoiceLine

func (i StandardLine) AsInvoiceLine() InvoiceLine

func (StandardLine) Clone

func (i StandardLine) Clone() (*StandardLine, error)

func (StandardLine) CloneWithoutChildren

func (i StandardLine) CloneWithoutChildren() (*StandardLine, error)

func (StandardLine) CloneWithoutDependencies

func (i StandardLine) CloneWithoutDependencies(edits ...StandardLineEditFunction) (*StandardLine, error)

CloneWithoutDependencies returns a clone of the line without any external dependencies. Could be used for creating a new line without any references to the parent or children (or config IDs).

func (StandardLine) DependsOnMeteredQuantity

func (i StandardLine) DependsOnMeteredQuantity() bool

func (StandardLine) DetailedLinesWithIDReuse

func (c StandardLine) DetailedLinesWithIDReuse(l DetailedLines) DetailedLines

DetailedLinesWithIDReuse returns a new DetailedLines instance with the given lines. If the line has a child with a unique reference ID, it will try to retain the database ID of the existing child to avoid a delete/create.

func (*StandardLine) DisassociateChildren

func (i *StandardLine) DisassociateChildren()

DissacociateChildren removes the Children both from the DBState and the current line, so that the line can be safely persisted/managed without the children.

The childrens receive DBState objects, so that they can be safely persisted/managed without the parent.

func (StandardLine) GetAnnotations

func (i StandardLine) GetAnnotations() models.Annotations

func (StandardLine) GetChildUniqueReferenceID

func (i StandardLine) GetChildUniqueReferenceID() *string

func (StandardLine) GetFeatureKey

func (i StandardLine) GetFeatureKey() string

func (StandardLine) GetID

func (i StandardLine) GetID() string

func (StandardLine) GetInvoiceAt

func (i StandardLine) GetInvoiceAt() time.Time

func (StandardLine) GetInvoiceID

func (i StandardLine) GetInvoiceID() string

func (StandardLine) GetLineID

func (i StandardLine) GetLineID() LineID

func (StandardLine) GetManagedBy

func (i StandardLine) GetManagedBy() InvoiceLineManagedBy

func (StandardLine) GetPrice

func (i StandardLine) GetPrice() *productcatalog.Price

func (StandardLine) GetQuantity

func (i StandardLine) GetQuantity() *alpacadecimal.Decimal

func (StandardLine) GetRateCardDiscounts

func (i StandardLine) GetRateCardDiscounts() Discounts

func (StandardLine) GetServicePeriod

func (i StandardLine) GetServicePeriod() timeutil.ClosedPeriod

func (StandardLine) GetSplitLineGroupID

func (i StandardLine) GetSplitLineGroupID() *string

func (StandardLine) GetSubscriptionReference

func (i StandardLine) GetSubscriptionReference() *SubscriptionReference

func (StandardLine) RemoveCircularReferences

func (i StandardLine) RemoveCircularReferences() (*StandardLine, error)

func (StandardLine) RemoveMetaForCompare

func (i StandardLine) RemoveMetaForCompare() (*StandardLine, error)

RemoveMetaForCompare returns a copy of the invoice without the fields that are not relevant for higher level tests that compare invoices. What gets removed: - Line's DB state - Line's dependencies are marked as resolved - Parent pointers are removed

func (*StandardLine) SaveDBSnapshot

func (i *StandardLine) SaveDBSnapshot() error

func (*StandardLine) SetChildUniqueReferenceID

func (i *StandardLine) SetChildUniqueReferenceID(id *string)

func (*StandardLine) SetDeletedAt

func (i *StandardLine) SetDeletedAt(at *time.Time)

func (StandardLine) SetDiscountExternalIDs

func (i StandardLine) SetDiscountExternalIDs(externalIDs map[string]string) []string

func (*StandardLine) SetPrice

func (i *StandardLine) SetPrice(price productcatalog.Price)

func (*StandardLine) SortDetailedLines

func (i *StandardLine) SortDetailedLines()

func (StandardLine) ToGatheringLineBase

func (i StandardLine) ToGatheringLineBase() (GatheringLineBase, error)

ToGatheringLineBase converts the standard line to a gathering line base. This is temporary until the full gathering invoice functionality is split.

func (*StandardLine) UpdateServicePeriod

func (i *StandardLine) UpdateServicePeriod(fn func(p *timeutil.ClosedPeriod))

func (StandardLine) Validate

func (i StandardLine) Validate() error

func (StandardLine) WithNormalizedValues

func (i StandardLine) WithNormalizedValues() (*StandardLine, error)

NormalizeValues normalizes the values of the line to ensure they are matching the expected invariants: - Period is truncated to the minimum window size duration - InvoiceAt is truncated to the minimum window size duration - UsageBased.Price is normalized to have the default inAdvance payment term for flat prices

func (StandardLine) WithoutDBState

func (i StandardLine) WithoutDBState() *StandardLine

func (StandardLine) WithoutSplitLineHierarchy

func (i StandardLine) WithoutSplitLineHierarchy() *StandardLine

type StandardLineBase

type StandardLineBase struct {
	models.ManagedResource

	Metadata    models.Metadata      `json:"metadata,omitempty"`
	Annotations models.Annotations   `json:"annotations,omitempty"`
	ManagedBy   InvoiceLineManagedBy `json:"managedBy"`

	InvoiceID string         `json:"invoiceID,omitempty"`
	Currency  currencyx.Code `json:"currency"`

	// Lifecycle
	Period    Period    `json:"period"`
	InvoiceAt time.Time `json:"invoiceAt"`

	// Relationships
	ParentLineID     *string `json:"parentLine,omitempty"`
	SplitLineGroupID *string `json:"splitLineGroupId,omitempty"`

	ChildUniqueReferenceID *string `json:"childUniqueReferenceID,omitempty"`

	TaxConfig         *productcatalog.TaxConfig `json:"taxOverrides,omitempty"`
	RateCardDiscounts Discounts                 `json:"rateCardDiscounts,omitempty"`

	ExternalIDs  LineExternalIDs        `json:"externalIDs,omitempty"`
	Subscription *SubscriptionReference `json:"subscription,omitempty"`

	Totals Totals `json:"totals,omitempty"`
}

StandardLineBase represents the common fields for an invoice item.

func (StandardLineBase) Clone

func (StandardLineBase) Equal

func (i StandardLineBase) Equal(other StandardLineBase) bool

func (StandardLineBase) GetParentID

func (i StandardLineBase) GetParentID() (string, bool)

func (StandardLineBase) Validate

func (i StandardLineBase) Validate() error

type StandardLineEditFunction

type StandardLineEditFunction func(*StandardLine)

type StandardLineWithInvoiceHeader

type StandardLineWithInvoiceHeader struct {
	Line    *StandardLine
	Invoice StandardInvoice
}

type StandardLines

type StandardLines []*StandardLine

func NewStandardLines

func NewStandardLines(children []*StandardLine) StandardLines

func (StandardLines) Clone

func (i StandardLines) Clone() (StandardLines, error)

func (StandardLines) GetByChildUniqueReferenceID

func (c StandardLines) GetByChildUniqueReferenceID(id string) *StandardLine

func (StandardLines) GetReferencedFeatureKeys

func (c StandardLines) GetReferencedFeatureKeys() ([]string, error)

func (StandardLines) Map

func (*StandardLines) Sort

func (c *StandardLines) Sort()

func (StandardLines) Validate

func (c StandardLines) Validate() error

type SubscriptionReference

type SubscriptionReference struct {
	SubscriptionID string                `json:"subscriptionID"`
	PhaseID        string                `json:"phaseID"`
	ItemID         string                `json:"itemID"`
	BillingPeriod  timeutil.ClosedPeriod `json:"billingPeriod"`
}

func (SubscriptionReference) Clone

func (SubscriptionReference) Validate

func (i SubscriptionReference) Validate() error

type SumNetAmountInput

type SumNetAmountInput struct {
	PeriodEndLTE   time.Time
	IncludeCharges bool
}

type SupplierContact

type SupplierContact struct {
	ID      string         `json:"id"`
	Name    string         `json:"name"`
	Address models.Address `json:"address"`
	TaxCode *string        `json:"taxCode,omitempty"`
}

func (SupplierContact) Validate

func (c SupplierContact) Validate() error

Validate checks if the supplier contact is valid for invoice generation (e.g. Country is required)

type SyncDraftStandardInvoiceInput

type SyncDraftStandardInvoiceInput struct {
	InvoiceID            InvoiceID
	UpsertInvoiceResults *UpsertStandardInvoiceResult
	AdditionalMetadata   map[string]string
	InvoiceValidator     func(invoice StandardInvoice) error
}

func (SyncDraftStandardInvoiceInput) GetAdditionalMetadata

func (i SyncDraftStandardInvoiceInput) GetAdditionalMetadata() map[string]string

func (SyncDraftStandardInvoiceInput) GetInvoiceID

func (i SyncDraftStandardInvoiceInput) GetInvoiceID() InvoiceID

func (SyncDraftStandardInvoiceInput) MergeIntoInvoice

func (i SyncDraftStandardInvoiceInput) MergeIntoInvoice(invoice *StandardInvoice) error

func (SyncDraftStandardInvoiceInput) Validate

func (i SyncDraftStandardInvoiceInput) Validate() error

func (SyncDraftStandardInvoiceInput) ValidateWithInvoice

func (i SyncDraftStandardInvoiceInput) ValidateWithInvoice(invoice StandardInvoice) error

type SyncInput

type SyncInput interface {
	models.Validator

	ValidateWithInvoice(invoice StandardInvoice) error
	MergeIntoInvoice(invoice *StandardInvoice) error
	GetAdditionalMetadata() map[string]string
	GetInvoiceID() InvoiceID
}

type SyncIssuingStandardInvoiceInput

type SyncIssuingStandardInvoiceInput struct {
	InvoiceID             InvoiceID
	FinalizeInvoiceResult *FinalizeStandardInvoiceResult
	AdditionalMetadata    map[string]string
	InvoiceValidator      func(invoice StandardInvoice) error
}

func (SyncIssuingStandardInvoiceInput) GetAdditionalMetadata

func (i SyncIssuingStandardInvoiceInput) GetAdditionalMetadata() map[string]string

func (SyncIssuingStandardInvoiceInput) GetInvoiceID

func (i SyncIssuingStandardInvoiceInput) GetInvoiceID() InvoiceID

func (SyncIssuingStandardInvoiceInput) MergeIntoInvoice

func (i SyncIssuingStandardInvoiceInput) MergeIntoInvoice(invoice *StandardInvoice) error

func (SyncIssuingStandardInvoiceInput) Validate

func (SyncIssuingStandardInvoiceInput) ValidateWithInvoice

func (i SyncIssuingStandardInvoiceInput) ValidateWithInvoice(invoice StandardInvoice) error

type Totals

type Totals struct {
	// Amount is the total amount value of the line before taxes, discounts and commitments
	Amount alpacadecimal.Decimal `json:"amount"`
	// ChargesTotal is the amount of value of the line that are due to additional charges
	ChargesTotal alpacadecimal.Decimal `json:"chargesTotal"`
	// DiscountsTotal is the amount of value of the line that are due to discounts
	DiscountsTotal alpacadecimal.Decimal `json:"discountsTotal"`

	// TaxesInclusiveTotal is the total amount of taxes that are included in the line
	TaxesInclusiveTotal alpacadecimal.Decimal `json:"taxesInclusiveTotal"`
	// TaxesExclusiveTotal is the total amount of taxes that are excluded from the line
	TaxesExclusiveTotal alpacadecimal.Decimal `json:"taxesExclusiveTotal"`
	// TaxesTotal is the total amount of taxes that are included in the line
	TaxesTotal alpacadecimal.Decimal `json:"taxesTotal"`

	// Total is the total amount value of the line after taxes, discounts and commitments
	Total alpacadecimal.Decimal `json:"total"`
}

func (Totals) Add

func (t Totals) Add(others ...Totals) Totals

func (Totals) CalculateTotal

func (t Totals) CalculateTotal() alpacadecimal.Decimal

func (Totals) Validate

func (t Totals) Validate() error

type UpdateAfterDeleteError

type UpdateAfterDeleteError genericError

func (UpdateAfterDeleteError) Error

func (e UpdateAfterDeleteError) Error() string

func (UpdateAfterDeleteError) Unwrap

func (e UpdateAfterDeleteError) Unwrap() error

type UpdateCustomerOverrideAdapterInput

type UpdateCustomerOverrideAdapterInput = UpsertCustomerOverrideInput

type UpdateGatheringInvoiceAdapterInput

type UpdateGatheringInvoiceAdapterInput = GatheringInvoice

type UpdateGatheringInvoiceInput

type UpdateGatheringInvoiceInput struct {
	Invoice InvoiceID
	EditFn  func(*GatheringInvoice) error
	// IncludeDeletedLines signals the update to populate the deleted lines into the lines field, for the edit function
	IncludeDeletedLines bool
}

func (UpdateGatheringInvoiceInput) Validate

func (i UpdateGatheringInvoiceInput) Validate() error

type UpdateInvoiceAdapterInput

type UpdateInvoiceAdapterInput = StandardInvoice

type UpdateInvoiceFieldsInput

type UpdateInvoiceFieldsInput struct {
	Invoice          InvoiceID
	SentToCustomerAt mo.Option[*time.Time]
}

func (UpdateInvoiceFieldsInput) Validate

func (i UpdateInvoiceFieldsInput) Validate() error

type UpdateInvoiceInput

type UpdateInvoiceInput struct {
	Invoice InvoiceID
	EditFn  func(Invoice) (Invoice, error)
	// IncludeDeletedLines signals the update to populate the deleted lines into the lines field, for the edit function
	IncludeDeletedLines bool
}

func (UpdateInvoiceInput) Validate

func (i UpdateInvoiceInput) Validate() error

type UpdateInvoiceLinesInternalInput

type UpdateInvoiceLinesInternalInput struct {
	Namespace  string
	CustomerID string
	Lines      []*StandardLine
}

func (UpdateInvoiceLinesInternalInput) Validate

type UpdateProfileAdapterInput

type UpdateProfileAdapterInput struct {
	TargetState      BaseProfile
	WorkflowConfigID string
}

func (UpdateProfileAdapterInput) Validate

func (i UpdateProfileAdapterInput) Validate() error

type UpdateProfileInput

type UpdateProfileInput BaseProfile

func (UpdateProfileInput) ProfileID

func (i UpdateProfileInput) ProfileID() ProfileID

func (UpdateProfileInput) Validate

func (i UpdateProfileInput) Validate() error

type UpdateSplitLineGroupInput

type UpdateSplitLineGroupInput = SplitLineGroupUpdate

Adapter

type UpdateStandardInvoiceInput

type UpdateStandardInvoiceInput struct {
	Invoice InvoiceID
	EditFn  func(*StandardInvoice) error
	// IncludeDeletedLines signals the update to populate the deleted lines into the lines field, for the edit function
	IncludeDeletedLines bool
}

func (UpdateStandardInvoiceInput) Validate

func (i UpdateStandardInvoiceInput) Validate() error

type UpsertCustomerLockAdapterInput

type UpsertCustomerLockAdapterInput = LockCustomerForUpdateAdapterInput

type UpsertCustomerOverrideInput

type UpsertCustomerOverrideInput struct {
	Namespace  string `json:"namespace"`
	CustomerID string `json:"customerID"`

	ProfileID string `json:"billingProfileID"`

	Collection CollectionOverrideConfig `json:"collection"`
	Invoicing  InvoicingOverrideConfig  `json:"invoicing"`
	Payment    PaymentOverrideConfig    `json:"payment"`
}

func (UpsertCustomerOverrideInput) Validate

func (u UpsertCustomerOverrideInput) Validate() error

type UpsertInvoiceLinesAdapterInput

type UpsertInvoiceLinesAdapterInput struct {
	Namespace   string
	Lines       StandardLines
	SchemaLevel int
	InvoiceID   string
}

func (UpsertInvoiceLinesAdapterInput) Validate

type UpsertResults

type UpsertResults struct {
	// contains filtered or unexported fields
}

func NewUpsertResults

func NewUpsertResults() *UpsertResults

func (*UpsertResults) AddLineDiscountExternalID

func (u *UpsertResults) AddLineDiscountExternalID(lineDiscountID string, externalID string) *UpsertResults

func (*UpsertResults) AddLineExternalID

func (u *UpsertResults) AddLineExternalID(lineID string, externalID string) *UpsertResults

func (*UpsertResults) GetExternalID

func (u *UpsertResults) GetExternalID() (string, bool)

func (*UpsertResults) GetInvoiceNumber

func (u *UpsertResults) GetInvoiceNumber() (string, bool)

func (*UpsertResults) GetLineDiscountExternalID

func (u *UpsertResults) GetLineDiscountExternalID(lineDiscountID string) (string, bool)

func (*UpsertResults) GetLineDiscountExternalIDs

func (u *UpsertResults) GetLineDiscountExternalIDs() map[string]string

func (*UpsertResults) GetLineExternalID

func (u *UpsertResults) GetLineExternalID(lineID string) (string, bool)

func (*UpsertResults) GetLineExternalIDs

func (u *UpsertResults) GetLineExternalIDs() map[string]string

func (*UpsertResults) SetExternalID

func (u *UpsertResults) SetExternalID(externalID string) *UpsertResults

func (*UpsertResults) SetInvoiceNumber

func (u *UpsertResults) SetInvoiceNumber(invoiceNumber string) *UpsertResults

type UpsertStandardInvoiceResult

type UpsertStandardInvoiceResult = UpsertResults

func NewUpsertStandardInvoiceResult

func NewUpsertStandardInvoiceResult() *UpsertStandardInvoiceResult

func (UpsertStandardInvoiceResult) MergeIntoInvoice

func (r UpsertStandardInvoiceResult) MergeIntoInvoice(invoice *StandardInvoice) error

MergeIntoInvoice merges the upsert invoice result into the invoice.

type UpsertValidationIssuesInput

type UpsertValidationIssuesInput struct {
	Invoice InvoiceID
	Issues  ValidationIssues
}

func (UpsertValidationIssuesInput) Validate

func (i UpsertValidationIssuesInput) Validate() error

type UsageBasedLine

type UsageBasedLine struct {
	ConfigID string `json:"configId,omitempty"`

	// Price is the price of the usage based line. Note: this should be a pointer or marshaling will fail for
	// empty prices.
	Price      *productcatalog.Price `json:"price"`
	FeatureKey string                `json:"featureKey"`

	Quantity        *alpacadecimal.Decimal `json:"quantity,omitempty"`
	MeteredQuantity *alpacadecimal.Decimal `json:"meteredQuantity,omitempty"`

	PreLinePeriodQuantity        *alpacadecimal.Decimal `json:"preLinePeriodQuantity,omitempty"`
	MeteredPreLinePeriodQuantity *alpacadecimal.Decimal `json:"meteredPreLinePeriodQuantity,omitempty"`
}

func (UsageBasedLine) Clone

func (i UsageBasedLine) Clone() *UsageBasedLine

func (UsageBasedLine) Equal

func (i UsageBasedLine) Equal(other *UsageBasedLine) bool

func (UsageBasedLine) Validate

func (i UsageBasedLine) Validate() error

type UsageDiscount

type UsageDiscount struct {
	productcatalog.UsageDiscount `json:",inline"`

	CorrelationID string `json:"correlationID"`
}

func (UsageDiscount) Clone

func (d UsageDiscount) Clone() UsageDiscount

func (UsageDiscount) Equal

func (d UsageDiscount) Equal(other UsageDiscount) bool

type UsageLineDiscount

type UsageLineDiscount struct {
	LineDiscountBase `json:",inline"`

	Quantity              alpacadecimal.Decimal  `json:"quantity"`
	PreLinePeriodQuantity *alpacadecimal.Decimal `json:"preLinePeriodQuantity"`
}

func (UsageLineDiscount) Clone

func (UsageLineDiscount) Equal

func (i UsageLineDiscount) Equal(other UsageLineDiscount) bool

func (UsageLineDiscount) Validate

func (i UsageLineDiscount) Validate() error

type UsageLineDiscountManaged

type UsageLineDiscountManaged struct {
	models.ManagedModelWithID `json:",inline"`
	UsageLineDiscount         `json:",inline"`
}

func (UsageLineDiscountManaged) Clone

func (UsageLineDiscountManaged) ContentsEqual

func (UsageLineDiscountManaged) Equal

func (UsageLineDiscountManaged) GetManagedFieldsWithID

func (i UsageLineDiscountManaged) GetManagedFieldsWithID() models.ManagedModelWithID

func (UsageLineDiscountManaged) Validate

func (i UsageLineDiscountManaged) Validate() error

func (UsageLineDiscountManaged) WithManagedFieldsWithID

type UsageLineDiscountsManaged

type UsageLineDiscountsManaged []UsageLineDiscountManaged

func (UsageLineDiscountsManaged) Clone

func (UsageLineDiscountsManaged) MergeDiscountsByChildUniqueReferenceID

func (d UsageLineDiscountsManaged) MergeDiscountsByChildUniqueReferenceID(newDiscount UsageLineDiscountManaged) UsageLineDiscountsManaged

type ValidationError

type ValidationError genericError

func (ValidationError) Error

func (e ValidationError) Error() string

func (ValidationError) Unwrap

func (e ValidationError) Unwrap() error

type ValidationIssue

type ValidationIssue struct {
	ID        string     `json:"id,omitempty"`
	CreatedAt time.Time  `json:"createdAt,omitempty"`
	UpdatedAt time.Time  `json:"updatedAt,omitempty"`
	DeletedAt *time.Time `json:"deletedAt,omitempty"`

	Severity  ValidationIssueSeverity `json:"severity"`
	Message   string                  `json:"message"`
	Code      string                  `json:"code,omitempty"`
	Component ComponentName           `json:"component,omitempty"`
	Path      string                  `json:"path,omitempty"`
}

func NewValidationError

func NewValidationError(code, message string) ValidationIssue

func NewValidationWarning

func NewValidationWarning(code, message string) ValidationIssue

func (ValidationIssue) EncodeAsErrorExtension

func (i ValidationIssue) EncodeAsErrorExtension() map[string]interface{}

func (ValidationIssue) Error

func (i ValidationIssue) Error() string

type ValidationIssueSeverity

type ValidationIssueSeverity string

func (ValidationIssueSeverity) Values

func (ValidationIssueSeverity) Values() []string

type ValidationIssues

type ValidationIssues []ValidationIssue

func ToValidationIssues

func ToValidationIssues(errIn error) (ValidationIssues, error)

ToValidationIssues converts an error into a list of validation issues If the error is nil, it returns nil If any error in the error tree is not wrapped in ValidationWithComponent or ValidationWithFieldPrefix and not an instance of ValidationIssue, it will return an error. This behavior allows us to have critical errors that are not validation issues.

func (ValidationIssues) AsError

func (v ValidationIssues) AsError() error

func (ValidationIssues) Clone

func (ValidationIssues) Map

func (ValidationIssues) RemoveMetaForCompare

func (v ValidationIssues) RemoveMetaForCompare() ValidationIssues

type VersionedCustomerUsageAttribution

type VersionedCustomerUsageAttribution struct {
	streaming.CustomerUsageAttribution `json:",inline"`
	Type                               string `json:"type"`
}

type WorkflowConfig

type WorkflowConfig struct {
	Collection CollectionConfig  `json:"collection"`
	Invoicing  InvoicingConfig   `json:"invoicing"`
	Payment    PaymentConfig     `json:"payment"`
	Tax        WorkflowTaxConfig `json:"tax"`
}

func (WorkflowConfig) Validate

func (c WorkflowConfig) Validate() error

type WorkflowTaxConfig

type WorkflowTaxConfig struct {
	// Enable automatic tax calculation when tax is supported by the app.
	// For example, with Stripe Invoicing when enabled, tax is calculated via Stripe Tax.
	Enabled bool `json:"enabled"`

	// Enforce tax calculation when tax is supported by the app.
	// When enabled, OpenMeter will not allow to create an invoice without tax calculation.
	// Enforcement is different per apps, for example, Stripe app requires customer
	// to have a tax location when starting a paid subscription.
	Enforced bool `json:"enforced"`
}

WorkflowTaxConfig groups fields related to tax settings.

func (*WorkflowTaxConfig) Validate

func (c *WorkflowTaxConfig) Validate() error

Validate validates the tax config.

Directories

Path Synopsis
lineservice
lineservice package contains the implementation of the LineAdapter interface which acts as a adapter between the specific line types and the billing service.
lineservice package contains the implementation of the LineAdapter interface which acts as a adapter between the specific line types and the billing service.
validators

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL