@@ -16,6 +16,10 @@ import (
16
16
"github.com/stripe/stripe-go/v72/client"
17
17
)
18
18
19
+ const (
20
+ reportIDMetadataKey = "reportId"
21
+ )
22
+
19
23
type Client struct {
20
24
sc * client.API
21
25
}
@@ -58,9 +62,14 @@ type Invoice struct {
58
62
Credits int64
59
63
}
60
64
65
+ type CreditSummary struct {
66
+ Credits int64
67
+ ReportID string
68
+ }
69
+
61
70
// UpdateUsage updates teams' Stripe subscriptions with usage data
62
71
// `usageForTeam` is a map from team name to total workspace seconds used within a billing period.
63
- func (c * Client ) UpdateUsage (ctx context.Context , creditsPerTeam map [string ]int64 ) error {
72
+ func (c * Client ) UpdateUsage (ctx context.Context , creditsPerTeam map [string ]CreditSummary ) error {
64
73
teamIds := make ([]string , 0 , len (creditsPerTeam ))
65
74
for k := range creditsPerTeam {
66
75
teamIds = append (teamIds , k )
@@ -117,7 +126,7 @@ func (c *Client) findCustomers(ctx context.Context, query string) ([]*stripe.Cus
117
126
return customers , nil
118
127
}
119
128
120
- func (c * Client ) updateUsageForCustomer (ctx context.Context , customer * stripe.Customer , credits int64 ) (* UsageRecord , error ) {
129
+ func (c * Client ) updateUsageForCustomer (ctx context.Context , customer * stripe.Customer , summary CreditSummary ) (* UsageRecord , error ) {
121
130
subscriptions := customer .Subscriptions .Data
122
131
if len (subscriptions ) != 1 {
123
132
return nil , fmt .Errorf ("customer has an unexpected number of subscriptions %v (expected 1, got %d)" , subscriptions , len (subscriptions ))
@@ -136,15 +145,27 @@ func (c *Client) updateUsageForCustomer(ctx context.Context, customer *stripe.Cu
136
145
Context : ctx ,
137
146
},
138
147
SubscriptionItem : stripe .String (subscriptionItemId ),
139
- Quantity : stripe .Int64 (credits ),
148
+ Quantity : stripe .Int64 (summary . Credits ),
140
149
})
141
150
if err != nil {
142
151
return nil , fmt .Errorf ("failed to register usage for customer %q on subscription item %s" , customer .Name , subscriptionItemId )
143
152
}
144
153
154
+ invoice , err := c .GetUpcomingInvoice (ctx , customer .ID )
155
+ if err != nil {
156
+ return nil , fmt .Errorf ("failed to find upcoming invoice for customer %s: %w" , customer .ID , err )
157
+ }
158
+
159
+ _ , err = c .UpdateInvoiceMetadata (ctx , invoice .ID , map [string ]string {
160
+ reportIDMetadataKey : summary .ReportID ,
161
+ })
162
+ if err != nil {
163
+ return nil , fmt .Errorf ("failed to udpate invoice %s metadata with report ID: %w" , invoice .ID , err )
164
+ }
165
+
145
166
return & UsageRecord {
146
167
SubscriptionItemID : subscriptionItemId ,
147
- Quantity : credits ,
168
+ Quantity : summary . Credits ,
148
169
}, nil
149
170
}
150
171
@@ -205,6 +226,20 @@ func (c *Client) GetUpcomingInvoice(ctx context.Context, customerID string) (*In
205
226
}, nil
206
227
}
207
228
229
+ func (c * Client ) UpdateInvoiceMetadata (ctx context.Context , invoiceID string , metadata map [string ]string ) (* stripe.Invoice , error ) {
230
+ invoice , err := c .sc .Invoices .Update (invoiceID , & stripe.InvoiceParams {
231
+ Params : stripe.Params {
232
+ Context : ctx ,
233
+ Metadata : metadata ,
234
+ },
235
+ })
236
+ if err != nil {
237
+ return nil , fmt .Errorf ("failed to update invoice %s metadata: %w" , invoiceID , err )
238
+ }
239
+
240
+ return invoice , nil
241
+ }
242
+
208
243
// queriesForCustomersWithTeamIds constructs Stripe query strings to find the Stripe Customer for each teamId
209
244
// It returns multiple queries, each being a big disjunction of subclauses so that we can process multiple teamIds in one query.
210
245
// `clausesPerQuery` is a limit enforced by the Stripe API.
0 commit comments