// 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 }`