Initial commit

This commit is contained in:
Donny
2019-04-22 20:46:32 +08:00
commit 49ab8aadd1
25441 changed files with 4055000 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"content_ext_test.go",
"service_test.go",
"upload_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"content_ext.go",
"service.go",
"upload.go",
],
importmap = "go-common/app/admin/main/up/service",
importpath = "go-common/app/admin/main/up/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//app/admin/main/up/dao:go_default_library",
"//app/admin/main/up/dao/global:go_default_library",
"//app/admin/main/up/dao/manager:go_default_library",
"//app/admin/main/up/service/upcrmservice:go_default_library",
"//app/admin/main/up/util:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/render:go_default_library",
"//library/stat/prom:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/admin/main/up/service/cache:all-srcs",
"//app/admin/main/up/service/data:all-srcs",
"//app/admin/main/up/service/upcrmservice:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

56
app/admin/main/up/service/cache/BUILD vendored Normal file
View File

@@ -0,0 +1,56 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"cache.go",
"tag.go",
"video_types.go",
],
importpath = "go-common/app/admin/main/up/service/cache",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//app/interface/main/creative/model/tag:go_default_library",
"//app/service/main/videoup/model/archive:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = [
"cache_test.go",
"tag_test.go",
"video_types_test.go",
],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//app/interface/main/creative/model/tag:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,9 @@
package cache
import "time"
//LoadCache load cache
func LoadCache() {
var now = time.Now()
RefreshUpType(now)
}

View File

@@ -0,0 +1,45 @@
package cache
import (
"testing"
"flag"
"github.com/smartystreets/goconvey/convey"
"go-common/app/admin/main/up/conf"
"os"
)
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.up-admin")
flag.Set("conf_token", "930697bb7def4df0713ef8080596b863")
flag.Set("tree_id", "36438")
flag.Set("conf_version", "1")
flag.Set("deploy_env", "uat")
flag.Set("conf_host", "config.bilibili.co")
flag.Set("conf_path", "/tmp")
flag.Set("region", "sh")
flag.Set("zone", "sh001")
} else {
flag.Set("conf", "../../cmd/up-admin.toml")
}
if os.Getenv("UT_LOCAL_TEST") != "" {
flag.Set("conf", "../../cmd/up-admin.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
os.Exit(m.Run())
}
func TestCacheLoadCache(t *testing.T) {
convey.Convey("LoadCache", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
LoadCache()
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}

45
app/admin/main/up/service/cache/tag.go vendored Normal file
View File

@@ -0,0 +1,45 @@
package cache
import (
"go-common/app/interface/main/creative/model/tag"
"sync"
"time"
)
var (
//TagCache tag's cache key=>tag_id, value=>*tag.Meta
TagCache = make(map[int64]*tag.Meta)
tagMutex sync.Mutex
)
//ClearTagCache clear all tag cache
func ClearTagCache(tm time.Time) {
TagCache = make(map[int64]*tag.Meta)
}
//AddTagCache add tag cache
func AddTagCache(meta *tag.Meta) {
if meta == nil {
return
}
tagMutex.Lock()
TagCache[meta.TagID] = meta
tagMutex.Unlock()
}
//GetTagCache get tag cache
func GetTagCache(ids ...int64) (result map[int64]*tag.Meta, leftIDs []int64) {
result = make(map[int64]*tag.Meta)
tagMutex.Lock()
for _, v := range ids {
var d, ok = TagCache[v]
if !ok {
leftIDs = append(leftIDs, v)
continue
}
result[v] = d
}
tagMutex.Unlock()
return
}

View File

@@ -0,0 +1,50 @@
package cache
import (
"go-common/app/interface/main/creative/model/tag"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestCacheClearTagCache(t *testing.T) {
convey.Convey("ClearTagCache", t, func(ctx convey.C) {
var (
tm = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
ClearTagCache(tm)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}
func TestCacheAddTagCache(t *testing.T) {
convey.Convey("AddTagCache", t, func(ctx convey.C) {
var (
meta = &tag.Meta{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
AddTagCache(meta)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}
func TestCacheGetTagCache(t *testing.T) {
convey.Convey("GetTagCache", t, func(ctx convey.C) {
var (
ids = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, leftIDs := GetTagCache(ids)
ctx.Convey("Then result,leftIDs should not be nil.", func(ctx convey.C) {
ctx.So(leftIDs, convey.ShouldNotBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,50 @@
package cache
import (
"context"
"go-common/app/admin/main/up/conf"
"go-common/app/service/main/videoup/model/archive"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"time"
)
var (
//VideoUpTypeCache cache for video types, map key is tid
VideoUpTypeCache = make(map[int]archive.Type)
)
//RefreshUpTypeAsync refresh in a goroutine
func RefreshUpTypeAsync(tm time.Time) {
go RefreshUpType(tm)
}
//RefreshUpType refresh
func RefreshUpType(tm time.Time) {
var url = conf.Conf.Host.Videoup + "/videoup/types"
var client = bm.NewClient(conf.Conf.HTTPClient.Normal)
var result struct {
Code int `json:"code"`
Data map[int]archive.Type `json:"data"`
}
var err = client.Get(context.Background(), url, "", nil, &result)
if err != nil {
log.Error("refresh videoup types fail, err=%v", err)
return
}
log.Info("refresh videoup types ok")
VideoUpTypeCache = result.Data
}
// GetTidName get tid name
func GetTidName(tids ...int64) (tpNames map[int64]string) {
tpNames = make(map[int64]string, len(tids))
for _, tid := range tids {
info, ok := VideoUpTypeCache[int(tid)]
if !ok {
continue
}
tpNames[tid] = info.Name
}
return
}

View File

@@ -0,0 +1,48 @@
package cache
import (
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestCacheRefreshUpTypeAsync(t *testing.T) {
convey.Convey("RefreshUpTypeAsync", t, func(ctx convey.C) {
var (
tm = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
RefreshUpTypeAsync(tm)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}
func TestCacheRefreshUpType(t *testing.T) {
convey.Convey("RefreshUpType", t, func(ctx convey.C) {
var (
tm = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
RefreshUpType(tm)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}
func TestCacheGetTidName(t *testing.T) {
convey.Convey("GetTidName", t, func(ctx convey.C) {
var (
tids = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
tpNames := GetTidName(tids)
ctx.Convey("Then tpNames should not be nil.", func(ctx convey.C) {
ctx.So(tpNames, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,57 @@
package service
import (
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/render"
"net/http"
)
//BmHTTPErrorWithMsg return customed message to client
func BmHTTPErrorWithMsg(c *bm.Context, err error, msg string) {
if c.IsAborted() {
return
}
c.Error = err
bcode := ecode.Cause(err)
if msg == "" {
msg = err.Error()
}
c.Render(http.StatusOK, render.JSON{
Code: bcode.Code(),
Message: msg,
Data: nil,
})
}
//BmGetStringOrDefault util to get string from context
func BmGetStringOrDefault(c *bm.Context, key string, defaul string) (value string, exist bool) {
i, exist := c.Get(key)
if !exist {
value = defaul
return
}
value, exist = i.(string)
if !exist {
value = defaul
}
return
}
//BmGetInt64OrDefault util to get int64 from context
func BmGetInt64OrDefault(c *bm.Context, key string, defaul int64) (value int64, exist bool) {
i, exist := c.Get(key)
if !exist {
value = defaul
return
}
value, exist = i.(int64)
if !exist {
value = defaul
}
return
}

View File

@@ -0,0 +1,57 @@
package service
import (
bm "go-common/library/net/http/blademaster"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestServiceBmHTTPErrorWithMsg(t *testing.T) {
convey.Convey("BmHTTPErrorWithMsg", t, func(ctx convey.C) {
var (
c = &bm.Context{}
err error
msg = ""
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
BmHTTPErrorWithMsg(c, err, msg)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}
func TestServiceBmGetStringOrDefault(t *testing.T) {
convey.Convey("BmGetStringOrDefault", t, func(ctx convey.C) {
var (
c = &bm.Context{}
key = ""
defaul = ""
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
value, exist := BmGetStringOrDefault(c, key, defaul)
ctx.Convey("Then value,exist should not be nil.", func(ctx convey.C) {
ctx.So(exist, convey.ShouldNotBeNil)
ctx.So(value, convey.ShouldNotBeNil)
})
})
})
}
func TestServiceBmGetInt64OrDefault(t *testing.T) {
convey.Convey("BmGetInt64OrDefault", t, func(ctx convey.C) {
var (
c = &bm.Context{}
key = ""
defaul = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
value, exist := BmGetInt64OrDefault(c, key, defaul)
ctx.Convey("Then value,exist should not be nil.", func(ctx convey.C) {
ctx.So(exist, convey.ShouldNotBeNil)
ctx.So(value, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,60 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"service.go",
"uparchiveinfo.go",
"viewer.go",
],
importpath = "go-common/app/admin/main/up/service/data",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//app/admin/main/up/dao/data:go_default_library",
"//app/admin/main/up/dao/tag:go_default_library",
"//app/admin/main/up/model/datamodel:go_default_library",
"//app/admin/main/up/service/cache:go_default_library",
"//app/admin/main/up/util:go_default_library",
"//app/interface/main/creative/model/tag:go_default_library",
"//library/log:go_default_library",
"//library/sync/errgroup:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = [
"service_test.go",
"uparchiveinfo_test.go",
"viewer_test.go",
],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//app/admin/main/up/model/datamodel:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,62 @@
package data
import (
"go-common/app/admin/main/up/conf"
"go-common/app/admin/main/up/dao/data"
"go-common/app/admin/main/up/dao/tag"
"time"
)
//Service data service
type Service struct {
c *conf.Config
data *data.Dao
dtag *tag.Dao
}
//New get service
func New(c *conf.Config) *Service {
s := &Service{
c: c,
data: data.New(c),
dtag: tag.New(c),
}
return s
}
func beginningOfDay(t time.Time) time.Time {
d := time.Duration(-t.Hour()) * time.Hour
return t.Truncate(time.Hour).Add(d)
}
func getTuesday(now time.Time) time.Time {
t := beginningOfDay(now)
weekday := int(t.Weekday())
if weekday == 0 {
weekday = 7
}
d := time.Duration(-weekday+2) * 24 * time.Hour
return t.Truncate(time.Hour).Add(d)
}
func getSunday(now time.Time) time.Time {
t := beginningOfDay(now)
weekday := int(t.Weekday())
if weekday == 0 {
return t
}
d := time.Duration(7-weekday) * 24 * time.Hour
return t.Truncate(time.Hour).Add(d)
}
func getDateLastSunday() (date time.Time) {
t := time.Now()
td := getTuesday(t).Add(12 * time.Hour)
if t.Before(td) { //当前时间在本周二12点之前则取上上周日的数据否则取上周日的数据
date = getSunday(t.AddDate(0, 0, -14))
} else {
date = getSunday(t.AddDate(0, 0, -7))
}
//log.Info("current time (%s) tuesday (%s) sunday (%s)", t.Format("2006-01-02 15:04:05"), td, sd)
return
}

View File

@@ -0,0 +1,23 @@
package data
import (
"flag"
"go-common/app/admin/main/up/conf"
"os"
"testing"
)
var (
s *Service
)
func TestMain(m *testing.M) {
flag.Set("conf", "../../cmd/up-admin.toml")
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
s = New(conf.Conf)
m.Run()
os.Exit(m.Run())
}

View File

@@ -0,0 +1,96 @@
package data
import (
"context"
"go-common/app/admin/main/up/dao/data"
"go-common/app/admin/main/up/model/datamodel"
"go-common/app/admin/main/up/util"
"go-common/library/log"
"sort"
"strconv"
)
//GetUpArchiveInfo get up archive info
func (s *Service) GetUpArchiveInfo(c context.Context, arg *datamodel.GetUpArchiveInfoArg) (result *datamodel.GetUpArchiveInfoResult, err error) {
if arg.DataType == 0 {
arg.DataType = datamodel.DataType30Day
}
result = &datamodel.GetUpArchiveInfoResult{}
var mids = util.ExplodeInt64(arg.Mids, ",")
var length = len(mids)
if length == 0 {
log.Info("no mids specified")
return
} else if length > 100 {
// 每次最多100个
mids = mids[0:100]
}
dataMap, err := s.data.UpArchiveInfo(c, mids, data.UpArchiveDataType(arg.DataType))
if err != nil {
log.Error("get up archive info fail, err=%v, arg=%+v", err, arg)
return
}
for mid, v := range dataMap {
(*result)[mid] = v
}
log.Info("get up archive info ok, type=%d", arg.DataType)
return
}
//GetUpArchiveTagInfo get up archive tag info
func (s *Service) GetUpArchiveTagInfo(c context.Context, arg *datamodel.GetUpArchiveTagInfoArg) (result []*datamodel.ViewerTagData, err error) {
tagData, err := s.data.UpArchiveTagInfo(c, arg.Mid)
if err != nil {
log.Error("get up archive tag fail, err=%v", err)
return
}
var tagResultMap = make(map[int64]*datamodel.ViewerTagData)
var tagIds []int64
for idxstr, tid := range tagData.TagMap {
tagIds = append(tagIds, tid)
var idx, _ = strconv.Atoi(idxstr)
var tag = &datamodel.ViewerTagData{
Idx: idx,
TagID: int(tid),
}
tagResultMap[tid] = tag
}
var tagMeta = s.GetTags(c, tagIds...)
for tid, meta := range tagMeta {
tag, ok := tagResultMap[tid]
if !ok {
continue
}
tag.Name = meta.TagName
}
for _, tag := range tagResultMap {
result = append(result, tag)
}
if len(result) > 1 {
sort.Slice(result, func(i, j int) bool {
return result[i].Idx < result[j].Idx
})
}
log.Info("get up archive tag info ok, mid=%d", arg.Mid)
return
}
//GetUpArchiveTypeInfo get type info
func (s *Service) GetUpArchiveTypeInfo(c context.Context, arg *datamodel.GetUpArchiveTypeInfoArg) (result *datamodel.UpArchiveTypeData, err error) {
res, err := s.data.UpArchiveTypeInfo(c, arg.Mid)
result = &res
if err != nil {
log.Error("fail to get up type, err=%v", err)
return
}
log.Info("get up archive type info ok, mid=%d", arg.Mid)
return
}

View File

@@ -0,0 +1,57 @@
package data
import (
"context"
"go-common/app/admin/main/up/model/datamodel"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDataGetUpArchiveInfo(t *testing.T) {
convey.Convey("GetUpArchiveInfo", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &datamodel.GetUpArchiveInfoArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.GetUpArchiveInfo(c, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestDataGetUpArchiveTagInfo(t *testing.T) {
convey.Convey("GetUpArchiveTagInfo", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &datamodel.GetUpArchiveTagInfoArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.GetUpArchiveTagInfo(c, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestDataGetUpArchiveTypeInfo(t *testing.T) {
convey.Convey("GetUpArchiveTypeInfo", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &datamodel.GetUpArchiveTypeInfoArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.GetUpArchiveTypeInfo(c, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,234 @@
package data
import (
"context"
"fmt"
"time"
"go-common/app/admin/main/up/model/datamodel"
"go-common/app/admin/main/up/service/cache"
"go-common/app/interface/main/creative/model/tag"
"go-common/library/log"
"go-common/library/sync/errgroup"
)
// ViewerBase get up viewer base data.
func (s *Service) ViewerBase(c context.Context, mid int64) (res *datamodel.ViewerBaseInfo, err error) {
dt := getDateLastSunday()
if res, err = s.data.ViewerBase(c, mid, dt); err != nil {
log.Error("get viewer base error, err=%v", err)
return
}
return
}
// ViewerArea get up viewer area data.
func (s *Service) ViewerArea(c context.Context, mid int64) (res *datamodel.ViewerAreaInfo, err error) {
dt := getDateLastSunday()
res, err = s.data.ViewerArea(c, mid, dt)
if err != nil {
log.Error("get viewer area error, err=%v", err)
return
}
return
}
// CacheTrend get trend from mc.
func (s *Service) CacheTrend(c context.Context, mid int64) (res *datamodel.ViewerTrendInfo, err error) {
dt := getDateLastSunday()
if res, err = s.viewerTrend(c, mid, dt); err != nil {
return
}
return
}
//GetTags get tag
func (s *Service) GetTags(c context.Context, ids ...int64) (result map[int64]*tag.Meta) {
var tagMetaMap, leftIDs = cache.GetTagCache(ids...)
if len(leftIDs) > 0 {
if tlist, err := s.dtag.TagList(c, leftIDs); err != nil {
log.Error("trend s.dtag.TagList err(%v)", err)
} else {
for _, v := range tlist {
tagMetaMap[v.TagID] = v
cache.AddTagCache(v)
}
}
}
result = tagMetaMap
return
}
// ViewerTrend get up viewer trend data.
func (s *Service) viewerTrend(c context.Context, mid int64, dt time.Time) (res *datamodel.ViewerTrendInfo, err error) {
ut, err := s.data.ViewerTrend(c, mid, dt)
if err != nil || ut == nil {
log.Error("trend s.data.ViewerTrend err(%v)", err)
return
}
f := []string{"fan", "guest"}
skeys := make([]int, 0) //for tag sort.
tgs := make([]int64, 0) // for request tag name.
res = &datamodel.ViewerTrendInfo{}
var dataMap = make(map[string]*datamodel.ViewerTypeTagInfo)
for _, fk := range f {
td := ut[fk]
vt := &datamodel.ViewerTypeTagInfo{}
if td == nil {
vt.Type = nil
vt.Tag = nil
dataMap[fk] = vt
continue
}
typeMap := make(map[int]*datamodel.ViewerTypeData) //return type map to user.
//deal type for type name.
if td.Ty != nil {
for k, v := range td.Ty {
var tagInfo, ok = cache.VideoUpTypeCache[k]
var name = ""
if ok {
name = tagInfo.Name
}
typeMap[k] = &datamodel.ViewerTypeData{
Tid: k,
Name: name,
Play: v,
}
}
} else {
typeMap = nil
}
// deal tag for tag name.
if td.Tag != nil {
for k, v := range td.Tag {
tgs = append(tgs, v)
skeys = append(skeys, k)
}
var tagMetaMap, leftIDs = cache.GetTagCache(tgs...)
if len(leftIDs) > 0 {
var tlist []*tag.Meta
if tlist, err = s.dtag.TagList(c, leftIDs); err != nil {
log.Error("trend s.dtag.TagList err(%v)", err)
} else {
for _, v := range tlist {
tagMetaMap[v.TagID] = v
cache.AddTagCache(v)
}
}
}
for _, k := range skeys {
var tagID = td.Tag[k]
var tagData = &datamodel.ViewerTagData{
Idx: k,
TagID: int(tagID),
Name: "",
}
if tagMeta, ok := tagMetaMap[tagID]; ok {
tagData.Name = tagMeta.TagName
}
vt.Tag = append(vt.Tag, tagData)
}
}
for _, v := range typeMap {
vt.Type = append(vt.Type, v)
}
dataMap[fk] = vt
}
res.Fans = dataMap["fan"]
res.Guest = dataMap["guest"]
return
}
//ViewData view data for up
type ViewData struct {
Base *datamodel.ViewerBaseInfo `json:"viewer_base"`
Trend *datamodel.ViewerTrendInfo `json:"viewer_trend"`
Area *datamodel.ViewerAreaInfo `json:"viewer_area"`
}
//GetUpViewInfo get view info by arg
func (s *Service) GetUpViewInfo(c context.Context, arg *datamodel.GetUpViewInfoArg) (result *ViewData, err error) {
if arg == nil {
log.Error("arg is nil")
return
}
res, err := s.GetViewData(c, arg.Mid)
result = &res
return
}
//GetViewData get all view data
func (s *Service) GetViewData(c context.Context, mid int64) (result ViewData, err error) {
var group, ctx = errgroup.WithContext(c)
group.Go(func() error {
var e error
result.Base, e = s.ViewerBase(ctx, mid)
if e != nil {
log.Error("get base view err happen, err=%v", e)
}
return nil
})
group.Go(func() error {
var e error
result.Area, e = s.ViewerArea(ctx, mid)
if e != nil {
log.Error("get area view err happen, err=%v", e)
}
return nil
})
group.Go(func() error {
var e error
result.Trend, e = s.CacheTrend(ctx, mid)
if e != nil {
log.Error("get trend view err happen, err=%v", e)
}
return nil
})
err = group.Wait()
if err != nil {
log.Error("get view data error, err=%+v", err)
}
return
}
//GetFansSummary get fan summary
func (s *Service) GetFansSummary(c context.Context, arg *datamodel.GetFansSummaryArg) (result *datamodel.FansSummaryResult, err error) {
result = &datamodel.FansSummaryResult{}
var fanInfo, e = s.data.UpFansAnalysis(c, arg.Mid, datamodel.Thirty)
if e != nil || fanInfo == nil {
err = e
log.Error("get fan analysis err happen, err=%v", e)
return
}
result.FanSummary = fanInfo.Summary
return
}
//GetRelationFansDay get fan day history
func (s *Service) GetRelationFansDay(c context.Context, arg *datamodel.GetRelationFansHistoryArg) (result *datamodel.GetRelationFansHistoryResult, err error) {
result = &datamodel.GetRelationFansHistoryResult{}
if arg.DataType == 0 {
arg.DataType = datamodel.DataType30Day
}
switch arg.DataType {
case datamodel.DataType30Day:
result.RelationFanHistoryData, err = s.data.RelationFansDay(c, arg.Mid)
case datamodel.DataTypeMonth:
result.RelationFanHistoryData, err = s.data.RelationFansMonth(c, arg.Mid)
default:
err = fmt.Errorf("invalid data type(%d)", arg.DataType)
}
if err != nil {
log.Error("get relation fans day fail, err=%v", err)
return
}
return
}

View File

@@ -0,0 +1,154 @@
package data
import (
"context"
"go-common/app/admin/main/up/model/datamodel"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestDataViewerBase(t *testing.T) {
convey.Convey("ViewerBase", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := s.ViewerBase(c, mid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDataViewerArea(t *testing.T) {
convey.Convey("ViewerArea", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := s.ViewerArea(c, mid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDataCacheTrend(t *testing.T) {
convey.Convey("CacheTrend", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := s.CacheTrend(c, mid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDataGetTags(t *testing.T) {
convey.Convey("GetTags", t, func(ctx convey.C) {
var (
c = context.Background()
ids = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result := s.GetTags(c, ids)
ctx.Convey("Then result should not be nil.", func(ctx convey.C) {
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestDataviewerTrend(t *testing.T) {
convey.Convey("viewerTrend", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
dt = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := s.viewerTrend(c, mid, dt)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDataGetUpViewInfo(t *testing.T) {
convey.Convey("GetUpViewInfo", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &datamodel.GetUpViewInfoArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.GetUpViewInfo(c, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestDataGetViewData(t *testing.T) {
convey.Convey("GetViewData", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.GetViewData(c, mid)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestDataGetFansSummary(t *testing.T) {
convey.Convey("GetFansSummary", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &datamodel.GetFansSummaryArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.GetFansSummary(c, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestDataGetRelationFansDay(t *testing.T) {
convey.Convey("GetRelationFansDay", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &datamodel.GetRelationFansHistoryArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.GetRelationFansDay(c, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,99 @@
package service
import (
"context"
"sync"
"time"
"go-common/app/admin/main/up/conf"
"go-common/app/admin/main/up/dao/global"
"go-common/app/admin/main/up/dao/manager"
"go-common/app/admin/main/up/service/upcrmservice"
"go-common/app/admin/main/up/util"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/stat/prom"
)
// Service is service.
type Service struct {
c *conf.Config
mng *manager.Dao
// databus sub
//upSub *databus.Databus
// wait group
wg sync.WaitGroup
// chan for mids
//midsChan chan map[int64]int
//for cache func
missch chan func()
//prom
pCacheHit *prom.Prom
pCacheMiss *prom.Prom
tokenMX sync.Mutex
changeMX sync.Mutex
tokenChan chan int
httpClient *bm.Client
Crmservice *upcrmservice.Service
}
// New is go-common/business/service/videoup service implementation.
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
mng: manager.New(c),
//upSub: databus.New(c.UpSub.Config),
//midsChan: make(chan map[int64]int, c.ChanSize),
//upChan: make(chan *model.Msg, c.UpSub.UpChanSize),
//consumeToken: time.Now().UnixNano(),
//consumeRate: int64(1e9 / c.UpSub.ConsumeLimit),
tokenMX: sync.Mutex{},
missch: make(chan func(), 1024),
pCacheHit: prom.CacheHit,
pCacheMiss: prom.CacheMiss,
changeMX: sync.Mutex{},
tokenChan: make(chan int, 10),
httpClient: bm.NewClient(c.HTTPClient.Normal),
Crmservice: upcrmservice.New(c),
}
s.mng.HTTPClient = s.httpClient
s.Crmservice.SetHTTPClient(s.httpClient)
global.Init(c)
// load for first time
s.refreshCache()
go s.cacheproc()
go s.timerproc()
return s
}
func (s *Service) refreshCache() {
log.Info("refresh cache")
}
func (s *Service) cacheproc() {
for {
time.Sleep(5 * time.Minute)
s.refreshCache()
}
}
// Ping service
func (s *Service) Ping(c context.Context) (err error) {
return
}
// Close sub.
func (s *Service) Close() {
//close(s.midsChan)
s.wg.Wait()
s.mng.Close()
}
// AddCache add to chan for cache
func (s *Service) timerproc() {
var t = time.NewTicker(time.Second)
for now := range t.C {
util.GlobalTimer.Advance(now)
}
}

View File

@@ -0,0 +1,23 @@
package service
import (
"flag"
"go-common/app/admin/main/up/conf"
"os"
"testing"
)
var (
s *Service
)
func TestMain(m *testing.M) {
flag.Set("conf", "../cmd/up-admin.toml")
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
s = New(conf.Conf)
m.Run()
os.Exit(m.Run())
}

View File

@@ -0,0 +1,95 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"audit_log_test.go",
"command_test.go",
"credit_log_test.go",
"play_info_test.go",
"scoresection_test.go",
"sign_up_test.go",
"up_base_info_test.go",
"up_rank_test.go",
"up_stat_history_test.go",
"upcrmservice_test.go",
"utils_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//app/admin/main/up/model:go_default_library",
"//app/admin/main/up/model/signmodel:go_default_library",
"//app/admin/main/up/model/upcrmmodel:go_default_library",
"//vendor/github.com/jinzhu/gorm:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"audit_log.go",
"command.go",
"credit_log.go",
"play_info.go",
"scoresection.go",
"sign_up.go",
"up_base_info.go",
"up_rank.go",
"up_stat_history.go",
"upcrmservice.go",
"utils.go",
],
importpath = "go-common/app/admin/main/up/service/upcrmservice",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//app/admin/main/up/dao/email:go_default_library",
"//app/admin/main/up/dao/global:go_default_library",
"//app/admin/main/up/dao/manager:go_default_library",
"//app/admin/main/up/dao/upcrm:go_default_library",
"//app/admin/main/up/model:go_default_library",
"//app/admin/main/up/model/datamodel:go_default_library",
"//app/admin/main/up/model/signmodel:go_default_library",
"//app/admin/main/up/model/upcrmmodel:go_default_library",
"//app/admin/main/up/service/cache:go_default_library",
"//app/admin/main/up/service/data:go_default_library",
"//app/admin/main/up/util:go_default_library",
"//app/admin/main/up/util/mathutil:go_default_library",
"//app/admin/main/up/util/timerqueue:go_default_library",
"//app/service/main/account/api:go_default_library",
"//library/database/elastic:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/metadata:go_default_library",
"//library/queue/databus/report:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/jinzhu/gorm:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,32 @@
package upcrmservice
import (
"time"
"go-common/library/log"
manager "go-common/library/queue/databus/report"
)
// AddAuditLog .
func (s *Service) AddAuditLog(bizID int, tp int8, action string, uid int64, uname string, oids []int64, index []interface{}, content map[string]interface{}) error {
var err error
for _, oid := range oids {
managerInfo := &manager.ManagerInfo{
UID: uid,
Uname: uname,
Business: bizID,
Type: int(tp),
Action: action,
Oid: oid,
Ctime: time.Now(),
Index: index,
Content: content,
}
if err = manager.Manager(managerInfo); err != nil {
log.Error("manager.Manager(%+v) error(%+v)", managerInfo, err)
continue
}
log.Info("s.managerSendLog(%+v)", managerInfo)
}
return err
}

View File

@@ -0,0 +1,28 @@
package upcrmservice
import (
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestUpcrmserviceAddAuditLog(t *testing.T) {
convey.Convey("AddAuditLog", t, func(ctx convey.C) {
var (
bizID = int(0)
tp = int8(0)
action = ""
uid = int64(0)
uname = ""
oids = []int64{}
index = []interface{}{}
content map[string]interface{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := s.AddAuditLog(bizID, tp, action, uid, uname, oids, index, content)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,13 @@
package upcrmservice
import (
"context"
"go-common/app/admin/main/up/model"
"time"
)
//CommandRefreshUpRank refresh up rank
func (s *Service) CommandRefreshUpRank(con context.Context, arg *model.CommandCommonArg) (result model.CommandCommonResult, err error) {
s.RefreshCache(time.Now())
return
}

View File

@@ -0,0 +1,25 @@
package upcrmservice
import (
"context"
"go-common/app/admin/main/up/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestUpcrmserviceCommandRefreshUpRank(t *testing.T) {
convey.Convey("CommandRefreshUpRank", t, func(ctx convey.C) {
var (
con = context.Background()
arg = &model.CommandCommonArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.CommandRefreshUpRank(con, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,46 @@
package upcrmservice
import (
"context"
"fmt"
"go-common/app/admin/main/up/model/upcrmmodel"
"go-common/library/log"
)
func formatLog(log upcrmmodel.SimpleCreditLogWithContent) (result upcrmmodel.CreditLogInfo) {
var timeStr = log.CTime.Time().Format(upcrmmodel.TimeFmtDate)
switch log.BusinessType {
case upcrmmodel.BusinessTypeArticleAudit:
result.Log = fmt.Sprintf("[%s][aid=%d]%s", timeStr, log.Oid, log.Content)
default:
result.Log = fmt.Sprintf("[%s]%s", timeStr, log.Content)
}
result.Time = log.CTime
return
}
//CreditLogQueryUp query credit log
func (s *Service) CreditLogQueryUp(context context.Context, arg *upcrmmodel.CreditLogQueryArgs) (result upcrmmodel.CreditLogUpResult, err error) {
if arg.Limit <= 0 {
arg.Limit = 20
} else if arg.Limit >= 100 {
arg.Limit = 100
}
logs, e := s.crmdb.GetCreditLog(arg.Mid, arg.Limit)
err = e
if err != nil {
log.Error("credit log get fail, err=%+v", err)
return
}
for _, v := range logs {
//if v == nil {
// continue
//}
result.Logs = append(result.Logs, formatLog(v))
}
log.Info("credit log get ok, mid=%d, length=%d", arg.Mid, len(logs))
return
}

View File

@@ -0,0 +1,39 @@
package upcrmservice
import (
"context"
"go-common/app/admin/main/up/model/upcrmmodel"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestUpcrmserviceformatLog(t *testing.T) {
convey.Convey("formatLog", t, func(ctx convey.C) {
var (
log upcrmmodel.SimpleCreditLogWithContent
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result := formatLog(log)
ctx.Convey("Then result should not be nil.", func(ctx convey.C) {
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceCreditLogQueryUp(t *testing.T) {
convey.Convey("CreditLogQueryUp", t, func(ctx convey.C) {
var (
context = context.Background()
arg = &upcrmmodel.CreditLogQueryArgs{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.CreditLogQueryUp(context, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,51 @@
package upcrmservice
import (
"context"
"errors"
"go-common/app/admin/main/up/model/upcrmmodel"
"go-common/library/ecode"
"go-common/library/log"
)
//PlayQueryInfo handle PlayQueryInfo
func (s *Service) PlayQueryInfo(context context.Context, arg *upcrmmodel.PlayQueryArgs) (result upcrmmodel.PlayQueryResult, err error) {
var types []int
switch arg.BusinessType {
case 0:
types = append(types, upcrmmodel.BusinessTypeVideo, upcrmmodel.BusinessTypeAudio, upcrmmodel.BusinessTypeArticle)
case upcrmmodel.BusinessTypeVideo, upcrmmodel.BusinessTypeAudio, upcrmmodel.BusinessTypeArticle:
types = append(types, arg.BusinessType)
default:
err = errors.New("business type not support")
return
}
playData, e := s.crmdb.QueryPlayInfo(arg.Mid, types)
err = e
if err != nil && err != ecode.NothingFound {
log.Error("fail to get from db, err=%+v", err)
return
}
if err == ecode.NothingFound {
err = nil
log.Warn("up not found in play info db, mid=%d", arg.Mid)
}
for _, v := range playData {
result.BusinessData = append(result.BusinessData, upcrmmodel.CastUpPlayInfoToPlayInfo(v))
}
// 去查up_base_info以获取总稿件量
baseInfo, e := s.crmdb.QueryUpBaseInfo(arg.Mid, "article_count_accumulate, article_count_30day")
err = e
if err == nil {
result.ArticleCount30Day = baseInfo.ArticleCount30day
result.ArticleCountAccumulate = baseInfo.ArticleCountAccumulate
} else if err == ecode.NothingFound {
err = nil
log.Warn("up base info not found, mid=%d", arg.Mid)
}
log.Info("get play info ok, mid=%d", arg.Mid)
return
}

View File

@@ -0,0 +1,25 @@
package upcrmservice
import (
"context"
"go-common/app/admin/main/up/model/upcrmmodel"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestUpcrmservicePlayQueryInfo(t *testing.T) {
convey.Convey("PlayQueryInfo", t, func(ctx convey.C) {
var (
context = context.Background()
arg = &upcrmmodel.PlayQueryArgs{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.PlayQueryInfo(context, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,260 @@
package upcrmservice
import (
"context"
"errors"
"fmt"
"time"
"go-common/app/admin/main/up/dao/upcrm"
"go-common/app/admin/main/up/model/upcrmmodel"
"go-common/library/ecode"
"go-common/library/log"
xtime "go-common/library/time"
"github.com/jinzhu/gorm"
)
func convertValueList(score upcrmmodel.ScoreSectionHistory) []upcrmmodel.ScoreSection {
var values []int
values = append(values, score.Section0)
values = append(values, score.Section1)
values = append(values, score.Section2)
values = append(values, score.Section3)
values = append(values, score.Section4)
values = append(values, score.Section5)
values = append(values, score.Section6)
values = append(values, score.Section7)
values = append(values, score.Section8)
values = append(values, score.Section9)
var list []upcrmmodel.ScoreSection
var total = 0
for i, v := range values {
var newsection = upcrmmodel.ScoreSection{
Section: i,
Value: v,
}
list = append(list, newsection)
total += v
}
if total > 0 {
for i := range list {
list[i].Percent = int(float32(list[i].Value) * 10000.0 / float32(total))
}
}
return list
}
func generateScoreQueryXAxis(num int) (axis []string) {
if num == 0 {
return
}
axis = append(axis, fmt.Sprintf("%d-%d", 0, 100))
for i := 1; i < num; i++ {
axis = append(axis, fmt.Sprintf("%d-%d", i*100+1, (i+1)*100))
}
return
}
//ScoreQuery query score
func (s *Service) ScoreQuery(context context.Context, arg *upcrmmodel.ScoreQueryArgs) (result upcrmmodel.ScoreQueryResult, err error) {
var today = time.Now()
var yesterday, e = s.crmdb.GetLastHistory(arg.ScoreType)
result = upcrmmodel.NewEmptyScoreQueryResult()
err = e
if err == ecode.NothingFound {
log.Info("no record found in db, arg=%+v", arg)
err = nil
return
}
if err != nil {
log.Error("fail get last history, arg=%+v, err=%+v", arg, err)
return
}
yesterdayData, e := s.crmdb.ScoreQueryHistory(arg.ScoreType, yesterday)
err = e
// orm.go 里修改了gorm.ErrRecordNotFound
if err != nil {
log.Error("fail query score history, err=%+v", err)
return
}
result.XAxis = generateScoreQueryXAxis(10)
result.YAxis = convertValueList(yesterdayData)
var comparedate time.Time
// 获取对比数据
switch arg.CompareType {
case upcrmmodel.CompareTypeNothing:
break
case upcrmmodel.CompareType7day:
comparedate = yesterday.AddDate(0, 0, -7)
case upcrmmodel.CompareType30day:
comparedate = yesterday.AddDate(0, 0, -30)
case upcrmmodel.CompareTypeMonthFirstDay:
y, m, _ := today.Date()
comparedate = time.Date(y, m, 1, 0, 0, 0, 0, today.Location())
}
if !comparedate.IsZero() {
var compareData, e = s.crmdb.ScoreQueryHistory(arg.ScoreType, comparedate)
err = e
// orm.go 里修改了gorm.ErrRecordNotFound
if err != nil {
log.Error("fail query score history, err=%+v", err)
return
}
result.CompareAxis = convertValueList(compareData)
}
log.Info("result=%+v", result)
return
}
func calcScoreInfo(datamap map[int8]map[time.Time]upcrmmodel.UpScoreHistory, stype int8, todate time.Time, fromdate time.Time) (info upcrmmodel.ScoreInfo) {
var typeMap map[time.Time]upcrmmodel.UpScoreHistory
var ok bool
if typeMap, ok = datamap[stype]; !ok {
log.Error("score type not found, type=%d", stype)
return
}
var currentData upcrmmodel.UpScoreHistory
if currentData, ok = typeMap[todate]; !ok {
log.Error("score type for todate not exist, todate=%v", todate)
return
}
info.Current = currentData.Score
var lastScore = 0
if lastData, ok := typeMap[fromdate]; ok {
lastScore = lastData.Score
}
info.DiffLastDay = info.Current - lastScore
return
}
func generateDataMap(scoreHistory []upcrmmodel.UpScoreHistory) map[int8]map[time.Time]upcrmmodel.UpScoreHistory {
var dataMap = map[int8]map[time.Time]upcrmmodel.UpScoreHistory{}
for _, v := range scoreHistory {
var typeMap map[time.Time]upcrmmodel.UpScoreHistory
var ok bool
if typeMap, ok = dataMap[v.ScoreType]; !ok {
typeMap = map[time.Time]upcrmmodel.UpScoreHistory{}
dataMap[v.ScoreType] = typeMap
}
typeMap[GetDateStamp(v.GenerateDate.Time())] = v
}
return dataMap
}
func getDataFromMap(dataMap map[int8]map[time.Time]upcrmmodel.UpScoreHistory, scoreType int, date time.Time) (data upcrmmodel.UpScoreHistory, ok bool) {
var mapDate, o = dataMap[int8(scoreType)]
ok = o
if !ok {
return
}
data, ok = mapDate[date]
return
}
//ScoreQueryUp query up score
func (s *Service) ScoreQueryUp(context context.Context, arg *upcrmmodel.ScoreQueryUpArgs) (result upcrmmodel.ScoreQueryUpResult, err error) {
var now = time.Now()
var todate = GetDateStamp(now)
if arg.Date != "" {
todate, err = time.ParseInLocation(upcrmmodel.TimeFmtDate, arg.Date, now.Location())
if err != nil {
log.Error("fail to parse date, date=%s", arg.Date)
return
}
}
var latestDate, e = s.crmdb.GetLatestUpScoreDate(arg.Mid, upcrm.ScoreTypePr, todate)
if e != nil && e != gorm.ErrRecordNotFound {
err = e
return
}
todate = latestDate
var fromdate = GetDateStamp(todate.AddDate(0, 0, -1))
log.Info("query up's score all")
var scoreHistory []upcrmmodel.UpScoreHistory
scoreHistory, err = s.crmdb.QueryUpScoreHistory(arg.Mid, []int{upcrm.ScoreTypePr, upcrm.ScoreTypeQuality, upcrm.ScoreTypeCredit}, fromdate, todate)
if err != nil {
log.Error("query up score error, err=%+v", err)
return
}
var dataMap = generateDataMap(scoreHistory)
// 计算数据
result.PrScore = calcScoreInfo(dataMap, upcrm.ScoreTypePr, todate, fromdate)
result.QualityScore = calcScoreInfo(dataMap, upcrm.ScoreTypeQuality, todate, fromdate)
result.CreditScore = calcScoreInfo(dataMap, upcrm.ScoreTypeCredit, todate, fromdate)
result.Date = xtime.Time(todate.Unix())
log.Info("score history ok req=%+v, result=%+v", arg, result)
return
}
//ScoreQueryUpHistory query up history
func (s *Service) ScoreQueryUpHistory(context context.Context, arg *upcrmmodel.ScoreQueryUpHistoryArgs) (result upcrmmodel.ScoreQueryUpHistoryResult, err error) {
var now = time.Now()
var todate = now
if arg.Date != "" {
todate, err = time.ParseInLocation(upcrmmodel.TimeFmtDate, arg.Date, now.Location())
if err != nil {
log.Error("parse time fail, err=%+v", err)
return
}
}
switch arg.Day {
case 7, 30, 90:
break
default:
arg.Day = 7
}
latestDate, e := s.crmdb.GetLatestUpScoreDate(arg.Mid, upcrm.ScoreTypePr, todate)
if e != nil && e != gorm.ErrRecordNotFound {
err = e
return
}
todate = latestDate
var fromdate = todate.AddDate(0, 0, 1-arg.Day)
var types []int
switch arg.ScoreType {
case 0:
types = append(types, upcrm.ScoreTypePr, upcrm.ScoreTypeQuality, upcrm.ScoreTypeCredit)
case upcrm.ScoreTypePr, upcrm.ScoreTypeQuality, upcrm.ScoreTypeCredit:
types = append(types, arg.ScoreType)
default:
err = errors.New("score type not support")
return
}
scoreHistory, e := s.crmdb.QueryUpScoreHistory(arg.Mid, types, fromdate, todate)
err = e
if err != nil {
log.Error("query up score error, err=%+v", err)
return
}
var dataMap = generateDataMap(scoreHistory)
// 产生历史列表数据
var dateSeries []xtime.Time
var origDateSeries []time.Time
for start := fromdate; !start.After(todate); start = start.AddDate(0, 0, 1) {
var onlyDate = GetDateStamp(start)
origDateSeries = append(origDateSeries, onlyDate)
dateSeries = append(dateSeries, xtime.Time(onlyDate.Unix()))
}
//result.ScoreData = []
for _, t := range types {
var typehistory upcrmmodel.ScoreHistoryInfo
typehistory.Type = t
typehistory.Date = dateSeries
for _, date := range origDateSeries {
// 如果没有找到就用默认的score = 0
var score, _ = getDataFromMap(dataMap, t, date)
typehistory.Score = append(typehistory.Score, score.Score)
}
result.ScoreData = append(result.ScoreData, typehistory)
}
log.Info("query up history sucessful, arg=%+v, result=%+v", arg, result)
return
}

View File

@@ -0,0 +1,135 @@
package upcrmservice
import (
"context"
"testing"
"time"
"go-common/app/admin/main/up/model/upcrmmodel"
"github.com/smartystreets/goconvey/convey"
)
func TestUpcrmserviceconvertValueList(t *testing.T) {
convey.Convey("convertValueList", t, func(ctx convey.C) {
var (
score upcrmmodel.ScoreSectionHistory
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := convertValueList(score)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmservicegenerateScoreQueryXAxis(t *testing.T) {
convey.Convey("generateScoreQueryXAxis", t, func(ctx convey.C) {
var (
num = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
axis := generateScoreQueryXAxis(num)
ctx.Convey("Then axis should not be nil.", func(ctx convey.C) {
ctx.So(axis, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceScoreQuery(t *testing.T) {
convey.Convey("ScoreQuery", t, func(ctx convey.C) {
var (
context = context.Background()
arg = &upcrmmodel.ScoreQueryArgs{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.ScoreQuery(context, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmservicecalcScoreInfo(t *testing.T) {
convey.Convey("calcScoreInfo", t, func(ctx convey.C) {
var (
datamap map[int8]map[time.Time]upcrmmodel.UpScoreHistory
stype = int8(0)
todate = time.Now()
fromdate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
info := calcScoreInfo(datamap, stype, todate, fromdate)
ctx.Convey("Then info should not be nil.", func(ctx convey.C) {
ctx.So(info, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmservicegenerateDataMap(t *testing.T) {
convey.Convey("generateDataMap", t, func(ctx convey.C) {
var (
scoreHistory = []upcrmmodel.UpScoreHistory{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := generateDataMap(scoreHistory)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmservicegetDataFromMap(t *testing.T) {
convey.Convey("getDataFromMap", t, func(ctx convey.C) {
var (
dataMap map[int8]map[time.Time]upcrmmodel.UpScoreHistory
scoreType = int(0)
date = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
data, ok := getDataFromMap(dataMap, scoreType, date)
ctx.Convey("Then data,ok should not be nil.", func(ctx convey.C) {
ctx.So(ok, convey.ShouldNotBeNil)
ctx.So(data, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceScoreQueryUp(t *testing.T) {
convey.Convey("ScoreQueryUp", t, func(ctx convey.C) {
var (
context = context.Background()
arg = &upcrmmodel.ScoreQueryUpArgs{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.ScoreQueryUp(context, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceScoreQueryUpHistory(t *testing.T) {
convey.Convey("ScoreQueryUpHistory", t, func(ctx convey.C) {
var (
context = context.Background()
arg = &upcrmmodel.ScoreQueryUpHistoryArgs{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.ScoreQueryUpHistory(context, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,299 @@
package upcrmservice
import (
"context"
"testing"
"go-common/app/admin/main/up/model/signmodel"
"github.com/jinzhu/gorm"
"github.com/smartystreets/goconvey/convey"
)
func TestUpcrmserviceSignUpAuditLogs(t *testing.T) {
convey.Convey("SignUpAuditLogs", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &signmodel.SignOpSearchArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := s.SignUpAuditLogs(c, arg)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceSignAdd(t *testing.T) {
convey.Convey("SignAdd", t, func(ctx convey.C) {
var (
context = context.Background()
arg = &signmodel.SignUpArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.SignAdd(context, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceSignUpdate(t *testing.T) {
convey.Convey("SignUpdate", t, func(ctx convey.C) {
var (
context = context.Background()
arg = &signmodel.SignUpArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.SignUpdate(context, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceViolationAdd(t *testing.T) {
convey.Convey("ViolationAdd", t, func(ctx convey.C) {
var (
context = context.Background()
arg = &signmodel.ViolationArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.ViolationAdd(context, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceViolationRetract(t *testing.T) {
convey.Convey("ViolationRetract", t, func(ctx convey.C) {
var (
context = context.Background()
arg = &signmodel.IDArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.ViolationRetract(context, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceViolationList(t *testing.T) {
convey.Convey("ViolationList", t, func(ctx convey.C) {
var (
context = context.Background()
arg = &signmodel.PageArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.ViolationList(context, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceAbsenceAdd(t *testing.T) {
convey.Convey("AbsenceAdd", t, func(ctx convey.C) {
var (
context = context.Background()
arg = &signmodel.AbsenceArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.AbsenceAdd(context, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmservicegetOrCreateTaskHistory(t *testing.T) {
convey.Convey("getOrCreateTaskHistory", t, func(ctx convey.C) {
var (
tx = &gorm.DB{}
signID = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := s.getOrCreateTaskHistory(tx, signID)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceAbsenceRetract(t *testing.T) {
convey.Convey("AbsenceRetract", t, func(ctx convey.C) {
var (
context = context.Background()
arg = &signmodel.IDArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.AbsenceRetract(context, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceAbsenceList(t *testing.T) {
convey.Convey("AbsenceList", t, func(ctx convey.C) {
var (
context = context.Background()
arg = &signmodel.PageArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.AbsenceList(context, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceViewCheck(t *testing.T) {
convey.Convey("ViewCheck", t, func(ctx convey.C) {
var (
context = context.Background()
arg = &signmodel.PowerCheckArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := s.ViewCheck(context, arg)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceaddPayInfo(t *testing.T) {
convey.Convey("addPayInfo", t, func(ctx convey.C) {
var (
tx = &gorm.DB{}
arg = &signmodel.SignPayInfoArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
id, err := s.addPayInfo(tx, arg)
ctx.Convey("Then err should be nil.id should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(id, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceaddTaskInfo(t *testing.T) {
convey.Convey("addTaskInfo", t, func(ctx convey.C) {
var (
tx = &gorm.DB{}
arg = &signmodel.SignTaskInfoArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
id, err := s.addTaskInfo(tx, arg)
ctx.Convey("Then err should be nil.id should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(id, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceaddContractInfo(t *testing.T) {
convey.Convey("addContractInfo", t, func(ctx convey.C) {
var (
tx = &gorm.DB{}
arg = &signmodel.SignContractInfoArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
id, err := s.addContractInfo(tx, arg)
ctx.Convey("Then err should be nil.id should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(id, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceSignQuery(t *testing.T) {
convey.Convey("SignQuery", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &signmodel.SignQueryArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := s.SignQuery(c, arg)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceSignQueryID(t *testing.T) {
convey.Convey("SignQueryID", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &signmodel.SignIDArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := s.SignQueryID(c, arg)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceSignPayComplete(t *testing.T) {
convey.Convey("SignPayComplete", t, func(ctx convey.C) {
var (
con = context.Background()
arg = &signmodel.SignPayCompleteArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.SignPayComplete(con, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceSignCheckExist(t *testing.T) {
convey.Convey("SignCheckExist", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &signmodel.SignCheckExsitArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.SignCheckExist(c, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,444 @@
package upcrmservice
import (
"context"
"errors"
"sync"
"time"
"go-common/app/admin/main/up/dao/global"
"go-common/app/admin/main/up/model/datamodel"
"go-common/app/admin/main/up/model/upcrmmodel"
"go-common/app/admin/main/up/util"
accgrpc "go-common/app/service/main/account/api"
"go-common/library/database/elastic"
"go-common/library/log"
"go-common/library/net/metadata"
"go-common/library/sync/errgroup"
)
const (
maxSearchItemCount = 10000
maxBatchCount = 100
)
var (
//ErrTooManySearchItem too many search items, 搜索只支持返回前10000条数据
ErrTooManySearchItem = errors.New("筛选仅支持展示前1万条")
//ErrNoMid no mid
ErrNoMid = errors.New("Mid为空")
)
//UpBaseInfoQuery query
func (s *Service) UpBaseInfoQuery(context context.Context, arg *upcrmmodel.InfoQueryArgs) (result *upcrmmodel.InfoQueryResult, err error) {
var data, e = s.upBaseInfoQueryBatch(s.crmdb.QueryUpBaseInfoBatchByMid, arg.Mid)
err = e
// 没找到按照错误处理
if err != nil || len(data) == 0 {
log.Error("get from db fail, req=%+v, err=%+v", arg, err)
return
}
result = data[0]
log.Info("query base info ok, req=%+v, err=%+v", arg, result)
return
}
//QueryDbFunc query func type
type QueryDbFunc func(fields string, mid ...int64) (result []upcrmmodel.UpBaseInfo, err error)
func (s *Service) upBaseInfoQueryBatch(queryfunc QueryDbFunc, ids ...int64) (result []*upcrmmodel.InfoQueryResult, err error) {
var data, e = queryfunc("*", ids...)
err = e
if err != nil {
log.Error("get from db fail, err=%+v", err)
return
}
for _, v := range data {
var info = upcrmmodel.InfoQueryResult{}
info.CopyFromBaseInfo(v)
info.CalculateAttr()
result = append(result, &info)
}
return
}
// UpAccountInfo get account info
func (s *Service) UpAccountInfo(c context.Context, arg *upcrmmodel.InfoAccountInfoArgs) (res []*accgrpc.Info, err error) {
var (
infosReply *accgrpc.InfosReply
mids = util.ExplodeInt64(arg.Mids, ",")
)
if infosReply, err = global.GetAccClient().Infos3(c, &accgrpc.MidsReq{Mids: mids, RealIp: metadata.String(c, metadata.RemoteIP)}); err != nil {
return
}
if infosReply == nil || infosReply.Infos == nil {
return
}
for _, v := range infosReply.Infos {
res = append(res, v)
}
log.Info("query acount info ok, req=%+v, result=%+v", arg, res)
return
}
//SearchResult struct
type SearchResult struct {
AccountState int `json:"account_state"`
Activity int `json:"activity"`
Attr int `json:"attr"`
ArticleCountAccumulate int `json:"article_count_accumulate"`
ID uint32
Mid int64
}
func getAttrFormat(attrs upcrmmodel.UpAttr) (result []int) {
// 什么要shift因为es的位是从1开始的而存储的位是从0开始的
const shift = 1
if attrs.AttrVideo != 0 {
result = append(result, upcrmmodel.AttrBitVideo+shift)
}
if attrs.AttrAudio != 0 {
result = append(result, upcrmmodel.AttrBitAudio+shift)
}
if attrs.AttrArticle != 0 {
result = append(result, upcrmmodel.AttrBitArticle+shift)
}
if attrs.AttrPhoto != 0 {
result = append(result, upcrmmodel.AttrBitPhoto+shift)
}
if attrs.AttrSign != 0 {
result = append(result, upcrmmodel.AttrBitSign+shift)
}
if attrs.AttrGrowup != 0 {
result = append(result, upcrmmodel.AttrBitGrowup+shift)
}
if attrs.AttrVerify != 0 {
result = append(result, upcrmmodel.AttrBitVerify+shift)
}
return
}
func getEsCombo(attrs upcrmmodel.UpAttr) (combos []*elastic.Combo) {
const shift = 1
var attrs1, attrs2 []interface{}
var attrFlagList = getAttrFormat(attrs)
for _, v := range attrFlagList {
if _, ok := upcrmmodel.AttrGroup1[v-shift]; ok {
attrs1 = append(attrs1, v)
} else if _, ok := upcrmmodel.AttrGroup2[v-shift]; ok {
attrs2 = append(attrs2, v)
}
}
if attrs1 != nil {
var attrGroup = make(map[string][]interface{})
attrGroup["attr_format"] = attrs1
cmb := &elastic.Combo{}
cmb.ComboIn([]map[string][]interface{}{
attrGroup},
).MinIn(1).MinAll(1)
combos = append(combos, cmb)
}
if attrs2 != nil {
var attrGroup = make(map[string][]interface{})
attrGroup["attr_format"] = attrs2
cmb := &elastic.Combo{}
cmb.ComboIn([]map[string][]interface{}{
attrGroup},
).MinIn(1).MinAll(1)
combos = append(combos, cmb)
}
return
}
//UpInfoSearch info search
func (s *Service) UpInfoSearch(c context.Context, arg *upcrmmodel.InfoSearchArgs) (result upcrmmodel.InfoSearchResult, err error) {
//调用搜索的接口
var searchData esResult
searchData, err = s.searchFromEs(c, arg)
if err != nil {
log.Error("search arg=%+v, err=%+v", arg, err)
return
}
if len(searchData.Result) == 0 {
log.Info("no data return from search, just return")
return
}
var ids []int64
for _, v := range searchData.Result {
ids = append(ids, int64(v.ID))
}
result.Result, err = s.queryUpBaseInfo(c, ids...)
if err != nil {
log.Error("query up base info fail, err=%+v", err)
return
}
result.PageInfo = searchData.Page.ToPageInfo()
log.Info("res=%+v, page=%+v", searchData, result.PageInfo)
return
}
type esPage struct {
Num int `json:"num"`
Size int `json:"size"`
Total int `json:"total"`
}
//ToPageInfo cast to page info
func (e *esPage) ToPageInfo() (pageInfo upcrmmodel.PageInfo) {
if e == nil {
return
}
pageInfo.TotalCount = e.Total
pageInfo.Size = e.Size
pageInfo.Page = e.Num
return
}
type esResult struct {
Page *esPage `json:"page"`
Result []*SearchResult `json:"result"`
}
func (s *Service) searchFromEs(c context.Context, arg *upcrmmodel.InfoSearchArgs) (searchData esResult, err error) {
if arg.Page*arg.Size > maxSearchItemCount {
err = ErrTooManySearchItem
return
}
var searchSdk = elastic.NewElastic(nil)
var r = searchSdk.NewRequest("up_crm_info")
r.Pn(arg.Page).Ps(arg.Size).Index("up_base_info").
Fields("id")
if arg.Mid != 0 {
r.WhereEq("mid", arg.Mid)
} else {
if arg.AccountState != 0 {
// 字段有0值所以接口改为12表示字段的01接口的0表示没有此条件
var realArg = arg.AccountState - 1
r.WhereEq("account_state", realArg)
}
if arg.Activity != 0 {
r.WhereEq("activity", arg.Activity)
}
var startdate, _ = time.Parse(upcrmmodel.TimeFmtDate, arg.FirstDateBegin)
var enddate, _ = time.Parse(upcrmmodel.TimeFmtDate, arg.FirstDateEnd)
enddate = enddate.AddDate(0, 0, 1)
var startStr = startdate.Format(upcrmmodel.TimeFmtMysql)
var endStr = enddate.Format(upcrmmodel.TimeFmtMysql)
if arg.FirstDateBegin != "" && arg.FirstDateEnd != "" {
r.WhereRange("first_up_time", startStr, endStr, elastic.RangeScopeLcRc)
}
if arg.Order.Order == "" {
arg.Order.Order = "desc"
}
if arg.Order.Field == "" {
arg.Order.Field = "first_up_time"
arg.Order.Order = "desc"
}
var combos = getEsCombo(arg.Attrs)
r.WhereCombo(combos...)
r.Order(arg.Order.Field, arg.Order.Order)
}
err = r.Scan(c, &searchData)
return
}
func (s *Service) queryUpBaseInfo(c context.Context, ids ...int64) (result []*upcrmmodel.InfoQueryResult, err error) {
var group, ctx = errgroup.WithContext(c)
var infoData []*upcrmmodel.InfoQueryResult
group.Go(func() error {
var e error
infoData, e = s.upBaseInfoQueryBatch(s.crmdb.QueryUpBaseInfoBatchByID, ids...)
if e != nil {
err = e
log.Error("get base info fail, err=%+v", err)
}
return nil
})
var tidMap = make(map[int64]*datamodel.UpArchiveTypeData)
var mapLock sync.Mutex
for _, mid := range ids {
group.Go(func() error {
var arg = datamodel.GetUpArchiveTypeInfoArg{Mid: mid}
var tidData, e = s.dataService.GetUpArchiveTypeInfo(ctx, &arg)
if e != nil || tidData == nil {
log.Error("get up type info err, err=%v", e)
return nil
}
mapLock.Lock()
tidMap[arg.Mid] = tidData
mapLock.Unlock()
return nil
})
}
if err = group.Wait(); err != nil {
log.Error("get data error, err=%v", err)
return
}
var infoIDMap = make(map[uint32]*upcrmmodel.InfoQueryResult)
for _, v := range infoData {
infoIDMap[v.ID] = v
}
for _, v := range ids {
var info, ok = infoIDMap[uint32(v)]
if !ok {
continue
}
if typeInfo, ok := tidMap[v]; ok {
info.ActiveTid = typeInfo.Tid
info.ActiveSubtid = typeInfo.SubTid
}
result = append(result, info)
}
return
}
//QueryUpInfoWithViewerData query with view data
func (s *Service) QueryUpInfoWithViewerData(c context.Context, arg *upcrmmodel.UpInfoWithViewerArg) (result upcrmmodel.UpInfoWithViewerResult, err error) {
if arg.Page*arg.Size > maxSearchItemCount {
err = ErrTooManySearchItem
return
}
// 如果是0则默认设置所有的tag
if arg.Flag == 0 {
arg.Flag = -1
}
var mids []int64
if arg.Mids != "" {
mids = util.ExplodeInt64(arg.Mids, ",")
var midlen = len(mids)
if midlen == 0 {
err = ErrNoMid
log.Error("no mid get from mids, arg=%+v", arg)
return
}
if midlen > maxBatchCount {
mids = mids[:maxBatchCount]
}
} else {
var searchSdk = elastic.NewElastic(nil)
var r = searchSdk.NewRequest("up_crm_info")
if arg.Size > maxBatchCount {
arg.Size = maxBatchCount
}
r.Pn(arg.Page).Ps(arg.Size).Index("up_base_info").
Fields("mid").
Order(arg.Sort, arg.Order)
var searchData esResult
err = r.Scan(c, &searchData)
if err != nil {
log.Error("fail to get from search, arg=%+v", arg)
return
}
for _, v := range searchData.Result {
mids = append(mids, int64(v.Mid))
}
result.PageInfo = searchData.Page.ToPageInfo()
}
var group, ctx = errgroup.WithContext(c)
var infoData []*upcrmmodel.InfoQueryResult
var playData []*upcrmmodel.UpPlayInfo
group.Go(func() error {
if arg.Flag&upcrmmodel.FlagUpBaseData != 0 {
infoData, err = s.upBaseInfoQueryBatch(s.crmdb.QueryUpBaseInfoBatchByMid, mids...)
if err != nil {
log.Error("query up base error, err=%v", err)
return err
}
}
if arg.Flag&upcrmmodel.FlagUpPlayData != 0 {
playData, err = s.crmdb.QueryPlayInfoBatch(mids, upcrmmodel.BusinessTypeVideo)
if err != nil {
log.Error("query play info err, err=%v", err)
return err
}
}
return nil
})
var dataMap = make(map[int64]*upcrmmodel.UpInfoWithViewerData)
if arg.Flag&upcrmmodel.FlagViewData != 0 {
for _, v := range mids {
var mid = v // copy this v
group.Go(func() error {
var info, e = s.dataService.GetViewData(ctx, mid)
if e != nil {
err = e
log.Error("query up view info from hbase error, err=%v", err)
return err
}
var data = getOrCreateUpInfo(dataMap, mid)
data.ViewerBase = info.Base
data.ViewerTrend = info.Trend
data.ViewerArea = info.Area
return err
})
}
}
if err = group.Wait(); err != nil {
log.Error("get data fail, err=%v", err)
return
}
for _, baseInfo := range infoData {
var data = getOrCreateUpInfo(dataMap, baseInfo.Mid)
data.UpBaseInfo = baseInfo
}
for _, playInfo := range playData {
var data = getOrCreateUpInfo(dataMap, playInfo.Mid)
data.UpPlayInfo = playInfo
}
for _, mid := range mids {
var data, ok = dataMap[mid]
if !ok {
log.Warn("up info not found, mid=%d", mid)
continue
}
data.Mid = mid
result.Result = append(result.Result, data)
}
log.Info("query up with view ok, arg=%+v, result count=%d", arg, len(mids))
return
}
var dataMapMutex sync.Mutex
func getOrCreateUpInfo(dataMap map[int64]*upcrmmodel.UpInfoWithViewerData, mid int64) (result *upcrmmodel.UpInfoWithViewerData) {
dataMapMutex.Lock()
defer dataMapMutex.Unlock()
var ok bool
if result, ok = dataMap[mid]; !ok {
result = &upcrmmodel.UpInfoWithViewerData{}
dataMap[mid] = result
}
return result
}

View File

@@ -0,0 +1,177 @@
package upcrmservice
import (
"context"
"testing"
"go-common/app/admin/main/up/model/upcrmmodel"
"github.com/smartystreets/goconvey/convey"
)
func TestUpcrmserviceUpBaseInfoQuery(t *testing.T) {
convey.Convey("UpBaseInfoQuery", t, func(ctx convey.C) {
var (
context = context.Background()
arg = &upcrmmodel.InfoQueryArgs{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.UpBaseInfoQuery(context, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceupBaseInfoQueryBatch(t *testing.T) {
convey.Convey("upBaseInfoQueryBatch", t, func(ctx convey.C) {
var (
queryfunc QueryDbFunc
ids = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.upBaseInfoQueryBatch(queryfunc, ids)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceUpAccountInfo(t *testing.T) {
convey.Convey("UpAccountInfo", t, func(ctx convey.C) {
var (
con = context.Background()
arg = &upcrmmodel.InfoAccountInfoArgs{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.UpAccountInfo(con, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmservicegetAttrFormat(t *testing.T) {
convey.Convey("getAttrFormat", t, func(ctx convey.C) {
var (
attrs upcrmmodel.UpAttr
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result := getAttrFormat(attrs)
ctx.Convey("Then result should not be nil.", func(ctx convey.C) {
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmservicegetEsCombo(t *testing.T) {
convey.Convey("getEsCombo", t, func(ctx convey.C) {
var (
attrs upcrmmodel.UpAttr
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
combos := getEsCombo(attrs)
ctx.Convey("Then combos should not be nil.", func(ctx convey.C) {
ctx.So(combos, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceUpInfoSearch(t *testing.T) {
convey.Convey("UpInfoSearch", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &upcrmmodel.InfoSearchArgs{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.UpInfoSearch(c, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceToPageInfo(t *testing.T) {
convey.Convey("ToPageInfo", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
var p = esPage{}
pageInfo := p.ToPageInfo()
ctx.Convey("Then pageInfo should not be nil.", func(ctx convey.C) {
ctx.So(pageInfo, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmservicesearchFromEs(t *testing.T) {
convey.Convey("searchFromEs", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &upcrmmodel.InfoSearchArgs{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
searchData, err := s.searchFromEs(c, arg)
ctx.Convey("Then err should be nil.searchData should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(searchData, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmservicequeryUpBaseInfo(t *testing.T) {
convey.Convey("queryUpBaseInfo", t, func(ctx convey.C) {
var (
c = context.Background()
ids = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.queryUpBaseInfo(c, ids)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceQueryUpInfoWithViewerData(t *testing.T) {
convey.Convey("QueryUpInfoWithViewerData", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &upcrmmodel.UpInfoWithViewerArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.QueryUpInfoWithViewerData(c, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmservicegetOrCreateUpInfo(t *testing.T) {
convey.Convey("getOrCreateUpInfo", t, func(ctx convey.C) {
var (
dataMap map[int64]*upcrmmodel.UpInfoWithViewerData
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result := getOrCreateUpInfo(dataMap, mid)
ctx.Convey("Then result should not be nil.", func(ctx convey.C) {
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,180 @@
package upcrmservice
import (
"context"
"sort"
"time"
"go-common/app/admin/main/up/model/upcrmmodel"
"go-common/app/admin/main/up/util/mathutil"
"go-common/library/log"
xtime "go-common/library/time"
)
var (
//AllRankTyps all rank types
AllRankTyps = []int{
upcrmmodel.UpRankTypeFans30day1k,
upcrmmodel.UpRankTypeFans30day1w,
upcrmmodel.UpRankTypePlay30day1k,
upcrmmodel.UpRankTypePlay30day1w,
upcrmmodel.UpRankTypePlay30day10k,
upcrmmodel.UpRankTypeFans30dayIncreaseCount,
upcrmmodel.UpRankTypeFans30dayIncreasePercent,
}
)
type sortRankFunc func(p1, p2 *upcrmmodel.UpRankInfo) bool
type upRankSorter struct {
datas []*upcrmmodel.UpRankInfo
by sortRankFunc // Closure used in the Less method.
}
// Len is part of sort.Interface.
func (s *upRankSorter) Len() int {
return len(s.datas)
}
// Swap is part of sort.Interface.
func (s *upRankSorter) Swap(i, j int) {
s.datas[i], s.datas[j] = s.datas[j], s.datas[i]
}
// Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
func (s *upRankSorter) Less(i, j int) bool {
return s.by(s.datas[i], s.datas[j])
}
func sortRankInfo(planets []*upcrmmodel.UpRankInfo, sortfunc sortRankFunc) {
ps := &upRankSorter{
datas: planets,
by: sortfunc, // The Sort method's receiver is the function (closure) that defines the sort order.
}
sort.Sort(ps)
}
func sortByValueAsc(p1, p2 *upcrmmodel.UpRankInfo) bool {
if p1.Value < p2.Value {
return true
}
if p1.Value == p2.Value {
return p1.Value2 < p2.Value2
}
return false
}
func sortByValueDesc(p1, p2 *upcrmmodel.UpRankInfo) bool {
if p1.Value > p2.Value {
return true
}
if p1.Value == p2.Value {
return p1.Value2 > p2.Value2
}
return false
}
// 从数据库中更新数据
func (s *Service) refreshUpRankDate(date time.Time) {
rankData, err := s.crmdb.QueryUpRankAll(date)
if err != nil {
log.Error("refresh from db fail, err=%+v", err)
return
}
var typeMap = map[int][]*upcrmmodel.UpRankInfo{}
var upInfoMap = map[int64]*upcrmmodel.InfoQueryResult{}
for _, v := range rankData {
var rankType = int(v.Type)
var rankInfo = &upcrmmodel.UpRankInfo{}
rankInfo.Mid = v.Mid
rankInfo.CopyFromUpRank(&v)
typeMap[rankType] = append(typeMap[rankType], rankInfo)
upInfoMap[v.Mid] = nil
}
log.Info("refresh from db, get for date=%v, len=%d", date, len(rankData))
// interestring code
var mids []int64
for k := range upInfoMap {
mids = append(mids, k)
}
// 查询并合并
var infoData, e = s.upBaseInfoQueryBatch(s.crmdb.QueryUpBaseInfoBatchByMid, mids...)
err = e
if err != nil {
log.Error("get from base info fail, err=%+v", err)
return
}
for _, v := range infoData {
upInfoMap[v.Mid] = v
}
for _, list := range typeMap {
for _, info := range list {
var data, _ = upInfoMap[info.Mid]
if data == nil {
continue
}
info.InfoQueryResult = *data
switch info.RankType {
case upcrmmodel.UpRankTypeFans30day1k,
upcrmmodel.UpRankTypeFans30day1w,
upcrmmodel.UpRankTypePlay30day1k,
upcrmmodel.UpRankTypePlay30day1w,
upcrmmodel.UpRankTypePlay30day10k,
upcrmmodel.UpRankTypeFans30dayIncreaseCount,
upcrmmodel.UpRankTypeFans30dayIncreasePercent:
info.CompleteTime = info.FirstUpTime + xtime.Time(info.Value)
}
}
}
// 排序
for k, list := range typeMap {
var sortFunc sortRankFunc = sortByValueAsc
switch k {
case upcrmmodel.UpRankTypeFans30dayIncreaseCount,
upcrmmodel.UpRankTypeFans30dayIncreasePercent:
sortFunc = sortByValueDesc
}
sortRankInfo(list, sortFunc)
for i, v := range list {
v.Rank = i + 1
}
log.Info("cache rank type=%d, len=%d, date=%v", k, len(list), date)
}
s.uprankCache = typeMap
s.lastCacheDate = date
}
//UpRankQueryList query up rank list
func (s *Service) UpRankQueryList(c context.Context, arg *upcrmmodel.UpRankQueryArgs) (result upcrmmodel.UpRankQueryResult, err error) {
if arg.Page == 0 {
arg.Page = 1
}
if arg.Size <= 0 || arg.Size > 50 {
arg.Size = 20
}
// 1.从内存中读数据
var rankList, ok = s.uprankCache[arg.Type]
if !ok || rankList == nil {
log.Warn("no available rank data in cache, type=%d", arg.Type)
return
}
var startIndex = (arg.Page - 1) * arg.Size
var endIndex = startIndex + arg.Size
var totalCount = len(rankList)
endIndex = mathutil.Min(endIndex, totalCount)
if startIndex < endIndex {
result.Result = rankList[startIndex:endIndex]
}
result.Date = xtime.Time(s.lastCacheDate.Unix())
result.TotalCount = totalCount
result.Size = arg.Size
result.Page = arg.Page
log.Info("get rank list for type=%d", arg.Type)
// 2.如果没有,从数据库中刷数据
return
}

View File

@@ -0,0 +1,84 @@
package upcrmservice
import (
"context"
"testing"
"time"
"go-common/app/admin/main/up/model/upcrmmodel"
"github.com/smartystreets/goconvey/convey"
)
func TestUpcrmservicesortRankInfo(t *testing.T) {
convey.Convey("sortRankInfo", t, func(ctx convey.C) {
var (
planets = []*upcrmmodel.UpRankInfo{}
sortfunc sortRankFunc
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
sortRankInfo(planets, sortfunc)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}
func TestUpcrmservicesortByValueAsc(t *testing.T) {
convey.Convey("sortByValueAsc", t, func(ctx convey.C) {
var (
p1 = &upcrmmodel.UpRankInfo{}
p2 = &upcrmmodel.UpRankInfo{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := sortByValueAsc(p1, p2)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmservicesortByValueDesc(t *testing.T) {
convey.Convey("sortByValueDesc", t, func(ctx convey.C) {
var (
p1 = &upcrmmodel.UpRankInfo{}
p2 = &upcrmmodel.UpRankInfo{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := sortByValueDesc(p1, p2)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmservicerefreshUpRankDate(t *testing.T) {
convey.Convey("refreshUpRankDate", t, func(ctx convey.C) {
var (
date = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
s.refreshUpRankDate(date)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}
func TestUpcrmserviceUpRankQueryList(t *testing.T) {
convey.Convey("UpRankQueryList", t, func(ctx convey.C) {
var (
c = context.Background()
arg = &upcrmmodel.UpRankQueryArgs{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.UpRankQueryList(c, arg)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,164 @@
package upcrmservice
import (
"context"
"time"
"go-common/app/admin/main/up/dao/upcrm"
"go-common/app/admin/main/up/model/upcrmmodel"
"go-common/library/log"
)
//YesterdayRes struct
type YesterdayRes struct {
ActivityUps int64 `json:"activity_ups"`
IncrUps int64 `json:"incr_ups"`
TotalUps int64 `json:"total_ups"`
Date int64 `json:"date"` // 截止日期
}
//TrendRes struct
type TrendRes struct {
Date int64 `json:"date"` // 截止日期
Ups int64 `json:"ups"`
}
//TrendDetail struct
type TrendDetail struct {
ActivityUps int64 `json:"activity_ups"`
IncrUps int64 `json:"incr_ups"`
TotalUps int64 `json:"total_ups"`
Date int64 `json:"date"`
}
//QueryYesterday query yesterday data
func (s *Service) QueryYesterday(ctx context.Context, date time.Time) (item *YesterdayRes, err error) {
var lastday, e = s.crmdb.GetUpStatLastDate(date)
if e != nil {
err = e
log.Error("err get up stat last day, err=%+v", err)
return
}
histories, err := s.crmdb.QueryYesterday(lastday)
if err != nil {
return nil, err
}
item = &YesterdayRes{}
item.Date = lastday.Unix()
for _, v := range histories {
if v.Type == upcrmmodel.ActivityType {
item.ActivityUps += v.Value1
}
if v.Type == upcrmmodel.IncrType {
item.IncrUps += v.Value1
}
if v.Type == upcrmmodel.TotalType {
item.TotalUps += v.Value1
}
}
return
}
//QueryTrend query trend
func (s *Service) QueryTrend(ctx context.Context, statType int, currentDate time.Time, days int) (result []*TrendRes, err error) {
histories, err := s.crmdb.QueryTrend(statType, currentDate, days)
if err != nil {
return nil, err
}
var items = make(map[string]*TrendRes)
var length = len(histories)
var endDate = currentDate
if length > 0 {
endDate = histories[0].GenerateDate.Time()
}
for _, v := range histories {
key := v.GenerateDate.Time().Format(upcrm.ISO8601DATE)
if old, ok := items[key]; ok {
new := &TrendRes{
Date: old.Date,
Ups: old.Ups + v.Value1,
}
items[key] = new
} else {
items[key] = &TrendRes{
Date: v.GenerateDate.Time().Unix(),
Ups: v.Value1,
}
}
}
// 这里的范围是[endDate - 6, endDate]包含endDate
for date := endDate.AddDate(0, 0, 1-days); !date.After(endDate); date = date.AddDate(0, 0, 1) {
var dateStr = date.Format(upcrmmodel.TimeFmtDate)
var d *TrendRes
var ok bool
if d, ok = items[dateStr]; !ok {
d = &TrendRes{
Date: date.Unix(),
Ups: 0,
}
}
result = append(result, d)
}
return
}
//QueryDetail query detail info
func (s *Service) QueryDetail(ctx context.Context, currentDate time.Time, days int) (result []*TrendDetail, err error) {
var endDate, e = s.crmdb.GetUpStatLastDate(currentDate)
if e != nil {
err = e
log.Error("err get up stat last day, err=%+v", err)
return
}
var startDate = endDate.AddDate(0, 0, 1-days)
histories, err := s.crmdb.QueryDetail(startDate, endDate)
if err != nil {
return nil, err
}
var items = make(map[string]*TrendDetail)
for _, v := range histories {
key := v.GenerateDate.Time().Format(upcrm.ISO8601DATE)
if old, ok := items[key]; ok {
if v.Type == upcrmmodel.ActivityType {
old.ActivityUps += v.Value1
}
if v.Type == upcrmmodel.IncrType {
old.IncrUps += v.Value1
}
if v.Type == upcrmmodel.TotalType {
old.TotalUps += v.Value1
}
items[key] = old
} else {
new := &TrendDetail{
Date: v.GenerateDate.Time().Unix(),
}
if v.Type == upcrmmodel.ActivityType {
new.ActivityUps = v.Value1
}
if v.Type == upcrmmodel.IncrType {
new.IncrUps = v.Value1
}
if v.Type == upcrmmodel.TotalType {
new.TotalUps = v.Value1
}
items[key] = new
}
}
// 这里的范围是[endDate - 6, endDate]包含endDate
for date := endDate.AddDate(0, 0, 1-days); !date.After(endDate); date = date.AddDate(0, 0, 1) {
var dateStr = date.Format(upcrmmodel.TimeFmtDate)
var d *TrendDetail
var ok bool
if d, ok = items[dateStr]; !ok {
d = &TrendDetail{
Date: date.Unix(),
}
}
result = append(result, d)
}
return
}

View File

@@ -0,0 +1,60 @@
package upcrmservice
import (
"context"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestUpcrmserviceQueryYesterday(t *testing.T) {
convey.Convey("QueryYesterday", t, func(ctx convey.C) {
var (
c = context.Background()
date = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
item, err := s.QueryYesterday(c, date)
ctx.Convey("Then err should be nil.item should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(item, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceQueryTrend(t *testing.T) {
convey.Convey("QueryTrend", t, func(ctx convey.C) {
var (
c = context.Background()
statType = int(0)
currentDate = time.Now()
days = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.QueryTrend(c, statType, currentDate, days)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmserviceQueryDetail(t *testing.T) {
convey.Convey("QueryDetail", t, func(ctx convey.C) {
var (
c = context.Background()
currentDate = time.Now()
days = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := s.QueryDetail(c, currentDate, days)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,98 @@
package upcrmservice
import (
"context"
"fmt"
"time"
"go-common/app/admin/main/up/conf"
"go-common/app/admin/main/up/dao/email"
"go-common/app/admin/main/up/dao/manager"
"go-common/app/admin/main/up/dao/upcrm"
"go-common/app/admin/main/up/model/upcrmmodel"
"go-common/app/admin/main/up/service/cache"
"go-common/app/admin/main/up/service/data"
"go-common/app/admin/main/up/util"
"go-common/app/admin/main/up/util/timerqueue"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
//Service upcrm service
type Service struct {
crmdb *upcrm.Dao
mng *manager.Dao
httpClient *bm.Client
mailService *email.Dao
uprankCache map[int][]*upcrmmodel.UpRankInfo
lastCacheDate time.Time
dataService *data.Service
}
//New create service
func New(c *conf.Config) (svc *Service) {
svc = &Service{
crmdb: upcrm.New(c),
mng: manager.New(c),
mailService: email.New(c),
dataService: data.New(c),
}
svc.initSvc()
return svc
}
func (s *Service) initSvc() {
addScheduleWithConf(conf.Conf.TimeConf.RefreshUpRankTime, s.RefreshCache, "03:00:00", "refresh up rank data")
go s.RefreshCache(time.Now())
cache.LoadCache()
var cacheInterval = 60 * time.Minute
util.GlobalTimer.ScheduleRepeat(timerqueue.NewTimerWrapper(cache.RefreshUpTypeAsync), time.Now().Add(cacheInterval), cacheInterval)
util.GlobalTimer.ScheduleRepeat(timerqueue.NewTimerWrapper(cache.ClearTagCache), time.Now().Add(cacheInterval), cacheInterval)
}
func addScheduleWithConf(scheduleTime string, timerFunc timerqueue.TimerFunc, defaultTime string, desc string) {
if scheduleTime == "" {
scheduleTime = defaultTime
}
var next, err = util.GetNextPeriodTime(scheduleTime, time.Hour*24, time.Now())
if err != nil {
panic(fmt.Sprintf("config for time fail, err=%+v", err))
}
log.Info("[%s] next period time is %+v", desc, next)
util.GlobalTimer.ScheduleRepeat(timerqueue.NewTimerWrapper(timerFunc), next, time.Hour*24)
}
//SetHTTPClient set client
func (s *Service) SetHTTPClient(client *bm.Client) {
s.httpClient = client
s.crmdb.SetHTTPClient(client)
}
//DataService data service
func (s *Service) DataService() *data.Service {
return s.dataService
}
//RefreshCache refresh cache
func (s *Service) RefreshCache(tm time.Time) {
latestDate, err := s.crmdb.GetUpRankLatestDate()
if err != nil {
log.Error("get latest rank time from db fail, err=%+v", err)
return
}
if latestDate == s.lastCacheDate {
log.Info("no need to refresh cache, latest cache date=%v", latestDate)
return
}
s.refreshUpRankDate(latestDate)
}
//TestGetViewBase test get view
func (s *Service) TestGetViewBase(c context.Context, arg *upcrmmodel.TestGetViewBaseArgs) (res interface{}, err error) {
var dataMap = make(map[string]interface{})
dataMap["info"], err = s.dataService.GetViewData(c, arg.Mid)
res = dataMap
return
}

View File

@@ -0,0 +1,24 @@
package upcrmservice
import (
"flag"
"os"
"testing"
"go-common/app/admin/main/up/conf"
)
var (
s *Service
)
func TestMain(m *testing.M) {
flag.Set("conf", "../../cmd/up-admin.toml")
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
s = New(conf.Conf)
m.Run()
os.Exit(m.Run())
}

View File

@@ -0,0 +1,11 @@
package upcrmservice
import (
"time"
)
//GetDateStamp get date from time stamp
func GetDateStamp(timeStamp time.Time) time.Time {
var y, m, d = timeStamp.Date()
return time.Date(y, m, d, 0, 0, 0, 0, timeStamp.Location())
}

View File

@@ -0,0 +1,22 @@
package upcrmservice
import (
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestUpcrmserviceGetDateStamp(t *testing.T) {
convey.Convey("GetDateStamp", t, func(ctx convey.C) {
var (
timeStamp = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := GetDateStamp(timeStamp)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,25 @@
package service
import (
"bytes"
"context"
"time"
"go-common/app/admin/main/up/conf"
"go-common/app/admin/main/up/dao"
"go-common/library/ecode"
"go-common/library/log"
)
// Upload upload.
func (s *Service) Upload(c context.Context, fileName, fileType string, t time.Time, body []byte, bfs *conf.Bfs) (location string, err error) {
if len(body) > bfs.MaxFileSize {
err = ecode.FileTooLarge
return
}
if location, err = dao.Upload(c, fileName, fileType, t.Unix(), bytes.NewReader(body), bfs); err != nil {
log.Error("Upload error(%v)", err)
return
}
return
}

View File

@@ -0,0 +1,30 @@
package service
import (
"context"
"go-common/app/admin/main/up/conf"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestServiceUpload(t *testing.T) {
convey.Convey("Upload", t, func(ctx convey.C) {
var (
c = context.Background()
fileName = ""
fileType = ""
no = time.Now()
body = []byte("")
bfs = &conf.Bfs{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
location, err := s.Upload(c, fileName, fileType, no, body, bfs)
ctx.Convey("Then err should be nil.location should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(location, convey.ShouldNotBeNil)
})
})
})
}