storj/satellite/payments/stripe/accounts_test.go
Cameron 09ec5f107d satellite/payments: Remove expired package credits
During billing, before invoice creation, check if users are part of a
package plan. If so, and if the package plan is expired, remove unused
credit from the user's balance. If the user has credit in addition to
the package credit, send an analytics event to notify someone to handle
the credit removal manually.

Change-Id: Iad71d791f67c9733f9d9e42f962c64b2780264cc
2023-05-22 11:58:37 +00:00

167 lines
5.0 KiB
Go

// Copyright (C) 2021 Storj Labs, Inc.
// See LICENSE for copying information.
package stripe_test
import (
"testing"
"time"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest"
"storj.io/common/testcontext"
"storj.io/storj/private/testplanet"
"storj.io/storj/private/testredis"
"storj.io/storj/satellite/accounting"
"storj.io/storj/satellite/accounting/live"
"storj.io/storj/satellite/analytics"
"storj.io/storj/satellite/console"
"storj.io/storj/satellite/console/consoleauth"
"storj.io/storj/satellite/console/restkeys"
"storj.io/storj/satellite/payments"
"storj.io/storj/satellite/payments/paymentsconfig"
"storj.io/storj/satellite/payments/stripe"
)
func TestSignupCouponCodes(t *testing.T) {
testplanet.Run(t, testplanet.Config{SatelliteCount: 1}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
sat := planet.Satellites[0]
db := sat.DB
log := zaptest.NewLogger(t)
analyticsService := analytics.NewService(log, analytics.Config{}, "test-satellite")
redis, err := testredis.Mini(ctx)
require.NoError(t, err)
defer ctx.Check(redis.Close)
cache, err := live.OpenCache(ctx, log.Named("cache"), live.Config{StorageBackend: "redis://" + redis.Addr() + "?db=0"})
require.NoError(t, err)
projectLimitCache := accounting.NewProjectLimitCache(db.ProjectAccounting(), 0, 0, 0, accounting.ProjectLimitConfig{CacheCapacity: 100})
projectUsage := accounting.NewService(db.ProjectAccounting(), cache, projectLimitCache, *sat.API.Metainfo.Metabase, 5*time.Minute, -10*time.Second)
pc := paymentsconfig.Config{
UsagePrice: paymentsconfig.ProjectUsagePrice{
StorageTB: "10",
EgressTB: "45",
Segment: "0.0000022",
},
}
prices, err := pc.UsagePrice.ToModel()
require.NoError(t, err)
priceOverrides, err := pc.UsagePriceOverrides.ToModels()
require.NoError(t, err)
paymentsService, err := stripe.NewService(
log.Named("payments.stripe:service"),
stripe.NewStripeMock(
db.StripeCoinPayments().Customers(),
db.Console().Users(),
),
pc.StripeCoinPayments,
db.StripeCoinPayments(),
db.Wallets(),
db.Billing(),
db.Console().Projects(),
db.Console().Users(),
db.ProjectAccounting(),
prices,
priceOverrides,
pc.PackagePlans.Packages,
pc.BonusRate,
nil,
)
require.NoError(t, err)
service, err := console.NewService(
log.Named("console"),
db.Console(),
restkeys.NewService(db.OIDC().OAuthTokens(), planet.Satellites[0].Config.RESTKeys),
db.ProjectAccounting(),
projectUsage,
sat.API.Buckets.Service,
paymentsService.Accounts(),
// TODO: do we need a payment deposit wallet here?
nil,
db.Billing(),
analyticsService,
consoleauth.NewService(consoleauth.Config{
TokenExpirationTime: 24 * time.Hour,
}, &consoleauth.Hmac{Secret: []byte("my-suppa-secret-key")}),
nil,
"",
console.Config{PasswordCost: console.TestPasswordCost, DefaultProjectLimit: 5},
)
require.NoError(t, err)
testCases := []struct {
name string
email string
signupPromoCode string
expectedCouponType payments.CouponType
}{
{"good signup promo code", "test1@mail.test", "promo1", payments.SignupCoupon},
{"bad signup promo code", "test2@mail.test", "badpromo", payments.NoCoupon},
}
for _, tt := range testCases {
tt := tt
t.Run(tt.name, func(t *testing.T) {
createUser := console.CreateUser{
FullName: "Fullname",
ShortName: "Shortname",
Email: tt.email,
Password: "123a123",
SignupPromoCode: tt.signupPromoCode,
}
regToken, err := service.CreateRegToken(ctx, 1)
require.NoError(t, err)
rootUser, err := service.CreateUser(ctx, createUser, regToken.Secret)
require.NoError(t, err)
couponType, err := paymentsService.Accounts().Setup(ctx, rootUser.ID, rootUser.Email, rootUser.SignupPromoCode)
require.NoError(t, err)
require.Equal(t, tt.expectedCouponType, couponType)
})
}
})
}
func TestUpdateGetPackage(t *testing.T) {
testplanet.Run(t, testplanet.Config{
SatelliteCount: 1, StorageNodeCount: 0, UplinkCount: 1,
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
accounts := planet.Satellites[0].API.Payments.Accounts
userID := planet.Uplinks[0].Projects[0].Owner.ID
var packagePlan string
var purchaseTime time.Time
packagePlan = "package-plan-1"
purchaseTime = time.Now()
require.NoError(t, accounts.UpdatePackage(ctx, userID, &packagePlan, &purchaseTime))
dbPackagePlan, dbPurchaseTime, err := accounts.GetPackageInfo(ctx, userID)
require.NoError(t, err)
require.NotNil(t, dbPackagePlan)
require.NotNil(t, dbPurchaseTime)
require.Equal(t, packagePlan, *dbPackagePlan)
require.Equal(t, purchaseTime.Truncate(time.Millisecond), dbPurchaseTime.Truncate(time.Millisecond))
require.NoError(t, accounts.UpdatePackage(ctx, userID, nil, nil))
dbPackagePlan, dbPurchaseTime, err = accounts.GetPackageInfo(ctx, userID)
require.NoError(t, err)
require.Nil(t, dbPackagePlan)
require.Nil(t, dbPurchaseTime)
})
}