diff --git a/components/server/ee/src/billing/billing-service.ts b/components/server/ee/src/billing/billing-service.ts index 1294fa8844a79e..d890f3c6924f1c 100644 --- a/components/server/ee/src/billing/billing-service.ts +++ b/components/server/ee/src/billing/billing-service.ts @@ -7,10 +7,12 @@ import { CostCenterDB } from "@gitpod/gitpod-db/lib"; import { User } from "@gitpod/gitpod-protocol"; import { AttributionId } from "@gitpod/gitpod-protocol/lib/attribution"; -import { BillableSession, BillableSessionRequest, SortOrder } from "@gitpod/gitpod-protocol/lib/usage"; import { log } from "@gitpod/gitpod-protocol/lib/util/logging"; -import { CachingUsageServiceClientProvider, UsageService } from "@gitpod/usage-api/lib/usage/v1/sugar"; -import { Timestamp } from "google-protobuf/google/protobuf/timestamp_pb"; +import { GetUpcomingInvoiceResponse } from "@gitpod/usage-api/lib/usage/v1/billing_pb"; +import { + CachingUsageServiceClientProvider, + CachingBillingServiceClientProvider, +} from "@gitpod/usage-api/lib/usage/v1/sugar"; import { inject, injectable } from "inversify"; import { UserService } from "../../../src/user/user-service"; @@ -26,6 +28,8 @@ export class BillingService { @inject(CostCenterDB) protected readonly costCenterDB: CostCenterDB; @inject(CachingUsageServiceClientProvider) protected readonly usageServiceClientProvider: CachingUsageServiceClientProvider; + @inject(CachingBillingServiceClientProvider) + protected readonly billingServiceClientProvider: CachingBillingServiceClientProvider; async checkSpendingLimitReached(user: User): Promise { const attributionId = await this.userService.getWorkspaceUsageAttributionId(user); @@ -40,50 +44,39 @@ export class BillingService { }; } - const allSessions = await this.listBilledUsage({ - attributionId: AttributionId.render(attributionId), - startedTimeOrder: SortOrder.Descending, - }); - const totalUsage = allSessions.map((s) => s.credits).reduce((a, b) => a + b, 0); - if (totalUsage >= costCenter.spendingLimit) { + const upcomingInvoice = await this.getUpcomingInvoice(attributionId); + const currentInvoiceCredits = upcomingInvoice.getCredits(); + if (currentInvoiceCredits >= costCenter.spendingLimit) { + log.info({ userId: user.id }, "Spending limit reached", { + attributionId, + currentInvoiceCredits, + spendingLimit: costCenter.spendingLimit, + }); return { reached: true, attributionId, }; - } else if (totalUsage > costCenter.spendingLimit * 0.8) { + } else if (currentInvoiceCredits > costCenter.spendingLimit * 0.8) { + log.info({ userId: user.id }, "Spending limit almost reached", { + attributionId, + currentInvoiceCredits, + spendingLimit: costCenter.spendingLimit, + }); return { reached: false, almostReached: true, attributionId, }; } + return { reached: false, attributionId, }; } - // TODO (gpl): Replace this with call to stripeService.getInvoice() - async listBilledUsage(req: BillableSessionRequest): Promise { - const { attributionId, startedTimeOrder, from, to } = req; - let timestampFrom; - let timestampTo; - - if (from) { - timestampFrom = Timestamp.fromDate(new Date(from)); - } - if (to) { - timestampTo = Timestamp.fromDate(new Date(to)); - } - const usageClient = this.usageServiceClientProvider.getDefault(); - const response = await usageClient.listBilledUsage( - {}, - attributionId, - startedTimeOrder as number, - timestampFrom, - timestampTo, - ); - const sessions = response.getSessionsList().map((s) => UsageService.mapBilledSession(s)); - return sessions; + async getUpcomingInvoice(attributionId: AttributionId): Promise { + const response = await this.billingServiceClientProvider.getDefault().getUpcomingInvoice(attributionId); + return response; } } diff --git a/components/usage-api/go/v1/billing.pb.go b/components/usage-api/go/v1/billing.pb.go index 97f6730cfa4a5b..784c6b867b434d 100644 --- a/components/usage-api/go/v1/billing.pb.go +++ b/components/usage-api/go/v1/billing.pb.go @@ -184,20 +184,19 @@ func (*UpdateInvoicesResponse) Descriptor() ([]byte, []int) { return file_usage_v1_billing_proto_rawDescGZIP(), []int{1} } -type GetLatestInvoiceRequest struct { +type GetUpcomingInvoiceRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Types that are assignable to Identifier: - // - // *GetLatestInvoiceRequest_TeamId - // *GetLatestInvoiceRequest_UserId - Identifier isGetLatestInvoiceRequest_Identifier `protobuf_oneof:"identifier"` + // *GetUpcomingInvoiceRequest_TeamId + // *GetUpcomingInvoiceRequest_UserId + Identifier isGetUpcomingInvoiceRequest_Identifier `protobuf_oneof:"identifier"` } -func (x *GetLatestInvoiceRequest) Reset() { - *x = GetLatestInvoiceRequest{} +func (x *GetUpcomingInvoiceRequest) Reset() { + *x = GetUpcomingInvoiceRequest{} if protoimpl.UnsafeEnabled { mi := &file_usage_v1_billing_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -205,13 +204,13 @@ func (x *GetLatestInvoiceRequest) Reset() { } } -func (x *GetLatestInvoiceRequest) String() string { +func (x *GetUpcomingInvoiceRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*GetLatestInvoiceRequest) ProtoMessage() {} +func (*GetUpcomingInvoiceRequest) ProtoMessage() {} -func (x *GetLatestInvoiceRequest) ProtoReflect() protoreflect.Message { +func (x *GetUpcomingInvoiceRequest) ProtoReflect() protoreflect.Message { mi := &file_usage_v1_billing_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -223,49 +222,49 @@ func (x *GetLatestInvoiceRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use GetLatestInvoiceRequest.ProtoReflect.Descriptor instead. -func (*GetLatestInvoiceRequest) Descriptor() ([]byte, []int) { +// Deprecated: Use GetUpcomingInvoiceRequest.ProtoReflect.Descriptor instead. +func (*GetUpcomingInvoiceRequest) Descriptor() ([]byte, []int) { return file_usage_v1_billing_proto_rawDescGZIP(), []int{2} } -func (m *GetLatestInvoiceRequest) GetIdentifier() isGetLatestInvoiceRequest_Identifier { +func (m *GetUpcomingInvoiceRequest) GetIdentifier() isGetUpcomingInvoiceRequest_Identifier { if m != nil { return m.Identifier } return nil } -func (x *GetLatestInvoiceRequest) GetTeamId() string { - if x, ok := x.GetIdentifier().(*GetLatestInvoiceRequest_TeamId); ok { +func (x *GetUpcomingInvoiceRequest) GetTeamId() string { + if x, ok := x.GetIdentifier().(*GetUpcomingInvoiceRequest_TeamId); ok { return x.TeamId } return "" } -func (x *GetLatestInvoiceRequest) GetUserId() string { - if x, ok := x.GetIdentifier().(*GetLatestInvoiceRequest_UserId); ok { +func (x *GetUpcomingInvoiceRequest) GetUserId() string { + if x, ok := x.GetIdentifier().(*GetUpcomingInvoiceRequest_UserId); ok { return x.UserId } return "" } -type isGetLatestInvoiceRequest_Identifier interface { - isGetLatestInvoiceRequest_Identifier() +type isGetUpcomingInvoiceRequest_Identifier interface { + isGetUpcomingInvoiceRequest_Identifier() } -type GetLatestInvoiceRequest_TeamId struct { +type GetUpcomingInvoiceRequest_TeamId struct { TeamId string `protobuf:"bytes,1,opt,name=team_id,json=teamId,proto3,oneof"` } -type GetLatestInvoiceRequest_UserId struct { +type GetUpcomingInvoiceRequest_UserId struct { UserId string `protobuf:"bytes,2,opt,name=user_id,json=userId,proto3,oneof"` } -func (*GetLatestInvoiceRequest_TeamId) isGetLatestInvoiceRequest_Identifier() {} +func (*GetUpcomingInvoiceRequest_TeamId) isGetUpcomingInvoiceRequest_Identifier() {} -func (*GetLatestInvoiceRequest_UserId) isGetLatestInvoiceRequest_Identifier() {} +func (*GetUpcomingInvoiceRequest_UserId) isGetUpcomingInvoiceRequest_Identifier() {} -type GetLatestInvoiceResponse struct { +type GetUpcomingInvoiceResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -273,10 +272,11 @@ type GetLatestInvoiceResponse struct { InvoiceId string `protobuf:"bytes,1,opt,name=invoice_id,json=invoiceId,proto3" json:"invoice_id,omitempty"` Currency string `protobuf:"bytes,2,opt,name=currency,proto3" json:"currency,omitempty"` Amount float64 `protobuf:"fixed64,3,opt,name=amount,proto3" json:"amount,omitempty"` + Credits int64 `protobuf:"varint,4,opt,name=credits,proto3" json:"credits,omitempty"` } -func (x *GetLatestInvoiceResponse) Reset() { - *x = GetLatestInvoiceResponse{} +func (x *GetUpcomingInvoiceResponse) Reset() { + *x = GetUpcomingInvoiceResponse{} if protoimpl.UnsafeEnabled { mi := &file_usage_v1_billing_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -284,13 +284,13 @@ func (x *GetLatestInvoiceResponse) Reset() { } } -func (x *GetLatestInvoiceResponse) String() string { +func (x *GetUpcomingInvoiceResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*GetLatestInvoiceResponse) ProtoMessage() {} +func (*GetUpcomingInvoiceResponse) ProtoMessage() {} -func (x *GetLatestInvoiceResponse) ProtoReflect() protoreflect.Message { +func (x *GetUpcomingInvoiceResponse) ProtoReflect() protoreflect.Message { mi := &file_usage_v1_billing_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -302,32 +302,39 @@ func (x *GetLatestInvoiceResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use GetLatestInvoiceResponse.ProtoReflect.Descriptor instead. -func (*GetLatestInvoiceResponse) Descriptor() ([]byte, []int) { +// Deprecated: Use GetUpcomingInvoiceResponse.ProtoReflect.Descriptor instead. +func (*GetUpcomingInvoiceResponse) Descriptor() ([]byte, []int) { return file_usage_v1_billing_proto_rawDescGZIP(), []int{3} } -func (x *GetLatestInvoiceResponse) GetInvoiceId() string { +func (x *GetUpcomingInvoiceResponse) GetInvoiceId() string { if x != nil { return x.InvoiceId } return "" } -func (x *GetLatestInvoiceResponse) GetCurrency() string { +func (x *GetUpcomingInvoiceResponse) GetCurrency() string { if x != nil { return x.Currency } return "" } -func (x *GetLatestInvoiceResponse) GetAmount() float64 { +func (x *GetUpcomingInvoiceResponse) GetAmount() float64 { if x != nil { return x.Amount } return 0 } +func (x *GetUpcomingInvoiceResponse) GetCredits() int64 { + if x != nil { + return x.Credits + } + return 0 +} + type FinalizeInvoiceRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -540,67 +547,70 @@ var file_usage_v1_billing_proto_rawDesc = []byte{ 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x49, 0x64, 0x22, 0x18, 0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x5d, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x49, 0x6e, - 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x07, - 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, - 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, - 0x49, 0x64, 0x42, 0x0c, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, - 0x22, 0x6d, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x76, - 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, - 0x69, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x69, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x63, - 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, - 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, - 0x37, 0x0a, 0x16, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, - 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, 0x76, - 0x6f, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, - 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x49, 0x64, 0x22, 0x19, 0x0a, 0x17, 0x46, 0x69, 0x6e, 0x61, - 0x6c, 0x69, 0x7a, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x94, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x74, 0x42, 0x69, 0x6c, 0x6c, 0x65, - 0x64, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, - 0x12, 0x2e, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, - 0x12, 0x28, 0x0a, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x10, 0x2e, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x73, 0x74, - 0x65, 0x6d, 0x52, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x22, 0x1a, 0x0a, 0x18, 0x53, 0x65, - 0x74, 0x42, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x45, 0x0a, 0x06, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, - 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, - 0x57, 0x4e, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x5f, 0x43, - 0x48, 0x41, 0x52, 0x47, 0x45, 0x42, 0x45, 0x45, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x59, - 0x53, 0x54, 0x45, 0x4d, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x50, 0x45, 0x10, 0x02, 0x32, 0xfb, 0x02, - 0x0a, 0x0e, 0x42, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x55, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, - 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4c, 0x61, - 0x74, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x21, 0x2e, 0x75, 0x73, - 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, - 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, - 0x2e, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x61, 0x74, - 0x65, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x0f, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, - 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x20, 0x2e, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, - 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x75, 0x73, 0x61, 0x67, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x49, 0x6e, 0x76, - 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5b, - 0x0a, 0x10, 0x53, 0x65, 0x74, 0x42, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x53, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x21, 0x2e, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, - 0x74, 0x42, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x65, 0x74, 0x42, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x2a, 0x5a, 0x28, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, - 0x2d, 0x69, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2f, 0x75, 0x73, 0x61, 0x67, 0x65, - 0x2d, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x22, 0x5f, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x55, 0x70, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, + 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, + 0x0a, 0x07, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x00, 0x52, 0x06, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x07, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x75, 0x73, + 0x65, 0x72, 0x49, 0x64, 0x42, 0x0c, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, + 0x65, 0x72, 0x22, 0x89, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x55, 0x70, 0x63, 0x6f, 0x6d, 0x69, + 0x6e, 0x67, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x49, 0x64, + 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x16, 0x0a, 0x06, + 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x73, 0x22, 0x37, + 0x0a, 0x16, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, 0x76, 0x6f, + 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, + 0x76, 0x6f, 0x69, 0x63, 0x65, 0x49, 0x64, 0x22, 0x19, 0x0a, 0x17, 0x46, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x7a, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x94, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x74, 0x42, 0x69, 0x6c, 0x6c, 0x65, 0x64, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, + 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, + 0x2e, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, + 0x28, 0x0a, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x10, 0x2e, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x52, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x22, 0x1a, 0x0a, 0x18, 0x53, 0x65, 0x74, + 0x42, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x45, 0x0a, 0x06, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, + 0x12, 0x0a, 0x0e, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, + 0x4e, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x5f, 0x43, 0x48, + 0x41, 0x52, 0x47, 0x45, 0x42, 0x45, 0x45, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x59, 0x53, + 0x54, 0x45, 0x4d, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x50, 0x45, 0x10, 0x02, 0x32, 0x81, 0x03, 0x0a, + 0x0e, 0x42, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x55, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, + 0x73, 0x12, 0x1f, 0x2e, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x61, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x55, 0x70, 0x63, + 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x23, 0x2e, 0x75, + 0x73, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x70, 0x63, 0x6f, 0x6d, + 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x24, 0x2e, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x55, 0x70, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x0f, 0x46, 0x69, 0x6e, + 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x20, 0x2e, 0x75, + 0x73, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, + 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, + 0x2e, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, + 0x7a, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x42, 0x69, 0x6c, 0x6c, 0x65, 0x64, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x2e, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x42, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x53, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x75, 0x73, 0x61, + 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x42, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x53, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x42, 0x2a, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, + 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2d, 0x69, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2f, + 0x75, 0x73, 0x61, 0x67, 0x65, 0x2d, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -618,17 +628,17 @@ func file_usage_v1_billing_proto_rawDescGZIP() []byte { var file_usage_v1_billing_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_usage_v1_billing_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_usage_v1_billing_proto_goTypes = []interface{}{ - (System)(0), // 0: usage.v1.System - (*UpdateInvoicesRequest)(nil), // 1: usage.v1.UpdateInvoicesRequest - (*UpdateInvoicesResponse)(nil), // 2: usage.v1.UpdateInvoicesResponse - (*GetLatestInvoiceRequest)(nil), // 3: usage.v1.GetLatestInvoiceRequest - (*GetLatestInvoiceResponse)(nil), // 4: usage.v1.GetLatestInvoiceResponse - (*FinalizeInvoiceRequest)(nil), // 5: usage.v1.FinalizeInvoiceRequest - (*FinalizeInvoiceResponse)(nil), // 6: usage.v1.FinalizeInvoiceResponse - (*SetBilledSessionRequest)(nil), // 7: usage.v1.SetBilledSessionRequest - (*SetBilledSessionResponse)(nil), // 8: usage.v1.SetBilledSessionResponse - (*timestamppb.Timestamp)(nil), // 9: google.protobuf.Timestamp - (*BilledSession)(nil), // 10: usage.v1.BilledSession + (System)(0), // 0: usage.v1.System + (*UpdateInvoicesRequest)(nil), // 1: usage.v1.UpdateInvoicesRequest + (*UpdateInvoicesResponse)(nil), // 2: usage.v1.UpdateInvoicesResponse + (*GetUpcomingInvoiceRequest)(nil), // 3: usage.v1.GetUpcomingInvoiceRequest + (*GetUpcomingInvoiceResponse)(nil), // 4: usage.v1.GetUpcomingInvoiceResponse + (*FinalizeInvoiceRequest)(nil), // 5: usage.v1.FinalizeInvoiceRequest + (*FinalizeInvoiceResponse)(nil), // 6: usage.v1.FinalizeInvoiceResponse + (*SetBilledSessionRequest)(nil), // 7: usage.v1.SetBilledSessionRequest + (*SetBilledSessionResponse)(nil), // 8: usage.v1.SetBilledSessionResponse + (*timestamppb.Timestamp)(nil), // 9: google.protobuf.Timestamp + (*BilledSession)(nil), // 10: usage.v1.BilledSession } var file_usage_v1_billing_proto_depIdxs = []int32{ 9, // 0: usage.v1.UpdateInvoicesRequest.start_time:type_name -> google.protobuf.Timestamp @@ -637,11 +647,11 @@ var file_usage_v1_billing_proto_depIdxs = []int32{ 9, // 3: usage.v1.SetBilledSessionRequest.from:type_name -> google.protobuf.Timestamp 0, // 4: usage.v1.SetBilledSessionRequest.system:type_name -> usage.v1.System 1, // 5: usage.v1.BillingService.UpdateInvoices:input_type -> usage.v1.UpdateInvoicesRequest - 3, // 6: usage.v1.BillingService.GetLatestInvoice:input_type -> usage.v1.GetLatestInvoiceRequest + 3, // 6: usage.v1.BillingService.GetUpcomingInvoice:input_type -> usage.v1.GetUpcomingInvoiceRequest 5, // 7: usage.v1.BillingService.FinalizeInvoice:input_type -> usage.v1.FinalizeInvoiceRequest 7, // 8: usage.v1.BillingService.SetBilledSession:input_type -> usage.v1.SetBilledSessionRequest 2, // 9: usage.v1.BillingService.UpdateInvoices:output_type -> usage.v1.UpdateInvoicesResponse - 4, // 10: usage.v1.BillingService.GetLatestInvoice:output_type -> usage.v1.GetLatestInvoiceResponse + 4, // 10: usage.v1.BillingService.GetUpcomingInvoice:output_type -> usage.v1.GetUpcomingInvoiceResponse 6, // 11: usage.v1.BillingService.FinalizeInvoice:output_type -> usage.v1.FinalizeInvoiceResponse 8, // 12: usage.v1.BillingService.SetBilledSession:output_type -> usage.v1.SetBilledSessionResponse 9, // [9:13] is the sub-list for method output_type @@ -683,7 +693,7 @@ func file_usage_v1_billing_proto_init() { } } file_usage_v1_billing_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetLatestInvoiceRequest); i { + switch v := v.(*GetUpcomingInvoiceRequest); i { case 0: return &v.state case 1: @@ -695,7 +705,7 @@ func file_usage_v1_billing_proto_init() { } } file_usage_v1_billing_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetLatestInvoiceResponse); i { + switch v := v.(*GetUpcomingInvoiceResponse); i { case 0: return &v.state case 1: @@ -756,8 +766,8 @@ func file_usage_v1_billing_proto_init() { } } file_usage_v1_billing_proto_msgTypes[2].OneofWrappers = []interface{}{ - (*GetLatestInvoiceRequest_TeamId)(nil), - (*GetLatestInvoiceRequest_UserId)(nil), + (*GetUpcomingInvoiceRequest_TeamId)(nil), + (*GetUpcomingInvoiceRequest_UserId)(nil), } type x struct{} out := protoimpl.TypeBuilder{ diff --git a/components/usage-api/go/v1/billing_grpc.pb.go b/components/usage-api/go/v1/billing_grpc.pb.go index 09875d32013174..e1c603801666a7 100644 --- a/components/usage-api/go/v1/billing_grpc.pb.go +++ b/components/usage-api/go/v1/billing_grpc.pb.go @@ -30,8 +30,8 @@ type BillingServiceClient interface { // in a billing system. // This is an Internal RPC used by the usage reconciler and not intended for general consumption. UpdateInvoices(ctx context.Context, in *UpdateInvoicesRequest, opts ...grpc.CallOption) (*UpdateInvoicesResponse, error) - // GetLatestInvoice retrieves the latest invoice for a given query. - GetLatestInvoice(ctx context.Context, in *GetLatestInvoiceRequest, opts ...grpc.CallOption) (*GetLatestInvoiceResponse, error) + // GetUpcomingInvoice retrieves the latest invoice for a given query. + GetUpcomingInvoice(ctx context.Context, in *GetUpcomingInvoiceRequest, opts ...grpc.CallOption) (*GetUpcomingInvoiceResponse, error) // FinalizeInvoice marks all sessions occurring in the given Stripe invoice as // having been invoiced. FinalizeInvoice(ctx context.Context, in *FinalizeInvoiceRequest, opts ...grpc.CallOption) (*FinalizeInvoiceResponse, error) @@ -56,9 +56,9 @@ func (c *billingServiceClient) UpdateInvoices(ctx context.Context, in *UpdateInv return out, nil } -func (c *billingServiceClient) GetLatestInvoice(ctx context.Context, in *GetLatestInvoiceRequest, opts ...grpc.CallOption) (*GetLatestInvoiceResponse, error) { - out := new(GetLatestInvoiceResponse) - err := c.cc.Invoke(ctx, "/usage.v1.BillingService/GetLatestInvoice", in, out, opts...) +func (c *billingServiceClient) GetUpcomingInvoice(ctx context.Context, in *GetUpcomingInvoiceRequest, opts ...grpc.CallOption) (*GetUpcomingInvoiceResponse, error) { + out := new(GetUpcomingInvoiceResponse) + err := c.cc.Invoke(ctx, "/usage.v1.BillingService/GetUpcomingInvoice", in, out, opts...) if err != nil { return nil, err } @@ -91,8 +91,8 @@ type BillingServiceServer interface { // in a billing system. // This is an Internal RPC used by the usage reconciler and not intended for general consumption. UpdateInvoices(context.Context, *UpdateInvoicesRequest) (*UpdateInvoicesResponse, error) - // GetLatestInvoice retrieves the latest invoice for a given query. - GetLatestInvoice(context.Context, *GetLatestInvoiceRequest) (*GetLatestInvoiceResponse, error) + // GetUpcomingInvoice retrieves the latest invoice for a given query. + GetUpcomingInvoice(context.Context, *GetUpcomingInvoiceRequest) (*GetUpcomingInvoiceResponse, error) // FinalizeInvoice marks all sessions occurring in the given Stripe invoice as // having been invoiced. FinalizeInvoice(context.Context, *FinalizeInvoiceRequest) (*FinalizeInvoiceResponse, error) @@ -108,8 +108,8 @@ type UnimplementedBillingServiceServer struct { func (UnimplementedBillingServiceServer) UpdateInvoices(context.Context, *UpdateInvoicesRequest) (*UpdateInvoicesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UpdateInvoices not implemented") } -func (UnimplementedBillingServiceServer) GetLatestInvoice(context.Context, *GetLatestInvoiceRequest) (*GetLatestInvoiceResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetLatestInvoice not implemented") +func (UnimplementedBillingServiceServer) GetUpcomingInvoice(context.Context, *GetUpcomingInvoiceRequest) (*GetUpcomingInvoiceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetUpcomingInvoice not implemented") } func (UnimplementedBillingServiceServer) FinalizeInvoice(context.Context, *FinalizeInvoiceRequest) (*FinalizeInvoiceResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method FinalizeInvoice not implemented") @@ -148,20 +148,20 @@ func _BillingService_UpdateInvoices_Handler(srv interface{}, ctx context.Context return interceptor(ctx, in, info, handler) } -func _BillingService_GetLatestInvoice_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetLatestInvoiceRequest) +func _BillingService_GetUpcomingInvoice_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetUpcomingInvoiceRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(BillingServiceServer).GetLatestInvoice(ctx, in) + return srv.(BillingServiceServer).GetUpcomingInvoice(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/usage.v1.BillingService/GetLatestInvoice", + FullMethod: "/usage.v1.BillingService/GetUpcomingInvoice", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BillingServiceServer).GetLatestInvoice(ctx, req.(*GetLatestInvoiceRequest)) + return srv.(BillingServiceServer).GetUpcomingInvoice(ctx, req.(*GetUpcomingInvoiceRequest)) } return interceptor(ctx, in, info, handler) } @@ -214,8 +214,8 @@ var BillingService_ServiceDesc = grpc.ServiceDesc{ Handler: _BillingService_UpdateInvoices_Handler, }, { - MethodName: "GetLatestInvoice", - Handler: _BillingService_GetLatestInvoice_Handler, + MethodName: "GetUpcomingInvoice", + Handler: _BillingService_GetUpcomingInvoice_Handler, }, { MethodName: "FinalizeInvoice", diff --git a/components/usage-api/typescript/src/usage/v1/billing_grpc_pb.d.ts b/components/usage-api/typescript/src/usage/v1/billing_grpc_pb.d.ts index 8506e0921b2310..0ee95459faa04f 100644 --- a/components/usage-api/typescript/src/usage/v1/billing_grpc_pb.d.ts +++ b/components/usage-api/typescript/src/usage/v1/billing_grpc_pb.d.ts @@ -17,7 +17,7 @@ import * as usage_v1_usage_pb from "../../usage/v1/usage_pb"; interface IBillingServiceService extends grpc.ServiceDefinition { updateInvoices: IBillingServiceService_IUpdateInvoices; - getLatestInvoice: IBillingServiceService_IGetLatestInvoice; + getUpcomingInvoice: IBillingServiceService_IGetUpcomingInvoice; finalizeInvoice: IBillingServiceService_IFinalizeInvoice; setBilledSession: IBillingServiceService_ISetBilledSession; } @@ -31,14 +31,14 @@ interface IBillingServiceService_IUpdateInvoices extends grpc.MethodDefinition; responseDeserialize: grpc.deserialize; } -interface IBillingServiceService_IGetLatestInvoice extends grpc.MethodDefinition { - path: "/usage.v1.BillingService/GetLatestInvoice"; +interface IBillingServiceService_IGetUpcomingInvoice extends grpc.MethodDefinition { + path: "/usage.v1.BillingService/GetUpcomingInvoice"; requestStream: false; responseStream: false; - requestSerialize: grpc.serialize; - requestDeserialize: grpc.deserialize; - responseSerialize: grpc.serialize; - responseDeserialize: grpc.deserialize; + requestSerialize: grpc.serialize; + requestDeserialize: grpc.deserialize; + responseSerialize: grpc.serialize; + responseDeserialize: grpc.deserialize; } interface IBillingServiceService_IFinalizeInvoice extends grpc.MethodDefinition { path: "/usage.v1.BillingService/FinalizeInvoice"; @@ -63,7 +63,7 @@ export const BillingServiceService: IBillingServiceService; export interface IBillingServiceServer extends grpc.UntypedServiceImplementation { updateInvoices: grpc.handleUnaryCall; - getLatestInvoice: grpc.handleUnaryCall; + getUpcomingInvoice: grpc.handleUnaryCall; finalizeInvoice: grpc.handleUnaryCall; setBilledSession: grpc.handleUnaryCall; } @@ -72,9 +72,9 @@ export interface IBillingServiceClient { updateInvoices(request: usage_v1_billing_pb.UpdateInvoicesRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.UpdateInvoicesResponse) => void): grpc.ClientUnaryCall; updateInvoices(request: usage_v1_billing_pb.UpdateInvoicesRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.UpdateInvoicesResponse) => void): grpc.ClientUnaryCall; updateInvoices(request: usage_v1_billing_pb.UpdateInvoicesRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.UpdateInvoicesResponse) => void): grpc.ClientUnaryCall; - getLatestInvoice(request: usage_v1_billing_pb.GetLatestInvoiceRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetLatestInvoiceResponse) => void): grpc.ClientUnaryCall; - getLatestInvoice(request: usage_v1_billing_pb.GetLatestInvoiceRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetLatestInvoiceResponse) => void): grpc.ClientUnaryCall; - getLatestInvoice(request: usage_v1_billing_pb.GetLatestInvoiceRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetLatestInvoiceResponse) => void): grpc.ClientUnaryCall; + getUpcomingInvoice(request: usage_v1_billing_pb.GetUpcomingInvoiceRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetUpcomingInvoiceResponse) => void): grpc.ClientUnaryCall; + getUpcomingInvoice(request: usage_v1_billing_pb.GetUpcomingInvoiceRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetUpcomingInvoiceResponse) => void): grpc.ClientUnaryCall; + getUpcomingInvoice(request: usage_v1_billing_pb.GetUpcomingInvoiceRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetUpcomingInvoiceResponse) => void): grpc.ClientUnaryCall; finalizeInvoice(request: usage_v1_billing_pb.FinalizeInvoiceRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.FinalizeInvoiceResponse) => void): grpc.ClientUnaryCall; finalizeInvoice(request: usage_v1_billing_pb.FinalizeInvoiceRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.FinalizeInvoiceResponse) => void): grpc.ClientUnaryCall; finalizeInvoice(request: usage_v1_billing_pb.FinalizeInvoiceRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.FinalizeInvoiceResponse) => void): grpc.ClientUnaryCall; @@ -88,9 +88,9 @@ export class BillingServiceClient extends grpc.Client implements IBillingService public updateInvoices(request: usage_v1_billing_pb.UpdateInvoicesRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.UpdateInvoicesResponse) => void): grpc.ClientUnaryCall; public updateInvoices(request: usage_v1_billing_pb.UpdateInvoicesRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.UpdateInvoicesResponse) => void): grpc.ClientUnaryCall; public updateInvoices(request: usage_v1_billing_pb.UpdateInvoicesRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.UpdateInvoicesResponse) => void): grpc.ClientUnaryCall; - public getLatestInvoice(request: usage_v1_billing_pb.GetLatestInvoiceRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetLatestInvoiceResponse) => void): grpc.ClientUnaryCall; - public getLatestInvoice(request: usage_v1_billing_pb.GetLatestInvoiceRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetLatestInvoiceResponse) => void): grpc.ClientUnaryCall; - public getLatestInvoice(request: usage_v1_billing_pb.GetLatestInvoiceRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetLatestInvoiceResponse) => void): grpc.ClientUnaryCall; + public getUpcomingInvoice(request: usage_v1_billing_pb.GetUpcomingInvoiceRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetUpcomingInvoiceResponse) => void): grpc.ClientUnaryCall; + public getUpcomingInvoice(request: usage_v1_billing_pb.GetUpcomingInvoiceRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetUpcomingInvoiceResponse) => void): grpc.ClientUnaryCall; + public getUpcomingInvoice(request: usage_v1_billing_pb.GetUpcomingInvoiceRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.GetUpcomingInvoiceResponse) => void): grpc.ClientUnaryCall; public finalizeInvoice(request: usage_v1_billing_pb.FinalizeInvoiceRequest, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.FinalizeInvoiceResponse) => void): grpc.ClientUnaryCall; public finalizeInvoice(request: usage_v1_billing_pb.FinalizeInvoiceRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.FinalizeInvoiceResponse) => void): grpc.ClientUnaryCall; public finalizeInvoice(request: usage_v1_billing_pb.FinalizeInvoiceRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: usage_v1_billing_pb.FinalizeInvoiceResponse) => void): grpc.ClientUnaryCall; diff --git a/components/usage-api/typescript/src/usage/v1/billing_grpc_pb.js b/components/usage-api/typescript/src/usage/v1/billing_grpc_pb.js index e69caec24726cf..41d6bb903d14de 100644 --- a/components/usage-api/typescript/src/usage/v1/billing_grpc_pb.js +++ b/components/usage-api/typescript/src/usage/v1/billing_grpc_pb.js @@ -34,26 +34,26 @@ function deserialize_usage_v1_FinalizeInvoiceResponse(buffer_arg) { return usage_v1_billing_pb.FinalizeInvoiceResponse.deserializeBinary(new Uint8Array(buffer_arg)); } -function serialize_usage_v1_GetLatestInvoiceRequest(arg) { - if (!(arg instanceof usage_v1_billing_pb.GetLatestInvoiceRequest)) { - throw new Error('Expected argument of type usage.v1.GetLatestInvoiceRequest'); +function serialize_usage_v1_GetUpcomingInvoiceRequest(arg) { + if (!(arg instanceof usage_v1_billing_pb.GetUpcomingInvoiceRequest)) { + throw new Error('Expected argument of type usage.v1.GetUpcomingInvoiceRequest'); } return Buffer.from(arg.serializeBinary()); } -function deserialize_usage_v1_GetLatestInvoiceRequest(buffer_arg) { - return usage_v1_billing_pb.GetLatestInvoiceRequest.deserializeBinary(new Uint8Array(buffer_arg)); +function deserialize_usage_v1_GetUpcomingInvoiceRequest(buffer_arg) { + return usage_v1_billing_pb.GetUpcomingInvoiceRequest.deserializeBinary(new Uint8Array(buffer_arg)); } -function serialize_usage_v1_GetLatestInvoiceResponse(arg) { - if (!(arg instanceof usage_v1_billing_pb.GetLatestInvoiceResponse)) { - throw new Error('Expected argument of type usage.v1.GetLatestInvoiceResponse'); +function serialize_usage_v1_GetUpcomingInvoiceResponse(arg) { + if (!(arg instanceof usage_v1_billing_pb.GetUpcomingInvoiceResponse)) { + throw new Error('Expected argument of type usage.v1.GetUpcomingInvoiceResponse'); } return Buffer.from(arg.serializeBinary()); } -function deserialize_usage_v1_GetLatestInvoiceResponse(buffer_arg) { - return usage_v1_billing_pb.GetLatestInvoiceResponse.deserializeBinary(new Uint8Array(buffer_arg)); +function deserialize_usage_v1_GetUpcomingInvoiceResponse(buffer_arg) { + return usage_v1_billing_pb.GetUpcomingInvoiceResponse.deserializeBinary(new Uint8Array(buffer_arg)); } function serialize_usage_v1_SetBilledSessionRequest(arg) { @@ -116,17 +116,17 @@ updateInvoices: { responseSerialize: serialize_usage_v1_UpdateInvoicesResponse, responseDeserialize: deserialize_usage_v1_UpdateInvoicesResponse, }, - // GetLatestInvoice retrieves the latest invoice for a given query. -getLatestInvoice: { - path: '/usage.v1.BillingService/GetLatestInvoice', + // GetUpcomingInvoice retrieves the latest invoice for a given query. +getUpcomingInvoice: { + path: '/usage.v1.BillingService/GetUpcomingInvoice', requestStream: false, responseStream: false, - requestType: usage_v1_billing_pb.GetLatestInvoiceRequest, - responseType: usage_v1_billing_pb.GetLatestInvoiceResponse, - requestSerialize: serialize_usage_v1_GetLatestInvoiceRequest, - requestDeserialize: deserialize_usage_v1_GetLatestInvoiceRequest, - responseSerialize: serialize_usage_v1_GetLatestInvoiceResponse, - responseDeserialize: deserialize_usage_v1_GetLatestInvoiceResponse, + requestType: usage_v1_billing_pb.GetUpcomingInvoiceRequest, + responseType: usage_v1_billing_pb.GetUpcomingInvoiceResponse, + requestSerialize: serialize_usage_v1_GetUpcomingInvoiceRequest, + requestDeserialize: deserialize_usage_v1_GetUpcomingInvoiceRequest, + responseSerialize: serialize_usage_v1_GetUpcomingInvoiceResponse, + responseDeserialize: deserialize_usage_v1_GetUpcomingInvoiceResponse, }, // FinalizeInvoice marks all sessions occurring in the given Stripe invoice as // having been invoiced. diff --git a/components/usage-api/typescript/src/usage/v1/billing_pb.d.ts b/components/usage-api/typescript/src/usage/v1/billing_pb.d.ts index 6f5ea7ada8268a..89706e8be3671b 100644 --- a/components/usage-api/typescript/src/usage/v1/billing_pb.d.ts +++ b/components/usage-api/typescript/src/usage/v1/billing_pb.d.ts @@ -68,31 +68,31 @@ export namespace UpdateInvoicesResponse { } } -export class GetLatestInvoiceRequest extends jspb.Message { +export class GetUpcomingInvoiceRequest extends jspb.Message { hasTeamId(): boolean; clearTeamId(): void; getTeamId(): string; - setTeamId(value: string): GetLatestInvoiceRequest; + setTeamId(value: string): GetUpcomingInvoiceRequest; hasUserId(): boolean; clearUserId(): void; getUserId(): string; - setUserId(value: string): GetLatestInvoiceRequest; + setUserId(value: string): GetUpcomingInvoiceRequest; - getIdentifierCase(): GetLatestInvoiceRequest.IdentifierCase; + getIdentifierCase(): GetUpcomingInvoiceRequest.IdentifierCase; serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): GetLatestInvoiceRequest.AsObject; - static toObject(includeInstance: boolean, msg: GetLatestInvoiceRequest): GetLatestInvoiceRequest.AsObject; + toObject(includeInstance?: boolean): GetUpcomingInvoiceRequest.AsObject; + static toObject(includeInstance: boolean, msg: GetUpcomingInvoiceRequest): GetUpcomingInvoiceRequest.AsObject; static extensions: {[key: number]: jspb.ExtensionFieldInfo}; static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: GetLatestInvoiceRequest, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): GetLatestInvoiceRequest; - static deserializeBinaryFromReader(message: GetLatestInvoiceRequest, reader: jspb.BinaryReader): GetLatestInvoiceRequest; + static serializeBinaryToWriter(message: GetUpcomingInvoiceRequest, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): GetUpcomingInvoiceRequest; + static deserializeBinaryFromReader(message: GetUpcomingInvoiceRequest, reader: jspb.BinaryReader): GetUpcomingInvoiceRequest; } -export namespace GetLatestInvoiceRequest { +export namespace GetUpcomingInvoiceRequest { export type AsObject = { teamId: string, userId: string, @@ -106,29 +106,32 @@ export namespace GetLatestInvoiceRequest { } -export class GetLatestInvoiceResponse extends jspb.Message { +export class GetUpcomingInvoiceResponse extends jspb.Message { getInvoiceId(): string; - setInvoiceId(value: string): GetLatestInvoiceResponse; + setInvoiceId(value: string): GetUpcomingInvoiceResponse; getCurrency(): string; - setCurrency(value: string): GetLatestInvoiceResponse; + setCurrency(value: string): GetUpcomingInvoiceResponse; getAmount(): number; - setAmount(value: number): GetLatestInvoiceResponse; + setAmount(value: number): GetUpcomingInvoiceResponse; + getCredits(): number; + setCredits(value: number): GetUpcomingInvoiceResponse; serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): GetLatestInvoiceResponse.AsObject; - static toObject(includeInstance: boolean, msg: GetLatestInvoiceResponse): GetLatestInvoiceResponse.AsObject; + toObject(includeInstance?: boolean): GetUpcomingInvoiceResponse.AsObject; + static toObject(includeInstance: boolean, msg: GetUpcomingInvoiceResponse): GetUpcomingInvoiceResponse.AsObject; static extensions: {[key: number]: jspb.ExtensionFieldInfo}; static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: GetLatestInvoiceResponse, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): GetLatestInvoiceResponse; - static deserializeBinaryFromReader(message: GetLatestInvoiceResponse, reader: jspb.BinaryReader): GetLatestInvoiceResponse; + static serializeBinaryToWriter(message: GetUpcomingInvoiceResponse, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): GetUpcomingInvoiceResponse; + static deserializeBinaryFromReader(message: GetUpcomingInvoiceResponse, reader: jspb.BinaryReader): GetUpcomingInvoiceResponse; } -export namespace GetLatestInvoiceResponse { +export namespace GetUpcomingInvoiceResponse { export type AsObject = { invoiceId: string, currency: string, amount: number, + credits: number, } } diff --git a/components/usage-api/typescript/src/usage/v1/billing_pb.js b/components/usage-api/typescript/src/usage/v1/billing_pb.js index 619371a5659497..d1301162c46f2f 100644 --- a/components/usage-api/typescript/src/usage/v1/billing_pb.js +++ b/components/usage-api/typescript/src/usage/v1/billing_pb.js @@ -27,9 +27,9 @@ var usage_v1_usage_pb = require('../../usage/v1/usage_pb.js'); goog.object.extend(proto, usage_v1_usage_pb); goog.exportSymbol('proto.usage.v1.FinalizeInvoiceRequest', null, global); goog.exportSymbol('proto.usage.v1.FinalizeInvoiceResponse', null, global); -goog.exportSymbol('proto.usage.v1.GetLatestInvoiceRequest', null, global); -goog.exportSymbol('proto.usage.v1.GetLatestInvoiceRequest.IdentifierCase', null, global); -goog.exportSymbol('proto.usage.v1.GetLatestInvoiceResponse', null, global); +goog.exportSymbol('proto.usage.v1.GetUpcomingInvoiceRequest', null, global); +goog.exportSymbol('proto.usage.v1.GetUpcomingInvoiceRequest.IdentifierCase', null, global); +goog.exportSymbol('proto.usage.v1.GetUpcomingInvoiceResponse', null, global); goog.exportSymbol('proto.usage.v1.SetBilledSessionRequest', null, global); goog.exportSymbol('proto.usage.v1.SetBilledSessionResponse', null, global); goog.exportSymbol('proto.usage.v1.System', null, global); @@ -87,16 +87,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.usage.v1.GetLatestInvoiceRequest = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, proto.usage.v1.GetLatestInvoiceRequest.oneofGroups_); +proto.usage.v1.GetUpcomingInvoiceRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, proto.usage.v1.GetUpcomingInvoiceRequest.oneofGroups_); }; -goog.inherits(proto.usage.v1.GetLatestInvoiceRequest, jspb.Message); +goog.inherits(proto.usage.v1.GetUpcomingInvoiceRequest, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.usage.v1.GetLatestInvoiceRequest.displayName = 'proto.usage.v1.GetLatestInvoiceRequest'; + proto.usage.v1.GetUpcomingInvoiceRequest.displayName = 'proto.usage.v1.GetUpcomingInvoiceRequest'; } /** * Generated by JsPbCodeGenerator. @@ -108,16 +108,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.usage.v1.GetLatestInvoiceResponse = function(opt_data) { +proto.usage.v1.GetUpcomingInvoiceResponse = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; -goog.inherits(proto.usage.v1.GetLatestInvoiceResponse, jspb.Message); +goog.inherits(proto.usage.v1.GetUpcomingInvoiceResponse, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.usage.v1.GetLatestInvoiceResponse.displayName = 'proto.usage.v1.GetLatestInvoiceResponse'; + proto.usage.v1.GetUpcomingInvoiceResponse.displayName = 'proto.usage.v1.GetUpcomingInvoiceResponse'; } /** * Generated by JsPbCodeGenerator. @@ -605,22 +605,22 @@ proto.usage.v1.UpdateInvoicesResponse.serializeBinaryToWriter = function(message * @private {!Array>} * @const */ -proto.usage.v1.GetLatestInvoiceRequest.oneofGroups_ = [[1,2]]; +proto.usage.v1.GetUpcomingInvoiceRequest.oneofGroups_ = [[1,2]]; /** * @enum {number} */ -proto.usage.v1.GetLatestInvoiceRequest.IdentifierCase = { +proto.usage.v1.GetUpcomingInvoiceRequest.IdentifierCase = { IDENTIFIER_NOT_SET: 0, TEAM_ID: 1, USER_ID: 2 }; /** - * @return {proto.usage.v1.GetLatestInvoiceRequest.IdentifierCase} + * @return {proto.usage.v1.GetUpcomingInvoiceRequest.IdentifierCase} */ -proto.usage.v1.GetLatestInvoiceRequest.prototype.getIdentifierCase = function() { - return /** @type {proto.usage.v1.GetLatestInvoiceRequest.IdentifierCase} */(jspb.Message.computeOneofCase(this, proto.usage.v1.GetLatestInvoiceRequest.oneofGroups_[0])); +proto.usage.v1.GetUpcomingInvoiceRequest.prototype.getIdentifierCase = function() { + return /** @type {proto.usage.v1.GetUpcomingInvoiceRequest.IdentifierCase} */(jspb.Message.computeOneofCase(this, proto.usage.v1.GetUpcomingInvoiceRequest.oneofGroups_[0])); }; @@ -638,8 +638,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.usage.v1.GetLatestInvoiceRequest.prototype.toObject = function(opt_includeInstance) { - return proto.usage.v1.GetLatestInvoiceRequest.toObject(opt_includeInstance, this); +proto.usage.v1.GetUpcomingInvoiceRequest.prototype.toObject = function(opt_includeInstance) { + return proto.usage.v1.GetUpcomingInvoiceRequest.toObject(opt_includeInstance, this); }; @@ -648,11 +648,11 @@ proto.usage.v1.GetLatestInvoiceRequest.prototype.toObject = function(opt_include * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.usage.v1.GetLatestInvoiceRequest} msg The msg instance to transform. + * @param {!proto.usage.v1.GetUpcomingInvoiceRequest} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.usage.v1.GetLatestInvoiceRequest.toObject = function(includeInstance, msg) { +proto.usage.v1.GetUpcomingInvoiceRequest.toObject = function(includeInstance, msg) { var f, obj = { teamId: jspb.Message.getFieldWithDefault(msg, 1, ""), userId: jspb.Message.getFieldWithDefault(msg, 2, "") @@ -669,23 +669,23 @@ proto.usage.v1.GetLatestInvoiceRequest.toObject = function(includeInstance, msg) /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.usage.v1.GetLatestInvoiceRequest} + * @return {!proto.usage.v1.GetUpcomingInvoiceRequest} */ -proto.usage.v1.GetLatestInvoiceRequest.deserializeBinary = function(bytes) { +proto.usage.v1.GetUpcomingInvoiceRequest.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.usage.v1.GetLatestInvoiceRequest; - return proto.usage.v1.GetLatestInvoiceRequest.deserializeBinaryFromReader(msg, reader); + var msg = new proto.usage.v1.GetUpcomingInvoiceRequest; + return proto.usage.v1.GetUpcomingInvoiceRequest.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.usage.v1.GetLatestInvoiceRequest} msg The message object to deserialize into. + * @param {!proto.usage.v1.GetUpcomingInvoiceRequest} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.usage.v1.GetLatestInvoiceRequest} + * @return {!proto.usage.v1.GetUpcomingInvoiceRequest} */ -proto.usage.v1.GetLatestInvoiceRequest.deserializeBinaryFromReader = function(msg, reader) { +proto.usage.v1.GetUpcomingInvoiceRequest.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -713,9 +713,9 @@ proto.usage.v1.GetLatestInvoiceRequest.deserializeBinaryFromReader = function(ms * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.usage.v1.GetLatestInvoiceRequest.prototype.serializeBinary = function() { +proto.usage.v1.GetUpcomingInvoiceRequest.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.usage.v1.GetLatestInvoiceRequest.serializeBinaryToWriter(this, writer); + proto.usage.v1.GetUpcomingInvoiceRequest.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -723,11 +723,11 @@ proto.usage.v1.GetLatestInvoiceRequest.prototype.serializeBinary = function() { /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.usage.v1.GetLatestInvoiceRequest} message + * @param {!proto.usage.v1.GetUpcomingInvoiceRequest} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.usage.v1.GetLatestInvoiceRequest.serializeBinaryToWriter = function(message, writer) { +proto.usage.v1.GetUpcomingInvoiceRequest.serializeBinaryToWriter = function(message, writer) { var f = undefined; f = /** @type {string} */ (jspb.Message.getField(message, 1)); if (f != null) { @@ -750,26 +750,26 @@ proto.usage.v1.GetLatestInvoiceRequest.serializeBinaryToWriter = function(messag * optional string team_id = 1; * @return {string} */ -proto.usage.v1.GetLatestInvoiceRequest.prototype.getTeamId = function() { +proto.usage.v1.GetUpcomingInvoiceRequest.prototype.getTeamId = function() { return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); }; /** * @param {string} value - * @return {!proto.usage.v1.GetLatestInvoiceRequest} returns this + * @return {!proto.usage.v1.GetUpcomingInvoiceRequest} returns this */ -proto.usage.v1.GetLatestInvoiceRequest.prototype.setTeamId = function(value) { - return jspb.Message.setOneofField(this, 1, proto.usage.v1.GetLatestInvoiceRequest.oneofGroups_[0], value); +proto.usage.v1.GetUpcomingInvoiceRequest.prototype.setTeamId = function(value) { + return jspb.Message.setOneofField(this, 1, proto.usage.v1.GetUpcomingInvoiceRequest.oneofGroups_[0], value); }; /** * Clears the field making it undefined. - * @return {!proto.usage.v1.GetLatestInvoiceRequest} returns this + * @return {!proto.usage.v1.GetUpcomingInvoiceRequest} returns this */ -proto.usage.v1.GetLatestInvoiceRequest.prototype.clearTeamId = function() { - return jspb.Message.setOneofField(this, 1, proto.usage.v1.GetLatestInvoiceRequest.oneofGroups_[0], undefined); +proto.usage.v1.GetUpcomingInvoiceRequest.prototype.clearTeamId = function() { + return jspb.Message.setOneofField(this, 1, proto.usage.v1.GetUpcomingInvoiceRequest.oneofGroups_[0], undefined); }; @@ -777,7 +777,7 @@ proto.usage.v1.GetLatestInvoiceRequest.prototype.clearTeamId = function() { * Returns whether this field is set. * @return {boolean} */ -proto.usage.v1.GetLatestInvoiceRequest.prototype.hasTeamId = function() { +proto.usage.v1.GetUpcomingInvoiceRequest.prototype.hasTeamId = function() { return jspb.Message.getField(this, 1) != null; }; @@ -786,26 +786,26 @@ proto.usage.v1.GetLatestInvoiceRequest.prototype.hasTeamId = function() { * optional string user_id = 2; * @return {string} */ -proto.usage.v1.GetLatestInvoiceRequest.prototype.getUserId = function() { +proto.usage.v1.GetUpcomingInvoiceRequest.prototype.getUserId = function() { return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); }; /** * @param {string} value - * @return {!proto.usage.v1.GetLatestInvoiceRequest} returns this + * @return {!proto.usage.v1.GetUpcomingInvoiceRequest} returns this */ -proto.usage.v1.GetLatestInvoiceRequest.prototype.setUserId = function(value) { - return jspb.Message.setOneofField(this, 2, proto.usage.v1.GetLatestInvoiceRequest.oneofGroups_[0], value); +proto.usage.v1.GetUpcomingInvoiceRequest.prototype.setUserId = function(value) { + return jspb.Message.setOneofField(this, 2, proto.usage.v1.GetUpcomingInvoiceRequest.oneofGroups_[0], value); }; /** * Clears the field making it undefined. - * @return {!proto.usage.v1.GetLatestInvoiceRequest} returns this + * @return {!proto.usage.v1.GetUpcomingInvoiceRequest} returns this */ -proto.usage.v1.GetLatestInvoiceRequest.prototype.clearUserId = function() { - return jspb.Message.setOneofField(this, 2, proto.usage.v1.GetLatestInvoiceRequest.oneofGroups_[0], undefined); +proto.usage.v1.GetUpcomingInvoiceRequest.prototype.clearUserId = function() { + return jspb.Message.setOneofField(this, 2, proto.usage.v1.GetUpcomingInvoiceRequest.oneofGroups_[0], undefined); }; @@ -813,7 +813,7 @@ proto.usage.v1.GetLatestInvoiceRequest.prototype.clearUserId = function() { * Returns whether this field is set. * @return {boolean} */ -proto.usage.v1.GetLatestInvoiceRequest.prototype.hasUserId = function() { +proto.usage.v1.GetUpcomingInvoiceRequest.prototype.hasUserId = function() { return jspb.Message.getField(this, 2) != null; }; @@ -834,8 +834,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.usage.v1.GetLatestInvoiceResponse.prototype.toObject = function(opt_includeInstance) { - return proto.usage.v1.GetLatestInvoiceResponse.toObject(opt_includeInstance, this); +proto.usage.v1.GetUpcomingInvoiceResponse.prototype.toObject = function(opt_includeInstance) { + return proto.usage.v1.GetUpcomingInvoiceResponse.toObject(opt_includeInstance, this); }; @@ -844,15 +844,16 @@ proto.usage.v1.GetLatestInvoiceResponse.prototype.toObject = function(opt_includ * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.usage.v1.GetLatestInvoiceResponse} msg The msg instance to transform. + * @param {!proto.usage.v1.GetUpcomingInvoiceResponse} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.usage.v1.GetLatestInvoiceResponse.toObject = function(includeInstance, msg) { +proto.usage.v1.GetUpcomingInvoiceResponse.toObject = function(includeInstance, msg) { var f, obj = { invoiceId: jspb.Message.getFieldWithDefault(msg, 1, ""), currency: jspb.Message.getFieldWithDefault(msg, 2, ""), - amount: jspb.Message.getFloatingPointFieldWithDefault(msg, 3, 0.0) + amount: jspb.Message.getFloatingPointFieldWithDefault(msg, 3, 0.0), + credits: jspb.Message.getFieldWithDefault(msg, 4, 0) }; if (includeInstance) { @@ -866,23 +867,23 @@ proto.usage.v1.GetLatestInvoiceResponse.toObject = function(includeInstance, msg /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.usage.v1.GetLatestInvoiceResponse} + * @return {!proto.usage.v1.GetUpcomingInvoiceResponse} */ -proto.usage.v1.GetLatestInvoiceResponse.deserializeBinary = function(bytes) { +proto.usage.v1.GetUpcomingInvoiceResponse.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.usage.v1.GetLatestInvoiceResponse; - return proto.usage.v1.GetLatestInvoiceResponse.deserializeBinaryFromReader(msg, reader); + var msg = new proto.usage.v1.GetUpcomingInvoiceResponse; + return proto.usage.v1.GetUpcomingInvoiceResponse.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.usage.v1.GetLatestInvoiceResponse} msg The message object to deserialize into. + * @param {!proto.usage.v1.GetUpcomingInvoiceResponse} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.usage.v1.GetLatestInvoiceResponse} + * @return {!proto.usage.v1.GetUpcomingInvoiceResponse} */ -proto.usage.v1.GetLatestInvoiceResponse.deserializeBinaryFromReader = function(msg, reader) { +proto.usage.v1.GetUpcomingInvoiceResponse.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -901,6 +902,10 @@ proto.usage.v1.GetLatestInvoiceResponse.deserializeBinaryFromReader = function(m var value = /** @type {number} */ (reader.readDouble()); msg.setAmount(value); break; + case 4: + var value = /** @type {number} */ (reader.readInt64()); + msg.setCredits(value); + break; default: reader.skipField(); break; @@ -914,9 +919,9 @@ proto.usage.v1.GetLatestInvoiceResponse.deserializeBinaryFromReader = function(m * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.usage.v1.GetLatestInvoiceResponse.prototype.serializeBinary = function() { +proto.usage.v1.GetUpcomingInvoiceResponse.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.usage.v1.GetLatestInvoiceResponse.serializeBinaryToWriter(this, writer); + proto.usage.v1.GetUpcomingInvoiceResponse.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -924,11 +929,11 @@ proto.usage.v1.GetLatestInvoiceResponse.prototype.serializeBinary = function() { /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.usage.v1.GetLatestInvoiceResponse} message + * @param {!proto.usage.v1.GetUpcomingInvoiceResponse} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.usage.v1.GetLatestInvoiceResponse.serializeBinaryToWriter = function(message, writer) { +proto.usage.v1.GetUpcomingInvoiceResponse.serializeBinaryToWriter = function(message, writer) { var f = undefined; f = message.getInvoiceId(); if (f.length > 0) { @@ -951,6 +956,13 @@ proto.usage.v1.GetLatestInvoiceResponse.serializeBinaryToWriter = function(messa f ); } + f = message.getCredits(); + if (f !== 0) { + writer.writeInt64( + 4, + f + ); + } }; @@ -958,16 +970,16 @@ proto.usage.v1.GetLatestInvoiceResponse.serializeBinaryToWriter = function(messa * optional string invoice_id = 1; * @return {string} */ -proto.usage.v1.GetLatestInvoiceResponse.prototype.getInvoiceId = function() { +proto.usage.v1.GetUpcomingInvoiceResponse.prototype.getInvoiceId = function() { return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); }; /** * @param {string} value - * @return {!proto.usage.v1.GetLatestInvoiceResponse} returns this + * @return {!proto.usage.v1.GetUpcomingInvoiceResponse} returns this */ -proto.usage.v1.GetLatestInvoiceResponse.prototype.setInvoiceId = function(value) { +proto.usage.v1.GetUpcomingInvoiceResponse.prototype.setInvoiceId = function(value) { return jspb.Message.setProto3StringField(this, 1, value); }; @@ -976,16 +988,16 @@ proto.usage.v1.GetLatestInvoiceResponse.prototype.setInvoiceId = function(value) * optional string currency = 2; * @return {string} */ -proto.usage.v1.GetLatestInvoiceResponse.prototype.getCurrency = function() { +proto.usage.v1.GetUpcomingInvoiceResponse.prototype.getCurrency = function() { return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); }; /** * @param {string} value - * @return {!proto.usage.v1.GetLatestInvoiceResponse} returns this + * @return {!proto.usage.v1.GetUpcomingInvoiceResponse} returns this */ -proto.usage.v1.GetLatestInvoiceResponse.prototype.setCurrency = function(value) { +proto.usage.v1.GetUpcomingInvoiceResponse.prototype.setCurrency = function(value) { return jspb.Message.setProto3StringField(this, 2, value); }; @@ -994,20 +1006,38 @@ proto.usage.v1.GetLatestInvoiceResponse.prototype.setCurrency = function(value) * optional double amount = 3; * @return {number} */ -proto.usage.v1.GetLatestInvoiceResponse.prototype.getAmount = function() { +proto.usage.v1.GetUpcomingInvoiceResponse.prototype.getAmount = function() { return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 3, 0.0)); }; /** * @param {number} value - * @return {!proto.usage.v1.GetLatestInvoiceResponse} returns this + * @return {!proto.usage.v1.GetUpcomingInvoiceResponse} returns this */ -proto.usage.v1.GetLatestInvoiceResponse.prototype.setAmount = function(value) { +proto.usage.v1.GetUpcomingInvoiceResponse.prototype.setAmount = function(value) { return jspb.Message.setProto3FloatField(this, 3, value); }; +/** + * optional int64 credits = 4; + * @return {number} + */ +proto.usage.v1.GetUpcomingInvoiceResponse.prototype.getCredits = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.usage.v1.GetUpcomingInvoiceResponse} returns this + */ +proto.usage.v1.GetUpcomingInvoiceResponse.prototype.setCredits = function(value) { + return jspb.Message.setProto3IntField(this, 4, value); +}; + + diff --git a/components/usage-api/typescript/src/usage/v1/sugar.ts b/components/usage-api/typescript/src/usage/v1/sugar.ts index 4750c7e5f61999..d3fc76f280a78b 100644 --- a/components/usage-api/typescript/src/usage/v1/sugar.ts +++ b/components/usage-api/typescript/src/usage/v1/sugar.ts @@ -10,13 +10,20 @@ import { TraceContext } from "@gitpod/gitpod-protocol/lib/util/tracing"; import * as opentracing from "opentracing"; import { Metadata } from "@grpc/grpc-js"; import { BilledSession, ListBilledUsageRequest, ListBilledUsageResponse } from "./usage_pb"; -import { SetBilledSessionRequest, SetBilledSessionResponse, System } from "./billing_pb"; +import { + GetUpcomingInvoiceRequest, + GetUpcomingInvoiceResponse, + SetBilledSessionRequest, + SetBilledSessionResponse, + System, +} from "./billing_pb"; import { injectable, inject, optional } from "inversify"; import { createClientCallMetricsInterceptor, IClientCallMetrics } from "@gitpod/gitpod-protocol/lib/util/grpc"; import * as grpc from "@grpc/grpc-js"; import { Timestamp } from "google-protobuf/google/protobuf/timestamp_pb"; import { BillableSession } from "@gitpod/gitpod-protocol/lib/usage"; import { WorkspaceType } from "@gitpod/gitpod-protocol"; +import { AttributionId } from "@gitpod/gitpod-protocol/lib/attribution"; export const UsageServiceClientProvider = Symbol("UsageServiceClientProvider"); export const BillingServiceClientProvider = Symbol("BillingServiceClientProvider"); @@ -254,4 +261,28 @@ export class PromisifiedBillingServiceClient { interceptors: this.interceptor, }; } + + public async getUpcomingInvoice(attributionId: AttributionId) { + const req = new GetUpcomingInvoiceRequest(); + if (attributionId.kind === "team") { + req.setTeamId(attributionId.teamId); + } + if (attributionId.kind === "user") { + req.setUserId(attributionId.userId); + } + + const response = await new Promise((resolve, reject) => { + this.client.getUpcomingInvoice( + req, + (err: grpc.ServiceError | null, response: GetUpcomingInvoiceResponse) => { + if (err) { + reject(err); + return; + } + resolve(response); + }, + ); + }); + return response; + } } diff --git a/components/usage-api/usage/v1/billing.proto b/components/usage-api/usage/v1/billing.proto index 7bbdbaae7e1da8..5af6bb62536d7b 100644 --- a/components/usage-api/usage/v1/billing.proto +++ b/components/usage-api/usage/v1/billing.proto @@ -13,8 +13,8 @@ service BillingService { // This is an Internal RPC used by the usage reconciler and not intended for general consumption. rpc UpdateInvoices(UpdateInvoicesRequest) returns (UpdateInvoicesResponse) {}; - // GetLatestInvoice retrieves the latest invoice for a given query. - rpc GetLatestInvoice(GetLatestInvoiceRequest) returns (GetLatestInvoiceResponse) {}; + // GetUpcomingInvoice retrieves the latest invoice for a given query. + rpc GetUpcomingInvoice(GetUpcomingInvoiceRequest) returns (GetUpcomingInvoiceResponse) {}; // FinalizeInvoice marks all sessions occurring in the given Stripe invoice as // having been invoiced. @@ -36,17 +36,18 @@ message UpdateInvoicesRequest { message UpdateInvoicesResponse { } -message GetLatestInvoiceRequest { +message GetUpcomingInvoiceRequest { oneof identifier { string team_id = 1; string user_id = 2; } } -message GetLatestInvoiceResponse { +message GetUpcomingInvoiceResponse { string invoice_id = 1; string currency = 2; double amount = 3; + int64 credits = 4; } message FinalizeInvoiceRequest { diff --git a/components/usage/pkg/apiv1/billing.go b/components/usage/pkg/apiv1/billing.go index e33c01760a7162..8dad524e310dc3 100644 --- a/components/usage/pkg/apiv1/billing.go +++ b/components/usage/pkg/apiv1/billing.go @@ -58,6 +58,31 @@ func (s *BillingService) FinalizeInvoice(ctx context.Context, in *v1.FinalizeInv return &v1.FinalizeInvoiceResponse{}, nil } +func (s *BillingService) GetUpcomingInvoice(ctx context.Context, in *v1.GetUpcomingInvoiceRequest) (*v1.GetUpcomingInvoiceResponse, error) { + if in.GetTeamId() == "" && in.GetUserId() == "" { + return nil, status.Errorf(codes.InvalidArgument, "teamId or userId is required") + } + var customerKind = "user" + var metaId = in.GetUserId() + if in.GetTeamId() != "" { + customerKind = "team" + metaId = in.GetTeamId() + } + + invoice, err := s.stripeClient.GetUpcomingInvoice(ctx, stripe.CustomerKind(customerKind), metaId) + if err != nil { + log.Log.WithError(err).Errorf("Failed to fetch upcoming invoice from stripe.") + return nil, status.Errorf(codes.Internal, "failed to fetcht upcoming invoice from stripe") + } + + return &v1.GetUpcomingInvoiceResponse{ + InvoiceId: invoice.ID, + Currency: invoice.Currency, + Amount: float64(invoice.Amount), + Credits: invoice.Credits, + }, nil +} + func (s *BillingService) creditSummaryForTeams(sessions []*v1.BilledSession) (map[string]int64, error) { creditsPerTeamID := map[string]float64{} diff --git a/components/usage/pkg/apiv1/billing_test.go b/components/usage/pkg/apiv1/billing_test.go index cde6094b5aaff1..5710de769d571b 100644 --- a/components/usage/pkg/apiv1/billing_test.go +++ b/components/usage/pkg/apiv1/billing_test.go @@ -5,7 +5,6 @@ package apiv1 import ( - "context" "testing" "time" @@ -117,11 +116,3 @@ func TestCreditSummaryForTeams(t *testing.T) { }) } } - -func TestFinalizeInvoice(t *testing.T) { - b := BillingService{} - - _, err := b.FinalizeInvoice(context.Background(), &v1.FinalizeInvoiceRequest{}) - - require.NoError(t, err) -} diff --git a/components/usage/pkg/server/server.go b/components/usage/pkg/server/server.go index ce7759e2625ece..c6c09cc65538a9 100644 --- a/components/usage/pkg/server/server.go +++ b/components/usage/pkg/server/server.go @@ -6,11 +6,12 @@ package server import ( "fmt" - grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" "net" "os" "time" + grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" + "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" diff --git a/components/usage/pkg/stripe/stripe.go b/components/usage/pkg/stripe/stripe.go index 4c11661c8d399d..56b1c84855468c 100644 --- a/components/usage/pkg/stripe/stripe.go +++ b/components/usage/pkg/stripe/stripe.go @@ -7,6 +7,7 @@ package stripe import ( "context" "encoding/json" + "errors" "fmt" "os" "strings" @@ -50,6 +51,26 @@ type UsageRecord struct { Quantity int64 } +type StripeInvoice struct { + ID string + SubscriptionID string + Amount int64 + Currency string + Credits int64 +} + +type CustomerKind string + +const ( + User CustomerKind = "user" + Team = "team" +) + +var ( + // ErrorCustomerNotFound is returned when no stripe customer is found for a given user account + ErrorCustomerNotFound = errors.New("invalid size") +) + // UpdateUsage updates teams' Stripe subscriptions with usage data // `usageForTeam` is a map from team name to total workspace seconds used within a billing period. func (c *Client) UpdateUsage(ctx context.Context, creditsPerTeam map[string]int64) error { @@ -122,6 +143,44 @@ func (c *Client) updateUsageForCustomer(ctx context.Context, customer *stripe.Cu }, nil } +// GetUpcomingInvoice fetches the upcoming invoice for the given team or user id. +func (c *Client) GetUpcomingInvoice(ctx context.Context, kind CustomerKind, id string) (*StripeInvoice, error) { + query := fmt.Sprintf("metadata['%sId']:'%s'", kind, id) + searchParams := &stripe.CustomerSearchParams{ + SearchParams: stripe.SearchParams{ + Query: query, + Expand: []*string{stripe.String("data.subscriptions")}, + Context: ctx, + }, + } + iter := c.sc.Customers.Search(searchParams) + if iter.Err() != nil && !iter.Next() { + return nil, ErrorCustomerNotFound + } + customer := iter.Customer() + if iter.Next() { + return nil, fmt.Errorf("found more than one customer for query %s", query) + } + invoiceParams := &stripe.InvoiceParams{ + Customer: stripe.String(customer.ID), + } + invoice, err := c.sc.Invoices.GetNext(invoiceParams) + if err != nil { + return nil, fmt.Errorf("failed to fetch the upcoming invoice for customer %s", customer.ID) + } + if len(invoice.Lines.Data) < 1 { + return nil, fmt.Errorf("no line items on invoice %s", invoice.ID) + } + + return &StripeInvoice{ + ID: invoice.ID, + SubscriptionID: invoice.Subscription.ID, + Amount: invoice.AmountRemaining, + Currency: string(invoice.Currency), + Credits: invoice.Lines.Data[0].Quantity, + }, nil +} + // queriesForCustomersWithTeamIds constructs Stripe query strings to find the Stripe Customer for each teamId // It returns multiple queries, each being a big disjunction of subclauses so that we can process multiple teamIds in one query. // `clausesPerQuery` is a limit enforced by the Stripe API.