openmeter / ledger /query.go
Leon4gr45's picture
Upload folder using huggingface_hub (part 5)
cee2387 verified
Raw
History Blame Contribute Delete
3.96 kB
package ledger
import (
"fmt"
"time"
"github.com/samber/mo"
"github.com/openmeterio/openmeter/pkg/models"
"github.com/openmeterio/openmeter/pkg/pagination/v2"
"github.com/openmeterio/openmeter/pkg/timeutil"
)
type Query struct {
Namespace string
Cursor *pagination.Cursor
Filters Filters
}
func (p Query) Validate() error {
if p.Namespace == "" {
return ErrLedgerQueryInvalid.WithAttrs(models.Attributes{
"reason": "namespace_required",
"namespace": p.Namespace,
})
}
if p.Cursor != nil {
if err := p.Cursor.Validate(); err != nil {
return ErrLedgerQueryInvalid.WithAttrs(models.Attributes{
"reason": "cursor_invalid",
"cursor": p.Cursor,
"error": err,
})
}
}
if p.Filters.TransactionID != nil && *p.Filters.TransactionID == "" {
return ErrLedgerQueryInvalid.WithAttrs(models.Attributes{
"reason": "transaction_id_required",
"transaction_id": *p.Filters.TransactionID,
})
}
if p.Filters.AccountID != nil && *p.Filters.AccountID == "" {
return ErrLedgerQueryInvalid.WithAttrs(models.Attributes{
"reason": "account_id_required",
"account_id": *p.Filters.AccountID,
})
}
if err := validateOptionalChargeIDFilter("source_charge_id", p.Filters.SourceChargeID); err != nil {
return ErrLedgerQueryInvalid.WithAttrs(models.Attributes{
"reason": "source_charge_id_invalid",
"error": err,
})
}
if err := validateOptionalChargeIDFilter("spend_charge_id", p.Filters.SpendChargeID); err != nil {
return ErrLedgerQueryInvalid.WithAttrs(models.Attributes{
"reason": "spend_charge_id_invalid",
"error": err,
})
}
if p.Filters.BookedAtPeriod != nil {
if err := p.Filters.BookedAtPeriod.Validate(); err != nil {
return ErrLedgerQueryInvalid.WithAttrs(models.Attributes{
"reason": "booked_at_period_invalid",
"booked_at_period": p.Filters.BookedAtPeriod,
"error": err,
})
}
}
if p.Filters.After != nil {
if err := p.Filters.After.Validate(); err != nil {
return ErrLedgerQueryInvalid.WithAttrs(models.Attributes{
"reason": "after_invalid",
"after": p.Filters.After,
"error": err,
})
}
}
if p.Filters.AsOf != nil && p.Filters.AsOf.IsZero() {
return ErrLedgerQueryInvalid.WithAttrs(models.Attributes{
"reason": "as_of_invalid",
"as_of": p.Filters.AsOf,
"error": fmt.Errorf("as_of must not be zero"),
})
}
if p.Filters.After != nil && p.Filters.AsOf != nil {
return ErrLedgerQueryInvalid.WithAttrs(models.Attributes{
"reason": "after_as_of_both_set",
})
}
if _, err := p.Filters.Route.Normalize(); err != nil {
return ErrLedgerQueryInvalid.WithAttrs(models.Attributes{
"reason": "route_invalid",
"route": p.Filters.Route,
"error": err,
})
}
return nil
}
type Filters struct {
// BookedAtPeriod is inclusive-exclusive... should it be? Maybe finally add period inclusivity params?
BookedAtPeriod *timeutil.OpenPeriod
After *TransactionCursor
AsOf *time.Time
TransactionID *string
// AccountID narrows the query to a single account via its sub-accounts.
AccountID *string
// SourceChargeID narrows entries by the creditpurchase charge that funded them.
// Absent aggregates across source charges, Some(nil) selects source-less entries.
SourceChargeID mo.Option[*string]
// SpendChargeID narrows entries by the charge that consumed or accrued value.
// Absent aggregates across spend charges, Some(nil) selects spend-less entries.
SpendChargeID mo.Option[*string]
// Route is a partial route filter. AccountID plus a full Route.Filter() identifies
// one sub-account, but arbitrary RouteFilter values can match many sub-accounts.
Route RouteFilter
}
func validateOptionalChargeIDFilter(name string, filter mo.Option[*string]) error {
if filter.IsAbsent() {
return nil
}
value, _ := filter.Get()
if value != nil && *value == "" {
return fmt.Errorf("%s must not be empty", name)
}
return nil
}