diff --git a/go.mod b/go.mod index 1ccd64eb9..e4ee5a15c 100644 --- a/go.mod +++ b/go.mod @@ -111,6 +111,7 @@ require ( github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/authzed/authzed-go v1.4.1 // indirect github.com/authzed/grpcutil v0.0.0-20250221190651-1985b19b35b8 // indirect + github.com/awalterschulze/goderive v0.5.1 // indirect github.com/bhmj/xpression v0.9.4 // indirect github.com/bitfield/gotestdox v0.2.2 // indirect github.com/bmatcuk/doublestar v1.3.4 // indirect @@ -150,6 +151,7 @@ require ( github.com/jonboulle/clockwork v0.5.0 // indirect github.com/jzelinskie/stringz v0.0.3 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect + github.com/kisielk/gotool v1.0.0 // indirect github.com/klauspost/asmfmt v1.3.2 // indirect github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 // indirect github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 // indirect @@ -532,6 +534,7 @@ require ( ) tool ( + github.com/awalterschulze/goderive github.com/google/wire/cmd/wire github.com/jmattheis/goverter/cmd/goverter github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen diff --git a/go.sum b/go.sum index 8d31f717d..c38ff9869 100644 --- a/go.sum +++ b/go.sum @@ -864,6 +864,8 @@ github.com/authzed/grpcutil v0.0.0-20250221190651-1985b19b35b8 h1:y17oq4U8n+k1Oc github.com/authzed/grpcutil v0.0.0-20250221190651-1985b19b35b8/go.mod h1:Pf1ZSi41EePvx1GC1DeEJw5dn35iUcxZHqpHuG1Rpic= github.com/avast/retry-go/v4 v4.7.0 h1:yjDs35SlGvKwRNSykujfjdMxMhMQQM0TnIjJaHB+Zio= github.com/avast/retry-go/v4 v4.7.0/go.mod h1:ZMPDa3sY2bKgpLtap9JRUgk2yTAba7cgiFhqxY2Sg6Q= +github.com/awalterschulze/goderive v0.5.1 h1:H2XNRDw0Ordwj/pgLAVqQgDC1LQWP7L99ofOs72bjqg= +github.com/awalterschulze/goderive v0.5.1/go.mod h1:DLlff0SRVo846CBrp8nXuXJ4mdWA92ai5CYTr+LV/II= github.com/aws/aws-lambda-go v1.49.0 h1:z4VhTqkFZPM3xpEtTqWqRqsRH4TZBMJqTkRiBPYLqIQ= github.com/aws/aws-lambda-go v1.49.0/go.mod h1:dpMpZgvWx5vuQJfBt0zqBha60q7Dd7RfgJv23DymV8A= github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= @@ -1797,6 +1799,7 @@ github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU= github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4= github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= @@ -2002,8 +2005,6 @@ github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s= github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 h1:Yl0tPBa8QPjGmesFh1D0rDy+q1Twx6FyU7VWHi8wZbI= github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852/go.mod h1:eqOVx5Vwu4gd2mmMZvVZsgIqNSaW3xxRThUJ0k/TPk4= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= diff --git a/openmeter/billing/derived.gen.go b/openmeter/billing/derived.gen.go new file mode 100644 index 000000000..68b25870e --- /dev/null +++ b/openmeter/billing/derived.gen.go @@ -0,0 +1,186 @@ +// Code generated by goderive DO NOT EDIT. + +package billing + +import ( + models "github.com/openmeterio/openmeter/pkg/models" + timeutil "github.com/openmeterio/openmeter/pkg/timeutil" +) + +// deriveEqualDetailedLineBase returns whether this and that are equal. +func deriveEqualDetailedLineBase(this, that *DetailedLineBase) bool { + return (this == nil && that == nil) || + this != nil && that != nil && + deriveEqual(&this.ManagedResource, &that.ManagedResource) && + this.InvoiceID == that.InvoiceID && + this.Category == that.Category && + ((this.ChildUniqueReferenceID == nil && that.ChildUniqueReferenceID == nil) || (this.ChildUniqueReferenceID != nil && that.ChildUniqueReferenceID != nil && *(this.ChildUniqueReferenceID) == *(that.ChildUniqueReferenceID))) && + ((this.Index == nil && that.Index == nil) || (this.Index != nil && that.Index != nil && *(this.Index) == *(that.Index))) && + this.PaymentTerm == that.PaymentTerm && + this.ServicePeriod.Equal(that.ServicePeriod) && + this.Currency == that.Currency && + this.PerUnitAmount.Equal(that.PerUnitAmount) && + this.Quantity.Equal(that.Quantity) && + deriveEqual_(&this.Totals, &that.Totals) && + this.TaxConfig.Equal(that.TaxConfig) && + this.ExternalIDs.Equal(that.ExternalIDs) && + this.FeeLineConfigID == that.FeeLineConfigID +} + +// deriveEqualLineBase returns whether this and that are equal. +func deriveEqualLineBase(this, that *LineBase) bool { + return (this == nil && that == nil) || + this != nil && that != nil && + deriveEqual(&this.ManagedResource, &that.ManagedResource) && + deriveEqual_1(this.Metadata, that.Metadata) && + this.Annotations.Equal(that.Annotations) && + this.ManagedBy == that.ManagedBy && + this.InvoiceID == that.InvoiceID && + this.Currency == that.Currency && + this.Period.Equal(that.Period) && + this.InvoiceAt.Equal(that.InvoiceAt) && + ((this.ParentLineID == nil && that.ParentLineID == nil) || (this.ParentLineID != nil && that.ParentLineID != nil && *(this.ParentLineID) == *(that.ParentLineID))) && + ((this.SplitLineGroupID == nil && that.SplitLineGroupID == nil) || (this.SplitLineGroupID != nil && that.SplitLineGroupID != nil && *(this.SplitLineGroupID) == *(that.SplitLineGroupID))) && + ((this.ChildUniqueReferenceID == nil && that.ChildUniqueReferenceID == nil) || (this.ChildUniqueReferenceID != nil && that.ChildUniqueReferenceID != nil && *(this.ChildUniqueReferenceID) == *(that.ChildUniqueReferenceID))) && + this.TaxConfig.Equal(that.TaxConfig) && + deriveEqual_2(&this.RateCardDiscounts, &that.RateCardDiscounts) && + this.ExternalIDs.Equal(that.ExternalIDs) && + deriveEqual_3(this.Subscription, that.Subscription) && + deriveEqual_(&this.Totals, &that.Totals) +} + +// deriveEqualUsageBasedLine returns whether this and that are equal. +func deriveEqualUsageBasedLine(this, that *UsageBasedLine) bool { + return (this == nil && that == nil) || + this != nil && that != nil && + this.ConfigID == that.ConfigID && + this.Price.Equal(that.Price) && + this.FeatureKey == that.FeatureKey && + ((this.Quantity == nil && that.Quantity == nil) || (this.Quantity != nil && that.Quantity != nil && (*(this.Quantity)).Equal(*(that.Quantity)))) && + ((this.MeteredQuantity == nil && that.MeteredQuantity == nil) || (this.MeteredQuantity != nil && that.MeteredQuantity != nil && (*(this.MeteredQuantity)).Equal(*(that.MeteredQuantity)))) && + ((this.PreLinePeriodQuantity == nil && that.PreLinePeriodQuantity == nil) || (this.PreLinePeriodQuantity != nil && that.PreLinePeriodQuantity != nil && (*(this.PreLinePeriodQuantity)).Equal(*(that.PreLinePeriodQuantity)))) && + ((this.MeteredPreLinePeriodQuantity == nil && that.MeteredPreLinePeriodQuantity == nil) || (this.MeteredPreLinePeriodQuantity != nil && that.MeteredPreLinePeriodQuantity != nil && (*(this.MeteredPreLinePeriodQuantity)).Equal(*(that.MeteredPreLinePeriodQuantity)))) +} + +// deriveEqualLineDiscountBase returns whether this and that are equal. +func deriveEqualLineDiscountBase(this, that *LineDiscountBase) bool { + return (this == nil && that == nil) || + this != nil && that != nil && + ((this.Description == nil && that.Description == nil) || (this.Description != nil && that.Description != nil && *(this.Description) == *(that.Description))) && + ((this.ChildUniqueReferenceID == nil && that.ChildUniqueReferenceID == nil) || (this.ChildUniqueReferenceID != nil && that.ChildUniqueReferenceID != nil && *(this.ChildUniqueReferenceID) == *(that.ChildUniqueReferenceID))) && + this.ExternalIDs.Equal(that.ExternalIDs) && + deriveEqual_4(&this.Reason, &that.Reason) +} + +// deriveEqualAmountLineDiscount returns whether this and that are equal. +func deriveEqualAmountLineDiscount(this, that *AmountLineDiscount) bool { + return (this == nil && that == nil) || + this != nil && that != nil && + this.LineDiscountBase.Equal(that.LineDiscountBase) && + this.Amount.Equal(that.Amount) && + this.RoundingAmount.Equal(that.RoundingAmount) +} + +// deriveEqualAmountLineDiscountManaged returns whether this and that are equal. +func deriveEqualAmountLineDiscountManaged(this, that *AmountLineDiscountManaged) bool { + return (this == nil && that == nil) || + this != nil && that != nil && + this.ManagedModelWithID.Equal(that.ManagedModelWithID) && + this.AmountLineDiscount.Equal(that.AmountLineDiscount) +} + +// deriveEqualUsageLineDiscount returns whether this and that are equal. +func deriveEqualUsageLineDiscount(this, that *UsageLineDiscount) bool { + return (this == nil && that == nil) || + this != nil && that != nil && + this.LineDiscountBase.Equal(that.LineDiscountBase) && + this.Quantity.Equal(that.Quantity) && + ((this.PreLinePeriodQuantity == nil && that.PreLinePeriodQuantity == nil) || (this.PreLinePeriodQuantity != nil && that.PreLinePeriodQuantity != nil && (*(this.PreLinePeriodQuantity)).Equal(*(that.PreLinePeriodQuantity)))) +} + +// deriveEqualUsageLineDiscountManaged returns whether this and that are equal. +func deriveEqualUsageLineDiscountManaged(this, that *UsageLineDiscountManaged) bool { + return (this == nil && that == nil) || + this != nil && that != nil && + this.ManagedModelWithID.Equal(that.ManagedModelWithID) && + this.UsageLineDiscount.Equal(that.UsageLineDiscount) +} + +// deriveEqual returns whether this and that are equal. +func deriveEqual(this, that *models.ManagedResource) bool { + return (this == nil && that == nil) || + this != nil && that != nil && + this.NamespacedModel == that.NamespacedModel && + this.ManagedModel.Equal(that.ManagedModel) && + this.ID == that.ID && + ((this.Description == nil && that.Description == nil) || (this.Description != nil && that.Description != nil && *(this.Description) == *(that.Description))) && + this.Name == that.Name +} + +// deriveEqual_ returns whether this and that are equal. +func deriveEqual_(this, that *Totals) bool { + return (this == nil && that == nil) || + this != nil && that != nil && + this.Amount.Equal(that.Amount) && + this.ChargesTotal.Equal(that.ChargesTotal) && + this.DiscountsTotal.Equal(that.DiscountsTotal) && + this.TaxesInclusiveTotal.Equal(that.TaxesInclusiveTotal) && + this.TaxesExclusiveTotal.Equal(that.TaxesExclusiveTotal) && + this.TaxesTotal.Equal(that.TaxesTotal) && + this.Total.Equal(that.Total) +} + +// deriveEqual_1 returns whether this and that are equal. +func deriveEqual_1(this, that map[string]string) bool { + if this == nil || that == nil { + return this == nil && that == nil + } + if len(this) != len(that) { + return false + } + for k, v := range this { + thatv, ok := that[k] + if !ok { + return false + } + if !(v == thatv) { + return false + } + } + return true +} + +// deriveEqual_2 returns whether this and that are equal. +func deriveEqual_2(this, that *Discounts) bool { + return (this == nil && that == nil) || + this != nil && that != nil && + ((this.Percentage == nil && that.Percentage == nil) || (this.Percentage != nil && that.Percentage != nil && (*(this.Percentage)).Equal(*(that.Percentage)))) && + ((this.Usage == nil && that.Usage == nil) || (this.Usage != nil && that.Usage != nil && (*(this.Usage)).Equal(*(that.Usage)))) +} + +// deriveEqual_3 returns whether this and that are equal. +func deriveEqual_3(this, that *SubscriptionReference) bool { + return (this == nil && that == nil) || + this != nil && that != nil && + this.SubscriptionID == that.SubscriptionID && + this.PhaseID == that.PhaseID && + this.ItemID == that.ItemID && + deriveEqual_5(&this.BillingPeriod, &that.BillingPeriod) +} + +// deriveEqual_4 returns whether this and that are equal. +func deriveEqual_4(this, that *DiscountReason) bool { + return (this == nil && that == nil) || + this != nil && that != nil && + this.t == that.t && + ((this.percentage == nil && that.percentage == nil) || (this.percentage != nil && that.percentage != nil && (*(this.percentage)).Equal(*(that.percentage)))) && + ((this.usage == nil && that.usage == nil) || (this.usage != nil && that.usage != nil && (*(this.usage)).Equal(*(that.usage)))) +} + +// deriveEqual_5 returns whether this and that are equal. +func deriveEqual_5(this, that *timeutil.ClosedPeriod) bool { + return (this == nil && that == nil) || + this != nil && that != nil && + this.From.Equal(that.From) && + this.To.Equal(that.To) +} diff --git a/openmeter/billing/generate.go b/openmeter/billing/generate.go new file mode 100644 index 000000000..53b2ecf3e --- /dev/null +++ b/openmeter/billing/generate.go @@ -0,0 +1,3 @@ +package billing + +//go:generate go run github.com/awalterschulze/goderive diff --git a/openmeter/billing/invoicedetailedline.go b/openmeter/billing/invoicedetailedline.go index 195b21817..778c3bd54 100644 --- a/openmeter/billing/invoicedetailedline.go +++ b/openmeter/billing/invoicedetailedline.go @@ -3,7 +3,6 @@ package billing import ( "errors" "fmt" - "reflect" "slices" "github.com/alpacahq/alpacadecimal" @@ -115,7 +114,7 @@ func (l DetailedLineBase) Clone() DetailedLineBase { } func (l DetailedLineBase) Equal(other DetailedLineBase) bool { - return reflect.DeepEqual(l, other) + return deriveEqualDetailedLineBase(&l, &other) } type DetailedLine struct { diff --git a/openmeter/billing/invoiceline.go b/openmeter/billing/invoiceline.go index 333580e06..ba0cf60fc 100644 --- a/openmeter/billing/invoiceline.go +++ b/openmeter/billing/invoiceline.go @@ -3,7 +3,6 @@ package billing import ( "errors" "fmt" - "reflect" "slices" "sort" "strings" @@ -17,7 +16,6 @@ import ( "github.com/openmeterio/openmeter/openmeter/productcatalog" "github.com/openmeterio/openmeter/openmeter/streaming" "github.com/openmeterio/openmeter/pkg/currencyx" - "github.com/openmeterio/openmeter/pkg/equal" "github.com/openmeterio/openmeter/pkg/models" "github.com/openmeterio/openmeter/pkg/timeutil" ) @@ -125,7 +123,7 @@ type LineBase struct { } func (i LineBase) Equal(other LineBase) bool { - return reflect.DeepEqual(i, other) + return deriveEqualLineBase(&i, &other) } func (i LineBase) GetParentID() (string, bool) { @@ -647,35 +645,7 @@ type UsageBasedLine struct { } func (i UsageBasedLine) Equal(other *UsageBasedLine) bool { - if other == nil { - return false - } - - if !i.Price.Equal(other.Price) { - return false - } - - if i.FeatureKey != other.FeatureKey { - return false - } - - if !equal.PtrEqual(i.Quantity, other.Quantity) { - return false - } - - if !equal.PtrEqual(i.MeteredQuantity, other.MeteredQuantity) { - return false - } - - if !equal.PtrEqual(i.PreLinePeriodQuantity, other.PreLinePeriodQuantity) { - return false - } - - if !equal.PtrEqual(i.MeteredPreLinePeriodQuantity, other.MeteredPreLinePeriodQuantity) { - return false - } - - return true + return deriveEqualUsageBasedLine(&i, other) } func (i UsageBasedLine) Clone() *UsageBasedLine { diff --git a/openmeter/billing/invoicelinediscount.go b/openmeter/billing/invoicelinediscount.go index aa1e4a1ea..5c8ab2d23 100644 --- a/openmeter/billing/invoicelinediscount.go +++ b/openmeter/billing/invoicelinediscount.go @@ -3,13 +3,11 @@ package billing import ( "errors" "fmt" - "reflect" "github.com/alpacahq/alpacadecimal" "github.com/samber/lo" "github.com/openmeterio/openmeter/pkg/currencyx" - "github.com/openmeterio/openmeter/pkg/equal" "github.com/openmeterio/openmeter/pkg/models" "github.com/openmeterio/openmeter/pkg/slicesx" ) @@ -37,7 +35,7 @@ func (i LineDiscountBase) Validate() error { } func (i LineDiscountBase) Equal(other LineDiscountBase) bool { - return reflect.DeepEqual(i, other) + return deriveEqualLineDiscountBase(&i, &other) } func (i LineDiscountBase) Clone() LineDiscountBase { @@ -82,19 +80,7 @@ func (i AmountLineDiscount) Validate() error { } func (i AmountLineDiscount) Equal(other AmountLineDiscount) bool { - if !i.LineDiscountBase.Equal(other.LineDiscountBase) { - return false - } - - if !i.Amount.Equal(other.Amount) { - return false - } - - if !i.RoundingAmount.Equal(other.RoundingAmount) { - return false - } - - return true + return deriveEqualAmountLineDiscount(&i, &other) } func (i AmountLineDiscount) Clone() AmountLineDiscount { @@ -121,15 +107,7 @@ func (i AmountLineDiscountManaged) Validate() error { } func (i AmountLineDiscountManaged) Equal(other AmountLineDiscountManaged) bool { - if !i.ManagedModelWithID.Equal(other.ManagedModelWithID) { - return false - } - - if !i.AmountLineDiscount.Equal(other.AmountLineDiscount) { - return false - } - - return true + return deriveEqualAmountLineDiscountManaged(&i, &other) } func (i AmountLineDiscountManaged) Clone() AmountLineDiscountManaged { @@ -248,19 +226,7 @@ func (i UsageLineDiscount) Validate() error { } func (i UsageLineDiscount) Equal(other UsageLineDiscount) bool { - if !i.LineDiscountBase.Equal(other.LineDiscountBase) { - return false - } - - if !i.Quantity.Equal(other.Quantity) { - return false - } - - if !equal.PtrEqual(i.PreLinePeriodQuantity, other.PreLinePeriodQuantity) { - return false - } - - return true + return deriveEqualUsageLineDiscount(&i, &other) } func (i UsageLineDiscount) Clone() UsageLineDiscount { @@ -287,15 +253,7 @@ func (i UsageLineDiscountManaged) Validate() error { } func (i UsageLineDiscountManaged) Equal(other UsageLineDiscountManaged) bool { - if !i.ManagedModelWithID.Equal(other.ManagedModelWithID) { - return false - } - - if !i.UsageLineDiscount.Equal(other.UsageLineDiscount) { - return false - } - - return true + return deriveEqualUsageLineDiscountManaged(&i, &other) } func (i UsageLineDiscountManaged) Clone() UsageLineDiscountManaged { diff --git a/pkg/models/annotation.go b/pkg/models/annotation.go index 32855f295..19fa01168 100644 --- a/pkg/models/annotation.go +++ b/pkg/models/annotation.go @@ -1,5 +1,7 @@ package models +import "reflect" + type Annotations map[string]interface{} func (a Annotations) GetBool(key string) bool { @@ -87,3 +89,25 @@ func (a Annotations) Merge(m Annotations) Annotations { return result } + +func (a Annotations) Equal(other Annotations) bool { + if a == nil || other == nil { + return a == nil && other == nil + } + + if len(a) != len(other) { + return false + } + + for k, v := range a { + otherV, ok := other[k] + if !ok { + return false + } + + if !reflect.DeepEqual(v, otherV) { + return false + } + } + return true +}