Skip to content

Commit

Permalink
Transfer service (#4594)
Browse files Browse the repository at this point in the history
* add transfer/invoice service
  • Loading branch information
bxy4543 committed Mar 15, 2024
1 parent 424fcc7 commit 5e0ea54
Show file tree
Hide file tree
Showing 18 changed files with 910 additions and 180 deletions.
2 changes: 1 addition & 1 deletion controllers/account/controllers/accountv2_test.go
Expand Up @@ -299,7 +299,7 @@ func TestAccountV2_GetUser(t *testing.T) {
t.Errorf("failed close connection: %v", err)
}
}()
user, err := account.GetUser(&types.UserQueryOpts{Owner: "eoxwhh80"})
user, err := account.GetUserCr(&types.UserQueryOpts{Owner: "eoxwhh80"})
if err != nil {
t.Errorf("failed to get user: %v", err)
}
Expand Down
6 changes: 0 additions & 6 deletions controllers/account/controllers/debt_controller.go
Expand Up @@ -75,7 +75,6 @@ const (
type DebtReconciler struct {
client.Client
AccountV2 database.AccountV2
DBClient database.Auth
Scheme *runtime.Scheme
DebtDetectionCycle time.Duration
LocalRegionID string
Expand Down Expand Up @@ -377,11 +376,6 @@ func (r *DebtReconciler) sendSMSNotice(user string, oweAmount int64, noticeType
if r.SmsConfig == nil {
return nil
}
// TODO send sms
//usr, err := r.DBClient.GetUser(user)
//if err != nil {
// return fmt.Errorf("failed to get user: %w", err)
//}
outh, err := r.AccountV2.GetUserOauthProvider(&pkgtypes.UserQueryOpts{Owner: user})
if err != nil {
return fmt.Errorf("failed to get user oauth provider: %w", err)
Expand Down
1 change: 0 additions & 1 deletion controllers/account/main.go
Expand Up @@ -199,7 +199,6 @@ func main() {
if err = (&controllers.DebtReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
DBClient: dbClient,
AccountV2: v2Account,
}).SetupWithManager(mgr, rateOpts); err != nil {
setupManagerError(err, "Debt")
Expand Down
129 changes: 113 additions & 16 deletions controllers/pkg/database/cockroach/accountv2.go
Expand Up @@ -51,7 +51,7 @@ const (
EnvBaseBalance = "BASE_BALANCE"
)

func (g *Cockroach) GetUser(ops *types.UserQueryOpts) (*types.RegionUserCr, error) {
func (g *Cockroach) GetUserCr(ops *types.UserQueryOpts) (*types.RegionUserCr, error) {
if err := checkOps(ops); err != nil {
return nil, err
}
Expand All @@ -61,11 +61,29 @@ func (g *Cockroach) GetUser(ops *types.UserQueryOpts) (*types.RegionUserCr, erro
if ops.UID != uuid.Nil {
query.UserUID = ops.UID
}
var user types.RegionUserCr
if err := g.Localdb.Where(query).First(&user).Error; err != nil {
var userCr types.RegionUserCr
if err := g.Localdb.Where(query).First(&userCr).Error; err != nil {
return nil, err
}
return &user, nil
return &userCr, nil
}

func (g *Cockroach) GetUserUID(ops *types.UserQueryOpts) (uuid.UUID, error) {
if ops.UID != uuid.Nil {
return ops.UID, nil
}
if ops.ID != "" {
var user types.User
if err := g.DB.Where(&types.User{ID: ops.ID}).First(&user).Error; err != nil {
return uuid.Nil, fmt.Errorf("failed to get user: %v", err)
}
return user.UID, nil
}
userCr, err := g.GetUserCr(ops)
if err != nil {
return uuid.Nil, err
}
return userCr.UserUID, nil
}

func checkOps(ops *types.UserQueryOpts) error {
Expand All @@ -79,9 +97,45 @@ func (g *Cockroach) GetAccount(ops *types.UserQueryOpts) (*types.Account, error)
return g.getAccount(ops)
}

func (g *Cockroach) GetTransfer(ops *types.UserQueryOpts) ([]types.Transfer, error) {
userUID, err := g.GetUserUID(ops)
if err != nil {
return nil, fmt.Errorf("failed to get user uid: %v", err)
}
var transfers []types.Transfer
if err := g.DB.Where(types.Transfer{FromUserUID: userUID}).Or(types.Transfer{ToUserUID: userUID}).Find(&transfers).Error; err != nil {
return nil, fmt.Errorf("failed to get transfer: %v", err)
}
return transfers, nil
}

func (g *Cockroach) GetTransferTo(ops *types.UserQueryOpts) ([]types.Transfer, error) {
userUID, err := g.GetUserUID(ops)
if err != nil {
return nil, fmt.Errorf("failed to get user uid: %v", err)
}
var transfers []types.Transfer
if err := g.DB.Where(types.Transfer{ToUserUID: userUID}).Find(&transfers).Error; err != nil {
return nil, fmt.Errorf("failed to get transfer: %v", err)
}
return transfers, nil
}

func (g *Cockroach) GetTransferFrom(ops *types.UserQueryOpts) ([]types.Transfer, error) {
userUID, err := g.GetUserUID(ops)
if err != nil {
return nil, fmt.Errorf("failed to get user uid: %v", err)
}
var transfers []types.Transfer
if err := g.DB.Where(types.Transfer{FromUserUID: userUID}).Find(&transfers).Error; err != nil {
return nil, fmt.Errorf("failed to get transfer: %v", err)
}
return transfers, nil
}

func (g *Cockroach) getAccount(ops *types.UserQueryOpts) (*types.Account, error) {
if ops.UID == uuid.Nil {
user, err := g.GetUser(ops)
user, err := g.GetUserCr(ops)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -109,7 +163,7 @@ func (g *Cockroach) getAccount(ops *types.UserQueryOpts) (*types.Account, error)

func (g *Cockroach) GetUserOauthProvider(ops *types.UserQueryOpts) (*types.OauthProvider, error) {
if ops.UID == uuid.Nil {
user, err := g.GetUser(ops)
user, err := g.GetUserCr(ops)
if err != nil {
return nil, fmt.Errorf("failed to get user: %v", err)
}
Expand All @@ -127,7 +181,7 @@ func (g *Cockroach) GetUserOauthProvider(ops *types.UserQueryOpts) (*types.Oauth

func (g *Cockroach) updateBalance(tx *gorm.DB, ops *types.UserQueryOpts, amount int64, isDeduction, add bool) error {
if ops.UID == uuid.Nil {
user, err := g.GetUser(ops)
user, err := g.GetUserCr(ops)
if err != nil {
return fmt.Errorf("failed to get user: %v", err)
}
Expand Down Expand Up @@ -208,7 +262,7 @@ func (g *Cockroach) AddDeductionBalance(ops *types.UserQueryOpts, amount int64)

func (g *Cockroach) CreateAccount(ops *types.UserQueryOpts, account *types.Account) (*types.Account, error) {
if ops.UID == uuid.Nil {
user, err := g.GetUser(ops)
user, err := g.GetUserCr(ops)
if err != nil {
return nil, fmt.Errorf("failed to get user: %v", err)
}
Expand Down Expand Up @@ -399,7 +453,7 @@ func (g *Cockroach) payment(payment *types.Payment, updateBalance bool) error {
if payment.RegionUserOwner == "" {
return fmt.Errorf("empty payment owner and user")
}
user, err := g.GetUser(&types.UserQueryOpts{Owner: payment.RegionUserOwner})
user, err := g.GetUserCr(&types.UserQueryOpts{Owner: payment.RegionUserOwner})
if err != nil {
return fmt.Errorf("failed to get user: %v", err)
}
Expand All @@ -422,10 +476,46 @@ func (g *Cockroach) payment(payment *types.Payment, updateBalance bool) error {
})
}

func (g *Cockroach) GetPayment(ops *types.UserQueryOpts, startTime, endTime time.Time) ([]types.Payment, error) {
userUID, err := g.GetUserUID(ops)
if err != nil {
return nil, fmt.Errorf("failed to get user uid: %v", err)
}
var payment []types.Payment
if startTime != endTime {
if err := g.DB.Where(types.Payment{PaymentRaw: types.PaymentRaw{UserUID: userUID}}).Where("created_at >= ? AND created_at <= ?", startTime, endTime).Find(&payment).Error; err != nil {
return nil, fmt.Errorf("failed to get payment: %w", err)
}
} else {
if err := g.DB.Where(types.Payment{PaymentRaw: types.PaymentRaw{UserUID: userUID}}).Find(&payment).Error; err != nil {
return nil, fmt.Errorf("failed to get payment: %w", err)
}
}
return payment, nil
}

func (g *Cockroach) SetPaymentInvoice(ops *types.UserQueryOpts, paymentIDList []string) error {
userUID, err := g.GetUserUID(ops)
if err != nil {
return fmt.Errorf("failed to get user uid: %v", err)
}
var payment []types.Payment
if err := g.DB.Where(types.Payment{PaymentRaw: types.PaymentRaw{UserUID: userUID}}).Where("id IN ?", paymentIDList).Find(&payment).Error; err != nil {
return fmt.Errorf("failed to get payment: %w", err)
}
for i := range payment {
payment[i].InvoicedAt = true
if err := g.DB.Save(&payment[i]).Error; err != nil {
return fmt.Errorf("failed to save payment: %v", err)
}
}
return nil
}

// NewAccount create a new account
func (g *Cockroach) NewAccount(ops *types.UserQueryOpts) (*types.Account, error) {
if ops.UID == uuid.Nil {
user, err := g.GetUser(ops)
user, err := g.GetUserCr(ops)
if err != nil {
return nil, err
}
Expand All @@ -450,7 +540,7 @@ func (g *Cockroach) NewAccount(ops *types.UserQueryOpts) (*types.Account, error)
func (g *Cockroach) GetUserAccountRechargeDiscount(ops *types.UserQueryOpts) (*types.RechargeDiscount, error) {
userID := ops.UID
if userID == uuid.Nil {
user, err := g.GetUser(ops)
user, err := g.GetUserCr(ops)
if err != nil {
return nil, fmt.Errorf("failed to get user %v: %v", ops, err)
}
Expand Down Expand Up @@ -510,18 +600,18 @@ var (

func (g *Cockroach) TransferAccount(from, to *types.UserQueryOpts, amount int64) error {
if from.UID == uuid.Nil {
fromUser, err := g.GetUser(from)
fromUserUID, err := g.GetUserUID(from)
if err != nil {
return fmt.Errorf("failed to get user: %v", err)
}
from.UID = fromUser.UserUID
from.UID = fromUserUID
}
if to.UID == uuid.Nil {
toUser, err := g.GetUser(to)
toUserUID, err := g.GetUserUID(to)
if err != nil {
return fmt.Errorf("failed to get user: %v", err)
}
to.UID = toUser.UserUID
to.UID = toUserUID
}
err := g.DB.Transaction(func(tx *gorm.DB) error {
sender, err := g.GetAccount(&types.UserQueryOpts{UID: from.UID})
Expand All @@ -538,6 +628,13 @@ func (g *Cockroach) TransferAccount(from, to *types.UserQueryOpts, amount int64)
if err = g.updateBalance(tx, &types.UserQueryOpts{UID: to.UID}, amount, false, true); err != nil {
return fmt.Errorf("failed to update receiver balance: %w", err)
}
if err = g.DB.Create(&types.Transfer{
FromUserUID: from.UID,
ToUserUID: to.UID,
Amount: amount,
}).Error; err != nil {
return fmt.Errorf("failed to create transfer record: %w", err)
}
return nil
})

Expand Down Expand Up @@ -575,7 +672,7 @@ func NewCockRoach(globalURI, localURI string) (*Cockroach, error) {
if err != nil {
return nil, fmt.Errorf("failed to encrypt zero value")
}
if err := CreateTableIfNotExist(db, types.Account{}, types.ErrorAccountCreate{}, types.ErrorPaymentCreate{}, types.Payment{}); err != nil {
if err := CreateTableIfNotExist(db, types.Account{}, types.ErrorAccountCreate{}, types.ErrorPaymentCreate{}, types.Payment{}, types.Transfer{}); err != nil {
return nil, err
}
cockroach := &Cockroach{DB: db, Localdb: localdb, ZeroAccount: &types.Account{EncryptBalance: *newEncryptBalance, EncryptDeductionBalance: *newEncryptDeductionBalance, Balance: baseBalance, DeductionBalance: 0}}
Expand Down
7 changes: 1 addition & 6 deletions controllers/pkg/database/interface.go
Expand Up @@ -32,14 +32,9 @@ import (

type Interface interface {
Account
Auth
Traffic
}

type Auth interface {
GetUser(k8sUser string) (*types.User, error)
}

type Account interface {
//InitDB() error
GetBillingLastUpdateTime(owner string, _type common.Type) (bool, time.Time, error)
Expand Down Expand Up @@ -85,7 +80,7 @@ type Traffic interface {

type AccountV2 interface {
Close() error
GetUser(user *types.UserQueryOpts) (*types.RegionUserCr, error)
GetUserCr(user *types.UserQueryOpts) (*types.RegionUserCr, error)
GetAccount(user *types.UserQueryOpts) (*types.Account, error)
GetUserOauthProvider(ops *types.UserQueryOpts) (*types.OauthProvider, error)
AddBalance(user *types.UserQueryOpts, balance int64) error
Expand Down
31 changes: 0 additions & 31 deletions controllers/pkg/database/mongo/user.go
Expand Up @@ -13,34 +13,3 @@
// limitations under the License.

package mongo

import (
"context"
"fmt"

"go.mongodb.org/mongo-driver/bson"

"go.mongodb.org/mongo-driver/mongo"

"github.com/labring/sealos/controllers/pkg/types"
)

func (m *mongoDB) GetUser(name string) (*types.User, error) {
collection := m.getUserCollection()
if collection == nil {
return nil, fmt.Errorf("failed to get user collection")
}
var user types.User
err := collection.FindOne(context.Background(), bson.M{"k8s_users.name": name}).Decode(&user)
if err != nil {
if err == mongo.ErrNoDocuments {
return nil, nil
}
return nil, fmt.Errorf("failed to find user: error = %v", err)
}
return &user, nil
}

func (m *mongoDB) getUserCollection() *mongo.Collection {
return m.Client.Database(m.AuthDB).Collection(m.UserConn)
}
24 changes: 0 additions & 24 deletions controllers/pkg/database/mongo/user_test.go
Expand Up @@ -13,27 +13,3 @@
// limitations under the License.

package mongo

import (
"context"
"os"
"testing"
)

func Test_mongoDB_GetUser(t *testing.T) {
dbCTX := context.Background()
m, err := NewMongoInterface(dbCTX, os.Getenv("MONGODB_URI"))
if err != nil {
t.Errorf("failed to connect mongo: error = %v", err)
}
defer func() {
if err = m.Disconnect(dbCTX); err != nil {
t.Errorf("failed to disconnect mongo: error = %v", err)
}
}()
users, err := m.GetUser("admin")
if err != nil {
t.Errorf("failed to get user: error = %v", err)
}
t.Logf("users: %v", users)
}
14 changes: 0 additions & 14 deletions controllers/pkg/types/User.go
Expand Up @@ -13,17 +13,3 @@
// limitations under the License.

package types

type User struct {
//UID string `bson:"uid" json:"uid"`
//Name string `bson:"name" json:"name"`
//Email string `bson:"email" json:"email"`
Phone string `bson:"phone" json:"phone"`
//Wechat string `bson:"wechat" json:"wechat"`
//CreatedTime string `bson:"created_time" json:"created_time"`
K8sUsers []K8sUser `bson:"k8s_users" json:"k8s_users"`
}

type K8sUser struct {
Name string `bson:"name" json:"name"`
}
1 change: 1 addition & 0 deletions controllers/pkg/types/dbquery.go
Expand Up @@ -18,6 +18,7 @@ import "github.com/google/uuid"

type UserQueryOpts struct {
UID uuid.UUID
ID string
Owner string
IgnoreEmpty bool
}

0 comments on commit 5e0ea54

Please sign in to comment.