mirror of
https://github.com/TeaOSLab/EdgeAPI.git
synced 2025-11-07 10:40:25 +08:00
[账单]显示账单、手动生成账单
This commit is contained in:
@@ -13,6 +13,7 @@ type Log struct {
|
|||||||
Ip string `field:"ip"` // IP地址
|
Ip string `field:"ip"` // IP地址
|
||||||
Type string `field:"type"` // 类型:admin, user
|
Type string `field:"type"` // 类型:admin, user
|
||||||
Day string `field:"day"` // 日期
|
Day string `field:"day"` // 日期
|
||||||
|
BillId uint32 `field:"billId"` // 账单ID
|
||||||
}
|
}
|
||||||
|
|
||||||
type LogOperator struct {
|
type LogOperator struct {
|
||||||
@@ -27,6 +28,7 @@ type LogOperator struct {
|
|||||||
Ip interface{} // IP地址
|
Ip interface{} // IP地址
|
||||||
Type interface{} // 类型:admin, user
|
Type interface{} // 类型:admin, user
|
||||||
Day interface{} // 日期
|
Day interface{} // 日期
|
||||||
|
BillId interface{} // 账单ID
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLogOperator() *LogOperator {
|
func NewLogOperator() *LogOperator {
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import (
|
|||||||
const (
|
const (
|
||||||
NodePriceItemStateEnabled = 1 // 已启用
|
NodePriceItemStateEnabled = 1 // 已启用
|
||||||
NodePriceItemStateDisabled = 0 // 已禁用
|
NodePriceItemStateDisabled = 0 // 已禁用
|
||||||
|
|
||||||
|
NodePriceTypeTraffic = "traffic" // 价格类型之流量
|
||||||
)
|
)
|
||||||
|
|
||||||
type NodePriceItemDAO dbs.DAO
|
type NodePriceItemDAO dbs.DAO
|
||||||
@@ -118,3 +120,15 @@ func (this *NodePriceItemDAO) FindAllEnabledAndOnRegionPrices(priceType string)
|
|||||||
FindAll()
|
FindAll()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 根据字节查找付费项目
|
||||||
|
func (this *NodePriceItemDAO) SearchItemsWithBytes(items []*NodePriceItem, bytes int64) int64 {
|
||||||
|
bytes *= 8
|
||||||
|
|
||||||
|
for _, item := range items {
|
||||||
|
if bytes >= int64(item.BitsFrom) && (bytes < int64(item.BitsTo) || item.BitsTo == 0) {
|
||||||
|
return int64(item.Id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|||||||
@@ -108,6 +108,18 @@ func (this *NodeRegionDAO) FindAllEnabledRegions() (result []*NodeRegion, err er
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 列出所有价格
|
||||||
|
func (this *NodeRegionDAO) FindAllEnabledRegionPrices() (result []*NodeRegion, err error) {
|
||||||
|
_, err = this.Query().
|
||||||
|
State(NodeRegionStateEnabled).
|
||||||
|
Desc("order").
|
||||||
|
AscPk().
|
||||||
|
Result("id", "prices").
|
||||||
|
Slice(&result).
|
||||||
|
FindAll()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 列出所有启用的区域
|
// 列出所有启用的区域
|
||||||
func (this *NodeRegionDAO) FindAllEnabledAndOnRegions() (result []*NodeRegion, err error) {
|
func (this *NodeRegionDAO) FindAllEnabledAndOnRegions() (result []*NodeRegion, err error) {
|
||||||
_, err = this.Query().
|
_, err = this.Query().
|
||||||
|
|||||||
@@ -55,3 +55,14 @@ func (this *ServerDailyStatDAO) SaveStats(stats []*pb.ServerDailyStat) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 根据用户计算某月合计
|
||||||
|
// month 格式为YYYYMM
|
||||||
|
func (this *ServerDailyStatDAO) SumUserMonthly(userId int64, regionId int64, month string) (int64, error) {
|
||||||
|
return this.Query().
|
||||||
|
Attr("regionId", regionId).
|
||||||
|
Between("day", month+"01", month+"32").
|
||||||
|
Where("serverId IN (SELECT id FROM "+SharedServerDAO.Table+" WHERE userId=:userId)").
|
||||||
|
Param("userId", userId).
|
||||||
|
SumInt64("bytes", 0)
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package models
|
|||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
"github.com/iwind/TeaGo/dbs"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -37,3 +39,12 @@ func TestServerDailyStatDAO_SaveStats2(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Log("ok")
|
t.Log("ok")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestServerDailyStatDAO_SumUserMonthly(t *testing.T) {
|
||||||
|
dbs.NotifyReady()
|
||||||
|
bytes, err := NewServerDailyStatDAO().SumUserMonthly(1, 1, timeutil.Format("Ym"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log("bytes:", bytes)
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,23 +2,25 @@ package models
|
|||||||
|
|
||||||
// 计费流量统计
|
// 计费流量统计
|
||||||
type ServerDailyStat struct {
|
type ServerDailyStat struct {
|
||||||
Id uint64 `field:"id"` // ID
|
Id uint64 `field:"id"` // ID
|
||||||
ServerId uint32 `field:"serverId"` // 服务ID
|
ServerId uint32 `field:"serverId"` // 服务ID
|
||||||
RegionId uint32 `field:"regionId"` // 区域ID
|
RegionId uint32 `field:"regionId"` // 区域ID
|
||||||
Bytes uint64 `field:"bytes"` // 流量
|
Bytes uint64 `field:"bytes"` // 流量
|
||||||
Day string `field:"day"` // 日期YYYYMMDD
|
Day string `field:"day"` // 日期YYYYMMDD
|
||||||
TimeFrom string `field:"timeFrom"` // 开始时间HHMMSS
|
TimeFrom string `field:"timeFrom"` // 开始时间HHMMSS
|
||||||
TimeTo string `field:"timeTo"` // 结束时间
|
TimeTo string `field:"timeTo"` // 结束时间
|
||||||
|
IsCharged uint8 `field:"isCharged"` // 是否已计算费用
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerDailyStatOperator struct {
|
type ServerDailyStatOperator struct {
|
||||||
Id interface{} // ID
|
Id interface{} // ID
|
||||||
ServerId interface{} // 服务ID
|
ServerId interface{} // 服务ID
|
||||||
RegionId interface{} // 区域ID
|
RegionId interface{} // 区域ID
|
||||||
Bytes interface{} // 流量
|
Bytes interface{} // 流量
|
||||||
Day interface{} // 日期YYYYMMDD
|
Day interface{} // 日期YYYYMMDD
|
||||||
TimeFrom interface{} // 开始时间HHMMSS
|
TimeFrom interface{} // 开始时间HHMMSS
|
||||||
TimeTo interface{} // 结束时间
|
TimeTo interface{} // 结束时间
|
||||||
|
IsCharged interface{} // 是否已计算费用
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServerDailyStatOperator() *ServerDailyStatOperator {
|
func NewServerDailyStatOperator() *ServerDailyStatOperator {
|
||||||
|
|||||||
206
internal/db/models/user_bill_dao.go
Normal file
206
internal/db/models/user_bill_dao.go
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/utils/numberutils"
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
"github.com/iwind/TeaGo/Tea"
|
||||||
|
"github.com/iwind/TeaGo/dbs"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BillType = string
|
||||||
|
|
||||||
|
const (
|
||||||
|
BillTypeTraffic BillType = "traffic" // 按流量计费
|
||||||
|
)
|
||||||
|
|
||||||
|
type UserBillDAO dbs.DAO
|
||||||
|
|
||||||
|
func NewUserBillDAO() *UserBillDAO {
|
||||||
|
return dbs.NewDAO(&UserBillDAO{
|
||||||
|
DAOObject: dbs.DAOObject{
|
||||||
|
DB: Tea.Env,
|
||||||
|
Table: "edgeUserBills",
|
||||||
|
Model: new(UserBill),
|
||||||
|
PkName: "id",
|
||||||
|
},
|
||||||
|
}).(*UserBillDAO)
|
||||||
|
}
|
||||||
|
|
||||||
|
var SharedUserBillDAO *UserBillDAO
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
dbs.OnReady(func() {
|
||||||
|
SharedUserBillDAO = NewUserBillDAO()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算账单数量
|
||||||
|
func (this *UserBillDAO) CountAllUserBills(isPaid int32, userId int64, month string) (int64, error) {
|
||||||
|
query := this.Query()
|
||||||
|
if isPaid == 0 {
|
||||||
|
query.Attr("isPaid", 0)
|
||||||
|
} else if isPaid > 0 {
|
||||||
|
query.Attr("isPaid", 1)
|
||||||
|
}
|
||||||
|
if userId > 0 {
|
||||||
|
query.Attr("userId", userId)
|
||||||
|
}
|
||||||
|
if len(month) > 0 {
|
||||||
|
query.Attr("month", month)
|
||||||
|
}
|
||||||
|
return query.Count()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 列出单页账单
|
||||||
|
func (this *UserBillDAO) ListUserBills(isPaid int32, userId int64, month string, offset, size int64) (result []*UserBill, err error) {
|
||||||
|
query := this.Query()
|
||||||
|
if isPaid == 0 {
|
||||||
|
query.Attr("isPaid", 0)
|
||||||
|
} else if isPaid > 0 {
|
||||||
|
query.Attr("isPaid", 1)
|
||||||
|
}
|
||||||
|
if userId > 0 {
|
||||||
|
query.Attr("userId", userId)
|
||||||
|
}
|
||||||
|
if len(month) > 0 {
|
||||||
|
query.Attr("month", month)
|
||||||
|
}
|
||||||
|
_, err = query.
|
||||||
|
Offset(offset).
|
||||||
|
Limit(size).
|
||||||
|
Slice(&result).
|
||||||
|
DescPk().
|
||||||
|
FindAll()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建账单
|
||||||
|
func (this *UserBillDAO) CreateBill(userId int64, billType BillType, description string, amount float32, month string) (int64, error) {
|
||||||
|
op := NewUserBillOperator()
|
||||||
|
op.UserId = userId
|
||||||
|
op.Type = billType
|
||||||
|
op.Description = description
|
||||||
|
op.Amount = amount
|
||||||
|
op.Month = month
|
||||||
|
op.IsPaid = false
|
||||||
|
return this.SaveInt64(op)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否有当月账单
|
||||||
|
func (this *UserBillDAO) ExistBill(userId int64, billType BillType, month string) (bool, error) {
|
||||||
|
return this.Query().
|
||||||
|
Attr("userId", userId).
|
||||||
|
Attr("month", month).
|
||||||
|
Attr("type", billType).
|
||||||
|
Exist()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成账单
|
||||||
|
// month 格式YYYYMM
|
||||||
|
func (this *UserBillDAO) GenerateBills(month string) error {
|
||||||
|
// 用户
|
||||||
|
offset := int64(0)
|
||||||
|
size := int64(100) // 每次只查询N次,防止由于执行时间过长而锁表
|
||||||
|
for {
|
||||||
|
userIds, err := SharedUserDAO.ListEnabledUserIds(offset, size)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
offset += size
|
||||||
|
if len(userIds) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, userId := range userIds {
|
||||||
|
// CDN流量账单
|
||||||
|
err := this.generateTrafficBill(userId, month)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成CDN流量账单
|
||||||
|
// month 格式YYYYMM
|
||||||
|
func (this *UserBillDAO) generateTrafficBill(userId int64, month string) error {
|
||||||
|
// 检查是否已经有账单了
|
||||||
|
b, err := this.ExistBill(userId, BillTypeTraffic, month)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if b {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO 优化使用缓存
|
||||||
|
regions, err := SharedNodeRegionDAO.FindAllEnabledRegionPrices()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(regions) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
priceItems, err := SharedNodePriceItemDAO.FindAllEnabledRegionPrices(NodePriceTypeTraffic)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(priceItems) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
cost := float32(0)
|
||||||
|
for _, region := range regions {
|
||||||
|
if len(region.Prices) == 0 || region.Prices == "null" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
priceMap := map[string]float32{}
|
||||||
|
err = json.Unmarshal([]byte(region.Prices), &priceMap)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
trafficBytes, err := SharedServerDailyStatDAO.SumUserMonthly(userId, int64(region.Id), month)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if trafficBytes == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
itemId := SharedNodePriceItemDAO.SearchItemsWithBytes(priceItems, trafficBytes)
|
||||||
|
if itemId == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
price, ok := priceMap[numberutils.FormatInt64(itemId)]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算钱
|
||||||
|
// 这里采用1000进制
|
||||||
|
cost += (float32(trafficBytes*8) / 1_000_000_000) * price
|
||||||
|
}
|
||||||
|
|
||||||
|
if cost == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建账单
|
||||||
|
_, err = this.CreateBill(userId, BillTypeTraffic, "按流量计费", cost, month)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取账单类型名称
|
||||||
|
func (this *UserBillDAO) BillTypeName(billType BillType) string {
|
||||||
|
switch billType {
|
||||||
|
case BillTypeTraffic:
|
||||||
|
return "流量"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
18
internal/db/models/user_bill_dao_test.go
Normal file
18
internal/db/models/user_bill_dao_test.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
"github.com/iwind/TeaGo/dbs"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestUserBillDAO_GenerateBills(t *testing.T) {
|
||||||
|
dbs.NotifyReady()
|
||||||
|
|
||||||
|
err := SharedUserBillDAO.GenerateBills(timeutil.Format("Ym"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log("ok")
|
||||||
|
}
|
||||||
30
internal/db/models/user_bill_model.go
Normal file
30
internal/db/models/user_bill_model.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
// 用户账单
|
||||||
|
type UserBill struct {
|
||||||
|
Id uint64 `field:"id"` // ID
|
||||||
|
UserId uint32 `field:"userId"` // 用户ID
|
||||||
|
Type string `field:"type"` // 消费类型
|
||||||
|
Description string `field:"description"` // 描述
|
||||||
|
Amount float64 `field:"amount"` // 消费数额
|
||||||
|
Month string `field:"month"` // 帐期YYYYMM
|
||||||
|
IsPaid uint8 `field:"isPaid"` // 是否已支付
|
||||||
|
PaidAt uint64 `field:"paidAt"` // 支付时间
|
||||||
|
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserBillOperator struct {
|
||||||
|
Id interface{} // ID
|
||||||
|
UserId interface{} // 用户ID
|
||||||
|
Type interface{} // 消费类型
|
||||||
|
Description interface{} // 描述
|
||||||
|
Amount interface{} // 消费数额
|
||||||
|
Month interface{} // 帐期YYYYMM
|
||||||
|
IsPaid interface{} // 是否已支付
|
||||||
|
PaidAt interface{} // 支付时间
|
||||||
|
CreatedAt interface{} // 创建时间
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUserBillOperator() *UserBillOperator {
|
||||||
|
return &UserBillOperator{}
|
||||||
|
}
|
||||||
1
internal/db/models/user_bill_model_ext.go
Normal file
1
internal/db/models/user_bill_model_ext.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package models
|
||||||
@@ -160,3 +160,22 @@ func (this *UserDAO) ExistUser(userId int64, username string) (bool, error) {
|
|||||||
Neq("id", userId).
|
Neq("id", userId).
|
||||||
Exist()
|
Exist()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 列出单页的用户ID
|
||||||
|
func (this *UserDAO) ListEnabledUserIds(offset, size int64) ([]int64, error) {
|
||||||
|
ones, _, err := this.Query().
|
||||||
|
ResultPk().
|
||||||
|
State(UserStateEnabled).
|
||||||
|
Offset(offset).
|
||||||
|
Limit(size).
|
||||||
|
AscPk().
|
||||||
|
FindOnes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := []int64{}
|
||||||
|
for _, one := range ones {
|
||||||
|
result = append(result, one.GetInt64("id"))
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -204,6 +204,7 @@ func (this *APINode) listenRPC(listener net.Listener, tlsConfig *tls.Config) err
|
|||||||
pb.RegisterACMEAuthenticationServiceServer(rpcServer, &services.ACMEAuthenticationService{})
|
pb.RegisterACMEAuthenticationServiceServer(rpcServer, &services.ACMEAuthenticationService{})
|
||||||
pb.RegisterUserServiceServer(rpcServer, &services.UserService{})
|
pb.RegisterUserServiceServer(rpcServer, &services.UserService{})
|
||||||
pb.RegisterServerDailyStatServiceServer(rpcServer, &services.ServerDailyStatService{})
|
pb.RegisterServerDailyStatServiceServer(rpcServer, &services.ServerDailyStatService{})
|
||||||
|
pb.RegisterUserBillServiceServer(rpcServer, &services.UserBillService{})
|
||||||
err := rpcServer.Serve(listener)
|
err := rpcServer.Serve(listener)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("[API_NODE]start rpc failed: " + err.Error())
|
return errors.New("[API_NODE]start rpc failed: " + err.Error())
|
||||||
|
|||||||
88
internal/rpc/services/service_user_bill.go
Normal file
88
internal/rpc/services/service_user_bill.go
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 账单相关服务
|
||||||
|
type UserBillService struct {
|
||||||
|
BaseService
|
||||||
|
}
|
||||||
|
|
||||||
|
// 手工生成订单
|
||||||
|
func (this *UserBillService) GenerateAllUserBills(ctx context.Context, req *pb.GenerateAllUserBillsRequest) (*pb.RPCSuccess, error) {
|
||||||
|
_, err := this.ValidateAdmin(ctx, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验Month
|
||||||
|
if !regexp.MustCompile(`^\d{6}$`).MatchString(req.Month) {
|
||||||
|
return nil, errors.New("invalid month '" + req.Month + "'")
|
||||||
|
}
|
||||||
|
if req.Month >= timeutil.Format("Ym") {
|
||||||
|
return nil, errors.New("invalid month '" + req.Month + "'")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = models.SharedUserBillDAO.GenerateBills(req.Month)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.Success()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算所有账单数量
|
||||||
|
func (this *UserBillService) CountAllUserBills(ctx context.Context, req *pb.CountAllUserBillsRequest) (*pb.RPCCountResponse, error) {
|
||||||
|
_, err := this.ValidateAdmin(ctx, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
count, err := models.SharedUserBillDAO.CountAllUserBills(req.PaidFlag, req.UserId, req.Month)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return this.SuccessCount(count)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 列出单页账单
|
||||||
|
func (this *UserBillService) ListUserBills(ctx context.Context, req *pb.ListUserBillsRequest) (*pb.ListUserBillsResponse, error) {
|
||||||
|
_, err := this.ValidateAdmin(ctx, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
bills, err := models.SharedUserBillDAO.ListUserBills(req.PaidFlag, req.UserId, req.Month, req.Offset, req.Size)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := []*pb.UserBill{}
|
||||||
|
for _, bill := range bills {
|
||||||
|
userFullname, err := models.SharedUserDAO.FindUserFullname(int64(bill.UserId))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result = append(result, &pb.UserBill{
|
||||||
|
Id: int64(bill.Id),
|
||||||
|
User: &pb.User{
|
||||||
|
Id: int64(bill.UserId),
|
||||||
|
Fullname: userFullname,
|
||||||
|
},
|
||||||
|
Type: bill.Type,
|
||||||
|
TypeName: models.SharedUserBillDAO.BillTypeName(bill.Type),
|
||||||
|
Description: bill.Description,
|
||||||
|
Amount: float32(bill.Amount),
|
||||||
|
Month: bill.Month,
|
||||||
|
IsPaid: bill.IsPaid == 1,
|
||||||
|
PaidAt: int64(bill.PaidAt),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return &pb.ListUserBillsResponse{UserBills: result}, nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user