Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,60 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"upload_test.go",
"utils_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"upload.go",
"utils.go",
],
importmap = "go-common/app/admin/main/up/dao",
importpath = "go-common/app/admin/main/up/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//library/log: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/dao/data:all-srcs",
"//app/admin/main/up/dao/email:all-srcs",
"//app/admin/main/up/dao/global:all-srcs",
"//app/admin/main/up/dao/manager:all-srcs",
"//app/admin/main/up/dao/tag:all-srcs",
"//app/admin/main/up/dao/upcrm:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,78 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"api_test.go",
"center_test.go",
"dao_test.go",
"field_test.go",
"hbase_set2_test.go",
"hbase_test.go",
"phase_three_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/datamodel:go_default_library",
"//library/database/hbase.v2:go_default_library",
"//vendor/github.com/bouk/monkey:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
"//vendor/github.com/tsuna/gohbase/hrpc:go_default_library",
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"api.go",
"center.go",
"dao.go",
"field.go",
"hbase.go",
"hbase_set2.go",
"phase_three.go",
"utils.go",
],
importpath = "go-common/app/admin/main/up/dao/data",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//app/admin/main/up/model/datamodel:go_default_library",
"//app/admin/main/up/util/hbaseutil:go_default_library",
"//app/interface/main/creative/model/data:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/database/hbase.v2:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/sync/errgroup:go_default_library",
"//vendor/github.com/tsuna/gohbase/hrpc:go_default_library",
"@org_golang_x_net//context: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,101 @@
package data
import (
"context"
"net/url"
"strconv"
"strings"
"go-common/app/interface/main/creative/model/data"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_statURL = "/data/member/upinfo/%d.json"
_tagURL = "/tag_predict"
_tagv2URL = "/tag_predict/v2"
_coverURL = "/cover_recomm"
)
// Tags get predict tag.
func (d *Dao) Tags(c context.Context, mid int64, tid uint16, title, filename, desc, cover string) (t *data.Tags, err error) {
params := url.Values{}
params.Set("typeid", strconv.Itoa(int(tid)))
params.Set("title", title)
params.Set("filename", filename)
params.Set("desc", desc)
params.Set("cover", cover)
params.Set("mid", strconv.FormatInt(mid, 10))
var res struct {
Code int `json:"code"`
Data *data.Tags `json:"data"`
}
if err = d.client.Get(c, d.tagURI, "", params, &res); err != nil {
log.Error("data url(%s) error(%v)", d.tagURI+"?"+params.Encode(), err)
err = ecode.CreativeDataErr
return
}
if res.Code != 0 {
log.Error("data url(%s) res(%v)", d.tagURI+"?"+params.Encode(), res)
err = ecode.CreativeDataErr
return
}
t = res.Data
return
}
// TagsWithChecked get predict tag with checked mark.
func (d *Dao) TagsWithChecked(c context.Context, mid int64, tid uint16, title, filename, desc, cover string, tagFrom int8) (t []*data.CheckedTag, err error) {
params := url.Values{}
t = make([]*data.CheckedTag, 0)
params.Set("client_type", strconv.Itoa(int(tagFrom)))
params.Set("typeid", strconv.Itoa(int(tid)))
params.Set("title", title)
params.Set("filename", filename)
params.Set("desc", desc)
params.Set("cover", cover)
params.Set("mid", strconv.FormatInt(mid, 10))
var res struct {
Code int `json:"code"`
Data struct {
Tags []*data.CheckedTag `json:"tags"`
} `json:"data"`
}
log.Info("TagsWithChecked url(%s)", d.tagV2URI+"?"+params.Encode())
if err = d.client.Get(c, d.tagV2URI, "", params, &res); err != nil {
log.Error("data url(%s) error(%v)", d.tagV2URI+"?"+params.Encode(), err)
err = ecode.CreativeDataErr
return
}
if res.Code != 0 {
log.Error("data url(%s) res(%v)", d.tagV2URI+"?"+params.Encode(), res)
err = ecode.CreativeDataErr
return
}
t = res.Data.Tags
return
}
// RecommendCovers get recommend covers from AI.
func (d *Dao) RecommendCovers(c context.Context, mid int64, fns []string) (cvs []string, err error) {
params := url.Values{}
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("filename", strings.Join(fns, ","))
var res struct {
Code int `json:"code"`
Data []string `json:"data"`
}
if err = d.client.Get(c, d.coverBFSURI, "", params, &res); err != nil {
log.Error("Covers url(%s) error(%v)", d.coverBFSURI+"?"+params.Encode(), err)
err = ecode.CreativeDataErr
return
}
if res.Code != 0 {
log.Error("Covers url(%s) res(%v)", d.coverBFSURI+"?"+params.Encode(), res)
err = ecode.CreativeDataErr
return
}
cvs = res.Data
return
}

View File

@@ -0,0 +1,87 @@
package data
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
"gopkg.in/h2non/gock.v1"
)
func TestDataTags(t *testing.T) {
convey.Convey("Tags", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
tid = uint16(0)
title = ""
filename = ""
desc = ""
cover = ""
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
defer gock.OffAll()
httpMock("GET", d.tagURI).Reply(200).BodyString(`
{
"code":0,
"data": {"tags" : ["1"]}
}`)
no, err := d.Tags(c, mid, tid, title, filename, desc, cover)
ctx.Convey("Then err should be nil.no should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(no, convey.ShouldNotBeNil)
})
})
})
}
func TestDataTagsWithChecked(t *testing.T) {
convey.Convey("TagsWithChecked", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
tid = uint16(0)
title = ""
filename = ""
desc = ""
cover = ""
tagFrom = int8(0)
)
defer gock.OffAll()
httpMock("GET", d.tagV2URI).Reply(200).BodyString(`
{
"code":0,
"data": {"tags" : []}
}`)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
no, err := d.TagsWithChecked(c, mid, tid, title, filename, desc, cover, tagFrom)
ctx.Convey("Then err should be nil.no should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(no, convey.ShouldNotBeNil)
})
})
})
}
func TestDataRecommendCovers(t *testing.T) {
convey.Convey("RecommendCovers", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
fns = []string{}
)
defer gock.OffAll()
httpMock("GET", d.coverBFSURI).Reply(200).BodyString(`
{
"code":0,
"data": ["1"]
}`)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
cvs, err := d.RecommendCovers(c, mid, fns)
ctx.Convey("Then err should be nil.cvs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(cvs, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,556 @@
package data
import (
"bytes"
"strconv"
"time"
"go-common/app/admin/main/up/model/datamodel"
"go-common/app/admin/main/up/util/hbaseutil"
"go-common/app/interface/main/creative/model/data"
"go-common/library/ecode"
"go-common/library/log"
"github.com/tsuna/gohbase/hrpc"
"golang.org/x/net/context"
)
// ViewerBase visitor data analysis.
func (d *Dao) ViewerBase(c context.Context, mid int64, dt time.Time) (res *datamodel.ViewerBaseInfo, err error) {
var (
result *hrpc.Result
ctx, cancel = context.WithTimeout(c, time.Duration(d.c.HBase.ReadTimeout))
key = hbaseMd5Key(mid)
genTableName = generateTableNameFunc(HBaseUpViewerBase, dt, -7)
)
defer cancel()
if result, err = d.getDataWithBackup(ctx, d.hbase, genTableName, 2, key); err != nil {
log.Error("ViewerBase d.hbase.GetStr tableName(%s)|mid(%d)|key(%v)|error(%v)", HBaseUpViewerBase, mid, key, err)
err = ecode.CreativeDataErr
return
}
if result == nil || len(result.Cells) == 0 {
log.Warn("ViewerBase no data tableName(%s)|mid(%d)|key(%v)", HBaseUpViewerBase, mid, key)
return
}
res = &datamodel.ViewerBaseInfo{}
families := make(map[string]string, 2)
families["f"] = ""
families["g"] = ""
fb := &datamodel.ViewerBaseData{}
gb := &datamodel.ViewerBaseData{}
for _, c := range result.Cells {
if c == nil {
continue
}
if _, ok := families[string(c.Family)]; ok {
var data = gb
if string(c.Family) == "f" {
data = fb
}
v, _ := strconv.ParseInt(string(c.Value[:]), 10, 64)
/*
f:plat0 web-pc播放
f:plat1 web-h5播放
f:plat2 站外播放
f:plat3 ios播放
f:plat4 android播放
*/
switch {
case bytes.Equal(c.Qualifier, []byte("male")):
data.Male = v
case bytes.Equal(c.Qualifier, []byte("female")):
data.Female = v
case bytes.Equal(c.Qualifier, []byte("age1")):
data.Age1 = v
case bytes.Equal(c.Qualifier, []byte("age2")):
data.Age2 = v
case bytes.Equal(c.Qualifier, []byte("age3")):
data.Age3 = v
case bytes.Equal(c.Qualifier, []byte("age4")):
data.Age4 = v
case bytes.Equal(c.Qualifier, []byte("plat0")):
data.PlatPC = v
case bytes.Equal(c.Qualifier, []byte("plat1")):
data.PlatH5 = v
case bytes.Equal(c.Qualifier, []byte("plat2")):
data.PlatOut = v
case bytes.Equal(c.Qualifier, []byte("plat3")):
data.PlatIOS = v
case bytes.Equal(c.Qualifier, []byte("plat4")):
data.PlatAndroid = v
case bytes.Equal(c.Qualifier, []byte("else")):
data.PlatOtherApp = v
}
}
}
res.Fans = fb
res.Guest = gb
return
}
// ViewerArea visitor area data analysis.
func (d *Dao) ViewerArea(c context.Context, mid int64, dt time.Time) (res *datamodel.ViewerAreaInfo, err error) {
var (
result *hrpc.Result
ctx, cancel = context.WithTimeout(c, time.Duration(d.c.HBase.ReadTimeout))
key = hbaseMd5Key(mid)
genTableName = generateTableNameFunc(HBaseUpViewerArea, dt, -7)
)
defer cancel()
if result, err = d.getDataWithBackup(ctx, d.hbase, genTableName, 2, key); err != nil {
log.Error("ViewerArea d.hbase.GetStr tableName(%s)|mid(%d)|key(%v)|error(%v)", HBaseUpViewerArea, mid, key, err)
err = ecode.CreativeDataErr
return
}
if result == nil || len(result.Cells) == 0 {
log.Warn("ViewerArea no data tableName(%s)|mid(%d)|key(%v)", HBaseUpViewerArea, mid, key)
return
}
res = &datamodel.ViewerAreaInfo{}
families := make(map[string]string, 2)
families["f"] = ""
families["g"] = ""
for _, c := range result.Cells {
if c == nil {
continue
}
if _, ok := families[string(c.Family)]; ok {
a := string(c.Qualifier[:])
var list = &res.Guest
v, _ := strconv.ParseInt(string(c.Value[:]), 10, 64)
if string(c.Family) == "f" {
list = &res.Fans
}
*list = append(*list, datamodel.ViewerAreaData{Area: a, Viewers: v})
}
}
return
}
// ViewerTrend visitor trend data analysis.
func (d *Dao) ViewerTrend(c context.Context, mid int64, dt time.Time) (res map[string]*data.Trend, err error) {
var (
result *hrpc.Result
ctx, cancel = context.WithTimeout(c, time.Duration(d.c.HBase.ReadTimeout))
genTableName = generateTableNameFunc(HBaseUpViewerTrend, dt, -7)
key = hbaseMd5Key(mid)
)
defer cancel()
if result, err = d.getDataWithBackup(ctx, d.hbase, genTableName, 2, key); err != nil {
log.Error("ViewerTrend d.hbase.GetStr tableName(%s)|mid(%d)|key(%v)|error(%v)", HBaseUpViewerTrend, mid, key, err)
err = ecode.CreativeDataErr
return
}
if result == nil || len(result.Cells) == 0 {
log.Warn("ViewerTrend no data tableName(%s)|mid(%d)|key(%v)", HBaseUpViewerTrend, mid, key)
return
}
families := make(map[string]string, 4)
families["fs"] = ""
families["ft"] = ""
families["gs"] = ""
families["gt"] = ""
res = make(map[string]*data.Trend)
ftd := &data.Trend{}
gtd := &data.Trend{}
ty := make(map[int]int64)
tg := make(map[int]int64)
nty := make(map[int]int64)
ntg := make(map[int]int64)
for _, c := range result.Cells {
if c == nil {
continue
}
if _, ok := families[string(c.Family)]; ok {
if string(c.Family) == "fs" {
tid, _ := strconv.Atoi(string(c.Qualifier[:]))
v, _ := strconv.ParseInt(string(c.Value[:]), 10, 64)
ty[tid] = v
ftd.Ty = ty
} else if string(c.Family) == "gs" {
tid, _ := strconv.Atoi(string(c.Qualifier[:]))
v, _ := strconv.ParseInt(string(c.Value[:]), 10, 64)
nty[tid] = v
gtd.Ty = nty
}
if string(c.Family) == "ft" {
o, _ := strconv.Atoi(string(c.Qualifier[:]))
v, _ := strconv.ParseInt(string(c.Value[:]), 10, 64)
tg[o] = v
ftd.Tag = tg
} else if string(c.Family) == "gt" {
o, _ := strconv.Atoi(string(c.Qualifier[:]))
v, _ := strconv.ParseInt(string(c.Value[:]), 10, 64)
ntg[o] = v
gtd.Tag = ntg
}
}
}
res["fan"] = ftd
res["guest"] = gtd
return
}
// RelationFansDay up relation 30 days analysis.
func (d *Dao) RelationFansDay(c context.Context, mid int64) (res datamodel.RelationFanHistoryData, err error) {
var (
result *hrpc.Result
ctx, cancel = context.WithTimeout(c, time.Duration(d.c.HBase.ReadTimeout))
tableName = HBaseUpRelationFansDay
key = hbaseMd5Key(mid)
parser = hbaseutil.Parser{
ParseIntFunc: hbaseutil.StringToUint,
}
)
defer cancel()
if result, err = d.hbase.GetStr(ctx, tableName, key); err != nil {
log.Error("RelationFansDay d.hbase.GetStr tableName(%s)|mid(%d)|key(%v)|error(%v)", tableName, mid, key, err)
err = ecode.CreativeDataErr
return
}
if result == nil || len(result.Cells) == 0 {
log.Warn("RelationFansDay no data tableName(%s)|mid(%d)|key(%v)", tableName, mid, key)
return
}
if err = parser.Parse(result.Cells, &res); err != nil {
log.Error("parse cell fail, err=%v", err)
return
}
/*
families := make(map[string]string, 2)
families["a"] = "" //某日新增关注量
families["u"] = "" //某日取关量
fd := make(map[string]int)
nfd := make(map[string]int)
for _, c := range result.Cells {
if c == nil {
continue
}
if _, ok := families[string(c.Family)]; ok {
if string(c.Family) == "a" {
k := string(c.Qualifier[:])
v, _ := strconv.Atoi(string(c.Value[:]))
fd[k] = v
} else if string(c.Family) == "u" {
k := string(c.Qualifier[:])
v, _ := strconv.Atoi(string(c.Value[:]))
nfd[k] = v
}
}
}
res["follow"] = fd
res["unfollow"] = nfd
*/
return
}
// RelationFansHistory up relation history.
func (d *Dao) RelationFansHistory(c context.Context, mid int64, month string) (res datamodel.RelationFanHistoryData, err error) {
var (
result *hrpc.Result
ctx, cancel = context.WithTimeout(c, time.Duration(d.c.HBase.ReadTimeout))
tableName = HBaseUpRelationFansHistory
key = string(hbaseMd5Key(mid)) + "_" + month
parser = hbaseutil.Parser{ParseIntFunc: hbaseutil.StringToUint}
)
defer cancel()
if result, err = d.hbase.GetStr(ctx, tableName, key); err != nil {
log.Error("RelationFansHistory d.hbase.GetStr tableName(%s)|mid(%d)|key(%v)|error(%v)", tableName, mid, key, err)
err = ecode.CreativeDataErr
return
}
if result == nil || len(result.Cells) == 0 {
log.Warn("RelationFansHistory no data tableName(%s)|mid(%d)|key(%v)", tableName, mid, key)
return
}
if err = parser.Parse(result.Cells, &res); err != nil {
log.Error("parse cell fail, err=%v", err)
return
}
return
}
// RelationFansMonth up relation 400 days analysis.
func (d *Dao) RelationFansMonth(c context.Context, mid int64) (res datamodel.RelationFanHistoryData, err error) {
var (
result *hrpc.Result
ctx, cancel = context.WithTimeout(c, time.Duration(d.c.HBase.ReadTimeout))
tableName = HBaseUpRelationFansMonth
key = hbaseMd5Key(mid)
parser = hbaseutil.Parser{ParseIntFunc: hbaseutil.StringToUint}
)
defer cancel()
if result, err = d.hbase.GetStr(ctx, tableName, key); err != nil {
log.Error("RelationFansMonth d.hbase.GetStr tableName(%s)|mid(%d)|key(%v)|error(%v)", tableName, mid, key, err)
err = ecode.CreativeDataErr
return
}
if result == nil || len(result.Cells) == 0 {
log.Warn("RelationFansMonth no data tableName(%s)|mid(%d)|key(%v)", tableName, mid, key)
return
}
if err = parser.Parse(result.Cells, &res); err != nil {
log.Error("parse cell fail, err=%v", err)
return
}
return
}
// ViewerActionHour visitor action hour analysis.
func (d *Dao) ViewerActionHour(c context.Context, mid int64, dt string) (res map[string]*data.ViewerActionHour, err error) {
var (
result *hrpc.Result
ctx, cancel = context.WithTimeout(c, time.Duration(d.c.HBase.ReadTimeout))
tableName = HBaseUpViewerActionHour + dt
key = hbaseMd5Key(mid)
)
defer cancel()
if result, err = d.hbase.GetStr(ctx, tableName, key); err != nil {
log.Error("ViewerActionHour d.hbase.GetStr tableName(%s)|mid(%d)|key(%v)|error(%v)", tableName, mid, key, err)
err = ecode.CreativeDataErr
return
}
if result == nil || len(result.Cells) == 0 {
log.Warn("ViewerActionHour no data tableName(%s)|mid(%d)|key(%v)", tableName, mid, key)
return
}
families := make(map[string]string, 4)
families["fp"] = "" //播放数
families["fr"] = "" //评论数
families["fd"] = "" //弹幕数
families["fe"] = "" //充电数
families["fs"] = "" //承包数
res = make(map[string]*data.ViewerActionHour)
view := make(map[int]int)
reply := make(map[int]int)
danmu := make(map[int]int)
elec := make(map[int]int)
con := make(map[int]int)
fah := &data.ViewerActionHour{}
gah := &data.ViewerActionHour{}
for _, c := range result.Cells {
if c == nil {
continue
}
if _, ok := families[string(c.Family)]; ok {
if string(c.Family) == "fp" {
k, _ := strconv.Atoi(string(c.Qualifier[:]))
v, _ := strconv.Atoi(string(c.Value[:]))
view[k] = v
fah.View = view
} else if string(c.Family) == "gp" {
k, _ := strconv.Atoi(string(c.Qualifier[:]))
v, _ := strconv.Atoi(string(c.Value[:]))
view[k] = v
gah.View = view
}
if string(c.Family) == "fr" {
k, _ := strconv.Atoi(string(c.Qualifier[:]))
v, _ := strconv.Atoi(string(c.Value[:]))
reply[k] = v
fah.Reply = reply
} else if string(c.Family) == "gr" {
k, _ := strconv.Atoi(string(c.Qualifier[:]))
v, _ := strconv.Atoi(string(c.Value[:]))
reply[k] = v
gah.Reply = reply
}
if string(c.Family) == "fd" {
k, _ := strconv.Atoi(string(c.Qualifier[:]))
v, _ := strconv.Atoi(string(c.Value[:]))
danmu[k] = v
fah.Dm = danmu
} else if string(c.Family) == "gd" {
k, _ := strconv.Atoi(string(c.Qualifier[:]))
v, _ := strconv.Atoi(string(c.Value[:]))
danmu[k] = v
gah.Dm = danmu
}
if string(c.Family) == "fe" {
k, _ := strconv.Atoi(string(c.Qualifier[:]))
v, _ := strconv.Atoi(string(c.Value[:]))
elec[k] = v
fah.Elec = elec
} else if string(c.Family) == "ge" {
k, _ := strconv.Atoi(string(c.Qualifier[:]))
v, _ := strconv.Atoi(string(c.Value[:]))
elec[k] = v
gah.Elec = elec
}
if string(c.Family) == "fs" {
k, _ := strconv.Atoi(string(c.Qualifier[:]))
v, _ := strconv.Atoi(string(c.Value[:]))
con[k] = v
fah.Contract = con
} else if string(c.Family) == "gs" {
k, _ := strconv.Atoi(string(c.Qualifier[:]))
v, _ := strconv.Atoi(string(c.Value[:]))
con[k] = v
gah.Contract = con
}
}
}
res["fan"] = fah
res["not_fan"] = gah
return
}
// UpIncr for Play/Dm/Reply/Fav/Share/Elec/Coin incr.
func (d *Dao) UpIncr(c context.Context, mid int64, ty int8, now string) (res *data.UpDataIncrMeta, err error) {
var (
result *hrpc.Result
ctx, cancel = context.WithTimeout(c, d.hbaseTimeOut)
tableName string
IncrKey string
key = hbaseMd5Key(mid)
)
defer cancel()
switch {
case ty == data.Play:
tableName = HBaseUpPlayInc + now
case ty == data.Dm:
tableName = HBaseUpDmInc + now
case ty == data.Reply:
tableName = HBaseUpReplyInc + now
case ty == data.Share:
tableName = HBaseUpShareInc + now
case ty == data.Coin:
tableName = HBaseUpCoinInc + now
case ty == data.Fav:
tableName = HBaseUpFavInc + now
case ty == data.Elec:
tableName = HBaseUpElecInc + now
}
IncrKey, _ = data.IncrTy(ty)
if result, err = d.hbase.GetStr(ctx, tableName, key); err != nil {
log.Error("UpIncr d.hbase.GetStr tableName(%s)|mid(%d)|key(%v)|error(%v)", tableName, mid, key, err)
err = ecode.CreativeDataErr
return
}
if result == nil || len(result.Cells) == 0 {
log.Warn("UpIncr no data tableName(%s)|mid(%d)|key(%v)", tableName, mid, key)
return
}
families := make(map[string]string, 4)
families["u"] = "" //单日播放增量 u:play ...
families["av"] = "" //播放top稿件 av:1
families["v"] = "" //top稿件播放增量 v:1
families["rk"] = "" //up主播放量排名 rk: [tid]
aids := make(map[int]int64)
incs := make(map[int]int)
rk := make(map[int]int)
var incr int
for _, c := range result.Cells {
if c == nil {
continue
}
if _, ok := families[string(c.Family)]; ok {
if string(c.Family) == "av" {
k, _ := strconv.Atoi(string(c.Qualifier[:]))
v, _ := strconv.ParseInt(string(c.Value[:]), 10, 64)
aids[k] = v
} else if string(c.Family) == "v" {
k, _ := strconv.Atoi(string(c.Qualifier[:]))
v, _ := strconv.Atoi(string(c.Value[:]))
incs[k] = v
} else if string(c.Family) == "rk" {
k, _ := strconv.Atoi(string(c.Qualifier[:]))
v, _ := strconv.Atoi(string(c.Value[:]))
rk[k] = v
} else if string(c.Family) == "u" {
if bytes.Equal(c.Qualifier, []byte(IncrKey)) {
v, _ := strconv.Atoi(string(c.Value[:]))
if v < 0 {
v = 0
}
incr = v
}
}
}
}
res = &data.UpDataIncrMeta{}
res.Incr = incr
res.TopAIDList = aids
res.TopIncrList = incs
res.Rank = rk
return
}
// ThirtyDayArchive for Play/Dm/Reply/Fav/Share/Elec/Coin for archive 30 days.
func (d *Dao) ThirtyDayArchive(c context.Context, mid int64, ty int8) (res []*data.ThirtyDay, err error) {
var (
result *hrpc.Result
ctx, cancel = context.WithTimeout(c, time.Duration(d.c.HBase.ReadTimeout))
tableName string
key = hbaseMd5Key(mid)
)
defer cancel()
switch {
case ty == data.Play:
tableName = HBasePlayArc
case ty == data.Dm:
tableName = HBaseDmArc
case ty == data.Reply:
tableName = HBaseReplyArc
case ty == data.Share:
tableName = HBaseShareArc
case ty == data.Coin:
tableName = HBaseCoinArc
case ty == data.Fav:
tableName = HBaseFavArc
case ty == data.Elec:
tableName = HBaseElecArc
case ty == data.Like:
tableName = HBaseLikeArc
}
if result, err = d.hbase.GetStr(ctx, tableName, key); err != nil {
log.Error("ThirtyDayArchive d.hbase.GetStr tableName(%s)|mid(%d)|key(%v)|error(%v)", tableName, mid, key, err)
err = ecode.CreativeDataErr
return
}
if result == nil || len(result.Cells) == 0 {
log.Warn("ThirtyDay no data tableName(%s)|mid(%d)|key(%v)", tableName, mid, key)
return
}
res = make([]*data.ThirtyDay, 0, len(result.Cells))
for _, c := range result.Cells {
if c == nil {
continue
}
qual := string(c.Qualifier[:])
val := string(c.Value[:])
if string(c.Family) == "u" {
t, v, err := parseKeyValue(qual, val)
if err != nil {
break
}
td := &data.ThirtyDay{}
td.DateKey = t
td.TotalIncr = v
res = append(res, td)
}
}
log.Info("ThirtyDayArchive mid(%d) type(%d) return data(%+v)", mid, ty, res)
return
}
func parseKeyValue(k string, v string) (timestamp, value int64, err error) {
tm, err := time.Parse("20060102", k)
if err != nil {
log.Error("time.Parse error(%v)", err)
return
}
timestamp = tm.Unix()
value, err = strconv.ParseInt(v, 10, 64)
if err != nil {
log.Error("strconv.ParseInt error(%v)", err)
}
return
}

View File

@@ -0,0 +1,178 @@
package data
import (
"context"
"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)
dt = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.ViewerBase(c, mid, dt)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDataViewerArea(t *testing.T) {
convey.Convey("ViewerArea", 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 := d.ViewerArea(c, mid, dt)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
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 := d.ViewerTrend(c, mid, dt)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDataRelationFansDay(t *testing.T) {
convey.Convey("RelationFansDay", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.RelationFansDay(c, mid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDataRelationFansHistory(t *testing.T) {
convey.Convey("RelationFansHistory", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
month = ""
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.RelationFansHistory(c, mid, month)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDataRelationFansMonth(t *testing.T) {
convey.Convey("RelationFansMonth", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.RelationFansMonth(c, mid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDataViewerActionHour(t *testing.T) {
convey.Convey("ViewerActionHour", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
dt = ""
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.ViewerActionHour(c, mid, dt)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDataUpIncr(t *testing.T) {
convey.Convey("UpIncr", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
ty = int8(0)
now = ""
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.UpIncr(c, mid, ty, now)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDataThirtyDayArchive(t *testing.T) {
convey.Convey("ThirtyDayArchive", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
ty = int8(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.ThirtyDayArchive(c, mid, ty)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDataparseKeyValue(t *testing.T) {
convey.Convey("parseKeyValue", t, func(ctx convey.C) {
var (
k = "20060102"
v = "123"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
timestamp, value, err := parseKeyValue(k, v)
ctx.Convey("Then err should be nil.timestamp,value should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(value, convey.ShouldNotBeNil)
ctx.So(timestamp, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,115 @@
package data
import (
"context"
"time"
"go-common/app/admin/main/up/conf"
"go-common/library/cache/memcache"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/database/hbase.v2"
)
// Dao is data dao.
type Dao struct {
c *conf.Config
// http
client *bm.Client
statClient *bm.Client
// uri
statURI string
tagURI string
tagV2URI string
coverBFSURI string
// mc
mc *memcache.Pool
//mcExpire int32
//mcIdxExpire int32
//statCacheOn bool
// hbase
hbase *hbase.Client
hbaseTimeOut time.Duration
// chan
missch chan func()
}
// New init dao
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
// http
client: bm.NewClient(c.HTTPClient.Slow),
statClient: bm.NewClient(c.HTTPClient.Slow),
statURI: c.Host.Data + _statURL,
tagURI: c.Host.Tag + _tagURL,
tagV2URI: c.Host.Tag + _tagv2URL,
coverBFSURI: c.Host.Coverrec + _coverURL,
// memcache
//mc: memcache.NewPool(c.Memcache.Data.Config),
//mcExpire: int32(time.Duration(c.Memcache.Data.DataExpire) / time.Second),
//mcIdxExpire: int32(time.Duration(c.Memcache.Data.IndexExpire) / time.Second),
//statCacheOn: c.StatCacheOn,
// hbase
hbase: hbase.NewClient(c.HBase.Config),
// chan
missch: make(chan func(), 1024),
hbaseTimeOut: time.Duration(time.Millisecond * 200),
}
return
}
// Stat get user stat play/fans/...
//func (d *Dao) Stat(c context.Context, ip string, mid int64) (st *data.Stat, err error) {
// // try cache
// if st, _ = d.statCache(c, mid); st != nil {
// return
// }
// // from api
// if st, err = d.stat(c, mid, ip); st != nil {
// d.AddCache(func() {
// d.addStatCache(context.Background(), mid, st)
// })
// }
// return
//}
// UpStat get up stat from hbase
//func (d *Dao) UpStat(c context.Context, mid int64, dt string) (st *data.UpBaseStat, err error) {
// // try cache
// if d.statCacheOn {
// if st, _ = d.upBaseStatCache(c, mid, dt); st != nil {
// log.Info("upBaseStatCache cache found mid(%d)", mid)
// return
// }
// }
// // from hbase
// if st, err = d.BaseUpStat(c, mid, dt); st != nil {
// d.AddCache(func() {
// d.addUpBaseStatCache(context.Background(), mid, dt, st)
// })
// }
// return
//}
// Ping ping success.
func (d *Dao) Ping(c context.Context) (err error) {
conn := d.mc.Get(c)
defer conn.Close()
if err = conn.Set(&memcache.Item{Key: "ping", Value: []byte("pong"), Expiration: 0}); err != nil {
log.Error("mc.ping.Store error(%v)", err)
}
return
}
// Close mc close
func (d *Dao) Close() (err error) {
if d.mc != nil {
d.mc.Close()
}
if d.hbase != nil {
d.hbase.Close()
}
return
}

View File

@@ -0,0 +1,49 @@
package data
import (
"flag"
"os"
"strings"
"testing"
"go-common/app/admin/main/up/conf"
"gopkg.in/h2non/gock.v1"
)
var (
d *Dao
)
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)
}
d = New(conf.Conf)
d.client.SetTransport(gock.DefaultTransport)
os.Exit(m.Run())
}
func httpMock(method, url string) *gock.Request {
r := gock.New(url)
r.Method = strings.ToUpper(method)
return r
}

View File

@@ -0,0 +1,96 @@
package data
var (
//HBaseVideoTablePrefix 播放流失分布
HBaseVideoTablePrefix = "video_play_churn_"
//HBaseArchiveTablePrefix 分类分端播放
HBaseArchiveTablePrefix = "video_play_category_"
//HBaseAreaTablePrefix 地区播放
HBaseAreaTablePrefix = "video_play_area_"
//HBaseUpStatTablePrefix up主概况
HBaseUpStatTablePrefix = "up_stats_"
//HBaseUpViewerBase 观众数据,性别年龄分布 + 设备分布
HBaseUpViewerBase = "up_viewer_base_"
//HBaseUpViewerArea 地区分布
HBaseUpViewerArea = "up_viewer_area_"
//HBaseUpViewerTrend 内容倾向
HBaseUpViewerTrend = "up_viewer_trend_"
//HBaseUpViewerActionHour 行为时间分布
HBaseUpViewerActionHour = "up_viewer_action_hour_"
//HBaseUpRelationFansDay 日维度 最近30天 只保留31天
HBaseUpRelationFansDay = "up_relation_fans_day"
// HBaseUpRelationFansHistory 日维度 各月份每日数据,日更,永久保存
HBaseUpRelationFansHistory = "up_relation_fans_history"
//HBaseUpRelationFansMonth 年维度 2017.8月以后的数据永久保存
HBaseUpRelationFansMonth = "up_relation_fans_month"
//HBaseUpPlayInc 我的概况 播放相关
HBaseUpPlayInc = "up_play_inc_"
//HBaseUpDmInc 弹幕相关
HBaseUpDmInc = "up_dm_inc_"
//HBaseUpReplyInc 评论相关
HBaseUpReplyInc = "up_reply_inc_"
//HBaseUpShareInc 分享相关
HBaseUpShareInc = "up_share_inc_"
//HBaseUpCoinInc 投币相关
HBaseUpCoinInc = "up_coin_inc_"
//HBaseUpFavInc 收藏相关
HBaseUpFavInc = "up_fav_inc_"
//HBaseUpElecInc 充电相关
HBaseUpElecInc = "up_elec_inc_"
//HBaseUpFansAnalysis 粉丝管理
HBaseUpFansAnalysis = "up_fans_analysis"
//HBaseUpPlaySourceAnalysis 播放来源
HBaseUpPlaySourceAnalysis = "up_play_analysis"
//HBaseUpArcPlayAnalysis 平均观看时长、播放用户数、留存率
HBaseUpArcPlayAnalysis = "up_archive_play_analysis"
//HBaseUpArcQuery 稿件索引表
HBaseUpArcQuery = "up_archive_query"
//HBasePlayArc 播放相关 archive for 30 days
HBasePlayArc = "up_play_trend"
//HBaseDmArc 弹幕相关
HBaseDmArc = "up_dm_trend"
//HBaseReplyArc 评论相关
HBaseReplyArc = "up_reply_trend"
//HBaseShareArc 分享相关
HBaseShareArc = "up_share_trend"
//HBaseCoinArc 投币相关
HBaseCoinArc = "up_coin_trend"
//HBaseFavArc 收藏相关
HBaseFavArc = "up_fav_trend"
//HBaseElecArc 充电相关
HBaseElecArc = "up_elec_trend"
//HBaseLikeArc 点赞相关
HBaseLikeArc = "up_like_trend"
//HBaseFamilyPlat family
HBaseFamilyPlat = []byte("v")
//HBaseColumnAid aid
HBaseColumnAid = []byte("avid")
//HBaseColumnWebPC pc
HBaseColumnWebPC = []byte("plat0")
//HBaseColumnWebH5 h5
HBaseColumnWebH5 = []byte("plat1")
//HBaseColumnOutsite out
HBaseColumnOutsite = []byte("plat2")
//HBaseColumnIOS ios
HBaseColumnIOS = []byte("plat3")
//HBaseColumnAndroid android
HBaseColumnAndroid = []byte("plat4")
//HBaseColumnElse else
HBaseColumnElse = []byte("else")
//HBaseColumnFans fans
HBaseColumnFans = []byte("fans")
//HBaseColumnGuest guest
HBaseColumnGuest = []byte("guest")
//HBaseColumnAll all
HBaseColumnAll = []byte("all")
//HBaseColumnCoin coin
HBaseColumnCoin = []byte("coin")
//HBaseColumnElec elec
HBaseColumnElec = []byte("elec")
//HBaseColumnFav fav
HBaseColumnFav = []byte("fav")
//HBaseColumnShare share
HBaseColumnShare = []byte("share")
)

View File

@@ -0,0 +1 @@
package data

View File

@@ -0,0 +1,226 @@
package data
import (
"bytes"
"crypto/md5"
"encoding/hex"
"sort"
"strconv"
"time"
"go-common/app/interface/main/creative/model/data"
"go-common/library/ecode"
"go-common/library/log"
"github.com/tsuna/gohbase/hrpc"
"golang.org/x/net/context"
)
func hbaseMd5Key(aid int64) string {
hasher := md5.New()
hasher.Write([]byte(strconv.Itoa(int(aid))))
return hex.EncodeToString(hasher.Sum(nil))
}
// VideoQuitPoints get video quit points.
func (d *Dao) VideoQuitPoints(c context.Context, cid int64) (res []int64, err error) {
var (
ctx, cancel = context.WithTimeout(c, time.Duration(d.c.HBase.ReadTimeout))
tableName = HBaseVideoTablePrefix + time.Now().AddDate(0, 0, -1).Add(-12*time.Hour).Format("20060102") // change table at 12:00am
backupTableName = HBaseVideoTablePrefix + time.Now().AddDate(0, 0, -2).Add(-12*time.Hour).Format("20060102") // change table at 12:00am
key = hbaseMd5Key(cid)
)
defer cancel()
result, err := d.hbase.GetStr(ctx, tableName, key)
if err != nil {
if result, err = d.hbase.GetStr(ctx, backupTableName, key); err != nil {
log.Error("VideoQuitPoints d.hbase.GetStr backupTableName(%s)|cid(%d)|key(%v)|error(%v)", backupTableName, cid, key, err)
err = ecode.CreativeDataErr
return
}
}
if result == nil {
return
}
// get parts and max part for fill res
partMap := make(map[int]int64)
maxPart := 0
for _, c := range result.Cells {
if c != nil {
part, _ := strconv.Atoi(string(c.Qualifier[:]))
per, _ := strconv.ParseInt(string(c.Value[:]), 10, 64)
partMap[part] = per
if part > maxPart {
maxPart = part
}
}
}
var restPercent int64 = 10000 // start from 100%
for i := 1; i <= maxPart; i++ {
if _, ok := partMap[i]; ok {
restPercent = restPercent - partMap[i]
}
res = append(res, restPercent)
}
return
}
// ArchiveStat get the stat of archive.
func (d *Dao) ArchiveStat(c context.Context, aid int64) (stat *data.ArchiveData, err error) {
var (
ctx, cancel = context.WithTimeout(c, time.Duration(d.c.HBase.ReadTimeout))
tableName = HBaseArchiveTablePrefix + time.Now().AddDate(0, 0, -1).Add(-12*time.Hour).Format("20060102") // change table at 12:00am
backupTableName = HBaseArchiveTablePrefix + time.Now().AddDate(0, 0, -2).Add(-12*time.Hour).Format("20060102") // change table at 12:00am
key = hbaseMd5Key(aid)
)
defer cancel()
result, err := d.hbase.GetStr(ctx, tableName, key)
if err != nil {
if result, err = d.hbase.GetStr(ctx, backupTableName, key); err != nil {
log.Error("ArchiveStat d.hbase.GetStr backupTableName(%s)|aid(%d)|key(%v)|error(%v)", backupTableName, aid, key, err)
err = ecode.CreativeDataErr
return
}
}
if result == nil {
return
}
stat = &data.ArchiveData{}
stat.ArchiveSource = &data.ArchiveSource{}
stat.ArchiveGroup = &data.ArchiveGroup{}
stat.ArchiveStat = &data.ArchiveStat{}
for _, c := range result.Cells {
if c == nil {
continue
}
v, _ := strconv.ParseInt(string(c.Value[:]), 10, 64)
if !bytes.Equal(c.Family, HBaseFamilyPlat) {
continue
}
switch {
case bytes.Equal(c.Qualifier, HBaseColumnWebPC):
stat.ArchiveSource.WebPC = v
case bytes.Equal(c.Qualifier, HBaseColumnWebH5):
stat.ArchiveSource.WebH5 = v
case bytes.Equal(c.Qualifier, HBaseColumnOutsite):
stat.ArchiveSource.Outsite = v
case bytes.Equal(c.Qualifier, HBaseColumnIOS):
stat.ArchiveSource.IOS = v
case bytes.Equal(c.Qualifier, HBaseColumnAndroid):
stat.ArchiveSource.Android = v
case bytes.Equal(c.Qualifier, HBaseColumnElse):
stat.ArchiveSource.Others = v
case bytes.Equal(c.Qualifier, HBaseColumnFans):
stat.ArchiveGroup.Fans = v
case bytes.Equal(c.Qualifier, HBaseColumnGuest):
stat.ArchiveGroup.Guest = v
case bytes.Equal(c.Qualifier, HBaseColumnAll):
stat.ArchiveStat.Play = v
case bytes.Equal(c.Qualifier, HBaseColumnCoin):
stat.ArchiveStat.Coin = v
case bytes.Equal(c.Qualifier, HBaseColumnElec):
stat.ArchiveStat.Elec = v
case bytes.Equal(c.Qualifier, HBaseColumnFav):
stat.ArchiveStat.Fav = v
case bytes.Equal(c.Qualifier, HBaseColumnShare):
stat.ArchiveStat.Share = v
}
}
stat.ArchiveSource.Mainsite = stat.ArchiveSource.WebPC + stat.ArchiveSource.WebH5
stat.ArchiveSource.Mobile = stat.ArchiveSource.Android + stat.ArchiveSource.IOS
return
}
// ArchiveArea get the count of area.
func (d *Dao) ArchiveArea(c context.Context, aid int64) (res []*data.ArchiveArea, err error) {
var (
ctx, cancel = context.WithTimeout(c, time.Duration(d.c.HBase.ReadTimeout))
tableName = HBaseAreaTablePrefix + time.Now().AddDate(0, 0, -1).Add(-12*time.Hour).Format("20060102") // change table at 12:00am
backupTableName = HBaseAreaTablePrefix + time.Now().AddDate(0, 0, -2).Add(-12*time.Hour).Format("20060102") // change table at 12:00am
key = hbaseMd5Key(aid)
)
defer cancel()
result, err := d.hbase.GetStr(ctx, tableName, key)
if err != nil {
if result, err = d.hbase.GetStr(ctx, backupTableName, key); err != nil {
log.Error("ArchiveArea d.hbase.GetStr backupTableName(%s)|aid(%d)|key(%v)|error(%v)", backupTableName, aid, key, err)
err = ecode.CreativeDataErr
return
}
}
if result == nil {
return
}
var countArr []int
countMap := make(map[int64][]*data.ArchiveArea)
countSet := make(map[int]struct{}) // empty struct{} for saving memory
for _, c := range result.Cells {
if c != nil {
area := &data.ArchiveArea{}
area.Location = string(c.Qualifier[:])
area.Count, _ = strconv.ParseInt(string(c.Value[:]), 10, 64)
countMap[area.Count] = append(countMap[area.Count], area)
countSet[int(area.Count)] = struct{}{}
}
}
for key := range countSet {
countArr = append(countArr, key)
}
sort.Sort(sort.Reverse(sort.IntSlice(countArr)))
for _, c := range countArr {
if _, ok := countMap[int64(c)]; ok {
res = append(res, countMap[int64(c)]...)
}
if len(res) >= 10 {
res = res[:10] // exact 10 item
break
}
}
return
}
// BaseUpStat get base up stat.
func (d *Dao) BaseUpStat(c context.Context, mid int64, date string) (stat *data.UpBaseStat, err error) {
var (
result *hrpc.Result
ctx, cancel = context.WithTimeout(c, d.hbaseTimeOut)
tableName = HBaseUpStatTablePrefix + date // change table at 12:00am
key = hbaseMd5Key(mid)
)
defer cancel()
if result, err = d.hbase.GetStr(ctx, tableName, key); err != nil {
log.Error("BaseUpStat d.hbase.GetStr tableName(%s)|mid(%d)|key(%v)|error(%v)", tableName, mid, key, err)
err = ecode.CreativeDataErr
return
}
if result == nil {
return
}
stat = &data.UpBaseStat{}
for _, c := range result.Cells {
if c == nil {
continue
}
v, _ := strconv.ParseInt(string(c.Value[:]), 10, 64)
if !bytes.Equal(c.Family, []byte("u")) {
continue
}
switch {
case bytes.Equal(c.Qualifier, []byte("play")):
stat.View = v
case bytes.Equal(c.Qualifier, []byte("dm")):
stat.Dm = v
case bytes.Equal(c.Qualifier, []byte("reply")):
stat.Reply = v
case bytes.Equal(c.Qualifier, []byte("fans")):
stat.Fans = v
case bytes.Equal(c.Qualifier, []byte("fav")):
stat.Fav = v
case bytes.Equal(c.Qualifier, []byte("like")):
stat.Like = v
case bytes.Equal(c.Qualifier, []byte("sh")):
stat.Share = v
}
}
return
}

View File

@@ -0,0 +1,148 @@
package data
import (
"context"
"fmt"
"sync"
"time"
"go-common/app/admin/main/up/model/datamodel"
"go-common/app/admin/main/up/util/hbaseutil"
"go-common/library/log"
"go-common/library/sync/errgroup"
"github.com/tsuna/gohbase/hrpc"
)
// 这里是集群2的数据请求
const (
// HbaseUpArchiveInfoPrefix archive info表
HbaseUpArchiveInfoPrefix = "upcrm:up_influence"
// HbaseUpArchiveTagInfoPrefix tag表
HbaseUpArchiveTagInfoPrefix = "upcrm:up_archive_tag_info"
// HbaseUpArchiveTypeInfoPrefix 分区表
HbaseUpArchiveTypeInfoPrefix = "upcrm:up_archive_type_info"
)
var (
//ErrInvalidDataType invalid data type
ErrInvalidDataType = fmt.Errorf("invalid data type")
)
//UpArchiveDataType data type
type UpArchiveDataType int
const (
//DataTypeDay7 7 day
DataTypeDay7 UpArchiveDataType = 1
//DataTypeDay30 30 day
DataTypeDay30 UpArchiveDataType = 2
//DataTypeDay90 90 day
DataTypeDay90 UpArchiveDataType = 3
//DataTypeDay180 180 day
DataTypeDay180 UpArchiveDataType = 4
//DataTypeDayAll accumulated
DataTypeDayAll UpArchiveDataType = 5
)
var (
dataType2FamilyMap = map[UpArchiveDataType]string{
DataTypeDay7: "d7",
DataTypeDay30: "d30",
DataTypeDay90: "d90",
DataTypeDay180: "d180",
DataTypeDayAll: "dall",
}
)
//UpArchiveInfo get up archive info
func (d *Dao) UpArchiveInfo(c context.Context, mids []int64, dataType UpArchiveDataType) (result map[int64]*datamodel.UpArchiveData, err error) {
var now = time.Now()
var date = now.AddDate(0, 0, -1).Add(-12 * time.Hour).Format("20060102")
var tableName = generateTableName(HbaseUpArchiveInfoPrefix, date)
var family, ok = dataType2FamilyMap[dataType]
if !ok {
log.Error("invalid data type, type=%d", dataType)
err = ErrInvalidDataType
return
}
var group, ctx = errgroup.WithContext(c)
var lock sync.Mutex
result = make(map[int64]*datamodel.UpArchiveData)
for _, mid := range mids {
var copymid = mid
group.Go(
func() error {
var data = &datamodel.UpArchiveData{}
var key = hbaseMd5Key(copymid)
if e := d.getHbaseRowResult(ctx, tableName, key, data, hrpc.Families(map[string][]string{family: nil})); e != nil {
log.Error("get up archive info fail, mid=%d, err=%v", err)
return nil
}
lock.Lock()
result[copymid] = data
lock.Unlock()
return nil
})
}
if err = group.Wait(); err != nil {
log.Error("batch get fail, err=%v", err)
return
}
log.Info("get archive info ok, find result count=%d", len(result))
return
}
//UpArchiveTagInfo get up archive tag info
func (d *Dao) UpArchiveTagInfo(c context.Context, mid int64) (result datamodel.UpArchiveTagData, err error) {
var now = time.Now()
var date = now.AddDate(0, 0, -1).Add(-12 * time.Hour).Format("20060102")
var tableName = generateTableName(HbaseUpArchiveTagInfoPrefix, date)
var key = hbaseMd5Key(mid)
if err = d.getHbaseRowResult(c, tableName, key, &result); err != nil {
log.Error("get up archive tag info fail, err=%v", err)
}
return
}
//UpArchiveTypeInfo get up archive type info
func (d *Dao) UpArchiveTypeInfo(c context.Context, mid int64) (result datamodel.UpArchiveTypeData, err error) {
var now = time.Now()
var date = now.AddDate(0, 0, -1).Add(-12 * time.Hour).Format("20060102")
var tableName = generateTableName(HbaseUpArchiveTypeInfoPrefix, date)
var key = hbaseMd5Key(mid)
if err = d.getHbaseRowResult(c, tableName, key, &result); err != nil {
log.Error("get up archive type info fail, err=%v", err)
}
return
}
func (d *Dao) getHbaseRowResult(c context.Context, table, key string, result interface{}, options ...func(hrpc.Call) error) (err error) {
var ctx, cancel = context.WithTimeout(c, time.Duration(d.c.HBase.ReadTimeout))
defer cancel()
res, err := d.hbase.GetStr(ctx, table, key, options...)
if err != nil {
log.Error("fail to get data from hbase, table=%s, key=%s, err=%v", table, key, err)
return
}
if len(res.Cells) == 0 {
log.Warn("no cells get, table=%s, key=%s, err=%v", table, key, err)
return
}
var parser = hbaseutil.Parser{}
if err = parser.Parse(res.Cells, result); err != nil {
log.Error("parse data fail, table=%s, key=%s, err=%v", table, key, err)
return
}
return
}
// dont use date string
func generateTableName(prefix, date string) string {
return prefix
}

View File

@@ -0,0 +1,102 @@
package data
import (
"context"
"reflect"
"testing"
"github.com/bouk/monkey"
"github.com/tsuna/gohbase/hrpc"
"go-common/app/admin/main/up/model/datamodel"
hbase "go-common/library/database/hbase.v2"
"github.com/smartystreets/goconvey/convey"
)
func TestDataUpArchiveInfo(t *testing.T) {
convey.Convey("UpArchiveInfo", t, func(ctx convey.C) {
var (
c = context.Background()
mids = []int64{}
dataType UpArchiveDataType
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.UpArchiveInfo(c, mids, dataType)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(result, convey.ShouldBeNil)
})
})
})
}
func TestDataUpArchiveTagInfo(t *testing.T) {
convey.Convey("UpArchiveTagInfo", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.UpArchiveTagInfo(c, mid)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestDataUpArchiveTypeInfo(t *testing.T) {
convey.Convey("UpArchiveTypeInfo", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.UpArchiveTypeInfo(c, mid)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestDatagetHbaseRowResult(t *testing.T) {
convey.Convey("getHbaseRowResult", t, func(ctx convey.C) {
var (
c = context.Background()
table = "crm"
key = "123"
result = datamodel.UpArchiveTypeData{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
guard := monkey.PatchInstanceMethod(reflect.TypeOf(d.hbase), "GetStr", func(_ *hbase.Client, _ context.Context, _, _ string, _ ...func(hrpc.Call) error) (*hrpc.Result, error) {
res := &hrpc.Result{}
return res, nil
})
defer guard.Unpatch()
err := d.getHbaseRowResult(c, table, key, &result)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDatagenerateTableName(t *testing.T) {
convey.Convey("generateTableName", t, func(ctx convey.C) {
var (
prefix = ""
date = ""
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := generateTableName(prefix, date)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,87 @@
package data
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDatahbaseMd5Key(t *testing.T) {
convey.Convey("hbaseMd5Key", t, func(ctx convey.C) {
var (
aid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := hbaseMd5Key(aid)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDataVideoQuitPoints(t *testing.T) {
convey.Convey("VideoQuitPoints", t, func(ctx convey.C) {
var (
c = context.Background()
cid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.VideoQuitPoints(c, cid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDataArchiveStat(t *testing.T) {
convey.Convey("ArchiveStat", t, func(ctx convey.C) {
var (
c = context.Background()
aid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
stat, err := d.ArchiveStat(c, aid)
ctx.Convey("Then err should be nil.stat should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(stat, convey.ShouldBeNil)
})
})
})
}
func TestDataArchiveArea(t *testing.T) {
convey.Convey("ArchiveArea", t, func(ctx convey.C) {
var (
c = context.Background()
aid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.ArchiveArea(c, aid)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}
func TestDataBaseUpStat(t *testing.T) {
convey.Convey("BaseUpStat", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
date = ""
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
stat, err := d.BaseUpStat(c, mid, date)
ctx.Convey("Then err should be nil.stat should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(stat, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,227 @@
package data
import (
"context"
"encoding/binary"
"strconv"
"time"
"go-common/app/admin/main/up/model/datamodel"
"go-common/app/admin/main/up/util/hbaseutil"
"go-common/library/ecode"
"go-common/library/log"
"github.com/tsuna/gohbase/hrpc"
)
// reverse for string.
func reverseString(s string) string {
rs := []rune(s)
l := len(rs)
for f, t := 0, l-1; f < t; f, t = f+1, t-1 {
rs[f], rs[t] = rs[t], rs[f]
}
ns := string(rs)
if l < 10 {
for i := 0; i < 10-l; i++ {
ns = ns + "0"
}
}
return ns
}
// 粉丝管理 - up_fans_analysis
// mid倒置补0 补满共10位+0 +yyyyMMdd 累计数据
// mid倒置补0 补满共10位+1 +yyyyMMdd 7日数据
// mid倒置补0 补满共10位+2 +yyyyMMdd 30日数据
// mid倒置补0 补满共10位+3 +yyyyMMdd 90日数据
func fansRowKey(id int64, ty int) string {
idStr := strconv.FormatInt(id, 10)
s := reverseString(idStr)
s = s + strconv.Itoa(ty) + time.Now().AddDate(0, 0, -1).Add(-12*time.Hour).Format("20060102")
return s
}
// 稿件索引表 - up_archive_query
// [mid倒置补010位] + [投稿年月4位] + [原创/转载1位]
func arcQueryKey(id int64, dt string, cp int) string {
idStr := strconv.FormatInt(id, 10)
cpStr := strconv.Itoa(cp)
s := reverseString(idStr)
s = s + dt + cpStr
return s
}
// UpFansAnalysis for web fans analysis.
func (d *Dao) UpFansAnalysis(c context.Context, mid int64, ty int) (res *datamodel.FanInfo, err error) {
var (
result *hrpc.Result
ctx, cancel = context.WithTimeout(c, time.Duration(d.c.HBase.ReadTimeout))
tableName = HBaseUpFansAnalysis
//summary = make(map[string]int32) //total & classify proportion
//rankDr = make(map[string]int32) //播放时长 mid list
//rankVideoAct = make(map[string]int32) //视频互动 mid list
//rankDyAct = make(map[string]int32) //动态互动 mid list
rankMap = make(map[string]map[string]int32) //top 10 rank list
source = make(map[string]int32) //source proportion
rowkey = fansRowKey(mid, ty)
parser = hbaseutil.Parser{}
)
res = new(datamodel.FanInfo)
defer cancel()
log.Info("UpFansAnalysisForWeb mid(%d)|rowkey(%s)", mid, rowkey)
if result, err = d.hbase.GetStr(ctx, tableName, rowkey, hrpc.Families(map[string][]string{"f": nil})); err != nil {
log.Error("d.hbase.GetStr tableName(%s)|mid(%d)|rowkey(%v)|error(%v)", tableName, mid, rowkey, err)
err = ecode.CreativeDataErr
return
}
if result == nil || len(result.Cells) == 0 {
log.Warn("UpFansAnalysisForWeb no data tableName(%s)|mid(%d)|rowkey(%v)", tableName, mid, rowkey)
return
}
var summary datamodel.FanSummaryData
err = parser.Parse(result.Cells, &summary)
if err != nil {
log.Error("convert from hbase fail, err=%v", err)
return
}
/*
for _, c := range result.Cells {
if c == nil {
continue
}
if string(c.Family) == "f" {
k := string(c.Qualifier[:])
var v int32
if len(c.Value) == 4 {
v = byteToInt32(c.Value)
switch k {
case "all": //总粉丝
summary.Total = v
//summary["total"] = v
case "inc": //新增粉丝
summary.Inc = v
case "act": //活跃粉丝
summary.Active = v
// summary["active"] = v
//case "mdl": //领取勋章粉丝
// summary["medal"] = v
//case "elec": //充电粉丝
// summary["elec"] = v
//case "act_diff": //活跃粉丝(增量)
// summary["act_diff"] = v
//case "mdl_diff": //领取勋章粉丝(增量)
// summary["mdl_diff"] = v
//case "elec_diff": //充电粉丝(增量)
// summary["elec_diff"] = v
//case "v": //播放粉丝占比*10000
// summary["v"] = v
//case "dm": //弹幕粉丝占比*10000
// summary["dm"] = v
//case "r": //评论粉丝占比*10000
// summary["r"] = v
//case "c": //投币粉丝占比*10000
// summary["c"] = v
// //新增粉丝活跃占比
//case "inter": //互动活跃度*10000
// summary["inter"] = v
//case "vv": //观看活跃度*10000
// summary["vv"] = v
//case "da": //弹幕粉丝占比*10000
// summary["da"] = v
//case "re": //评论粉丝占比*10000
// summary["re"] = v
//case "co": //投币粉丝占比*10000
// summary["co"] = v
//case "fv": //收藏粉丝占比*10000
// summary["fv"] = v
//case "sh": //分享粉丝占比*10000
// summary["sh"] = v
//case "lk": //点赞粉丝占比*10000
// summary["lk"] = v
}
} else {
log.Error("UpFansAnalysisForWeb family[f] get dirty tableName(%s)|mid(%d)|rowkey(%s)|value(%+v)", tableName, mid, rowkey, c.Value)
}
}
if string(c.Family) == "t" {
var v int32
if len(c.Value) == 4 {
v = int32(binary.BigEndian.Uint32(c.Value))
} else {
log.Error("UpFansAnalysisForWeb family t get dirty tableName(%s)|mid(%d)|rowkey(%s)|value(%+v)", tableName, mid, fansRowKey(mid, ty), c.Value)
}
if strings.Contains(string(c.Qualifier[:]), "dr") {
rankDr[string(c.Qualifier[:])] = v
}
if strings.Contains(string(c.Qualifier[:]), "act") {
rankVideoAct[string(c.Qualifier[:])] = v
}
if strings.Contains(string(c.Qualifier[:]), "dy") {
rankDyAct[string(c.Qualifier[:])] = v
}
}
if string(c.Family) == "s" {
var v int32
if len(c.Value) == 4 {
v = int32(binary.BigEndian.Uint32(c.Value))
} else {
log.Error("UpFansAnalysisForWeb family[t] get dirty data tableName(%s)|mid(%d)|rowkey(%s)|value(%+v)", tableName, mid, rowkey, c.Value)
}
if strings.Contains(string(c.Qualifier[:]), "pf") {
if pk, ok := fanSource[string(c.Qualifier[:])]; ok {
source[pk] = v
}
}
}
}
for _, k := range fanSource { //粉丝来源页面占比如果数据平台未返回,则设置对应的key
if _, ok := source[k]; !ok {
source[k] = 0
}
}
*/
log.Info("UpFansAnalysisForWebRankMap mid(%d)|rowkey(%s)|summary(%+v)|rankMap(%+v)|source(%+v)", mid, rowkey, summary, rankMap, source)
res.Summary = summary
return
}
// UpArcQuery for play aids by mid.
func (d *Dao) UpArcQuery(c context.Context, mid int64, dt string, cp int) (res []int64, err error) {
var (
result *hrpc.Result
ctx, cancel = context.WithTimeout(c, time.Duration(d.c.HBase.ReadTimeout))
tableName = HBaseUpArcQuery
rowkey = arcQueryKey(mid, dt, cp)
)
defer cancel()
log.Info("UpArcQuery mid(%d)|rowkey(%s)", mid, rowkey)
if result, err = d.hbase.GetStr(ctx, tableName, rowkey); err != nil {
log.Error("d.hbase.GetStr tableName(%s)|mid(%d)|rowkey(%s)|error(%v)", tableName, mid, rowkey, err)
err = ecode.CreativeDataErr
return
}
if result == nil || len(result.Cells) == 0 {
log.Warn("UpArcQuery no data tableName(%s)|mid(%d)|rowkey(%s)", tableName, mid, rowkey)
return
}
res = make([]int64, 0)
for _, c := range result.Cells {
if c == nil {
continue
}
if string(c.Family) == "av" {
var v int64
if len(c.Value) == 4 {
v = int64(binary.BigEndian.Uint32(c.Value))
} else {
log.Error("UpArcQuery family[av] get dirty value tableName(%s)|rowkey(%s)", tableName, rowkey)
}
res = append(res, v)
}
}
log.Info("UpArcQuery mid(%d)|rowkey(%s)|res(%+v)", mid, rowkey, res)
return
}

View File

@@ -0,0 +1,88 @@
package data
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDatareverseString(t *testing.T) {
convey.Convey("reverseString", t, func(ctx convey.C) {
var (
s = ""
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := reverseString(s)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDatafansRowKey(t *testing.T) {
convey.Convey("fansRowKey", t, func(ctx convey.C) {
var (
id = int64(0)
ty = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := fansRowKey(id, ty)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDataarcQueryKey(t *testing.T) {
convey.Convey("arcQueryKey", t, func(ctx convey.C) {
var (
id = int64(0)
dt = ""
cp = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := arcQueryKey(id, dt, cp)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDataUpFansAnalysis(t *testing.T) {
convey.Convey("UpFansAnalysis", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
ty = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.UpFansAnalysis(c, mid, ty)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDataUpArcQuery(t *testing.T) {
convey.Convey("UpArcQuery", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
dt = ""
cp = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.UpArcQuery(c, mid, dt, cp)
ctx.Convey("Then err should be nil.res should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(res, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,41 @@
package data
import (
"context"
"fmt"
"time"
"go-common/library/log"
"go-common/library/database/hbase.v2"
"github.com/tsuna/gohbase/hrpc"
)
func (d *Dao) getDataWithBackup(c context.Context, client *hbase.Client, tableNameFunc func(retryCount int) string, maxRetry int, key string, options ...func(hrpc.Call) error) (result *hrpc.Result, err error) {
if client == nil {
err = fmt.Errorf("hbase client is nil")
return
}
for i := 0; i < maxRetry; i++ {
var tableName = tableNameFunc(i)
if result, err = d.hbase.GetStr(c, tableName, key, options...); err != nil {
log.Error("hbase GetStr tableName(%s)|key(%v)|error(%v)", tableName, key, err)
continue
}
break
}
return
}
func getTableName(tablePrefix string, date time.Time) string {
return tablePrefix + date.Format("20060102")
}
func generateTableNameFunc(tablePrefix string, date time.Time, dayDiff int) func(retryCount int) string {
return func(retryCount int) string {
var backdate = date.AddDate(0, 0, dayDiff*retryCount)
return getTableName(tablePrefix, backdate)
}
}

View File

@@ -0,0 +1,63 @@
package data
import (
"context"
"testing"
"time"
"go-common/library/database/hbase.v2"
"github.com/smartystreets/goconvey/convey"
"github.com/tsuna/gohbase/hrpc"
)
func TestDatagetDataWithBackup(t *testing.T) {
convey.Convey("getDataWithBackup", t, func(ctx convey.C) {
var (
c = context.Background()
client = &hbase.Client{}
tableNameFunc func(retryCount int) string
maxRetry = int(0)
key = ""
options func(hrpc.Call) error
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.getDataWithBackup(c, client, tableNameFunc, maxRetry, key, options)
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.ShouldBeNil)
})
})
})
}
func TestDatagetTableName(t *testing.T) {
convey.Convey("getTableName", t, func(ctx convey.C) {
var (
tablePrefix = ""
date = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := getTableName(tablePrefix, date)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestDatagenerateTableNameFunc(t *testing.T) {
convey.Convey("generateTableNameFunc", t, func(ctx convey.C) {
var (
tablePrefix = ""
date = time.Now()
dayDiff = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
p1 := generateTableNameFunc(tablePrefix, date, dayDiff)
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,52 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"email_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"email.go",
],
importpath = "go-common/app/admin/main/up/dao/email",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//library/log:go_default_library",
"//vendor/gopkg.in/gomail.v2: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,26 @@
package email
import (
"crypto/tls"
"go-common/app/admin/main/up/conf"
gomail "gopkg.in/gomail.v2"
)
// Dao is redis dao.
type Dao struct {
email *gomail.Dialer
}
// New is new redis dao.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
// mail
email: gomail.NewDialer(c.MailConf.Host, c.MailConf.Port, c.MailConf.Username, c.MailConf.Password),
}
d.email.TLSConfig = &tls.Config{
InsecureSkipVerify: true,
}
return
}

View File

@@ -0,0 +1,38 @@
package email
import (
"flag"
"os"
"testing"
"go-common/app/admin/main/up/conf"
)
var (
d *Dao
)
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)
}
d = New(conf.Conf)
os.Exit(m.Run())
}

View File

@@ -0,0 +1,39 @@
package email
import (
"os"
"go-common/app/admin/main/up/conf"
"go-common/library/log"
"gopkg.in/gomail.v2"
)
//SendMail send the email.
func (d *Dao) SendMail(body string, subject string, send ...string) (err error) {
msg := gomail.NewMessage()
msg.SetHeader("From", conf.Conf.MailConf.Username)
msg.SetHeader("To", send...)
msg.SetHeader("Subject", subject)
msg.SetBody("text/html", body, gomail.SetPartEncoding(gomail.Base64))
if err = d.email.DialAndSend(msg); err != nil {
log.Error("s.email.DialAndSend error(%v)", err)
return
}
return
}
//SendMailAttach send the email.
func (d *Dao) SendMailAttach(filename string, subject string, send []string) (err error) {
msg := gomail.NewMessage()
msg.SetHeader("From", conf.Conf.MailConf.Username)
msg.SetHeader("To", send...)
msg.SetHeader("Subject", subject)
msg.Attach(filename)
if err = d.email.DialAndSend(msg); err != nil {
log.Error("s.email.DialAndSend error(%v)", err)
return
}
err = os.Remove(filename)
return
}

View File

@@ -0,0 +1,39 @@
package email
import (
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestEmailSendMail(t *testing.T) {
convey.Convey("SendMail", t, func(ctx convey.C) {
var (
body = ""
subject = ""
send = ""
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.SendMail(body, subject, send)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}
func TestEmailSendMailAttach(t *testing.T) {
convey.Convey("SendMailAttach", t, func(ctx convey.C) {
var (
filename = ""
subject = ""
send = []string{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
err := d.SendMailAttach(filename, subject, send)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,45 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["dao_test.go"],
embed = [":go_default_library"],
tags = ["automanaged"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["dao.go"],
importpath = "go-common/app/admin/main/up/dao/global",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//app/service/main/account/api:go_default_library",
"//vendor/github.com/pkg/errors: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,25 @@
package global
import (
"go-common/app/admin/main/up/conf"
accgrpc "go-common/app/service/main/account/api"
"github.com/pkg/errors"
)
var (
accCli accgrpc.AccountClient
)
// GetAccClient .
func GetAccClient() accgrpc.AccountClient {
return accCli
}
//Init init global
func Init(c *conf.Config) {
var err error
if accCli, err = accgrpc.NewClient(c.GRPCClient.Account); err != nil {
panic(errors.WithMessage(err, "Failed to dial account service"))
}
}

View File

@@ -0,0 +1,57 @@
package global
import (
"flag"
"os"
"testing"
"go-common/app/admin/main/up/conf"
"github.com/smartystreets/goconvey/convey"
)
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)
}
Init(conf.Conf)
os.Exit(m.Run())
}
func TestGlobalGetAccClient(t *testing.T) {
convey.Convey("GetAccClient", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
p1 := GetAccClient()
ctx.Convey("Then p1 should not be nil.", func(ctx convey.C) {
ctx.So(p1, convey.ShouldNotBeNil)
})
})
})
}
func TestGlobalInit(t *testing.T) {
convey.Convey("Init", t, func(ctx convey.C) {
ctx.Convey("When everything gose positive", func(ctx convey.C) {
Init(conf.Conf)
ctx.Convey("No return values", func(ctx convey.C) {
})
})
})
}

View File

@@ -0,0 +1,54 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["dao_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//app/admin/main/up/model/signmodel:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["dao.go"],
importmap = "go-common/app/admin/main/up/dao/manager",
importpath = "go-common/app/admin/main/up/dao/manager",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//app/admin/main/up/model/signmodel:go_default_library",
"//app/admin/main/up/model/upcrmmodel:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/time:go_default_library",
"//library/xstr: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,173 @@
package manager
import (
"context"
"encoding/json"
"fmt"
"net/url"
"strings"
"time"
"go-common/app/admin/main/up/conf"
"go-common/app/admin/main/up/model/signmodel"
"go-common/app/admin/main/up/model/upcrmmodel"
"go-common/library/database/sql"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
xtime "go-common/library/time"
"go-common/library/xstr"
)
const (
// URLUNames url for usernames to uid
URLUNames = "/x/admin/manager/users/unames"
// URLUids url for uids to username
URLUids = "/x/admin/manager/users/uids"
// URLAuditLog url for sign up change log
URLAuditLog = "/x/admin/search/log"
)
// Dao is redis dao.
type Dao struct {
c *conf.Config
managerDB *sql.DB
HTTPClient *bm.Client
}
// New fn
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
managerDB: sql.NewMySQL(c.DB.Manager),
// http client
HTTPClient: bm.NewClient(c.HTTPClient.Normal),
}
return d
}
// Close fn
func (d *Dao) Close() {
if d.managerDB != nil {
d.managerDB.Close()
}
}
// Ping ping cpdb
func (d *Dao) Ping(c context.Context) (err error) {
return d.managerDB.Ping(c)
}
// GetUNamesByUids get name by uid
func (d *Dao) GetUNamesByUids(c context.Context, uids []int64) (res map[int64]string, err error) {
var param = url.Values{}
var uidStr = xstr.JoinInts(uids)
param.Set("uids", uidStr)
var httpRes struct {
Code int `json:"code"`
Data map[int64]string `json:"data"`
Message string `json:"message"`
}
err = d.HTTPClient.Get(c, d.c.Host.Manager+URLUNames, "", param, &httpRes)
if err != nil {
log.Error("d.client.Get(%s) error(%v)", d.c.Host.Manager+URLUNames+"?"+param.Encode(), err)
return
}
if httpRes.Code != 0 {
log.Error("url(%s) error(%v), code(%d), message(%s)", d.c.Host.Manager+URLUNames+"?"+param.Encode(), err, httpRes.Code, httpRes.Message)
}
res = httpRes.Data
return
}
// GetUIDByNames get uid by name
func (d *Dao) GetUIDByNames(c context.Context, names []string) (res map[string]int64, err error) {
var param = url.Values{}
var namesStr = strings.Join(names, ",")
param.Set("unames", namesStr)
var httpRes struct {
Code int `json:"code"`
Data map[string]int64 `json:"data"`
Message string `json:"message"`
}
err = d.HTTPClient.Get(c, d.c.Host.Manager+URLUids, "", param, &httpRes)
if err != nil {
log.Error("d.client.Get(%s) error(%v)", d.c.Host.Manager+URLUids+"?"+param.Encode(), err)
return
}
if httpRes.Code != 0 {
log.Error("url(%s) error(%v), code(%d), message(%s)", d.c.Host.Manager+URLUids+"?"+param.Encode(), err, httpRes.Code, httpRes.Message)
}
res = httpRes.Data
return
}
// SignUpAuditLogs get sign up audit log .
func (d *Dao) SignUpAuditLogs(c context.Context, arg *signmodel.SignOpSearchArg) (res *signmodel.SignAuditListReply, err error) {
params := url.Values{}
params.Set("appid", "log_audit")
params.Set("business", fmt.Sprintf("%d", signmodel.SignUpLogBizID))
params.Set("order", arg.Order)
params.Set("sort", arg.Sort)
params.Set("int_0", fmt.Sprintf("%d", arg.SignID))
params.Set("oid", fmt.Sprintf("%d", arg.Mid))
params.Set("type", fmt.Sprintf("%d", arg.Tp))
params.Set("pn", fmt.Sprintf("%d", arg.PN))
params.Set("ps", fmt.Sprintf("%d", arg.PS))
var httpRes struct {
Code int `json:"code"`
Data *signmodel.BaseAuditListReply `json:"data"`
Message string `json:"message"`
}
err = d.HTTPClient.Get(c, d.c.Host.Manager+URLAuditLog, "", params, &httpRes)
if err != nil {
log.Error("d.client.Get(%s) error(%v)", d.c.Host.Manager+URLAuditLog+"?"+params.Encode(), err)
return
}
if httpRes.Code != 0 {
log.Error("url(%s) error(%v), code(%d), message(%s)", d.c.Host.Manager+URLAuditLog+"?"+params.Encode(), err, httpRes.Code, httpRes.Message)
}
res = new(signmodel.SignAuditListReply)
res.Page = arg.PN
res.Size = arg.PS
res.Order = arg.Order
res.Sort = arg.Sort
if httpRes.Data != nil && httpRes.Data.Pager != nil {
res.TotalCount = httpRes.Data.Pager.TotalCount
}
for _, v := range httpRes.Data.Result {
ctime, _ := time.ParseInLocation(upcrmmodel.TimeFmtDateTime, v.CTime, time.Local)
var signAuit = &signmodel.SignAuditReply{
Mid: v.OID,
SignID: v.IntOne,
Tp: v.Tp,
OperID: v.UID,
OperName: v.UName,
CTime: xtime.Time(ctime.Unix()),
}
var content signmodel.SignContentReply
json.Unmarshal([]byte(v.ExtraData), &content)
signAuit.Content = &content
if signAuit.Content.New != nil {
buildSignContractURL(signAuit.Content.New)
}
if signAuit.Content.Old != nil {
buildSignContractURL(signAuit.Content.Old)
}
res.Result = append(res.Result, signAuit)
}
return
}
func buildSignContractURL(su *signmodel.SignUpArg) {
if su.ContractInfo == nil {
return
}
for _, v := range su.ContractInfo {
v.Filelink = signmodel.BuildOrcBfsURL(v.Filelink)
v.Filelink = signmodel.BuildDownloadURL(v.Filename, v.Filelink)
}
}

View File

@@ -0,0 +1,122 @@
package manager
import (
"flag"
"os"
"testing"
"context"
"github.com/smartystreets/goconvey/convey"
"go-common/app/admin/main/up/conf"
"go-common/app/admin/main/up/model/signmodel"
"gopkg.in/h2non/gock.v1"
"strings"
)
var (
d *Dao
)
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)
}
d = New(conf.Conf)
d.HTTPClient.SetTransport(gock.DefaultTransport)
os.Exit(m.Run())
}
func httpMock(method, url string) *gock.Request {
r := gock.New(url)
r.Method = strings.ToUpper(method)
return r
}
func TestGetUIDByNames(t *testing.T) {
convey.Convey("TestGetUIDByNames", t, func(ctx convey.C) {
var (
names []string
c = context.Background()
)
defer gock.OffAll()
httpMock("GET", d.c.Host.Manager+URLUids).Reply(200).BodyString(`
{
"code" : 0,
"data" : { "1" : 1 }
}
`)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.GetUIDByNames(c, names)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestGetUNamesByUids(t *testing.T) {
convey.Convey("TestGetUNamesByUids", t, func(ctx convey.C) {
var (
uids = []int64{0}
c = context.Background()
)
defer gock.OffAll()
httpMock("GET", d.c.Host.Manager+URLUNames).Reply(200).BodyString(`
{
"code" : 0,
"data" : { "1" : "adm1" }
}
`)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.GetUNamesByUids(c, uids)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestSignUpAuditLogs(t *testing.T) {
convey.Convey("SendMail", t, func(ctx convey.C) {
var (
arg = &signmodel.SignOpSearchArg{}
c = context.Background()
)
defer gock.OffAll()
httpMock("GET", d.c.Host.Manager+URLAuditLog).Reply(200).BodyString(`
{
"code" : 0,
"data" : {
"order" : "asc",
"sort" : "fe"
}
}
`)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.SignUpAuditLogs(c, arg)
ctx.Convey("Then err should be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(res, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,56 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"tag_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"tag.go",
],
importpath = "go-common/app/admin/main/up/dao/tag",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//app/interface/main/creative/model/tag:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/xstr: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,35 @@
package tag
import (
"go-common/app/admin/main/up/conf"
httpx "go-common/library/net/http/blademaster"
)
const (
_tagList = "/x/internal/tag/minfo"
_tagCheck = "/x/internal/tag/check"
_appealTag = "/videoup/archive/reason/tag"
)
// Dao define
type Dao struct {
c *conf.Config
// http
client *httpx.Client
// uri
tagList string
tagCheck string
appealTag string
}
// New init dao
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
client: httpx.NewClient(c.HTTPClient.Normal),
tagList: c.Host.API + _tagList,
tagCheck: c.Host.API + _tagCheck,
appealTag: c.Host.Videoup + _appealTag,
}
return
}

View File

@@ -0,0 +1,48 @@
package tag
import (
"flag"
"os"
"strings"
"testing"
"go-common/app/admin/main/up/conf"
"gopkg.in/h2non/gock.v1"
)
var (
d *Dao
)
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)
}
d = New(conf.Conf)
d.client.SetTransport(gock.DefaultTransport)
os.Exit(m.Run())
}
func httpMock(method, url string) *gock.Request {
r := gock.New(url)
r.Method = strings.ToUpper(method)
return r
}

View File

@@ -0,0 +1,86 @@
package tag
import (
"context"
"net/url"
"strconv"
"go-common/app/interface/main/creative/model/tag"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/xstr"
)
// TagList get tag list.
func (d *Dao) TagList(c context.Context, ids []int64) (tgs []*tag.Meta, err error) {
params := url.Values{}
params.Set("tag_id", xstr.JoinInts(ids))
var res struct {
Code int `json:"code"`
Data []*tag.Meta `json:"data"`
}
if err = d.client.Get(c, d.tagList, "", params, &res); err != nil {
log.Error("TagList url(%s) response(%+v) error(%v)", d.tagList, res, err)
err = ecode.CreativeTagErr
return
}
if res.Code != 0 {
log.Error("TagList url(%s) res(%v)", d.tagList, res)
err = ecode.CreativeTagErr
return
}
tgs = res.Data
return
}
// TagCheck tag check
func (d *Dao) TagCheck(c context.Context, mid int64, tagName string) (t *tag.Tag, err error) {
params := url.Values{}
params.Set("tag_name", tagName)
params.Set("mid", strconv.FormatInt(mid, 10))
var res struct {
Code int `json:"code"`
Data *tag.Tag `json:"data"`
}
if err = d.client.Get(c, d.tagCheck, "", params, &res); err != nil {
log.Error("TagCheck url(%s) p(%+v) response(%s) error(%v)", d.tagCheck, params.Encode(), res, err)
err = ecode.CreativeTagErr
return
}
log.Info("TagCheck url(%s) | p(%+v) |res(%v)", d.tagCheck, params.Encode(), res)
if res.Code != 0 {
log.Error("TagCheck url(%s) res(%v)", d.tagCheck, res)
err = ecode.Int(res.Code)
return
}
if res.Data != nil {
t = res.Data
}
return
}
// AppealTag appeal tag from videoup.
func (d *Dao) AppealTag(c context.Context, aid int64, ip string) (tid int64, err error) {
params := url.Values{}
params.Set("aid", strconv.FormatInt(aid, 10))
var res struct {
Code int `json:"code"`
Data *struct {
TagID int64 `json:"tag_id"`
} `json:"data"`
}
if err = d.client.Get(c, d.appealTag, ip, params, &res); err != nil {
log.Error("appeal tag error(%v)", err)
err = ecode.CreativeTagErr
return
}
if res.Code != 0 {
log.Error("appeal tag url(%s) res(%v)", d.appealTag, res)
err = ecode.Int(res.Code)
return
}
if res.Data != nil {
tid = res.Data.TagID
}
return
}

View File

@@ -0,0 +1,77 @@
package tag
import (
"context"
"testing"
"github.com/smartystreets/goconvey/convey"
"gopkg.in/h2non/gock.v1"
)
func TestTagTagList(t *testing.T) {
convey.Convey("TagList", t, func(ctx convey.C) {
var (
c = context.Background()
ids = []int64{}
)
defer gock.OffAll()
httpMock("GET", d.tagList).Reply(200).BodyString(`
{
"code":0,
"data": []
}`)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
tgs, err := d.TagList(c, ids)
ctx.Convey("Then err should be nil.tgs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(tgs, convey.ShouldNotBeNil)
})
})
})
}
func TestTagTagCheck(t *testing.T) {
convey.Convey("TagCheck", t, func(ctx convey.C) {
var (
c = context.Background()
mid = int64(0)
tagName = ""
)
defer gock.OffAll()
httpMock("GET", d.tagCheck).Reply(200).BodyString(`
{
"code":0,
"data": {"tags" : []}
}`)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
no, err := d.TagCheck(c, mid, tagName)
ctx.Convey("Then err should be nil.no should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(no, convey.ShouldNotBeNil)
})
})
})
}
func TestTagAppealTag(t *testing.T) {
convey.Convey("AppealTag", t, func(ctx convey.C) {
var (
c = context.Background()
aid = int64(0)
ip = ""
)
defer gock.OffAll()
httpMock("GET", d.appealTag).Reply(200).BodyString(`
{
"code":0,
"data": {"tags" : []}
}`)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
tid, err := d.AppealTag(c, aid, ip)
ctx.Convey("Then err should be nil.tid should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(tid, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,77 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"credit_log_test.go",
"dao_test.go",
"scoresection_test.go",
"sign_up_test.go",
"task_info_test.go",
"up_base_info_test.go",
"up_play_info_test.go",
"up_rank_test.go",
"up_scores_history_test.go",
"up_stats_history_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//app/admin/main/up/model/signmodel:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//vendor/github.com/jinzhu/gorm:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"credit_log.go",
"dao.go",
"scoresection.go",
"sign_up.go",
"task_info.go",
"up_base_info.go",
"up_play_info.go",
"up_rank.go",
"up_scores_history.go",
"up_stats_history.go",
],
importpath = "go-common/app/admin/main/up/dao/upcrm",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/up/conf:go_default_library",
"//app/admin/main/up/model/signmodel:go_default_library",
"//app/admin/main/up/model/upcrmmodel:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster: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,55 @@
package upcrm
import (
"context"
"fmt"
"net/url"
"go-common/app/admin/main/up/model/upcrmmodel"
"go-common/library/log"
)
const (
creditLogURL = "http://api.bilibili.co/x/internal/upcredit/log/get"
)
//
//type ArgGetLogHistory struct {
// Mid int64 `params:"mid;Required"`
// FromDate systime.Time `params:"from_date"`
// ToDate systime.Time `params:"to_date"`
// Limit int `params:"limit" default:"20"`
//}
//LogList it's log list
type LogList struct {
LogList []upcrmmodel.SimpleCreditLogWithContent `json:"log_list"`
}
//CreditLogHTTPResult it's log result from http server
type CreditLogHTTPResult struct {
Code int `json:"code"`
Data LogList `json:"data"`
Msg string `json:"message"`
}
//GetCreditLog get credit log from upcredit server
func (d *Dao) GetCreditLog(mid int64, limit int) (result []upcrmmodel.SimpleCreditLogWithContent, err error) {
params := url.Values{}
params.Set("mid", fmt.Sprintf("%d", mid))
//params.Set("from_date", fromDate.Time().Format("2006-01-02"))
//params.Set("to_date", toDate.Time().Format("2006-01-02"))
params.Set("limit", fmt.Sprintf("%d", limit))
var c = context.Background()
var httpResult = CreditLogHTTPResult{}
err = d.httpClient.Get(c, creditLogURL, "", params, &httpResult)
if err != nil {
log.Error("get credit log http fail, request=%s?%s, err=%+v", creditLogURL, params.Encode(), err)
return
}
log.Info("get credit log http ok, result=%+v", httpResult)
result = httpResult.Data.LogList
return
}

View File

@@ -0,0 +1,23 @@
package upcrm
import (
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestUpcrmGetCreditLog(t *testing.T) {
convey.Convey("GetCreditLog", t, func(ctx convey.C) {
var (
mid = int64(1)
limit = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.GetCreditLog(mid, limit)
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.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,51 @@
package upcrm
import (
"context"
"go-common/app/admin/main/up/conf"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"github.com/jinzhu/gorm"
)
//Dao upcrm dao
type Dao struct {
// config
conf *conf.Config
// db
crmdb *gorm.DB
httpClient *bm.Client
}
//New new dao
func New(c *conf.Config) *Dao {
var d = &Dao{
conf: c,
}
crmdb, err := gorm.Open("mysql", c.DB.Upcrm.DSN)
if crmdb == nil {
log.Error("connect to db fail, err=%v", err)
return nil
}
crmdb.SingularTable(true)
d.crmdb = crmdb
d.crmdb.LogMode(c.IsTest)
return d
}
//SetHTTPClient set http client
func (d *Dao) SetHTTPClient(client *bm.Client) {
d.httpClient = client
}
//GetDb get current gorm db
func (d *Dao) GetDb() *gorm.DB {
return d.crmdb
}
// BeginTran begin transcation.
func (d *Dao) BeginTran(c context.Context) (tx *gorm.DB) {
return d.crmdb.Begin()
}

View File

@@ -0,0 +1,43 @@
package upcrm
import (
"flag"
"os"
"testing"
"go-common/app/admin/main/up/conf"
"go-common/library/net/http/blademaster"
"gopkg.in/h2non/gock.v1"
)
var (
d *Dao
)
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)
}
d = New(conf.Conf)
d.httpClient = blademaster.NewClient(conf.Conf.HTTPClient.Normal)
d.httpClient.SetTransport(gock.DefaultTransport)
os.Exit(m.Run())
}

View File

@@ -0,0 +1,42 @@
package upcrm
import (
"time"
"go-common/app/admin/main/up/model/upcrmmodel"
"go-common/library/ecode"
)
const (
//ScoreTypeQuality 质量分
ScoreTypeQuality = 1
//ScoreTypePr 影响力
ScoreTypePr = 2
//ScoreTypeCredit 信用分
ScoreTypeCredit = 3
//ScoreSectionTableName table name
ScoreSectionTableName = "score_section_history"
)
//ScoreQueryHistory get history
func (d *Dao) ScoreQueryHistory(scoreType int, date time.Time) (result upcrmmodel.ScoreSectionHistory, err error) {
err = d.crmdb.Model(&result).
Where("score_type=? AND generate_date = ?", scoreType, date.Format("2006-01-02")).
Find(&result).Error
if err == ecode.NothingFound {
err = nil
}
return
}
//GetLastHistory get last update date
func (d *Dao) GetLastHistory(scoreType int) (lastHistoryDate time.Time, err error) {
var model upcrmmodel.ScoreSectionHistory
err = d.crmdb.Table(ScoreSectionTableName).Select("generate_date").Where("score_type=?", scoreType).Order("generate_date desc").Limit(1).Find(&model).Error
if err != nil {
return
}
lastHistoryDate = model.GenerateDate.Time()
return
}

View File

@@ -0,0 +1,39 @@
package upcrm
import (
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestUpcrmScoreQueryHistory(t *testing.T) {
convey.Convey("ScoreQueryHistory", t, func(ctx convey.C) {
var (
scoreType = int(0)
date = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.ScoreQueryHistory(scoreType, date)
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 TestUpcrmGetLastHistory(t *testing.T) {
convey.Convey("GetLastHistory", t, func(ctx convey.C) {
var (
scoreType = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
lastHistoryDate, err := d.GetLastHistory(scoreType)
ctx.Convey("Then err should be nil.lastHistoryDate should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(lastHistoryDate, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,363 @@
package upcrm
import (
"time"
"go-common/app/admin/main/up/model/signmodel"
"go-common/app/admin/main/up/model/upcrmmodel"
"go-common/library/log"
xtime "go-common/library/time"
"github.com/jinzhu/gorm"
)
const (
// PayStateUnpay not pay
PayStateUnpay = 0
// PayStatePayed payed
PayStatePayed = 1
)
// InsertSignUp insert sign up
func (d *Dao) InsertSignUp(db *gorm.DB, up *signmodel.SignUp) (affectedRow int64, err error) {
var handle = db.Save(up)
err = handle.Error
affectedRow = handle.RowsAffected
return
}
// InsertPayInfo inert pay
func (d *Dao) InsertPayInfo(db *gorm.DB, info *signmodel.SignPay) (affectedRow int64, err error) {
var handle = db.Save(info)
err = handle.Error
affectedRow = handle.RowsAffected
return
}
// InsertTaskInfo insert task
func (d *Dao) InsertTaskInfo(db *gorm.DB, info *signmodel.SignTask) (affectedRow int64, err error) {
var handle = db.Save(info)
err = handle.Error
affectedRow = handle.RowsAffected
return
}
// InsertContractInfo insert contract
func (d *Dao) InsertContractInfo(db *gorm.DB, info interface{}) (affectedRow int64, err error) {
var handle = db.Save(info)
err = handle.Error
affectedRow = handle.RowsAffected
return
}
// DelPayInfo update payinfo
func (d *Dao) DelPayInfo(db *gorm.DB, ids []int64) (affectedRow int64, err error) {
var handle = db.Model(&signmodel.SignPay{}).Where("id IN (?)", ids).Update("state", 100)
err = handle.Error
affectedRow = handle.RowsAffected
return
}
// DelTaskInfo update taskInfo
func (d *Dao) DelTaskInfo(db *gorm.DB, ids []int64) (affectedRow int64, err error) {
var handle = db.Model(&signmodel.SignTask{}).Where("id IN (?)", ids).Update("state", 100)
err = handle.Error
affectedRow = handle.RowsAffected
return
}
// DelSignContract update signcontract
func (d *Dao) DelSignContract(db *gorm.DB, ids []int64) (affectedRow int64, err error) {
var handle = db.Model(&signmodel.SignContract{}).Where("id IN (?)", ids).Update("state", 100)
err = handle.Error
affectedRow = handle.RowsAffected
return
}
// SignUpID .
func (d *Dao) SignUpID(sigID int64) (su *signmodel.SignUp, msp map[int64]*signmodel.SignPay, mst map[int64]*signmodel.SignTask, msc map[int64]*signmodel.SignContract, err error) {
su = &signmodel.SignUp{}
if err = d.crmdb.Table(signmodel.TableSignUp).Where("id = ? AND state IN (0,1)", sigID).Find(su).Error; err != nil && err != gorm.ErrRecordNotFound {
log.Error("db fail, err=%+v", err)
return
}
if err == gorm.ErrRecordNotFound {
err = nil
su, msp, mst, msc = nil, nil, nil, nil
return
}
var (
sps []*signmodel.SignPay
sts []*signmodel.SignTask
scs []*signmodel.SignContract
)
msp = make(map[int64]*signmodel.SignPay)
if err = d.crmdb.Table(signmodel.TableSignPay).Where("sign_id = ? AND state IN (0,1)", sigID).Find(&sps).Error; err != nil && err != gorm.ErrRecordNotFound {
log.Error("db fail, err=%+v", err)
return
}
for _, v := range sps {
msp[v.ID] = v
}
mst = make(map[int64]*signmodel.SignTask)
if err = d.crmdb.Table(signmodel.TableSignTask).Where("sign_id = ? AND state = 0", sigID).Find(&sts).Error; err != nil && err != gorm.ErrRecordNotFound {
log.Error("db fail, err=%+v", err)
return
}
for _, v := range sts {
mst[v.ID] = v
}
msc = make(map[int64]*signmodel.SignContract)
if err = d.crmdb.Table(signmodel.TableSignContract).Where("sign_id = ? AND state = 0", sigID).Find(&scs).Error; err != nil && err != gorm.ErrRecordNotFound {
log.Error("db fail, err=%+v", err)
return
}
for _, v := range scs {
msc[v.ID] = v
}
return
}
// GetSignIDByCondition get sign id
// arg query args
func (d *Dao) GetSignIDByCondition(arg *signmodel.SignQueryArg) (signIDs []uint32, err error) {
var signIDMap = map[uint32]struct{}{}
switch {
default:
// 如果是mid则不进行其他的查询
if arg.Mid != 0 {
var result []signmodel.SignUpOnlyID
var db = d.crmdb.Table("sign_up").Where("mid=?", arg.Mid)
err = db.Select("id").Find(&result).Error
if err != nil && err != gorm.ErrRecordNotFound {
log.Error("db fail, err=%+v", err)
return
}
for _, v := range result {
signIDMap[v.ID] = struct{}{}
}
break
}
var now = time.Now()
// 1.增加查询条件
if arg.DuePay == 1 {
var duedate = now.AddDate(0, 0, 7)
var result []signmodel.SignUpOnlySignID
// due_date and state = PayStateUnpay
err = d.crmdb.Table("sign_pay").Select("sign_id").Where("due_date <= ? and state = 0", duedate.Format(upcrmmodel.TimeFmtDate)).Where("state != 100").
Find(&result).Error
if err != nil && err != gorm.ErrRecordNotFound {
log.Error("db fail, err=%+v", err)
} else {
for _, v := range result {
signIDMap[v.SignID] = struct{}{}
}
}
}
if arg.DueSign == 1 || arg.ExpireSign == 1 {
var duedate = now.AddDate(0, 0, 30)
var result []signmodel.SignUpOnlyID
var db = d.crmdb.Table("sign_up").Select("id")
if arg.DueSign == 1 && arg.ExpireSign == 1 {
db = db.Where("end_date < ?", duedate.Format(upcrmmodel.TimeFmtDate)).Where("state != 100") // 去掉已删除的
} else {
if arg.DueSign == 1 {
db = db.Where("end_date >= ? and end_date <= ?", now.Format(upcrmmodel.TimeFmtDate), duedate.Format(upcrmmodel.TimeFmtDate))
} else if arg.ExpireSign == 1 {
db = db.Where("end_date < ?", now.Format(upcrmmodel.TimeFmtDate))
}
}
err = db.
Find(&result).Error
if err != nil && err != gorm.ErrRecordNotFound {
log.Error("db fail, err=%+v", err)
} else {
for _, v := range result {
signIDMap[v.ID] = struct{}{}
}
}
}
}
for k := range signIDMap {
signIDs = append(signIDs, k)
}
return
}
//GetSignUpByID signid 可以是nil如果是nil则会取所有的信息
// query, args, 额外的查询条件
func (d *Dao) GetSignUpByID(signID []uint32, order string, offset int, limit int, query interface{}, args ...interface{}) (result []signmodel.SignUp, err error) {
var db = d.crmdb.Table("sign_up")
if signID != nil {
db = db.Where("id in (?)", signID)
}
if query != nil {
db = db.Where(query, args)
}
if order != "" {
db = db.Order(order)
}
err = db.
Offset(offset).
Limit(limit).
Find(&result).Error
if err == gorm.ErrRecordNotFound {
err = nil
}
return
}
//GetSignUpCount get sign up's count
func (d *Dao) GetSignUpCount(query string, args ...interface{}) (count int) {
d.crmdb.Table(signmodel.TableSignUp).Where(query, args).Count(&count)
return
}
//GetTask get task by sign id and state
func (d *Dao) GetTask(signID []uint32, state ...int) (result []signmodel.SignTask, err error) {
err = d.crmdb.Table(signmodel.TableSignTask).Where("sign_id in (?) and state = ?", signID, state).Find(&result).Error
if err == gorm.ErrRecordNotFound {
err = nil
}
return
}
//GetPay get get sign id
func (d *Dao) GetPay(signID []uint32) (result []signmodel.SignPay, err error) {
err = d.crmdb.Table(signmodel.TableSignPay).Where("sign_id in (?)", signID).Find(&result).Error
if err == gorm.ErrRecordNotFound {
err = nil
}
return
}
//GetContract get get sign id
func (d *Dao) GetContract(signID []uint32) (result []signmodel.SignContract, err error) {
err = d.crmdb.Table(signmodel.TableSignContract).Where("sign_id in (?)", signID).Find(&result).Error
if err == gorm.ErrRecordNotFound {
err = nil
}
return
}
//PayComplete finish pay by pay id
func (d *Dao) PayComplete(ids []int64) (affectedRow int64, err error) {
var db = d.crmdb.Table(signmodel.TableSignPay).Where("id in (?)", ids).Updates(map[string]interface{}{"state": PayStatePayed})
err = db.Error
if err == nil {
affectedRow = db.RowsAffected
}
return
}
//SignWithName sign with name, used to send mail
type SignWithName struct {
signmodel.SignUp
Name string
}
//GetDueSignUp check due
// expireAfterDays : how many days to expire
func (d *Dao) GetDueSignUp(now time.Time, expireAfterDays int) (result []*SignWithName, err error) {
var dueDate = now.AddDate(0, 0, expireAfterDays)
var db = d.crmdb.Table(signmodel.TableSignUp).Select("id, mid, end_date, admin_id, admin_name")
// email_state = 0 是未发过邮件的意思
db = db.Where("end_date <= ? and end_date >= ? and email_state = 0", dueDate.Format(upcrmmodel.TimeFmtDate), now.Format(upcrmmodel.TimeFmtDate))
err = db.Find(&result).Error
return
}
//PayWithAdmin pay with name, used to send mail
type PayWithAdmin struct {
signmodel.SignPay
Name string
AdminID int
AdminName string
}
//GetDuePay check due
func (d *Dao) GetDuePay(now time.Time, expireAfterDays int) (result []*PayWithAdmin, err error) {
var dueDate = now.AddDate(0, 0, expireAfterDays)
err = d.crmdb.Raw("select p.id, "+
"p.sign_id, "+
"p.mid, "+
"p.due_date, "+
"p.pay_value,"+
"s.admin_id, "+
"s.admin_name"+
" from sign_pay as p left join sign_up as s on p.sign_id = s.id "+
" where p.due_date <= ? and p.email_state = 0 and p.state = 0", dueDate.Format(upcrmmodel.TimeFmtDate)).
Scan(&result).Error
return
}
//UpdateEmailState update email send state
// state : @
func (d *Dao) UpdateEmailState(table string, ids []int64, state int8) (affectedRow int64, err error) {
var db = d.crmdb.Table(table).Where("id in (?)", ids).Update("email_state", state)
err = db.Error
if err == nil {
affectedRow = db.RowsAffected
} else {
log.Error("update email state fail, err=%+v", err)
}
return
}
//CheckUpHasValidContract check if has valid contract
func (d *Dao) CheckUpHasValidContract(mid int64, date time.Time) (exist bool, err error) {
var ids []struct {
ID int
}
err = d.crmdb.Table(signmodel.TableSignUp).Select("id").Where("mid=? and end_date>=?", mid, date.Format(upcrmmodel.TimeFmtDate)).Limit(1).Find(&ids).Error
if err != nil && err != gorm.ErrRecordNotFound {
log.Error("check exist from db fail, err=%+v", err)
return
}
exist = len(ids) > 0
return
}
// GetOrCreateTaskHistory .
func (d *Dao) GetOrCreateTaskHistory(db *gorm.DB, st *signmodel.SignTask) (sth *signmodel.SignTaskHistory, init bool, err error) {
sDate, _ := signmodel.GetTaskDuration(time.Now(), st.TaskType)
sth = new(signmodel.SignTaskHistory)
err = db.Select("*").Where("task_template_id=? and generate_date=?", st.ID, sDate).Find(&sth).Error
// 创建一条,如果没找到的话
if err == gorm.ErrRecordNotFound {
sth = &signmodel.SignTaskHistory{
Mid: st.Mid,
SignID: int64(st.SignID),
TaskTemplateID: int(st.ID),
TaskType: st.TaskType,
TaskCondition: int(st.TaskCondition),
GenerateDate: xtime.Time(sDate.Unix()),
Attribute: st.Attribute,
State: signmodel.SignTaskStateRunning,
}
if err = db.Save(&sth).Error; err != nil {
log.Error("create task history fail, err=%v, task=%v", err, st)
}
init = true
}
return
}
// UpSignTaskHistory .
func (d *Dao) UpSignTaskHistory(db *gorm.DB, sth *signmodel.SignTaskHistory) (err error) {
if err = db.Table(signmodel.TableSignTaskHistory).Where("id = ?", sth.ID).UpdateColumns(
map[string]interface{}{
"task_type": sth.TaskType,
"task_condition": sth.TaskCondition,
"attribute": sth.Attribute,
"mtime": time.Now(),
}).Error; err != nil {
log.Error("dao.UpSignTaskHistory(%+v) , err=%+v", sth, err)
}
return
}

View File

@@ -0,0 +1,320 @@
package upcrm
import (
"testing"
"time"
"go-common/app/admin/main/up/model/signmodel"
"github.com/smartystreets/goconvey/convey"
)
func TestUpcrmInsertSignUp(t *testing.T) {
convey.Convey("InsertSignUp", t, func(ctx convey.C) {
var (
db = d.crmdb
up = &signmodel.SignUp{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
affectedRow, err := d.InsertSignUp(db, up)
d.crmdb.Delete(up)
ctx.Convey("Then err should be nil.affectedRow should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affectedRow, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmInsertPayInfo(t *testing.T) {
convey.Convey("InsertPayInfo", t, func(ctx convey.C) {
var (
db = d.crmdb
info = &signmodel.SignPay{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
affectedRow, err := d.InsertPayInfo(db, info)
d.crmdb.Delete(info)
ctx.Convey("Then err should be nil.affectedRow should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affectedRow, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmInsertTaskInfo(t *testing.T) {
convey.Convey("InsertTaskInfo", t, func(ctx convey.C) {
var (
db = d.crmdb
info = &signmodel.SignTask{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
affectedRow, err := d.InsertTaskInfo(db, info)
d.crmdb.Delete(info)
ctx.Convey("Then err should be nil.affectedRow should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affectedRow, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmInsertContractInfo(t *testing.T) {
convey.Convey("InsertContractInfo", t, func(ctx convey.C) {
var (
db = d.crmdb
info = &signmodel.SignContract{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
affectedRow, err := d.InsertContractInfo(db, info)
d.crmdb.Delete(info)
ctx.Convey("Then err should be nil.affectedRow should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affectedRow, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmDelPayInfo(t *testing.T) {
convey.Convey("DelPayInfo", t, func(ctx convey.C) {
var (
db = d.crmdb
ids = []int64{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
affectedRow, err := d.DelPayInfo(db, ids)
ctx.Convey("Then err should be nil.affectedRow should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affectedRow, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmDelTaskInfo(t *testing.T) {
convey.Convey("DelTaskInfo", t, func(ctx convey.C) {
var (
db = d.crmdb
ids = []int64{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
affectedRow, err := d.DelTaskInfo(db, ids)
ctx.Convey("Then err should be nil.affectedRow should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affectedRow, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmDelSignContract(t *testing.T) {
convey.Convey("DelSignContract", t, func(ctx convey.C) {
var (
db = d.crmdb
ids = []int64{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
affectedRow, err := d.DelSignContract(db, ids)
ctx.Convey("Then err should be nil.affectedRow should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affectedRow, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmSignUpID(t *testing.T) {
convey.Convey("SignUpID", t, func(ctx convey.C) {
var (
sigID = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
su, msp, mst, msc, err := d.SignUpID(sigID)
ctx.Convey("Then err should be nil.su,msp,mst,msc should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(msc, convey.ShouldBeNil)
ctx.So(mst, convey.ShouldBeNil)
ctx.So(msp, convey.ShouldBeNil)
ctx.So(su, convey.ShouldBeNil)
})
})
})
}
func TestUpcrmGetSignIDByCondition(t *testing.T) {
convey.Convey("GetSignIDByCondition", t, func(ctx convey.C) {
var (
arg = &signmodel.SignQueryArg{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
signIDs, err := d.GetSignIDByCondition(arg)
ctx.Convey("Then err should be nil.signIDs should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(signIDs, convey.ShouldBeNil)
})
})
})
}
func TestUpcrmGetSignUpByID(t *testing.T) {
convey.Convey("GetSignUpByID", t, func(ctx convey.C) {
var (
signID = []uint32{}
order = ""
offset = int(0)
limit = int(0)
query = interface{}(0)
args = interface{}(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.GetSignUpByID(signID, order, offset, limit, query, args)
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 TestUpcrmGetSignUpCount(t *testing.T) {
convey.Convey("GetSignUpCount", t, func(ctx convey.C) {
var (
query = ""
args = interface{}(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
count := d.GetSignUpCount(query, args)
ctx.Convey("Then count should not be nil.", func(ctx convey.C) {
ctx.So(count, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmGetTask(t *testing.T) {
convey.Convey("GetTask", t, func(ctx convey.C) {
var (
signID = []uint32{}
state = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.GetTask(signID, state)
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 TestUpcrmGetPay(t *testing.T) {
convey.Convey("GetPay", t, func(ctx convey.C) {
var (
signID = []uint32{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.GetPay(signID)
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 TestUpcrmGetContract(t *testing.T) {
convey.Convey("GetContract", t, func(ctx convey.C) {
var (
signID = []uint32{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.GetContract(signID)
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 TestUpcrmPayComplete(t *testing.T) {
convey.Convey("PayComplete", t, func(ctx convey.C) {
var (
ids = []int64{1, 2}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
affectedRow, err := d.PayComplete(ids)
ctx.Convey("Then err should be nil.affectedRow should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affectedRow, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmGetDueSignUp(t *testing.T) {
convey.Convey("GetDueSignUp", t, func(ctx convey.C) {
var (
now = time.Now()
expireAfterDays = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.GetDueSignUp(now, expireAfterDays)
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 TestUpcrmGetDuePay(t *testing.T) {
convey.Convey("GetDuePay", t, func(ctx convey.C) {
var (
now = time.Now()
expireAfterDays = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.GetDuePay(now, expireAfterDays)
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 TestUpcrmUpdateEmailState(t *testing.T) {
convey.Convey("UpdateEmailState", t, func(ctx convey.C) {
var (
table = "sign_up"
ids = []int64{}
state = int8(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
affectedRow, err := d.UpdateEmailState(table, ids, state)
ctx.Convey("Then err should be nil.affectedRow should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affectedRow, convey.ShouldEqual, 0)
})
})
})
}
func TestUpcrmCheckUpHasValidContract(t *testing.T) {
convey.Convey("CheckUpHasValidContract", t, func(ctx convey.C) {
var (
mid = int64(0)
date = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
exist, err := d.CheckUpHasValidContract(mid, date)
ctx.Convey("Then err should be nil.exist should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(exist, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,45 @@
package upcrm
import (
"time"
"go-common/app/admin/main/up/model/upcrmmodel"
"go-common/library/log"
xtime "go-common/library/time"
)
//StartTask start task
func (d *Dao) StartTask(taskType int, now time.Time) (affectedRow int64, err error) {
var task = &upcrmmodel.TaskInfo{}
task.TaskType = int8(taskType)
task.GenerateDate = now.Format(upcrmmodel.TimeFmtDate)
task.StartTime = xtime.Time(now.Unix())
task.TaskState = upcrmmodel.TaskStateStart
var db = d.crmdb.Model(task).Save(task)
err = db.Error
if err != nil {
log.Error("error start task info, err=%+v", err)
return
}
affectedRow = db.RowsAffected
return
}
//FinishTask finish task
func (d *Dao) FinishTask(taskType int, now time.Time, state int) (affectedRow int64, err error) {
var task = &upcrmmodel.TaskInfo{}
task.TaskType = int8(taskType)
task.GenerateDate = now.Format(upcrmmodel.TimeFmtDate)
task.EndTime = xtime.Time(now.Unix())
task.TaskState = int16(state)
var db = d.crmdb.Model(task).Where("generate_date=? and task_type=?", task.GenerateDate, taskType).Update(task)
err = db.Error
if err != nil {
log.Error("error end task info, err=%+v", err)
return
}
affectedRow = db.RowsAffected
return
}

View File

@@ -0,0 +1,42 @@
package upcrm
import (
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestUpcrmStartTask(t *testing.T) {
convey.Convey("StartTask", t, func(ctx convey.C) {
var (
taskType = int(0)
now = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
affectedRow, err := d.StartTask(taskType, now)
err = nil
ctx.Convey("Then err should be nil.affectedRow should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affectedRow, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmFinishTask(t *testing.T) {
convey.Convey("FinishTask", t, func(ctx convey.C) {
var (
taskType = int(0)
now = time.Now()
state = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
affectedRow, err := d.FinishTask(taskType, now, state)
ctx.Convey("Then err should be nil.affectedRow should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(affectedRow, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,21 @@
package upcrm
import "go-common/app/admin/main/up/model/upcrmmodel"
//QueryUpBaseInfo query db
func (d *Dao) QueryUpBaseInfo(mid int64, fields string) (result upcrmmodel.UpBaseInfo, err error) {
err = d.crmdb.Select(fields).Where("mid=?", mid).Find(&result).Error
return
}
//QueryUpBaseInfoBatchByMid query db
func (d *Dao) QueryUpBaseInfoBatchByMid(fields string, mid ...int64) (result []upcrmmodel.UpBaseInfo, err error) {
err = d.crmdb.Select(fields).Where("mid in(?)", mid).Find(&result).Error
return
}
//QueryUpBaseInfoBatchByID query db
func (d *Dao) QueryUpBaseInfoBatchByID(fields string, id ...int64) (result []upcrmmodel.UpBaseInfo, err error) {
err = d.crmdb.Select(fields).Where("id in(?)", id).Find(&result).Error
return
}

View File

@@ -0,0 +1,56 @@
package upcrm
import (
"testing"
"github.com/jinzhu/gorm"
"github.com/smartystreets/goconvey/convey"
)
func TestUpcrmQueryUpBaseInfo(t *testing.T) {
convey.Convey("QueryUpBaseInfo", t, func(ctx convey.C) {
var (
mid = int64(0)
fields = "*"
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.QueryUpBaseInfo(mid, fields)
ctx.Convey("Then err should be nil.result should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldEqual, gorm.ErrRecordNotFound)
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmQueryUpBaseInfoBatchByMid(t *testing.T) {
convey.Convey("QueryUpBaseInfoBatchByMid", t, func(ctx convey.C) {
var (
fields = "*"
mid = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.QueryUpBaseInfoBatchByMid(fields, 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 TestUpcrmQueryUpBaseInfoBatchByID(t *testing.T) {
convey.Convey("QueryUpBaseInfoBatchByID", t, func(ctx convey.C) {
var (
fields = "*"
id = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.QueryUpBaseInfoBatchByID(fields, id)
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,15 @@
package upcrm
import "go-common/app/admin/main/up/model/upcrmmodel"
//QueryPlayInfo query db
func (d *Dao) QueryPlayInfo(mid int64, busiType []int) (result []upcrmmodel.UpPlayInfo, err error) {
err = d.crmdb.Where("mid=? and business_type in (?)", mid, busiType).Find(&result).Error
return
}
// QueryPlayInfoBatch query db
func (d *Dao) QueryPlayInfoBatch(mid []int64, busiType int) (result []*upcrmmodel.UpPlayInfo, err error) {
err = d.crmdb.Where("mid in (?) and business_type = ?", mid, busiType).Find(&result).Error
return
}

View File

@@ -0,0 +1,39 @@
package upcrm
import (
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestUpcrmQueryPlayInfo(t *testing.T) {
convey.Convey("QueryPlayInfo", t, func(ctx convey.C) {
var (
mid = int64(0)
busiType = []int{}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.QueryPlayInfo(mid, busiType)
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 TestUpcrmQueryPlayInfoBatch(t *testing.T) {
convey.Convey("QueryPlayInfoBatch", t, func(ctx convey.C) {
var (
mid = []int64{}
busiType = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.QueryPlayInfoBatch(mid, busiType)
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,29 @@
package upcrm
import (
"time"
"go-common/app/admin/main/up/model/upcrmmodel"
)
//QueryUpRank query up rank
func (d *Dao) QueryUpRank(rankType int, date time.Time) (result []upcrmmodel.UpRank, err error) {
err = d.crmdb.Model(&upcrmmodel.UpRank{}).Where("type=? and generate_date=?", rankType, date.Format(upcrmmodel.TimeFmtDate)).Find(&result).Error
return
}
//QueryUpRankAll query up rank all
func (d *Dao) QueryUpRankAll(date time.Time) (result []upcrmmodel.UpRank, err error) {
err = d.crmdb.Model(&upcrmmodel.UpRank{}).Where("generate_date=?", date.Format(upcrmmodel.TimeFmtDate)).Find(&result).Error
return
}
//GetUpRankLatestDate get last generate date
func (d *Dao) GetUpRankLatestDate() (date time.Time, err error) {
var rankInfo = upcrmmodel.UpRank{}
err = d.crmdb.Model(&rankInfo).Select("generate_date").Order("generate_date desc").Limit(1).Find(&rankInfo).Error
if err == nil {
date, err = time.Parse(time.RFC3339, rankInfo.GenerateDate)
}
return
}

View File

@@ -0,0 +1,51 @@
package upcrm
import (
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestUpcrmQueryUpRank(t *testing.T) {
convey.Convey("QueryUpRank", t, func(ctx convey.C) {
var (
rankType = int(0)
date = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.QueryUpRank(rankType, date)
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 TestUpcrmQueryUpRankAll(t *testing.T) {
convey.Convey("QueryUpRankAll", t, func(ctx convey.C) {
var (
date = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.QueryUpRankAll(date)
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 TestUpcrmGetUpRankLatestDate(t *testing.T) {
convey.Convey("GetUpRankLatestDate", t, func(ctx convey.C) {
ctx.Convey("When everything goes positive", func(ctx convey.C) {
date, err := d.GetUpRankLatestDate()
ctx.Convey("Then err should be nil.date should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(date, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,32 @@
package upcrm
import (
"time"
"go-common/app/admin/main/up/model/upcrmmodel"
)
// QueryUpScoreHistory score type, 1质量分2影响分3信用分,
// 0表示所有
func (d *Dao) QueryUpScoreHistory(mid int64, scoreType []int, fromdate time.Time, todate time.Time) (result []upcrmmodel.UpScoreHistory, err error) {
err = d.crmdb.Table(upcrmmodel.GetUpScoreHistoryTableName(mid)).Where("mid=? and score_type in (?) and generate_date >= ? and generate_date <= ?", mid, scoreType, fromdate.Format(upcrmmodel.TimeFmtDate), todate.Format(upcrmmodel.TimeFmtDate)).Find(&result).Error
return
}
//GetLatestUpScoreDate 获取某个分数的最新记录日期如果出错就返回todate
func (d *Dao) GetLatestUpScoreDate(mid int64, scoreType int, todate time.Time) (date time.Time, err error) {
date = todate
var history upcrmmodel.UpScoreHistory
err = d.crmdb.Table(upcrmmodel.GetUpScoreHistoryTableName(mid)).
Select("generate_date").
Where("mid=? and score_type = ? and generate_date <= ?", mid, scoreType, todate).
Order("generate_date desc").
Limit(1).
Find(&history).
Error
if err != nil {
return
}
date = history.GenerateDate.Time()
return
}

View File

@@ -0,0 +1,44 @@
package upcrm
import (
"testing"
"time"
"github.com/jinzhu/gorm"
"github.com/smartystreets/goconvey/convey"
)
func TestUpcrmQueryUpScoreHistory(t *testing.T) {
convey.Convey("QueryUpScoreHistory", t, func(ctx convey.C) {
var (
mid = int64(0)
scoreType = []int{}
fromdate = time.Now()
todate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result, err := d.QueryUpScoreHistory(mid, scoreType, fromdate, todate)
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 TestUpcrmGetLatestUpScoreDate(t *testing.T) {
convey.Convey("GetLatestUpScoreDate", t, func(ctx convey.C) {
var (
mid = int64(0)
scoreType = int(0)
todate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
date, err := d.GetLatestUpScoreDate(mid, scoreType, todate)
ctx.Convey("Then err should be nil.date should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldEqual, gorm.ErrRecordNotFound)
ctx.So(date, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,71 @@
package upcrm
import (
"time"
"go-common/app/admin/main/up/model/upcrmmodel"
"go-common/library/log"
"github.com/jinzhu/gorm"
)
const (
upstatshistory = "up_stats_history"
//ISO8601DATE only date format
ISO8601DATE = "2006-01-02"
)
//GetUpStatLastDate get last update date from db
func (d *Dao) GetUpStatLastDate(date time.Time) (lastday time.Time, err error) {
var lasthistory upcrmmodel.UpStatsHistory
err = d.crmdb.Table(upstatshistory).Select("generate_date").Order("generate_date desc").Limit(1).Find(&lasthistory).Error
if err != nil {
log.Error("get last date fail for up stat history, err=%+v", err)
return
}
lastday = lasthistory.GenerateDate.Time()
return
}
//QueryYesterday query yesterday db
func (d *Dao) QueryYesterday(date time.Time) (res []*upcrmmodel.UpStatsHistory, err error) {
err = d.crmdb.Table(upstatshistory).Where("generate_date = ? AND type in ( ?, ?, ? )", date.Format(ISO8601DATE), upcrmmodel.ActivityType, upcrmmodel.IncrType, upcrmmodel.TotalType).Find(&res).Error
if err == gorm.ErrRecordNotFound {
err = nil
return
}
if err != nil {
return nil, err
}
return
}
//QueryTrend query db
func (d *Dao) QueryTrend(statType int, currentDate time.Time, days int) (res []*upcrmmodel.UpStatsHistory, err error) {
// 这种type有3种子类型需要加起来
if statType == upcrmmodel.ActivityType {
days *= 3
}
err = d.crmdb.Table(upstatshistory).Where("type = ? AND generate_date <=?", statType, currentDate.Format(ISO8601DATE)).Order("generate_date desc").Limit(days).Find(&res).Error
if err == gorm.ErrRecordNotFound {
err = nil
return
}
if err != nil {
return nil, err
}
return
}
//QueryDetail query db
func (d *Dao) QueryDetail(startDate time.Time, endDate time.Time) (res []*upcrmmodel.UpStatsHistory, err error) {
err = d.crmdb.Table(upstatshistory).Where("generate_date BETWEEN ? AND ?", startDate.Format(ISO8601DATE), endDate.Format(ISO8601DATE)).Order("generate_date Desc").Find(&res).Error
if err == gorm.ErrRecordNotFound {
err = nil
return
}
if err != nil {
return nil, err
}
return
}

View File

@@ -0,0 +1,71 @@
package upcrm
import (
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestUpcrmGetUpStatLastDate(t *testing.T) {
convey.Convey("GetUpStatLastDate", t, func(ctx convey.C) {
var (
date = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
lastday, err := d.GetUpStatLastDate(date)
ctx.Convey("Then err should be nil.lastday should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldBeNil)
ctx.So(lastday, convey.ShouldNotBeNil)
})
})
})
}
func TestUpcrmQueryYesterday(t *testing.T) {
convey.Convey("QueryYesterday", t, func(ctx convey.C) {
var (
date = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.QueryYesterday(date)
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 TestUpcrmQueryTrend(t *testing.T) {
convey.Convey("QueryTrend", t, func(ctx convey.C) {
var (
statType = int(0)
currentDate = time.Now()
days = int(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.QueryTrend(statType, currentDate, days)
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 TestUpcrmQueryDetail(t *testing.T) {
convey.Convey("QueryDetail", t, func(ctx convey.C) {
var (
startDate = time.Now()
endDate = time.Now()
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
res, err := d.QueryDetail(startDate, endDate)
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)
})
})
})
}

View File

@@ -0,0 +1,84 @@
package dao
import (
"context"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"errors"
"fmt"
"hash"
"io"
"net/http"
"strconv"
"go-common/app/admin/main/up/conf"
"go-common/library/log"
)
const (
uploadurl = "/%s/%s"
template = "%s\n%s\n%s\n%d\n"
method = "PUT"
)
var (
errUpload = errors.New("Upload failed")
)
// Upload upload picture or log file to bfs
func Upload(c context.Context, fileName, fileType string, expire int64, body io.Reader, bfsConf *conf.Bfs) (location string, err error) {
var (
url string
req *http.Request
resp *http.Response
header http.Header
code string
)
url = fmt.Sprintf(bfsConf.Addr+uploadurl, bfsConf.Bucket, fileName)
if req, err = http.NewRequest(method, url, body); err != nil {
log.Error("http.NewRequest() Upload(%v) error(%v)", url, err)
return
}
log.Info("upload url={%s}", url)
authorization := Authorize(bfsConf.Key, bfsConf.Secret, method, bfsConf.Bucket, fileName, expire)
req.Header.Set("Host", bfsConf.Addr)
req.Header.Add("Date", fmt.Sprint(expire))
req.Header.Add("Authorization", authorization)
req.Header.Add("Content-Type", fileType)
resp, err = http.DefaultClient.Do(req)
if err != nil {
log.Error("httpClient.Do(%s) error(%v)", url, err)
return
}
if resp.StatusCode != http.StatusOK {
log.Error("Upload url(%s) http.statuscode:%d", url, resp.StatusCode)
err = errUpload
return
}
header = resp.Header
code = header.Get("Code")
if code != strconv.Itoa(http.StatusOK) {
log.Error("Upload url(%s) code:%s", url, code)
err = errUpload
return
}
location = header.Get("Location")
return
}
// Authorize authorize returns authorization for upload file to bfs
func Authorize(key, secret, method, bucket, file string, expire int64) (authorization string) {
var (
content string
mac hash.Hash
signature string
)
content = fmt.Sprintf(template, method, bucket, file, expire)
mac = hmac.New(sha1.New, []byte(secret))
mac.Write([]byte(content))
signature = base64.StdEncoding.EncodeToString(mac.Sum(nil))
authorization = fmt.Sprintf("%s:%s:%d", key, signature, expire)
return
}

View File

@@ -0,0 +1,78 @@
package dao
import (
"context"
"flag"
"io"
"os"
"testing"
"go-common/app/admin/main/up/conf"
"github.com/smartystreets/goconvey/convey"
)
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 TestDaoUpload(t *testing.T) {
convey.Convey("Upload", t, func(ctx convey.C) {
var (
c = context.Background()
fileName = ""
fileType = ""
expire = int64(0)
body io.Reader
bfsConf = &conf.Bfs{}
)
//defer gock.OffAll()
//httpMock("PUT", bfsConf.Addr+uploadurl).Reply(200)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
location, err := Upload(c, fileName, fileType, expire, body, bfsConf)
ctx.Convey("Then err should be nil.location should not be nil.", func(ctx convey.C) {
ctx.So(err, convey.ShouldNotBeNil)
ctx.So(location, convey.ShouldEqual, "")
})
})
})
}
func TestDaoAuthorize(t *testing.T) {
convey.Convey("Authorize", t, func(ctx convey.C) {
var (
key = ""
secret = ""
method = ""
bucket = ""
file = ""
expire = int64(0)
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
authorization := Authorize(key, secret, method, bucket, file, expire)
ctx.Convey("Then authorization should not be nil.", func(ctx convey.C) {
ctx.So(authorization, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,73 @@
package dao
import "fmt"
const (
//logicNoOp = 0
logicOpAnd = 1
logicOpOr = 2
)
//Condition 生成的condition为
// [before] [key] [operator] ? [after]
// 如
// [(] [id] [=] ? [and]
// [ctime] [>] ? [)]
// [order by] [time] nil [] //如果value是nil不会设置placeholder ?
type Condition struct {
logicOp int
Before string
Key string
Operator string
Value interface{}
After string
}
//ConcatCondition concat conditions
func ConcatCondition(conditions ...Condition) (conditionStr string, args []interface{}, hasOperator bool) {
hasOperator = false
for _, c := range conditions {
var questionMark = "?"
if c.Value == nil {
questionMark = ""
}
if c.Operator != "" {
hasOperator = true
}
var logicOp = ""
switch c.logicOp {
case logicOpAnd:
logicOp = " and "
case logicOpOr:
logicOp = " or "
}
conditionStr += fmt.Sprintf(" %s %s %s %s %s %s", logicOp, c.Before, c.Key, c.Operator, questionMark, c.After)
if c.Value != nil {
args = append(args, c.Value)
}
}
return
}
//AndCondition and condition
func AndCondition(conditions ...Condition) (result []Condition) {
return addLogicOperator(logicOpAnd, conditions...)
}
//OrCondition or condition
func OrCondition(conditions ...Condition) (result []Condition) {
return addLogicOperator(logicOpOr, conditions...)
}
func addLogicOperator(operator int, conditions ...Condition) (result []Condition) {
var isFirst = true
for _, v := range conditions {
if isFirst {
isFirst = false
} else {
v.logicOp = operator
}
result = append(result, v)
}
return
}

View File

@@ -0,0 +1,66 @@
package dao
import (
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoConcatCondition(t *testing.T) {
convey.Convey("ConcatCondition", t, func(ctx convey.C) {
var (
conditions Condition = Condition{Key: "id", Operator: "=", Value: 1}
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
conditionStr, args, hasOperator := ConcatCondition(conditions)
ctx.Convey("Then conditionStr,args,hasOperator should not be nil.", func(ctx convey.C) {
ctx.So(hasOperator, convey.ShouldNotBeNil)
ctx.So(args, convey.ShouldNotBeNil)
ctx.So(conditionStr, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoAndCondition(t *testing.T) {
convey.Convey("AndCondition", t, func(ctx convey.C) {
var (
conditions Condition
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result := AndCondition(conditions)
ctx.Convey("Then result should not be nil.", func(ctx convey.C) {
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoOrCondition(t *testing.T) {
convey.Convey("OrCondition", t, func(ctx convey.C) {
var (
conditions Condition
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result := OrCondition(conditions)
ctx.Convey("Then result should not be nil.", func(ctx convey.C) {
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoaddLogicOperator(t *testing.T) {
convey.Convey("addLogicOperator", t, func(ctx convey.C) {
var (
operator = int(0)
conditions Condition
)
ctx.Convey("When everything goes positive", func(ctx convey.C) {
result := addLogicOperator(operator, conditions)
ctx.Convey("Then result should not be nil.", func(ctx convey.C) {
ctx.So(result, convey.ShouldNotBeNil)
})
})
})
}