diff --git a/apis/types.api b/apis/types.api index c80fb52..f3bb0b5 100644 --- a/apis/types.api +++ b/apis/types.api @@ -575,6 +575,7 @@ type ( Traffic int64 `json:"traffic"` Download int64 `json:"download"` Upload int64 `json:"upload"` + TrafficLimit []TrafficLimit `json:"user_traffic_limit"` Token string `json:"token"` Status uint8 `json:"status"` EntitlementSource string `json:"entitlement_source"` diff --git a/internal/logic/admin/user/getUserSubscribeLogic.go b/internal/logic/admin/user/getUserSubscribeLogic.go index c33040a..19b7ee0 100644 --- a/internal/logic/admin/user/getUserSubscribeLogic.go +++ b/internal/logic/admin/user/getUserSubscribeLogic.go @@ -2,8 +2,10 @@ package user import ( "context" + "encoding/json" "github.com/perfect-panel/server/internal/model/group" + "github.com/perfect-panel/server/internal/model/user" "github.com/perfect-panel/server/internal/svc" "github.com/perfect-panel/server/internal/types" "github.com/perfect-panel/server/pkg/logger" @@ -61,12 +63,20 @@ func (l *GetUserSubscribeLogic) GetUserSubscribe(req *types.GetUserSubscribeList } for _, item := range data { - var sub types.UserSubscribe - tool.DeepCopy(&sub, item) - sub.Short, _ = tool.FixedUniqueString(item.Token, 8, "") - sub.NodeGroupId = item.NodeGroupId - sub.NodeGroupName = groupNames[item.NodeGroupId] + sub := buildUserSubscribeListItem(item, groupNames[item.NodeGroupId]) resp.List = append(resp.List, sub) } return } + +func buildUserSubscribeListItem(item *user.SubscribeDetails, groupName string) types.UserSubscribe { + var sub types.UserSubscribe + tool.DeepCopy(&sub, item) + sub.Short, _ = tool.FixedUniqueString(item.Token, 8, "") + sub.NodeGroupId = item.NodeGroupId + sub.NodeGroupName = groupName + if item.TrafficLimit != nil && *item.TrafficLimit != "" { + _ = json.Unmarshal([]byte(*item.TrafficLimit), &sub.TrafficLimit) + } + return sub +} diff --git a/internal/logic/admin/user/getUserSubscribeLogic_test.go b/internal/logic/admin/user/getUserSubscribeLogic_test.go new file mode 100644 index 0000000..1bcaa1b --- /dev/null +++ b/internal/logic/admin/user/getUserSubscribeLogic_test.go @@ -0,0 +1,73 @@ +package user + +import ( + "testing" + "time" + + modeluser "github.com/perfect-panel/server/internal/model/user" + "github.com/perfect-panel/server/internal/types" +) + +func TestBuildUserSubscribeListItem(t *testing.T) { + trafficLimitJSON := `[{"stat_type":"day","stat_value":1,"traffic_usage":10,"speed_limit":5}]` + now := time.Unix(1718000000, 0) + + tests := []struct { + name string + item *modeluser.SubscribeDetails + wantTrafficLimit []types.TrafficLimit + }{ + { + name: "non-empty user traffic limit", + item: &modeluser.SubscribeDetails{ + Id: 1, + UserId: 2, + NodeGroupId: 3, + Token: "token-12345678", + TrafficLimit: &trafficLimitJSON, + StartTime: now, + ExpireTime: now, + }, + wantTrafficLimit: []types.TrafficLimit{ + { + StatType: "day", + StatValue: 1, + TrafficUsage: 10, + SpeedLimit: 5, + }, + }, + }, + { + name: "empty user traffic limit", + item: &modeluser.SubscribeDetails{ + Id: 4, + UserId: 5, + NodeGroupId: 6, + Token: "token-empty", + StartTime: now, + ExpireTime: now, + }, + wantTrafficLimit: nil, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + got := buildUserSubscribeListItem(tc.item, "group-a") + if got.NodeGroupName != "group-a" { + t.Fatalf("NodeGroupName = %q, want %q", got.NodeGroupName, "group-a") + } + if len(got.Short) != 8 { + t.Fatalf("Short length = %d, want 8", len(got.Short)) + } + if len(got.TrafficLimit) != len(tc.wantTrafficLimit) { + t.Fatalf("TrafficLimit length = %d, want %d", len(got.TrafficLimit), len(tc.wantTrafficLimit)) + } + for i := range tc.wantTrafficLimit { + if got.TrafficLimit[i] != tc.wantTrafficLimit[i] { + t.Fatalf("TrafficLimit[%d] = %+v, want %+v", i, got.TrafficLimit[i], tc.wantTrafficLimit[i]) + } + } + }) + } +} diff --git a/internal/types/types.go b/internal/types/types.go index 9215fca..44cbaf7 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -3679,30 +3679,31 @@ type UserStatisticsResponse struct { } type UserSubscribe struct { - Id int64 `json:"id"` - IdStr string `json:"id_str"` - UserId int64 `json:"user_id"` - OrderId int64 `json:"order_id"` - SubscribeId int64 `json:"subscribe_id"` - Subscribe Subscribe `json:"subscribe"` - NodeGroupId int64 `json:"node_group_id"` - NodeGroupName string `json:"node_group_name"` - StartTime int64 `json:"start_time"` - ExpireTime int64 `json:"expire_time"` - FinishedAt int64 `json:"finished_at"` - ResetTime int64 `json:"reset_time"` - Traffic int64 `json:"traffic"` - Download int64 `json:"download"` - Upload int64 `json:"upload"` - Token string `json:"token"` - Status uint8 `json:"status"` - EntitlementSource string `json:"entitlement_source"` - EntitlementOwnerUserId int64 `json:"entitlement_owner_user_id"` - ReadOnly bool `json:"read_only"` - IsGift bool `json:"is_gift"` - Short string `json:"short"` - CreatedAt int64 `json:"created_at"` - UpdatedAt int64 `json:"updated_at"` + Id int64 `json:"id"` + IdStr string `json:"id_str"` + UserId int64 `json:"user_id"` + OrderId int64 `json:"order_id"` + SubscribeId int64 `json:"subscribe_id"` + Subscribe Subscribe `json:"subscribe"` + NodeGroupId int64 `json:"node_group_id"` + NodeGroupName string `json:"node_group_name"` + StartTime int64 `json:"start_time"` + ExpireTime int64 `json:"expire_time"` + FinishedAt int64 `json:"finished_at"` + ResetTime int64 `json:"reset_time"` + Traffic int64 `json:"traffic"` + Download int64 `json:"download"` + Upload int64 `json:"upload"` + TrafficLimit []TrafficLimit `json:"user_traffic_limit"` + Token string `json:"token"` + Status uint8 `json:"status"` + EntitlementSource string `json:"entitlement_source"` + EntitlementOwnerUserId int64 `json:"entitlement_owner_user_id"` + ReadOnly bool `json:"read_only"` + IsGift bool `json:"is_gift"` + Short string `json:"short"` + CreatedAt int64 `json:"created_at"` + UpdatedAt int64 `json:"updated_at"` } type UserSubscribeDetail struct {