@@ -16,6 +16,10 @@ import (
1616 "github.com/stripe/stripe-go/v72/client"
1717)
1818
19+ const (
20+ reportIDMetadataKey = "reportId"
21+ )
22+
1923type Client struct {
2024 sc * client.API
2125}
@@ -58,9 +62,14 @@ type Invoice struct {
5862 Credits int64
5963}
6064
65+ type CreditSummary struct {
66+ Credits int64
67+ ReportID string
68+ }
69+
6170// UpdateUsage updates teams' Stripe subscriptions with usage data
6271// `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 {
6473 teamIds := make ([]string , 0 , len (creditsPerTeam ))
6574 for k := range creditsPerTeam {
6675 teamIds = append (teamIds , k )
@@ -117,7 +126,7 @@ func (c *Client) findCustomers(ctx context.Context, query string) ([]*stripe.Cus
117126 return customers , nil
118127}
119128
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 ) {
121130 subscriptions := customer .Subscriptions .Data
122131 if len (subscriptions ) != 1 {
123132 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
136145 Context : ctx ,
137146 },
138147 SubscriptionItem : stripe .String (subscriptionItemId ),
139- Quantity : stripe .Int64 (credits ),
148+ Quantity : stripe .Int64 (summary . Credits ),
140149 })
141150 if err != nil {
142151 return nil , fmt .Errorf ("failed to register usage for customer %q on subscription item %s" , customer .Name , subscriptionItemId )
143152 }
144153
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+
145166 return & UsageRecord {
146167 SubscriptionItemID : subscriptionItemId ,
147- Quantity : credits ,
168+ Quantity : summary . Credits ,
148169 }, nil
149170}
150171
@@ -205,6 +226,20 @@ func (c *Client) GetUpcomingInvoice(ctx context.Context, customerID string) (*In
205226 }, nil
206227}
207228
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+
208243// queriesForCustomersWithTeamIds constructs Stripe query strings to find the Stripe Customer for each teamId
209244// It returns multiple queries, each being a big disjunction of subclauses so that we can process multiple teamIds in one query.
210245// `clausesPerQuery` is a limit enforced by the Stripe API.
0 commit comments