tenseleyflow/shithub / 2d00a68

Browse files

Add billing domain schema

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
2d00a681f2f7d14b645cc6862eab05b62ed52552
Parents
8f9f8d6
Tree
b4ea699

22 changed files

StatusFile+-
M internal/actions/sqlc/models.go 250 0
M internal/admin/sqlc/models.go 250 0
M internal/auth/policy/sqlc/models.go 250 0
A internal/billing/queries/billing.sql 291 0
A internal/billing/sqlc/billing.sql.go 865 0
A internal/billing/sqlc/db.go 25 0
C internal/billing/sqlc/models.go 0 0
A internal/billing/sqlc/querier.go 32 0
M internal/checks/sqlc/models.go 250 0
M internal/issues/sqlc/models.go 250 0
M internal/meta/sqlc/models.go 250 0
A internal/migrationsfs/migrations/0061_billing_domain.sql 252 0
M internal/notif/sqlc/models.go 250 0
M internal/orgs/sqlc/models.go 250 0
M internal/pulls/sqlc/models.go 250 0
M internal/ratelimit/sqlc/models.go 250 0
M internal/repos/sqlc/models.go 250 0
M internal/social/sqlc/models.go 250 0
M internal/users/sqlc/models.go 250 0
M internal/webhook/sqlc/models.go 250 0
M internal/worker/sqlc/models.go 250 0
M sqlc.yaml 16 0
internal/actions/sqlc/models.gomodified
@@ -12,6 +12,184 @@ import (
1212
 	"github.com/jackc/pgx/v5/pgtype"
1313
 )
1414
 
15
+type BillingInvoiceStatus string
16
+
17
+const (
18
+	BillingInvoiceStatusDraft         BillingInvoiceStatus = "draft"
19
+	BillingInvoiceStatusOpen          BillingInvoiceStatus = "open"
20
+	BillingInvoiceStatusPaid          BillingInvoiceStatus = "paid"
21
+	BillingInvoiceStatusVoid          BillingInvoiceStatus = "void"
22
+	BillingInvoiceStatusUncollectible BillingInvoiceStatus = "uncollectible"
23
+)
24
+
25
+func (e *BillingInvoiceStatus) Scan(src interface{}) error {
26
+	switch s := src.(type) {
27
+	case []byte:
28
+		*e = BillingInvoiceStatus(s)
29
+	case string:
30
+		*e = BillingInvoiceStatus(s)
31
+	default:
32
+		return fmt.Errorf("unsupported scan type for BillingInvoiceStatus: %T", src)
33
+	}
34
+	return nil
35
+}
36
+
37
+type NullBillingInvoiceStatus struct {
38
+	BillingInvoiceStatus BillingInvoiceStatus
39
+	Valid                bool // Valid is true if BillingInvoiceStatus is not NULL
40
+}
41
+
42
+// Scan implements the Scanner interface.
43
+func (ns *NullBillingInvoiceStatus) Scan(value interface{}) error {
44
+	if value == nil {
45
+		ns.BillingInvoiceStatus, ns.Valid = "", false
46
+		return nil
47
+	}
48
+	ns.Valid = true
49
+	return ns.BillingInvoiceStatus.Scan(value)
50
+}
51
+
52
+// Value implements the driver Valuer interface.
53
+func (ns NullBillingInvoiceStatus) Value() (driver.Value, error) {
54
+	if !ns.Valid {
55
+		return nil, nil
56
+	}
57
+	return string(ns.BillingInvoiceStatus), nil
58
+}
59
+
60
+type BillingLockReason string
61
+
62
+const (
63
+	BillingLockReasonPastDue  BillingLockReason = "past_due"
64
+	BillingLockReasonCanceled BillingLockReason = "canceled"
65
+	BillingLockReasonUnpaid   BillingLockReason = "unpaid"
66
+	BillingLockReasonManual   BillingLockReason = "manual"
67
+)
68
+
69
+func (e *BillingLockReason) Scan(src interface{}) error {
70
+	switch s := src.(type) {
71
+	case []byte:
72
+		*e = BillingLockReason(s)
73
+	case string:
74
+		*e = BillingLockReason(s)
75
+	default:
76
+		return fmt.Errorf("unsupported scan type for BillingLockReason: %T", src)
77
+	}
78
+	return nil
79
+}
80
+
81
+type NullBillingLockReason struct {
82
+	BillingLockReason BillingLockReason
83
+	Valid             bool // Valid is true if BillingLockReason is not NULL
84
+}
85
+
86
+// Scan implements the Scanner interface.
87
+func (ns *NullBillingLockReason) Scan(value interface{}) error {
88
+	if value == nil {
89
+		ns.BillingLockReason, ns.Valid = "", false
90
+		return nil
91
+	}
92
+	ns.Valid = true
93
+	return ns.BillingLockReason.Scan(value)
94
+}
95
+
96
+// Value implements the driver Valuer interface.
97
+func (ns NullBillingLockReason) Value() (driver.Value, error) {
98
+	if !ns.Valid {
99
+		return nil, nil
100
+	}
101
+	return string(ns.BillingLockReason), nil
102
+}
103
+
104
+type BillingProvider string
105
+
106
+const (
107
+	BillingProviderStripe BillingProvider = "stripe"
108
+)
109
+
110
+func (e *BillingProvider) Scan(src interface{}) error {
111
+	switch s := src.(type) {
112
+	case []byte:
113
+		*e = BillingProvider(s)
114
+	case string:
115
+		*e = BillingProvider(s)
116
+	default:
117
+		return fmt.Errorf("unsupported scan type for BillingProvider: %T", src)
118
+	}
119
+	return nil
120
+}
121
+
122
+type NullBillingProvider struct {
123
+	BillingProvider BillingProvider
124
+	Valid           bool // Valid is true if BillingProvider is not NULL
125
+}
126
+
127
+// Scan implements the Scanner interface.
128
+func (ns *NullBillingProvider) Scan(value interface{}) error {
129
+	if value == nil {
130
+		ns.BillingProvider, ns.Valid = "", false
131
+		return nil
132
+	}
133
+	ns.Valid = true
134
+	return ns.BillingProvider.Scan(value)
135
+}
136
+
137
+// Value implements the driver Valuer interface.
138
+func (ns NullBillingProvider) Value() (driver.Value, error) {
139
+	if !ns.Valid {
140
+		return nil, nil
141
+	}
142
+	return string(ns.BillingProvider), nil
143
+}
144
+
145
+type BillingSubscriptionStatus string
146
+
147
+const (
148
+	BillingSubscriptionStatusNone       BillingSubscriptionStatus = "none"
149
+	BillingSubscriptionStatusIncomplete BillingSubscriptionStatus = "incomplete"
150
+	BillingSubscriptionStatusTrialing   BillingSubscriptionStatus = "trialing"
151
+	BillingSubscriptionStatusActive     BillingSubscriptionStatus = "active"
152
+	BillingSubscriptionStatusPastDue    BillingSubscriptionStatus = "past_due"
153
+	BillingSubscriptionStatusCanceled   BillingSubscriptionStatus = "canceled"
154
+	BillingSubscriptionStatusUnpaid     BillingSubscriptionStatus = "unpaid"
155
+	BillingSubscriptionStatusPaused     BillingSubscriptionStatus = "paused"
156
+)
157
+
158
+func (e *BillingSubscriptionStatus) Scan(src interface{}) error {
159
+	switch s := src.(type) {
160
+	case []byte:
161
+		*e = BillingSubscriptionStatus(s)
162
+	case string:
163
+		*e = BillingSubscriptionStatus(s)
164
+	default:
165
+		return fmt.Errorf("unsupported scan type for BillingSubscriptionStatus: %T", src)
166
+	}
167
+	return nil
168
+}
169
+
170
+type NullBillingSubscriptionStatus struct {
171
+	BillingSubscriptionStatus BillingSubscriptionStatus
172
+	Valid                     bool // Valid is true if BillingSubscriptionStatus is not NULL
173
+}
174
+
175
+// Scan implements the Scanner interface.
176
+func (ns *NullBillingSubscriptionStatus) Scan(value interface{}) error {
177
+	if value == nil {
178
+		ns.BillingSubscriptionStatus, ns.Valid = "", false
179
+		return nil
180
+	}
181
+	ns.Valid = true
182
+	return ns.BillingSubscriptionStatus.Scan(value)
183
+}
184
+
185
+// Value implements the driver Valuer interface.
186
+func (ns NullBillingSubscriptionStatus) Value() (driver.Value, error) {
187
+	if !ns.Valid {
188
+		return nil, nil
189
+	}
190
+	return string(ns.BillingSubscriptionStatus), nil
191
+}
192
+
15193
 type CheckConclusion string
16194
 
17195
 const (
@@ -1601,6 +1779,54 @@ type AuthThrottle struct {
16011779
 	WindowStartedAt pgtype.Timestamptz
16021780
 }
16031781
 
1782
+type BillingInvoice struct {
1783
+	ID                   int64
1784
+	OrgID                int64
1785
+	Provider             BillingProvider
1786
+	StripeInvoiceID      string
1787
+	StripeCustomerID     string
1788
+	StripeSubscriptionID pgtype.Text
1789
+	Status               BillingInvoiceStatus
1790
+	Number               string
1791
+	Currency             string
1792
+	AmountDueCents       int64
1793
+	AmountPaidCents      int64
1794
+	AmountRemainingCents int64
1795
+	HostedInvoiceUrl     string
1796
+	InvoicePdfUrl        string
1797
+	PeriodStart          pgtype.Timestamptz
1798
+	PeriodEnd            pgtype.Timestamptz
1799
+	DueAt                pgtype.Timestamptz
1800
+	PaidAt               pgtype.Timestamptz
1801
+	VoidedAt             pgtype.Timestamptz
1802
+	CreatedAt            pgtype.Timestamptz
1803
+	UpdatedAt            pgtype.Timestamptz
1804
+}
1805
+
1806
+type BillingSeatSnapshot struct {
1807
+	ID                   int64
1808
+	OrgID                int64
1809
+	Provider             BillingProvider
1810
+	StripeSubscriptionID pgtype.Text
1811
+	ActiveMembers        int32
1812
+	BillableSeats        int32
1813
+	Source               string
1814
+	CapturedAt           pgtype.Timestamptz
1815
+}
1816
+
1817
+type BillingWebhookEvent struct {
1818
+	ID                 int64
1819
+	Provider           BillingProvider
1820
+	ProviderEventID    string
1821
+	EventType          string
1822
+	ApiVersion         string
1823
+	Payload            []byte
1824
+	ReceivedAt         pgtype.Timestamptz
1825
+	ProcessedAt        pgtype.Timestamptz
1826
+	ProcessError       string
1827
+	ProcessingAttempts int32
1828
+}
1829
+
16041830
 type BranchProtectionRule struct {
16051831
 	ID                             int64
16061832
 	RepoID                         int64
@@ -1870,6 +2096,30 @@ type Org struct {
18702096
 	UpdatedAt             pgtype.Timestamptz
18712097
 }
18722098
 
2099
+type OrgBillingState struct {
2100
+	OrgID                    int64
2101
+	Provider                 BillingProvider
2102
+	StripeCustomerID         pgtype.Text
2103
+	StripeSubscriptionID     pgtype.Text
2104
+	StripeSubscriptionItemID pgtype.Text
2105
+	Plan                     OrgPlan
2106
+	SubscriptionStatus       BillingSubscriptionStatus
2107
+	BillableSeats            int32
2108
+	SeatSnapshotAt           pgtype.Timestamptz
2109
+	CurrentPeriodStart       pgtype.Timestamptz
2110
+	CurrentPeriodEnd         pgtype.Timestamptz
2111
+	CancelAtPeriodEnd        bool
2112
+	TrialEnd                 pgtype.Timestamptz
2113
+	PastDueAt                pgtype.Timestamptz
2114
+	CanceledAt               pgtype.Timestamptz
2115
+	LockedAt                 pgtype.Timestamptz
2116
+	LockReason               NullBillingLockReason
2117
+	GraceUntil               pgtype.Timestamptz
2118
+	LastWebhookEventID       string
2119
+	CreatedAt                pgtype.Timestamptz
2120
+	UpdatedAt                pgtype.Timestamptz
2121
+}
2122
+
18732123
 type OrgGithubImport struct {
18742124
 	ID                int64
18752125
 	OrgID             int64
internal/admin/sqlc/models.gomodified
@@ -12,6 +12,184 @@ import (
1212
 	"github.com/jackc/pgx/v5/pgtype"
1313
 )
1414
 
15
+type BillingInvoiceStatus string
16
+
17
+const (
18
+	BillingInvoiceStatusDraft         BillingInvoiceStatus = "draft"
19
+	BillingInvoiceStatusOpen          BillingInvoiceStatus = "open"
20
+	BillingInvoiceStatusPaid          BillingInvoiceStatus = "paid"
21
+	BillingInvoiceStatusVoid          BillingInvoiceStatus = "void"
22
+	BillingInvoiceStatusUncollectible BillingInvoiceStatus = "uncollectible"
23
+)
24
+
25
+func (e *BillingInvoiceStatus) Scan(src interface{}) error {
26
+	switch s := src.(type) {
27
+	case []byte:
28
+		*e = BillingInvoiceStatus(s)
29
+	case string:
30
+		*e = BillingInvoiceStatus(s)
31
+	default:
32
+		return fmt.Errorf("unsupported scan type for BillingInvoiceStatus: %T", src)
33
+	}
34
+	return nil
35
+}
36
+
37
+type NullBillingInvoiceStatus struct {
38
+	BillingInvoiceStatus BillingInvoiceStatus
39
+	Valid                bool // Valid is true if BillingInvoiceStatus is not NULL
40
+}
41
+
42
+// Scan implements the Scanner interface.
43
+func (ns *NullBillingInvoiceStatus) Scan(value interface{}) error {
44
+	if value == nil {
45
+		ns.BillingInvoiceStatus, ns.Valid = "", false
46
+		return nil
47
+	}
48
+	ns.Valid = true
49
+	return ns.BillingInvoiceStatus.Scan(value)
50
+}
51
+
52
+// Value implements the driver Valuer interface.
53
+func (ns NullBillingInvoiceStatus) Value() (driver.Value, error) {
54
+	if !ns.Valid {
55
+		return nil, nil
56
+	}
57
+	return string(ns.BillingInvoiceStatus), nil
58
+}
59
+
60
+type BillingLockReason string
61
+
62
+const (
63
+	BillingLockReasonPastDue  BillingLockReason = "past_due"
64
+	BillingLockReasonCanceled BillingLockReason = "canceled"
65
+	BillingLockReasonUnpaid   BillingLockReason = "unpaid"
66
+	BillingLockReasonManual   BillingLockReason = "manual"
67
+)
68
+
69
+func (e *BillingLockReason) Scan(src interface{}) error {
70
+	switch s := src.(type) {
71
+	case []byte:
72
+		*e = BillingLockReason(s)
73
+	case string:
74
+		*e = BillingLockReason(s)
75
+	default:
76
+		return fmt.Errorf("unsupported scan type for BillingLockReason: %T", src)
77
+	}
78
+	return nil
79
+}
80
+
81
+type NullBillingLockReason struct {
82
+	BillingLockReason BillingLockReason
83
+	Valid             bool // Valid is true if BillingLockReason is not NULL
84
+}
85
+
86
+// Scan implements the Scanner interface.
87
+func (ns *NullBillingLockReason) Scan(value interface{}) error {
88
+	if value == nil {
89
+		ns.BillingLockReason, ns.Valid = "", false
90
+		return nil
91
+	}
92
+	ns.Valid = true
93
+	return ns.BillingLockReason.Scan(value)
94
+}
95
+
96
+// Value implements the driver Valuer interface.
97
+func (ns NullBillingLockReason) Value() (driver.Value, error) {
98
+	if !ns.Valid {
99
+		return nil, nil
100
+	}
101
+	return string(ns.BillingLockReason), nil
102
+}
103
+
104
+type BillingProvider string
105
+
106
+const (
107
+	BillingProviderStripe BillingProvider = "stripe"
108
+)
109
+
110
+func (e *BillingProvider) Scan(src interface{}) error {
111
+	switch s := src.(type) {
112
+	case []byte:
113
+		*e = BillingProvider(s)
114
+	case string:
115
+		*e = BillingProvider(s)
116
+	default:
117
+		return fmt.Errorf("unsupported scan type for BillingProvider: %T", src)
118
+	}
119
+	return nil
120
+}
121
+
122
+type NullBillingProvider struct {
123
+	BillingProvider BillingProvider
124
+	Valid           bool // Valid is true if BillingProvider is not NULL
125
+}
126
+
127
+// Scan implements the Scanner interface.
128
+func (ns *NullBillingProvider) Scan(value interface{}) error {
129
+	if value == nil {
130
+		ns.BillingProvider, ns.Valid = "", false
131
+		return nil
132
+	}
133
+	ns.Valid = true
134
+	return ns.BillingProvider.Scan(value)
135
+}
136
+
137
+// Value implements the driver Valuer interface.
138
+func (ns NullBillingProvider) Value() (driver.Value, error) {
139
+	if !ns.Valid {
140
+		return nil, nil
141
+	}
142
+	return string(ns.BillingProvider), nil
143
+}
144
+
145
+type BillingSubscriptionStatus string
146
+
147
+const (
148
+	BillingSubscriptionStatusNone       BillingSubscriptionStatus = "none"
149
+	BillingSubscriptionStatusIncomplete BillingSubscriptionStatus = "incomplete"
150
+	BillingSubscriptionStatusTrialing   BillingSubscriptionStatus = "trialing"
151
+	BillingSubscriptionStatusActive     BillingSubscriptionStatus = "active"
152
+	BillingSubscriptionStatusPastDue    BillingSubscriptionStatus = "past_due"
153
+	BillingSubscriptionStatusCanceled   BillingSubscriptionStatus = "canceled"
154
+	BillingSubscriptionStatusUnpaid     BillingSubscriptionStatus = "unpaid"
155
+	BillingSubscriptionStatusPaused     BillingSubscriptionStatus = "paused"
156
+)
157
+
158
+func (e *BillingSubscriptionStatus) Scan(src interface{}) error {
159
+	switch s := src.(type) {
160
+	case []byte:
161
+		*e = BillingSubscriptionStatus(s)
162
+	case string:
163
+		*e = BillingSubscriptionStatus(s)
164
+	default:
165
+		return fmt.Errorf("unsupported scan type for BillingSubscriptionStatus: %T", src)
166
+	}
167
+	return nil
168
+}
169
+
170
+type NullBillingSubscriptionStatus struct {
171
+	BillingSubscriptionStatus BillingSubscriptionStatus
172
+	Valid                     bool // Valid is true if BillingSubscriptionStatus is not NULL
173
+}
174
+
175
+// Scan implements the Scanner interface.
176
+func (ns *NullBillingSubscriptionStatus) Scan(value interface{}) error {
177
+	if value == nil {
178
+		ns.BillingSubscriptionStatus, ns.Valid = "", false
179
+		return nil
180
+	}
181
+	ns.Valid = true
182
+	return ns.BillingSubscriptionStatus.Scan(value)
183
+}
184
+
185
+// Value implements the driver Valuer interface.
186
+func (ns NullBillingSubscriptionStatus) Value() (driver.Value, error) {
187
+	if !ns.Valid {
188
+		return nil, nil
189
+	}
190
+	return string(ns.BillingSubscriptionStatus), nil
191
+}
192
+
15193
 type CheckConclusion string
16194
 
17195
 const (
@@ -1601,6 +1779,54 @@ type AuthThrottle struct {
16011779
 	WindowStartedAt pgtype.Timestamptz
16021780
 }
16031781
 
1782
+type BillingInvoice struct {
1783
+	ID                   int64
1784
+	OrgID                int64
1785
+	Provider             BillingProvider
1786
+	StripeInvoiceID      string
1787
+	StripeCustomerID     string
1788
+	StripeSubscriptionID pgtype.Text
1789
+	Status               BillingInvoiceStatus
1790
+	Number               string
1791
+	Currency             string
1792
+	AmountDueCents       int64
1793
+	AmountPaidCents      int64
1794
+	AmountRemainingCents int64
1795
+	HostedInvoiceUrl     string
1796
+	InvoicePdfUrl        string
1797
+	PeriodStart          pgtype.Timestamptz
1798
+	PeriodEnd            pgtype.Timestamptz
1799
+	DueAt                pgtype.Timestamptz
1800
+	PaidAt               pgtype.Timestamptz
1801
+	VoidedAt             pgtype.Timestamptz
1802
+	CreatedAt            pgtype.Timestamptz
1803
+	UpdatedAt            pgtype.Timestamptz
1804
+}
1805
+
1806
+type BillingSeatSnapshot struct {
1807
+	ID                   int64
1808
+	OrgID                int64
1809
+	Provider             BillingProvider
1810
+	StripeSubscriptionID pgtype.Text
1811
+	ActiveMembers        int32
1812
+	BillableSeats        int32
1813
+	Source               string
1814
+	CapturedAt           pgtype.Timestamptz
1815
+}
1816
+
1817
+type BillingWebhookEvent struct {
1818
+	ID                 int64
1819
+	Provider           BillingProvider
1820
+	ProviderEventID    string
1821
+	EventType          string
1822
+	ApiVersion         string
1823
+	Payload            []byte
1824
+	ReceivedAt         pgtype.Timestamptz
1825
+	ProcessedAt        pgtype.Timestamptz
1826
+	ProcessError       string
1827
+	ProcessingAttempts int32
1828
+}
1829
+
16041830
 type BranchProtectionRule struct {
16051831
 	ID                             int64
16061832
 	RepoID                         int64
@@ -1870,6 +2096,30 @@ type Org struct {
18702096
 	UpdatedAt             pgtype.Timestamptz
18712097
 }
18722098
 
2099
+type OrgBillingState struct {
2100
+	OrgID                    int64
2101
+	Provider                 BillingProvider
2102
+	StripeCustomerID         pgtype.Text
2103
+	StripeSubscriptionID     pgtype.Text
2104
+	StripeSubscriptionItemID pgtype.Text
2105
+	Plan                     OrgPlan
2106
+	SubscriptionStatus       BillingSubscriptionStatus
2107
+	BillableSeats            int32
2108
+	SeatSnapshotAt           pgtype.Timestamptz
2109
+	CurrentPeriodStart       pgtype.Timestamptz
2110
+	CurrentPeriodEnd         pgtype.Timestamptz
2111
+	CancelAtPeriodEnd        bool
2112
+	TrialEnd                 pgtype.Timestamptz
2113
+	PastDueAt                pgtype.Timestamptz
2114
+	CanceledAt               pgtype.Timestamptz
2115
+	LockedAt                 pgtype.Timestamptz
2116
+	LockReason               NullBillingLockReason
2117
+	GraceUntil               pgtype.Timestamptz
2118
+	LastWebhookEventID       string
2119
+	CreatedAt                pgtype.Timestamptz
2120
+	UpdatedAt                pgtype.Timestamptz
2121
+}
2122
+
18732123
 type OrgGithubImport struct {
18742124
 	ID                int64
18752125
 	OrgID             int64
internal/auth/policy/sqlc/models.gomodified
@@ -12,6 +12,184 @@ import (
1212
 	"github.com/jackc/pgx/v5/pgtype"
1313
 )
1414
 
15
+type BillingInvoiceStatus string
16
+
17
+const (
18
+	BillingInvoiceStatusDraft         BillingInvoiceStatus = "draft"
19
+	BillingInvoiceStatusOpen          BillingInvoiceStatus = "open"
20
+	BillingInvoiceStatusPaid          BillingInvoiceStatus = "paid"
21
+	BillingInvoiceStatusVoid          BillingInvoiceStatus = "void"
22
+	BillingInvoiceStatusUncollectible BillingInvoiceStatus = "uncollectible"
23
+)
24
+
25
+func (e *BillingInvoiceStatus) Scan(src interface{}) error {
26
+	switch s := src.(type) {
27
+	case []byte:
28
+		*e = BillingInvoiceStatus(s)
29
+	case string:
30
+		*e = BillingInvoiceStatus(s)
31
+	default:
32
+		return fmt.Errorf("unsupported scan type for BillingInvoiceStatus: %T", src)
33
+	}
34
+	return nil
35
+}
36
+
37
+type NullBillingInvoiceStatus struct {
38
+	BillingInvoiceStatus BillingInvoiceStatus
39
+	Valid                bool // Valid is true if BillingInvoiceStatus is not NULL
40
+}
41
+
42
+// Scan implements the Scanner interface.
43
+func (ns *NullBillingInvoiceStatus) Scan(value interface{}) error {
44
+	if value == nil {
45
+		ns.BillingInvoiceStatus, ns.Valid = "", false
46
+		return nil
47
+	}
48
+	ns.Valid = true
49
+	return ns.BillingInvoiceStatus.Scan(value)
50
+}
51
+
52
+// Value implements the driver Valuer interface.
53
+func (ns NullBillingInvoiceStatus) Value() (driver.Value, error) {
54
+	if !ns.Valid {
55
+		return nil, nil
56
+	}
57
+	return string(ns.BillingInvoiceStatus), nil
58
+}
59
+
60
+type BillingLockReason string
61
+
62
+const (
63
+	BillingLockReasonPastDue  BillingLockReason = "past_due"
64
+	BillingLockReasonCanceled BillingLockReason = "canceled"
65
+	BillingLockReasonUnpaid   BillingLockReason = "unpaid"
66
+	BillingLockReasonManual   BillingLockReason = "manual"
67
+)
68
+
69
+func (e *BillingLockReason) Scan(src interface{}) error {
70
+	switch s := src.(type) {
71
+	case []byte:
72
+		*e = BillingLockReason(s)
73
+	case string:
74
+		*e = BillingLockReason(s)
75
+	default:
76
+		return fmt.Errorf("unsupported scan type for BillingLockReason: %T", src)
77
+	}
78
+	return nil
79
+}
80
+
81
+type NullBillingLockReason struct {
82
+	BillingLockReason BillingLockReason
83
+	Valid             bool // Valid is true if BillingLockReason is not NULL
84
+}
85
+
86
+// Scan implements the Scanner interface.
87
+func (ns *NullBillingLockReason) Scan(value interface{}) error {
88
+	if value == nil {
89
+		ns.BillingLockReason, ns.Valid = "", false
90
+		return nil
91
+	}
92
+	ns.Valid = true
93
+	return ns.BillingLockReason.Scan(value)
94
+}
95
+
96
+// Value implements the driver Valuer interface.
97
+func (ns NullBillingLockReason) Value() (driver.Value, error) {
98
+	if !ns.Valid {
99
+		return nil, nil
100
+	}
101
+	return string(ns.BillingLockReason), nil
102
+}
103
+
104
+type BillingProvider string
105
+
106
+const (
107
+	BillingProviderStripe BillingProvider = "stripe"
108
+)
109
+
110
+func (e *BillingProvider) Scan(src interface{}) error {
111
+	switch s := src.(type) {
112
+	case []byte:
113
+		*e = BillingProvider(s)
114
+	case string:
115
+		*e = BillingProvider(s)
116
+	default:
117
+		return fmt.Errorf("unsupported scan type for BillingProvider: %T", src)
118
+	}
119
+	return nil
120
+}
121
+
122
+type NullBillingProvider struct {
123
+	BillingProvider BillingProvider
124
+	Valid           bool // Valid is true if BillingProvider is not NULL
125
+}
126
+
127
+// Scan implements the Scanner interface.
128
+func (ns *NullBillingProvider) Scan(value interface{}) error {
129
+	if value == nil {
130
+		ns.BillingProvider, ns.Valid = "", false
131
+		return nil
132
+	}
133
+	ns.Valid = true
134
+	return ns.BillingProvider.Scan(value)
135
+}
136
+
137
+// Value implements the driver Valuer interface.
138
+func (ns NullBillingProvider) Value() (driver.Value, error) {
139
+	if !ns.Valid {
140
+		return nil, nil
141
+	}
142
+	return string(ns.BillingProvider), nil
143
+}
144
+
145
+type BillingSubscriptionStatus string
146
+
147
+const (
148
+	BillingSubscriptionStatusNone       BillingSubscriptionStatus = "none"
149
+	BillingSubscriptionStatusIncomplete BillingSubscriptionStatus = "incomplete"
150
+	BillingSubscriptionStatusTrialing   BillingSubscriptionStatus = "trialing"
151
+	BillingSubscriptionStatusActive     BillingSubscriptionStatus = "active"
152
+	BillingSubscriptionStatusPastDue    BillingSubscriptionStatus = "past_due"
153
+	BillingSubscriptionStatusCanceled   BillingSubscriptionStatus = "canceled"
154
+	BillingSubscriptionStatusUnpaid     BillingSubscriptionStatus = "unpaid"
155
+	BillingSubscriptionStatusPaused     BillingSubscriptionStatus = "paused"
156
+)
157
+
158
+func (e *BillingSubscriptionStatus) Scan(src interface{}) error {
159
+	switch s := src.(type) {
160
+	case []byte:
161
+		*e = BillingSubscriptionStatus(s)
162
+	case string:
163
+		*e = BillingSubscriptionStatus(s)
164
+	default:
165
+		return fmt.Errorf("unsupported scan type for BillingSubscriptionStatus: %T", src)
166
+	}
167
+	return nil
168
+}
169
+
170
+type NullBillingSubscriptionStatus struct {
171
+	BillingSubscriptionStatus BillingSubscriptionStatus
172
+	Valid                     bool // Valid is true if BillingSubscriptionStatus is not NULL
173
+}
174
+
175
+// Scan implements the Scanner interface.
176
+func (ns *NullBillingSubscriptionStatus) Scan(value interface{}) error {
177
+	if value == nil {
178
+		ns.BillingSubscriptionStatus, ns.Valid = "", false
179
+		return nil
180
+	}
181
+	ns.Valid = true
182
+	return ns.BillingSubscriptionStatus.Scan(value)
183
+}
184
+
185
+// Value implements the driver Valuer interface.
186
+func (ns NullBillingSubscriptionStatus) Value() (driver.Value, error) {
187
+	if !ns.Valid {
188
+		return nil, nil
189
+	}
190
+	return string(ns.BillingSubscriptionStatus), nil
191
+}
192
+
15193
 type CheckConclusion string
16194
 
17195
 const (
@@ -1601,6 +1779,54 @@ type AuthThrottle struct {
16011779
 	WindowStartedAt pgtype.Timestamptz
16021780
 }
16031781
 
1782
+type BillingInvoice struct {
1783
+	ID                   int64
1784
+	OrgID                int64
1785
+	Provider             BillingProvider
1786
+	StripeInvoiceID      string
1787
+	StripeCustomerID     string
1788
+	StripeSubscriptionID pgtype.Text
1789
+	Status               BillingInvoiceStatus
1790
+	Number               string
1791
+	Currency             string
1792
+	AmountDueCents       int64
1793
+	AmountPaidCents      int64
1794
+	AmountRemainingCents int64
1795
+	HostedInvoiceUrl     string
1796
+	InvoicePdfUrl        string
1797
+	PeriodStart          pgtype.Timestamptz
1798
+	PeriodEnd            pgtype.Timestamptz
1799
+	DueAt                pgtype.Timestamptz
1800
+	PaidAt               pgtype.Timestamptz
1801
+	VoidedAt             pgtype.Timestamptz
1802
+	CreatedAt            pgtype.Timestamptz
1803
+	UpdatedAt            pgtype.Timestamptz
1804
+}
1805
+
1806
+type BillingSeatSnapshot struct {
1807
+	ID                   int64
1808
+	OrgID                int64
1809
+	Provider             BillingProvider
1810
+	StripeSubscriptionID pgtype.Text
1811
+	ActiveMembers        int32
1812
+	BillableSeats        int32
1813
+	Source               string
1814
+	CapturedAt           pgtype.Timestamptz
1815
+}
1816
+
1817
+type BillingWebhookEvent struct {
1818
+	ID                 int64
1819
+	Provider           BillingProvider
1820
+	ProviderEventID    string
1821
+	EventType          string
1822
+	ApiVersion         string
1823
+	Payload            []byte
1824
+	ReceivedAt         pgtype.Timestamptz
1825
+	ProcessedAt        pgtype.Timestamptz
1826
+	ProcessError       string
1827
+	ProcessingAttempts int32
1828
+}
1829
+
16041830
 type BranchProtectionRule struct {
16051831
 	ID                             int64
16061832
 	RepoID                         int64
@@ -1870,6 +2096,30 @@ type Org struct {
18702096
 	UpdatedAt             pgtype.Timestamptz
18712097
 }
18722098
 
2099
+type OrgBillingState struct {
2100
+	OrgID                    int64
2101
+	Provider                 BillingProvider
2102
+	StripeCustomerID         pgtype.Text
2103
+	StripeSubscriptionID     pgtype.Text
2104
+	StripeSubscriptionItemID pgtype.Text
2105
+	Plan                     OrgPlan
2106
+	SubscriptionStatus       BillingSubscriptionStatus
2107
+	BillableSeats            int32
2108
+	SeatSnapshotAt           pgtype.Timestamptz
2109
+	CurrentPeriodStart       pgtype.Timestamptz
2110
+	CurrentPeriodEnd         pgtype.Timestamptz
2111
+	CancelAtPeriodEnd        bool
2112
+	TrialEnd                 pgtype.Timestamptz
2113
+	PastDueAt                pgtype.Timestamptz
2114
+	CanceledAt               pgtype.Timestamptz
2115
+	LockedAt                 pgtype.Timestamptz
2116
+	LockReason               NullBillingLockReason
2117
+	GraceUntil               pgtype.Timestamptz
2118
+	LastWebhookEventID       string
2119
+	CreatedAt                pgtype.Timestamptz
2120
+	UpdatedAt                pgtype.Timestamptz
2121
+}
2122
+
18732123
 type OrgGithubImport struct {
18742124
 	ID                int64
18752125
 	OrgID             int64
internal/billing/queries/billing.sqladded
@@ -0,0 +1,291 @@
1
+-- SPDX-License-Identifier: AGPL-3.0-or-later
2
+
3
+-- ─── org_billing_states ────────────────────────────────────────────
4
+
5
+-- name: GetOrgBillingState :one
6
+SELECT * FROM org_billing_states WHERE org_id = $1;
7
+
8
+-- name: SetStripeCustomer :one
9
+INSERT INTO org_billing_states (org_id, provider, stripe_customer_id)
10
+VALUES ($1, 'stripe', $2)
11
+ON CONFLICT (org_id) DO UPDATE
12
+   SET stripe_customer_id = EXCLUDED.stripe_customer_id,
13
+       provider = 'stripe',
14
+       updated_at = now()
15
+RETURNING *;
16
+
17
+-- name: ApplySubscriptionSnapshot :one
18
+WITH state AS (
19
+    INSERT INTO org_billing_states (
20
+        org_id,
21
+        provider,
22
+        plan,
23
+        subscription_status,
24
+        stripe_subscription_id,
25
+        stripe_subscription_item_id,
26
+        current_period_start,
27
+        current_period_end,
28
+        cancel_at_period_end,
29
+        trial_end,
30
+        canceled_at,
31
+        last_webhook_event_id,
32
+        past_due_at,
33
+        locked_at,
34
+        lock_reason,
35
+        grace_until
36
+    )
37
+    VALUES (
38
+        sqlc.arg(org_id)::bigint,
39
+        'stripe',
40
+        sqlc.arg(plan)::org_plan,
41
+        sqlc.arg(subscription_status)::billing_subscription_status,
42
+        sqlc.narg(stripe_subscription_id)::text,
43
+        sqlc.narg(stripe_subscription_item_id)::text,
44
+        sqlc.narg(current_period_start)::timestamptz,
45
+        sqlc.narg(current_period_end)::timestamptz,
46
+        sqlc.arg(cancel_at_period_end)::boolean,
47
+        sqlc.narg(trial_end)::timestamptz,
48
+        sqlc.narg(canceled_at)::timestamptz,
49
+        sqlc.arg(last_webhook_event_id)::text,
50
+        CASE
51
+            WHEN sqlc.arg(subscription_status)::billing_subscription_status = 'past_due' THEN now()
52
+            ELSE NULL
53
+        END,
54
+        NULL,
55
+        NULL,
56
+        NULL
57
+    )
58
+    ON CONFLICT (org_id) DO UPDATE
59
+       SET plan = EXCLUDED.plan,
60
+           subscription_status = EXCLUDED.subscription_status,
61
+           stripe_subscription_id = EXCLUDED.stripe_subscription_id,
62
+           stripe_subscription_item_id = EXCLUDED.stripe_subscription_item_id,
63
+           current_period_start = EXCLUDED.current_period_start,
64
+           current_period_end = EXCLUDED.current_period_end,
65
+           cancel_at_period_end = EXCLUDED.cancel_at_period_end,
66
+           trial_end = EXCLUDED.trial_end,
67
+           canceled_at = EXCLUDED.canceled_at,
68
+           last_webhook_event_id = EXCLUDED.last_webhook_event_id,
69
+           past_due_at = CASE
70
+               WHEN EXCLUDED.subscription_status = 'past_due' THEN COALESCE(org_billing_states.past_due_at, now())
71
+               ELSE NULL
72
+           END,
73
+           locked_at = NULL,
74
+           lock_reason = NULL,
75
+           grace_until = NULL,
76
+           updated_at = now()
77
+    RETURNING *
78
+), org_update AS (
79
+    UPDATE orgs
80
+       SET plan = sqlc.arg(plan)::org_plan,
81
+           updated_at = now()
82
+     WHERE id = sqlc.arg(org_id)::bigint
83
+    RETURNING id
84
+)
85
+SELECT * FROM state;
86
+
87
+-- name: MarkPastDue :one
88
+UPDATE org_billing_states
89
+   SET subscription_status = 'past_due',
90
+       past_due_at = COALESCE(past_due_at, now()),
91
+       locked_at = now(),
92
+       lock_reason = 'past_due',
93
+       grace_until = sqlc.narg(grace_until)::timestamptz,
94
+       last_webhook_event_id = sqlc.arg(last_webhook_event_id)::text,
95
+       updated_at = now()
96
+ WHERE org_id = sqlc.arg(org_id)::bigint
97
+RETURNING *;
98
+
99
+-- name: MarkCanceled :one
100
+WITH state AS (
101
+    UPDATE org_billing_states
102
+       SET plan = 'free',
103
+           subscription_status = 'canceled',
104
+           canceled_at = COALESCE(canceled_at, now()),
105
+           locked_at = now(),
106
+           lock_reason = 'canceled',
107
+           grace_until = NULL,
108
+           cancel_at_period_end = false,
109
+           last_webhook_event_id = sqlc.arg(last_webhook_event_id)::text,
110
+           updated_at = now()
111
+     WHERE org_id = sqlc.arg(org_id)::bigint
112
+    RETURNING *
113
+), org_update AS (
114
+    UPDATE orgs
115
+       SET plan = 'free',
116
+           updated_at = now()
117
+     WHERE id = sqlc.arg(org_id)::bigint
118
+    RETURNING id
119
+)
120
+SELECT * FROM state;
121
+
122
+-- name: ClearBillingLock :one
123
+WITH state AS (
124
+    UPDATE org_billing_states
125
+       SET plan = CASE
126
+               WHEN subscription_status = 'canceled' THEN 'free'
127
+               ELSE plan
128
+           END,
129
+           subscription_status = CASE
130
+               WHEN subscription_status = 'canceled' THEN 'none'
131
+               ELSE subscription_status
132
+           END,
133
+           locked_at = NULL,
134
+           lock_reason = NULL,
135
+           grace_until = NULL,
136
+           updated_at = now()
137
+     WHERE org_id = $1
138
+    RETURNING *
139
+), org_update AS (
140
+    UPDATE orgs
141
+       SET plan = state.plan,
142
+           updated_at = now()
143
+      FROM state
144
+     WHERE orgs.id = state.org_id
145
+    RETURNING orgs.id
146
+)
147
+SELECT * FROM state;
148
+
149
+-- ─── billing_seat_snapshots ────────────────────────────────────────
150
+
151
+-- name: CreateSeatSnapshot :one
152
+WITH snapshot AS (
153
+    INSERT INTO billing_seat_snapshots (
154
+        org_id,
155
+        provider,
156
+        stripe_subscription_id,
157
+        active_members,
158
+        billable_seats,
159
+        source
160
+    )
161
+    VALUES (
162
+        sqlc.arg(org_id)::bigint,
163
+        'stripe',
164
+        sqlc.narg(stripe_subscription_id)::text,
165
+        sqlc.arg(active_members)::integer,
166
+        sqlc.arg(billable_seats)::integer,
167
+        sqlc.arg(source)::text
168
+    )
169
+    RETURNING *
170
+), state AS (
171
+    INSERT INTO org_billing_states (org_id, billable_seats, seat_snapshot_at)
172
+    SELECT org_id, billable_seats, captured_at FROM snapshot
173
+    ON CONFLICT (org_id) DO UPDATE
174
+       SET billable_seats = EXCLUDED.billable_seats,
175
+           seat_snapshot_at = EXCLUDED.seat_snapshot_at,
176
+           updated_at = now()
177
+    RETURNING org_id
178
+)
179
+SELECT * FROM snapshot;
180
+
181
+-- name: ListSeatSnapshotsForOrg :many
182
+SELECT * FROM billing_seat_snapshots
183
+WHERE org_id = $1
184
+ORDER BY captured_at DESC, id DESC
185
+LIMIT $2;
186
+
187
+-- ─── billing_invoices ──────────────────────────────────────────────
188
+
189
+-- name: UpsertInvoice :one
190
+INSERT INTO billing_invoices (
191
+    org_id,
192
+    provider,
193
+    stripe_invoice_id,
194
+    stripe_customer_id,
195
+    stripe_subscription_id,
196
+    status,
197
+    number,
198
+    currency,
199
+    amount_due_cents,
200
+    amount_paid_cents,
201
+    amount_remaining_cents,
202
+    hosted_invoice_url,
203
+    invoice_pdf_url,
204
+    period_start,
205
+    period_end,
206
+    due_at,
207
+    paid_at,
208
+    voided_at
209
+)
210
+VALUES (
211
+    sqlc.arg(org_id)::bigint,
212
+    'stripe',
213
+    sqlc.arg(stripe_invoice_id)::text,
214
+    sqlc.arg(stripe_customer_id)::text,
215
+    sqlc.narg(stripe_subscription_id)::text,
216
+    sqlc.arg(status)::billing_invoice_status,
217
+    sqlc.arg(number)::text,
218
+    sqlc.arg(currency)::text,
219
+    sqlc.arg(amount_due_cents)::bigint,
220
+    sqlc.arg(amount_paid_cents)::bigint,
221
+    sqlc.arg(amount_remaining_cents)::bigint,
222
+    sqlc.arg(hosted_invoice_url)::text,
223
+    sqlc.arg(invoice_pdf_url)::text,
224
+    sqlc.narg(period_start)::timestamptz,
225
+    sqlc.narg(period_end)::timestamptz,
226
+    sqlc.narg(due_at)::timestamptz,
227
+    sqlc.narg(paid_at)::timestamptz,
228
+    sqlc.narg(voided_at)::timestamptz
229
+)
230
+ON CONFLICT (provider, stripe_invoice_id) DO UPDATE
231
+   SET org_id = EXCLUDED.org_id,
232
+       stripe_customer_id = EXCLUDED.stripe_customer_id,
233
+       stripe_subscription_id = EXCLUDED.stripe_subscription_id,
234
+       status = EXCLUDED.status,
235
+       number = EXCLUDED.number,
236
+       currency = EXCLUDED.currency,
237
+       amount_due_cents = EXCLUDED.amount_due_cents,
238
+       amount_paid_cents = EXCLUDED.amount_paid_cents,
239
+       amount_remaining_cents = EXCLUDED.amount_remaining_cents,
240
+       hosted_invoice_url = EXCLUDED.hosted_invoice_url,
241
+       invoice_pdf_url = EXCLUDED.invoice_pdf_url,
242
+       period_start = EXCLUDED.period_start,
243
+       period_end = EXCLUDED.period_end,
244
+       due_at = EXCLUDED.due_at,
245
+       paid_at = EXCLUDED.paid_at,
246
+       voided_at = EXCLUDED.voided_at,
247
+       updated_at = now()
248
+RETURNING *;
249
+
250
+-- name: ListInvoicesForOrg :many
251
+SELECT * FROM billing_invoices
252
+WHERE org_id = $1
253
+ORDER BY created_at DESC, id DESC
254
+LIMIT $2;
255
+
256
+-- ─── billing_webhook_events ────────────────────────────────────────
257
+
258
+-- name: CreateWebhookEventReceipt :one
259
+INSERT INTO billing_webhook_events (
260
+    provider,
261
+    provider_event_id,
262
+    event_type,
263
+    api_version,
264
+    payload
265
+)
266
+VALUES (
267
+    'stripe',
268
+    sqlc.arg(provider_event_id)::text,
269
+    sqlc.arg(event_type)::text,
270
+    sqlc.arg(api_version)::text,
271
+    sqlc.arg(payload)::jsonb
272
+)
273
+ON CONFLICT (provider, provider_event_id) DO NOTHING
274
+RETURNING *;
275
+
276
+-- name: MarkWebhookEventProcessed :one
277
+UPDATE billing_webhook_events
278
+   SET processed_at = now(),
279
+       process_error = '',
280
+       processing_attempts = processing_attempts + 1
281
+ WHERE provider = 'stripe'
282
+   AND provider_event_id = $1
283
+RETURNING *;
284
+
285
+-- name: MarkWebhookEventFailed :one
286
+UPDATE billing_webhook_events
287
+   SET process_error = $2,
288
+       processing_attempts = processing_attempts + 1
289
+ WHERE provider = 'stripe'
290
+   AND provider_event_id = $1
291
+RETURNING *;
internal/billing/sqlc/billing.sql.goadded
@@ -0,0 +1,865 @@
1
+// Code generated by sqlc. DO NOT EDIT.
2
+// versions:
3
+//   sqlc v1.31.1
4
+// source: billing.sql
5
+
6
+package billingdb
7
+
8
+import (
9
+	"context"
10
+
11
+	"github.com/jackc/pgx/v5/pgtype"
12
+)
13
+
14
+const applySubscriptionSnapshot = `-- name: ApplySubscriptionSnapshot :one
15
+WITH state AS (
16
+    INSERT INTO org_billing_states (
17
+        org_id,
18
+        provider,
19
+        plan,
20
+        subscription_status,
21
+        stripe_subscription_id,
22
+        stripe_subscription_item_id,
23
+        current_period_start,
24
+        current_period_end,
25
+        cancel_at_period_end,
26
+        trial_end,
27
+        canceled_at,
28
+        last_webhook_event_id,
29
+        past_due_at,
30
+        locked_at,
31
+        lock_reason,
32
+        grace_until
33
+    )
34
+    VALUES (
35
+        $1::bigint,
36
+        'stripe',
37
+        $2::org_plan,
38
+        $3::billing_subscription_status,
39
+        $4::text,
40
+        $5::text,
41
+        $6::timestamptz,
42
+        $7::timestamptz,
43
+        $8::boolean,
44
+        $9::timestamptz,
45
+        $10::timestamptz,
46
+        $11::text,
47
+        CASE
48
+            WHEN $3::billing_subscription_status = 'past_due' THEN now()
49
+            ELSE NULL
50
+        END,
51
+        NULL,
52
+        NULL,
53
+        NULL
54
+    )
55
+    ON CONFLICT (org_id) DO UPDATE
56
+       SET plan = EXCLUDED.plan,
57
+           subscription_status = EXCLUDED.subscription_status,
58
+           stripe_subscription_id = EXCLUDED.stripe_subscription_id,
59
+           stripe_subscription_item_id = EXCLUDED.stripe_subscription_item_id,
60
+           current_period_start = EXCLUDED.current_period_start,
61
+           current_period_end = EXCLUDED.current_period_end,
62
+           cancel_at_period_end = EXCLUDED.cancel_at_period_end,
63
+           trial_end = EXCLUDED.trial_end,
64
+           canceled_at = EXCLUDED.canceled_at,
65
+           last_webhook_event_id = EXCLUDED.last_webhook_event_id,
66
+           past_due_at = CASE
67
+               WHEN EXCLUDED.subscription_status = 'past_due' THEN COALESCE(org_billing_states.past_due_at, now())
68
+               ELSE NULL
69
+           END,
70
+           locked_at = NULL,
71
+           lock_reason = NULL,
72
+           grace_until = NULL,
73
+           updated_at = now()
74
+    RETURNING org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at
75
+), org_update AS (
76
+    UPDATE orgs
77
+       SET plan = $2::org_plan,
78
+           updated_at = now()
79
+     WHERE id = $1::bigint
80
+    RETURNING id
81
+)
82
+SELECT org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at FROM state
83
+`
84
+
85
+type ApplySubscriptionSnapshotParams struct {
86
+	OrgID                    int64
87
+	Plan                     OrgPlan
88
+	SubscriptionStatus       BillingSubscriptionStatus
89
+	StripeSubscriptionID     pgtype.Text
90
+	StripeSubscriptionItemID pgtype.Text
91
+	CurrentPeriodStart       pgtype.Timestamptz
92
+	CurrentPeriodEnd         pgtype.Timestamptz
93
+	CancelAtPeriodEnd        bool
94
+	TrialEnd                 pgtype.Timestamptz
95
+	CanceledAt               pgtype.Timestamptz
96
+	LastWebhookEventID       string
97
+}
98
+
99
+type ApplySubscriptionSnapshotRow struct {
100
+	OrgID                    int64
101
+	Provider                 BillingProvider
102
+	StripeCustomerID         pgtype.Text
103
+	StripeSubscriptionID     pgtype.Text
104
+	StripeSubscriptionItemID pgtype.Text
105
+	Plan                     OrgPlan
106
+	SubscriptionStatus       BillingSubscriptionStatus
107
+	BillableSeats            int32
108
+	SeatSnapshotAt           pgtype.Timestamptz
109
+	CurrentPeriodStart       pgtype.Timestamptz
110
+	CurrentPeriodEnd         pgtype.Timestamptz
111
+	CancelAtPeriodEnd        bool
112
+	TrialEnd                 pgtype.Timestamptz
113
+	PastDueAt                pgtype.Timestamptz
114
+	CanceledAt               pgtype.Timestamptz
115
+	LockedAt                 pgtype.Timestamptz
116
+	LockReason               NullBillingLockReason
117
+	GraceUntil               pgtype.Timestamptz
118
+	LastWebhookEventID       string
119
+	CreatedAt                pgtype.Timestamptz
120
+	UpdatedAt                pgtype.Timestamptz
121
+}
122
+
123
+func (q *Queries) ApplySubscriptionSnapshot(ctx context.Context, db DBTX, arg ApplySubscriptionSnapshotParams) (ApplySubscriptionSnapshotRow, error) {
124
+	row := db.QueryRow(ctx, applySubscriptionSnapshot,
125
+		arg.OrgID,
126
+		arg.Plan,
127
+		arg.SubscriptionStatus,
128
+		arg.StripeSubscriptionID,
129
+		arg.StripeSubscriptionItemID,
130
+		arg.CurrentPeriodStart,
131
+		arg.CurrentPeriodEnd,
132
+		arg.CancelAtPeriodEnd,
133
+		arg.TrialEnd,
134
+		arg.CanceledAt,
135
+		arg.LastWebhookEventID,
136
+	)
137
+	var i ApplySubscriptionSnapshotRow
138
+	err := row.Scan(
139
+		&i.OrgID,
140
+		&i.Provider,
141
+		&i.StripeCustomerID,
142
+		&i.StripeSubscriptionID,
143
+		&i.StripeSubscriptionItemID,
144
+		&i.Plan,
145
+		&i.SubscriptionStatus,
146
+		&i.BillableSeats,
147
+		&i.SeatSnapshotAt,
148
+		&i.CurrentPeriodStart,
149
+		&i.CurrentPeriodEnd,
150
+		&i.CancelAtPeriodEnd,
151
+		&i.TrialEnd,
152
+		&i.PastDueAt,
153
+		&i.CanceledAt,
154
+		&i.LockedAt,
155
+		&i.LockReason,
156
+		&i.GraceUntil,
157
+		&i.LastWebhookEventID,
158
+		&i.CreatedAt,
159
+		&i.UpdatedAt,
160
+	)
161
+	return i, err
162
+}
163
+
164
+const clearBillingLock = `-- name: ClearBillingLock :one
165
+WITH state AS (
166
+    UPDATE org_billing_states
167
+       SET plan = CASE
168
+               WHEN subscription_status = 'canceled' THEN 'free'
169
+               ELSE plan
170
+           END,
171
+           subscription_status = CASE
172
+               WHEN subscription_status = 'canceled' THEN 'none'
173
+               ELSE subscription_status
174
+           END,
175
+           locked_at = NULL,
176
+           lock_reason = NULL,
177
+           grace_until = NULL,
178
+           updated_at = now()
179
+     WHERE org_id = $1
180
+    RETURNING org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at
181
+), org_update AS (
182
+    UPDATE orgs
183
+       SET plan = state.plan,
184
+           updated_at = now()
185
+      FROM state
186
+     WHERE orgs.id = state.org_id
187
+    RETURNING orgs.id
188
+)
189
+SELECT org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at FROM state
190
+`
191
+
192
+type ClearBillingLockRow struct {
193
+	OrgID                    int64
194
+	Provider                 BillingProvider
195
+	StripeCustomerID         pgtype.Text
196
+	StripeSubscriptionID     pgtype.Text
197
+	StripeSubscriptionItemID pgtype.Text
198
+	Plan                     OrgPlan
199
+	SubscriptionStatus       BillingSubscriptionStatus
200
+	BillableSeats            int32
201
+	SeatSnapshotAt           pgtype.Timestamptz
202
+	CurrentPeriodStart       pgtype.Timestamptz
203
+	CurrentPeriodEnd         pgtype.Timestamptz
204
+	CancelAtPeriodEnd        bool
205
+	TrialEnd                 pgtype.Timestamptz
206
+	PastDueAt                pgtype.Timestamptz
207
+	CanceledAt               pgtype.Timestamptz
208
+	LockedAt                 pgtype.Timestamptz
209
+	LockReason               NullBillingLockReason
210
+	GraceUntil               pgtype.Timestamptz
211
+	LastWebhookEventID       string
212
+	CreatedAt                pgtype.Timestamptz
213
+	UpdatedAt                pgtype.Timestamptz
214
+}
215
+
216
+func (q *Queries) ClearBillingLock(ctx context.Context, db DBTX, orgID int64) (ClearBillingLockRow, error) {
217
+	row := db.QueryRow(ctx, clearBillingLock, orgID)
218
+	var i ClearBillingLockRow
219
+	err := row.Scan(
220
+		&i.OrgID,
221
+		&i.Provider,
222
+		&i.StripeCustomerID,
223
+		&i.StripeSubscriptionID,
224
+		&i.StripeSubscriptionItemID,
225
+		&i.Plan,
226
+		&i.SubscriptionStatus,
227
+		&i.BillableSeats,
228
+		&i.SeatSnapshotAt,
229
+		&i.CurrentPeriodStart,
230
+		&i.CurrentPeriodEnd,
231
+		&i.CancelAtPeriodEnd,
232
+		&i.TrialEnd,
233
+		&i.PastDueAt,
234
+		&i.CanceledAt,
235
+		&i.LockedAt,
236
+		&i.LockReason,
237
+		&i.GraceUntil,
238
+		&i.LastWebhookEventID,
239
+		&i.CreatedAt,
240
+		&i.UpdatedAt,
241
+	)
242
+	return i, err
243
+}
244
+
245
+const createSeatSnapshot = `-- name: CreateSeatSnapshot :one
246
+
247
+WITH snapshot AS (
248
+    INSERT INTO billing_seat_snapshots (
249
+        org_id,
250
+        provider,
251
+        stripe_subscription_id,
252
+        active_members,
253
+        billable_seats,
254
+        source
255
+    )
256
+    VALUES (
257
+        $1::bigint,
258
+        'stripe',
259
+        $2::text,
260
+        $3::integer,
261
+        $4::integer,
262
+        $5::text
263
+    )
264
+    RETURNING id, org_id, provider, stripe_subscription_id, active_members, billable_seats, source, captured_at
265
+), state AS (
266
+    INSERT INTO org_billing_states (org_id, billable_seats, seat_snapshot_at)
267
+    SELECT org_id, billable_seats, captured_at FROM snapshot
268
+    ON CONFLICT (org_id) DO UPDATE
269
+       SET billable_seats = EXCLUDED.billable_seats,
270
+           seat_snapshot_at = EXCLUDED.seat_snapshot_at,
271
+           updated_at = now()
272
+    RETURNING org_id
273
+)
274
+SELECT id, org_id, provider, stripe_subscription_id, active_members, billable_seats, source, captured_at FROM snapshot
275
+`
276
+
277
+type CreateSeatSnapshotParams struct {
278
+	OrgID                int64
279
+	StripeSubscriptionID pgtype.Text
280
+	ActiveMembers        int32
281
+	BillableSeats        int32
282
+	Source               string
283
+}
284
+
285
+type CreateSeatSnapshotRow struct {
286
+	ID                   int64
287
+	OrgID                int64
288
+	Provider             BillingProvider
289
+	StripeSubscriptionID pgtype.Text
290
+	ActiveMembers        int32
291
+	BillableSeats        int32
292
+	Source               string
293
+	CapturedAt           pgtype.Timestamptz
294
+}
295
+
296
+// ─── billing_seat_snapshots ────────────────────────────────────────
297
+func (q *Queries) CreateSeatSnapshot(ctx context.Context, db DBTX, arg CreateSeatSnapshotParams) (CreateSeatSnapshotRow, error) {
298
+	row := db.QueryRow(ctx, createSeatSnapshot,
299
+		arg.OrgID,
300
+		arg.StripeSubscriptionID,
301
+		arg.ActiveMembers,
302
+		arg.BillableSeats,
303
+		arg.Source,
304
+	)
305
+	var i CreateSeatSnapshotRow
306
+	err := row.Scan(
307
+		&i.ID,
308
+		&i.OrgID,
309
+		&i.Provider,
310
+		&i.StripeSubscriptionID,
311
+		&i.ActiveMembers,
312
+		&i.BillableSeats,
313
+		&i.Source,
314
+		&i.CapturedAt,
315
+	)
316
+	return i, err
317
+}
318
+
319
+const createWebhookEventReceipt = `-- name: CreateWebhookEventReceipt :one
320
+
321
+INSERT INTO billing_webhook_events (
322
+    provider,
323
+    provider_event_id,
324
+    event_type,
325
+    api_version,
326
+    payload
327
+)
328
+VALUES (
329
+    'stripe',
330
+    $1::text,
331
+    $2::text,
332
+    $3::text,
333
+    $4::jsonb
334
+)
335
+ON CONFLICT (provider, provider_event_id) DO NOTHING
336
+RETURNING id, provider, provider_event_id, event_type, api_version, payload, received_at, processed_at, process_error, processing_attempts
337
+`
338
+
339
+type CreateWebhookEventReceiptParams struct {
340
+	ProviderEventID string
341
+	EventType       string
342
+	ApiVersion      string
343
+	Payload         []byte
344
+}
345
+
346
+// ─── billing_webhook_events ────────────────────────────────────────
347
+func (q *Queries) CreateWebhookEventReceipt(ctx context.Context, db DBTX, arg CreateWebhookEventReceiptParams) (BillingWebhookEvent, error) {
348
+	row := db.QueryRow(ctx, createWebhookEventReceipt,
349
+		arg.ProviderEventID,
350
+		arg.EventType,
351
+		arg.ApiVersion,
352
+		arg.Payload,
353
+	)
354
+	var i BillingWebhookEvent
355
+	err := row.Scan(
356
+		&i.ID,
357
+		&i.Provider,
358
+		&i.ProviderEventID,
359
+		&i.EventType,
360
+		&i.ApiVersion,
361
+		&i.Payload,
362
+		&i.ReceivedAt,
363
+		&i.ProcessedAt,
364
+		&i.ProcessError,
365
+		&i.ProcessingAttempts,
366
+	)
367
+	return i, err
368
+}
369
+
370
+const getOrgBillingState = `-- name: GetOrgBillingState :one
371
+
372
+
373
+SELECT org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at FROM org_billing_states WHERE org_id = $1
374
+`
375
+
376
+// SPDX-License-Identifier: AGPL-3.0-or-later
377
+// ─── org_billing_states ────────────────────────────────────────────
378
+func (q *Queries) GetOrgBillingState(ctx context.Context, db DBTX, orgID int64) (OrgBillingState, error) {
379
+	row := db.QueryRow(ctx, getOrgBillingState, orgID)
380
+	var i OrgBillingState
381
+	err := row.Scan(
382
+		&i.OrgID,
383
+		&i.Provider,
384
+		&i.StripeCustomerID,
385
+		&i.StripeSubscriptionID,
386
+		&i.StripeSubscriptionItemID,
387
+		&i.Plan,
388
+		&i.SubscriptionStatus,
389
+		&i.BillableSeats,
390
+		&i.SeatSnapshotAt,
391
+		&i.CurrentPeriodStart,
392
+		&i.CurrentPeriodEnd,
393
+		&i.CancelAtPeriodEnd,
394
+		&i.TrialEnd,
395
+		&i.PastDueAt,
396
+		&i.CanceledAt,
397
+		&i.LockedAt,
398
+		&i.LockReason,
399
+		&i.GraceUntil,
400
+		&i.LastWebhookEventID,
401
+		&i.CreatedAt,
402
+		&i.UpdatedAt,
403
+	)
404
+	return i, err
405
+}
406
+
407
+const listInvoicesForOrg = `-- name: ListInvoicesForOrg :many
408
+SELECT id, org_id, provider, stripe_invoice_id, stripe_customer_id, stripe_subscription_id, status, number, currency, amount_due_cents, amount_paid_cents, amount_remaining_cents, hosted_invoice_url, invoice_pdf_url, period_start, period_end, due_at, paid_at, voided_at, created_at, updated_at FROM billing_invoices
409
+WHERE org_id = $1
410
+ORDER BY created_at DESC, id DESC
411
+LIMIT $2
412
+`
413
+
414
+type ListInvoicesForOrgParams struct {
415
+	OrgID int64
416
+	Limit int32
417
+}
418
+
419
+func (q *Queries) ListInvoicesForOrg(ctx context.Context, db DBTX, arg ListInvoicesForOrgParams) ([]BillingInvoice, error) {
420
+	rows, err := db.Query(ctx, listInvoicesForOrg, arg.OrgID, arg.Limit)
421
+	if err != nil {
422
+		return nil, err
423
+	}
424
+	defer rows.Close()
425
+	items := []BillingInvoice{}
426
+	for rows.Next() {
427
+		var i BillingInvoice
428
+		if err := rows.Scan(
429
+			&i.ID,
430
+			&i.OrgID,
431
+			&i.Provider,
432
+			&i.StripeInvoiceID,
433
+			&i.StripeCustomerID,
434
+			&i.StripeSubscriptionID,
435
+			&i.Status,
436
+			&i.Number,
437
+			&i.Currency,
438
+			&i.AmountDueCents,
439
+			&i.AmountPaidCents,
440
+			&i.AmountRemainingCents,
441
+			&i.HostedInvoiceUrl,
442
+			&i.InvoicePdfUrl,
443
+			&i.PeriodStart,
444
+			&i.PeriodEnd,
445
+			&i.DueAt,
446
+			&i.PaidAt,
447
+			&i.VoidedAt,
448
+			&i.CreatedAt,
449
+			&i.UpdatedAt,
450
+		); err != nil {
451
+			return nil, err
452
+		}
453
+		items = append(items, i)
454
+	}
455
+	if err := rows.Err(); err != nil {
456
+		return nil, err
457
+	}
458
+	return items, nil
459
+}
460
+
461
+const listSeatSnapshotsForOrg = `-- name: ListSeatSnapshotsForOrg :many
462
+SELECT id, org_id, provider, stripe_subscription_id, active_members, billable_seats, source, captured_at FROM billing_seat_snapshots
463
+WHERE org_id = $1
464
+ORDER BY captured_at DESC, id DESC
465
+LIMIT $2
466
+`
467
+
468
+type ListSeatSnapshotsForOrgParams struct {
469
+	OrgID int64
470
+	Limit int32
471
+}
472
+
473
+func (q *Queries) ListSeatSnapshotsForOrg(ctx context.Context, db DBTX, arg ListSeatSnapshotsForOrgParams) ([]BillingSeatSnapshot, error) {
474
+	rows, err := db.Query(ctx, listSeatSnapshotsForOrg, arg.OrgID, arg.Limit)
475
+	if err != nil {
476
+		return nil, err
477
+	}
478
+	defer rows.Close()
479
+	items := []BillingSeatSnapshot{}
480
+	for rows.Next() {
481
+		var i BillingSeatSnapshot
482
+		if err := rows.Scan(
483
+			&i.ID,
484
+			&i.OrgID,
485
+			&i.Provider,
486
+			&i.StripeSubscriptionID,
487
+			&i.ActiveMembers,
488
+			&i.BillableSeats,
489
+			&i.Source,
490
+			&i.CapturedAt,
491
+		); err != nil {
492
+			return nil, err
493
+		}
494
+		items = append(items, i)
495
+	}
496
+	if err := rows.Err(); err != nil {
497
+		return nil, err
498
+	}
499
+	return items, nil
500
+}
501
+
502
+const markCanceled = `-- name: MarkCanceled :one
503
+WITH state AS (
504
+    UPDATE org_billing_states
505
+       SET plan = 'free',
506
+           subscription_status = 'canceled',
507
+           canceled_at = COALESCE(canceled_at, now()),
508
+           locked_at = now(),
509
+           lock_reason = 'canceled',
510
+           grace_until = NULL,
511
+           cancel_at_period_end = false,
512
+           last_webhook_event_id = $1::text,
513
+           updated_at = now()
514
+     WHERE org_id = $2::bigint
515
+    RETURNING org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at
516
+), org_update AS (
517
+    UPDATE orgs
518
+       SET plan = 'free',
519
+           updated_at = now()
520
+     WHERE id = $2::bigint
521
+    RETURNING id
522
+)
523
+SELECT org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at FROM state
524
+`
525
+
526
+type MarkCanceledParams struct {
527
+	LastWebhookEventID string
528
+	OrgID              int64
529
+}
530
+
531
+type MarkCanceledRow struct {
532
+	OrgID                    int64
533
+	Provider                 BillingProvider
534
+	StripeCustomerID         pgtype.Text
535
+	StripeSubscriptionID     pgtype.Text
536
+	StripeSubscriptionItemID pgtype.Text
537
+	Plan                     OrgPlan
538
+	SubscriptionStatus       BillingSubscriptionStatus
539
+	BillableSeats            int32
540
+	SeatSnapshotAt           pgtype.Timestamptz
541
+	CurrentPeriodStart       pgtype.Timestamptz
542
+	CurrentPeriodEnd         pgtype.Timestamptz
543
+	CancelAtPeriodEnd        bool
544
+	TrialEnd                 pgtype.Timestamptz
545
+	PastDueAt                pgtype.Timestamptz
546
+	CanceledAt               pgtype.Timestamptz
547
+	LockedAt                 pgtype.Timestamptz
548
+	LockReason               NullBillingLockReason
549
+	GraceUntil               pgtype.Timestamptz
550
+	LastWebhookEventID       string
551
+	CreatedAt                pgtype.Timestamptz
552
+	UpdatedAt                pgtype.Timestamptz
553
+}
554
+
555
+func (q *Queries) MarkCanceled(ctx context.Context, db DBTX, arg MarkCanceledParams) (MarkCanceledRow, error) {
556
+	row := db.QueryRow(ctx, markCanceled, arg.LastWebhookEventID, arg.OrgID)
557
+	var i MarkCanceledRow
558
+	err := row.Scan(
559
+		&i.OrgID,
560
+		&i.Provider,
561
+		&i.StripeCustomerID,
562
+		&i.StripeSubscriptionID,
563
+		&i.StripeSubscriptionItemID,
564
+		&i.Plan,
565
+		&i.SubscriptionStatus,
566
+		&i.BillableSeats,
567
+		&i.SeatSnapshotAt,
568
+		&i.CurrentPeriodStart,
569
+		&i.CurrentPeriodEnd,
570
+		&i.CancelAtPeriodEnd,
571
+		&i.TrialEnd,
572
+		&i.PastDueAt,
573
+		&i.CanceledAt,
574
+		&i.LockedAt,
575
+		&i.LockReason,
576
+		&i.GraceUntil,
577
+		&i.LastWebhookEventID,
578
+		&i.CreatedAt,
579
+		&i.UpdatedAt,
580
+	)
581
+	return i, err
582
+}
583
+
584
+const markPastDue = `-- name: MarkPastDue :one
585
+UPDATE org_billing_states
586
+   SET subscription_status = 'past_due',
587
+       past_due_at = COALESCE(past_due_at, now()),
588
+       locked_at = now(),
589
+       lock_reason = 'past_due',
590
+       grace_until = $1::timestamptz,
591
+       last_webhook_event_id = $2::text,
592
+       updated_at = now()
593
+ WHERE org_id = $3::bigint
594
+RETURNING org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at
595
+`
596
+
597
+type MarkPastDueParams struct {
598
+	GraceUntil         pgtype.Timestamptz
599
+	LastWebhookEventID string
600
+	OrgID              int64
601
+}
602
+
603
+func (q *Queries) MarkPastDue(ctx context.Context, db DBTX, arg MarkPastDueParams) (OrgBillingState, error) {
604
+	row := db.QueryRow(ctx, markPastDue, arg.GraceUntil, arg.LastWebhookEventID, arg.OrgID)
605
+	var i OrgBillingState
606
+	err := row.Scan(
607
+		&i.OrgID,
608
+		&i.Provider,
609
+		&i.StripeCustomerID,
610
+		&i.StripeSubscriptionID,
611
+		&i.StripeSubscriptionItemID,
612
+		&i.Plan,
613
+		&i.SubscriptionStatus,
614
+		&i.BillableSeats,
615
+		&i.SeatSnapshotAt,
616
+		&i.CurrentPeriodStart,
617
+		&i.CurrentPeriodEnd,
618
+		&i.CancelAtPeriodEnd,
619
+		&i.TrialEnd,
620
+		&i.PastDueAt,
621
+		&i.CanceledAt,
622
+		&i.LockedAt,
623
+		&i.LockReason,
624
+		&i.GraceUntil,
625
+		&i.LastWebhookEventID,
626
+		&i.CreatedAt,
627
+		&i.UpdatedAt,
628
+	)
629
+	return i, err
630
+}
631
+
632
+const markWebhookEventFailed = `-- name: MarkWebhookEventFailed :one
633
+UPDATE billing_webhook_events
634
+   SET process_error = $2,
635
+       processing_attempts = processing_attempts + 1
636
+ WHERE provider = 'stripe'
637
+   AND provider_event_id = $1
638
+RETURNING id, provider, provider_event_id, event_type, api_version, payload, received_at, processed_at, process_error, processing_attempts
639
+`
640
+
641
+type MarkWebhookEventFailedParams struct {
642
+	ProviderEventID string
643
+	ProcessError    string
644
+}
645
+
646
+func (q *Queries) MarkWebhookEventFailed(ctx context.Context, db DBTX, arg MarkWebhookEventFailedParams) (BillingWebhookEvent, error) {
647
+	row := db.QueryRow(ctx, markWebhookEventFailed, arg.ProviderEventID, arg.ProcessError)
648
+	var i BillingWebhookEvent
649
+	err := row.Scan(
650
+		&i.ID,
651
+		&i.Provider,
652
+		&i.ProviderEventID,
653
+		&i.EventType,
654
+		&i.ApiVersion,
655
+		&i.Payload,
656
+		&i.ReceivedAt,
657
+		&i.ProcessedAt,
658
+		&i.ProcessError,
659
+		&i.ProcessingAttempts,
660
+	)
661
+	return i, err
662
+}
663
+
664
+const markWebhookEventProcessed = `-- name: MarkWebhookEventProcessed :one
665
+UPDATE billing_webhook_events
666
+   SET processed_at = now(),
667
+       process_error = '',
668
+       processing_attempts = processing_attempts + 1
669
+ WHERE provider = 'stripe'
670
+   AND provider_event_id = $1
671
+RETURNING id, provider, provider_event_id, event_type, api_version, payload, received_at, processed_at, process_error, processing_attempts
672
+`
673
+
674
+func (q *Queries) MarkWebhookEventProcessed(ctx context.Context, db DBTX, providerEventID string) (BillingWebhookEvent, error) {
675
+	row := db.QueryRow(ctx, markWebhookEventProcessed, providerEventID)
676
+	var i BillingWebhookEvent
677
+	err := row.Scan(
678
+		&i.ID,
679
+		&i.Provider,
680
+		&i.ProviderEventID,
681
+		&i.EventType,
682
+		&i.ApiVersion,
683
+		&i.Payload,
684
+		&i.ReceivedAt,
685
+		&i.ProcessedAt,
686
+		&i.ProcessError,
687
+		&i.ProcessingAttempts,
688
+	)
689
+	return i, err
690
+}
691
+
692
+const setStripeCustomer = `-- name: SetStripeCustomer :one
693
+INSERT INTO org_billing_states (org_id, provider, stripe_customer_id)
694
+VALUES ($1, 'stripe', $2)
695
+ON CONFLICT (org_id) DO UPDATE
696
+   SET stripe_customer_id = EXCLUDED.stripe_customer_id,
697
+       provider = 'stripe',
698
+       updated_at = now()
699
+RETURNING org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at
700
+`
701
+
702
+type SetStripeCustomerParams struct {
703
+	OrgID            int64
704
+	StripeCustomerID pgtype.Text
705
+}
706
+
707
+func (q *Queries) SetStripeCustomer(ctx context.Context, db DBTX, arg SetStripeCustomerParams) (OrgBillingState, error) {
708
+	row := db.QueryRow(ctx, setStripeCustomer, arg.OrgID, arg.StripeCustomerID)
709
+	var i OrgBillingState
710
+	err := row.Scan(
711
+		&i.OrgID,
712
+		&i.Provider,
713
+		&i.StripeCustomerID,
714
+		&i.StripeSubscriptionID,
715
+		&i.StripeSubscriptionItemID,
716
+		&i.Plan,
717
+		&i.SubscriptionStatus,
718
+		&i.BillableSeats,
719
+		&i.SeatSnapshotAt,
720
+		&i.CurrentPeriodStart,
721
+		&i.CurrentPeriodEnd,
722
+		&i.CancelAtPeriodEnd,
723
+		&i.TrialEnd,
724
+		&i.PastDueAt,
725
+		&i.CanceledAt,
726
+		&i.LockedAt,
727
+		&i.LockReason,
728
+		&i.GraceUntil,
729
+		&i.LastWebhookEventID,
730
+		&i.CreatedAt,
731
+		&i.UpdatedAt,
732
+	)
733
+	return i, err
734
+}
735
+
736
+const upsertInvoice = `-- name: UpsertInvoice :one
737
+
738
+INSERT INTO billing_invoices (
739
+    org_id,
740
+    provider,
741
+    stripe_invoice_id,
742
+    stripe_customer_id,
743
+    stripe_subscription_id,
744
+    status,
745
+    number,
746
+    currency,
747
+    amount_due_cents,
748
+    amount_paid_cents,
749
+    amount_remaining_cents,
750
+    hosted_invoice_url,
751
+    invoice_pdf_url,
752
+    period_start,
753
+    period_end,
754
+    due_at,
755
+    paid_at,
756
+    voided_at
757
+)
758
+VALUES (
759
+    $1::bigint,
760
+    'stripe',
761
+    $2::text,
762
+    $3::text,
763
+    $4::text,
764
+    $5::billing_invoice_status,
765
+    $6::text,
766
+    $7::text,
767
+    $8::bigint,
768
+    $9::bigint,
769
+    $10::bigint,
770
+    $11::text,
771
+    $12::text,
772
+    $13::timestamptz,
773
+    $14::timestamptz,
774
+    $15::timestamptz,
775
+    $16::timestamptz,
776
+    $17::timestamptz
777
+)
778
+ON CONFLICT (provider, stripe_invoice_id) DO UPDATE
779
+   SET org_id = EXCLUDED.org_id,
780
+       stripe_customer_id = EXCLUDED.stripe_customer_id,
781
+       stripe_subscription_id = EXCLUDED.stripe_subscription_id,
782
+       status = EXCLUDED.status,
783
+       number = EXCLUDED.number,
784
+       currency = EXCLUDED.currency,
785
+       amount_due_cents = EXCLUDED.amount_due_cents,
786
+       amount_paid_cents = EXCLUDED.amount_paid_cents,
787
+       amount_remaining_cents = EXCLUDED.amount_remaining_cents,
788
+       hosted_invoice_url = EXCLUDED.hosted_invoice_url,
789
+       invoice_pdf_url = EXCLUDED.invoice_pdf_url,
790
+       period_start = EXCLUDED.period_start,
791
+       period_end = EXCLUDED.period_end,
792
+       due_at = EXCLUDED.due_at,
793
+       paid_at = EXCLUDED.paid_at,
794
+       voided_at = EXCLUDED.voided_at,
795
+       updated_at = now()
796
+RETURNING id, org_id, provider, stripe_invoice_id, stripe_customer_id, stripe_subscription_id, status, number, currency, amount_due_cents, amount_paid_cents, amount_remaining_cents, hosted_invoice_url, invoice_pdf_url, period_start, period_end, due_at, paid_at, voided_at, created_at, updated_at
797
+`
798
+
799
+type UpsertInvoiceParams struct {
800
+	OrgID                int64
801
+	StripeInvoiceID      string
802
+	StripeCustomerID     string
803
+	StripeSubscriptionID pgtype.Text
804
+	Status               BillingInvoiceStatus
805
+	Number               string
806
+	Currency             string
807
+	AmountDueCents       int64
808
+	AmountPaidCents      int64
809
+	AmountRemainingCents int64
810
+	HostedInvoiceUrl     string
811
+	InvoicePdfUrl        string
812
+	PeriodStart          pgtype.Timestamptz
813
+	PeriodEnd            pgtype.Timestamptz
814
+	DueAt                pgtype.Timestamptz
815
+	PaidAt               pgtype.Timestamptz
816
+	VoidedAt             pgtype.Timestamptz
817
+}
818
+
819
+// ─── billing_invoices ──────────────────────────────────────────────
820
+func (q *Queries) UpsertInvoice(ctx context.Context, db DBTX, arg UpsertInvoiceParams) (BillingInvoice, error) {
821
+	row := db.QueryRow(ctx, upsertInvoice,
822
+		arg.OrgID,
823
+		arg.StripeInvoiceID,
824
+		arg.StripeCustomerID,
825
+		arg.StripeSubscriptionID,
826
+		arg.Status,
827
+		arg.Number,
828
+		arg.Currency,
829
+		arg.AmountDueCents,
830
+		arg.AmountPaidCents,
831
+		arg.AmountRemainingCents,
832
+		arg.HostedInvoiceUrl,
833
+		arg.InvoicePdfUrl,
834
+		arg.PeriodStart,
835
+		arg.PeriodEnd,
836
+		arg.DueAt,
837
+		arg.PaidAt,
838
+		arg.VoidedAt,
839
+	)
840
+	var i BillingInvoice
841
+	err := row.Scan(
842
+		&i.ID,
843
+		&i.OrgID,
844
+		&i.Provider,
845
+		&i.StripeInvoiceID,
846
+		&i.StripeCustomerID,
847
+		&i.StripeSubscriptionID,
848
+		&i.Status,
849
+		&i.Number,
850
+		&i.Currency,
851
+		&i.AmountDueCents,
852
+		&i.AmountPaidCents,
853
+		&i.AmountRemainingCents,
854
+		&i.HostedInvoiceUrl,
855
+		&i.InvoicePdfUrl,
856
+		&i.PeriodStart,
857
+		&i.PeriodEnd,
858
+		&i.DueAt,
859
+		&i.PaidAt,
860
+		&i.VoidedAt,
861
+		&i.CreatedAt,
862
+		&i.UpdatedAt,
863
+	)
864
+	return i, err
865
+}
internal/billing/sqlc/db.goadded
@@ -0,0 +1,25 @@
1
+// Code generated by sqlc. DO NOT EDIT.
2
+// versions:
3
+//   sqlc v1.31.1
4
+
5
+package billingdb
6
+
7
+import (
8
+	"context"
9
+
10
+	"github.com/jackc/pgx/v5"
11
+	"github.com/jackc/pgx/v5/pgconn"
12
+)
13
+
14
+type DBTX interface {
15
+	Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
16
+	Query(context.Context, string, ...interface{}) (pgx.Rows, error)
17
+	QueryRow(context.Context, string, ...interface{}) pgx.Row
18
+}
19
+
20
+func New() *Queries {
21
+	return &Queries{}
22
+}
23
+
24
+type Queries struct {
25
+}
internal/actions/sqlc/models.go → internal/billing/sqlc/models.gocopied (89% similarity)
@@ -2,7 +2,7 @@
22
 // versions:
33
 //   sqlc v1.31.1
44
 
5
-package actionsdb
5
+package billingdb
66
 
77
 import (
88
 	"database/sql/driver"
@@ -12,6 +12,184 @@ import (
1212
 	"github.com/jackc/pgx/v5/pgtype"
1313
 )
1414
 
15
+type BillingInvoiceStatus string
16
+
17
+const (
18
+	BillingInvoiceStatusDraft         BillingInvoiceStatus = "draft"
19
+	BillingInvoiceStatusOpen          BillingInvoiceStatus = "open"
20
+	BillingInvoiceStatusPaid          BillingInvoiceStatus = "paid"
21
+	BillingInvoiceStatusVoid          BillingInvoiceStatus = "void"
22
+	BillingInvoiceStatusUncollectible BillingInvoiceStatus = "uncollectible"
23
+)
24
+
25
+func (e *BillingInvoiceStatus) Scan(src interface{}) error {
26
+	switch s := src.(type) {
27
+	case []byte:
28
+		*e = BillingInvoiceStatus(s)
29
+	case string:
30
+		*e = BillingInvoiceStatus(s)
31
+	default:
32
+		return fmt.Errorf("unsupported scan type for BillingInvoiceStatus: %T", src)
33
+	}
34
+	return nil
35
+}
36
+
37
+type NullBillingInvoiceStatus struct {
38
+	BillingInvoiceStatus BillingInvoiceStatus
39
+	Valid                bool // Valid is true if BillingInvoiceStatus is not NULL
40
+}
41
+
42
+// Scan implements the Scanner interface.
43
+func (ns *NullBillingInvoiceStatus) Scan(value interface{}) error {
44
+	if value == nil {
45
+		ns.BillingInvoiceStatus, ns.Valid = "", false
46
+		return nil
47
+	}
48
+	ns.Valid = true
49
+	return ns.BillingInvoiceStatus.Scan(value)
50
+}
51
+
52
+// Value implements the driver Valuer interface.
53
+func (ns NullBillingInvoiceStatus) Value() (driver.Value, error) {
54
+	if !ns.Valid {
55
+		return nil, nil
56
+	}
57
+	return string(ns.BillingInvoiceStatus), nil
58
+}
59
+
60
+type BillingLockReason string
61
+
62
+const (
63
+	BillingLockReasonPastDue  BillingLockReason = "past_due"
64
+	BillingLockReasonCanceled BillingLockReason = "canceled"
65
+	BillingLockReasonUnpaid   BillingLockReason = "unpaid"
66
+	BillingLockReasonManual   BillingLockReason = "manual"
67
+)
68
+
69
+func (e *BillingLockReason) Scan(src interface{}) error {
70
+	switch s := src.(type) {
71
+	case []byte:
72
+		*e = BillingLockReason(s)
73
+	case string:
74
+		*e = BillingLockReason(s)
75
+	default:
76
+		return fmt.Errorf("unsupported scan type for BillingLockReason: %T", src)
77
+	}
78
+	return nil
79
+}
80
+
81
+type NullBillingLockReason struct {
82
+	BillingLockReason BillingLockReason
83
+	Valid             bool // Valid is true if BillingLockReason is not NULL
84
+}
85
+
86
+// Scan implements the Scanner interface.
87
+func (ns *NullBillingLockReason) Scan(value interface{}) error {
88
+	if value == nil {
89
+		ns.BillingLockReason, ns.Valid = "", false
90
+		return nil
91
+	}
92
+	ns.Valid = true
93
+	return ns.BillingLockReason.Scan(value)
94
+}
95
+
96
+// Value implements the driver Valuer interface.
97
+func (ns NullBillingLockReason) Value() (driver.Value, error) {
98
+	if !ns.Valid {
99
+		return nil, nil
100
+	}
101
+	return string(ns.BillingLockReason), nil
102
+}
103
+
104
+type BillingProvider string
105
+
106
+const (
107
+	BillingProviderStripe BillingProvider = "stripe"
108
+)
109
+
110
+func (e *BillingProvider) Scan(src interface{}) error {
111
+	switch s := src.(type) {
112
+	case []byte:
113
+		*e = BillingProvider(s)
114
+	case string:
115
+		*e = BillingProvider(s)
116
+	default:
117
+		return fmt.Errorf("unsupported scan type for BillingProvider: %T", src)
118
+	}
119
+	return nil
120
+}
121
+
122
+type NullBillingProvider struct {
123
+	BillingProvider BillingProvider
124
+	Valid           bool // Valid is true if BillingProvider is not NULL
125
+}
126
+
127
+// Scan implements the Scanner interface.
128
+func (ns *NullBillingProvider) Scan(value interface{}) error {
129
+	if value == nil {
130
+		ns.BillingProvider, ns.Valid = "", false
131
+		return nil
132
+	}
133
+	ns.Valid = true
134
+	return ns.BillingProvider.Scan(value)
135
+}
136
+
137
+// Value implements the driver Valuer interface.
138
+func (ns NullBillingProvider) Value() (driver.Value, error) {
139
+	if !ns.Valid {
140
+		return nil, nil
141
+	}
142
+	return string(ns.BillingProvider), nil
143
+}
144
+
145
+type BillingSubscriptionStatus string
146
+
147
+const (
148
+	BillingSubscriptionStatusNone       BillingSubscriptionStatus = "none"
149
+	BillingSubscriptionStatusIncomplete BillingSubscriptionStatus = "incomplete"
150
+	BillingSubscriptionStatusTrialing   BillingSubscriptionStatus = "trialing"
151
+	BillingSubscriptionStatusActive     BillingSubscriptionStatus = "active"
152
+	BillingSubscriptionStatusPastDue    BillingSubscriptionStatus = "past_due"
153
+	BillingSubscriptionStatusCanceled   BillingSubscriptionStatus = "canceled"
154
+	BillingSubscriptionStatusUnpaid     BillingSubscriptionStatus = "unpaid"
155
+	BillingSubscriptionStatusPaused     BillingSubscriptionStatus = "paused"
156
+)
157
+
158
+func (e *BillingSubscriptionStatus) Scan(src interface{}) error {
159
+	switch s := src.(type) {
160
+	case []byte:
161
+		*e = BillingSubscriptionStatus(s)
162
+	case string:
163
+		*e = BillingSubscriptionStatus(s)
164
+	default:
165
+		return fmt.Errorf("unsupported scan type for BillingSubscriptionStatus: %T", src)
166
+	}
167
+	return nil
168
+}
169
+
170
+type NullBillingSubscriptionStatus struct {
171
+	BillingSubscriptionStatus BillingSubscriptionStatus
172
+	Valid                     bool // Valid is true if BillingSubscriptionStatus is not NULL
173
+}
174
+
175
+// Scan implements the Scanner interface.
176
+func (ns *NullBillingSubscriptionStatus) Scan(value interface{}) error {
177
+	if value == nil {
178
+		ns.BillingSubscriptionStatus, ns.Valid = "", false
179
+		return nil
180
+	}
181
+	ns.Valid = true
182
+	return ns.BillingSubscriptionStatus.Scan(value)
183
+}
184
+
185
+// Value implements the driver Valuer interface.
186
+func (ns NullBillingSubscriptionStatus) Value() (driver.Value, error) {
187
+	if !ns.Valid {
188
+		return nil, nil
189
+	}
190
+	return string(ns.BillingSubscriptionStatus), nil
191
+}
192
+
15193
 type CheckConclusion string
16194
 
17195
 const (
@@ -1601,6 +1779,54 @@ type AuthThrottle struct {
16011779
 	WindowStartedAt pgtype.Timestamptz
16021780
 }
16031781
 
1782
+type BillingInvoice struct {
1783
+	ID                   int64
1784
+	OrgID                int64
1785
+	Provider             BillingProvider
1786
+	StripeInvoiceID      string
1787
+	StripeCustomerID     string
1788
+	StripeSubscriptionID pgtype.Text
1789
+	Status               BillingInvoiceStatus
1790
+	Number               string
1791
+	Currency             string
1792
+	AmountDueCents       int64
1793
+	AmountPaidCents      int64
1794
+	AmountRemainingCents int64
1795
+	HostedInvoiceUrl     string
1796
+	InvoicePdfUrl        string
1797
+	PeriodStart          pgtype.Timestamptz
1798
+	PeriodEnd            pgtype.Timestamptz
1799
+	DueAt                pgtype.Timestamptz
1800
+	PaidAt               pgtype.Timestamptz
1801
+	VoidedAt             pgtype.Timestamptz
1802
+	CreatedAt            pgtype.Timestamptz
1803
+	UpdatedAt            pgtype.Timestamptz
1804
+}
1805
+
1806
+type BillingSeatSnapshot struct {
1807
+	ID                   int64
1808
+	OrgID                int64
1809
+	Provider             BillingProvider
1810
+	StripeSubscriptionID pgtype.Text
1811
+	ActiveMembers        int32
1812
+	BillableSeats        int32
1813
+	Source               string
1814
+	CapturedAt           pgtype.Timestamptz
1815
+}
1816
+
1817
+type BillingWebhookEvent struct {
1818
+	ID                 int64
1819
+	Provider           BillingProvider
1820
+	ProviderEventID    string
1821
+	EventType          string
1822
+	ApiVersion         string
1823
+	Payload            []byte
1824
+	ReceivedAt         pgtype.Timestamptz
1825
+	ProcessedAt        pgtype.Timestamptz
1826
+	ProcessError       string
1827
+	ProcessingAttempts int32
1828
+}
1829
+
16041830
 type BranchProtectionRule struct {
16051831
 	ID                             int64
16061832
 	RepoID                         int64
@@ -1870,6 +2096,30 @@ type Org struct {
18702096
 	UpdatedAt             pgtype.Timestamptz
18712097
 }
18722098
 
2099
+type OrgBillingState struct {
2100
+	OrgID                    int64
2101
+	Provider                 BillingProvider
2102
+	StripeCustomerID         pgtype.Text
2103
+	StripeSubscriptionID     pgtype.Text
2104
+	StripeSubscriptionItemID pgtype.Text
2105
+	Plan                     OrgPlan
2106
+	SubscriptionStatus       BillingSubscriptionStatus
2107
+	BillableSeats            int32
2108
+	SeatSnapshotAt           pgtype.Timestamptz
2109
+	CurrentPeriodStart       pgtype.Timestamptz
2110
+	CurrentPeriodEnd         pgtype.Timestamptz
2111
+	CancelAtPeriodEnd        bool
2112
+	TrialEnd                 pgtype.Timestamptz
2113
+	PastDueAt                pgtype.Timestamptz
2114
+	CanceledAt               pgtype.Timestamptz
2115
+	LockedAt                 pgtype.Timestamptz
2116
+	LockReason               NullBillingLockReason
2117
+	GraceUntil               pgtype.Timestamptz
2118
+	LastWebhookEventID       string
2119
+	CreatedAt                pgtype.Timestamptz
2120
+	UpdatedAt                pgtype.Timestamptz
2121
+}
2122
+
18732123
 type OrgGithubImport struct {
18742124
 	ID                int64
18752125
 	OrgID             int64
internal/billing/sqlc/querier.goadded
@@ -0,0 +1,32 @@
1
+// Code generated by sqlc. DO NOT EDIT.
2
+// versions:
3
+//   sqlc v1.31.1
4
+
5
+package billingdb
6
+
7
+import (
8
+	"context"
9
+)
10
+
11
+type Querier interface {
12
+	ApplySubscriptionSnapshot(ctx context.Context, db DBTX, arg ApplySubscriptionSnapshotParams) (ApplySubscriptionSnapshotRow, error)
13
+	ClearBillingLock(ctx context.Context, db DBTX, orgID int64) (ClearBillingLockRow, error)
14
+	// ─── billing_seat_snapshots ────────────────────────────────────────
15
+	CreateSeatSnapshot(ctx context.Context, db DBTX, arg CreateSeatSnapshotParams) (CreateSeatSnapshotRow, error)
16
+	// ─── billing_webhook_events ────────────────────────────────────────
17
+	CreateWebhookEventReceipt(ctx context.Context, db DBTX, arg CreateWebhookEventReceiptParams) (BillingWebhookEvent, error)
18
+	// SPDX-License-Identifier: AGPL-3.0-or-later
19
+	// ─── org_billing_states ────────────────────────────────────────────
20
+	GetOrgBillingState(ctx context.Context, db DBTX, orgID int64) (OrgBillingState, error)
21
+	ListInvoicesForOrg(ctx context.Context, db DBTX, arg ListInvoicesForOrgParams) ([]BillingInvoice, error)
22
+	ListSeatSnapshotsForOrg(ctx context.Context, db DBTX, arg ListSeatSnapshotsForOrgParams) ([]BillingSeatSnapshot, error)
23
+	MarkCanceled(ctx context.Context, db DBTX, arg MarkCanceledParams) (MarkCanceledRow, error)
24
+	MarkPastDue(ctx context.Context, db DBTX, arg MarkPastDueParams) (OrgBillingState, error)
25
+	MarkWebhookEventFailed(ctx context.Context, db DBTX, arg MarkWebhookEventFailedParams) (BillingWebhookEvent, error)
26
+	MarkWebhookEventProcessed(ctx context.Context, db DBTX, providerEventID string) (BillingWebhookEvent, error)
27
+	SetStripeCustomer(ctx context.Context, db DBTX, arg SetStripeCustomerParams) (OrgBillingState, error)
28
+	// ─── billing_invoices ──────────────────────────────────────────────
29
+	UpsertInvoice(ctx context.Context, db DBTX, arg UpsertInvoiceParams) (BillingInvoice, error)
30
+}
31
+
32
+var _ Querier = (*Queries)(nil)
internal/checks/sqlc/models.gomodified
@@ -12,6 +12,184 @@ import (
1212
 	"github.com/jackc/pgx/v5/pgtype"
1313
 )
1414
 
15
+type BillingInvoiceStatus string
16
+
17
+const (
18
+	BillingInvoiceStatusDraft         BillingInvoiceStatus = "draft"
19
+	BillingInvoiceStatusOpen          BillingInvoiceStatus = "open"
20
+	BillingInvoiceStatusPaid          BillingInvoiceStatus = "paid"
21
+	BillingInvoiceStatusVoid          BillingInvoiceStatus = "void"
22
+	BillingInvoiceStatusUncollectible BillingInvoiceStatus = "uncollectible"
23
+)
24
+
25
+func (e *BillingInvoiceStatus) Scan(src interface{}) error {
26
+	switch s := src.(type) {
27
+	case []byte:
28
+		*e = BillingInvoiceStatus(s)
29
+	case string:
30
+		*e = BillingInvoiceStatus(s)
31
+	default:
32
+		return fmt.Errorf("unsupported scan type for BillingInvoiceStatus: %T", src)
33
+	}
34
+	return nil
35
+}
36
+
37
+type NullBillingInvoiceStatus struct {
38
+	BillingInvoiceStatus BillingInvoiceStatus
39
+	Valid                bool // Valid is true if BillingInvoiceStatus is not NULL
40
+}
41
+
42
+// Scan implements the Scanner interface.
43
+func (ns *NullBillingInvoiceStatus) Scan(value interface{}) error {
44
+	if value == nil {
45
+		ns.BillingInvoiceStatus, ns.Valid = "", false
46
+		return nil
47
+	}
48
+	ns.Valid = true
49
+	return ns.BillingInvoiceStatus.Scan(value)
50
+}
51
+
52
+// Value implements the driver Valuer interface.
53
+func (ns NullBillingInvoiceStatus) Value() (driver.Value, error) {
54
+	if !ns.Valid {
55
+		return nil, nil
56
+	}
57
+	return string(ns.BillingInvoiceStatus), nil
58
+}
59
+
60
+type BillingLockReason string
61
+
62
+const (
63
+	BillingLockReasonPastDue  BillingLockReason = "past_due"
64
+	BillingLockReasonCanceled BillingLockReason = "canceled"
65
+	BillingLockReasonUnpaid   BillingLockReason = "unpaid"
66
+	BillingLockReasonManual   BillingLockReason = "manual"
67
+)
68
+
69
+func (e *BillingLockReason) Scan(src interface{}) error {
70
+	switch s := src.(type) {
71
+	case []byte:
72
+		*e = BillingLockReason(s)
73
+	case string:
74
+		*e = BillingLockReason(s)
75
+	default:
76
+		return fmt.Errorf("unsupported scan type for BillingLockReason: %T", src)
77
+	}
78
+	return nil
79
+}
80
+
81
+type NullBillingLockReason struct {
82
+	BillingLockReason BillingLockReason
83
+	Valid             bool // Valid is true if BillingLockReason is not NULL
84
+}
85
+
86
+// Scan implements the Scanner interface.
87
+func (ns *NullBillingLockReason) Scan(value interface{}) error {
88
+	if value == nil {
89
+		ns.BillingLockReason, ns.Valid = "", false
90
+		return nil
91
+	}
92
+	ns.Valid = true
93
+	return ns.BillingLockReason.Scan(value)
94
+}
95
+
96
+// Value implements the driver Valuer interface.
97
+func (ns NullBillingLockReason) Value() (driver.Value, error) {
98
+	if !ns.Valid {
99
+		return nil, nil
100
+	}
101
+	return string(ns.BillingLockReason), nil
102
+}
103
+
104
+type BillingProvider string
105
+
106
+const (
107
+	BillingProviderStripe BillingProvider = "stripe"
108
+)
109
+
110
+func (e *BillingProvider) Scan(src interface{}) error {
111
+	switch s := src.(type) {
112
+	case []byte:
113
+		*e = BillingProvider(s)
114
+	case string:
115
+		*e = BillingProvider(s)
116
+	default:
117
+		return fmt.Errorf("unsupported scan type for BillingProvider: %T", src)
118
+	}
119
+	return nil
120
+}
121
+
122
+type NullBillingProvider struct {
123
+	BillingProvider BillingProvider
124
+	Valid           bool // Valid is true if BillingProvider is not NULL
125
+}
126
+
127
+// Scan implements the Scanner interface.
128
+func (ns *NullBillingProvider) Scan(value interface{}) error {
129
+	if value == nil {
130
+		ns.BillingProvider, ns.Valid = "", false
131
+		return nil
132
+	}
133
+	ns.Valid = true
134
+	return ns.BillingProvider.Scan(value)
135
+}
136
+
137
+// Value implements the driver Valuer interface.
138
+func (ns NullBillingProvider) Value() (driver.Value, error) {
139
+	if !ns.Valid {
140
+		return nil, nil
141
+	}
142
+	return string(ns.BillingProvider), nil
143
+}
144
+
145
+type BillingSubscriptionStatus string
146
+
147
+const (
148
+	BillingSubscriptionStatusNone       BillingSubscriptionStatus = "none"
149
+	BillingSubscriptionStatusIncomplete BillingSubscriptionStatus = "incomplete"
150
+	BillingSubscriptionStatusTrialing   BillingSubscriptionStatus = "trialing"
151
+	BillingSubscriptionStatusActive     BillingSubscriptionStatus = "active"
152
+	BillingSubscriptionStatusPastDue    BillingSubscriptionStatus = "past_due"
153
+	BillingSubscriptionStatusCanceled   BillingSubscriptionStatus = "canceled"
154
+	BillingSubscriptionStatusUnpaid     BillingSubscriptionStatus = "unpaid"
155
+	BillingSubscriptionStatusPaused     BillingSubscriptionStatus = "paused"
156
+)
157
+
158
+func (e *BillingSubscriptionStatus) Scan(src interface{}) error {
159
+	switch s := src.(type) {
160
+	case []byte:
161
+		*e = BillingSubscriptionStatus(s)
162
+	case string:
163
+		*e = BillingSubscriptionStatus(s)
164
+	default:
165
+		return fmt.Errorf("unsupported scan type for BillingSubscriptionStatus: %T", src)
166
+	}
167
+	return nil
168
+}
169
+
170
+type NullBillingSubscriptionStatus struct {
171
+	BillingSubscriptionStatus BillingSubscriptionStatus
172
+	Valid                     bool // Valid is true if BillingSubscriptionStatus is not NULL
173
+}
174
+
175
+// Scan implements the Scanner interface.
176
+func (ns *NullBillingSubscriptionStatus) Scan(value interface{}) error {
177
+	if value == nil {
178
+		ns.BillingSubscriptionStatus, ns.Valid = "", false
179
+		return nil
180
+	}
181
+	ns.Valid = true
182
+	return ns.BillingSubscriptionStatus.Scan(value)
183
+}
184
+
185
+// Value implements the driver Valuer interface.
186
+func (ns NullBillingSubscriptionStatus) Value() (driver.Value, error) {
187
+	if !ns.Valid {
188
+		return nil, nil
189
+	}
190
+	return string(ns.BillingSubscriptionStatus), nil
191
+}
192
+
15193
 type CheckConclusion string
16194
 
17195
 const (
@@ -1601,6 +1779,54 @@ type AuthThrottle struct {
16011779
 	WindowStartedAt pgtype.Timestamptz
16021780
 }
16031781
 
1782
+type BillingInvoice struct {
1783
+	ID                   int64
1784
+	OrgID                int64
1785
+	Provider             BillingProvider
1786
+	StripeInvoiceID      string
1787
+	StripeCustomerID     string
1788
+	StripeSubscriptionID pgtype.Text
1789
+	Status               BillingInvoiceStatus
1790
+	Number               string
1791
+	Currency             string
1792
+	AmountDueCents       int64
1793
+	AmountPaidCents      int64
1794
+	AmountRemainingCents int64
1795
+	HostedInvoiceUrl     string
1796
+	InvoicePdfUrl        string
1797
+	PeriodStart          pgtype.Timestamptz
1798
+	PeriodEnd            pgtype.Timestamptz
1799
+	DueAt                pgtype.Timestamptz
1800
+	PaidAt               pgtype.Timestamptz
1801
+	VoidedAt             pgtype.Timestamptz
1802
+	CreatedAt            pgtype.Timestamptz
1803
+	UpdatedAt            pgtype.Timestamptz
1804
+}
1805
+
1806
+type BillingSeatSnapshot struct {
1807
+	ID                   int64
1808
+	OrgID                int64
1809
+	Provider             BillingProvider
1810
+	StripeSubscriptionID pgtype.Text
1811
+	ActiveMembers        int32
1812
+	BillableSeats        int32
1813
+	Source               string
1814
+	CapturedAt           pgtype.Timestamptz
1815
+}
1816
+
1817
+type BillingWebhookEvent struct {
1818
+	ID                 int64
1819
+	Provider           BillingProvider
1820
+	ProviderEventID    string
1821
+	EventType          string
1822
+	ApiVersion         string
1823
+	Payload            []byte
1824
+	ReceivedAt         pgtype.Timestamptz
1825
+	ProcessedAt        pgtype.Timestamptz
1826
+	ProcessError       string
1827
+	ProcessingAttempts int32
1828
+}
1829
+
16041830
 type BranchProtectionRule struct {
16051831
 	ID                             int64
16061832
 	RepoID                         int64
@@ -1870,6 +2096,30 @@ type Org struct {
18702096
 	UpdatedAt             pgtype.Timestamptz
18712097
 }
18722098
 
2099
+type OrgBillingState struct {
2100
+	OrgID                    int64
2101
+	Provider                 BillingProvider
2102
+	StripeCustomerID         pgtype.Text
2103
+	StripeSubscriptionID     pgtype.Text
2104
+	StripeSubscriptionItemID pgtype.Text
2105
+	Plan                     OrgPlan
2106
+	SubscriptionStatus       BillingSubscriptionStatus
2107
+	BillableSeats            int32
2108
+	SeatSnapshotAt           pgtype.Timestamptz
2109
+	CurrentPeriodStart       pgtype.Timestamptz
2110
+	CurrentPeriodEnd         pgtype.Timestamptz
2111
+	CancelAtPeriodEnd        bool
2112
+	TrialEnd                 pgtype.Timestamptz
2113
+	PastDueAt                pgtype.Timestamptz
2114
+	CanceledAt               pgtype.Timestamptz
2115
+	LockedAt                 pgtype.Timestamptz
2116
+	LockReason               NullBillingLockReason
2117
+	GraceUntil               pgtype.Timestamptz
2118
+	LastWebhookEventID       string
2119
+	CreatedAt                pgtype.Timestamptz
2120
+	UpdatedAt                pgtype.Timestamptz
2121
+}
2122
+
18732123
 type OrgGithubImport struct {
18742124
 	ID                int64
18752125
 	OrgID             int64
internal/issues/sqlc/models.gomodified
@@ -12,6 +12,184 @@ import (
1212
 	"github.com/jackc/pgx/v5/pgtype"
1313
 )
1414
 
15
+type BillingInvoiceStatus string
16
+
17
+const (
18
+	BillingInvoiceStatusDraft         BillingInvoiceStatus = "draft"
19
+	BillingInvoiceStatusOpen          BillingInvoiceStatus = "open"
20
+	BillingInvoiceStatusPaid          BillingInvoiceStatus = "paid"
21
+	BillingInvoiceStatusVoid          BillingInvoiceStatus = "void"
22
+	BillingInvoiceStatusUncollectible BillingInvoiceStatus = "uncollectible"
23
+)
24
+
25
+func (e *BillingInvoiceStatus) Scan(src interface{}) error {
26
+	switch s := src.(type) {
27
+	case []byte:
28
+		*e = BillingInvoiceStatus(s)
29
+	case string:
30
+		*e = BillingInvoiceStatus(s)
31
+	default:
32
+		return fmt.Errorf("unsupported scan type for BillingInvoiceStatus: %T", src)
33
+	}
34
+	return nil
35
+}
36
+
37
+type NullBillingInvoiceStatus struct {
38
+	BillingInvoiceStatus BillingInvoiceStatus
39
+	Valid                bool // Valid is true if BillingInvoiceStatus is not NULL
40
+}
41
+
42
+// Scan implements the Scanner interface.
43
+func (ns *NullBillingInvoiceStatus) Scan(value interface{}) error {
44
+	if value == nil {
45
+		ns.BillingInvoiceStatus, ns.Valid = "", false
46
+		return nil
47
+	}
48
+	ns.Valid = true
49
+	return ns.BillingInvoiceStatus.Scan(value)
50
+}
51
+
52
+// Value implements the driver Valuer interface.
53
+func (ns NullBillingInvoiceStatus) Value() (driver.Value, error) {
54
+	if !ns.Valid {
55
+		return nil, nil
56
+	}
57
+	return string(ns.BillingInvoiceStatus), nil
58
+}
59
+
60
+type BillingLockReason string
61
+
62
+const (
63
+	BillingLockReasonPastDue  BillingLockReason = "past_due"
64
+	BillingLockReasonCanceled BillingLockReason = "canceled"
65
+	BillingLockReasonUnpaid   BillingLockReason = "unpaid"
66
+	BillingLockReasonManual   BillingLockReason = "manual"
67
+)
68
+
69
+func (e *BillingLockReason) Scan(src interface{}) error {
70
+	switch s := src.(type) {
71
+	case []byte:
72
+		*e = BillingLockReason(s)
73
+	case string:
74
+		*e = BillingLockReason(s)
75
+	default:
76
+		return fmt.Errorf("unsupported scan type for BillingLockReason: %T", src)
77
+	}
78
+	return nil
79
+}
80
+
81
+type NullBillingLockReason struct {
82
+	BillingLockReason BillingLockReason
83
+	Valid             bool // Valid is true if BillingLockReason is not NULL
84
+}
85
+
86
+// Scan implements the Scanner interface.
87
+func (ns *NullBillingLockReason) Scan(value interface{}) error {
88
+	if value == nil {
89
+		ns.BillingLockReason, ns.Valid = "", false
90
+		return nil
91
+	}
92
+	ns.Valid = true
93
+	return ns.BillingLockReason.Scan(value)
94
+}
95
+
96
+// Value implements the driver Valuer interface.
97
+func (ns NullBillingLockReason) Value() (driver.Value, error) {
98
+	if !ns.Valid {
99
+		return nil, nil
100
+	}
101
+	return string(ns.BillingLockReason), nil
102
+}
103
+
104
+type BillingProvider string
105
+
106
+const (
107
+	BillingProviderStripe BillingProvider = "stripe"
108
+)
109
+
110
+func (e *BillingProvider) Scan(src interface{}) error {
111
+	switch s := src.(type) {
112
+	case []byte:
113
+		*e = BillingProvider(s)
114
+	case string:
115
+		*e = BillingProvider(s)
116
+	default:
117
+		return fmt.Errorf("unsupported scan type for BillingProvider: %T", src)
118
+	}
119
+	return nil
120
+}
121
+
122
+type NullBillingProvider struct {
123
+	BillingProvider BillingProvider
124
+	Valid           bool // Valid is true if BillingProvider is not NULL
125
+}
126
+
127
+// Scan implements the Scanner interface.
128
+func (ns *NullBillingProvider) Scan(value interface{}) error {
129
+	if value == nil {
130
+		ns.BillingProvider, ns.Valid = "", false
131
+		return nil
132
+	}
133
+	ns.Valid = true
134
+	return ns.BillingProvider.Scan(value)
135
+}
136
+
137
+// Value implements the driver Valuer interface.
138
+func (ns NullBillingProvider) Value() (driver.Value, error) {
139
+	if !ns.Valid {
140
+		return nil, nil
141
+	}
142
+	return string(ns.BillingProvider), nil
143
+}
144
+
145
+type BillingSubscriptionStatus string
146
+
147
+const (
148
+	BillingSubscriptionStatusNone       BillingSubscriptionStatus = "none"
149
+	BillingSubscriptionStatusIncomplete BillingSubscriptionStatus = "incomplete"
150
+	BillingSubscriptionStatusTrialing   BillingSubscriptionStatus = "trialing"
151
+	BillingSubscriptionStatusActive     BillingSubscriptionStatus = "active"
152
+	BillingSubscriptionStatusPastDue    BillingSubscriptionStatus = "past_due"
153
+	BillingSubscriptionStatusCanceled   BillingSubscriptionStatus = "canceled"
154
+	BillingSubscriptionStatusUnpaid     BillingSubscriptionStatus = "unpaid"
155
+	BillingSubscriptionStatusPaused     BillingSubscriptionStatus = "paused"
156
+)
157
+
158
+func (e *BillingSubscriptionStatus) Scan(src interface{}) error {
159
+	switch s := src.(type) {
160
+	case []byte:
161
+		*e = BillingSubscriptionStatus(s)
162
+	case string:
163
+		*e = BillingSubscriptionStatus(s)
164
+	default:
165
+		return fmt.Errorf("unsupported scan type for BillingSubscriptionStatus: %T", src)
166
+	}
167
+	return nil
168
+}
169
+
170
+type NullBillingSubscriptionStatus struct {
171
+	BillingSubscriptionStatus BillingSubscriptionStatus
172
+	Valid                     bool // Valid is true if BillingSubscriptionStatus is not NULL
173
+}
174
+
175
+// Scan implements the Scanner interface.
176
+func (ns *NullBillingSubscriptionStatus) Scan(value interface{}) error {
177
+	if value == nil {
178
+		ns.BillingSubscriptionStatus, ns.Valid = "", false
179
+		return nil
180
+	}
181
+	ns.Valid = true
182
+	return ns.BillingSubscriptionStatus.Scan(value)
183
+}
184
+
185
+// Value implements the driver Valuer interface.
186
+func (ns NullBillingSubscriptionStatus) Value() (driver.Value, error) {
187
+	if !ns.Valid {
188
+		return nil, nil
189
+	}
190
+	return string(ns.BillingSubscriptionStatus), nil
191
+}
192
+
15193
 type CheckConclusion string
16194
 
17195
 const (
@@ -1601,6 +1779,54 @@ type AuthThrottle struct {
16011779
 	WindowStartedAt pgtype.Timestamptz
16021780
 }
16031781
 
1782
+type BillingInvoice struct {
1783
+	ID                   int64
1784
+	OrgID                int64
1785
+	Provider             BillingProvider
1786
+	StripeInvoiceID      string
1787
+	StripeCustomerID     string
1788
+	StripeSubscriptionID pgtype.Text
1789
+	Status               BillingInvoiceStatus
1790
+	Number               string
1791
+	Currency             string
1792
+	AmountDueCents       int64
1793
+	AmountPaidCents      int64
1794
+	AmountRemainingCents int64
1795
+	HostedInvoiceUrl     string
1796
+	InvoicePdfUrl        string
1797
+	PeriodStart          pgtype.Timestamptz
1798
+	PeriodEnd            pgtype.Timestamptz
1799
+	DueAt                pgtype.Timestamptz
1800
+	PaidAt               pgtype.Timestamptz
1801
+	VoidedAt             pgtype.Timestamptz
1802
+	CreatedAt            pgtype.Timestamptz
1803
+	UpdatedAt            pgtype.Timestamptz
1804
+}
1805
+
1806
+type BillingSeatSnapshot struct {
1807
+	ID                   int64
1808
+	OrgID                int64
1809
+	Provider             BillingProvider
1810
+	StripeSubscriptionID pgtype.Text
1811
+	ActiveMembers        int32
1812
+	BillableSeats        int32
1813
+	Source               string
1814
+	CapturedAt           pgtype.Timestamptz
1815
+}
1816
+
1817
+type BillingWebhookEvent struct {
1818
+	ID                 int64
1819
+	Provider           BillingProvider
1820
+	ProviderEventID    string
1821
+	EventType          string
1822
+	ApiVersion         string
1823
+	Payload            []byte
1824
+	ReceivedAt         pgtype.Timestamptz
1825
+	ProcessedAt        pgtype.Timestamptz
1826
+	ProcessError       string
1827
+	ProcessingAttempts int32
1828
+}
1829
+
16041830
 type BranchProtectionRule struct {
16051831
 	ID                             int64
16061832
 	RepoID                         int64
@@ -1870,6 +2096,30 @@ type Org struct {
18702096
 	UpdatedAt             pgtype.Timestamptz
18712097
 }
18722098
 
2099
+type OrgBillingState struct {
2100
+	OrgID                    int64
2101
+	Provider                 BillingProvider
2102
+	StripeCustomerID         pgtype.Text
2103
+	StripeSubscriptionID     pgtype.Text
2104
+	StripeSubscriptionItemID pgtype.Text
2105
+	Plan                     OrgPlan
2106
+	SubscriptionStatus       BillingSubscriptionStatus
2107
+	BillableSeats            int32
2108
+	SeatSnapshotAt           pgtype.Timestamptz
2109
+	CurrentPeriodStart       pgtype.Timestamptz
2110
+	CurrentPeriodEnd         pgtype.Timestamptz
2111
+	CancelAtPeriodEnd        bool
2112
+	TrialEnd                 pgtype.Timestamptz
2113
+	PastDueAt                pgtype.Timestamptz
2114
+	CanceledAt               pgtype.Timestamptz
2115
+	LockedAt                 pgtype.Timestamptz
2116
+	LockReason               NullBillingLockReason
2117
+	GraceUntil               pgtype.Timestamptz
2118
+	LastWebhookEventID       string
2119
+	CreatedAt                pgtype.Timestamptz
2120
+	UpdatedAt                pgtype.Timestamptz
2121
+}
2122
+
18732123
 type OrgGithubImport struct {
18742124
 	ID                int64
18752125
 	OrgID             int64
internal/meta/sqlc/models.gomodified
@@ -12,6 +12,184 @@ import (
1212
 	"github.com/jackc/pgx/v5/pgtype"
1313
 )
1414
 
15
+type BillingInvoiceStatus string
16
+
17
+const (
18
+	BillingInvoiceStatusDraft         BillingInvoiceStatus = "draft"
19
+	BillingInvoiceStatusOpen          BillingInvoiceStatus = "open"
20
+	BillingInvoiceStatusPaid          BillingInvoiceStatus = "paid"
21
+	BillingInvoiceStatusVoid          BillingInvoiceStatus = "void"
22
+	BillingInvoiceStatusUncollectible BillingInvoiceStatus = "uncollectible"
23
+)
24
+
25
+func (e *BillingInvoiceStatus) Scan(src interface{}) error {
26
+	switch s := src.(type) {
27
+	case []byte:
28
+		*e = BillingInvoiceStatus(s)
29
+	case string:
30
+		*e = BillingInvoiceStatus(s)
31
+	default:
32
+		return fmt.Errorf("unsupported scan type for BillingInvoiceStatus: %T", src)
33
+	}
34
+	return nil
35
+}
36
+
37
+type NullBillingInvoiceStatus struct {
38
+	BillingInvoiceStatus BillingInvoiceStatus
39
+	Valid                bool // Valid is true if BillingInvoiceStatus is not NULL
40
+}
41
+
42
+// Scan implements the Scanner interface.
43
+func (ns *NullBillingInvoiceStatus) Scan(value interface{}) error {
44
+	if value == nil {
45
+		ns.BillingInvoiceStatus, ns.Valid = "", false
46
+		return nil
47
+	}
48
+	ns.Valid = true
49
+	return ns.BillingInvoiceStatus.Scan(value)
50
+}
51
+
52
+// Value implements the driver Valuer interface.
53
+func (ns NullBillingInvoiceStatus) Value() (driver.Value, error) {
54
+	if !ns.Valid {
55
+		return nil, nil
56
+	}
57
+	return string(ns.BillingInvoiceStatus), nil
58
+}
59
+
60
+type BillingLockReason string
61
+
62
+const (
63
+	BillingLockReasonPastDue  BillingLockReason = "past_due"
64
+	BillingLockReasonCanceled BillingLockReason = "canceled"
65
+	BillingLockReasonUnpaid   BillingLockReason = "unpaid"
66
+	BillingLockReasonManual   BillingLockReason = "manual"
67
+)
68
+
69
+func (e *BillingLockReason) Scan(src interface{}) error {
70
+	switch s := src.(type) {
71
+	case []byte:
72
+		*e = BillingLockReason(s)
73
+	case string:
74
+		*e = BillingLockReason(s)
75
+	default:
76
+		return fmt.Errorf("unsupported scan type for BillingLockReason: %T", src)
77
+	}
78
+	return nil
79
+}
80
+
81
+type NullBillingLockReason struct {
82
+	BillingLockReason BillingLockReason
83
+	Valid             bool // Valid is true if BillingLockReason is not NULL
84
+}
85
+
86
+// Scan implements the Scanner interface.
87
+func (ns *NullBillingLockReason) Scan(value interface{}) error {
88
+	if value == nil {
89
+		ns.BillingLockReason, ns.Valid = "", false
90
+		return nil
91
+	}
92
+	ns.Valid = true
93
+	return ns.BillingLockReason.Scan(value)
94
+}
95
+
96
+// Value implements the driver Valuer interface.
97
+func (ns NullBillingLockReason) Value() (driver.Value, error) {
98
+	if !ns.Valid {
99
+		return nil, nil
100
+	}
101
+	return string(ns.BillingLockReason), nil
102
+}
103
+
104
+type BillingProvider string
105
+
106
+const (
107
+	BillingProviderStripe BillingProvider = "stripe"
108
+)
109
+
110
+func (e *BillingProvider) Scan(src interface{}) error {
111
+	switch s := src.(type) {
112
+	case []byte:
113
+		*e = BillingProvider(s)
114
+	case string:
115
+		*e = BillingProvider(s)
116
+	default:
117
+		return fmt.Errorf("unsupported scan type for BillingProvider: %T", src)
118
+	}
119
+	return nil
120
+}
121
+
122
+type NullBillingProvider struct {
123
+	BillingProvider BillingProvider
124
+	Valid           bool // Valid is true if BillingProvider is not NULL
125
+}
126
+
127
+// Scan implements the Scanner interface.
128
+func (ns *NullBillingProvider) Scan(value interface{}) error {
129
+	if value == nil {
130
+		ns.BillingProvider, ns.Valid = "", false
131
+		return nil
132
+	}
133
+	ns.Valid = true
134
+	return ns.BillingProvider.Scan(value)
135
+}
136
+
137
+// Value implements the driver Valuer interface.
138
+func (ns NullBillingProvider) Value() (driver.Value, error) {
139
+	if !ns.Valid {
140
+		return nil, nil
141
+	}
142
+	return string(ns.BillingProvider), nil
143
+}
144
+
145
+type BillingSubscriptionStatus string
146
+
147
+const (
148
+	BillingSubscriptionStatusNone       BillingSubscriptionStatus = "none"
149
+	BillingSubscriptionStatusIncomplete BillingSubscriptionStatus = "incomplete"
150
+	BillingSubscriptionStatusTrialing   BillingSubscriptionStatus = "trialing"
151
+	BillingSubscriptionStatusActive     BillingSubscriptionStatus = "active"
152
+	BillingSubscriptionStatusPastDue    BillingSubscriptionStatus = "past_due"
153
+	BillingSubscriptionStatusCanceled   BillingSubscriptionStatus = "canceled"
154
+	BillingSubscriptionStatusUnpaid     BillingSubscriptionStatus = "unpaid"
155
+	BillingSubscriptionStatusPaused     BillingSubscriptionStatus = "paused"
156
+)
157
+
158
+func (e *BillingSubscriptionStatus) Scan(src interface{}) error {
159
+	switch s := src.(type) {
160
+	case []byte:
161
+		*e = BillingSubscriptionStatus(s)
162
+	case string:
163
+		*e = BillingSubscriptionStatus(s)
164
+	default:
165
+		return fmt.Errorf("unsupported scan type for BillingSubscriptionStatus: %T", src)
166
+	}
167
+	return nil
168
+}
169
+
170
+type NullBillingSubscriptionStatus struct {
171
+	BillingSubscriptionStatus BillingSubscriptionStatus
172
+	Valid                     bool // Valid is true if BillingSubscriptionStatus is not NULL
173
+}
174
+
175
+// Scan implements the Scanner interface.
176
+func (ns *NullBillingSubscriptionStatus) Scan(value interface{}) error {
177
+	if value == nil {
178
+		ns.BillingSubscriptionStatus, ns.Valid = "", false
179
+		return nil
180
+	}
181
+	ns.Valid = true
182
+	return ns.BillingSubscriptionStatus.Scan(value)
183
+}
184
+
185
+// Value implements the driver Valuer interface.
186
+func (ns NullBillingSubscriptionStatus) Value() (driver.Value, error) {
187
+	if !ns.Valid {
188
+		return nil, nil
189
+	}
190
+	return string(ns.BillingSubscriptionStatus), nil
191
+}
192
+
15193
 type CheckConclusion string
16194
 
17195
 const (
@@ -1601,6 +1779,54 @@ type AuthThrottle struct {
16011779
 	WindowStartedAt pgtype.Timestamptz
16021780
 }
16031781
 
1782
+type BillingInvoice struct {
1783
+	ID                   int64
1784
+	OrgID                int64
1785
+	Provider             BillingProvider
1786
+	StripeInvoiceID      string
1787
+	StripeCustomerID     string
1788
+	StripeSubscriptionID pgtype.Text
1789
+	Status               BillingInvoiceStatus
1790
+	Number               string
1791
+	Currency             string
1792
+	AmountDueCents       int64
1793
+	AmountPaidCents      int64
1794
+	AmountRemainingCents int64
1795
+	HostedInvoiceUrl     string
1796
+	InvoicePdfUrl        string
1797
+	PeriodStart          pgtype.Timestamptz
1798
+	PeriodEnd            pgtype.Timestamptz
1799
+	DueAt                pgtype.Timestamptz
1800
+	PaidAt               pgtype.Timestamptz
1801
+	VoidedAt             pgtype.Timestamptz
1802
+	CreatedAt            pgtype.Timestamptz
1803
+	UpdatedAt            pgtype.Timestamptz
1804
+}
1805
+
1806
+type BillingSeatSnapshot struct {
1807
+	ID                   int64
1808
+	OrgID                int64
1809
+	Provider             BillingProvider
1810
+	StripeSubscriptionID pgtype.Text
1811
+	ActiveMembers        int32
1812
+	BillableSeats        int32
1813
+	Source               string
1814
+	CapturedAt           pgtype.Timestamptz
1815
+}
1816
+
1817
+type BillingWebhookEvent struct {
1818
+	ID                 int64
1819
+	Provider           BillingProvider
1820
+	ProviderEventID    string
1821
+	EventType          string
1822
+	ApiVersion         string
1823
+	Payload            []byte
1824
+	ReceivedAt         pgtype.Timestamptz
1825
+	ProcessedAt        pgtype.Timestamptz
1826
+	ProcessError       string
1827
+	ProcessingAttempts int32
1828
+}
1829
+
16041830
 type BranchProtectionRule struct {
16051831
 	ID                             int64
16061832
 	RepoID                         int64
@@ -1870,6 +2096,30 @@ type Org struct {
18702096
 	UpdatedAt             pgtype.Timestamptz
18712097
 }
18722098
 
2099
+type OrgBillingState struct {
2100
+	OrgID                    int64
2101
+	Provider                 BillingProvider
2102
+	StripeCustomerID         pgtype.Text
2103
+	StripeSubscriptionID     pgtype.Text
2104
+	StripeSubscriptionItemID pgtype.Text
2105
+	Plan                     OrgPlan
2106
+	SubscriptionStatus       BillingSubscriptionStatus
2107
+	BillableSeats            int32
2108
+	SeatSnapshotAt           pgtype.Timestamptz
2109
+	CurrentPeriodStart       pgtype.Timestamptz
2110
+	CurrentPeriodEnd         pgtype.Timestamptz
2111
+	CancelAtPeriodEnd        bool
2112
+	TrialEnd                 pgtype.Timestamptz
2113
+	PastDueAt                pgtype.Timestamptz
2114
+	CanceledAt               pgtype.Timestamptz
2115
+	LockedAt                 pgtype.Timestamptz
2116
+	LockReason               NullBillingLockReason
2117
+	GraceUntil               pgtype.Timestamptz
2118
+	LastWebhookEventID       string
2119
+	CreatedAt                pgtype.Timestamptz
2120
+	UpdatedAt                pgtype.Timestamptz
2121
+}
2122
+
18732123
 type OrgGithubImport struct {
18742124
 	ID                int64
18752125
 	OrgID             int64
internal/migrationsfs/migrations/0061_billing_domain.sqladded
@@ -0,0 +1,252 @@
1
+-- SPDX-License-Identifier: AGPL-3.0-or-later
2
+--
3
+-- PAYMENTS SP02 — local billing domain.
4
+--
5
+-- Stripe remains the payment source of truth, but shithub needs local
6
+-- state for entitlement checks, UI summaries, idempotent webhook
7
+-- processing, and seat snapshots. These tables deliberately store
8
+-- provider IDs and invoice metadata only; card data never touches
9
+-- shithub.
10
+
11
+-- +goose Up
12
+
13
+CREATE TYPE billing_provider AS ENUM ('stripe');
14
+
15
+CREATE TYPE billing_subscription_status AS ENUM (
16
+    'none',
17
+    'incomplete',
18
+    'trialing',
19
+    'active',
20
+    'past_due',
21
+    'canceled',
22
+    'unpaid',
23
+    'paused'
24
+);
25
+
26
+CREATE TYPE billing_lock_reason AS ENUM (
27
+    'past_due',
28
+    'canceled',
29
+    'unpaid',
30
+    'manual'
31
+);
32
+
33
+CREATE TYPE billing_invoice_status AS ENUM (
34
+    'draft',
35
+    'open',
36
+    'paid',
37
+    'void',
38
+    'uncollectible'
39
+);
40
+
41
+CREATE TABLE org_billing_states (
42
+    org_id                      bigint                       PRIMARY KEY REFERENCES orgs(id) ON DELETE CASCADE,
43
+    provider                    billing_provider             NOT NULL DEFAULT 'stripe',
44
+    stripe_customer_id          text,
45
+    stripe_subscription_id      text,
46
+    stripe_subscription_item_id text,
47
+    plan                        org_plan                     NOT NULL DEFAULT 'free',
48
+    subscription_status         billing_subscription_status   NOT NULL DEFAULT 'none',
49
+    billable_seats              integer                      NOT NULL DEFAULT 0,
50
+    seat_snapshot_at            timestamptz,
51
+    current_period_start        timestamptz,
52
+    current_period_end          timestamptz,
53
+    cancel_at_period_end        boolean                      NOT NULL DEFAULT false,
54
+    trial_end                   timestamptz,
55
+    past_due_at                 timestamptz,
56
+    canceled_at                 timestamptz,
57
+    locked_at                   timestamptz,
58
+    lock_reason                 billing_lock_reason,
59
+    grace_until                 timestamptz,
60
+    last_webhook_event_id       text                          NOT NULL DEFAULT '',
61
+    created_at                  timestamptz                   NOT NULL DEFAULT now(),
62
+    updated_at                  timestamptz                   NOT NULL DEFAULT now(),
63
+
64
+    CONSTRAINT org_billing_states_seats_nonnegative CHECK (billable_seats >= 0),
65
+    CONSTRAINT org_billing_states_customer_id_not_blank CHECK (
66
+        stripe_customer_id IS NULL OR char_length(stripe_customer_id) > 0
67
+    ),
68
+    CONSTRAINT org_billing_states_subscription_id_not_blank CHECK (
69
+        stripe_subscription_id IS NULL OR char_length(stripe_subscription_id) > 0
70
+    ),
71
+    CONSTRAINT org_billing_states_subscription_item_id_not_blank CHECK (
72
+        stripe_subscription_item_id IS NULL OR char_length(stripe_subscription_item_id) > 0
73
+    ),
74
+    CONSTRAINT org_billing_states_lock_reason_requires_locked CHECK (
75
+        lock_reason IS NULL OR locked_at IS NOT NULL
76
+    ),
77
+    CONSTRAINT org_billing_states_grace_requires_locked CHECK (
78
+        grace_until IS NULL OR locked_at IS NOT NULL
79
+    ),
80
+    CONSTRAINT org_billing_states_period_order CHECK (
81
+        current_period_start IS NULL
82
+     OR current_period_end IS NULL
83
+     OR current_period_start <= current_period_end
84
+    )
85
+);
86
+
87
+CREATE UNIQUE INDEX org_billing_states_stripe_customer_unique
88
+    ON org_billing_states (stripe_customer_id)
89
+    WHERE stripe_customer_id IS NOT NULL;
90
+
91
+CREATE UNIQUE INDEX org_billing_states_stripe_subscription_unique
92
+    ON org_billing_states (stripe_subscription_id)
93
+    WHERE stripe_subscription_id IS NOT NULL;
94
+
95
+CREATE UNIQUE INDEX org_billing_states_stripe_subscription_item_unique
96
+    ON org_billing_states (stripe_subscription_item_id)
97
+    WHERE stripe_subscription_item_id IS NOT NULL;
98
+
99
+CREATE INDEX org_billing_states_status_idx
100
+    ON org_billing_states (subscription_status, updated_at DESC);
101
+
102
+CREATE INDEX org_billing_states_locked_idx
103
+    ON org_billing_states (locked_at)
104
+    WHERE locked_at IS NOT NULL;
105
+
106
+CREATE TRIGGER set_updated_at BEFORE UPDATE ON org_billing_states
107
+    FOR EACH ROW EXECUTE FUNCTION tg_set_updated_at();
108
+
109
+-- Backfill current organizations as Free. orgs.plan remains the
110
+-- human-facing summary; billing state starts conservative until Stripe
111
+-- webhooks activate a paid subscription.
112
+INSERT INTO org_billing_states (org_id, plan)
113
+SELECT id, 'free'::org_plan
114
+FROM orgs
115
+ON CONFLICT (org_id) DO NOTHING;
116
+
117
+-- +goose StatementBegin
118
+CREATE OR REPLACE FUNCTION tg_org_billing_state_seed() RETURNS trigger AS $$
119
+BEGIN
120
+    INSERT INTO org_billing_states (org_id, plan)
121
+    VALUES (NEW.id, 'free'::org_plan)
122
+    ON CONFLICT (org_id) DO NOTHING;
123
+    RETURN NEW;
124
+END;
125
+$$ LANGUAGE plpgsql;
126
+-- +goose StatementEnd
127
+
128
+CREATE TRIGGER tg_org_billing_state_seed_ai
129
+    AFTER INSERT ON orgs
130
+    FOR EACH ROW EXECUTE FUNCTION tg_org_billing_state_seed();
131
+
132
+CREATE TABLE billing_seat_snapshots (
133
+    id                         bigserial          PRIMARY KEY,
134
+    org_id                     bigint             NOT NULL REFERENCES orgs(id) ON DELETE CASCADE,
135
+    provider                   billing_provider   NOT NULL DEFAULT 'stripe',
136
+    stripe_subscription_id     text,
137
+    active_members             integer            NOT NULL,
138
+    billable_seats             integer            NOT NULL,
139
+    source                     text               NOT NULL DEFAULT 'local',
140
+    captured_at                timestamptz        NOT NULL DEFAULT now(),
141
+
142
+    CONSTRAINT billing_seat_snapshots_active_members_nonnegative CHECK (active_members >= 0),
143
+    CONSTRAINT billing_seat_snapshots_billable_seats_nonnegative CHECK (billable_seats >= 0),
144
+    CONSTRAINT billing_seat_snapshots_source_length CHECK (char_length(source) BETWEEN 1 AND 64)
145
+);
146
+
147
+CREATE INDEX billing_seat_snapshots_org_captured_idx
148
+    ON billing_seat_snapshots (org_id, captured_at DESC);
149
+
150
+CREATE TABLE billing_invoices (
151
+    id                         bigserial               PRIMARY KEY,
152
+    org_id                     bigint                  NOT NULL REFERENCES orgs(id) ON DELETE CASCADE,
153
+    provider                   billing_provider        NOT NULL DEFAULT 'stripe',
154
+    stripe_invoice_id          text                    NOT NULL,
155
+    stripe_customer_id         text                    NOT NULL,
156
+    stripe_subscription_id     text,
157
+    status                     billing_invoice_status  NOT NULL,
158
+    number                     text                    NOT NULL DEFAULT '',
159
+    currency                   text                    NOT NULL,
160
+    amount_due_cents           bigint                  NOT NULL DEFAULT 0,
161
+    amount_paid_cents          bigint                  NOT NULL DEFAULT 0,
162
+    amount_remaining_cents     bigint                  NOT NULL DEFAULT 0,
163
+    hosted_invoice_url         text                    NOT NULL DEFAULT '',
164
+    invoice_pdf_url            text                    NOT NULL DEFAULT '',
165
+    period_start               timestamptz,
166
+    period_end                 timestamptz,
167
+    due_at                     timestamptz,
168
+    paid_at                    timestamptz,
169
+    voided_at                  timestamptz,
170
+    created_at                 timestamptz             NOT NULL DEFAULT now(),
171
+    updated_at                 timestamptz             NOT NULL DEFAULT now(),
172
+
173
+    CONSTRAINT billing_invoices_stripe_invoice_not_blank CHECK (char_length(stripe_invoice_id) > 0),
174
+    CONSTRAINT billing_invoices_stripe_customer_not_blank CHECK (char_length(stripe_customer_id) > 0),
175
+    CONSTRAINT billing_invoices_currency_iso CHECK (
176
+        char_length(currency) = 3 AND currency = lower(currency)
177
+    ),
178
+    CONSTRAINT billing_invoices_amounts_nonnegative CHECK (
179
+        amount_due_cents >= 0
180
+        AND amount_paid_cents >= 0
181
+        AND amount_remaining_cents >= 0
182
+    ),
183
+    CONSTRAINT billing_invoices_period_order CHECK (
184
+        period_start IS NULL OR period_end IS NULL OR period_start <= period_end
185
+    ),
186
+
187
+    UNIQUE (provider, stripe_invoice_id)
188
+);
189
+
190
+CREATE INDEX billing_invoices_org_created_idx
191
+    ON billing_invoices (org_id, created_at DESC);
192
+
193
+CREATE INDEX billing_invoices_status_idx
194
+    ON billing_invoices (status, created_at DESC);
195
+
196
+CREATE TRIGGER set_updated_at BEFORE UPDATE ON billing_invoices
197
+    FOR EACH ROW EXECUTE FUNCTION tg_set_updated_at();
198
+
199
+CREATE TABLE billing_webhook_events (
200
+    id                         bigserial          PRIMARY KEY,
201
+    provider                   billing_provider   NOT NULL DEFAULT 'stripe',
202
+    provider_event_id          text               NOT NULL,
203
+    event_type                 text               NOT NULL,
204
+    api_version                text               NOT NULL DEFAULT '',
205
+    payload                    jsonb              NOT NULL DEFAULT '{}'::jsonb,
206
+    received_at                timestamptz        NOT NULL DEFAULT now(),
207
+    processed_at               timestamptz,
208
+    process_error              text               NOT NULL DEFAULT '',
209
+    processing_attempts        integer            NOT NULL DEFAULT 0,
210
+
211
+    CONSTRAINT billing_webhook_events_provider_event_not_blank CHECK (char_length(provider_event_id) > 0),
212
+    CONSTRAINT billing_webhook_events_type_not_blank CHECK (char_length(event_type) > 0),
213
+    CONSTRAINT billing_webhook_events_attempts_nonnegative CHECK (processing_attempts >= 0),
214
+    CONSTRAINT billing_webhook_events_payload_object CHECK (jsonb_typeof(payload) = 'object'),
215
+
216
+    UNIQUE (provider, provider_event_id)
217
+);
218
+
219
+CREATE INDEX billing_webhook_events_received_idx
220
+    ON billing_webhook_events (received_at DESC);
221
+
222
+CREATE INDEX billing_webhook_events_processed_idx
223
+    ON billing_webhook_events (processed_at)
224
+    WHERE processed_at IS NULL;
225
+
226
+-- +goose Down
227
+DROP INDEX IF EXISTS billing_webhook_events_processed_idx;
228
+DROP INDEX IF EXISTS billing_webhook_events_received_idx;
229
+DROP TABLE IF EXISTS billing_webhook_events;
230
+
231
+DROP TRIGGER IF EXISTS set_updated_at ON billing_invoices;
232
+DROP INDEX IF EXISTS billing_invoices_status_idx;
233
+DROP INDEX IF EXISTS billing_invoices_org_created_idx;
234
+DROP TABLE IF EXISTS billing_invoices;
235
+
236
+DROP INDEX IF EXISTS billing_seat_snapshots_org_captured_idx;
237
+DROP TABLE IF EXISTS billing_seat_snapshots;
238
+
239
+DROP TRIGGER IF EXISTS tg_org_billing_state_seed_ai ON orgs;
240
+DROP FUNCTION IF EXISTS tg_org_billing_state_seed();
241
+DROP TRIGGER IF EXISTS set_updated_at ON org_billing_states;
242
+DROP INDEX IF EXISTS org_billing_states_locked_idx;
243
+DROP INDEX IF EXISTS org_billing_states_status_idx;
244
+DROP INDEX IF EXISTS org_billing_states_stripe_subscription_item_unique;
245
+DROP INDEX IF EXISTS org_billing_states_stripe_subscription_unique;
246
+DROP INDEX IF EXISTS org_billing_states_stripe_customer_unique;
247
+DROP TABLE IF EXISTS org_billing_states;
248
+
249
+DROP TYPE IF EXISTS billing_invoice_status;
250
+DROP TYPE IF EXISTS billing_lock_reason;
251
+DROP TYPE IF EXISTS billing_subscription_status;
252
+DROP TYPE IF EXISTS billing_provider;
internal/notif/sqlc/models.gomodified
@@ -12,6 +12,184 @@ import (
1212
 	"github.com/jackc/pgx/v5/pgtype"
1313
 )
1414
 
15
+type BillingInvoiceStatus string
16
+
17
+const (
18
+	BillingInvoiceStatusDraft         BillingInvoiceStatus = "draft"
19
+	BillingInvoiceStatusOpen          BillingInvoiceStatus = "open"
20
+	BillingInvoiceStatusPaid          BillingInvoiceStatus = "paid"
21
+	BillingInvoiceStatusVoid          BillingInvoiceStatus = "void"
22
+	BillingInvoiceStatusUncollectible BillingInvoiceStatus = "uncollectible"
23
+)
24
+
25
+func (e *BillingInvoiceStatus) Scan(src interface{}) error {
26
+	switch s := src.(type) {
27
+	case []byte:
28
+		*e = BillingInvoiceStatus(s)
29
+	case string:
30
+		*e = BillingInvoiceStatus(s)
31
+	default:
32
+		return fmt.Errorf("unsupported scan type for BillingInvoiceStatus: %T", src)
33
+	}
34
+	return nil
35
+}
36
+
37
+type NullBillingInvoiceStatus struct {
38
+	BillingInvoiceStatus BillingInvoiceStatus
39
+	Valid                bool // Valid is true if BillingInvoiceStatus is not NULL
40
+}
41
+
42
+// Scan implements the Scanner interface.
43
+func (ns *NullBillingInvoiceStatus) Scan(value interface{}) error {
44
+	if value == nil {
45
+		ns.BillingInvoiceStatus, ns.Valid = "", false
46
+		return nil
47
+	}
48
+	ns.Valid = true
49
+	return ns.BillingInvoiceStatus.Scan(value)
50
+}
51
+
52
+// Value implements the driver Valuer interface.
53
+func (ns NullBillingInvoiceStatus) Value() (driver.Value, error) {
54
+	if !ns.Valid {
55
+		return nil, nil
56
+	}
57
+	return string(ns.BillingInvoiceStatus), nil
58
+}
59
+
60
+type BillingLockReason string
61
+
62
+const (
63
+	BillingLockReasonPastDue  BillingLockReason = "past_due"
64
+	BillingLockReasonCanceled BillingLockReason = "canceled"
65
+	BillingLockReasonUnpaid   BillingLockReason = "unpaid"
66
+	BillingLockReasonManual   BillingLockReason = "manual"
67
+)
68
+
69
+func (e *BillingLockReason) Scan(src interface{}) error {
70
+	switch s := src.(type) {
71
+	case []byte:
72
+		*e = BillingLockReason(s)
73
+	case string:
74
+		*e = BillingLockReason(s)
75
+	default:
76
+		return fmt.Errorf("unsupported scan type for BillingLockReason: %T", src)
77
+	}
78
+	return nil
79
+}
80
+
81
+type NullBillingLockReason struct {
82
+	BillingLockReason BillingLockReason
83
+	Valid             bool // Valid is true if BillingLockReason is not NULL
84
+}
85
+
86
+// Scan implements the Scanner interface.
87
+func (ns *NullBillingLockReason) Scan(value interface{}) error {
88
+	if value == nil {
89
+		ns.BillingLockReason, ns.Valid = "", false
90
+		return nil
91
+	}
92
+	ns.Valid = true
93
+	return ns.BillingLockReason.Scan(value)
94
+}
95
+
96
+// Value implements the driver Valuer interface.
97
+func (ns NullBillingLockReason) Value() (driver.Value, error) {
98
+	if !ns.Valid {
99
+		return nil, nil
100
+	}
101
+	return string(ns.BillingLockReason), nil
102
+}
103
+
104
+type BillingProvider string
105
+
106
+const (
107
+	BillingProviderStripe BillingProvider = "stripe"
108
+)
109
+
110
+func (e *BillingProvider) Scan(src interface{}) error {
111
+	switch s := src.(type) {
112
+	case []byte:
113
+		*e = BillingProvider(s)
114
+	case string:
115
+		*e = BillingProvider(s)
116
+	default:
117
+		return fmt.Errorf("unsupported scan type for BillingProvider: %T", src)
118
+	}
119
+	return nil
120
+}
121
+
122
+type NullBillingProvider struct {
123
+	BillingProvider BillingProvider
124
+	Valid           bool // Valid is true if BillingProvider is not NULL
125
+}
126
+
127
+// Scan implements the Scanner interface.
128
+func (ns *NullBillingProvider) Scan(value interface{}) error {
129
+	if value == nil {
130
+		ns.BillingProvider, ns.Valid = "", false
131
+		return nil
132
+	}
133
+	ns.Valid = true
134
+	return ns.BillingProvider.Scan(value)
135
+}
136
+
137
+// Value implements the driver Valuer interface.
138
+func (ns NullBillingProvider) Value() (driver.Value, error) {
139
+	if !ns.Valid {
140
+		return nil, nil
141
+	}
142
+	return string(ns.BillingProvider), nil
143
+}
144
+
145
+type BillingSubscriptionStatus string
146
+
147
+const (
148
+	BillingSubscriptionStatusNone       BillingSubscriptionStatus = "none"
149
+	BillingSubscriptionStatusIncomplete BillingSubscriptionStatus = "incomplete"
150
+	BillingSubscriptionStatusTrialing   BillingSubscriptionStatus = "trialing"
151
+	BillingSubscriptionStatusActive     BillingSubscriptionStatus = "active"
152
+	BillingSubscriptionStatusPastDue    BillingSubscriptionStatus = "past_due"
153
+	BillingSubscriptionStatusCanceled   BillingSubscriptionStatus = "canceled"
154
+	BillingSubscriptionStatusUnpaid     BillingSubscriptionStatus = "unpaid"
155
+	BillingSubscriptionStatusPaused     BillingSubscriptionStatus = "paused"
156
+)
157
+
158
+func (e *BillingSubscriptionStatus) Scan(src interface{}) error {
159
+	switch s := src.(type) {
160
+	case []byte:
161
+		*e = BillingSubscriptionStatus(s)
162
+	case string:
163
+		*e = BillingSubscriptionStatus(s)
164
+	default:
165
+		return fmt.Errorf("unsupported scan type for BillingSubscriptionStatus: %T", src)
166
+	}
167
+	return nil
168
+}
169
+
170
+type NullBillingSubscriptionStatus struct {
171
+	BillingSubscriptionStatus BillingSubscriptionStatus
172
+	Valid                     bool // Valid is true if BillingSubscriptionStatus is not NULL
173
+}
174
+
175
+// Scan implements the Scanner interface.
176
+func (ns *NullBillingSubscriptionStatus) Scan(value interface{}) error {
177
+	if value == nil {
178
+		ns.BillingSubscriptionStatus, ns.Valid = "", false
179
+		return nil
180
+	}
181
+	ns.Valid = true
182
+	return ns.BillingSubscriptionStatus.Scan(value)
183
+}
184
+
185
+// Value implements the driver Valuer interface.
186
+func (ns NullBillingSubscriptionStatus) Value() (driver.Value, error) {
187
+	if !ns.Valid {
188
+		return nil, nil
189
+	}
190
+	return string(ns.BillingSubscriptionStatus), nil
191
+}
192
+
15193
 type CheckConclusion string
16194
 
17195
 const (
@@ -1601,6 +1779,54 @@ type AuthThrottle struct {
16011779
 	WindowStartedAt pgtype.Timestamptz
16021780
 }
16031781
 
1782
+type BillingInvoice struct {
1783
+	ID                   int64
1784
+	OrgID                int64
1785
+	Provider             BillingProvider
1786
+	StripeInvoiceID      string
1787
+	StripeCustomerID     string
1788
+	StripeSubscriptionID pgtype.Text
1789
+	Status               BillingInvoiceStatus
1790
+	Number               string
1791
+	Currency             string
1792
+	AmountDueCents       int64
1793
+	AmountPaidCents      int64
1794
+	AmountRemainingCents int64
1795
+	HostedInvoiceUrl     string
1796
+	InvoicePdfUrl        string
1797
+	PeriodStart          pgtype.Timestamptz
1798
+	PeriodEnd            pgtype.Timestamptz
1799
+	DueAt                pgtype.Timestamptz
1800
+	PaidAt               pgtype.Timestamptz
1801
+	VoidedAt             pgtype.Timestamptz
1802
+	CreatedAt            pgtype.Timestamptz
1803
+	UpdatedAt            pgtype.Timestamptz
1804
+}
1805
+
1806
+type BillingSeatSnapshot struct {
1807
+	ID                   int64
1808
+	OrgID                int64
1809
+	Provider             BillingProvider
1810
+	StripeSubscriptionID pgtype.Text
1811
+	ActiveMembers        int32
1812
+	BillableSeats        int32
1813
+	Source               string
1814
+	CapturedAt           pgtype.Timestamptz
1815
+}
1816
+
1817
+type BillingWebhookEvent struct {
1818
+	ID                 int64
1819
+	Provider           BillingProvider
1820
+	ProviderEventID    string
1821
+	EventType          string
1822
+	ApiVersion         string
1823
+	Payload            []byte
1824
+	ReceivedAt         pgtype.Timestamptz
1825
+	ProcessedAt        pgtype.Timestamptz
1826
+	ProcessError       string
1827
+	ProcessingAttempts int32
1828
+}
1829
+
16041830
 type BranchProtectionRule struct {
16051831
 	ID                             int64
16061832
 	RepoID                         int64
@@ -1870,6 +2096,30 @@ type Org struct {
18702096
 	UpdatedAt             pgtype.Timestamptz
18712097
 }
18722098
 
2099
+type OrgBillingState struct {
2100
+	OrgID                    int64
2101
+	Provider                 BillingProvider
2102
+	StripeCustomerID         pgtype.Text
2103
+	StripeSubscriptionID     pgtype.Text
2104
+	StripeSubscriptionItemID pgtype.Text
2105
+	Plan                     OrgPlan
2106
+	SubscriptionStatus       BillingSubscriptionStatus
2107
+	BillableSeats            int32
2108
+	SeatSnapshotAt           pgtype.Timestamptz
2109
+	CurrentPeriodStart       pgtype.Timestamptz
2110
+	CurrentPeriodEnd         pgtype.Timestamptz
2111
+	CancelAtPeriodEnd        bool
2112
+	TrialEnd                 pgtype.Timestamptz
2113
+	PastDueAt                pgtype.Timestamptz
2114
+	CanceledAt               pgtype.Timestamptz
2115
+	LockedAt                 pgtype.Timestamptz
2116
+	LockReason               NullBillingLockReason
2117
+	GraceUntil               pgtype.Timestamptz
2118
+	LastWebhookEventID       string
2119
+	CreatedAt                pgtype.Timestamptz
2120
+	UpdatedAt                pgtype.Timestamptz
2121
+}
2122
+
18732123
 type OrgGithubImport struct {
18742124
 	ID                int64
18752125
 	OrgID             int64
internal/orgs/sqlc/models.gomodified
@@ -12,6 +12,184 @@ import (
1212
 	"github.com/jackc/pgx/v5/pgtype"
1313
 )
1414
 
15
+type BillingInvoiceStatus string
16
+
17
+const (
18
+	BillingInvoiceStatusDraft         BillingInvoiceStatus = "draft"
19
+	BillingInvoiceStatusOpen          BillingInvoiceStatus = "open"
20
+	BillingInvoiceStatusPaid          BillingInvoiceStatus = "paid"
21
+	BillingInvoiceStatusVoid          BillingInvoiceStatus = "void"
22
+	BillingInvoiceStatusUncollectible BillingInvoiceStatus = "uncollectible"
23
+)
24
+
25
+func (e *BillingInvoiceStatus) Scan(src interface{}) error {
26
+	switch s := src.(type) {
27
+	case []byte:
28
+		*e = BillingInvoiceStatus(s)
29
+	case string:
30
+		*e = BillingInvoiceStatus(s)
31
+	default:
32
+		return fmt.Errorf("unsupported scan type for BillingInvoiceStatus: %T", src)
33
+	}
34
+	return nil
35
+}
36
+
37
+type NullBillingInvoiceStatus struct {
38
+	BillingInvoiceStatus BillingInvoiceStatus
39
+	Valid                bool // Valid is true if BillingInvoiceStatus is not NULL
40
+}
41
+
42
+// Scan implements the Scanner interface.
43
+func (ns *NullBillingInvoiceStatus) Scan(value interface{}) error {
44
+	if value == nil {
45
+		ns.BillingInvoiceStatus, ns.Valid = "", false
46
+		return nil
47
+	}
48
+	ns.Valid = true
49
+	return ns.BillingInvoiceStatus.Scan(value)
50
+}
51
+
52
+// Value implements the driver Valuer interface.
53
+func (ns NullBillingInvoiceStatus) Value() (driver.Value, error) {
54
+	if !ns.Valid {
55
+		return nil, nil
56
+	}
57
+	return string(ns.BillingInvoiceStatus), nil
58
+}
59
+
60
+type BillingLockReason string
61
+
62
+const (
63
+	BillingLockReasonPastDue  BillingLockReason = "past_due"
64
+	BillingLockReasonCanceled BillingLockReason = "canceled"
65
+	BillingLockReasonUnpaid   BillingLockReason = "unpaid"
66
+	BillingLockReasonManual   BillingLockReason = "manual"
67
+)
68
+
69
+func (e *BillingLockReason) Scan(src interface{}) error {
70
+	switch s := src.(type) {
71
+	case []byte:
72
+		*e = BillingLockReason(s)
73
+	case string:
74
+		*e = BillingLockReason(s)
75
+	default:
76
+		return fmt.Errorf("unsupported scan type for BillingLockReason: %T", src)
77
+	}
78
+	return nil
79
+}
80
+
81
+type NullBillingLockReason struct {
82
+	BillingLockReason BillingLockReason
83
+	Valid             bool // Valid is true if BillingLockReason is not NULL
84
+}
85
+
86
+// Scan implements the Scanner interface.
87
+func (ns *NullBillingLockReason) Scan(value interface{}) error {
88
+	if value == nil {
89
+		ns.BillingLockReason, ns.Valid = "", false
90
+		return nil
91
+	}
92
+	ns.Valid = true
93
+	return ns.BillingLockReason.Scan(value)
94
+}
95
+
96
+// Value implements the driver Valuer interface.
97
+func (ns NullBillingLockReason) Value() (driver.Value, error) {
98
+	if !ns.Valid {
99
+		return nil, nil
100
+	}
101
+	return string(ns.BillingLockReason), nil
102
+}
103
+
104
+type BillingProvider string
105
+
106
+const (
107
+	BillingProviderStripe BillingProvider = "stripe"
108
+)
109
+
110
+func (e *BillingProvider) Scan(src interface{}) error {
111
+	switch s := src.(type) {
112
+	case []byte:
113
+		*e = BillingProvider(s)
114
+	case string:
115
+		*e = BillingProvider(s)
116
+	default:
117
+		return fmt.Errorf("unsupported scan type for BillingProvider: %T", src)
118
+	}
119
+	return nil
120
+}
121
+
122
+type NullBillingProvider struct {
123
+	BillingProvider BillingProvider
124
+	Valid           bool // Valid is true if BillingProvider is not NULL
125
+}
126
+
127
+// Scan implements the Scanner interface.
128
+func (ns *NullBillingProvider) Scan(value interface{}) error {
129
+	if value == nil {
130
+		ns.BillingProvider, ns.Valid = "", false
131
+		return nil
132
+	}
133
+	ns.Valid = true
134
+	return ns.BillingProvider.Scan(value)
135
+}
136
+
137
+// Value implements the driver Valuer interface.
138
+func (ns NullBillingProvider) Value() (driver.Value, error) {
139
+	if !ns.Valid {
140
+		return nil, nil
141
+	}
142
+	return string(ns.BillingProvider), nil
143
+}
144
+
145
+type BillingSubscriptionStatus string
146
+
147
+const (
148
+	BillingSubscriptionStatusNone       BillingSubscriptionStatus = "none"
149
+	BillingSubscriptionStatusIncomplete BillingSubscriptionStatus = "incomplete"
150
+	BillingSubscriptionStatusTrialing   BillingSubscriptionStatus = "trialing"
151
+	BillingSubscriptionStatusActive     BillingSubscriptionStatus = "active"
152
+	BillingSubscriptionStatusPastDue    BillingSubscriptionStatus = "past_due"
153
+	BillingSubscriptionStatusCanceled   BillingSubscriptionStatus = "canceled"
154
+	BillingSubscriptionStatusUnpaid     BillingSubscriptionStatus = "unpaid"
155
+	BillingSubscriptionStatusPaused     BillingSubscriptionStatus = "paused"
156
+)
157
+
158
+func (e *BillingSubscriptionStatus) Scan(src interface{}) error {
159
+	switch s := src.(type) {
160
+	case []byte:
161
+		*e = BillingSubscriptionStatus(s)
162
+	case string:
163
+		*e = BillingSubscriptionStatus(s)
164
+	default:
165
+		return fmt.Errorf("unsupported scan type for BillingSubscriptionStatus: %T", src)
166
+	}
167
+	return nil
168
+}
169
+
170
+type NullBillingSubscriptionStatus struct {
171
+	BillingSubscriptionStatus BillingSubscriptionStatus
172
+	Valid                     bool // Valid is true if BillingSubscriptionStatus is not NULL
173
+}
174
+
175
+// Scan implements the Scanner interface.
176
+func (ns *NullBillingSubscriptionStatus) Scan(value interface{}) error {
177
+	if value == nil {
178
+		ns.BillingSubscriptionStatus, ns.Valid = "", false
179
+		return nil
180
+	}
181
+	ns.Valid = true
182
+	return ns.BillingSubscriptionStatus.Scan(value)
183
+}
184
+
185
+// Value implements the driver Valuer interface.
186
+func (ns NullBillingSubscriptionStatus) Value() (driver.Value, error) {
187
+	if !ns.Valid {
188
+		return nil, nil
189
+	}
190
+	return string(ns.BillingSubscriptionStatus), nil
191
+}
192
+
15193
 type CheckConclusion string
16194
 
17195
 const (
@@ -1601,6 +1779,54 @@ type AuthThrottle struct {
16011779
 	WindowStartedAt pgtype.Timestamptz
16021780
 }
16031781
 
1782
+type BillingInvoice struct {
1783
+	ID                   int64
1784
+	OrgID                int64
1785
+	Provider             BillingProvider
1786
+	StripeInvoiceID      string
1787
+	StripeCustomerID     string
1788
+	StripeSubscriptionID pgtype.Text
1789
+	Status               BillingInvoiceStatus
1790
+	Number               string
1791
+	Currency             string
1792
+	AmountDueCents       int64
1793
+	AmountPaidCents      int64
1794
+	AmountRemainingCents int64
1795
+	HostedInvoiceUrl     string
1796
+	InvoicePdfUrl        string
1797
+	PeriodStart          pgtype.Timestamptz
1798
+	PeriodEnd            pgtype.Timestamptz
1799
+	DueAt                pgtype.Timestamptz
1800
+	PaidAt               pgtype.Timestamptz
1801
+	VoidedAt             pgtype.Timestamptz
1802
+	CreatedAt            pgtype.Timestamptz
1803
+	UpdatedAt            pgtype.Timestamptz
1804
+}
1805
+
1806
+type BillingSeatSnapshot struct {
1807
+	ID                   int64
1808
+	OrgID                int64
1809
+	Provider             BillingProvider
1810
+	StripeSubscriptionID pgtype.Text
1811
+	ActiveMembers        int32
1812
+	BillableSeats        int32
1813
+	Source               string
1814
+	CapturedAt           pgtype.Timestamptz
1815
+}
1816
+
1817
+type BillingWebhookEvent struct {
1818
+	ID                 int64
1819
+	Provider           BillingProvider
1820
+	ProviderEventID    string
1821
+	EventType          string
1822
+	ApiVersion         string
1823
+	Payload            []byte
1824
+	ReceivedAt         pgtype.Timestamptz
1825
+	ProcessedAt        pgtype.Timestamptz
1826
+	ProcessError       string
1827
+	ProcessingAttempts int32
1828
+}
1829
+
16041830
 type BranchProtectionRule struct {
16051831
 	ID                             int64
16061832
 	RepoID                         int64
@@ -1870,6 +2096,30 @@ type Org struct {
18702096
 	UpdatedAt             pgtype.Timestamptz
18712097
 }
18722098
 
2099
+type OrgBillingState struct {
2100
+	OrgID                    int64
2101
+	Provider                 BillingProvider
2102
+	StripeCustomerID         pgtype.Text
2103
+	StripeSubscriptionID     pgtype.Text
2104
+	StripeSubscriptionItemID pgtype.Text
2105
+	Plan                     OrgPlan
2106
+	SubscriptionStatus       BillingSubscriptionStatus
2107
+	BillableSeats            int32
2108
+	SeatSnapshotAt           pgtype.Timestamptz
2109
+	CurrentPeriodStart       pgtype.Timestamptz
2110
+	CurrentPeriodEnd         pgtype.Timestamptz
2111
+	CancelAtPeriodEnd        bool
2112
+	TrialEnd                 pgtype.Timestamptz
2113
+	PastDueAt                pgtype.Timestamptz
2114
+	CanceledAt               pgtype.Timestamptz
2115
+	LockedAt                 pgtype.Timestamptz
2116
+	LockReason               NullBillingLockReason
2117
+	GraceUntil               pgtype.Timestamptz
2118
+	LastWebhookEventID       string
2119
+	CreatedAt                pgtype.Timestamptz
2120
+	UpdatedAt                pgtype.Timestamptz
2121
+}
2122
+
18732123
 type OrgGithubImport struct {
18742124
 	ID                int64
18752125
 	OrgID             int64
internal/pulls/sqlc/models.gomodified
@@ -12,6 +12,184 @@ import (
1212
 	"github.com/jackc/pgx/v5/pgtype"
1313
 )
1414
 
15
+type BillingInvoiceStatus string
16
+
17
+const (
18
+	BillingInvoiceStatusDraft         BillingInvoiceStatus = "draft"
19
+	BillingInvoiceStatusOpen          BillingInvoiceStatus = "open"
20
+	BillingInvoiceStatusPaid          BillingInvoiceStatus = "paid"
21
+	BillingInvoiceStatusVoid          BillingInvoiceStatus = "void"
22
+	BillingInvoiceStatusUncollectible BillingInvoiceStatus = "uncollectible"
23
+)
24
+
25
+func (e *BillingInvoiceStatus) Scan(src interface{}) error {
26
+	switch s := src.(type) {
27
+	case []byte:
28
+		*e = BillingInvoiceStatus(s)
29
+	case string:
30
+		*e = BillingInvoiceStatus(s)
31
+	default:
32
+		return fmt.Errorf("unsupported scan type for BillingInvoiceStatus: %T", src)
33
+	}
34
+	return nil
35
+}
36
+
37
+type NullBillingInvoiceStatus struct {
38
+	BillingInvoiceStatus BillingInvoiceStatus
39
+	Valid                bool // Valid is true if BillingInvoiceStatus is not NULL
40
+}
41
+
42
+// Scan implements the Scanner interface.
43
+func (ns *NullBillingInvoiceStatus) Scan(value interface{}) error {
44
+	if value == nil {
45
+		ns.BillingInvoiceStatus, ns.Valid = "", false
46
+		return nil
47
+	}
48
+	ns.Valid = true
49
+	return ns.BillingInvoiceStatus.Scan(value)
50
+}
51
+
52
+// Value implements the driver Valuer interface.
53
+func (ns NullBillingInvoiceStatus) Value() (driver.Value, error) {
54
+	if !ns.Valid {
55
+		return nil, nil
56
+	}
57
+	return string(ns.BillingInvoiceStatus), nil
58
+}
59
+
60
+type BillingLockReason string
61
+
62
+const (
63
+	BillingLockReasonPastDue  BillingLockReason = "past_due"
64
+	BillingLockReasonCanceled BillingLockReason = "canceled"
65
+	BillingLockReasonUnpaid   BillingLockReason = "unpaid"
66
+	BillingLockReasonManual   BillingLockReason = "manual"
67
+)
68
+
69
+func (e *BillingLockReason) Scan(src interface{}) error {
70
+	switch s := src.(type) {
71
+	case []byte:
72
+		*e = BillingLockReason(s)
73
+	case string:
74
+		*e = BillingLockReason(s)
75
+	default:
76
+		return fmt.Errorf("unsupported scan type for BillingLockReason: %T", src)
77
+	}
78
+	return nil
79
+}
80
+
81
+type NullBillingLockReason struct {
82
+	BillingLockReason BillingLockReason
83
+	Valid             bool // Valid is true if BillingLockReason is not NULL
84
+}
85
+
86
+// Scan implements the Scanner interface.
87
+func (ns *NullBillingLockReason) Scan(value interface{}) error {
88
+	if value == nil {
89
+		ns.BillingLockReason, ns.Valid = "", false
90
+		return nil
91
+	}
92
+	ns.Valid = true
93
+	return ns.BillingLockReason.Scan(value)
94
+}
95
+
96
+// Value implements the driver Valuer interface.
97
+func (ns NullBillingLockReason) Value() (driver.Value, error) {
98
+	if !ns.Valid {
99
+		return nil, nil
100
+	}
101
+	return string(ns.BillingLockReason), nil
102
+}
103
+
104
+type BillingProvider string
105
+
106
+const (
107
+	BillingProviderStripe BillingProvider = "stripe"
108
+)
109
+
110
+func (e *BillingProvider) Scan(src interface{}) error {
111
+	switch s := src.(type) {
112
+	case []byte:
113
+		*e = BillingProvider(s)
114
+	case string:
115
+		*e = BillingProvider(s)
116
+	default:
117
+		return fmt.Errorf("unsupported scan type for BillingProvider: %T", src)
118
+	}
119
+	return nil
120
+}
121
+
122
+type NullBillingProvider struct {
123
+	BillingProvider BillingProvider
124
+	Valid           bool // Valid is true if BillingProvider is not NULL
125
+}
126
+
127
+// Scan implements the Scanner interface.
128
+func (ns *NullBillingProvider) Scan(value interface{}) error {
129
+	if value == nil {
130
+		ns.BillingProvider, ns.Valid = "", false
131
+		return nil
132
+	}
133
+	ns.Valid = true
134
+	return ns.BillingProvider.Scan(value)
135
+}
136
+
137
+// Value implements the driver Valuer interface.
138
+func (ns NullBillingProvider) Value() (driver.Value, error) {
139
+	if !ns.Valid {
140
+		return nil, nil
141
+	}
142
+	return string(ns.BillingProvider), nil
143
+}
144
+
145
+type BillingSubscriptionStatus string
146
+
147
+const (
148
+	BillingSubscriptionStatusNone       BillingSubscriptionStatus = "none"
149
+	BillingSubscriptionStatusIncomplete BillingSubscriptionStatus = "incomplete"
150
+	BillingSubscriptionStatusTrialing   BillingSubscriptionStatus = "trialing"
151
+	BillingSubscriptionStatusActive     BillingSubscriptionStatus = "active"
152
+	BillingSubscriptionStatusPastDue    BillingSubscriptionStatus = "past_due"
153
+	BillingSubscriptionStatusCanceled   BillingSubscriptionStatus = "canceled"
154
+	BillingSubscriptionStatusUnpaid     BillingSubscriptionStatus = "unpaid"
155
+	BillingSubscriptionStatusPaused     BillingSubscriptionStatus = "paused"
156
+)
157
+
158
+func (e *BillingSubscriptionStatus) Scan(src interface{}) error {
159
+	switch s := src.(type) {
160
+	case []byte:
161
+		*e = BillingSubscriptionStatus(s)
162
+	case string:
163
+		*e = BillingSubscriptionStatus(s)
164
+	default:
165
+		return fmt.Errorf("unsupported scan type for BillingSubscriptionStatus: %T", src)
166
+	}
167
+	return nil
168
+}
169
+
170
+type NullBillingSubscriptionStatus struct {
171
+	BillingSubscriptionStatus BillingSubscriptionStatus
172
+	Valid                     bool // Valid is true if BillingSubscriptionStatus is not NULL
173
+}
174
+
175
+// Scan implements the Scanner interface.
176
+func (ns *NullBillingSubscriptionStatus) Scan(value interface{}) error {
177
+	if value == nil {
178
+		ns.BillingSubscriptionStatus, ns.Valid = "", false
179
+		return nil
180
+	}
181
+	ns.Valid = true
182
+	return ns.BillingSubscriptionStatus.Scan(value)
183
+}
184
+
185
+// Value implements the driver Valuer interface.
186
+func (ns NullBillingSubscriptionStatus) Value() (driver.Value, error) {
187
+	if !ns.Valid {
188
+		return nil, nil
189
+	}
190
+	return string(ns.BillingSubscriptionStatus), nil
191
+}
192
+
15193
 type CheckConclusion string
16194
 
17195
 const (
@@ -1601,6 +1779,54 @@ type AuthThrottle struct {
16011779
 	WindowStartedAt pgtype.Timestamptz
16021780
 }
16031781
 
1782
+type BillingInvoice struct {
1783
+	ID                   int64
1784
+	OrgID                int64
1785
+	Provider             BillingProvider
1786
+	StripeInvoiceID      string
1787
+	StripeCustomerID     string
1788
+	StripeSubscriptionID pgtype.Text
1789
+	Status               BillingInvoiceStatus
1790
+	Number               string
1791
+	Currency             string
1792
+	AmountDueCents       int64
1793
+	AmountPaidCents      int64
1794
+	AmountRemainingCents int64
1795
+	HostedInvoiceUrl     string
1796
+	InvoicePdfUrl        string
1797
+	PeriodStart          pgtype.Timestamptz
1798
+	PeriodEnd            pgtype.Timestamptz
1799
+	DueAt                pgtype.Timestamptz
1800
+	PaidAt               pgtype.Timestamptz
1801
+	VoidedAt             pgtype.Timestamptz
1802
+	CreatedAt            pgtype.Timestamptz
1803
+	UpdatedAt            pgtype.Timestamptz
1804
+}
1805
+
1806
+type BillingSeatSnapshot struct {
1807
+	ID                   int64
1808
+	OrgID                int64
1809
+	Provider             BillingProvider
1810
+	StripeSubscriptionID pgtype.Text
1811
+	ActiveMembers        int32
1812
+	BillableSeats        int32
1813
+	Source               string
1814
+	CapturedAt           pgtype.Timestamptz
1815
+}
1816
+
1817
+type BillingWebhookEvent struct {
1818
+	ID                 int64
1819
+	Provider           BillingProvider
1820
+	ProviderEventID    string
1821
+	EventType          string
1822
+	ApiVersion         string
1823
+	Payload            []byte
1824
+	ReceivedAt         pgtype.Timestamptz
1825
+	ProcessedAt        pgtype.Timestamptz
1826
+	ProcessError       string
1827
+	ProcessingAttempts int32
1828
+}
1829
+
16041830
 type BranchProtectionRule struct {
16051831
 	ID                             int64
16061832
 	RepoID                         int64
@@ -1870,6 +2096,30 @@ type Org struct {
18702096
 	UpdatedAt             pgtype.Timestamptz
18712097
 }
18722098
 
2099
+type OrgBillingState struct {
2100
+	OrgID                    int64
2101
+	Provider                 BillingProvider
2102
+	StripeCustomerID         pgtype.Text
2103
+	StripeSubscriptionID     pgtype.Text
2104
+	StripeSubscriptionItemID pgtype.Text
2105
+	Plan                     OrgPlan
2106
+	SubscriptionStatus       BillingSubscriptionStatus
2107
+	BillableSeats            int32
2108
+	SeatSnapshotAt           pgtype.Timestamptz
2109
+	CurrentPeriodStart       pgtype.Timestamptz
2110
+	CurrentPeriodEnd         pgtype.Timestamptz
2111
+	CancelAtPeriodEnd        bool
2112
+	TrialEnd                 pgtype.Timestamptz
2113
+	PastDueAt                pgtype.Timestamptz
2114
+	CanceledAt               pgtype.Timestamptz
2115
+	LockedAt                 pgtype.Timestamptz
2116
+	LockReason               NullBillingLockReason
2117
+	GraceUntil               pgtype.Timestamptz
2118
+	LastWebhookEventID       string
2119
+	CreatedAt                pgtype.Timestamptz
2120
+	UpdatedAt                pgtype.Timestamptz
2121
+}
2122
+
18732123
 type OrgGithubImport struct {
18742124
 	ID                int64
18752125
 	OrgID             int64
internal/ratelimit/sqlc/models.gomodified
@@ -12,6 +12,184 @@ import (
1212
 	"github.com/jackc/pgx/v5/pgtype"
1313
 )
1414
 
15
+type BillingInvoiceStatus string
16
+
17
+const (
18
+	BillingInvoiceStatusDraft         BillingInvoiceStatus = "draft"
19
+	BillingInvoiceStatusOpen          BillingInvoiceStatus = "open"
20
+	BillingInvoiceStatusPaid          BillingInvoiceStatus = "paid"
21
+	BillingInvoiceStatusVoid          BillingInvoiceStatus = "void"
22
+	BillingInvoiceStatusUncollectible BillingInvoiceStatus = "uncollectible"
23
+)
24
+
25
+func (e *BillingInvoiceStatus) Scan(src interface{}) error {
26
+	switch s := src.(type) {
27
+	case []byte:
28
+		*e = BillingInvoiceStatus(s)
29
+	case string:
30
+		*e = BillingInvoiceStatus(s)
31
+	default:
32
+		return fmt.Errorf("unsupported scan type for BillingInvoiceStatus: %T", src)
33
+	}
34
+	return nil
35
+}
36
+
37
+type NullBillingInvoiceStatus struct {
38
+	BillingInvoiceStatus BillingInvoiceStatus
39
+	Valid                bool // Valid is true if BillingInvoiceStatus is not NULL
40
+}
41
+
42
+// Scan implements the Scanner interface.
43
+func (ns *NullBillingInvoiceStatus) Scan(value interface{}) error {
44
+	if value == nil {
45
+		ns.BillingInvoiceStatus, ns.Valid = "", false
46
+		return nil
47
+	}
48
+	ns.Valid = true
49
+	return ns.BillingInvoiceStatus.Scan(value)
50
+}
51
+
52
+// Value implements the driver Valuer interface.
53
+func (ns NullBillingInvoiceStatus) Value() (driver.Value, error) {
54
+	if !ns.Valid {
55
+		return nil, nil
56
+	}
57
+	return string(ns.BillingInvoiceStatus), nil
58
+}
59
+
60
+type BillingLockReason string
61
+
62
+const (
63
+	BillingLockReasonPastDue  BillingLockReason = "past_due"
64
+	BillingLockReasonCanceled BillingLockReason = "canceled"
65
+	BillingLockReasonUnpaid   BillingLockReason = "unpaid"
66
+	BillingLockReasonManual   BillingLockReason = "manual"
67
+)
68
+
69
+func (e *BillingLockReason) Scan(src interface{}) error {
70
+	switch s := src.(type) {
71
+	case []byte:
72
+		*e = BillingLockReason(s)
73
+	case string:
74
+		*e = BillingLockReason(s)
75
+	default:
76
+		return fmt.Errorf("unsupported scan type for BillingLockReason: %T", src)
77
+	}
78
+	return nil
79
+}
80
+
81
+type NullBillingLockReason struct {
82
+	BillingLockReason BillingLockReason
83
+	Valid             bool // Valid is true if BillingLockReason is not NULL
84
+}
85
+
86
+// Scan implements the Scanner interface.
87
+func (ns *NullBillingLockReason) Scan(value interface{}) error {
88
+	if value == nil {
89
+		ns.BillingLockReason, ns.Valid = "", false
90
+		return nil
91
+	}
92
+	ns.Valid = true
93
+	return ns.BillingLockReason.Scan(value)
94
+}
95
+
96
+// Value implements the driver Valuer interface.
97
+func (ns NullBillingLockReason) Value() (driver.Value, error) {
98
+	if !ns.Valid {
99
+		return nil, nil
100
+	}
101
+	return string(ns.BillingLockReason), nil
102
+}
103
+
104
+type BillingProvider string
105
+
106
+const (
107
+	BillingProviderStripe BillingProvider = "stripe"
108
+)
109
+
110
+func (e *BillingProvider) Scan(src interface{}) error {
111
+	switch s := src.(type) {
112
+	case []byte:
113
+		*e = BillingProvider(s)
114
+	case string:
115
+		*e = BillingProvider(s)
116
+	default:
117
+		return fmt.Errorf("unsupported scan type for BillingProvider: %T", src)
118
+	}
119
+	return nil
120
+}
121
+
122
+type NullBillingProvider struct {
123
+	BillingProvider BillingProvider
124
+	Valid           bool // Valid is true if BillingProvider is not NULL
125
+}
126
+
127
+// Scan implements the Scanner interface.
128
+func (ns *NullBillingProvider) Scan(value interface{}) error {
129
+	if value == nil {
130
+		ns.BillingProvider, ns.Valid = "", false
131
+		return nil
132
+	}
133
+	ns.Valid = true
134
+	return ns.BillingProvider.Scan(value)
135
+}
136
+
137
+// Value implements the driver Valuer interface.
138
+func (ns NullBillingProvider) Value() (driver.Value, error) {
139
+	if !ns.Valid {
140
+		return nil, nil
141
+	}
142
+	return string(ns.BillingProvider), nil
143
+}
144
+
145
+type BillingSubscriptionStatus string
146
+
147
+const (
148
+	BillingSubscriptionStatusNone       BillingSubscriptionStatus = "none"
149
+	BillingSubscriptionStatusIncomplete BillingSubscriptionStatus = "incomplete"
150
+	BillingSubscriptionStatusTrialing   BillingSubscriptionStatus = "trialing"
151
+	BillingSubscriptionStatusActive     BillingSubscriptionStatus = "active"
152
+	BillingSubscriptionStatusPastDue    BillingSubscriptionStatus = "past_due"
153
+	BillingSubscriptionStatusCanceled   BillingSubscriptionStatus = "canceled"
154
+	BillingSubscriptionStatusUnpaid     BillingSubscriptionStatus = "unpaid"
155
+	BillingSubscriptionStatusPaused     BillingSubscriptionStatus = "paused"
156
+)
157
+
158
+func (e *BillingSubscriptionStatus) Scan(src interface{}) error {
159
+	switch s := src.(type) {
160
+	case []byte:
161
+		*e = BillingSubscriptionStatus(s)
162
+	case string:
163
+		*e = BillingSubscriptionStatus(s)
164
+	default:
165
+		return fmt.Errorf("unsupported scan type for BillingSubscriptionStatus: %T", src)
166
+	}
167
+	return nil
168
+}
169
+
170
+type NullBillingSubscriptionStatus struct {
171
+	BillingSubscriptionStatus BillingSubscriptionStatus
172
+	Valid                     bool // Valid is true if BillingSubscriptionStatus is not NULL
173
+}
174
+
175
+// Scan implements the Scanner interface.
176
+func (ns *NullBillingSubscriptionStatus) Scan(value interface{}) error {
177
+	if value == nil {
178
+		ns.BillingSubscriptionStatus, ns.Valid = "", false
179
+		return nil
180
+	}
181
+	ns.Valid = true
182
+	return ns.BillingSubscriptionStatus.Scan(value)
183
+}
184
+
185
+// Value implements the driver Valuer interface.
186
+func (ns NullBillingSubscriptionStatus) Value() (driver.Value, error) {
187
+	if !ns.Valid {
188
+		return nil, nil
189
+	}
190
+	return string(ns.BillingSubscriptionStatus), nil
191
+}
192
+
15193
 type CheckConclusion string
16194
 
17195
 const (
@@ -1601,6 +1779,54 @@ type AuthThrottle struct {
16011779
 	WindowStartedAt pgtype.Timestamptz
16021780
 }
16031781
 
1782
+type BillingInvoice struct {
1783
+	ID                   int64
1784
+	OrgID                int64
1785
+	Provider             BillingProvider
1786
+	StripeInvoiceID      string
1787
+	StripeCustomerID     string
1788
+	StripeSubscriptionID pgtype.Text
1789
+	Status               BillingInvoiceStatus
1790
+	Number               string
1791
+	Currency             string
1792
+	AmountDueCents       int64
1793
+	AmountPaidCents      int64
1794
+	AmountRemainingCents int64
1795
+	HostedInvoiceUrl     string
1796
+	InvoicePdfUrl        string
1797
+	PeriodStart          pgtype.Timestamptz
1798
+	PeriodEnd            pgtype.Timestamptz
1799
+	DueAt                pgtype.Timestamptz
1800
+	PaidAt               pgtype.Timestamptz
1801
+	VoidedAt             pgtype.Timestamptz
1802
+	CreatedAt            pgtype.Timestamptz
1803
+	UpdatedAt            pgtype.Timestamptz
1804
+}
1805
+
1806
+type BillingSeatSnapshot struct {
1807
+	ID                   int64
1808
+	OrgID                int64
1809
+	Provider             BillingProvider
1810
+	StripeSubscriptionID pgtype.Text
1811
+	ActiveMembers        int32
1812
+	BillableSeats        int32
1813
+	Source               string
1814
+	CapturedAt           pgtype.Timestamptz
1815
+}
1816
+
1817
+type BillingWebhookEvent struct {
1818
+	ID                 int64
1819
+	Provider           BillingProvider
1820
+	ProviderEventID    string
1821
+	EventType          string
1822
+	ApiVersion         string
1823
+	Payload            []byte
1824
+	ReceivedAt         pgtype.Timestamptz
1825
+	ProcessedAt        pgtype.Timestamptz
1826
+	ProcessError       string
1827
+	ProcessingAttempts int32
1828
+}
1829
+
16041830
 type BranchProtectionRule struct {
16051831
 	ID                             int64
16061832
 	RepoID                         int64
@@ -1870,6 +2096,30 @@ type Org struct {
18702096
 	UpdatedAt             pgtype.Timestamptz
18712097
 }
18722098
 
2099
+type OrgBillingState struct {
2100
+	OrgID                    int64
2101
+	Provider                 BillingProvider
2102
+	StripeCustomerID         pgtype.Text
2103
+	StripeSubscriptionID     pgtype.Text
2104
+	StripeSubscriptionItemID pgtype.Text
2105
+	Plan                     OrgPlan
2106
+	SubscriptionStatus       BillingSubscriptionStatus
2107
+	BillableSeats            int32
2108
+	SeatSnapshotAt           pgtype.Timestamptz
2109
+	CurrentPeriodStart       pgtype.Timestamptz
2110
+	CurrentPeriodEnd         pgtype.Timestamptz
2111
+	CancelAtPeriodEnd        bool
2112
+	TrialEnd                 pgtype.Timestamptz
2113
+	PastDueAt                pgtype.Timestamptz
2114
+	CanceledAt               pgtype.Timestamptz
2115
+	LockedAt                 pgtype.Timestamptz
2116
+	LockReason               NullBillingLockReason
2117
+	GraceUntil               pgtype.Timestamptz
2118
+	LastWebhookEventID       string
2119
+	CreatedAt                pgtype.Timestamptz
2120
+	UpdatedAt                pgtype.Timestamptz
2121
+}
2122
+
18732123
 type OrgGithubImport struct {
18742124
 	ID                int64
18752125
 	OrgID             int64
internal/repos/sqlc/models.gomodified
@@ -12,6 +12,184 @@ import (
1212
 	"github.com/jackc/pgx/v5/pgtype"
1313
 )
1414
 
15
+type BillingInvoiceStatus string
16
+
17
+const (
18
+	BillingInvoiceStatusDraft         BillingInvoiceStatus = "draft"
19
+	BillingInvoiceStatusOpen          BillingInvoiceStatus = "open"
20
+	BillingInvoiceStatusPaid          BillingInvoiceStatus = "paid"
21
+	BillingInvoiceStatusVoid          BillingInvoiceStatus = "void"
22
+	BillingInvoiceStatusUncollectible BillingInvoiceStatus = "uncollectible"
23
+)
24
+
25
+func (e *BillingInvoiceStatus) Scan(src interface{}) error {
26
+	switch s := src.(type) {
27
+	case []byte:
28
+		*e = BillingInvoiceStatus(s)
29
+	case string:
30
+		*e = BillingInvoiceStatus(s)
31
+	default:
32
+		return fmt.Errorf("unsupported scan type for BillingInvoiceStatus: %T", src)
33
+	}
34
+	return nil
35
+}
36
+
37
+type NullBillingInvoiceStatus struct {
38
+	BillingInvoiceStatus BillingInvoiceStatus
39
+	Valid                bool // Valid is true if BillingInvoiceStatus is not NULL
40
+}
41
+
42
+// Scan implements the Scanner interface.
43
+func (ns *NullBillingInvoiceStatus) Scan(value interface{}) error {
44
+	if value == nil {
45
+		ns.BillingInvoiceStatus, ns.Valid = "", false
46
+		return nil
47
+	}
48
+	ns.Valid = true
49
+	return ns.BillingInvoiceStatus.Scan(value)
50
+}
51
+
52
+// Value implements the driver Valuer interface.
53
+func (ns NullBillingInvoiceStatus) Value() (driver.Value, error) {
54
+	if !ns.Valid {
55
+		return nil, nil
56
+	}
57
+	return string(ns.BillingInvoiceStatus), nil
58
+}
59
+
60
+type BillingLockReason string
61
+
62
+const (
63
+	BillingLockReasonPastDue  BillingLockReason = "past_due"
64
+	BillingLockReasonCanceled BillingLockReason = "canceled"
65
+	BillingLockReasonUnpaid   BillingLockReason = "unpaid"
66
+	BillingLockReasonManual   BillingLockReason = "manual"
67
+)
68
+
69
+func (e *BillingLockReason) Scan(src interface{}) error {
70
+	switch s := src.(type) {
71
+	case []byte:
72
+		*e = BillingLockReason(s)
73
+	case string:
74
+		*e = BillingLockReason(s)
75
+	default:
76
+		return fmt.Errorf("unsupported scan type for BillingLockReason: %T", src)
77
+	}
78
+	return nil
79
+}
80
+
81
+type NullBillingLockReason struct {
82
+	BillingLockReason BillingLockReason
83
+	Valid             bool // Valid is true if BillingLockReason is not NULL
84
+}
85
+
86
+// Scan implements the Scanner interface.
87
+func (ns *NullBillingLockReason) Scan(value interface{}) error {
88
+	if value == nil {
89
+		ns.BillingLockReason, ns.Valid = "", false
90
+		return nil
91
+	}
92
+	ns.Valid = true
93
+	return ns.BillingLockReason.Scan(value)
94
+}
95
+
96
+// Value implements the driver Valuer interface.
97
+func (ns NullBillingLockReason) Value() (driver.Value, error) {
98
+	if !ns.Valid {
99
+		return nil, nil
100
+	}
101
+	return string(ns.BillingLockReason), nil
102
+}
103
+
104
+type BillingProvider string
105
+
106
+const (
107
+	BillingProviderStripe BillingProvider = "stripe"
108
+)
109
+
110
+func (e *BillingProvider) Scan(src interface{}) error {
111
+	switch s := src.(type) {
112
+	case []byte:
113
+		*e = BillingProvider(s)
114
+	case string:
115
+		*e = BillingProvider(s)
116
+	default:
117
+		return fmt.Errorf("unsupported scan type for BillingProvider: %T", src)
118
+	}
119
+	return nil
120
+}
121
+
122
+type NullBillingProvider struct {
123
+	BillingProvider BillingProvider
124
+	Valid           bool // Valid is true if BillingProvider is not NULL
125
+}
126
+
127
+// Scan implements the Scanner interface.
128
+func (ns *NullBillingProvider) Scan(value interface{}) error {
129
+	if value == nil {
130
+		ns.BillingProvider, ns.Valid = "", false
131
+		return nil
132
+	}
133
+	ns.Valid = true
134
+	return ns.BillingProvider.Scan(value)
135
+}
136
+
137
+// Value implements the driver Valuer interface.
138
+func (ns NullBillingProvider) Value() (driver.Value, error) {
139
+	if !ns.Valid {
140
+		return nil, nil
141
+	}
142
+	return string(ns.BillingProvider), nil
143
+}
144
+
145
+type BillingSubscriptionStatus string
146
+
147
+const (
148
+	BillingSubscriptionStatusNone       BillingSubscriptionStatus = "none"
149
+	BillingSubscriptionStatusIncomplete BillingSubscriptionStatus = "incomplete"
150
+	BillingSubscriptionStatusTrialing   BillingSubscriptionStatus = "trialing"
151
+	BillingSubscriptionStatusActive     BillingSubscriptionStatus = "active"
152
+	BillingSubscriptionStatusPastDue    BillingSubscriptionStatus = "past_due"
153
+	BillingSubscriptionStatusCanceled   BillingSubscriptionStatus = "canceled"
154
+	BillingSubscriptionStatusUnpaid     BillingSubscriptionStatus = "unpaid"
155
+	BillingSubscriptionStatusPaused     BillingSubscriptionStatus = "paused"
156
+)
157
+
158
+func (e *BillingSubscriptionStatus) Scan(src interface{}) error {
159
+	switch s := src.(type) {
160
+	case []byte:
161
+		*e = BillingSubscriptionStatus(s)
162
+	case string:
163
+		*e = BillingSubscriptionStatus(s)
164
+	default:
165
+		return fmt.Errorf("unsupported scan type for BillingSubscriptionStatus: %T", src)
166
+	}
167
+	return nil
168
+}
169
+
170
+type NullBillingSubscriptionStatus struct {
171
+	BillingSubscriptionStatus BillingSubscriptionStatus
172
+	Valid                     bool // Valid is true if BillingSubscriptionStatus is not NULL
173
+}
174
+
175
+// Scan implements the Scanner interface.
176
+func (ns *NullBillingSubscriptionStatus) Scan(value interface{}) error {
177
+	if value == nil {
178
+		ns.BillingSubscriptionStatus, ns.Valid = "", false
179
+		return nil
180
+	}
181
+	ns.Valid = true
182
+	return ns.BillingSubscriptionStatus.Scan(value)
183
+}
184
+
185
+// Value implements the driver Valuer interface.
186
+func (ns NullBillingSubscriptionStatus) Value() (driver.Value, error) {
187
+	if !ns.Valid {
188
+		return nil, nil
189
+	}
190
+	return string(ns.BillingSubscriptionStatus), nil
191
+}
192
+
15193
 type CheckConclusion string
16194
 
17195
 const (
@@ -1601,6 +1779,54 @@ type AuthThrottle struct {
16011779
 	WindowStartedAt pgtype.Timestamptz
16021780
 }
16031781
 
1782
+type BillingInvoice struct {
1783
+	ID                   int64
1784
+	OrgID                int64
1785
+	Provider             BillingProvider
1786
+	StripeInvoiceID      string
1787
+	StripeCustomerID     string
1788
+	StripeSubscriptionID pgtype.Text
1789
+	Status               BillingInvoiceStatus
1790
+	Number               string
1791
+	Currency             string
1792
+	AmountDueCents       int64
1793
+	AmountPaidCents      int64
1794
+	AmountRemainingCents int64
1795
+	HostedInvoiceUrl     string
1796
+	InvoicePdfUrl        string
1797
+	PeriodStart          pgtype.Timestamptz
1798
+	PeriodEnd            pgtype.Timestamptz
1799
+	DueAt                pgtype.Timestamptz
1800
+	PaidAt               pgtype.Timestamptz
1801
+	VoidedAt             pgtype.Timestamptz
1802
+	CreatedAt            pgtype.Timestamptz
1803
+	UpdatedAt            pgtype.Timestamptz
1804
+}
1805
+
1806
+type BillingSeatSnapshot struct {
1807
+	ID                   int64
1808
+	OrgID                int64
1809
+	Provider             BillingProvider
1810
+	StripeSubscriptionID pgtype.Text
1811
+	ActiveMembers        int32
1812
+	BillableSeats        int32
1813
+	Source               string
1814
+	CapturedAt           pgtype.Timestamptz
1815
+}
1816
+
1817
+type BillingWebhookEvent struct {
1818
+	ID                 int64
1819
+	Provider           BillingProvider
1820
+	ProviderEventID    string
1821
+	EventType          string
1822
+	ApiVersion         string
1823
+	Payload            []byte
1824
+	ReceivedAt         pgtype.Timestamptz
1825
+	ProcessedAt        pgtype.Timestamptz
1826
+	ProcessError       string
1827
+	ProcessingAttempts int32
1828
+}
1829
+
16041830
 type BranchProtectionRule struct {
16051831
 	ID                             int64
16061832
 	RepoID                         int64
@@ -1870,6 +2096,30 @@ type Org struct {
18702096
 	UpdatedAt             pgtype.Timestamptz
18712097
 }
18722098
 
2099
+type OrgBillingState struct {
2100
+	OrgID                    int64
2101
+	Provider                 BillingProvider
2102
+	StripeCustomerID         pgtype.Text
2103
+	StripeSubscriptionID     pgtype.Text
2104
+	StripeSubscriptionItemID pgtype.Text
2105
+	Plan                     OrgPlan
2106
+	SubscriptionStatus       BillingSubscriptionStatus
2107
+	BillableSeats            int32
2108
+	SeatSnapshotAt           pgtype.Timestamptz
2109
+	CurrentPeriodStart       pgtype.Timestamptz
2110
+	CurrentPeriodEnd         pgtype.Timestamptz
2111
+	CancelAtPeriodEnd        bool
2112
+	TrialEnd                 pgtype.Timestamptz
2113
+	PastDueAt                pgtype.Timestamptz
2114
+	CanceledAt               pgtype.Timestamptz
2115
+	LockedAt                 pgtype.Timestamptz
2116
+	LockReason               NullBillingLockReason
2117
+	GraceUntil               pgtype.Timestamptz
2118
+	LastWebhookEventID       string
2119
+	CreatedAt                pgtype.Timestamptz
2120
+	UpdatedAt                pgtype.Timestamptz
2121
+}
2122
+
18732123
 type OrgGithubImport struct {
18742124
 	ID                int64
18752125
 	OrgID             int64
internal/social/sqlc/models.gomodified
@@ -12,6 +12,184 @@ import (
1212
 	"github.com/jackc/pgx/v5/pgtype"
1313
 )
1414
 
15
+type BillingInvoiceStatus string
16
+
17
+const (
18
+	BillingInvoiceStatusDraft         BillingInvoiceStatus = "draft"
19
+	BillingInvoiceStatusOpen          BillingInvoiceStatus = "open"
20
+	BillingInvoiceStatusPaid          BillingInvoiceStatus = "paid"
21
+	BillingInvoiceStatusVoid          BillingInvoiceStatus = "void"
22
+	BillingInvoiceStatusUncollectible BillingInvoiceStatus = "uncollectible"
23
+)
24
+
25
+func (e *BillingInvoiceStatus) Scan(src interface{}) error {
26
+	switch s := src.(type) {
27
+	case []byte:
28
+		*e = BillingInvoiceStatus(s)
29
+	case string:
30
+		*e = BillingInvoiceStatus(s)
31
+	default:
32
+		return fmt.Errorf("unsupported scan type for BillingInvoiceStatus: %T", src)
33
+	}
34
+	return nil
35
+}
36
+
37
+type NullBillingInvoiceStatus struct {
38
+	BillingInvoiceStatus BillingInvoiceStatus
39
+	Valid                bool // Valid is true if BillingInvoiceStatus is not NULL
40
+}
41
+
42
+// Scan implements the Scanner interface.
43
+func (ns *NullBillingInvoiceStatus) Scan(value interface{}) error {
44
+	if value == nil {
45
+		ns.BillingInvoiceStatus, ns.Valid = "", false
46
+		return nil
47
+	}
48
+	ns.Valid = true
49
+	return ns.BillingInvoiceStatus.Scan(value)
50
+}
51
+
52
+// Value implements the driver Valuer interface.
53
+func (ns NullBillingInvoiceStatus) Value() (driver.Value, error) {
54
+	if !ns.Valid {
55
+		return nil, nil
56
+	}
57
+	return string(ns.BillingInvoiceStatus), nil
58
+}
59
+
60
+type BillingLockReason string
61
+
62
+const (
63
+	BillingLockReasonPastDue  BillingLockReason = "past_due"
64
+	BillingLockReasonCanceled BillingLockReason = "canceled"
65
+	BillingLockReasonUnpaid   BillingLockReason = "unpaid"
66
+	BillingLockReasonManual   BillingLockReason = "manual"
67
+)
68
+
69
+func (e *BillingLockReason) Scan(src interface{}) error {
70
+	switch s := src.(type) {
71
+	case []byte:
72
+		*e = BillingLockReason(s)
73
+	case string:
74
+		*e = BillingLockReason(s)
75
+	default:
76
+		return fmt.Errorf("unsupported scan type for BillingLockReason: %T", src)
77
+	}
78
+	return nil
79
+}
80
+
81
+type NullBillingLockReason struct {
82
+	BillingLockReason BillingLockReason
83
+	Valid             bool // Valid is true if BillingLockReason is not NULL
84
+}
85
+
86
+// Scan implements the Scanner interface.
87
+func (ns *NullBillingLockReason) Scan(value interface{}) error {
88
+	if value == nil {
89
+		ns.BillingLockReason, ns.Valid = "", false
90
+		return nil
91
+	}
92
+	ns.Valid = true
93
+	return ns.BillingLockReason.Scan(value)
94
+}
95
+
96
+// Value implements the driver Valuer interface.
97
+func (ns NullBillingLockReason) Value() (driver.Value, error) {
98
+	if !ns.Valid {
99
+		return nil, nil
100
+	}
101
+	return string(ns.BillingLockReason), nil
102
+}
103
+
104
+type BillingProvider string
105
+
106
+const (
107
+	BillingProviderStripe BillingProvider = "stripe"
108
+)
109
+
110
+func (e *BillingProvider) Scan(src interface{}) error {
111
+	switch s := src.(type) {
112
+	case []byte:
113
+		*e = BillingProvider(s)
114
+	case string:
115
+		*e = BillingProvider(s)
116
+	default:
117
+		return fmt.Errorf("unsupported scan type for BillingProvider: %T", src)
118
+	}
119
+	return nil
120
+}
121
+
122
+type NullBillingProvider struct {
123
+	BillingProvider BillingProvider
124
+	Valid           bool // Valid is true if BillingProvider is not NULL
125
+}
126
+
127
+// Scan implements the Scanner interface.
128
+func (ns *NullBillingProvider) Scan(value interface{}) error {
129
+	if value == nil {
130
+		ns.BillingProvider, ns.Valid = "", false
131
+		return nil
132
+	}
133
+	ns.Valid = true
134
+	return ns.BillingProvider.Scan(value)
135
+}
136
+
137
+// Value implements the driver Valuer interface.
138
+func (ns NullBillingProvider) Value() (driver.Value, error) {
139
+	if !ns.Valid {
140
+		return nil, nil
141
+	}
142
+	return string(ns.BillingProvider), nil
143
+}
144
+
145
+type BillingSubscriptionStatus string
146
+
147
+const (
148
+	BillingSubscriptionStatusNone       BillingSubscriptionStatus = "none"
149
+	BillingSubscriptionStatusIncomplete BillingSubscriptionStatus = "incomplete"
150
+	BillingSubscriptionStatusTrialing   BillingSubscriptionStatus = "trialing"
151
+	BillingSubscriptionStatusActive     BillingSubscriptionStatus = "active"
152
+	BillingSubscriptionStatusPastDue    BillingSubscriptionStatus = "past_due"
153
+	BillingSubscriptionStatusCanceled   BillingSubscriptionStatus = "canceled"
154
+	BillingSubscriptionStatusUnpaid     BillingSubscriptionStatus = "unpaid"
155
+	BillingSubscriptionStatusPaused     BillingSubscriptionStatus = "paused"
156
+)
157
+
158
+func (e *BillingSubscriptionStatus) Scan(src interface{}) error {
159
+	switch s := src.(type) {
160
+	case []byte:
161
+		*e = BillingSubscriptionStatus(s)
162
+	case string:
163
+		*e = BillingSubscriptionStatus(s)
164
+	default:
165
+		return fmt.Errorf("unsupported scan type for BillingSubscriptionStatus: %T", src)
166
+	}
167
+	return nil
168
+}
169
+
170
+type NullBillingSubscriptionStatus struct {
171
+	BillingSubscriptionStatus BillingSubscriptionStatus
172
+	Valid                     bool // Valid is true if BillingSubscriptionStatus is not NULL
173
+}
174
+
175
+// Scan implements the Scanner interface.
176
+func (ns *NullBillingSubscriptionStatus) Scan(value interface{}) error {
177
+	if value == nil {
178
+		ns.BillingSubscriptionStatus, ns.Valid = "", false
179
+		return nil
180
+	}
181
+	ns.Valid = true
182
+	return ns.BillingSubscriptionStatus.Scan(value)
183
+}
184
+
185
+// Value implements the driver Valuer interface.
186
+func (ns NullBillingSubscriptionStatus) Value() (driver.Value, error) {
187
+	if !ns.Valid {
188
+		return nil, nil
189
+	}
190
+	return string(ns.BillingSubscriptionStatus), nil
191
+}
192
+
15193
 type CheckConclusion string
16194
 
17195
 const (
@@ -1601,6 +1779,54 @@ type AuthThrottle struct {
16011779
 	WindowStartedAt pgtype.Timestamptz
16021780
 }
16031781
 
1782
+type BillingInvoice struct {
1783
+	ID                   int64
1784
+	OrgID                int64
1785
+	Provider             BillingProvider
1786
+	StripeInvoiceID      string
1787
+	StripeCustomerID     string
1788
+	StripeSubscriptionID pgtype.Text
1789
+	Status               BillingInvoiceStatus
1790
+	Number               string
1791
+	Currency             string
1792
+	AmountDueCents       int64
1793
+	AmountPaidCents      int64
1794
+	AmountRemainingCents int64
1795
+	HostedInvoiceUrl     string
1796
+	InvoicePdfUrl        string
1797
+	PeriodStart          pgtype.Timestamptz
1798
+	PeriodEnd            pgtype.Timestamptz
1799
+	DueAt                pgtype.Timestamptz
1800
+	PaidAt               pgtype.Timestamptz
1801
+	VoidedAt             pgtype.Timestamptz
1802
+	CreatedAt            pgtype.Timestamptz
1803
+	UpdatedAt            pgtype.Timestamptz
1804
+}
1805
+
1806
+type BillingSeatSnapshot struct {
1807
+	ID                   int64
1808
+	OrgID                int64
1809
+	Provider             BillingProvider
1810
+	StripeSubscriptionID pgtype.Text
1811
+	ActiveMembers        int32
1812
+	BillableSeats        int32
1813
+	Source               string
1814
+	CapturedAt           pgtype.Timestamptz
1815
+}
1816
+
1817
+type BillingWebhookEvent struct {
1818
+	ID                 int64
1819
+	Provider           BillingProvider
1820
+	ProviderEventID    string
1821
+	EventType          string
1822
+	ApiVersion         string
1823
+	Payload            []byte
1824
+	ReceivedAt         pgtype.Timestamptz
1825
+	ProcessedAt        pgtype.Timestamptz
1826
+	ProcessError       string
1827
+	ProcessingAttempts int32
1828
+}
1829
+
16041830
 type BranchProtectionRule struct {
16051831
 	ID                             int64
16061832
 	RepoID                         int64
@@ -1870,6 +2096,30 @@ type Org struct {
18702096
 	UpdatedAt             pgtype.Timestamptz
18712097
 }
18722098
 
2099
+type OrgBillingState struct {
2100
+	OrgID                    int64
2101
+	Provider                 BillingProvider
2102
+	StripeCustomerID         pgtype.Text
2103
+	StripeSubscriptionID     pgtype.Text
2104
+	StripeSubscriptionItemID pgtype.Text
2105
+	Plan                     OrgPlan
2106
+	SubscriptionStatus       BillingSubscriptionStatus
2107
+	BillableSeats            int32
2108
+	SeatSnapshotAt           pgtype.Timestamptz
2109
+	CurrentPeriodStart       pgtype.Timestamptz
2110
+	CurrentPeriodEnd         pgtype.Timestamptz
2111
+	CancelAtPeriodEnd        bool
2112
+	TrialEnd                 pgtype.Timestamptz
2113
+	PastDueAt                pgtype.Timestamptz
2114
+	CanceledAt               pgtype.Timestamptz
2115
+	LockedAt                 pgtype.Timestamptz
2116
+	LockReason               NullBillingLockReason
2117
+	GraceUntil               pgtype.Timestamptz
2118
+	LastWebhookEventID       string
2119
+	CreatedAt                pgtype.Timestamptz
2120
+	UpdatedAt                pgtype.Timestamptz
2121
+}
2122
+
18732123
 type OrgGithubImport struct {
18742124
 	ID                int64
18752125
 	OrgID             int64
internal/users/sqlc/models.gomodified
@@ -12,6 +12,184 @@ import (
1212
 	"github.com/jackc/pgx/v5/pgtype"
1313
 )
1414
 
15
+type BillingInvoiceStatus string
16
+
17
+const (
18
+	BillingInvoiceStatusDraft         BillingInvoiceStatus = "draft"
19
+	BillingInvoiceStatusOpen          BillingInvoiceStatus = "open"
20
+	BillingInvoiceStatusPaid          BillingInvoiceStatus = "paid"
21
+	BillingInvoiceStatusVoid          BillingInvoiceStatus = "void"
22
+	BillingInvoiceStatusUncollectible BillingInvoiceStatus = "uncollectible"
23
+)
24
+
25
+func (e *BillingInvoiceStatus) Scan(src interface{}) error {
26
+	switch s := src.(type) {
27
+	case []byte:
28
+		*e = BillingInvoiceStatus(s)
29
+	case string:
30
+		*e = BillingInvoiceStatus(s)
31
+	default:
32
+		return fmt.Errorf("unsupported scan type for BillingInvoiceStatus: %T", src)
33
+	}
34
+	return nil
35
+}
36
+
37
+type NullBillingInvoiceStatus struct {
38
+	BillingInvoiceStatus BillingInvoiceStatus
39
+	Valid                bool // Valid is true if BillingInvoiceStatus is not NULL
40
+}
41
+
42
+// Scan implements the Scanner interface.
43
+func (ns *NullBillingInvoiceStatus) Scan(value interface{}) error {
44
+	if value == nil {
45
+		ns.BillingInvoiceStatus, ns.Valid = "", false
46
+		return nil
47
+	}
48
+	ns.Valid = true
49
+	return ns.BillingInvoiceStatus.Scan(value)
50
+}
51
+
52
+// Value implements the driver Valuer interface.
53
+func (ns NullBillingInvoiceStatus) Value() (driver.Value, error) {
54
+	if !ns.Valid {
55
+		return nil, nil
56
+	}
57
+	return string(ns.BillingInvoiceStatus), nil
58
+}
59
+
60
+type BillingLockReason string
61
+
62
+const (
63
+	BillingLockReasonPastDue  BillingLockReason = "past_due"
64
+	BillingLockReasonCanceled BillingLockReason = "canceled"
65
+	BillingLockReasonUnpaid   BillingLockReason = "unpaid"
66
+	BillingLockReasonManual   BillingLockReason = "manual"
67
+)
68
+
69
+func (e *BillingLockReason) Scan(src interface{}) error {
70
+	switch s := src.(type) {
71
+	case []byte:
72
+		*e = BillingLockReason(s)
73
+	case string:
74
+		*e = BillingLockReason(s)
75
+	default:
76
+		return fmt.Errorf("unsupported scan type for BillingLockReason: %T", src)
77
+	}
78
+	return nil
79
+}
80
+
81
+type NullBillingLockReason struct {
82
+	BillingLockReason BillingLockReason
83
+	Valid             bool // Valid is true if BillingLockReason is not NULL
84
+}
85
+
86
+// Scan implements the Scanner interface.
87
+func (ns *NullBillingLockReason) Scan(value interface{}) error {
88
+	if value == nil {
89
+		ns.BillingLockReason, ns.Valid = "", false
90
+		return nil
91
+	}
92
+	ns.Valid = true
93
+	return ns.BillingLockReason.Scan(value)
94
+}
95
+
96
+// Value implements the driver Valuer interface.
97
+func (ns NullBillingLockReason) Value() (driver.Value, error) {
98
+	if !ns.Valid {
99
+		return nil, nil
100
+	}
101
+	return string(ns.BillingLockReason), nil
102
+}
103
+
104
+type BillingProvider string
105
+
106
+const (
107
+	BillingProviderStripe BillingProvider = "stripe"
108
+)
109
+
110
+func (e *BillingProvider) Scan(src interface{}) error {
111
+	switch s := src.(type) {
112
+	case []byte:
113
+		*e = BillingProvider(s)
114
+	case string:
115
+		*e = BillingProvider(s)
116
+	default:
117
+		return fmt.Errorf("unsupported scan type for BillingProvider: %T", src)
118
+	}
119
+	return nil
120
+}
121
+
122
+type NullBillingProvider struct {
123
+	BillingProvider BillingProvider
124
+	Valid           bool // Valid is true if BillingProvider is not NULL
125
+}
126
+
127
+// Scan implements the Scanner interface.
128
+func (ns *NullBillingProvider) Scan(value interface{}) error {
129
+	if value == nil {
130
+		ns.BillingProvider, ns.Valid = "", false
131
+		return nil
132
+	}
133
+	ns.Valid = true
134
+	return ns.BillingProvider.Scan(value)
135
+}
136
+
137
+// Value implements the driver Valuer interface.
138
+func (ns NullBillingProvider) Value() (driver.Value, error) {
139
+	if !ns.Valid {
140
+		return nil, nil
141
+	}
142
+	return string(ns.BillingProvider), nil
143
+}
144
+
145
+type BillingSubscriptionStatus string
146
+
147
+const (
148
+	BillingSubscriptionStatusNone       BillingSubscriptionStatus = "none"
149
+	BillingSubscriptionStatusIncomplete BillingSubscriptionStatus = "incomplete"
150
+	BillingSubscriptionStatusTrialing   BillingSubscriptionStatus = "trialing"
151
+	BillingSubscriptionStatusActive     BillingSubscriptionStatus = "active"
152
+	BillingSubscriptionStatusPastDue    BillingSubscriptionStatus = "past_due"
153
+	BillingSubscriptionStatusCanceled   BillingSubscriptionStatus = "canceled"
154
+	BillingSubscriptionStatusUnpaid     BillingSubscriptionStatus = "unpaid"
155
+	BillingSubscriptionStatusPaused     BillingSubscriptionStatus = "paused"
156
+)
157
+
158
+func (e *BillingSubscriptionStatus) Scan(src interface{}) error {
159
+	switch s := src.(type) {
160
+	case []byte:
161
+		*e = BillingSubscriptionStatus(s)
162
+	case string:
163
+		*e = BillingSubscriptionStatus(s)
164
+	default:
165
+		return fmt.Errorf("unsupported scan type for BillingSubscriptionStatus: %T", src)
166
+	}
167
+	return nil
168
+}
169
+
170
+type NullBillingSubscriptionStatus struct {
171
+	BillingSubscriptionStatus BillingSubscriptionStatus
172
+	Valid                     bool // Valid is true if BillingSubscriptionStatus is not NULL
173
+}
174
+
175
+// Scan implements the Scanner interface.
176
+func (ns *NullBillingSubscriptionStatus) Scan(value interface{}) error {
177
+	if value == nil {
178
+		ns.BillingSubscriptionStatus, ns.Valid = "", false
179
+		return nil
180
+	}
181
+	ns.Valid = true
182
+	return ns.BillingSubscriptionStatus.Scan(value)
183
+}
184
+
185
+// Value implements the driver Valuer interface.
186
+func (ns NullBillingSubscriptionStatus) Value() (driver.Value, error) {
187
+	if !ns.Valid {
188
+		return nil, nil
189
+	}
190
+	return string(ns.BillingSubscriptionStatus), nil
191
+}
192
+
15193
 type CheckConclusion string
16194
 
17195
 const (
@@ -1601,6 +1779,54 @@ type AuthThrottle struct {
16011779
 	WindowStartedAt pgtype.Timestamptz
16021780
 }
16031781
 
1782
+type BillingInvoice struct {
1783
+	ID                   int64
1784
+	OrgID                int64
1785
+	Provider             BillingProvider
1786
+	StripeInvoiceID      string
1787
+	StripeCustomerID     string
1788
+	StripeSubscriptionID pgtype.Text
1789
+	Status               BillingInvoiceStatus
1790
+	Number               string
1791
+	Currency             string
1792
+	AmountDueCents       int64
1793
+	AmountPaidCents      int64
1794
+	AmountRemainingCents int64
1795
+	HostedInvoiceUrl     string
1796
+	InvoicePdfUrl        string
1797
+	PeriodStart          pgtype.Timestamptz
1798
+	PeriodEnd            pgtype.Timestamptz
1799
+	DueAt                pgtype.Timestamptz
1800
+	PaidAt               pgtype.Timestamptz
1801
+	VoidedAt             pgtype.Timestamptz
1802
+	CreatedAt            pgtype.Timestamptz
1803
+	UpdatedAt            pgtype.Timestamptz
1804
+}
1805
+
1806
+type BillingSeatSnapshot struct {
1807
+	ID                   int64
1808
+	OrgID                int64
1809
+	Provider             BillingProvider
1810
+	StripeSubscriptionID pgtype.Text
1811
+	ActiveMembers        int32
1812
+	BillableSeats        int32
1813
+	Source               string
1814
+	CapturedAt           pgtype.Timestamptz
1815
+}
1816
+
1817
+type BillingWebhookEvent struct {
1818
+	ID                 int64
1819
+	Provider           BillingProvider
1820
+	ProviderEventID    string
1821
+	EventType          string
1822
+	ApiVersion         string
1823
+	Payload            []byte
1824
+	ReceivedAt         pgtype.Timestamptz
1825
+	ProcessedAt        pgtype.Timestamptz
1826
+	ProcessError       string
1827
+	ProcessingAttempts int32
1828
+}
1829
+
16041830
 type BranchProtectionRule struct {
16051831
 	ID                             int64
16061832
 	RepoID                         int64
@@ -1870,6 +2096,30 @@ type Org struct {
18702096
 	UpdatedAt             pgtype.Timestamptz
18712097
 }
18722098
 
2099
+type OrgBillingState struct {
2100
+	OrgID                    int64
2101
+	Provider                 BillingProvider
2102
+	StripeCustomerID         pgtype.Text
2103
+	StripeSubscriptionID     pgtype.Text
2104
+	StripeSubscriptionItemID pgtype.Text
2105
+	Plan                     OrgPlan
2106
+	SubscriptionStatus       BillingSubscriptionStatus
2107
+	BillableSeats            int32
2108
+	SeatSnapshotAt           pgtype.Timestamptz
2109
+	CurrentPeriodStart       pgtype.Timestamptz
2110
+	CurrentPeriodEnd         pgtype.Timestamptz
2111
+	CancelAtPeriodEnd        bool
2112
+	TrialEnd                 pgtype.Timestamptz
2113
+	PastDueAt                pgtype.Timestamptz
2114
+	CanceledAt               pgtype.Timestamptz
2115
+	LockedAt                 pgtype.Timestamptz
2116
+	LockReason               NullBillingLockReason
2117
+	GraceUntil               pgtype.Timestamptz
2118
+	LastWebhookEventID       string
2119
+	CreatedAt                pgtype.Timestamptz
2120
+	UpdatedAt                pgtype.Timestamptz
2121
+}
2122
+
18732123
 type OrgGithubImport struct {
18742124
 	ID                int64
18752125
 	OrgID             int64
internal/webhook/sqlc/models.gomodified
@@ -12,6 +12,184 @@ import (
1212
 	"github.com/jackc/pgx/v5/pgtype"
1313
 )
1414
 
15
+type BillingInvoiceStatus string
16
+
17
+const (
18
+	BillingInvoiceStatusDraft         BillingInvoiceStatus = "draft"
19
+	BillingInvoiceStatusOpen          BillingInvoiceStatus = "open"
20
+	BillingInvoiceStatusPaid          BillingInvoiceStatus = "paid"
21
+	BillingInvoiceStatusVoid          BillingInvoiceStatus = "void"
22
+	BillingInvoiceStatusUncollectible BillingInvoiceStatus = "uncollectible"
23
+)
24
+
25
+func (e *BillingInvoiceStatus) Scan(src interface{}) error {
26
+	switch s := src.(type) {
27
+	case []byte:
28
+		*e = BillingInvoiceStatus(s)
29
+	case string:
30
+		*e = BillingInvoiceStatus(s)
31
+	default:
32
+		return fmt.Errorf("unsupported scan type for BillingInvoiceStatus: %T", src)
33
+	}
34
+	return nil
35
+}
36
+
37
+type NullBillingInvoiceStatus struct {
38
+	BillingInvoiceStatus BillingInvoiceStatus
39
+	Valid                bool // Valid is true if BillingInvoiceStatus is not NULL
40
+}
41
+
42
+// Scan implements the Scanner interface.
43
+func (ns *NullBillingInvoiceStatus) Scan(value interface{}) error {
44
+	if value == nil {
45
+		ns.BillingInvoiceStatus, ns.Valid = "", false
46
+		return nil
47
+	}
48
+	ns.Valid = true
49
+	return ns.BillingInvoiceStatus.Scan(value)
50
+}
51
+
52
+// Value implements the driver Valuer interface.
53
+func (ns NullBillingInvoiceStatus) Value() (driver.Value, error) {
54
+	if !ns.Valid {
55
+		return nil, nil
56
+	}
57
+	return string(ns.BillingInvoiceStatus), nil
58
+}
59
+
60
+type BillingLockReason string
61
+
62
+const (
63
+	BillingLockReasonPastDue  BillingLockReason = "past_due"
64
+	BillingLockReasonCanceled BillingLockReason = "canceled"
65
+	BillingLockReasonUnpaid   BillingLockReason = "unpaid"
66
+	BillingLockReasonManual   BillingLockReason = "manual"
67
+)
68
+
69
+func (e *BillingLockReason) Scan(src interface{}) error {
70
+	switch s := src.(type) {
71
+	case []byte:
72
+		*e = BillingLockReason(s)
73
+	case string:
74
+		*e = BillingLockReason(s)
75
+	default:
76
+		return fmt.Errorf("unsupported scan type for BillingLockReason: %T", src)
77
+	}
78
+	return nil
79
+}
80
+
81
+type NullBillingLockReason struct {
82
+	BillingLockReason BillingLockReason
83
+	Valid             bool // Valid is true if BillingLockReason is not NULL
84
+}
85
+
86
+// Scan implements the Scanner interface.
87
+func (ns *NullBillingLockReason) Scan(value interface{}) error {
88
+	if value == nil {
89
+		ns.BillingLockReason, ns.Valid = "", false
90
+		return nil
91
+	}
92
+	ns.Valid = true
93
+	return ns.BillingLockReason.Scan(value)
94
+}
95
+
96
+// Value implements the driver Valuer interface.
97
+func (ns NullBillingLockReason) Value() (driver.Value, error) {
98
+	if !ns.Valid {
99
+		return nil, nil
100
+	}
101
+	return string(ns.BillingLockReason), nil
102
+}
103
+
104
+type BillingProvider string
105
+
106
+const (
107
+	BillingProviderStripe BillingProvider = "stripe"
108
+)
109
+
110
+func (e *BillingProvider) Scan(src interface{}) error {
111
+	switch s := src.(type) {
112
+	case []byte:
113
+		*e = BillingProvider(s)
114
+	case string:
115
+		*e = BillingProvider(s)
116
+	default:
117
+		return fmt.Errorf("unsupported scan type for BillingProvider: %T", src)
118
+	}
119
+	return nil
120
+}
121
+
122
+type NullBillingProvider struct {
123
+	BillingProvider BillingProvider
124
+	Valid           bool // Valid is true if BillingProvider is not NULL
125
+}
126
+
127
+// Scan implements the Scanner interface.
128
+func (ns *NullBillingProvider) Scan(value interface{}) error {
129
+	if value == nil {
130
+		ns.BillingProvider, ns.Valid = "", false
131
+		return nil
132
+	}
133
+	ns.Valid = true
134
+	return ns.BillingProvider.Scan(value)
135
+}
136
+
137
+// Value implements the driver Valuer interface.
138
+func (ns NullBillingProvider) Value() (driver.Value, error) {
139
+	if !ns.Valid {
140
+		return nil, nil
141
+	}
142
+	return string(ns.BillingProvider), nil
143
+}
144
+
145
+type BillingSubscriptionStatus string
146
+
147
+const (
148
+	BillingSubscriptionStatusNone       BillingSubscriptionStatus = "none"
149
+	BillingSubscriptionStatusIncomplete BillingSubscriptionStatus = "incomplete"
150
+	BillingSubscriptionStatusTrialing   BillingSubscriptionStatus = "trialing"
151
+	BillingSubscriptionStatusActive     BillingSubscriptionStatus = "active"
152
+	BillingSubscriptionStatusPastDue    BillingSubscriptionStatus = "past_due"
153
+	BillingSubscriptionStatusCanceled   BillingSubscriptionStatus = "canceled"
154
+	BillingSubscriptionStatusUnpaid     BillingSubscriptionStatus = "unpaid"
155
+	BillingSubscriptionStatusPaused     BillingSubscriptionStatus = "paused"
156
+)
157
+
158
+func (e *BillingSubscriptionStatus) Scan(src interface{}) error {
159
+	switch s := src.(type) {
160
+	case []byte:
161
+		*e = BillingSubscriptionStatus(s)
162
+	case string:
163
+		*e = BillingSubscriptionStatus(s)
164
+	default:
165
+		return fmt.Errorf("unsupported scan type for BillingSubscriptionStatus: %T", src)
166
+	}
167
+	return nil
168
+}
169
+
170
+type NullBillingSubscriptionStatus struct {
171
+	BillingSubscriptionStatus BillingSubscriptionStatus
172
+	Valid                     bool // Valid is true if BillingSubscriptionStatus is not NULL
173
+}
174
+
175
+// Scan implements the Scanner interface.
176
+func (ns *NullBillingSubscriptionStatus) Scan(value interface{}) error {
177
+	if value == nil {
178
+		ns.BillingSubscriptionStatus, ns.Valid = "", false
179
+		return nil
180
+	}
181
+	ns.Valid = true
182
+	return ns.BillingSubscriptionStatus.Scan(value)
183
+}
184
+
185
+// Value implements the driver Valuer interface.
186
+func (ns NullBillingSubscriptionStatus) Value() (driver.Value, error) {
187
+	if !ns.Valid {
188
+		return nil, nil
189
+	}
190
+	return string(ns.BillingSubscriptionStatus), nil
191
+}
192
+
15193
 type CheckConclusion string
16194
 
17195
 const (
@@ -1601,6 +1779,54 @@ type AuthThrottle struct {
16011779
 	WindowStartedAt pgtype.Timestamptz
16021780
 }
16031781
 
1782
+type BillingInvoice struct {
1783
+	ID                   int64
1784
+	OrgID                int64
1785
+	Provider             BillingProvider
1786
+	StripeInvoiceID      string
1787
+	StripeCustomerID     string
1788
+	StripeSubscriptionID pgtype.Text
1789
+	Status               BillingInvoiceStatus
1790
+	Number               string
1791
+	Currency             string
1792
+	AmountDueCents       int64
1793
+	AmountPaidCents      int64
1794
+	AmountRemainingCents int64
1795
+	HostedInvoiceUrl     string
1796
+	InvoicePdfUrl        string
1797
+	PeriodStart          pgtype.Timestamptz
1798
+	PeriodEnd            pgtype.Timestamptz
1799
+	DueAt                pgtype.Timestamptz
1800
+	PaidAt               pgtype.Timestamptz
1801
+	VoidedAt             pgtype.Timestamptz
1802
+	CreatedAt            pgtype.Timestamptz
1803
+	UpdatedAt            pgtype.Timestamptz
1804
+}
1805
+
1806
+type BillingSeatSnapshot struct {
1807
+	ID                   int64
1808
+	OrgID                int64
1809
+	Provider             BillingProvider
1810
+	StripeSubscriptionID pgtype.Text
1811
+	ActiveMembers        int32
1812
+	BillableSeats        int32
1813
+	Source               string
1814
+	CapturedAt           pgtype.Timestamptz
1815
+}
1816
+
1817
+type BillingWebhookEvent struct {
1818
+	ID                 int64
1819
+	Provider           BillingProvider
1820
+	ProviderEventID    string
1821
+	EventType          string
1822
+	ApiVersion         string
1823
+	Payload            []byte
1824
+	ReceivedAt         pgtype.Timestamptz
1825
+	ProcessedAt        pgtype.Timestamptz
1826
+	ProcessError       string
1827
+	ProcessingAttempts int32
1828
+}
1829
+
16041830
 type BranchProtectionRule struct {
16051831
 	ID                             int64
16061832
 	RepoID                         int64
@@ -1870,6 +2096,30 @@ type Org struct {
18702096
 	UpdatedAt             pgtype.Timestamptz
18712097
 }
18722098
 
2099
+type OrgBillingState struct {
2100
+	OrgID                    int64
2101
+	Provider                 BillingProvider
2102
+	StripeCustomerID         pgtype.Text
2103
+	StripeSubscriptionID     pgtype.Text
2104
+	StripeSubscriptionItemID pgtype.Text
2105
+	Plan                     OrgPlan
2106
+	SubscriptionStatus       BillingSubscriptionStatus
2107
+	BillableSeats            int32
2108
+	SeatSnapshotAt           pgtype.Timestamptz
2109
+	CurrentPeriodStart       pgtype.Timestamptz
2110
+	CurrentPeriodEnd         pgtype.Timestamptz
2111
+	CancelAtPeriodEnd        bool
2112
+	TrialEnd                 pgtype.Timestamptz
2113
+	PastDueAt                pgtype.Timestamptz
2114
+	CanceledAt               pgtype.Timestamptz
2115
+	LockedAt                 pgtype.Timestamptz
2116
+	LockReason               NullBillingLockReason
2117
+	GraceUntil               pgtype.Timestamptz
2118
+	LastWebhookEventID       string
2119
+	CreatedAt                pgtype.Timestamptz
2120
+	UpdatedAt                pgtype.Timestamptz
2121
+}
2122
+
18732123
 type OrgGithubImport struct {
18742124
 	ID                int64
18752125
 	OrgID             int64
internal/worker/sqlc/models.gomodified
@@ -12,6 +12,184 @@ import (
1212
 	"github.com/jackc/pgx/v5/pgtype"
1313
 )
1414
 
15
+type BillingInvoiceStatus string
16
+
17
+const (
18
+	BillingInvoiceStatusDraft         BillingInvoiceStatus = "draft"
19
+	BillingInvoiceStatusOpen          BillingInvoiceStatus = "open"
20
+	BillingInvoiceStatusPaid          BillingInvoiceStatus = "paid"
21
+	BillingInvoiceStatusVoid          BillingInvoiceStatus = "void"
22
+	BillingInvoiceStatusUncollectible BillingInvoiceStatus = "uncollectible"
23
+)
24
+
25
+func (e *BillingInvoiceStatus) Scan(src interface{}) error {
26
+	switch s := src.(type) {
27
+	case []byte:
28
+		*e = BillingInvoiceStatus(s)
29
+	case string:
30
+		*e = BillingInvoiceStatus(s)
31
+	default:
32
+		return fmt.Errorf("unsupported scan type for BillingInvoiceStatus: %T", src)
33
+	}
34
+	return nil
35
+}
36
+
37
+type NullBillingInvoiceStatus struct {
38
+	BillingInvoiceStatus BillingInvoiceStatus
39
+	Valid                bool // Valid is true if BillingInvoiceStatus is not NULL
40
+}
41
+
42
+// Scan implements the Scanner interface.
43
+func (ns *NullBillingInvoiceStatus) Scan(value interface{}) error {
44
+	if value == nil {
45
+		ns.BillingInvoiceStatus, ns.Valid = "", false
46
+		return nil
47
+	}
48
+	ns.Valid = true
49
+	return ns.BillingInvoiceStatus.Scan(value)
50
+}
51
+
52
+// Value implements the driver Valuer interface.
53
+func (ns NullBillingInvoiceStatus) Value() (driver.Value, error) {
54
+	if !ns.Valid {
55
+		return nil, nil
56
+	}
57
+	return string(ns.BillingInvoiceStatus), nil
58
+}
59
+
60
+type BillingLockReason string
61
+
62
+const (
63
+	BillingLockReasonPastDue  BillingLockReason = "past_due"
64
+	BillingLockReasonCanceled BillingLockReason = "canceled"
65
+	BillingLockReasonUnpaid   BillingLockReason = "unpaid"
66
+	BillingLockReasonManual   BillingLockReason = "manual"
67
+)
68
+
69
+func (e *BillingLockReason) Scan(src interface{}) error {
70
+	switch s := src.(type) {
71
+	case []byte:
72
+		*e = BillingLockReason(s)
73
+	case string:
74
+		*e = BillingLockReason(s)
75
+	default:
76
+		return fmt.Errorf("unsupported scan type for BillingLockReason: %T", src)
77
+	}
78
+	return nil
79
+}
80
+
81
+type NullBillingLockReason struct {
82
+	BillingLockReason BillingLockReason
83
+	Valid             bool // Valid is true if BillingLockReason is not NULL
84
+}
85
+
86
+// Scan implements the Scanner interface.
87
+func (ns *NullBillingLockReason) Scan(value interface{}) error {
88
+	if value == nil {
89
+		ns.BillingLockReason, ns.Valid = "", false
90
+		return nil
91
+	}
92
+	ns.Valid = true
93
+	return ns.BillingLockReason.Scan(value)
94
+}
95
+
96
+// Value implements the driver Valuer interface.
97
+func (ns NullBillingLockReason) Value() (driver.Value, error) {
98
+	if !ns.Valid {
99
+		return nil, nil
100
+	}
101
+	return string(ns.BillingLockReason), nil
102
+}
103
+
104
+type BillingProvider string
105
+
106
+const (
107
+	BillingProviderStripe BillingProvider = "stripe"
108
+)
109
+
110
+func (e *BillingProvider) Scan(src interface{}) error {
111
+	switch s := src.(type) {
112
+	case []byte:
113
+		*e = BillingProvider(s)
114
+	case string:
115
+		*e = BillingProvider(s)
116
+	default:
117
+		return fmt.Errorf("unsupported scan type for BillingProvider: %T", src)
118
+	}
119
+	return nil
120
+}
121
+
122
+type NullBillingProvider struct {
123
+	BillingProvider BillingProvider
124
+	Valid           bool // Valid is true if BillingProvider is not NULL
125
+}
126
+
127
+// Scan implements the Scanner interface.
128
+func (ns *NullBillingProvider) Scan(value interface{}) error {
129
+	if value == nil {
130
+		ns.BillingProvider, ns.Valid = "", false
131
+		return nil
132
+	}
133
+	ns.Valid = true
134
+	return ns.BillingProvider.Scan(value)
135
+}
136
+
137
+// Value implements the driver Valuer interface.
138
+func (ns NullBillingProvider) Value() (driver.Value, error) {
139
+	if !ns.Valid {
140
+		return nil, nil
141
+	}
142
+	return string(ns.BillingProvider), nil
143
+}
144
+
145
+type BillingSubscriptionStatus string
146
+
147
+const (
148
+	BillingSubscriptionStatusNone       BillingSubscriptionStatus = "none"
149
+	BillingSubscriptionStatusIncomplete BillingSubscriptionStatus = "incomplete"
150
+	BillingSubscriptionStatusTrialing   BillingSubscriptionStatus = "trialing"
151
+	BillingSubscriptionStatusActive     BillingSubscriptionStatus = "active"
152
+	BillingSubscriptionStatusPastDue    BillingSubscriptionStatus = "past_due"
153
+	BillingSubscriptionStatusCanceled   BillingSubscriptionStatus = "canceled"
154
+	BillingSubscriptionStatusUnpaid     BillingSubscriptionStatus = "unpaid"
155
+	BillingSubscriptionStatusPaused     BillingSubscriptionStatus = "paused"
156
+)
157
+
158
+func (e *BillingSubscriptionStatus) Scan(src interface{}) error {
159
+	switch s := src.(type) {
160
+	case []byte:
161
+		*e = BillingSubscriptionStatus(s)
162
+	case string:
163
+		*e = BillingSubscriptionStatus(s)
164
+	default:
165
+		return fmt.Errorf("unsupported scan type for BillingSubscriptionStatus: %T", src)
166
+	}
167
+	return nil
168
+}
169
+
170
+type NullBillingSubscriptionStatus struct {
171
+	BillingSubscriptionStatus BillingSubscriptionStatus
172
+	Valid                     bool // Valid is true if BillingSubscriptionStatus is not NULL
173
+}
174
+
175
+// Scan implements the Scanner interface.
176
+func (ns *NullBillingSubscriptionStatus) Scan(value interface{}) error {
177
+	if value == nil {
178
+		ns.BillingSubscriptionStatus, ns.Valid = "", false
179
+		return nil
180
+	}
181
+	ns.Valid = true
182
+	return ns.BillingSubscriptionStatus.Scan(value)
183
+}
184
+
185
+// Value implements the driver Valuer interface.
186
+func (ns NullBillingSubscriptionStatus) Value() (driver.Value, error) {
187
+	if !ns.Valid {
188
+		return nil, nil
189
+	}
190
+	return string(ns.BillingSubscriptionStatus), nil
191
+}
192
+
15193
 type CheckConclusion string
16194
 
17195
 const (
@@ -1601,6 +1779,54 @@ type AuthThrottle struct {
16011779
 	WindowStartedAt pgtype.Timestamptz
16021780
 }
16031781
 
1782
+type BillingInvoice struct {
1783
+	ID                   int64
1784
+	OrgID                int64
1785
+	Provider             BillingProvider
1786
+	StripeInvoiceID      string
1787
+	StripeCustomerID     string
1788
+	StripeSubscriptionID pgtype.Text
1789
+	Status               BillingInvoiceStatus
1790
+	Number               string
1791
+	Currency             string
1792
+	AmountDueCents       int64
1793
+	AmountPaidCents      int64
1794
+	AmountRemainingCents int64
1795
+	HostedInvoiceUrl     string
1796
+	InvoicePdfUrl        string
1797
+	PeriodStart          pgtype.Timestamptz
1798
+	PeriodEnd            pgtype.Timestamptz
1799
+	DueAt                pgtype.Timestamptz
1800
+	PaidAt               pgtype.Timestamptz
1801
+	VoidedAt             pgtype.Timestamptz
1802
+	CreatedAt            pgtype.Timestamptz
1803
+	UpdatedAt            pgtype.Timestamptz
1804
+}
1805
+
1806
+type BillingSeatSnapshot struct {
1807
+	ID                   int64
1808
+	OrgID                int64
1809
+	Provider             BillingProvider
1810
+	StripeSubscriptionID pgtype.Text
1811
+	ActiveMembers        int32
1812
+	BillableSeats        int32
1813
+	Source               string
1814
+	CapturedAt           pgtype.Timestamptz
1815
+}
1816
+
1817
+type BillingWebhookEvent struct {
1818
+	ID                 int64
1819
+	Provider           BillingProvider
1820
+	ProviderEventID    string
1821
+	EventType          string
1822
+	ApiVersion         string
1823
+	Payload            []byte
1824
+	ReceivedAt         pgtype.Timestamptz
1825
+	ProcessedAt        pgtype.Timestamptz
1826
+	ProcessError       string
1827
+	ProcessingAttempts int32
1828
+}
1829
+
16041830
 type BranchProtectionRule struct {
16051831
 	ID                             int64
16061832
 	RepoID                         int64
@@ -1870,6 +2096,30 @@ type Org struct {
18702096
 	UpdatedAt             pgtype.Timestamptz
18712097
 }
18722098
 
2099
+type OrgBillingState struct {
2100
+	OrgID                    int64
2101
+	Provider                 BillingProvider
2102
+	StripeCustomerID         pgtype.Text
2103
+	StripeSubscriptionID     pgtype.Text
2104
+	StripeSubscriptionItemID pgtype.Text
2105
+	Plan                     OrgPlan
2106
+	SubscriptionStatus       BillingSubscriptionStatus
2107
+	BillableSeats            int32
2108
+	SeatSnapshotAt           pgtype.Timestamptz
2109
+	CurrentPeriodStart       pgtype.Timestamptz
2110
+	CurrentPeriodEnd         pgtype.Timestamptz
2111
+	CancelAtPeriodEnd        bool
2112
+	TrialEnd                 pgtype.Timestamptz
2113
+	PastDueAt                pgtype.Timestamptz
2114
+	CanceledAt               pgtype.Timestamptz
2115
+	LockedAt                 pgtype.Timestamptz
2116
+	LockReason               NullBillingLockReason
2117
+	GraceUntil               pgtype.Timestamptz
2118
+	LastWebhookEventID       string
2119
+	CreatedAt                pgtype.Timestamptz
2120
+	UpdatedAt                pgtype.Timestamptz
2121
+}
2122
+
18732123
 type OrgGithubImport struct {
18742124
 	ID                int64
18752125
 	OrgID             int64
sqlc.yamlmodified
@@ -241,3 +241,19 @@ sql:
241241
         emit_exact_table_names: false
242242
         emit_empty_slices: true
243243
         emit_methods_with_db_argument: true
244
+
245
+  - engine: postgresql
246
+    schema: internal/migrationsfs/migrations
247
+    queries: internal/billing/queries
248
+    gen:
249
+      go:
250
+        package: billingdb
251
+        out: internal/billing/sqlc
252
+        sql_package: pgx/v5
253
+        emit_json_tags: false
254
+        emit_pointers_for_null_types: false
255
+        emit_prepared_queries: false
256
+        emit_interface: true
257
+        emit_exact_table_names: false
258
+        emit_empty_slices: true
259
+        emit_methods_with_db_argument: true