Skip to content

Commit d377bbf

Browse files
committed
fix up
1 parent 4a6476e commit d377bbf

File tree

3 files changed

+66
-9
lines changed

3 files changed

+66
-9
lines changed

components/usage/pkg/apiv1/billing.go

+52-8
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"context"
99
"github.com/gitpod-io/gitpod/usage/pkg/contentservice"
1010
"fmt"
11+
"google.golang.org/protobuf/types/known/timestamppb"
1112
"math"
1213
"time"
1314

@@ -67,31 +68,74 @@ func (s *BillingService) UpdateInvoices(ctx context.Context, in *v1.UpdateInvoic
6768
}
6869

6970
func (s *BillingService) FinalizeInvoice(ctx context.Context, in *v1.FinalizeInvoiceRequest) (*v1.FinalizeInvoiceResponse, error) {
70-
log.Infof("Finalizing invoice for invoice %q", in.GetInvoiceId())
71+
logger := log.WithField("invoice_id", in.GetInvoiceId())
7172

7273
if in.GetInvoiceId() == "" {
7374
return nil, status.Errorf(codes.InvalidArgument, "Missing InvoiceID")
7475
}
7576

76-
invoiceID := in.GetInvoiceId()
77-
78-
invoice, err := s.stripeClient.GetInvoice(ctx, invoiceID)
77+
invoice, err := s.stripeClient.GetInvoice(ctx, in.GetInvoiceId())
7978
if err != nil {
80-
return nil, status.Errorf(codes.NotFound, "Failed to get invoice with ID %s: %s", invoiceID, err.Error())
79+
logger.WithError(err).Error("Failed to retrieve invoice from Stripe.")
80+
return nil, status.Errorf(codes.NotFound, "Failed to get invoice with ID %s: %s", in.GetInvoiceId(), err.Error())
8181
}
8282

8383
reportID, found := invoice.Metadata[stripe.ReportIDMetadataKey]
8484
if !found {
85-
return nil, status.Errorf(codes.NotFound, "Invoice %s does not contain reportID", invoiceID)
85+
logger.Error("Failed to find report ID metadata on invoice from Stripe.")
86+
return nil, status.Errorf(codes.NotFound, "Invoice %s does not contain reportID", in.GetInvoiceId())
87+
}
88+
logger = logger.WithField("report_id", reportID)
89+
90+
subscription := invoice.Subscription
91+
if subscription == nil {
92+
logger.Error("No subscription information available for invoice.")
93+
return nil, status.Errorf(codes.Internal, "Failed to retrieve subscription details from invoice.")
8694
}
8795

96+
teamID, found := subscription.Metadata[stripe.TeamIDMetadataKey]
97+
if !found {
98+
logger.Error("Failed to find teamID from subscription metadata.")
99+
return nil, status.Errorf(codes.Internal, "Failed to extra teamID from Stripe subscription.")
100+
}
101+
logger = logger.WithField("team_id", teamID)
102+
103+
attributionID := db.NewTeamAttributionID(teamID)
104+
105+
// To support individual `user`s, we'll need to also extract the `userId` from metadata here and handle separately.
106+
88107
report, err := s.contentService.DownloadUsageReport(ctx, reportID)
89108
if err != nil {
109+
logger.WithError(err).Error("Failed to retrieve usage report from content service.")
90110
return nil, status.Errorf(codes.Internal, "Failed to download usage report.")
91111
}
92112

93-
// need to identify which AttributionID this finalize invoice event is for, how do we do that?
94-
fmt.Println(report)
113+
for _, session := range report {
114+
if session.AttributionID == attributionID {
115+
116+
}
117+
}
118+
119+
invoicedSessions := report.FilterToAttributionID(attributionID)
120+
var errors []error
121+
for _, session := range invoicedSessions {
122+
_, err := s.SetBilledSession(ctx, &v1.SetBilledSessionRequest{
123+
InstanceId: session.InstanceID.String(),
124+
From: timestamppb.New(session.StartedAt),
125+
System: v1.System_SYSTEM_STRIPE,
126+
})
127+
if err != nil {
128+
logger.WithField("workspace_instance_id", session.InstanceID).WithError(err).Error("Failed to mark session as billed by Stripe.")
129+
errors = append(errors, err)
130+
}
131+
}
132+
133+
if len(errors) != 0 {
134+
logger.Errorf("Failed to mark %d sessions as billed. You have to update them manually!")
135+
// TODO(milan): Add metrics and alert on this!
136+
137+
return nil, status.Errorf(codes.Internal, "Failed to mark %d sessions as billed by stripe.")
138+
}
95139

96140
return &v1.FinalizeInvoiceResponse{}, nil
97141
}

components/usage/pkg/db/workspace_instance_usage.go

+11
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,14 @@ func ListUsage(ctx context.Context, conn *gorm.DB, attributionId AttributionID,
9191
}
9292

9393
type UsageReport []WorkspaceInstanceUsage
94+
95+
func (r UsageReport) FilterToAttributionID(attributionID AttributionID) UsageReport {
96+
var sessions []WorkspaceInstanceUsage
97+
for _, sess := range r {
98+
if sess.AttributionID == attributionID {
99+
sessions = append(sessions, sess)
100+
}
101+
}
102+
103+
return sessions
104+
}

components/usage/pkg/stripe/stripe.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818

1919
const (
2020
ReportIDMetadataKey = "reportId"
21+
TeamIDMetadataKey = "teamId"
2122
)
2223

2324
type Client struct {
@@ -248,6 +249,7 @@ func (c *Client) GetInvoice(ctx context.Context, invoiceID string) (*stripe.Invo
248249
invoice, err := c.sc.Invoices.Get(invoiceID, &stripe.InvoiceParams{
249250
Params: stripe.Params{
250251
Context: ctx,
252+
Expand: []*string{stripe.String("data.subscriptions")},
251253
},
252254
})
253255
if err != nil {
@@ -267,7 +269,7 @@ func queriesForCustomersWithTeamIds(teamIds []string) []string {
267269
for i := 0; i < len(teamIds); i += clausesPerQuery {
268270
sb.Reset()
269271
for j := 0; j < clausesPerQuery && i+j < len(teamIds); j++ {
270-
sb.WriteString(fmt.Sprintf("metadata['teamId']:'%s'", teamIds[i+j]))
272+
sb.WriteString(fmt.Sprintf("metadata['%s']:'%s'", TeamIDMetadataKey, teamIds[i+j]))
271273
if j < clausesPerQuery-1 && i+j < len(teamIds)-1 {
272274
sb.WriteString(" OR ")
273275
}

0 commit comments

Comments
 (0)