mirror of
https://github.com/gitpod-io/gitpod.git
synced 2025-12-08 17:36:30 +00:00
507 lines
13 KiB
Go
507 lines
13 KiB
Go
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
|
||
// Licensed under the GNU Affero General Public License (AGPL).
|
||
// See License.AGPL.txt in the project root for license information.
|
||
|
||
package apiv1
|
||
|
||
import (
|
||
"context"
|
||
"encoding/json"
|
||
"testing"
|
||
|
||
db "github.com/gitpod-io/gitpod/components/gitpod-db/go"
|
||
"github.com/gitpod-io/gitpod/components/gitpod-db/go/dbtest"
|
||
"github.com/google/uuid"
|
||
"github.com/stretchr/testify/require"
|
||
stripe_api "github.com/stripe/stripe-go/v72"
|
||
)
|
||
|
||
func TestBalancesForStripeCostCenters(t *testing.T) {
|
||
attributionIDForStripe := db.NewUserAttributionID(uuid.New().String())
|
||
attributionIDForOther := db.NewTeamAttributionID(uuid.New().String())
|
||
dbconn := dbtest.ConnectForTests(t)
|
||
|
||
dbtest.CreateCostCenters(t, dbconn,
|
||
dbtest.NewCostCenter(t, db.CostCenter{
|
||
ID: attributionIDForStripe,
|
||
BillingStrategy: db.CostCenter_Stripe,
|
||
}),
|
||
dbtest.NewCostCenter(t, db.CostCenter{
|
||
ID: attributionIDForOther,
|
||
BillingStrategy: db.CostCenter_Other,
|
||
}),
|
||
)
|
||
|
||
balances := []db.Balance{
|
||
{
|
||
AttributionID: attributionIDForStripe,
|
||
CreditCents: 100,
|
||
},
|
||
{
|
||
AttributionID: attributionIDForOther,
|
||
CreditCents: 100,
|
||
},
|
||
}
|
||
|
||
stripeBalances, err := balancesForStripeCostCenters(context.Background(), db.NewCostCenterManager(dbconn, db.DefaultSpendingLimit{}), balances)
|
||
require.NoError(t, err)
|
||
require.Len(t, stripeBalances, 1)
|
||
require.Equal(t, stripeBalances[0].AttributionID, attributionIDForStripe)
|
||
}
|
||
|
||
func TestFinalizeInvoiceForIndividual(t *testing.T) {
|
||
invoice := stripe_api.Invoice{}
|
||
require.NoError(t, json.Unmarshal([]byte(IndiInvoiceTestData), &invoice))
|
||
usage, err := InternalComputeInvoiceUsage(context.Background(), &invoice)
|
||
require.NoError(t, err)
|
||
require.Equal(t, usage.CreditCents, db.CreditCents(-103100))
|
||
}
|
||
|
||
var IndiInvoiceTestData = `{
|
||
"id": "in_1MA0RBAyBDPbWrhabNdJIuhl",
|
||
"object": "invoice",
|
||
"account_country": "DE",
|
||
"account_name": "Gitpod GmbH",
|
||
"account_tax_ids": null,
|
||
"amount_due": 1012,
|
||
"amount_paid": 1012,
|
||
"amount_remaining": 0,
|
||
"application": null,
|
||
"application_fee_amount": null,
|
||
"attempt_count": 1,
|
||
"attempted": true,
|
||
"auto_advance": false,
|
||
"automatic_tax": {
|
||
"enabled": false,
|
||
"status": null
|
||
},
|
||
"billing_reason": "subscription_cycle",
|
||
"charge": "ch_3MA1YjAyBDPbWrha1F1mqyQs",
|
||
"collection_method": "charge_automatically",
|
||
"created": 1669853737,
|
||
"currency": "usd",
|
||
"custom_fields": null,
|
||
"customer": {
|
||
"id": "cus_MoA9ghwDcE2vaA",
|
||
"object": "customer",
|
||
"address": {
|
||
"city": null,
|
||
"country": "TW",
|
||
"line1": "",
|
||
"line2": null,
|
||
"postal_code": null,
|
||
"state": null
|
||
},
|
||
"balance": 0,
|
||
"created": 1668552088,
|
||
"currency": "usd",
|
||
"default_currency": "usd",
|
||
"default_source": null,
|
||
"delinquent": false,
|
||
"description": null,
|
||
"discount": null,
|
||
"email": "xxxxx@email.com",
|
||
"invoice_prefix": "89796AD3",
|
||
"invoice_settings": {
|
||
"custom_fields": null,
|
||
"default_payment_method": "pm_1M4XoqAyBDPbWrhaqEc29Ev0",
|
||
"footer": null,
|
||
"rendering_options": null
|
||
},
|
||
"livemode": false,
|
||
"metadata": {
|
||
"attributionId": "user:12345678-1234-1234-1234-123456789abc",
|
||
"preferredCurrency": "USD"
|
||
},
|
||
"name": "user-name",
|
||
"phone": null,
|
||
"preferred_locales": [],
|
||
"shipping": null,
|
||
"tax_exempt": "none",
|
||
"test_clock": null
|
||
},
|
||
"customer_address": {
|
||
"city": null,
|
||
"country": "TW",
|
||
"line1": "",
|
||
"line2": null,
|
||
"postal_code": null,
|
||
"state": null
|
||
},
|
||
"customer_email": "xxxxx@email.com",
|
||
"customer_name": "user-name",
|
||
"customer_phone": null,
|
||
"customer_shipping": null,
|
||
"customer_tax_exempt": "none",
|
||
"customer_tax_ids": [],
|
||
"default_payment_method": null,
|
||
"default_source": null,
|
||
"default_tax_rates": [],
|
||
"description": null,
|
||
"discount": null,
|
||
"discounts": [],
|
||
"due_date": null,
|
||
"ending_balance": 0,
|
||
"footer": null,
|
||
"from_invoice": null,
|
||
"hosted_invoice_url": "xxxx",
|
||
"invoice_pdf": "xxxx",
|
||
"last_finalization_error": null,
|
||
"latest_revision": null,
|
||
"lines": {
|
||
"object": "list",
|
||
"data": [
|
||
{
|
||
"id": "il_1MA0RBAyBDPbWrhaMKGOYdcr",
|
||
"object": "line_item",
|
||
"amount": 0,
|
||
"amount_excluding_tax": 0,
|
||
"currency": "usd",
|
||
"description": "1000 credit × Gitpod Usage (Tier 1 at $0.00 / month)",
|
||
"discount_amounts": [],
|
||
"discountable": true,
|
||
"discounts": [],
|
||
"livemode": false,
|
||
"metadata": {},
|
||
"period": {
|
||
"end": 1669852800,
|
||
"start": 1668552093
|
||
},
|
||
"plan": {
|
||
"id": "price_1LmYDQAyBDPbWrhaiebWlzVX",
|
||
"object": "plan",
|
||
"active": true,
|
||
"aggregate_usage": "last_during_period",
|
||
"amount": null,
|
||
"amount_decimal": null,
|
||
"billing_scheme": "tiered",
|
||
"created": 1664263708,
|
||
"currency": "usd",
|
||
"interval": "month",
|
||
"interval_count": 1,
|
||
"livemode": false,
|
||
"metadata": {},
|
||
"nickname": "Individual USD",
|
||
"product": "prod_MIUT2nUscrEWBA",
|
||
"tiers_mode": "graduated",
|
||
"transform_usage": null,
|
||
"trial_period_days": null,
|
||
"usage_type": "metered"
|
||
},
|
||
"price": {
|
||
"id": "price_1LmYDQAyBDPbWrhaiebWlzVX",
|
||
"object": "price",
|
||
"active": true,
|
||
"billing_scheme": "tiered",
|
||
"created": 1664263708,
|
||
"currency": "usd",
|
||
"custom_unit_amount": null,
|
||
"livemode": false,
|
||
"lookup_key": null,
|
||
"metadata": {},
|
||
"nickname": "Individual USD",
|
||
"product": "prod_MIUT2nUscrEWBA",
|
||
"recurring": {
|
||
"aggregate_usage": "last_during_period",
|
||
"interval": "month",
|
||
"interval_count": 1,
|
||
"trial_period_days": null,
|
||
"usage_type": "metered"
|
||
},
|
||
"tax_behavior": "inclusive",
|
||
"tiers_mode": "graduated",
|
||
"transform_quantity": null,
|
||
"type": "recurring",
|
||
"unit_amount": null,
|
||
"unit_amount_decimal": null
|
||
},
|
||
"proration": false,
|
||
"proration_details": {
|
||
"credited_items": null
|
||
},
|
||
"quantity": 1000,
|
||
"subscription": "sub_1M4XovAyBDPbWrhaCnn4gigv",
|
||
"subscription_item": "si_MoA9zVoSS4gH2G",
|
||
"tax_amounts": [],
|
||
"tax_rates": [],
|
||
"type": "subscription",
|
||
"unit_amount_excluding_tax": "0"
|
||
},
|
||
{
|
||
"id": "il_1MA0RCAyBDPbWrhaogm8Cw8j",
|
||
"object": "line_item",
|
||
"amount": 900,
|
||
"amount_excluding_tax": 900,
|
||
"currency": "usd",
|
||
"description": "Gitpod Usage (Tier 1 at $9.00 / month)",
|
||
"discount_amounts": [],
|
||
"discountable": true,
|
||
"discounts": [],
|
||
"livemode": false,
|
||
"metadata": {},
|
||
"period": {
|
||
"end": 1669852800,
|
||
"start": 1668552093
|
||
},
|
||
"plan": {
|
||
"id": "price_1LmYDQAyBDPbWrhaiebWlzVX",
|
||
"object": "plan",
|
||
"active": true,
|
||
"aggregate_usage": "last_during_period",
|
||
"amount": null,
|
||
"amount_decimal": null,
|
||
"billing_scheme": "tiered",
|
||
"created": 1664263708,
|
||
"currency": "usd",
|
||
"interval": "month",
|
||
"interval_count": 1,
|
||
"livemode": false,
|
||
"metadata": {},
|
||
"nickname": "Individual USD",
|
||
"product": "prod_MIUT2nUscrEWBA",
|
||
"tiers_mode": "graduated",
|
||
"transform_usage": null,
|
||
"trial_period_days": null,
|
||
"usage_type": "metered"
|
||
},
|
||
"price": {
|
||
"id": "price_1LmYDQAyBDPbWrhaiebWlzVX",
|
||
"object": "price",
|
||
"active": true,
|
||
"billing_scheme": "tiered",
|
||
"created": 1664263708,
|
||
"currency": "usd",
|
||
"custom_unit_amount": null,
|
||
"livemode": false,
|
||
"lookup_key": null,
|
||
"metadata": {},
|
||
"nickname": "Individual USD",
|
||
"product": "prod_MIUT2nUscrEWBA",
|
||
"recurring": {
|
||
"aggregate_usage": "last_during_period",
|
||
"interval": "month",
|
||
"interval_count": 1,
|
||
"trial_period_days": null,
|
||
"usage_type": "metered"
|
||
},
|
||
"tax_behavior": "inclusive",
|
||
"tiers_mode": "graduated",
|
||
"transform_quantity": null,
|
||
"type": "recurring",
|
||
"unit_amount": null,
|
||
"unit_amount_decimal": null
|
||
},
|
||
"proration": false,
|
||
"proration_details": {
|
||
"credited_items": null
|
||
},
|
||
"quantity": 0,
|
||
"subscription": "sub_1M4XovAyBDPbWrhaCnn4gigv",
|
||
"subscription_item": "si_MoA9zVoSS4gH2G",
|
||
"tax_amounts": [],
|
||
"tax_rates": [],
|
||
"type": "subscription",
|
||
"unit_amount_excluding_tax": null
|
||
},
|
||
{
|
||
"id": "il_1MA0RDAyBDPbWrhaIF5LaBhx",
|
||
"object": "line_item",
|
||
"amount": 112,
|
||
"amount_excluding_tax": 112,
|
||
"currency": "usd",
|
||
"description": "31 credit × Gitpod Usage (Tier 2 at $0.036 / month)",
|
||
"discount_amounts": [],
|
||
"discountable": true,
|
||
"discounts": [],
|
||
"livemode": false,
|
||
"metadata": {},
|
||
"period": {
|
||
"end": 1669852800,
|
||
"start": 1668552093
|
||
},
|
||
"plan": {
|
||
"id": "price_1LmYDQAyBDPbWrhaiebWlzVX",
|
||
"object": "plan",
|
||
"active": true,
|
||
"aggregate_usage": "last_during_period",
|
||
"amount": null,
|
||
"amount_decimal": null,
|
||
"billing_scheme": "tiered",
|
||
"created": 1664263708,
|
||
"currency": "usd",
|
||
"interval": "month",
|
||
"interval_count": 1,
|
||
"livemode": false,
|
||
"metadata": {},
|
||
"nickname": "Individual USD",
|
||
"product": "prod_MIUT2nUscrEWBA",
|
||
"tiers_mode": "graduated",
|
||
"transform_usage": null,
|
||
"trial_period_days": null,
|
||
"usage_type": "metered"
|
||
},
|
||
"price": {
|
||
"id": "price_1LmYDQAyBDPbWrhaiebWlzVX",
|
||
"object": "price",
|
||
"active": true,
|
||
"billing_scheme": "tiered",
|
||
"created": 1664263708,
|
||
"currency": "usd",
|
||
"custom_unit_amount": null,
|
||
"livemode": false,
|
||
"lookup_key": null,
|
||
"metadata": {},
|
||
"nickname": "Individual USD",
|
||
"product": "prod_MIUT2nUscrEWBA",
|
||
"recurring": {
|
||
"aggregate_usage": "last_during_period",
|
||
"interval": "month",
|
||
"interval_count": 1,
|
||
"trial_period_days": null,
|
||
"usage_type": "metered"
|
||
},
|
||
"tax_behavior": "inclusive",
|
||
"tiers_mode": "graduated",
|
||
"transform_quantity": null,
|
||
"type": "recurring",
|
||
"unit_amount": null,
|
||
"unit_amount_decimal": null
|
||
},
|
||
"proration": false,
|
||
"proration_details": {
|
||
"credited_items": null
|
||
},
|
||
"quantity": 31,
|
||
"subscription": "sub_1M4XovAyBDPbWrhaCnn4gigv",
|
||
"subscription_item": "si_MoA9zVoSS4gH2G",
|
||
"tax_amounts": [],
|
||
"tax_rates": [],
|
||
"type": "subscription",
|
||
"unit_amount_excluding_tax": "4"
|
||
},
|
||
{
|
||
"id": "il_1MA0REAyBDPbWrhaMRhZhiJ6",
|
||
"object": "line_item",
|
||
"amount": 0,
|
||
"amount_excluding_tax": 0,
|
||
"currency": "usd",
|
||
"description": "Gitpod Usage (Tier 2 at $0.00 / month)",
|
||
"discount_amounts": [],
|
||
"discountable": true,
|
||
"discounts": [],
|
||
"livemode": false,
|
||
"metadata": {},
|
||
"period": {
|
||
"end": 1669852800,
|
||
"start": 1668552093
|
||
},
|
||
"plan": {
|
||
"id": "price_1LmYDQAyBDPbWrhaiebWlzVX",
|
||
"object": "plan",
|
||
"active": true,
|
||
"aggregate_usage": "last_during_period",
|
||
"amount": null,
|
||
"amount_decimal": null,
|
||
"billing_scheme": "tiered",
|
||
"created": 1664263708,
|
||
"currency": "usd",
|
||
"interval": "month",
|
||
"interval_count": 1,
|
||
"livemode": false,
|
||
"metadata": {},
|
||
"nickname": "Individual USD",
|
||
"product": "prod_MIUT2nUscrEWBA",
|
||
"tiers_mode": "graduated",
|
||
"transform_usage": null,
|
||
"trial_period_days": null,
|
||
"usage_type": "metered"
|
||
},
|
||
"price": {
|
||
"id": "price_1LmYDQAyBDPbWrhaiebWlzVX",
|
||
"object": "price",
|
||
"active": true,
|
||
"billing_scheme": "tiered",
|
||
"created": 1664263708,
|
||
"currency": "usd",
|
||
"custom_unit_amount": null,
|
||
"livemode": false,
|
||
"lookup_key": null,
|
||
"metadata": {},
|
||
"nickname": "Individual USD",
|
||
"product": "prod_MIUT2nUscrEWBA",
|
||
"recurring": {
|
||
"aggregate_usage": "last_during_period",
|
||
"interval": "month",
|
||
"interval_count": 1,
|
||
"trial_period_days": null,
|
||
"usage_type": "metered"
|
||
},
|
||
"tax_behavior": "inclusive",
|
||
"tiers_mode": "graduated",
|
||
"transform_quantity": null,
|
||
"type": "recurring",
|
||
"unit_amount": null,
|
||
"unit_amount_decimal": null
|
||
},
|
||
"proration": false,
|
||
"proration_details": {
|
||
"credited_items": null
|
||
},
|
||
"quantity": 0,
|
||
"subscription": "sub_1M4XovAyBDPbWrhaCnn4gigv",
|
||
"subscription_item": "si_MoA9zVoSS4gH2G",
|
||
"tax_amounts": [],
|
||
"tax_rates": [],
|
||
"type": "subscription",
|
||
"unit_amount_excluding_tax": null
|
||
}
|
||
],
|
||
"has_more": false,
|
||
"total_count": 4,
|
||
"url": "/v1/invoices/in_1MA0RBAyBDPbWrhabNdJIuhl/lines"
|
||
},
|
||
"livemode": false,
|
||
"metadata": {},
|
||
"next_payment_attempt": null,
|
||
"number": "DF67D6F2-0037",
|
||
"on_behalf_of": null,
|
||
"paid": true,
|
||
"paid_out_of_band": false,
|
||
"payment_intent": "pi_3MA1YjAyBDPbWrha1Tb6pdTW",
|
||
"payment_settings": {
|
||
"default_mandate": null,
|
||
"payment_method_options": null,
|
||
"payment_method_types": [
|
||
"card",
|
||
"link"
|
||
]
|
||
},
|
||
"period_end": 1669852800,
|
||
"period_start": 1668552093,
|
||
"post_payment_credit_notes_amount": 0,
|
||
"pre_payment_credit_notes_amount": 0,
|
||
"quote": null,
|
||
"receipt_number": "2061-6831",
|
||
"rendering_options": null,
|
||
"starting_balance": 0,
|
||
"statement_descriptor": null,
|
||
"status": "paid",
|
||
"status_transitions": {
|
||
"finalized_at": 1669858049,
|
||
"marked_uncollectible_at": null,
|
||
"paid_at": 1669948594,
|
||
"voided_at": null
|
||
},
|
||
"subscription": "sub_1M4XovAyBDPbWrhaCnn4gigv",
|
||
"subtotal": 1012,
|
||
"subtotal_excluding_tax": 1012,
|
||
"tax": null,
|
||
"test_clock": null,
|
||
"total": 1012,
|
||
"total_discount_amounts": [],
|
||
"total_excluding_tax": 1012,
|
||
"total_tax_amounts": [],
|
||
"transfer_data": null,
|
||
"webhooks_delivered_at": 1669853737
|
||
}`
|