1.4.5.2
This commit is contained in:
257
EdgeAPI/internal/rpc/services/accounts/service_order_method.go
Normal file
257
EdgeAPI/internal/rpc/services/accounts/service_order_method.go
Normal file
@@ -0,0 +1,257 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/accounts"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
)
|
||||
|
||||
// OrderMethodService 订单支付方式相关服务
|
||||
type OrderMethodService struct {
|
||||
services.BaseService
|
||||
}
|
||||
|
||||
// CreateOrderMethod 创建支付方式
|
||||
func (this *OrderMethodService) CreateOrderMethod(ctx context.Context, req *pb.CreateOrderMethodRequest) (*pb.CreateOrderMethodResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
// 检查代号是否相同
|
||||
exists, err := accounts.SharedOrderMethodDAO.ExistOrderMethodWithCode(tx, req.Code, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if exists {
|
||||
return nil, errors.New("pay method code already exists")
|
||||
}
|
||||
|
||||
var params any
|
||||
if len(req.ParentCode) > 0 {
|
||||
params, err = userconfigs.DecodePayMethodParams(req.ParentCode, req.ParamsJSON)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid params: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
methodId, err := accounts.SharedOrderMethodDAO.CreateMethod(tx, req.Name, req.Code, req.Url, req.Description, req.ParentCode, params, req.ClientType, req.QrcodeTitle)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.CreateOrderMethodResponse{
|
||||
OrderMethodId: methodId,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateOrderMethod 修改支付方式
|
||||
func (this *OrderMethodService) UpdateOrderMethod(ctx context.Context, req *pb.UpdateOrderMethodRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
// 检查代号是否相同
|
||||
exists, err := accounts.SharedOrderMethodDAO.ExistOrderMethodWithCode(tx, req.Code, req.OrderMethodId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if exists {
|
||||
return nil, errors.New("pay method code already exists")
|
||||
}
|
||||
|
||||
method, err := accounts.SharedOrderMethodDAO.FindEnabledBasicOrderMethod(tx, req.OrderMethodId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if method == nil {
|
||||
return nil, errors.New("could not find method")
|
||||
}
|
||||
|
||||
var params any
|
||||
if len(method.ParentCode) > 0 {
|
||||
params, err = userconfigs.DecodePayMethodParams(method.ParentCode, req.ParamsJSON)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid params: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
err = accounts.SharedOrderMethodDAO.UpdateMethod(tx, req.OrderMethodId, req.Name, req.Code, req.Url, req.Description, params, req.ClientType, req.QrcodeTitle, req.IsOn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// DeleteOrderMethod 删除支付方式
|
||||
func (this *OrderMethodService) DeleteOrderMethod(ctx context.Context, req *pb.DeleteOrderMethodRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
err = accounts.SharedOrderMethodDAO.DisableOrderMethod(tx, req.OrderMethodId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FindEnabledOrderMethod 查找单个支付方式
|
||||
func (this *OrderMethodService) FindEnabledOrderMethod(ctx context.Context, req *pb.FindEnabledOrderMethodRequest) (*pb.FindEnabledOrderMethodResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
method, err := accounts.SharedOrderMethodDAO.FindEnabledOrderMethod(tx, req.OrderMethodId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if method == nil {
|
||||
return &pb.FindEnabledOrderMethodResponse{
|
||||
OrderMethod: nil,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &pb.FindEnabledOrderMethodResponse{
|
||||
OrderMethod: &pb.OrderMethod{
|
||||
Id: int64(method.Id),
|
||||
Name: method.Name,
|
||||
Code: method.Code,
|
||||
Description: method.Description,
|
||||
Url: method.Url,
|
||||
Secret: method.Secret,
|
||||
IsOn: method.IsOn,
|
||||
ParentCode: method.ParentCode,
|
||||
Params: method.Params, // 注意参数不能通过接口泄露给平台用户
|
||||
ClientType: method.ClientType,
|
||||
QrcodeTitle: method.QrcodeTitle,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// FindEnabledOrderMethodWithCode 根据代号查找支付方式
|
||||
func (this *OrderMethodService) FindEnabledOrderMethodWithCode(ctx context.Context, req *pb.FindEnabledOrderMethodWithCodeRequest) (*pb.FindEnabledOrderMethodWithCodeResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
method, err := accounts.SharedOrderMethodDAO.FindEnabledOrderMethodWithCode(tx, req.Code)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if method == nil {
|
||||
return &pb.FindEnabledOrderMethodWithCodeResponse{
|
||||
OrderMethod: nil,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 保护数据
|
||||
if userId > 0 {
|
||||
method.Secret = ""
|
||||
}
|
||||
|
||||
return &pb.FindEnabledOrderMethodWithCodeResponse{
|
||||
OrderMethod: &pb.OrderMethod{
|
||||
Id: int64(method.Id),
|
||||
Name: method.Name,
|
||||
Code: method.Code,
|
||||
ParentCode: method.ParentCode,
|
||||
Description: method.Description,
|
||||
Url: method.Url,
|
||||
Secret: method.Secret,
|
||||
IsOn: method.IsOn,
|
||||
ClientType: method.ClientType,
|
||||
QrcodeTitle: method.QrcodeTitle,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// FindAllEnabledOrderMethods 查找所有支付方式
|
||||
func (this *OrderMethodService) FindAllEnabledOrderMethods(ctx context.Context, req *pb.FindAllEnabledOrderMethodsRequest) (*pb.FindAllEnabledOrderMethodsResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
methods, err := accounts.SharedOrderMethodDAO.FindAllEnabledMethodOrders(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbMethods = []*pb.OrderMethod{}
|
||||
for _, method := range methods {
|
||||
// 防止secret泄露
|
||||
if userId > 0 {
|
||||
method.Secret = ""
|
||||
}
|
||||
|
||||
pbMethods = append(pbMethods, &pb.OrderMethod{
|
||||
Id: int64(method.Id),
|
||||
Name: method.Name,
|
||||
Code: method.Code,
|
||||
Description: method.Description,
|
||||
Url: method.Url,
|
||||
Secret: method.Secret,
|
||||
IsOn: method.IsOn,
|
||||
ParentCode: method.ParentCode, // 不要返回params,以防止泄露
|
||||
ClientType: method.ClientType,
|
||||
})
|
||||
}
|
||||
return &pb.FindAllEnabledOrderMethodsResponse{
|
||||
OrderMethods: pbMethods,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// FindAllAvailableOrderMethods 查找所有已启用的支付方式
|
||||
func (this *OrderMethodService) FindAllAvailableOrderMethods(ctx context.Context, req *pb.FindAllAvailableOrderMethodsRequest) (*pb.FindAllAvailableOrderMethodsResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
methods, err := accounts.SharedOrderMethodDAO.FindAllEnabledAndOnMethodOrders(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbMethods = []*pb.OrderMethod{}
|
||||
for _, method := range methods {
|
||||
// 防止secret泄露
|
||||
if userId > 0 {
|
||||
method.Secret = ""
|
||||
}
|
||||
|
||||
pbMethods = append(pbMethods, &pb.OrderMethod{
|
||||
Id: int64(method.Id),
|
||||
Name: method.Name,
|
||||
Code: method.Code,
|
||||
Description: method.Description,
|
||||
Url: method.Url,
|
||||
Secret: method.Secret,
|
||||
IsOn: method.IsOn,
|
||||
ParentCode: method.ParentCode, // 不返回params,防止泄露
|
||||
ClientType: method.ClientType,
|
||||
})
|
||||
}
|
||||
return &pb.FindAllAvailableOrderMethodsResponse{
|
||||
OrderMethods: pbMethods,
|
||||
}, nil
|
||||
}
|
||||
195
EdgeAPI/internal/rpc/services/accounts/service_user_account.go
Normal file
195
EdgeAPI/internal/rpc/services/accounts/service_user_account.go
Normal file
@@ -0,0 +1,195 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/accounts"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
)
|
||||
|
||||
// UserAccountService 用户账户相关服务
|
||||
type UserAccountService struct {
|
||||
services.BaseService
|
||||
}
|
||||
|
||||
// CountUserAccounts 计算账户数量
|
||||
func (this *UserAccountService) CountUserAccounts(ctx context.Context, req *pb.CountUserAccountsRequest) (*pb.RPCCountResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
count, err := accounts.SharedUserAccountDAO.CountAllAccounts(tx, req.Keyword)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
|
||||
// ListUserAccounts 列出单页账户
|
||||
func (this *UserAccountService) ListUserAccounts(ctx context.Context, req *pb.ListUserAccountsRequest) (*pb.ListUserAccountsResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
userAccounts, err := accounts.SharedUserAccountDAO.ListAccounts(tx, req.Keyword, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbAccounts = []*pb.UserAccount{}
|
||||
for _, account := range userAccounts {
|
||||
// 用户
|
||||
user, err := models.SharedUserDAO.FindEnabledUser(tx, int64(account.UserId), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbUser = &pb.User{}
|
||||
if user != nil {
|
||||
pbUser = &pb.User{
|
||||
Id: int64(user.Id),
|
||||
Username: user.Username,
|
||||
Fullname: user.Fullname,
|
||||
}
|
||||
}
|
||||
|
||||
pbAccounts = append(pbAccounts, &pb.UserAccount{
|
||||
Id: int64(account.Id),
|
||||
UserId: int64(account.UserId),
|
||||
Total: account.Total,
|
||||
TotalFrozen: account.TotalFrozen,
|
||||
User: pbUser,
|
||||
})
|
||||
}
|
||||
return &pb.ListUserAccountsResponse{UserAccounts: pbAccounts}, nil
|
||||
}
|
||||
|
||||
// FindEnabledUserAccountWithUserId 根据用户ID查找单个账户
|
||||
func (this *UserAccountService) FindEnabledUserAccountWithUserId(ctx context.Context, req *pb.FindEnabledUserAccountWithUserIdRequest) (*pb.FindEnabledUserAccountWithUserIdResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if userId > 0 {
|
||||
req.UserId = userId
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
account, err := accounts.SharedUserAccountDAO.FindUserAccountWithUserId(tx, req.UserId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if account == nil {
|
||||
return &pb.FindEnabledUserAccountWithUserIdResponse{UserAccount: nil}, nil
|
||||
}
|
||||
|
||||
// 用户
|
||||
user, err := models.SharedUserDAO.FindEnabledUser(tx, int64(account.UserId), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbUser = &pb.User{}
|
||||
if user != nil {
|
||||
pbUser = &pb.User{
|
||||
Id: int64(user.Id),
|
||||
Username: user.Username,
|
||||
Fullname: user.Fullname,
|
||||
}
|
||||
}
|
||||
|
||||
return &pb.FindEnabledUserAccountWithUserIdResponse{
|
||||
UserAccount: &pb.UserAccount{
|
||||
Id: int64(account.Id),
|
||||
UserId: int64(account.UserId),
|
||||
Total: account.Total,
|
||||
TotalFrozen: account.TotalFrozen,
|
||||
User: pbUser,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// FindEnabledUserAccount 查找单个账户
|
||||
func (this *UserAccountService) FindEnabledUserAccount(ctx context.Context, req *pb.FindEnabledUserAccountRequest) (*pb.FindEnabledUserAccountResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
|
||||
if userId > 0 {
|
||||
err = accounts.SharedUserAccountDAO.CheckUserAccount(tx, userId, req.UserAccountId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
account, err := accounts.SharedUserAccountDAO.FindUserAccountWithAccountId(tx, req.UserAccountId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if account == nil {
|
||||
return &pb.FindEnabledUserAccountResponse{UserAccount: nil}, nil
|
||||
}
|
||||
|
||||
// 用户
|
||||
user, err := models.SharedUserDAO.FindEnabledUser(tx, int64(account.UserId), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbUser = &pb.User{}
|
||||
if user != nil {
|
||||
pbUser = &pb.User{
|
||||
Id: int64(user.Id),
|
||||
Username: user.Username,
|
||||
Fullname: user.Fullname,
|
||||
}
|
||||
}
|
||||
|
||||
return &pb.FindEnabledUserAccountResponse{
|
||||
UserAccount: &pb.UserAccount{
|
||||
Id: int64(account.Id),
|
||||
UserId: int64(account.UserId),
|
||||
Total: account.Total,
|
||||
TotalFrozen: account.TotalFrozen,
|
||||
User: pbUser,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UpdateUserAccount 修改用户账户
|
||||
func (this *UserAccountService) UpdateUserAccount(ctx context.Context, req *pb.UpdateUserAccountRequest) (*pb.RPCSuccess, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var params = maps.Map{}
|
||||
if len(req.ParamsJSON) > 0 {
|
||||
err = json.Unmarshal(req.ParamsJSON, ¶ms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
err = this.RunTx(func(tx *dbs.Tx) error {
|
||||
err := accounts.SharedUserAccountDAO.UpdateUserAccount(tx, req.UserAccountId, req.Delta, req.EventType, req.Description, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.Success()
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/accounts"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// UserAccountDailyStatService 用户账户统计服务
|
||||
type UserAccountDailyStatService struct {
|
||||
services.BaseService
|
||||
}
|
||||
|
||||
// ListUserAccountDailyStats 列出按天统计
|
||||
func (this *UserAccountDailyStatService) ListUserAccountDailyStats(ctx context.Context, req *pb.ListUserAccountDailyStatsRequest) (*pb.ListUserAccountDailyStatsResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var dayFrom = req.DayFrom
|
||||
var dayTo = req.DayTo
|
||||
|
||||
dayFrom = strings.ReplaceAll(dayFrom, "-", "")
|
||||
dayTo = strings.ReplaceAll(dayTo, "-", "")
|
||||
|
||||
days, err := utils.RangeDays(dayFrom, dayTo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(days) == 0 {
|
||||
return &pb.ListUserAccountDailyStatsResponse{Stats: nil}, nil
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
stats, err := accounts.SharedUserAccountDailyStatDAO.FindDailyStats(tx, dayFrom, dayTo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var statMap = map[string]*accounts.UserAccountDailyStat{} // day => Stat
|
||||
for _, stat := range stats {
|
||||
statMap[stat.Day] = stat
|
||||
}
|
||||
|
||||
var pbStats = []*pb.ListUserAccountDailyStatsResponse_Stat{}
|
||||
for _, day := range days {
|
||||
stat, ok := statMap[day]
|
||||
if ok {
|
||||
pbStats = append(pbStats, &pb.ListUserAccountDailyStatsResponse_Stat{
|
||||
Day: day,
|
||||
Income: float32(stat.Income),
|
||||
Expense: float32(stat.Expense),
|
||||
})
|
||||
} else {
|
||||
pbStats = append(pbStats, &pb.ListUserAccountDailyStatsResponse_Stat{
|
||||
Day: day,
|
||||
Income: 0,
|
||||
Expense: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 反向排序
|
||||
lists.Reverse(pbStats)
|
||||
|
||||
return &pb.ListUserAccountDailyStatsResponse{Stats: pbStats}, nil
|
||||
}
|
||||
|
||||
// ListUserAccountMonthlyStats 列出按月统计
|
||||
func (this *UserAccountDailyStatService) ListUserAccountMonthlyStats(ctx context.Context, req *pb.ListUserAccountMonthlyStatsRequest) (*pb.ListUserAccountMonthlyStatsResponse, error) {
|
||||
_, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var dayFrom = req.DayFrom
|
||||
var dayTo = req.DayTo
|
||||
|
||||
dayFrom = strings.ReplaceAll(dayFrom, "-", "")
|
||||
dayTo = strings.ReplaceAll(dayTo, "-", "")
|
||||
|
||||
months, err := utils.RangeMonths(dayFrom, dayTo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(months) == 0 {
|
||||
return &pb.ListUserAccountMonthlyStatsResponse{Stats: nil}, nil
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
stats, err := accounts.SharedUserAccountDailyStatDAO.FindMonthlyStats(tx, dayFrom, dayTo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var statMap = map[string]*accounts.UserAccountDailyStat{} // month => Stat
|
||||
for _, stat := range stats {
|
||||
statMap[stat.Month] = stat
|
||||
}
|
||||
|
||||
var pbStats = []*pb.ListUserAccountMonthlyStatsResponse_Stat{}
|
||||
|
||||
for _, month := range months {
|
||||
stat, ok := statMap[month]
|
||||
if ok {
|
||||
pbStats = append(pbStats, &pb.ListUserAccountMonthlyStatsResponse_Stat{
|
||||
Month: month,
|
||||
Income: float32(stat.Income),
|
||||
Expense: float32(stat.Expense),
|
||||
})
|
||||
} else {
|
||||
pbStats = append(pbStats, &pb.ListUserAccountMonthlyStatsResponse_Stat{
|
||||
Month: month,
|
||||
Income: 0,
|
||||
Expense: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 反向排序
|
||||
lists.Reverse(pbStats)
|
||||
|
||||
return &pb.ListUserAccountMonthlyStatsResponse{Stats: pbStats}, nil
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||
//go:build plus
|
||||
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/accounts"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
)
|
||||
|
||||
// UserAccountLogService 用户账户日志服务
|
||||
type UserAccountLogService struct {
|
||||
services.BaseService
|
||||
}
|
||||
|
||||
// CountUserAccountLogs 计算日志数量
|
||||
func (this *UserAccountLogService) CountUserAccountLogs(ctx context.Context, req *pb.CountUserAccountLogsRequest) (*pb.RPCCountResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
count, err := accounts.SharedUserAccountLogDAO.CountAccountLogs(tx, userId, req.UserAccountId, req.Keyword, req.EventType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
|
||||
// ListUserAccountLogs 列出单页日志
|
||||
func (this *UserAccountLogService) ListUserAccountLogs(ctx context.Context, req *pb.ListUserAccountLogsRequest) (*pb.ListUserAccountLogsResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
accountLogs, err := accounts.SharedUserAccountLogDAO.ListAccountLogs(tx, userId, req.UserAccountId, req.Keyword, req.EventType, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var pbLogs = []*pb.UserAccountLog{}
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
for _, log := range accountLogs {
|
||||
// 用户
|
||||
var pbUser = &pb.User{Id: int64(log.UserId)}
|
||||
user, err := models.SharedUserDAO.FindEnabledUser(tx, int64(log.UserId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if user != nil {
|
||||
pbUser = &pb.User{Id: int64(user.Id), Fullname: user.Fullname, Username: user.Username}
|
||||
}
|
||||
|
||||
// 账户
|
||||
var pbAccount = &pb.UserAccount{Id: int64(log.AccountId)}
|
||||
|
||||
pbLogs = append(pbLogs, &pb.UserAccountLog{
|
||||
Id: int64(log.Id),
|
||||
UserId: int64(log.UserId),
|
||||
UserAccountId: int64(log.AccountId),
|
||||
Delta: log.Delta,
|
||||
DeltaFrozen: log.DeltaFrozen,
|
||||
Total: log.Total,
|
||||
TotalFrozen: log.TotalFrozen,
|
||||
EventType: log.EventType,
|
||||
Description: log.Description,
|
||||
CreatedAt: int64(log.CreatedAt),
|
||||
ParamsJSON: log.Params,
|
||||
User: pbUser,
|
||||
UserAccount: pbAccount,
|
||||
})
|
||||
}
|
||||
return &pb.ListUserAccountLogsResponse{UserAccountLogs: pbLogs}, nil
|
||||
}
|
||||
342
EdgeAPI/internal/rpc/services/accounts/service_user_order.go
Normal file
342
EdgeAPI/internal/rpc/services/accounts/service_user_order.go
Normal file
@@ -0,0 +1,342 @@
|
||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build plus
|
||||
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models/accounts"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/payments"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// UserOrderService 用户订单相关服务
|
||||
type UserOrderService struct {
|
||||
services.BaseService
|
||||
}
|
||||
|
||||
// CreateUserOrder 创建订单
|
||||
func (this *UserOrderService) CreateUserOrder(ctx context.Context, req *pb.CreateUserOrderRequest) (*pb.CreateUserOrderResponse, error) {
|
||||
userId, err := this.ValidateUserNode(ctx, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !userconfigs.IsValidOrderType(req.Type) {
|
||||
return nil, errors.New("invalid order type '" + req.Type + "'")
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
method, err := accounts.SharedOrderMethodDAO.FindEnabledOrderMethodWithCode(tx, req.OrderMethodCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if method == nil {
|
||||
return nil, errors.New("can not find order method with code '" + req.OrderMethodCode + "'")
|
||||
}
|
||||
if !method.IsOn {
|
||||
return nil, errors.New("method is not enabled")
|
||||
}
|
||||
var methodId = int64(method.Id)
|
||||
|
||||
if req.Amount <= 0 {
|
||||
return nil, errors.New("'amount' should be greater than 0")
|
||||
}
|
||||
|
||||
var orderCode = ""
|
||||
err = this.RunTx(func(tx *dbs.Tx) error {
|
||||
_, code, err := accounts.SharedUserOrderDAO.CreateOrder(tx, 0, userId, req.Type, methodId, req.Amount, req.ParamsJSON)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
orderCode = code
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
order, err := accounts.SharedUserOrderDAO.FindUserOrderWithCode(tx, orderCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if order == nil {
|
||||
return nil, errors.New("can not find order with generated code '" + orderCode + "'")
|
||||
}
|
||||
payURL, err := payments.GeneratePayURL(order, method)
|
||||
if err != nil {
|
||||
return nil, errors.New("generate pay url failed: " + err.Error())
|
||||
}
|
||||
|
||||
return &pb.CreateUserOrderResponse{
|
||||
Code: orderCode,
|
||||
PayURL: payURL,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// FindEnabledUserOrder 查看订单
|
||||
func (this *UserOrderService) FindEnabledUserOrder(ctx context.Context, req *pb.FindEnabledUserOrderRequest) (*pb.FindEnabledUserOrderResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
order, err := accounts.SharedUserOrderDAO.FindUserOrderWithCode(tx, req.Code)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if order == nil {
|
||||
return &pb.FindEnabledUserOrderResponse{UserOrder: nil}, nil
|
||||
}
|
||||
|
||||
// 检查用户权限
|
||||
if userId > 0 {
|
||||
if int64(order.UserId) != userId {
|
||||
return &pb.FindEnabledUserOrderResponse{UserOrder: nil}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// 用户
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
user, err := models.SharedUserDAO.FindEnabledUser(tx, int64(order.UserId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbUser *pb.User
|
||||
if user != nil {
|
||||
pbUser = &pb.User{
|
||||
Id: int64(user.Id),
|
||||
Username: user.Username,
|
||||
Fullname: user.Fullname,
|
||||
}
|
||||
}
|
||||
|
||||
// 支付方式
|
||||
method, err := accounts.SharedOrderMethodDAO.FindEnabledOrderMethod(tx, int64(order.MethodId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbMethod *pb.OrderMethod
|
||||
if method != nil {
|
||||
pbMethod = &pb.OrderMethod{
|
||||
Id: int64(method.Id),
|
||||
Name: method.Name,
|
||||
Code: method.Code,
|
||||
IsOn: method.IsOn,
|
||||
ParentCode: method.ParentCode,
|
||||
ClientType: method.ClientType,
|
||||
QrcodeTitle: method.QrcodeTitle,
|
||||
}
|
||||
}
|
||||
|
||||
// 支付URL
|
||||
payURL, err := payments.GeneratePayURL(order, method)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &pb.FindEnabledUserOrderResponse{UserOrder: &pb.UserOrder{
|
||||
UserId: int64(order.UserId),
|
||||
Code: order.Code,
|
||||
Type: order.Type,
|
||||
OrderMethodId: int64(order.MethodId),
|
||||
Status: order.Status,
|
||||
Amount: float32(order.Amount),
|
||||
ParamsJSON: order.Params,
|
||||
CreatedAt: int64(order.CreatedAt),
|
||||
CancelledAt: int64(order.CancelledAt),
|
||||
FinishedAt: int64(order.FinishedAt),
|
||||
IsExpired: order.IsExpired(),
|
||||
User: pbUser,
|
||||
OrderMethod: pbMethod,
|
||||
CanPay: !order.IsExpired() && order.Status == userconfigs.OrderStatusNone,
|
||||
PayURL: payURL,
|
||||
}}, nil
|
||||
}
|
||||
|
||||
// CancelUserOrder 取消订单
|
||||
func (this *UserOrderService) CancelUserOrder(ctx context.Context, req *pb.CancelUserOrderRequest) (*pb.RPCSuccess, error) {
|
||||
adminId, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
order, err := accounts.SharedUserOrderDAO.FindUserOrderWithCode(tx, req.Code)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if order == nil {
|
||||
return nil, errors.New("can not find order")
|
||||
}
|
||||
|
||||
if userId > 0 {
|
||||
if int64(order.UserId) != userId {
|
||||
return nil, errors.New("can not find order")
|
||||
}
|
||||
}
|
||||
|
||||
err = this.RunTx(func(tx *dbs.Tx) error {
|
||||
return accounts.SharedUserOrderDAO.CancelOrder(tx, adminId, userId, int64(order.Id))
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// FinishUserOrder 完成订单
|
||||
func (this *UserOrderService) FinishUserOrder(ctx context.Context, req *pb.FinishUserOrderRequest) (*pb.RPCSuccess, error) {
|
||||
adminId, err := this.ValidateAdmin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
order, err := accounts.SharedUserOrderDAO.FindUserOrderWithCode(tx, req.Code)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if order == nil {
|
||||
return nil, errors.New("can not find order")
|
||||
}
|
||||
|
||||
err = this.RunTx(func(tx *dbs.Tx) error {
|
||||
return accounts.SharedUserOrderDAO.FinishOrder(tx, adminId, 0, int64(order.Id))
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
|
||||
// CountEnabledUserOrders 计算订单数量
|
||||
func (this *UserOrderService) CountEnabledUserOrders(ctx context.Context, req *pb.CountEnabledUserOrdersRequest) (*pb.RPCCountResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if userId > 0 {
|
||||
req.UserId = userId
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
count, err := accounts.SharedUserOrderDAO.CountEnabledUserOrders(tx, req.UserId, req.Status, req.Keyword)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.SuccessCount(count)
|
||||
}
|
||||
|
||||
// ListEnabledUserOrders 列出单页订单
|
||||
func (this *UserOrderService) ListEnabledUserOrders(ctx context.Context, req *pb.ListEnabledUserOrdersRequest) (*pb.ListEnabledUserOrdersResponse, error) {
|
||||
_, userId, err := this.ValidateAdminAndUser(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if userId > 0 {
|
||||
req.UserId = userId
|
||||
}
|
||||
|
||||
var tx = this.NullTx()
|
||||
orders, err := accounts.SharedUserOrderDAO.ListEnabledUserOrders(tx, req.UserId, req.Status, req.Keyword, req.Offset, req.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbOrders = []*pb.UserOrder{}
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
for _, order := range orders {
|
||||
// 用户
|
||||
user, err := models.SharedUserDAO.FindEnabledUser(tx, int64(order.UserId), cacheMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbUser *pb.User
|
||||
if user != nil {
|
||||
pbUser = &pb.User{
|
||||
Id: int64(user.Id),
|
||||
Username: user.Username,
|
||||
Fullname: user.Fullname,
|
||||
}
|
||||
}
|
||||
|
||||
// 支付方式
|
||||
method, err := accounts.SharedOrderMethodDAO.FindEnabledOrderMethod(tx, int64(order.MethodId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pbMethod *pb.OrderMethod
|
||||
if method != nil {
|
||||
pbMethod = &pb.OrderMethod{
|
||||
Id: int64(method.Id),
|
||||
Name: method.Name,
|
||||
Code: method.Code,
|
||||
IsOn: method.IsOn,
|
||||
}
|
||||
}
|
||||
|
||||
pbOrders = append(pbOrders, &pb.UserOrder{
|
||||
UserId: int64(order.UserId),
|
||||
Code: order.Code,
|
||||
Type: order.Type,
|
||||
OrderMethodId: int64(order.MethodId),
|
||||
Status: order.Status,
|
||||
Amount: float32(order.Amount),
|
||||
ParamsJSON: order.Params,
|
||||
CreatedAt: int64(order.CreatedAt),
|
||||
CancelledAt: int64(order.CancelledAt),
|
||||
FinishedAt: int64(order.FinishedAt),
|
||||
IsExpired: order.IsExpired(),
|
||||
User: pbUser,
|
||||
OrderMethod: pbMethod,
|
||||
})
|
||||
}
|
||||
return &pb.ListEnabledUserOrdersResponse{
|
||||
UserOrders: pbOrders,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NotifyUserOrderPayment 订单支付通知
|
||||
func (this *UserOrderService) NotifyUserOrderPayment(ctx context.Context, req *pb.NotifyUserOrderPaymentRequest) (*pb.RPCSuccess, error) {
|
||||
userId, err := this.ValidateUserNode(ctx, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var formValues = url.Values{}
|
||||
err = json.Unmarshal(req.FormData, &formValues)
|
||||
if err != nil {
|
||||
return nil, errors.New("decode form values failed: " + err.Error())
|
||||
}
|
||||
|
||||
err = this.RunTx(func(tx *dbs.Tx) error {
|
||||
// 校验检查订单
|
||||
orderId, err := payments.Verify(req.PayMethod, formValues)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return accounts.SharedUserOrderDAO.FinishOrder(tx, 0, userId, orderId)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return this.Success()
|
||||
}
|
||||
Reference in New Issue
Block a user