satellite: rearrange marketing package (#2268)
* move offer out of marketing package and remove marketing package * fix imports * fix rename errors * remove offer service * change package name from offers to rewards * fix linting * remove unused code and use appropriate comment
This commit is contained in:
parent
30f790a040
commit
bbedff12a6
@ -26,7 +26,7 @@ import (
|
||||
"storj.io/storj/satellite/console"
|
||||
"storj.io/storj/satellite/console/consoleweb"
|
||||
"storj.io/storj/satellite/mailservice"
|
||||
"storj.io/storj/satellite/marketing/marketingweb"
|
||||
"storj.io/storj/satellite/marketingweb"
|
||||
"storj.io/storj/satellite/metainfo"
|
||||
"storj.io/storj/satellite/orders"
|
||||
"storj.io/storj/satellite/satellitedb"
|
||||
|
@ -1,9 +0,0 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information
|
||||
|
||||
package marketing
|
||||
|
||||
// DB contains access to all marketing related databases
|
||||
type DB interface {
|
||||
Offers() Offers
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information
|
||||
|
||||
package marketing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/zeebo/errs"
|
||||
"go.uber.org/zap"
|
||||
monkit "gopkg.in/spacemonkeygo/monkit.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
// Error the default offers errs class
|
||||
Error = errs.Class("marketing error")
|
||||
|
||||
mon = monkit.Package()
|
||||
)
|
||||
|
||||
// Service allows access to offers info in the db
|
||||
type Service struct {
|
||||
log *zap.Logger
|
||||
db DB
|
||||
}
|
||||
|
||||
// NewService creates a new offers db
|
||||
func NewService(log *zap.Logger, db DB) (*Service, error) {
|
||||
if log == nil {
|
||||
return nil, Error.New("log can't be nil")
|
||||
}
|
||||
|
||||
return &Service{
|
||||
log: log,
|
||||
db: db,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ListAllOffers returns all available offers in the db
|
||||
func (s *Service) ListAllOffers(ctx context.Context) (offers []Offer, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
offers, err = s.db.Offers().ListAll(ctx)
|
||||
if err != nil {
|
||||
return offers, Error.Wrap(err)
|
||||
}
|
||||
|
||||
return offers, nil
|
||||
}
|
||||
|
||||
// GetCurrentOfferByType returns current active offer
|
||||
func (s *Service) GetCurrentOfferByType(ctx context.Context, offerType OfferType) (offer *Offer, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
offer, err = s.db.Offers().GetCurrentByType(ctx, offerType)
|
||||
if err != nil {
|
||||
return nil, Error.Wrap(err)
|
||||
}
|
||||
|
||||
return offer, nil
|
||||
}
|
||||
|
||||
// InsertNewOffer inserts a new offer into the db
|
||||
func (s *Service) InsertNewOffer(ctx context.Context, offer *NewOffer) (o *Offer, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
if offer.Status == Default {
|
||||
offer.ExpiresAt = time.Now().UTC().AddDate(100, 0, 0)
|
||||
offer.RedeemableCap = 1
|
||||
}
|
||||
|
||||
o, err = s.db.Offers().Create(ctx, offer)
|
||||
if err != nil {
|
||||
return nil, Error.Wrap(err)
|
||||
}
|
||||
|
||||
return o, nil
|
||||
}
|
||||
|
||||
// RedeemOffer adds 1 to the number of redeemed for an offer
|
||||
func (s *Service) RedeemOffer(ctx context.Context, uo *UpdateOffer) (err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
if uo.Status == Default {
|
||||
return nil
|
||||
}
|
||||
|
||||
err = s.db.Offers().Redeem(ctx, uo.ID)
|
||||
if err != nil {
|
||||
return Error.Wrap(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FinishOffer updates an active offer's status to be Done and its expiration time to be now
|
||||
func (s *Service) FinishOffer(ctx context.Context, oID int) (err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
err = s.db.Offers().Finish(ctx, oID)
|
||||
if err != nil {
|
||||
return Error.Wrap(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -19,13 +19,13 @@ import (
|
||||
// Error is satellite marketing error type
|
||||
var Error = errs.Class("satellite marketing error")
|
||||
|
||||
// Config contains configuration for marketing offersweb server
|
||||
// Config contains configuration for marketingweb server
|
||||
type Config struct {
|
||||
Address string `help:"server address of the marketing Admin GUI" default:"127.0.0.1:8090"`
|
||||
StaticDir string `help:"path to static resources" default:""`
|
||||
}
|
||||
|
||||
// Server represents marketing offersweb server
|
||||
// Server represents marketingweb server
|
||||
type Server struct {
|
||||
log *zap.Logger
|
||||
|
||||
@ -52,7 +52,7 @@ func (s *Server) commonPages() []string {
|
||||
}
|
||||
}
|
||||
|
||||
// NewServer creates new instance of offersweb server
|
||||
// NewServer creates new instance of marketingweb server
|
||||
func NewServer(logger *zap.Logger, config Config, listener net.Listener) (*Server, error) {
|
||||
s := &Server{
|
||||
log: logger,
|
@ -49,13 +49,13 @@ import (
|
||||
"storj.io/storj/satellite/inspector"
|
||||
"storj.io/storj/satellite/mailservice"
|
||||
"storj.io/storj/satellite/mailservice/simulate"
|
||||
"storj.io/storj/satellite/marketing"
|
||||
"storj.io/storj/satellite/marketing/marketingweb"
|
||||
"storj.io/storj/satellite/marketingweb"
|
||||
"storj.io/storj/satellite/metainfo"
|
||||
"storj.io/storj/satellite/orders"
|
||||
"storj.io/storj/satellite/payments"
|
||||
"storj.io/storj/satellite/payments/localpayments"
|
||||
"storj.io/storj/satellite/payments/stripepayments"
|
||||
"storj.io/storj/satellite/rewards"
|
||||
"storj.io/storj/satellite/vouchers"
|
||||
"storj.io/storj/storage"
|
||||
"storj.io/storj/storage/boltdb"
|
||||
@ -91,8 +91,8 @@ type DB interface {
|
||||
Irreparable() irreparable.DB
|
||||
// Console returns database for satellite console
|
||||
Console() console.DB
|
||||
// Marketing returns database for marketing admin GUI
|
||||
Marketing() marketing.DB
|
||||
// returns database for marketing admin GUI
|
||||
Rewards() rewards.DB
|
||||
// Orders returns database for orders
|
||||
Orders() orders.DB
|
||||
// Containment returns database for containment
|
||||
|
@ -1,24 +1,19 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information
|
||||
|
||||
package marketing
|
||||
package rewards
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/zeebo/errs"
|
||||
)
|
||||
|
||||
// OffersErr creates offer error class
|
||||
var OffersErr = errs.Class("offers error")
|
||||
|
||||
// Offers holds information about offer
|
||||
type Offers interface {
|
||||
// DB holds information about offer
|
||||
type DB interface {
|
||||
ListAll(ctx context.Context) ([]Offer, error)
|
||||
GetCurrentByType(ctx context.Context, offerType OfferType) (*Offer, error)
|
||||
Create(ctx context.Context, offer *NewOffer) (*Offer, error)
|
||||
Redeem(ctx context.Context, offerID int) error
|
||||
Redeem(ctx context.Context, offerID int, isDefault bool) error
|
||||
Finish(ctx context.Context, offerID int) error
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information
|
||||
|
||||
package marketing_test
|
||||
package rewards_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@ -11,7 +11,7 @@ import (
|
||||
|
||||
"storj.io/storj/internal/testcontext"
|
||||
"storj.io/storj/internal/testplanet"
|
||||
"storj.io/storj/satellite/marketing"
|
||||
"storj.io/storj/satellite/rewards"
|
||||
)
|
||||
|
||||
func TestOffer_Database(t *testing.T) {
|
||||
@ -19,7 +19,7 @@ func TestOffer_Database(t *testing.T) {
|
||||
SatelliteCount: 1,
|
||||
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
||||
// Happy path
|
||||
validOffers := []marketing.NewOffer{
|
||||
validOffers := []rewards.NewOffer{
|
||||
{
|
||||
Name: "test",
|
||||
Description: "test offer 1",
|
||||
@ -29,8 +29,8 @@ func TestOffer_Database(t *testing.T) {
|
||||
InviteeCreditDurationDays: 30,
|
||||
RedeemableCap: 50,
|
||||
ExpiresAt: time.Now().UTC().Add(time.Hour * 1),
|
||||
Status: marketing.Active,
|
||||
Type: marketing.Referral,
|
||||
Status: rewards.Active,
|
||||
Type: rewards.Referral,
|
||||
},
|
||||
{
|
||||
Name: "test",
|
||||
@ -41,47 +41,48 @@ func TestOffer_Database(t *testing.T) {
|
||||
InviteeCreditDurationDays: 30,
|
||||
RedeemableCap: 50,
|
||||
ExpiresAt: time.Now().UTC().Add(time.Hour * 1),
|
||||
Status: marketing.Default,
|
||||
Type: marketing.FreeCredit,
|
||||
Status: rewards.Default,
|
||||
Type: rewards.FreeCredit,
|
||||
},
|
||||
}
|
||||
|
||||
for i := range validOffers {
|
||||
new, err := planet.Satellites[0].DB.Marketing().Offers().Create(ctx, &validOffers[i])
|
||||
new, err := planet.Satellites[0].DB.Rewards().Create(ctx, &validOffers[i])
|
||||
require.NoError(t, err)
|
||||
|
||||
all, err := planet.Satellites[0].DB.Marketing().Offers().ListAll(ctx)
|
||||
all, err := planet.Satellites[0].DB.Rewards().ListAll(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Contains(t, all, *new)
|
||||
|
||||
c, err := planet.Satellites[0].DB.Marketing().Offers().GetCurrentByType(ctx, new.Type)
|
||||
c, err := planet.Satellites[0].DB.Rewards().GetCurrentByType(ctx, new.Type)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, new, c)
|
||||
|
||||
update := &marketing.UpdateOffer{
|
||||
update := &rewards.UpdateOffer{
|
||||
ID: new.ID,
|
||||
Status: marketing.Done,
|
||||
Status: rewards.Done,
|
||||
ExpiresAt: time.Now(),
|
||||
}
|
||||
|
||||
err = planet.Satellites[0].DB.Marketing().Offers().Redeem(ctx, update.ID)
|
||||
isDefault := update.Status == rewards.Default
|
||||
err = planet.Satellites[0].DB.Rewards().Redeem(ctx, update.ID, isDefault)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = planet.Satellites[0].DB.Marketing().Offers().Finish(ctx, update.ID)
|
||||
err = planet.Satellites[0].DB.Rewards().Finish(ctx, update.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
current, err := planet.Satellites[0].DB.Marketing().Offers().ListAll(ctx)
|
||||
current, err := planet.Satellites[0].DB.Rewards().ListAll(ctx)
|
||||
require.NoError(t, err)
|
||||
if new.Status == marketing.Default {
|
||||
if new.Status == rewards.Default {
|
||||
require.Equal(t, new.NumRedeemed, current[i].NumRedeemed)
|
||||
} else {
|
||||
require.Equal(t, new.NumRedeemed+1, current[i].NumRedeemed)
|
||||
}
|
||||
require.Equal(t, marketing.Done, current[i].Status)
|
||||
require.Equal(t, rewards.Done, current[i].Status)
|
||||
}
|
||||
|
||||
// create with expired offer
|
||||
expiredOffers := []marketing.NewOffer{
|
||||
expiredOffers := []rewards.NewOffer{
|
||||
{
|
||||
Name: "test",
|
||||
Description: "test offer",
|
||||
@ -91,8 +92,8 @@ func TestOffer_Database(t *testing.T) {
|
||||
InviteeCreditDurationDays: 30,
|
||||
RedeemableCap: 50,
|
||||
ExpiresAt: time.Now().UTC().Add(time.Hour * -1),
|
||||
Status: marketing.Active,
|
||||
Type: marketing.FreeCredit,
|
||||
Status: rewards.Active,
|
||||
Type: rewards.FreeCredit,
|
||||
},
|
||||
{
|
||||
Name: "test",
|
||||
@ -103,13 +104,13 @@ func TestOffer_Database(t *testing.T) {
|
||||
InviteeCreditDurationDays: 30,
|
||||
RedeemableCap: 50,
|
||||
ExpiresAt: time.Now().UTC().Add(time.Hour * -1),
|
||||
Status: marketing.Default,
|
||||
Type: marketing.Referral,
|
||||
Status: rewards.Default,
|
||||
Type: rewards.Referral,
|
||||
},
|
||||
}
|
||||
|
||||
for i := range expiredOffers {
|
||||
output, err := planet.Satellites[0].DB.Marketing().Offers().Create(ctx, &expiredOffers[i])
|
||||
output, err := planet.Satellites[0].DB.Rewards().Create(ctx, &expiredOffers[i])
|
||||
require.Error(t, err)
|
||||
require.Nil(t, output)
|
||||
}
|
@ -18,8 +18,8 @@ import (
|
||||
"storj.io/storj/satellite"
|
||||
"storj.io/storj/satellite/attribution"
|
||||
"storj.io/storj/satellite/console"
|
||||
"storj.io/storj/satellite/marketing"
|
||||
"storj.io/storj/satellite/orders"
|
||||
"storj.io/storj/satellite/rewards"
|
||||
dbx "storj.io/storj/satellite/satellitedb/dbx"
|
||||
)
|
||||
|
||||
@ -136,12 +136,9 @@ func (db *DB) Console() console.DB {
|
||||
}
|
||||
}
|
||||
|
||||
// Marketing returns database for storing offers and credits
|
||||
func (db *DB) Marketing() marketing.DB {
|
||||
return &MarketingDB{
|
||||
db: db.db,
|
||||
methods: db.db,
|
||||
}
|
||||
// Rewards returns database for storing offers
|
||||
func (db *DB) Rewards() rewards.DB {
|
||||
return &offersDB{db: db.db}
|
||||
}
|
||||
|
||||
// Orders returns database for storing orders
|
||||
|
@ -25,8 +25,8 @@ import (
|
||||
"storj.io/storj/satellite"
|
||||
"storj.io/storj/satellite/attribution"
|
||||
"storj.io/storj/satellite/console"
|
||||
"storj.io/storj/satellite/marketing"
|
||||
"storj.io/storj/satellite/orders"
|
||||
"storj.io/storj/satellite/rewards"
|
||||
)
|
||||
|
||||
// locked implements a locking wrapper around satellite.DB.
|
||||
@ -681,61 +681,6 @@ func (m *lockedIrreparable) IncrementRepairAttempts(ctx context.Context, segment
|
||||
return m.db.IncrementRepairAttempts(ctx, segmentInfo)
|
||||
}
|
||||
|
||||
// Marketing returns database for marketing admin GUI
|
||||
func (m *locked) Marketing() marketing.DB {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return &lockedMarketing{m.Locker, m.db.Marketing()}
|
||||
}
|
||||
|
||||
// lockedMarketing implements locking wrapper for marketing.DB
|
||||
type lockedMarketing struct {
|
||||
sync.Locker
|
||||
db marketing.DB
|
||||
}
|
||||
|
||||
func (m *lockedMarketing) Offers() marketing.Offers {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return &lockedOffers{m.Locker, m.db.Offers()}
|
||||
}
|
||||
|
||||
// lockedOffers implements locking wrapper for marketing.Offers
|
||||
type lockedOffers struct {
|
||||
sync.Locker
|
||||
db marketing.Offers
|
||||
}
|
||||
|
||||
func (m *lockedOffers) Create(ctx context.Context, offer *marketing.NewOffer) (*marketing.Offer, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Create(ctx, offer)
|
||||
}
|
||||
|
||||
func (m *lockedOffers) Finish(ctx context.Context, offerID int) error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Finish(ctx, offerID)
|
||||
}
|
||||
|
||||
func (m *lockedOffers) GetCurrentByType(ctx context.Context, offerType marketing.OfferType) (*marketing.Offer, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.GetCurrentByType(ctx, offerType)
|
||||
}
|
||||
|
||||
func (m *lockedOffers) ListAll(ctx context.Context) ([]marketing.Offer, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.ListAll(ctx)
|
||||
}
|
||||
|
||||
func (m *lockedOffers) Redeem(ctx context.Context, offerID int) error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Redeem(ctx, offerID)
|
||||
}
|
||||
|
||||
// Orders returns database for orders
|
||||
func (m *locked) Orders() orders.DB {
|
||||
m.Lock()
|
||||
@ -998,6 +943,49 @@ func (m *lockedRepairQueue) SelectN(ctx context.Context, limit int) ([]pb.Injure
|
||||
return m.db.SelectN(ctx, limit)
|
||||
}
|
||||
|
||||
// returns database for marketing admin GUI
|
||||
func (m *locked) Rewards() rewards.DB {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return &lockedRewards{m.Locker, m.db.Rewards()}
|
||||
}
|
||||
|
||||
// lockedRewards implements locking wrapper for rewards.DB
|
||||
type lockedRewards struct {
|
||||
sync.Locker
|
||||
db rewards.DB
|
||||
}
|
||||
|
||||
func (m *lockedRewards) Create(ctx context.Context, offer *rewards.NewOffer) (*rewards.Offer, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Create(ctx, offer)
|
||||
}
|
||||
|
||||
func (m *lockedRewards) Finish(ctx context.Context, offerID int) error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Finish(ctx, offerID)
|
||||
}
|
||||
|
||||
func (m *lockedRewards) GetCurrentByType(ctx context.Context, offerType rewards.OfferType) (*rewards.Offer, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.GetCurrentByType(ctx, offerType)
|
||||
}
|
||||
|
||||
func (m *lockedRewards) ListAll(ctx context.Context) ([]rewards.Offer, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.ListAll(ctx)
|
||||
}
|
||||
|
||||
func (m *lockedRewards) Redeem(ctx context.Context, offerID int, isDefault bool) error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Redeem(ctx, offerID, isDefault)
|
||||
}
|
||||
|
||||
// StoragenodeAccounting returns database for storing information about storagenode use
|
||||
func (m *locked) StoragenodeAccounting() accounting.StoragenodeAccounting {
|
||||
m.Lock()
|
||||
|
@ -1,21 +0,0 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information
|
||||
|
||||
package satellitedb
|
||||
|
||||
import (
|
||||
"storj.io/storj/satellite/marketing"
|
||||
dbx "storj.io/storj/satellite/satellitedb/dbx"
|
||||
)
|
||||
|
||||
// MarketingDB contains access to different satellite databases
|
||||
type MarketingDB struct {
|
||||
db *dbx.DB
|
||||
|
||||
methods dbx.Methods
|
||||
}
|
||||
|
||||
// Offers returns access to offers table
|
||||
func (db *MarketingDB) Offers() marketing.Offers {
|
||||
return &offers{db.db}
|
||||
}
|
@ -10,26 +10,31 @@ import (
|
||||
|
||||
"github.com/zeebo/errs"
|
||||
|
||||
"storj.io/storj/satellite/marketing"
|
||||
"storj.io/storj/satellite/rewards"
|
||||
dbx "storj.io/storj/satellite/satellitedb/dbx"
|
||||
)
|
||||
|
||||
type offers struct {
|
||||
var (
|
||||
// offerErr is the default offer errors class
|
||||
offerErr = errs.Class("offers error")
|
||||
)
|
||||
|
||||
type offersDB struct {
|
||||
db *dbx.DB
|
||||
}
|
||||
|
||||
// ListAll returns all offers from the db
|
||||
func (offers *offers) ListAll(ctx context.Context) ([]marketing.Offer, error) {
|
||||
offersDbx, err := offers.db.All_Offer(ctx)
|
||||
// ListAll returns all offersDB from the db
|
||||
func (db *offersDB) ListAll(ctx context.Context) ([]rewards.Offer, error) {
|
||||
offersDbx, err := db.db.All_Offer(ctx)
|
||||
if err != nil {
|
||||
return nil, marketing.OffersErr.Wrap(err)
|
||||
return nil, offerErr.Wrap(err)
|
||||
}
|
||||
|
||||
return offersFromDBX(offersDbx)
|
||||
}
|
||||
|
||||
// GetCurrent returns an offer that has not expired based on offer type
|
||||
func (offers *offers) GetCurrentByType(ctx context.Context, offerType marketing.OfferType) (*marketing.Offer, error) {
|
||||
func (db *offersDB) GetCurrentByType(ctx context.Context, offerType rewards.OfferType) (*rewards.Offer, error) {
|
||||
var statement string
|
||||
const columns = "id, name, description, award_credit_in_cents, invitee_credit_in_cents, award_credit_duration_days, invitee_credit_duration_days, redeemable_cap, num_redeemed, expires_at, created_at, status, type"
|
||||
statement = `
|
||||
@ -44,40 +49,45 @@ func (offers *offers) GetCurrentByType(ctx context.Context, offerType marketing.
|
||||
SELECT id FROM o
|
||||
) order by created_at desc;`
|
||||
|
||||
rows := offers.db.DB.QueryRowContext(ctx, offers.db.Rebind(statement), marketing.Active, offerType, time.Now().UTC(), offerType, marketing.Default)
|
||||
rows := db.db.DB.QueryRowContext(ctx, db.db.Rebind(statement), rewards.Active, offerType, time.Now().UTC(), offerType, rewards.Default)
|
||||
|
||||
o := marketing.Offer{}
|
||||
o := rewards.Offer{}
|
||||
err := rows.Scan(&o.ID, &o.Name, &o.Description, &o.AwardCreditInCents, &o.InviteeCreditInCents, &o.AwardCreditDurationDays, &o.InviteeCreditDurationDays, &o.RedeemableCap, &o.NumRedeemed, &o.ExpiresAt, &o.CreatedAt, &o.Status, &o.Type)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, marketing.OffersErr.New("no current offer")
|
||||
return nil, offerErr.New("no current offer")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, marketing.OffersErr.Wrap(err)
|
||||
return nil, offerErr.Wrap(err)
|
||||
}
|
||||
|
||||
return &o, nil
|
||||
}
|
||||
|
||||
// Create inserts a new offer into the db
|
||||
func (offers *offers) Create(ctx context.Context, o *marketing.NewOffer) (*marketing.Offer, error) {
|
||||
func (db *offersDB) Create(ctx context.Context, o *rewards.NewOffer) (*rewards.Offer, error) {
|
||||
currentTime := time.Now()
|
||||
if o.ExpiresAt.Before(currentTime) {
|
||||
return nil, marketing.OffersErr.New("expiration time: %v can't be before: %v", o.ExpiresAt, currentTime)
|
||||
return nil, offerErr.New("expiration time: %v can't be before: %v", o.ExpiresAt, currentTime)
|
||||
}
|
||||
|
||||
tx, err := offers.db.Open(ctx)
|
||||
if o.Status == rewards.Default {
|
||||
o.ExpiresAt = time.Now().UTC().AddDate(100, 0, 0)
|
||||
o.RedeemableCap = 1
|
||||
}
|
||||
|
||||
tx, err := db.db.Open(ctx)
|
||||
if err != nil {
|
||||
return nil, marketing.OffersErr.Wrap(err)
|
||||
return nil, offerErr.Wrap(err)
|
||||
}
|
||||
|
||||
// If there's an existing current offer, update its status to Done and set its expires_at to be NOW()
|
||||
statement := offers.db.Rebind(`
|
||||
statement := db.db.Rebind(`
|
||||
UPDATE offers SET status=?, expires_at=?
|
||||
WHERE status=? AND type=? AND expires_at>?;
|
||||
`)
|
||||
_, err = tx.Tx.ExecContext(ctx, statement, marketing.Done, currentTime, o.Status, o.Type, currentTime)
|
||||
_, err = tx.Tx.ExecContext(ctx, statement, rewards.Done, currentTime, o.Status, o.Type, currentTime)
|
||||
if err != nil {
|
||||
return nil, marketing.OffersErr.Wrap(errs.Combine(err, tx.Rollback()))
|
||||
return nil, offerErr.Wrap(errs.Combine(err, tx.Rollback()))
|
||||
}
|
||||
|
||||
offerDbx, err := tx.Create_Offer(ctx,
|
||||
@ -93,51 +103,55 @@ func (offers *offers) Create(ctx context.Context, o *marketing.NewOffer) (*marke
|
||||
dbx.Offer_Type(int(o.Type)),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, marketing.OffersErr.Wrap(errs.Combine(err, tx.Rollback()))
|
||||
return nil, offerErr.Wrap(errs.Combine(err, tx.Rollback()))
|
||||
}
|
||||
|
||||
newOffer, err := convertDBOffer(offerDbx)
|
||||
if err != nil {
|
||||
return nil, marketing.OffersErr.Wrap(errs.Combine(err, tx.Rollback()))
|
||||
return nil, offerErr.Wrap(errs.Combine(err, tx.Rollback()))
|
||||
}
|
||||
|
||||
return newOffer, marketing.OffersErr.Wrap(tx.Commit())
|
||||
return newOffer, offerErr.Wrap(tx.Commit())
|
||||
}
|
||||
|
||||
// Redeem adds 1 to the amount of offers redeemed based on offer id
|
||||
func (offers *offers) Redeem(ctx context.Context, oID int) error {
|
||||
statement := offers.db.Rebind(
|
||||
func (db *offersDB) Redeem(ctx context.Context, oID int, isDefault bool) error {
|
||||
if isDefault {
|
||||
return nil
|
||||
}
|
||||
|
||||
statement := db.db.Rebind(
|
||||
`UPDATE offers SET num_redeemed = num_redeemed + 1 where id = ? AND status = ? AND num_redeemed < redeemable_cap`,
|
||||
)
|
||||
|
||||
_, err := offers.db.DB.ExecContext(ctx, statement, oID, marketing.Active)
|
||||
_, err := db.db.DB.ExecContext(ctx, statement, oID, rewards.Active)
|
||||
if err != nil {
|
||||
return marketing.OffersErr.Wrap(err)
|
||||
return offerErr.Wrap(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Finish changes the offer status to be Done and its expiration date to be now based on offer id
|
||||
func (offers *offers) Finish(ctx context.Context, oID int) error {
|
||||
func (db *offersDB) Finish(ctx context.Context, oID int) error {
|
||||
updateFields := dbx.Offer_Update_Fields{
|
||||
Status: dbx.Offer_Status(int(marketing.Done)),
|
||||
Status: dbx.Offer_Status(int(rewards.Done)),
|
||||
ExpiresAt: dbx.Offer_ExpiresAt(time.Now().UTC()),
|
||||
}
|
||||
|
||||
offerID := dbx.Offer_Id(oID)
|
||||
|
||||
_, err := offers.db.Update_Offer_By_Id(ctx, offerID, updateFields)
|
||||
_, err := db.db.Update_Offer_By_Id(ctx, offerID, updateFields)
|
||||
if err != nil {
|
||||
return marketing.OffersErr.Wrap(err)
|
||||
return offerErr.Wrap(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func offersFromDBX(offersDbx []*dbx.Offer) ([]marketing.Offer, error) {
|
||||
var offers []marketing.Offer
|
||||
var errList errs.Group
|
||||
func offersFromDBX(offersDbx []*dbx.Offer) ([]rewards.Offer, error) {
|
||||
var offers []rewards.Offer
|
||||
errList := new(errs.Group)
|
||||
|
||||
for _, offerDbx := range offersDbx {
|
||||
|
||||
@ -152,12 +166,12 @@ func offersFromDBX(offersDbx []*dbx.Offer) ([]marketing.Offer, error) {
|
||||
return offers, errList.Err()
|
||||
}
|
||||
|
||||
func convertDBOffer(offerDbx *dbx.Offer) (*marketing.Offer, error) {
|
||||
func convertDBOffer(offerDbx *dbx.Offer) (*rewards.Offer, error) {
|
||||
if offerDbx == nil {
|
||||
return nil, marketing.OffersErr.New("offerDbx parameter is nil")
|
||||
return nil, offerErr.New("offerDbx parameter is nil")
|
||||
}
|
||||
|
||||
o := marketing.Offer{
|
||||
o := rewards.Offer{
|
||||
ID: offerDbx.Id,
|
||||
Name: offerDbx.Name,
|
||||
Description: offerDbx.Description,
|
||||
@ -169,8 +183,8 @@ func convertDBOffer(offerDbx *dbx.Offer) (*marketing.Offer, error) {
|
||||
AwardCreditDurationDays: offerDbx.AwardCreditDurationDays,
|
||||
InviteeCreditDurationDays: offerDbx.InviteeCreditDurationDays,
|
||||
CreatedAt: offerDbx.CreatedAt,
|
||||
Status: marketing.OfferStatus(offerDbx.Status),
|
||||
Type: marketing.OfferType(offerDbx.Type),
|
||||
Status: rewards.OfferStatus(offerDbx.Status),
|
||||
Type: rewards.OfferType(offerDbx.Type),
|
||||
}
|
||||
|
||||
return &o, nil
|
||||
|
@ -10,15 +10,12 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/skyrings/skyring-common/tools/uuid"
|
||||
|
||||
"storj.io/storj/satellite/marketing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"storj.io/storj/satellite/console"
|
||||
|
||||
"storj.io/storj/internal/testcontext"
|
||||
"storj.io/storj/satellite"
|
||||
"storj.io/storj/satellite/console"
|
||||
"storj.io/storj/satellite/rewards"
|
||||
"storj.io/storj/satellite/satellitedb/satellitedbtest"
|
||||
)
|
||||
|
||||
@ -166,9 +163,9 @@ func TestUsercredits(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func setupData(ctx context.Context, t *testing.T, db satellite.DB) (user *console.User, referrer *console.User, offer *marketing.Offer) {
|
||||
func setupData(ctx context.Context, t *testing.T, db satellite.DB) (user *console.User, referrer *console.User, offer *rewards.Offer) {
|
||||
consoleDB := db.Console()
|
||||
marketingDB := db.Marketing()
|
||||
offersDB := db.Rewards()
|
||||
// create user
|
||||
var userPassHash [8]byte
|
||||
_, err := rand.Read(userPassHash[:])
|
||||
@ -197,7 +194,7 @@ func setupData(ctx context.Context, t *testing.T, db satellite.DB) (user *consol
|
||||
require.NoError(t, err)
|
||||
|
||||
// create offer
|
||||
offer, err = marketingDB.Offers().Create(ctx, &marketing.NewOffer{
|
||||
offer, err = offersDB.Create(ctx, &rewards.NewOffer{
|
||||
Name: "test",
|
||||
Description: "test offer 1",
|
||||
AwardCreditInCents: 100,
|
||||
@ -206,8 +203,8 @@ func setupData(ctx context.Context, t *testing.T, db satellite.DB) (user *consol
|
||||
InviteeCreditDurationDays: 30,
|
||||
RedeemableCap: 50,
|
||||
ExpiresAt: time.Now().UTC().Add(time.Hour * 1),
|
||||
Status: marketing.Active,
|
||||
Type: marketing.Referral,
|
||||
Status: rewards.Active,
|
||||
Type: rewards.Referral,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -52,7 +52,7 @@ func main() {
|
||||
Mode: packages.LoadAllSyntax,
|
||||
}
|
||||
code.Wrapped = map[string]bool{}
|
||||
code.AdditionalNesting = map[string]int{"Console": 1, "Marketing": 1}
|
||||
code.AdditionalNesting = map[string]int{"Console": 1}
|
||||
|
||||
// e.g. storj.io/storj/satellite.DB
|
||||
p := strings.LastIndexByte(typeFullyQualifedName, '.')
|
||||
|
Loading…
Reference in New Issue
Block a user