Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 24 additions & 8 deletions internal/store/postgres/org_invoices_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ func (r OrgInvoicesRepository) prepareDataQuery(orgID string, rql *rql.Query) (s
}

func (r OrgInvoicesRepository) prepareGroupByQuery(orgID string, rql *rql.Query) (string, []any, error) {
query := dialect.From(TABLE_BILLING_INVOICES).Prepared(true).
query := fromLive(TABLE_BILLING_INVOICES).Prepared(true).
Select(
goqu.COUNT("*").As("count"),
goqu.I(TABLE_BILLING_INVOICES+"."+COLUMN_STATE).As("values"),
Expand All @@ -171,9 +171,17 @@ func (r OrgInvoicesRepository) prepareGroupByQuery(orgID string, rql *rql.Query)
goqu.T(TABLE_BILLING_CUSTOMERS),
goqu.On(goqu.I(TABLE_BILLING_INVOICES+".customer_id").Eq(goqu.I(TABLE_BILLING_CUSTOMERS+".id"))),
).
Where(goqu.Ex{
TABLE_BILLING_CUSTOMERS + "." + COLUMN_ORG_ID: orgID,
})
InnerJoin(
goqu.T(TABLE_ORGANIZATIONS),
goqu.On(goqu.I(TABLE_BILLING_CUSTOMERS+"."+COLUMN_ORG_ID).Eq(goqu.I(TABLE_ORGANIZATIONS+"."+COLUMN_ID))),
).
Where(
goqu.Ex{
TABLE_BILLING_CUSTOMERS + "." + COLUMN_ORG_ID: orgID,
},
live(TABLE_BILLING_CUSTOMERS),
live(TABLE_ORGANIZATIONS),
)

// Apply the same filters as the main query
for _, filter := range rql.Filters {
Expand All @@ -192,7 +200,7 @@ func (r OrgInvoicesRepository) prepareGroupByQuery(orgID string, rql *rql.Query)
}

func (r OrgInvoicesRepository) buildBaseQuery(orgID string) *goqu.SelectDataset {
return dialect.From(TABLE_BILLING_INVOICES).Prepared(true).
return fromLive(TABLE_BILLING_INVOICES).Prepared(true).
Select(
goqu.I(TABLE_BILLING_INVOICES+"."+COLUMN_ID).As("invoice_id"),
goqu.I(TABLE_BILLING_INVOICES+"."+COLUMN_AMOUNT).As("invoice_amount"),
Expand All @@ -206,9 +214,17 @@ func (r OrgInvoicesRepository) buildBaseQuery(orgID string) *goqu.SelectDataset
goqu.T(TABLE_BILLING_CUSTOMERS),
goqu.On(goqu.I(TABLE_BILLING_INVOICES+".customer_id").Eq(goqu.I(TABLE_BILLING_CUSTOMERS+".id"))),
).
Where(goqu.Ex{
TABLE_BILLING_CUSTOMERS + "." + COLUMN_ORG_ID: orgID,
})
InnerJoin(
goqu.T(TABLE_ORGANIZATIONS),
goqu.On(goqu.I(TABLE_BILLING_CUSTOMERS+"."+COLUMN_ORG_ID).Eq(goqu.I(TABLE_ORGANIZATIONS+"."+COLUMN_ID))),
).
Where(
goqu.Ex{
TABLE_BILLING_CUSTOMERS + "." + COLUMN_ORG_ID: orgID,
},
live(TABLE_BILLING_CUSTOMERS),
live(TABLE_ORGANIZATIONS),
)
}

func (r OrgInvoicesRepository) addFilter(query *goqu.SelectDataset, filter rql.Filter) *goqu.SelectDataset {
Expand Down
126 changes: 126 additions & 0 deletions internal/store/postgres/org_invoices_repository_pg_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package postgres_test

import (
"context"
"fmt"
"io"
"log/slog"
"testing"

"github.com/ory/dockertest"
"github.com/raystack/frontier/internal/store/postgres"
"github.com/raystack/frontier/pkg/db"
"github.com/raystack/salt/rql"
"github.com/stretchr/testify/suite"
)

// Runs the search against a real postgres to check that soft-deleted invoices,
// billing customers, and organizations stay out of both the list and the counts.
type OrgInvoicesRepositoryPGTestSuite struct {
suite.Suite
ctx context.Context
client *db.Client
pool *dockertest.Pool
resource *dockertest.Resource
repository *postgres.OrgInvoicesRepository
}

func (s *OrgInvoicesRepositoryPGTestSuite) SetupSuite() {
var err error
logger := slog.New(slog.NewTextHandler(io.Discard, nil))
s.client, s.pool, s.resource, err = newTestClient(logger)
if err != nil {
s.T().Fatal(err)
}
s.ctx = context.TODO()
s.repository = postgres.NewOrgInvoicesRepository(s.client)
}

func (s *OrgInvoicesRepositoryPGTestSuite) TearDownSuite() {
if err := purgeDocker(s.pool, s.resource); err != nil {
s.T().Fatal(err)
}
}

func (s *OrgInvoicesRepositoryPGTestSuite) SetupTest() {
s.exec(`INSERT INTO organizations (name, title) VALUES ('oi-live', 'Live Org'), ('oi-gone', 'Gone Org')`)

s.customer("oi-cust-live", "oi-live")
s.customer("oi-cust-gone", "oi-live")
s.customer("oi-cust-other", "oi-gone")

s.invoice("oi-cust-live", "oi-inv-live", "paid")
s.invoice("oi-cust-live", "oi-inv-deleted", "paid")
s.invoice("oi-cust-gone", "oi-inv-orphan", "open")
s.invoice("oi-cust-other", "oi-inv-otherorg", "paid")

s.exec(`UPDATE billing_invoices SET deleted_at = now() WHERE hosted_url = 'oi-inv-deleted'`)
s.exec(`UPDATE billing_customers SET deleted_at = now() WHERE name = 'oi-cust-gone'`)
s.exec(`UPDATE organizations SET deleted_at = now() WHERE name = 'oi-gone'`)
}

func (s *OrgInvoicesRepositoryPGTestSuite) TearDownTest() {
queries := []string{}
for _, table := range []string{postgres.TABLE_BILLING_INVOICES, postgres.TABLE_BILLING_CUSTOMERS,
postgres.TABLE_ORGANIZATIONS} {
queries = append(queries, fmt.Sprintf("TRUNCATE TABLE %s RESTART IDENTITY CASCADE", table))
}
if err := execQueries(s.ctx, s.client, queries); err != nil {
s.T().Fatal(err)
}
}

func (s *OrgInvoicesRepositoryPGTestSuite) exec(query string, args ...any) {
s.T().Helper()
execSQL(s.T(), s.ctx, s.client, query, args...)
}

func (s *OrgInvoicesRepositoryPGTestSuite) orgID(name string) string {
s.T().Helper()
return scalarSQL(s.T(), s.ctx, s.client, `SELECT id FROM organizations WHERE name = $1`, name)
}

func (s *OrgInvoicesRepositoryPGTestSuite) customer(name, orgName string) {
s.T().Helper()
s.exec(`INSERT INTO billing_customers (org_id, provider_id, name, email)
VALUES ($1, $2, $2, $2)`, s.orgID(orgName), name)
}

func (s *OrgInvoicesRepositoryPGTestSuite) invoice(customer, hostedURL, state string) {
s.T().Helper()
s.exec(`INSERT INTO billing_invoices (customer_id, provider_id, amount, currency, hosted_url, state)
VALUES ((SELECT id FROM billing_customers WHERE name = $1), $2, 100, 'usd', $2, $3)`,
customer, hostedURL, state)
}

func (s *OrgInvoicesRepositoryPGTestSuite) links(orgName string) []string {
s.T().Helper()
res, err := s.repository.Search(s.ctx, s.orgID(orgName), &rql.Query{Limit: 50})
s.Require().NoError(err)
out := make([]string, 0, len(res.Invoices))
for _, i := range res.Invoices {
out = append(out, i.InvoiceLink)
}
return out
}

func (s *OrgInvoicesRepositoryPGTestSuite) TestSkipsDeletedInvoicesCustomersAndOrgs() {
s.Equal([]string{"oi-inv-live"}, s.links("oi-live"))
}

func (s *OrgInvoicesRepositoryPGTestSuite) TestSoftDeletedOrgHasNoInvoices() {
s.Empty(s.links("oi-gone"))
}

func (s *OrgInvoicesRepositoryPGTestSuite) TestGroupCountsSkipDeletedRows() {
res, err := s.repository.Search(s.ctx, s.orgID("oi-live"),
&rql.Query{Limit: 50, GroupBy: []string{"state"}})
s.Require().NoError(err)
s.Require().Len(res.Group.Data, 1)
s.Equal("paid", res.Group.Data[0].Name)
s.Equal(1, res.Group.Data[0].Count)
}

func TestOrgInvoicesRepositoryPG(t *testing.T) {
suite.Run(t, new(OrgInvoicesRepositoryPGTestSuite))
}
18 changes: 9 additions & 9 deletions internal/store/postgres/org_invoices_repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestOrgInvoicesRepository_prepareDataQuery(t *testing.T) {
Limit: 10,
Offset: 20,
},
wantSQL: `SELECT "billing_invoices"."id" AS "invoice_id", "billing_invoices"."amount" AS "invoice_amount", "billing_invoices"."currency" AS "invoice_currency", "billing_invoices"."state" AS "invoice_state", "billing_invoices"."hosted_url" AS "invoice_hosted_url", "billing_invoices"."created_at" AS "invoice_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") WHERE ("billing_customers"."org_id" = $1) LIMIT $2 OFFSET $3`,
wantSQL: `SELECT "billing_invoices"."id" AS "invoice_id", "billing_invoices"."amount" AS "invoice_amount", "billing_invoices"."currency" AS "invoice_currency", "billing_invoices"."state" AS "invoice_state", "billing_invoices"."hosted_url" AS "invoice_hosted_url", "billing_invoices"."created_at" AS "invoice_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") INNER JOIN "organizations" ON ("billing_customers"."org_id" = "organizations"."id") WHERE (("billing_invoices"."deleted_at" IS NULL) AND ("billing_customers"."org_id" = $1) AND ("billing_customers"."deleted_at" IS NULL) AND ("organizations"."deleted_at" IS NULL)) LIMIT $2 OFFSET $3`,
wantParams: []any{"org123", int64(10), int64(20)},
wantErr: false,
},
Expand All @@ -41,7 +41,7 @@ func TestOrgInvoicesRepository_prepareDataQuery(t *testing.T) {
Limit: 10,
Offset: 50,
},
wantSQL: `SELECT "billing_invoices"."id" AS "invoice_id", "billing_invoices"."amount" AS "invoice_amount", "billing_invoices"."currency" AS "invoice_currency", "billing_invoices"."state" AS "invoice_state", "billing_invoices"."hosted_url" AS "invoice_hosted_url", "billing_invoices"."created_at" AS "invoice_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") WHERE (("billing_customers"."org_id" = $1) AND ("billing_invoices"."amount" >= $2)) LIMIT $3 OFFSET $4`,
wantSQL: `SELECT "billing_invoices"."id" AS "invoice_id", "billing_invoices"."amount" AS "invoice_amount", "billing_invoices"."currency" AS "invoice_currency", "billing_invoices"."state" AS "invoice_state", "billing_invoices"."hosted_url" AS "invoice_hosted_url", "billing_invoices"."created_at" AS "invoice_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") INNER JOIN "organizations" ON ("billing_customers"."org_id" = "organizations"."id") WHERE (("billing_invoices"."deleted_at" IS NULL) AND ("billing_customers"."org_id" = $1) AND ("billing_customers"."deleted_at" IS NULL) AND ("organizations"."deleted_at" IS NULL) AND ("billing_invoices"."amount" >= $2)) LIMIT $3 OFFSET $4`,
wantParams: []any{"org123", int64(1000), int64(10), int64(50)},
wantErr: false,
},
Expand All @@ -60,7 +60,7 @@ func TestOrgInvoicesRepository_prepareDataQuery(t *testing.T) {
Limit: 10,
Offset: 30,
},
wantSQL: `SELECT "billing_invoices"."id" AS "invoice_id", "billing_invoices"."amount" AS "invoice_amount", "billing_invoices"."currency" AS "invoice_currency", "billing_invoices"."state" AS "invoice_state", "billing_invoices"."hosted_url" AS "invoice_hosted_url", "billing_invoices"."created_at" AS "invoice_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") WHERE (("billing_customers"."org_id" = $1) AND ("billing_invoices"."state" = $2) AND ((CAST("billing_invoices"."state" AS TEXT) ILIKE $3) OR (CAST("billing_invoices"."hosted_url" AS TEXT) ILIKE $4) OR (CAST("billing_invoices"."amount" AS TEXT) ILIKE $5))) LIMIT $6 OFFSET $7`,
wantSQL: `SELECT "billing_invoices"."id" AS "invoice_id", "billing_invoices"."amount" AS "invoice_amount", "billing_invoices"."currency" AS "invoice_currency", "billing_invoices"."state" AS "invoice_state", "billing_invoices"."hosted_url" AS "invoice_hosted_url", "billing_invoices"."created_at" AS "invoice_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") INNER JOIN "organizations" ON ("billing_customers"."org_id" = "organizations"."id") WHERE (("billing_invoices"."deleted_at" IS NULL) AND ("billing_customers"."org_id" = $1) AND ("billing_customers"."deleted_at" IS NULL) AND ("organizations"."deleted_at" IS NULL) AND ("billing_invoices"."state" = $2) AND ((CAST("billing_invoices"."state" AS TEXT) ILIKE $3) OR (CAST("billing_invoices"."hosted_url" AS TEXT) ILIKE $4) OR (CAST("billing_invoices"."amount" AS TEXT) ILIKE $5))) LIMIT $6 OFFSET $7`,
wantParams: []any{"org123", "paid", "%test%", "%test%", "%test%", int64(10), int64(30)},
wantErr: false,
},
Expand All @@ -77,7 +77,7 @@ func TestOrgInvoicesRepository_prepareDataQuery(t *testing.T) {
Limit: 10,
Offset: 40,
},
wantSQL: `SELECT "billing_invoices"."id" AS "invoice_id", "billing_invoices"."amount" AS "invoice_amount", "billing_invoices"."currency" AS "invoice_currency", "billing_invoices"."state" AS "invoice_state", "billing_invoices"."hosted_url" AS "invoice_hosted_url", "billing_invoices"."created_at" AS "invoice_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") WHERE ("billing_customers"."org_id" = $1) ORDER BY "invoice_state" DESC LIMIT $2 OFFSET $3`,
wantSQL: `SELECT "billing_invoices"."id" AS "invoice_id", "billing_invoices"."amount" AS "invoice_amount", "billing_invoices"."currency" AS "invoice_currency", "billing_invoices"."state" AS "invoice_state", "billing_invoices"."hosted_url" AS "invoice_hosted_url", "billing_invoices"."created_at" AS "invoice_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") INNER JOIN "organizations" ON ("billing_customers"."org_id" = "organizations"."id") WHERE (("billing_invoices"."deleted_at" IS NULL) AND ("billing_customers"."org_id" = $1) AND ("billing_customers"."deleted_at" IS NULL) AND ("organizations"."deleted_at" IS NULL)) ORDER BY "invoice_state" DESC LIMIT $2 OFFSET $3`,
wantParams: []any{"org123", int64(10), int64(40)},
wantErr: false,
},
Expand All @@ -95,7 +95,7 @@ func TestOrgInvoicesRepository_prepareDataQuery(t *testing.T) {
Limit: 10,
Offset: 25,
},
wantSQL: `SELECT "billing_invoices"."id" AS "invoice_id", "billing_invoices"."amount" AS "invoice_amount", "billing_invoices"."currency" AS "invoice_currency", "billing_invoices"."state" AS "invoice_state", "billing_invoices"."hosted_url" AS "invoice_hosted_url", "billing_invoices"."created_at" AS "invoice_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") WHERE ("billing_customers"."org_id" = $1) ORDER BY "invoice_state" ASC, "invoice_amount" DESC LIMIT $2 OFFSET $3`,
wantSQL: `SELECT "billing_invoices"."id" AS "invoice_id", "billing_invoices"."amount" AS "invoice_amount", "billing_invoices"."currency" AS "invoice_currency", "billing_invoices"."state" AS "invoice_state", "billing_invoices"."hosted_url" AS "invoice_hosted_url", "billing_invoices"."created_at" AS "invoice_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") INNER JOIN "organizations" ON ("billing_customers"."org_id" = "organizations"."id") WHERE (("billing_invoices"."deleted_at" IS NULL) AND ("billing_customers"."org_id" = $1) AND ("billing_customers"."deleted_at" IS NULL) AND ("organizations"."deleted_at" IS NULL)) ORDER BY "invoice_state" ASC, "invoice_amount" DESC LIMIT $2 OFFSET $3`,
wantParams: []any{"org123", int64(10), int64(25)},
wantErr: false,
},
Expand Down Expand Up @@ -150,7 +150,7 @@ func TestOrgInvoicesRepository_prepareGroupByQuery(t *testing.T) {
rql: &rql.Query{
GroupBy: []string{"state"},
},
wantSQL: `SELECT COUNT(*) AS "count", "billing_invoices"."state" AS "values" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") WHERE ("billing_customers"."org_id" = $1) GROUP BY "billing_invoices"."state"`,
wantSQL: `SELECT COUNT(*) AS "count", "billing_invoices"."state" AS "values" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") INNER JOIN "organizations" ON ("billing_customers"."org_id" = "organizations"."id") WHERE (("billing_invoices"."deleted_at" IS NULL) AND ("billing_customers"."org_id" = $1) AND ("billing_customers"."deleted_at" IS NULL) AND ("organizations"."deleted_at" IS NULL)) GROUP BY "billing_invoices"."state"`,
wantParams: []any{"org123"},
wantErr: false,
},
Expand All @@ -167,7 +167,7 @@ func TestOrgInvoicesRepository_prepareGroupByQuery(t *testing.T) {
},
},
},
wantSQL: `SELECT COUNT(*) AS "count", "billing_invoices"."state" AS "values" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") WHERE (("billing_customers"."org_id" = $1) AND ("billing_invoices"."amount" >= $2)) GROUP BY "billing_invoices"."state"`,
wantSQL: `SELECT COUNT(*) AS "count", "billing_invoices"."state" AS "values" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") INNER JOIN "organizations" ON ("billing_customers"."org_id" = "organizations"."id") WHERE (("billing_invoices"."deleted_at" IS NULL) AND ("billing_customers"."org_id" = $1) AND ("billing_customers"."deleted_at" IS NULL) AND ("organizations"."deleted_at" IS NULL) AND ("billing_invoices"."amount" >= $2)) GROUP BY "billing_invoices"."state"`,
wantParams: []any{"org123", int64(1000)},
wantErr: false,
},
Expand All @@ -178,7 +178,7 @@ func TestOrgInvoicesRepository_prepareGroupByQuery(t *testing.T) {
GroupBy: []string{"state"},
Search: "test",
},
wantSQL: `SELECT COUNT(*) AS "count", "billing_invoices"."state" AS "values" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") WHERE (("billing_customers"."org_id" = $1) AND ((CAST("billing_invoices"."state" AS TEXT) ILIKE $2) OR (CAST("billing_invoices"."hosted_url" AS TEXT) ILIKE $3) OR (CAST("billing_invoices"."amount" AS TEXT) ILIKE $4))) GROUP BY "billing_invoices"."state"`,
wantSQL: `SELECT COUNT(*) AS "count", "billing_invoices"."state" AS "values" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") INNER JOIN "organizations" ON ("billing_customers"."org_id" = "organizations"."id") WHERE (("billing_invoices"."deleted_at" IS NULL) AND ("billing_customers"."org_id" = $1) AND ("billing_customers"."deleted_at" IS NULL) AND ("organizations"."deleted_at" IS NULL) AND ((CAST("billing_invoices"."state" AS TEXT) ILIKE $2) OR (CAST("billing_invoices"."hosted_url" AS TEXT) ILIKE $3) OR (CAST("billing_invoices"."amount" AS TEXT) ILIKE $4))) GROUP BY "billing_invoices"."state"`,
wantParams: []any{"org123", "%test%", "%test%", "%test%"},
wantErr: false,
},
Expand All @@ -196,7 +196,7 @@ func TestOrgInvoicesRepository_prepareGroupByQuery(t *testing.T) {
},
Search: "test",
},
wantSQL: `SELECT COUNT(*) AS "count", "billing_invoices"."state" AS "values" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") WHERE (("billing_customers"."org_id" = $1) AND ("billing_invoices"."amount" >= $2) AND ((CAST("billing_invoices"."state" AS TEXT) ILIKE $3) OR (CAST("billing_invoices"."hosted_url" AS TEXT) ILIKE $4) OR (CAST("billing_invoices"."amount" AS TEXT) ILIKE $5))) GROUP BY "billing_invoices"."state"`,
wantSQL: `SELECT COUNT(*) AS "count", "billing_invoices"."state" AS "values" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") INNER JOIN "organizations" ON ("billing_customers"."org_id" = "organizations"."id") WHERE (("billing_invoices"."deleted_at" IS NULL) AND ("billing_customers"."org_id" = $1) AND ("billing_customers"."deleted_at" IS NULL) AND ("organizations"."deleted_at" IS NULL) AND ("billing_invoices"."amount" >= $2) AND ((CAST("billing_invoices"."state" AS TEXT) ILIKE $3) OR (CAST("billing_invoices"."hosted_url" AS TEXT) ILIKE $4) OR (CAST("billing_invoices"."amount" AS TEXT) ILIKE $5))) GROUP BY "billing_invoices"."state"`,
wantParams: []any{"org123", int64(1000), "%test%", "%test%", "%test%"},
wantErr: false,
},
Expand Down
Loading