add user credit usage method into console service (#2240)

This commit is contained in:
Yingrong Zhao 2019-06-19 16:49:04 -04:00 committed by Stefan Benten
parent 213bcacc83
commit d583ab707b
5 changed files with 84 additions and 75 deletions

View File

@ -21,9 +21,7 @@ import (
"storj.io/storj/satellite/payments"
)
var (
mon = monkit.Package()
)
var mon = monkit.Package()
const (
// maxLimit specifies the limit for all paged queries
@ -457,6 +455,22 @@ func (s *Service) GetUsersProjects(ctx context.Context) (ps []Project, err error
return
}
// GetUserCreditUsage is a method for querying users' credit information up until now
func (s *Service) GetUserCreditUsage(ctx context.Context) (usage *UserCreditUsage, err error) {
defer mon.Task()(&ctx)(&err)
auth, err := GetAuth(ctx)
if err != nil {
return nil, errs.Wrap(err)
}
usage, err = s.store.UserCredits().GetCreditUsage(ctx, auth.User.ID, time.Now().UTC())
if err != nil {
return nil, errs.Wrap(err)
}
return usage, nil
}
// CreateProject is a method for creating new project
func (s *Service) CreateProject(ctx context.Context, projectInfo ProjectInfo) (p *Project, err error) {
defer mon.Task()(&ctx)(&err)

View File

@ -12,8 +12,7 @@ import (
// UserCredits holds information to interact with database
type UserCredits interface {
TotalReferredCount(ctx context.Context, userID uuid.UUID) (int64, error)
GetAvailableCredits(ctx context.Context, userID uuid.UUID, expirationEndDate time.Time) ([]UserCredit, error)
GetCreditUsage(ctx context.Context, userID uuid.UUID, expirationEndDate time.Time) (*UserCreditUsage, error)
Create(ctx context.Context, userCredit UserCredit) (*UserCredit, error)
UpdateAvailableCredits(ctx context.Context, creditsToCharge int, id uuid.UUID, billingStartDate time.Time) (remainingCharge int, err error)
}
@ -29,3 +28,10 @@ type UserCredit struct {
ExpiresAt time.Time
CreatedAt time.Time
}
// UserCreditUsage holds information about credit usage information
type UserCreditUsage struct {
Referred int64
AvailableCredits int64
UsedCredits int64
}

View File

@ -503,16 +503,10 @@ func (m *lockedUserCredits) Create(ctx context.Context, userCredit console.UserC
return m.db.Create(ctx, userCredit)
}
func (m *lockedUserCredits) GetAvailableCredits(ctx context.Context, userID uuid.UUID, expirationEndDate time.Time) ([]console.UserCredit, error) {
func (m *lockedUserCredits) GetCreditUsage(ctx context.Context, userID uuid.UUID, expirationEndDate time.Time) (*console.UserCreditUsage, error) {
m.Lock()
defer m.Unlock()
return m.db.GetAvailableCredits(ctx, userID, expirationEndDate)
}
func (m *lockedUserCredits) TotalReferredCount(ctx context.Context, userID uuid.UUID) (int64, error) {
m.Lock()
defer m.Unlock()
return m.db.TotalReferredCount(ctx, userID)
return m.db.GetCreditUsage(ctx, userID, expirationEndDate)
}
func (m *lockedUserCredits) UpdateAvailableCredits(ctx context.Context, creditsToCharge int, id uuid.UUID, billingStartDate time.Time) (remainingCharge int, err error) {

View File

@ -5,6 +5,7 @@ package satellitedb
import (
"context"
"database/sql"
"time"
"github.com/lib/pq"
@ -20,27 +21,36 @@ type usercredits struct {
db *dbx.DB
}
// TotalReferredCount returns the total amount of referral a user has made based on user id
func (c *usercredits) TotalReferredCount(ctx context.Context, id uuid.UUID) (int64, error) {
totalReferred, err := c.db.Count_UserCredit_By_ReferredBy(ctx, dbx.UserCredit_ReferredBy(id[:]))
if err != nil {
return totalReferred, errs.Wrap(err)
}
return totalReferred, nil
}
// GetAvailableCredits returns all records of user credit that are not expired or used
func (c *usercredits) GetAvailableCredits(ctx context.Context, referrerID uuid.UUID, expirationEndDate time.Time) ([]console.UserCredit, error) {
availableCredits, err := c.db.All_UserCredit_By_UserId_And_ExpiresAt_Greater_And_CreditsUsedInCents_Less_CreditsEarnedInCents_OrderBy_Asc_ExpiresAt(ctx,
dbx.UserCredit_UserId(referrerID[:]),
dbx.UserCredit_ExpiresAt(expirationEndDate),
)
// GetCreditUsage returns the total amount of referral a user has made based on user id, total available credits, and total used credits based on user id
func (c *usercredits) GetCreditUsage(ctx context.Context, userID uuid.UUID, expirationEndDate time.Time) (*console.UserCreditUsage, error) {
usageRows, err := c.db.DB.QueryContext(ctx, c.db.Rebind(`SELECT a.used_credit, b.available_credit, c.referred
FROM (SELECT SUM(credits_used_in_cents) AS used_credit FROM user_credits WHERE user_id = ?) AS a,
(SELECT SUM(credits_earned_in_cents - credits_used_in_cents) AS available_credit FROM user_credits WHERE expires_at > ? AND user_id = ?) AS b,
(SELECT count(id) AS referred FROM user_credits WHERE user_credits.referred_by = ?) AS c;`), userID[:], expirationEndDate, userID[:], userID[:])
if err != nil {
return nil, errs.Wrap(err)
}
return userCreditsFromDBX(availableCredits)
usage := console.UserCreditUsage{}
for usageRows.Next() {
var (
usedCredit sql.NullInt64
availableCredit sql.NullInt64
referred sql.NullInt64
)
err = usageRows.Scan(&usedCredit, &availableCredit, &referred)
if err != nil {
return nil, errs.Wrap(err)
}
usage.UsedCredits += usedCredit.Int64
usage.Referred += referred.Int64
usage.AvailableCredits += availableCredit.Int64
}
return &usage, nil
}
// Create insert a new record of user credit
@ -141,23 +151,6 @@ func generateQuery(totalRows int, toInt bool) (query string) {
return query
}
func userCreditsFromDBX(userCreditsDBX []*dbx.UserCredit) ([]console.UserCredit, error) {
var userCredits []console.UserCredit
errList := new(errs.Group)
for _, credit := range userCreditsDBX {
uc, err := convertDBCredit(credit)
if err != nil {
errList.Add(err)
continue
}
userCredits = append(userCredits, *uc)
}
return userCredits, errList.Err()
}
func convertDBCredit(userCreditDBX *dbx.UserCredit) (*console.UserCredit, error) {
if userCreditDBX == nil {
return nil, errs.New("userCreditDBX parameter is nil")

View File

@ -67,7 +67,7 @@ func TestUsercredits(t *testing.T) {
type result struct {
remainingCharge int
availableCredits int
usage console.UserCreditUsage
hasErr bool
}
@ -87,7 +87,11 @@ func TestUsercredits(t *testing.T) {
chargedCredits: 120,
expected: result{
remainingCharge: 20,
availableCredits: 0,
usage: console.UserCreditUsage{
AvailableCredits: 0,
UsedCredits: 100,
Referred: 0,
},
hasErr: false,
},
},
@ -103,7 +107,11 @@ func TestUsercredits(t *testing.T) {
chargedCredits: 60,
expected: result{
remainingCharge: 60,
availableCredits: 0,
usage: console.UserCreditUsage{
AvailableCredits: 0,
UsedCredits: 100,
Referred: 0,
},
hasErr: true,
},
},
@ -119,7 +127,11 @@ func TestUsercredits(t *testing.T) {
chargedCredits: 80,
expected: result{
remainingCharge: 0,
availableCredits: 20,
usage: console.UserCreditUsage{
AvailableCredits: 20,
UsedCredits: 180,
Referred: 0,
},
hasErr: false,
},
},
@ -129,16 +141,6 @@ func TestUsercredits(t *testing.T) {
_, err = consoleDB.UserCredits().Create(ctx, vc.userCredit)
require.NoError(t, err)
{
referredCount, err := consoleDB.UserCredits().TotalReferredCount(ctx, vc.userCredit.ReferredBy)
if err != nil {
require.True(t, uuid.Equal(*randomID, vc.userCredit.ReferredBy))
continue
}
require.NoError(t, err)
require.Equal(t, int64(i+1), referredCount)
}
{
remainingCharge, err := consoleDB.UserCredits().UpdateAvailableCredits(ctx, vc.chargedCredits, vc.userCredit.UserID, time.Now().UTC())
if vc.expected.hasErr {
@ -150,15 +152,15 @@ func TestUsercredits(t *testing.T) {
}
{
availableCredits, err := consoleDB.UserCredits().GetAvailableCredits(ctx, vc.userCredit.UserID, time.Now().UTC())
usage, err := consoleDB.UserCredits().GetCreditUsage(ctx, vc.userCredit.UserID, time.Now().UTC())
require.NoError(t, err)
var sum int
for i := range availableCredits {
sum += availableCredits[i].CreditsEarnedInCents - availableCredits[i].CreditsUsedInCents
require.Equal(t, vc.expected.usage, *usage)
}
{
referred, err := consoleDB.UserCredits().GetCreditUsage(ctx, referrer.ID, time.Now().UTC())
require.NoError(t, err)
require.Equal(t, vc.expected.availableCredits, sum)
require.Equal(t, int64(i+1), referred.Referred)
}
}
})