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,71 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"invite_test.go",
"medal_test.go",
"pendant_test.go",
"service_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/usersuit/conf:go_default_library",
"//app/admin/main/usersuit/model:go_default_library",
"//library/ecode:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"invite.go",
"medal.go",
"notify.go",
"pendant.go",
"service.go",
"upload.go",
],
importpath = "go-common/app/admin/main/usersuit/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/usersuit/conf:go_default_library",
"//app/admin/main/usersuit/dao:go_default_library",
"//app/admin/main/usersuit/model:go_default_library",
"//app/service/main/account/api:go_default_library",
"//app/service/main/account/model:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/metadata:go_default_library",
"//library/queue/databus:go_default_library",
"//library/sync/errgroup:go_default_library",
"//library/time:go_default_library",
"//library/xstr: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,209 @@
package service
import (
"context"
"crypto/md5"
"encoding/hex"
"fmt"
"math/rand"
"net"
"sort"
"sync"
"time"
"go-common/app/admin/main/usersuit/model"
accmdl "go-common/app/service/main/account/api"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/net/metadata"
xtime "go-common/library/time"
"go-common/library/sync/errgroup"
)
const (
_geneMaxLimit = int64(1000)
_geneSubCount = 200
_batch = 50
_fetchInfoTimeout = time.Second * 5
)
var (
_emptyRichInvites = make([]*model.RichInvite, 0)
_emptyInfoMap = make(map[int64]*accmdl.Info)
)
// Generate generate invite codes in batch.
func (s *Service) Generate(c context.Context, mid, num, expireDay int64) (res []*model.RichInvite, err error) {
if num > _geneMaxLimit {
err = ecode.UsersuitInviteReachMaxGeneLimit
return
}
expireSeconds := expireDay * 86400
nowTs := time.Now().Unix()
cm, err1 := concurrentGenerateCode(mid, nowTs, int(num), _geneSubCount)
if err1 != nil {
log.Error("concurrentGenerateCode(%d, %d, %d, %d) error(%v)", mid, nowTs, num, _geneSubCount, err)
}
ginvs := make([]*model.Invite, 0, num)
buyIP := net.ParseIP(metadata.String(c, metadata.RemoteIP))
for code := range cm {
ginvs = append(ginvs, &model.Invite{
Mid: mid,
Code: code,
IP: IPv4toN(buyIP),
IPng: buyIP,
Expires: nowTs + expireSeconds,
Ctime: xtime.Time(nowTs),
})
}
invs := make([]*model.Invite, 0)
var rc int64
for _, inv := range ginvs {
if rc, err = s.d.AddIgnoreInvite(c, inv); err != nil {
err = nil
break
}
if rc == 0 {
log.Error("service.dao.AddIgnoreInvite(%s), duplicate entry for invite_code %s", inv.Code, inv.Code)
continue
}
invs = append(invs, inv)
}
res = s.fillStatusAndInviteeInfo(c, invs)
return
}
func concurrentGenerateCode(mid, ts int64, num, subCount int) (res map[string]int, err error) {
batches := num / subCount
eg, _ := errgroup.WithContext(context.TODO())
ims := make([]map[string]int, batches)
mu := sync.Mutex{}
for i := 0; i < batches; i++ {
idx := i
eg.Go(func() error {
im := make(map[string]int)
for len(im) < subCount {
im[geneInviteCode(mid, ts)] = 1
}
mu.Lock()
ims[idx] = im
mu.Unlock()
return nil
})
}
err = eg.Wait()
m := make(map[string]int)
for _, im := range ims {
for code := range im {
m[code] = 1
}
}
for len(m) < num {
m[geneInviteCode(mid, ts)] = 1
}
res = m
return
}
func geneInviteCode(mid int64, ts int64) string {
data := md5.Sum([]byte(fmt.Sprintf("%d,%d,%d", ts, mid, rand.Int63())))
h := hex.EncodeToString(data[:])
return h[8:24]
}
// List list one's invite codes range time start and end.
func (s *Service) List(c context.Context, mid, start, end int64) (res []*model.RichInvite, err error) {
if start > end {
res = _emptyRichInvites
return
}
var invs []*model.Invite
if invs, err = s.d.RangeInvites(c, mid, time.Unix(start, 0), time.Unix(end, 0)); err != nil {
return
}
sort.Slice(invs, func(i, j int) bool {
return int64(invs[i].Ctime) > int64(invs[j].Ctime)
})
res = s.fillStatusAndInviteeInfo(c, invs)
return
}
func (s *Service) fillStatusAndInviteeInfo(c context.Context, invs []*model.Invite) []*model.RichInvite {
if len(invs) == 0 {
return _emptyRichInvites
}
imidm := make(map[int64]struct{})
now := time.Now().Unix()
for _, inv := range invs {
inv.FillStatus(now)
if inv.Status == model.StatusUsed {
imidm[inv.Imid] = struct{}{}
}
}
infom := _emptyInfoMap
if len(imidm) > 0 {
imids := make([]int64, 0, len(imidm))
for imid := range imidm {
imids = append(imids, imid)
}
var err1 error
if infom, err1 = s.fetchInfos(c, imids, _fetchInfoTimeout); err1 != nil {
log.Error("service.fetchInfos(%v, %s) error(%v)", imids, _fetchInfoTimeout, err1)
}
}
rinvs := make([]*model.RichInvite, 0)
for _, inv := range invs {
rinvs = append(rinvs, model.NewRichInvite(inv, infom[inv.Imid]))
}
return rinvs
}
func (s *Service) fetchInfos(c context.Context, mids []int64, timeout time.Duration) (res map[int64]*accmdl.Info, err error) {
if len(mids) == 0 {
res = _emptyInfoMap
return
}
batches := len(mids)/_batch + 1
tc, cancel := context.WithTimeout(c, timeout)
defer cancel()
eg, errCtx := errgroup.WithContext(tc)
bms := make([]map[int64]*accmdl.Info, batches)
mu := sync.Mutex{}
for i := 0; i < batches; i++ {
idx := i
end := (idx + 1) * _batch
if idx == batches-1 {
end = len(mids)
}
ids := mids[idx*_batch : end]
eg.Go(func() error {
m, err1 := s.accountClient.Infos3(errCtx, &accmdl.MidsReq{Mids: ids})
mu.Lock()
bms[idx] = m.Infos
mu.Unlock()
return err1
})
}
err = eg.Wait()
res = make(map[int64]*accmdl.Info)
for _, bm := range bms {
for mid, info := range bm {
res[mid] = info
}
}
return
}
// IPv4toN is
func IPv4toN(ip net.IP) (sum uint32) {
v4 := ip.To4()
if v4 == nil {
return
}
sum += uint32(v4[0]) << 24
sum += uint32(v4[1]) << 16
sum += uint32(v4[2]) << 8
sum += uint32(v4[3])
return sum
}

View File

@@ -0,0 +1,60 @@
package service
import (
"context"
"testing"
"time"
"go-common/library/ecode"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_Generate(t *testing.T) {
Convey("Generate 10 codes in batch", t, func() {
mid := int64(88888970)
num := int64(10)
expireDay := int64(30)
res, err := s.Generate(context.Background(), mid, num, expireDay)
So(err, ShouldBeNil)
So(len(res), ShouldEqual, num)
})
}
func TestService_List(t *testing.T) {
Convey("List when account's invite codes is not empty", t, func() {
mid := int64(88888970)
now := time.Now().Unix()
start, end := now-86400, now+86400
res, err := s.List(context.Background(), mid, start, end)
So(err, ShouldBeNil)
So(len(res), ShouldBeGreaterThan, 0)
})
}
func TestService_ConcurrentGeneInviteCode(t *testing.T) {
Convey("Generate 1000 codes in concurrency", t, func() {
num := 1000
mid := int64(88888970)
ts := time.Now().Unix()
m, err := concurrentGenerateCode(mid, ts, num, _geneSubCount)
So(err, ShouldBeNil)
So(len(m), ShouldEqual, num)
})
}
func TestService_FetchMultiInfo(t *testing.T) {
time.Sleep(time.Second * 2)
Convey("Fetch multi info", t, func() {
mids := []int64{88888970}
Convey("when not timeout", func() {
res, err := s.fetchInfos(context.Background(), mids, time.Second)
So(err, ShouldBeNil)
So(len(res), ShouldEqual, len(mids))
})
Convey("when timeout", func() {
_, err := s.fetchInfos(context.Background(), mids, time.Millisecond)
So(err, ShouldEqual, ecode.Deadline.Error())
})
})
}

View File

@@ -0,0 +1,328 @@
package service
import (
"context"
"encoding/csv"
"fmt"
"io"
"mime/multipart"
"net/url"
"strconv"
"strings"
"github.com/pkg/errors"
"go-common/app/admin/main/usersuit/model"
accmdl "go-common/app/service/main/account/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/xstr"
)
// Medal medal .
func (s *Service) Medal(c context.Context) (res []*model.MedalInfo, err error) {
nps, err := s.d.Medal(c)
if err != nil {
log.Error("s.d.Medal error(%v)", err)
}
mgs, err := s.d.MedalGroup(c)
if err != nil {
log.Error("s.d.MedalGroup error(%v)", err)
}
res = make([]*model.MedalInfo, 0)
for _, np := range nps {
re := &model.MedalInfo{}
re.Medal = np
if _, ok := mgs[np.GID]; ok {
re.GroupName = mgs[np.GID].Name
if mgs[np.GID].PID != 0 {
re.ParentGroupName = mgs[mgs[np.GID].PID].Name
}
}
res = append(res, re)
}
return
}
// MedalView .
func (s *Service) MedalView(c context.Context, id int64) (res *model.MedalInfo, err error) {
res = &model.MedalInfo{}
res.Medal, err = s.d.MedalByID(c, id)
if err != nil {
log.Error("s.d.MedalByID(%d) error(%v)", id, err)
return
}
mgs, err := s.d.MedalGroup(c)
if err != nil {
log.Error("s.d.MedalGroup error(%v)", err)
return
}
if _, ok := mgs[res.Medal.GID]; ok {
res.GroupName = mgs[res.Medal.GID].Name
if _, ok1 := mgs[mgs[res.Medal.GID].PID]; ok && ok1 {
res.ParentGroupName = mgs[mgs[res.Medal.GID].PID].Name
}
}
return
}
func getImagePath(raw string) string {
uri, err := url.Parse(raw)
if err != nil {
return raw
}
return uri.Path
}
// AddMedal add medal .
func (s *Service) AddMedal(c context.Context, np *model.Medal) (err error) {
np.Image = getImagePath(np.Image)
np.ImageSmall = getImagePath(np.ImageSmall)
if _, err := s.d.AddMedal(c, np); err != nil {
log.Error("s.d.AddMedal error(%v)", err)
}
return
}
// UpMedal update medal .
func (s *Service) UpMedal(c context.Context, id int64, np *model.Medal) (err error) {
np.Image = getImagePath(np.Image)
np.ImageSmall = getImagePath(np.ImageSmall)
if _, err := s.d.UpMedal(c, id, np); err != nil {
log.Error("s.d.UpMedal error(%v)", err)
}
return
}
// MedalGroup medal group .
func (s *Service) MedalGroup(c context.Context) (res map[int64]*model.MedalGroup, err error) {
res, err = s.d.MedalGroup(c)
if err != nil {
log.Error("s.MedalGroup error(%v)", err)
}
return
}
// MedalGroupInfo medal group all info include parent group name .
func (s *Service) MedalGroupInfo(c context.Context) (res []*model.MedalGroup, err error) {
res, err = s.d.MedalGroupInfo(c)
if err != nil {
log.Error("s.MedalGroupInfo error(%v)", err)
}
return
}
// MedalGroupParent medal group all info include parent group name .
func (s *Service) MedalGroupParent(c context.Context) (res []*model.MedalGroup, err error) {
res, err = s.d.MedalGroupParent(c)
if err != nil {
log.Error("s.MedalGroupParent error(%v)", err)
}
return
}
// MedalGroupByGid nameplate by gid .
func (s *Service) MedalGroupByGid(c context.Context, id int64) (ng *model.MedalGroup, err error) {
if ng, err = s.d.MedalGroupByID(c, id); err != nil {
log.Error("s.MedalGroupByID error(%v)", err)
}
return
}
// MedalGroupAdd add medal group.
func (s *Service) MedalGroupAdd(c context.Context, ng *model.MedalGroup) (err error) {
if _, err := s.d.MedalGroupAdd(c, ng); err != nil {
log.Error("s.MedalGroupAdd error(%v)", err)
}
return
}
// MedalGroupUp update medal group.
func (s *Service) MedalGroupUp(c context.Context, id int64, ng *model.MedalGroup) (err error) {
if _, err := s.d.MedalGroupUp(c, id, ng); err != nil {
log.Error("s.MedalGroupUp error(%v)", err)
}
return
}
// MedalOwner medal onwer .
func (s *Service) MedalOwner(c context.Context, mid int64) (no []*model.MedalMemberMID, err error) {
if no, err = s.d.MedalOwner(c, mid); err != nil {
log.Error("s.d.MedalOwner error(%+v)", err)
}
return
}
// MedalOwnerAdd medal owner add .
func (s *Service) MedalOwnerAdd(c context.Context, mid, nid int64, title, msg string, oid int64) (err error) {
count, err := s.d.CountOwnerBYNidMid(c, mid, nid)
if count > 0 || err != nil {
err = ecode.MedalHasGet
return
}
if _, err = s.d.MedalOwnerAdd(c, mid, nid); err != nil {
log.Error("s.MedalOwnerAdd(mid:%d nid:%d) error(%v)", mid, nid, err)
return
}
if err = s.d.DelMedalOwnersCache(c, mid); err != nil {
log.Error("s.DelMedalOwnersCache(mid:%d) error(%v)", mid, err)
err = nil
}
var (
mids []int64
ismsg bool
action string
)
mids = append(mids, mid)
log.Error("MedalOwnerAdd title(%+v) msg(%+v)", title, msg)
if title != "" && msg != "" {
ismsg = true
if err = s.d.SendSysMsg(c, mids, title, msg, ""); err != nil {
log.Error("MedalOwnerAdd(mid:%d nid:%d title:%s msg:%s) SendSysMsg error(%+v)", mid, nid, title, msg, err)
err = nil
}
}
if oid > 0 {
mi, err := s.d.MedalByID(c, nid)
if err != nil {
log.Error("MedalByID(id:%d) error(%+v)", nid, err)
err = nil
}
action = fmt.Sprintf("激活勋章:%s,", mi.Name)
log.Error("MedalOwnerAdd ismsg(id:%d %+v) error(%+v)", nid, ismsg, err)
if ismsg {
action += fmt.Sprintf("并发送消息title:%s msg:%s", title, msg)
} else {
action += fmt.Sprintf("并没有发送消息")
}
s.d.AddMedalOperLog(c, oid, mid, nid, action)
}
return
}
// MedalOwnerAddList .
func (s *Service) MedalOwnerAddList(c context.Context, mid int64) (res []*model.MedalMemberAddList, err error) {
if res, err = s.d.MedalAddList(c, mid); err != nil {
log.Error("s.d.MedalOwnerAddList(%d) error(%v)", mid, err)
}
return
}
// MedalOwnerUpActivated update medal owner is_activated.
func (s *Service) MedalOwnerUpActivated(c context.Context, mid, nid int64) (err error) {
if _, err = s.d.MedalOwnerUpActivated(c, mid, nid); err != nil {
log.Error("s.d.UpMedalOwnerActivated(mid:%d nid:%d) error(%v)", mid, nid, err)
}
if _, err = s.d.MedalOwnerUpNotActivated(c, mid, nid); err != nil {
log.Error("s.d.UpMedalOwnerNotActivated(mid:%d nid:%d) error(%v)", mid, nid, err)
}
if err = s.d.SetMedalActivatedCache(c, mid, nid); err != nil {
log.Error("s.d.DelMedalActivatedCache(mid:%d nid:%d) error(%v)", mid, nid, err)
err = nil
}
s.addAsyn(func() {
if err = s.accNotify(context.Background(), mid, model.AccountNotifyUpdateMedal); err != nil {
log.Error("s.accNotify(%d) error(%+v)", mid, err)
return
}
})
return
}
// MedalOwnerDel update medal owner is_del .
func (s *Service) MedalOwnerDel(c context.Context, mid, nid int64, isDel int8, title, msg string) (err error) {
if _, err = s.d.MedalOwnerDel(c, mid, nid, isDel); err != nil {
log.Error("s.d.MedalOwnerDel error(%v)", err)
}
if err = s.d.DelMedalOwnersCache(c, mid); err != nil {
log.Error("s.d.DelMedalOwnersCache(%d) error(%v)", mid, err)
err = nil
}
var mids []int64
mids = append(mids, mid)
if title != "" && msg != "" {
if err = s.d.SendSysMsg(c, mids, title, msg, ""); err != nil {
log.Error("MedalOwnerDel(mid:%d nid:%d title:%s msg:%s) SendSysMsg error(%+v)", mid, nid, title, msg, err)
err = nil
}
}
return
}
// ReadCsv read csv file
func (s *Service) ReadCsv(f multipart.File, h *multipart.FileHeader) (rs [][]string, err error) {
r := csv.NewReader(f)
for {
record, err := r.Read()
if err == io.EOF {
break
}
if err != nil {
fmt.Println(err)
log.Error("upload question ReadCsv error(%v)", err)
}
if len(record) == 1 {
rs = append(rs, record)
}
}
return
}
// BatchAdd medal bacth add.
func (s *Service) BatchAdd(c context.Context, nid int64, f multipart.File, h *multipart.FileHeader) (msg string, err error) {
if h != nil && !strings.HasSuffix(h.Filename, ".csv") {
msg = "not csv file."
return
}
rs, err := s.ReadCsv(f, h)
if len(rs) == 0 || len(rs) > model.MaxCount {
msg = "file size count is 0 or more than " + strconv.FormatInt(model.MaxCount, 10)
return
}
for _, r := range rs {
mid, err := strconv.ParseInt(r[0], 10, 64)
if err == nil {
if err = s.MedalOwnerAdd(c, mid, nid, "", "", 0); err != nil {
log.Error("s.d.MedalOwnerAdd(mid:%d nid:%d) error(%v)", mid, nid, err)
}
}
}
return
}
// MedalOperlog medal operactlog .
func (s *Service) MedalOperlog(c context.Context, mid int64, pn, ps int) (opers []*model.MedalOperLog, pager *model.Pager, err error) {
var total int64
pager = &model.Pager{
PN: pn,
PS: ps,
}
if total, err = s.d.MedalOperationLogTotal(c, mid); err != nil {
err = errors.Wrap(err, "s.d.MedalOperationLogTotal()")
return
}
if total <= 0 {
return
}
pager.Total = total
var uids []int64
if opers, uids, err = s.d.MedalOperLog(c, mid, pn, ps); err != nil {
err = errors.Wrapf(err, "s.d.MedalOperLog(%d,%d,%d)", mid, pn, ps)
return
}
var accInfoMap map[int64]*accmdl.Info
if accInfoMap, err = s.fetchInfos(c, uids, _fetchInfoTimeout); err != nil {
log.Error("service.fetchInfos(%v, %v) error(%v)", xstr.JoinInts(uids), _fetchInfoTimeout, err)
err = nil
}
for _, v := range opers {
if accInfo, ok := accInfoMap[v.MID]; ok {
v.Action = fmt.Sprintf("给用户(%s) %s", accInfo.Name, v.Action)
}
if operName, ok := s.Managers[v.OID]; ok {
v.OperName = operName
}
}
return
}

View File

@@ -0,0 +1,187 @@
package service
import (
"context"
"fmt"
"go-common/app/admin/main/usersuit/model"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_Medal(t *testing.T) {
Convey("return sth", t, func() {
res, err := s.Medal(context.Background())
for k, re := range res {
fmt.Printf("%d %+v \n", k, re)
}
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func TestService_MedalView(t *testing.T) {
Convey("return sth", t, func() {
res, err := s.MedalView(context.Background(), 3)
fmt.Printf("%+v \n", res)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func TestService_AddMedal(t *testing.T) {
Convey("return sth", t, func() {
np := &model.Medal{
Name: "出道偶像",
Description: "播放五十万,准备发新单",
Condition: "所有自制视频总播放数>=50万",
GID: 4,
Level: int8(2),
Sort: 2,
LevelRank: "50万",
IsOnline: 1,
Image: "/bfs/face/3f2d64f048b39fb6c26f3db39df47e6080ec0f9c.png",
ImageSmall: "/bfs/face/90c35d41d8a19b19474d6bac672394c17b444ce8.png",
}
err := s.AddMedal(context.Background(), np)
fmt.Printf("%+v \n", err)
So(err, ShouldBeNil)
})
}
func TestService_UpMedal(t *testing.T) {
Convey("return sth", t, func() {
np := &model.Medal{
Name: "出道偶像111",
Description: "播放五十万,准备发新单",
Condition: "所有自制视频总播放数>=50万",
GID: 4,
Level: int8(2),
Sort: 2,
LevelRank: "50万",
IsOnline: 1,
Image: "/bfs/face/3f2d64f048b39fb6c26f3db39df47e6080ec0f9c.png",
ImageSmall: "/bfs/face/90c35d41d8a19b19474d6bac672394c17b444ce8.png",
}
err := s.UpMedal(context.Background(), 1, np)
fmt.Printf("%+v \n", err)
So(err, ShouldBeNil)
})
}
func TestService_MedalGroup(t *testing.T) {
Convey("return someting", t, func() {
res, err := s.MedalGroup(context.Background())
for k, re := range res {
fmt.Printf("%d %+v \n", k, re)
}
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func TestService_MedalGroupInfo(t *testing.T) {
Convey("return someting", t, func() {
res, err := s.MedalGroupInfo(context.Background())
for k, re := range res {
fmt.Printf("%d %+v \n", k, re)
}
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func TestService_MedalGroupParent(t *testing.T) {
Convey("return someting", t, func() {
res, err := s.MedalGroupParent(context.Background())
for k, re := range res {
fmt.Printf("%d %+v \n", k, re)
}
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func TestService_MedalGroupByID(t *testing.T) {
Convey("return someting", t, func() {
re, err := s.MedalGroupByGid(context.Background(), 2)
So(err, ShouldBeNil)
So(re, ShouldNotBeNil)
fmt.Printf("%+v \n", re)
})
}
func TestService_MedalGroupAdd(t *testing.T) {
Convey("return someting", t, func() {
pg := &model.MedalGroup{
Name: "test",
PID: 1,
Rank: int8(1),
IsOnline: int8(1),
}
err := s.MedalGroupAdd(context.Background(), pg)
So(err, ShouldBeNil)
fmt.Printf("%+v \n", err)
})
}
func TestService_MedalGroupUp(t *testing.T) {
Convey("return someting", t, func() {
pg := &model.MedalGroup{
Name: "test222",
PID: 2,
Rank: 2,
IsOnline: 0,
}
err := s.MedalGroupUp(context.Background(), 37, pg)
So(err, ShouldBeNil)
fmt.Printf("%+v \n", err)
})
}
func TestService_MedalOwner(t *testing.T) {
Convey("return someting", t, func() {
res, err := s.MedalOwner(context.Background(), 111)
for k, re := range res {
fmt.Printf("%d %+v \n", k, re)
}
fmt.Printf("err:%+v \n", err)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func TestService_MedalOwnerAdd(t *testing.T) {
Convey("return someting", t, func() {
err := s.MedalOwnerAdd(context.Background(), 41, 1, "", "", 1)
fmt.Printf("%+v \n", err)
So(err, ShouldBeNil)
})
}
func TestService_MedalAddList(t *testing.T) {
Convey("return someting", t, func() {
res, err := s.MedalOwnerAddList(context.Background(), 1)
for k, re := range res {
fmt.Printf("%d %+v \n", k, re)
}
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func TestService_MedalOwnerUpActivated(t *testing.T) {
Convey("return someting", t, func() {
err := s.MedalOwnerUpActivated(context.Background(), 1, 1)
fmt.Printf("%+v \n", err)
So(err, ShouldBeNil)
})
}
func TestService_MedalOwnerDel(t *testing.T) {
Convey("return someting", t, func() {
err := s.MedalOwnerDel(context.Background(), 1, 5, 0, "", "")
fmt.Printf("%+v \n", err)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,17 @@
package service
import (
"context"
"strconv"
"go-common/app/admin/main/usersuit/model"
"go-common/library/log"
)
func (s *Service) accNotify(c context.Context, uid int64, action string) (err error) {
msg := &model.AccountNotify{UID: uid, Type: "update", Action: action}
if err = s.accountNotifyPub.Send(c, strconv.FormatInt(msg.UID, 10), msg); err != nil {
log.Error("mid(%d) s.accountNotifyPub.Send(%+v) error(%v)", msg.UID, msg, err)
}
return
}

View File

@@ -0,0 +1,643 @@
package service
import (
"context"
"fmt"
"time"
"go-common/app/admin/main/usersuit/model"
accmdl "go-common/app/service/main/account/model"
"go-common/library/database/sql"
"go-common/library/ecode"
"go-common/library/log"
xtime "go-common/library/time"
"go-common/library/xstr"
"github.com/pkg/errors"
)
// PendantInfoList pendant list by group rank.
func (s *Service) PendantInfoList(c context.Context, arg *model.ArgPendantGroupList) (pis []*model.PendantInfo, pager *model.Pager, err error) {
var (
total int64
pids []int64
ppm map[int64][]*model.PendantPrice
)
pager = &model.Pager{
PN: arg.PN,
PS: arg.PS,
}
// all group pendants
if arg.GID == 0 {
if total, err = s.d.PendantGroupInfoTotal(c); err != nil {
err = errors.Wrap(err, "s.d.PendantGroupInfoTotal()")
return
}
if total <= 0 {
return
}
pager.Total = total
if pis, pids, err = s.d.PendantInfoAll(c, arg.PN, arg.PS); err != nil {
err = errors.Wrapf(err, "s.d.PendantInfoAll(%d,%d)", arg.PN, arg.PS)
return
}
if len(pis) == 0 || len(pids) == 0 {
log.Warn("no pendant list")
return
}
if ppm, err = s.d.PendantPriceIDs(c, pids); err != nil {
err = errors.Wrapf(err, "s.d.PendantPriceIDs(%s)", xstr.JoinInts(pids))
return
}
for _, pi := range pis {
if pp, ok := ppm[pi.ID]; ok {
pi.Prices = pp
}
}
return
}
// one group pendants
if total, err = s.d.PendantGroupRefsGidTotal(c, arg.GID); err != nil {
err = errors.Wrap(err, "s.d.PendantGroupRefsGidTotal()")
return
}
if total <= 0 {
return
}
pager.Total = total
var pg *model.PendantGroup
if pids, err = s.d.PendantGroupPIDs(c, arg.GID, arg.PN, arg.PS); err != nil {
err = errors.Wrapf(err, "s.d.PendantGroupPIDs(%d,%d,%d)", arg.GID, arg.PN, arg.PS)
return
}
if pg, err = s.d.PendantGroupID(c, arg.GID); err != nil {
err = errors.Wrapf(err, "s.d.PendantGroupID(%d)", arg.GID)
return
}
if len(pids) == 0 {
log.Warn("no pendant group relation")
return
}
if pis, _, err = s.d.PendantInfoIDs(c, pids); err != nil {
err = errors.Wrapf(err, "s.d.PendantInfoIDs(%s)", xstr.JoinInts(pids))
return
}
if len(pis) == 0 {
log.Warn("no pendant list")
return
}
if ppm, err = s.d.PendantPriceIDs(c, pids); err != nil {
err = errors.Wrapf(err, "s.d.PendantPriceIDs(%s)", xstr.JoinInts(pids))
return
}
for _, pi := range pis {
if pp, ok := ppm[pi.ID]; ok {
pi.Prices = pp
}
pi.GID = arg.GID
pi.GroupName = pg.Name
pi.GroupRank = pg.Rank
}
return
}
// PendantInfoID pendant info by pid and gid.
func (s *Service) PendantInfoID(c context.Context, pid, gid int64) (pi *model.PendantInfo, err error) {
if pi, err = s.d.PendantInfoID(c, pid); err != nil {
err = errors.Wrapf(err, "s.d.PendantInfoID(%d)", pid)
return
}
if pi == nil {
err = ecode.PendantNotFound
return
}
var (
pg *model.PendantGroup
ppm map[int64][]*model.PendantPrice
)
if pg, err = s.d.PendantGroupID(c, gid); err != nil {
err = errors.Wrapf(err, "s.d.PendantGroupID(%d)", gid)
return
}
if ppm, err = s.d.PendantPriceIDs(c, []int64{pid}); err != nil {
err = errors.Wrapf(err, "s.d.PendantPriceIDs(%d)", pid)
return
}
pi.GID = gid
pi.GroupName = pg.Name
pi.GroupRank = pg.Rank
if pp, ok := ppm[pid]; ok {
pi.Prices = pp
}
return
}
// PendantGroupID pendant group by ID.
func (s *Service) PendantGroupID(c context.Context, gid int64) (pg *model.PendantGroup, err error) {
if pg, err = s.d.PendantGroupID(c, gid); err != nil {
err = errors.Wrapf(err, "s.d.PendantGroupID(%d)", gid)
}
return
}
// PendantGroupList group page.
func (s *Service) PendantGroupList(c context.Context, arg *model.ArgPendantGroupList) (pgs []*model.PendantGroup, pager *model.Pager, err error) {
var total int64
pager = &model.Pager{
PN: arg.PN,
PS: arg.PS,
}
if total, err = s.d.PendantGroupsTotal(c); err != nil {
err = errors.Wrap(err, "s.d.PendantGroupsTotal()")
return
}
if total <= 0 {
return
}
pager.Total = total
if pgs, err = s.d.PendantGroups(c, arg.PN, arg.PS); err != nil {
err = errors.Wrapf(err, "s.d.PendantGroups(%d,%d)", arg.PN, arg.PS)
}
return
}
// PendantGroupAll all groups.
func (s *Service) PendantGroupAll(c context.Context) (pgs []*model.PendantGroup, err error) {
if pgs, err = s.d.PendantGroupAll(c); err != nil {
err = errors.Wrap(err, "s.d.PendantGroupAll()")
return
}
return
}
// PendantInfoAllNoPage all info on no page.
func (s *Service) PendantInfoAllNoPage(c context.Context) (pis []*model.PendantInfo, err error) {
if pis, err = s.d.PendantInfoAllNoPage(c); err != nil {
err = errors.Wrap(err, "s.d.PendantInfoAllNoPage()")
return
}
return
}
// AddPendantInfo add pendantInfo .
func (s *Service) AddPendantInfo(c context.Context, arg *model.ArgPendantInfo) (err error) {
var pg *model.PendantGroup
if pg, err = s.d.PendantGroupID(c, arg.GID); err != nil {
err = errors.Wrapf(err, "s.d.PendantGroupID(%d)", arg.GID)
return
}
if pg == nil {
err = errors.New("group no exist")
return
}
// begin tran
var tx *sql.Tx
if tx, err = s.d.BeginTran(c); err != nil {
err = errors.Wrap(err, "s.arc.BeginTran()")
return
}
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
pi := &model.PendantInfo{
Name: arg.Name,
Image: arg.Image,
ImageModel: arg.ImageModel,
Status: arg.Status,
Rank: arg.Rank,
}
var pid int64
if pid, err = s.d.TxAddPendantInfo(tx, pi); err != nil {
err = errors.Wrapf(err, "s.d.TxAddPendantInfo(%+v)", pi)
return
}
arg.PID = pid
pr := &model.PendantGroupRef{GID: arg.GID, PID: arg.PID}
if _, err = s.d.TxAddPendantGroupRef(tx, pr); err != nil {
err = errors.Wrapf(err, "s.d.TxAddPendantGroupRef(%+v)", pr)
return
}
pp := &model.PendantPrice{}
for _, tp := range model.PriceTypes {
pp.BulidPendantPrice(arg, tp)
if pp.Price != 0 {
if _, err = s.d.TxAddPendantPrices(tx, pp); err != nil {
err = errors.Wrapf(err, "s.d.TxAddPendantPrices(%+v)", pp)
return
}
}
}
return
}
// UpPendantInfo update pendant info .
func (s *Service) UpPendantInfo(c context.Context, arg *model.ArgPendantInfo) (err error) {
// begin tran
var tx *sql.Tx
if tx, err = s.d.BeginTran(c); err != nil {
err = errors.Wrap(err, "s.arc.BeginTran()")
return
}
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
pi := &model.PendantInfo{
ID: arg.PID,
Name: arg.Name,
Image: arg.Image,
ImageModel: arg.ImageModel,
Status: arg.Status,
Rank: arg.Rank,
}
if _, err = s.d.TxUpPendantInfo(tx, pi); err != nil {
err = errors.Wrapf(err, "s.d.TxUpPendantInfo(%+v)", pi)
return
}
if _, err = s.d.TxUpPendantGroupRef(tx, arg.GID, arg.PID); err != nil {
err = errors.Wrapf(err, "s.d.TxUpPendantGroupRef(%d,%d)", arg.GID, arg.PID)
return
}
pp := &model.PendantPrice{}
for _, tp := range model.PriceTypes {
pp.BulidPendantPrice(arg, tp)
if pp.Price != 0 {
if _, err = s.d.TxAddPendantPrices(tx, pp); err != nil {
err = errors.Wrapf(err, "s.d.TxAddPendantPrices(%+v)", pp)
return
}
}
}
return
}
// UpPendantGroupStatus update pendant group status
func (s *Service) UpPendantGroupStatus(c context.Context, gid int64, status int8) (err error) {
if _, err = s.d.UpPendantGroupStatus(c, gid, status); err != nil {
err = errors.Wrapf(err, "s.d.UpPendantGroupStatus(%d,%d)", gid, status)
}
return
}
// UpPendantInfoStatus update pendant info status
func (s *Service) UpPendantInfoStatus(c context.Context, pid int64, status int8) (err error) {
if _, err = s.d.UpPendantInfoStatus(c, pid, status); err != nil {
err = errors.Wrapf(err, "s.d.UpPendantInfoStatus(%d,%d)", pid, status)
}
return
}
// AddPendantGroup update pendant group.
func (s *Service) AddPendantGroup(c context.Context, arg *model.ArgPendantGroup) (err error) {
pg := &model.PendantGroup{
Name: arg.Name,
Rank: arg.Rank,
Status: arg.Status,
}
if _, err = s.d.AddPendantGroup(c, pg); err != nil {
err = errors.Wrapf(err, "s.d.AddPendantGroup(%+v)", pg)
}
return
}
// UpPendantGroup update pendant group.
func (s *Service) UpPendantGroup(c context.Context, arg *model.ArgPendantGroup) (err error) {
if arg.GID == 0 {
err = ecode.PendantNotFound
return
}
pg := &model.PendantGroup{
ID: arg.GID,
Name: arg.Name,
Rank: arg.Rank,
Status: arg.Status,
}
if _, err = s.d.UpPendantGroup(c, pg); err != nil {
err = errors.Wrapf(err, "s.d.UpPendantGroup(%+v)", pg)
}
return
}
// PendantOrders get pendant order historys.
func (s *Service) PendantOrders(c context.Context, arg *model.ArgPendantOrder) (pos []*model.PendantOrder, pager *model.Pager, err error) {
var total int64
pager = &model.Pager{
PN: arg.PN,
PS: arg.PS,
}
if total, err = s.d.MaxOrderHistory(c); err != nil {
err = errors.Wrapf(err, "s.d.MaxOrderHistory(%+v)", arg)
return
}
if total <= 0 {
return
}
pager.Total = total
var pids []int64
if pos, pids, err = s.d.OrderHistorys(c, arg); err != nil {
err = errors.Wrapf(err, "s.d.OrderHistorys(%+v)", arg)
return
}
if len(pids) == 0 {
return
}
var pim map[int64]*model.PendantInfo
if _, pim, err = s.d.PendantInfoIDs(c, pids); err != nil {
err = errors.Wrapf(err, "s.d.PendantInfoIDs(%v)", xstr.JoinInts(pids))
return
}
for _, v := range pos {
if pi, ok := pim[v.PID]; ok {
v.PName = pi.Name
}
v.CoverToPlatform()
}
return
}
// PendantPKG get pendant in pkg.
func (s *Service) PendantPKG(c context.Context, uid int64) (pkgs []*model.PendantPKG, equip *model.PendantPKG, err error) {
if equip, err = s.d.PendantEquipUID(c, uid); err != nil {
err = errors.Wrapf(err, "s.d.PendantEquipUID(%d)", uid)
return
}
if pkgs, err = s.d.PendantPKGs(c, uid); err != nil {
err = errors.Wrapf(err, "s.d.PendantPKGs(%d)", uid)
return
}
if len(pkgs) == 0 {
return
}
var time = time.Now().Unix()
for _, pkg := range pkgs {
if equip != nil && pkg.PID == equip.PID {
pkg.Status = model.PendantPKGOnEquip
}
if pkg.Status == model.PendantPKGValid && pkg.Expires < time {
pkg.Status = model.PendantPKGInvalid
}
}
return
}
// UserPKGDetails get user pkg 's pendant details.
func (s *Service) UserPKGDetails(c context.Context, uid, pid int64) (pkg *model.PendantPKG, err error) {
if pkg, err = s.d.PendantPKG(c, uid, pid); err != nil {
err = errors.Wrapf(err, "s.d.PendantPKG(%d,%d)", uid, pid)
}
return
}
// EquipPendant equip pendant.
func (s *Service) EquipPendant(c context.Context, uid, pid int64) (err error) {
var pkg *model.PendantPKG
if pkg, err = s.d.PendantPKG(c, uid, pid); err != nil {
err = errors.Wrapf(err, "s.d.PendantPKG(%d,%d)", uid, pid)
return
}
if pkg == nil || pkg.Expires < time.Now().Unix() {
log.Warn("pid(%d) not exist or expires(%d) is failed", pid, time.Now().Unix())
return
}
if _, err = s.d.AddPendantEquip(c, pkg); err != nil {
err = errors.Wrapf(err, "s.d.AddPendantEquip(%+v)", pkg)
return
}
s.addAsyn(func() {
if err = s.d.DelEquipsCache(context.Background(), []int64{uid}); err != nil {
log.Error("s.d.DelEquipsCache(%d) error(%+v)", uid, err)
return
}
})
s.addAsyn(func() {
if err = s.accNotify(context.Background(), uid, model.AccountNotifyUpdatePendant); err != nil {
log.Error("s.accNotify(%d) error(%+v)", uid, err)
return
}
})
return
}
// UpPendantPKG update user pkg.
func (s *Service) UpPendantPKG(c context.Context, uid, pid int64, day int64, msg *model.SysMsg, oid int64) (err error) {
var (
pi *model.PendantInfo
pkg *model.PendantPKG
)
if pi, err = s.d.PendantInfoID(c, pid); err != nil {
err = errors.Wrapf(err, "s.d.PendantInfoID(%d)", pid)
return
}
if pi == nil {
err = ecode.PendantNotFound
return
}
if pkg, err = s.d.PendantPKG(c, uid, pid); err != nil {
err = errors.Wrapf(err, "s.d.PendantPKG(%d,%d)", uid, pid)
return
}
if pkg == nil {
pkg = &model.PendantPKG{}
}
var operAction string
switch msg.Type {
case model.PendantAddStyleDay:
if pkg.Expires < time.Now().Unix() {
pkg.Expires = time.Now().Unix() + day*86400
pkg.PID = pid
pkg.UID = uid
pkg.TP = model.PendantAddStyleDay
} else {
pkg.Expires = pkg.Expires + day*86400
}
operAction = fmt.Sprintf("新增%s挂件 %d天", pi.Name, day)
case model.PendantAddStyleDate:
if pkg.ID == 0 {
err = errors.New("no pkg")
return
}
oldExpires := pkg.Expires
pkg.Expires = day
operAction = fmt.Sprintf("修改%s挂件 到期时间从%s至%s", pi.Name,
xtime.Time(oldExpires).Time().Format("2006-01-02 15:04:05"),
xtime.Time(pkg.Expires).Time().Format("2006-01-02 15:04:05"))
}
if _, err = s.d.AddPendantPKG(c, pkg); err != nil {
err = errors.Wrapf(err, "s.d.AddPendantPKG(%+v)", pkg)
return
}
if msg.IsMsg {
s.addAsyn(func() {
msg.Type = model.MsgTypeCustom
title, content, ip := model.MsgInfo(msg)
if err = s.d.SendSysMsg(context.Background(), []int64{uid}, title, content, ip); err != nil {
log.Error("s.d.MutliSendSysMsg(%d,%s,%s,%s) error(%+v)", uid, title, content, ip, err)
}
})
}
s.addAsyn(func() {
if err = s.d.DelPKGCache(context.Background(), []int64{uid}); err != nil {
log.Error("s.d.DelPKGCache(%d) error(%+v)", uid, err)
}
if err = s.d.SetPendantPointCache(context.Background(), uid, pid); err != nil {
log.Error("s.d.SetPendantPointCache(%d,%d) error(%+v)", uid, pid, err)
}
if _, err = s.d.AddPendantOperLog(context.Background(), oid, []int64{uid}, pid, operAction); err != nil {
log.Error("s.d.AddPendantOperLog(%d,%s) error(%+v)", oid, operAction, err)
}
})
s.addAsyn(func() {
if err = s.accNotify(context.Background(), uid, model.AccountNotifyUpdatePendant); err != nil {
log.Error("s.accNotify(%d) error(%+v)", uid, err)
return
}
})
return
}
// MutliSendPendant mutli send pendant.
func (s *Service) MutliSendPendant(c context.Context, uids []int64, pid int64, day int64, msg *model.SysMsg, oid int64) (err error) {
var (
pi *model.PendantInfo
opkgs, npkgs []*model.PendantPKG
)
if pi, err = s.d.PendantInfoID(c, pid); err != nil {
err = errors.Wrapf(err, "s.d.PendantInfoID(%d)", pid)
return
}
if pi == nil {
err = ecode.PendantNotFound
return
}
if opkgs, err = s.d.PendantPKGUIDs(c, uids, pid); err != nil {
err = errors.Wrapf(err, "s.d.PendantPKGUIDs(%+v,%d)", uids, pid)
return
}
var ouids, nuids []int64
for _, pkg := range opkgs {
if pkg.Expires < time.Now().Unix() {
pkg.Expires = time.Now().Unix() + day*86400
} else {
pkg.Expires = pkg.Expires + day*86400
}
ouids = append(ouids, pkg.UID)
}
nuids = s.diffSlice(uids, ouids)
for _, nuid := range nuids {
npkgs = append(npkgs, &model.PendantPKG{PID: pid, UID: nuid, Expires: time.Now().Unix() + day*86400})
}
// begin tran
var tx *sql.Tx
if tx, err = s.d.BeginTran(c); err != nil {
err = errors.Wrap(err, "s.arc.BeginTran()")
return
}
defer func() {
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
if len(npkgs) != 0 {
if _, err = s.d.TxAddPendantPKGs(tx, npkgs); err != nil {
err = errors.Wrapf(err, "s.d.TxAddPendantPKGs(%d,%s)", pid, xstr.JoinInts(nuids))
return
}
}
if len(opkgs) != 0 {
if _, err = s.d.TxUpPendantPKGs(tx, opkgs); err != nil {
err = errors.Wrapf(err, "s.d.TxUpPendantPKGs(%d,%s)", pid, xstr.JoinInts(ouids))
return
}
}
if msg.IsMsg {
s.addAsyn(func() {
title, content, ip := model.MsgInfo(msg)
if err = s.d.MutliSendSysMsg(context.Background(), uids, title, content, ip); err != nil {
log.Error("s.d.MutliSendSysMsg(%s,%s,%s,%s) error(%+v)", xstr.JoinInts(uids), title, content, ip, err)
}
})
}
s.addAsyn(func() {
if err = s.d.DelPKGCache(context.Background(), uids); err != nil {
log.Error("s.d.DelPKGCache(%s) error(%+v)", xstr.JoinInts(uids), err)
}
operAction := fmt.Sprintf("新增%s挂件 %d天", pi.Name, day)
if _, err = s.d.AddPendantOperLog(context.Background(), oid, uids, pid, operAction); err != nil {
log.Error("s.d.AddPendantOperLog(%d,%s,%s) error(%+v)", oid, xstr.JoinInts(uids), operAction, err)
}
})
for _, uid := range uids {
tid := uid
s.addAsyn(func() {
if err = s.accNotify(context.Background(), tid, model.AccountNotifyUpdatePendant); err != nil {
log.Error("s.accNotify(%d) error(%+v)", tid, err)
}
if err = s.d.SetPendantPointCache(context.Background(), tid, pid); err != nil {
log.Error("s.d.SetPendantPointCache(%d,%d) error(%+v)", tid, pid, err)
}
})
}
return
}
func (s *Service) diffSlice(sliceOne, sliceTwo []int64) (res []int64) {
for _, ov := range sliceOne {
inSlice := func(ov int64, sliceTwo []int64) bool {
for _, tv := range sliceTwo {
if tv == ov {
return true
}
}
return false
}(ov, sliceTwo)
if !inSlice {
res = append(res, ov)
}
}
return
}
// PendantOperlog pendant operactlog .
func (s *Service) PendantOperlog(c context.Context, pn, ps int) (opers []*model.PendantOperLog, pager *model.Pager, err error) {
var total int64
pager = &model.Pager{
PN: pn,
PS: ps,
}
if total, err = s.d.PendantOperationLogTotal(c); err != nil {
err = errors.Wrap(err, "s.d.PendantOperationLogTotal()")
return
}
if total <= 0 {
return
}
pager.Total = total
var uids []int64
if opers, uids, err = s.d.PendantOperLog(c, pn, ps); err != nil {
err = errors.Wrapf(err, "s.d.PendantOperLog(%d,%d)", pn, ps)
return
}
var accInfoMap map[int64]*accmdl.Info
if accInfoMap, err = s.fetchInfos(c, uids, _fetchInfoTimeout); err != nil {
log.Error("service.fetchInfos(%v, %v) error(%v)", xstr.JoinInts(uids), _fetchInfoTimeout, err)
err = nil
}
for _, v := range opers {
if accInfo, ok := accInfoMap[v.UID]; ok {
v.Action = fmt.Sprintf("给用户(%s) %s", accInfo.Name, v.Action)
}
if operName, ok := s.Managers[v.OID]; ok {
v.OperName = operName
}
}
return
}

View File

@@ -0,0 +1,146 @@
package service
import (
"context"
"testing"
"go-common/app/admin/main/usersuit/model"
. "github.com/smartystreets/goconvey/convey"
)
func Test_PendantInfoList(t *testing.T) {
Convey("return sth", t, func() {
arg := &model.ArgPendantGroupList{}
res, pager, err := s.PendantInfoList(context.Background(), arg)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
So(pager, ShouldNotBeNil)
})
}
func Test_PendantInfoID(t *testing.T) {
Convey("return sth", t, func() {
pi, err := s.PendantInfoID(context.Background(), 11, 22)
So(err, ShouldBeNil)
So(pi, ShouldNotBeNil)
})
}
func Test_PendantGroupID(t *testing.T) {
Convey("return sth", t, func() {
pg, err := s.PendantGroupID(context.Background(), 11)
So(err, ShouldBeNil)
So(pg, ShouldNotBeNil)
})
}
func Test_PendantGroupList(t *testing.T) {
Convey("return sth", t, func() {
arg := &model.ArgPendantGroupList{}
pgs, pager, err := s.PendantGroupList(context.Background(), arg)
So(err, ShouldBeNil)
So(pgs, ShouldNotBeNil)
So(pager, ShouldNotBeNil)
})
}
func Test_PendantGroupAll(t *testing.T) {
Convey("return sth", t, func() {
pgs, err := s.PendantGroupAll(context.Background())
So(err, ShouldBeNil)
So(pgs, ShouldNotBeNil)
})
}
func Test_PendantInfoAllOnSale(t *testing.T) {
Convey("return sth", t, func() {
pis, err := s.PendantInfoAllNoPage(context.Background())
So(err, ShouldBeNil)
So(pis, ShouldNotBeNil)
})
}
func Test_AddPendantInfo(t *testing.T) {
Convey("return sth", t, func() {
arg := &model.ArgPendantInfo{
PID: 111,
GID: 22,
Name: "222",
Image: "sdada",
ImageModel: "dasdada",
Rank: 11,
Status: 1,
IntegralPrice: 22,
}
err := s.AddPendantInfo(context.Background(), arg)
So(err, ShouldBeNil)
})
}
func Test_UpPendantInfo(t *testing.T) {
Convey("return sth", t, func() {
arg := &model.ArgPendantInfo{
PID: 111,
GID: 22,
Name: "222",
Image: "sdada",
ImageModel: "dasdada",
Rank: 11,
Status: 1,
IntegralPrice: 22,
}
err := s.UpPendantInfo(context.Background(), arg)
So(err, ShouldBeNil)
})
}
func Test_UpPendantGroupStatus(t *testing.T) {
Convey("return sth", t, func() {
err := s.UpPendantGroupStatus(context.Background(), 1, 1)
So(err, ShouldBeNil)
})
}
func Test_UpPendantInfoStatus(t *testing.T) {
Convey("return sth", t, func() {
err := s.UpPendantInfoStatus(context.Background(), 1, 1)
So(err, ShouldBeNil)
})
}
func Test_AddPendantGroup(t *testing.T) {
Convey("return sth", t, func() {
arg := &model.ArgPendantGroup{
GID: 1,
Name: "2121",
Rank: 11,
Status: 1,
}
err := s.AddPendantGroup(context.Background(), arg)
So(err, ShouldBeNil)
})
}
func Test_UpPendantGroup(t *testing.T) {
Convey("return sth", t, func() {
arg := &model.ArgPendantGroup{
GID: 1,
Name: "2121",
Rank: 11,
Status: 1,
}
err := s.UpPendantGroup(context.Background(), arg)
So(err, ShouldBeNil)
})
}
func Test_PendantOrders(t *testing.T) {
Convey("return sth", t, func() {
arg := &model.ArgPendantOrder{}
pos, pager, err := s.PendantOrders(context.Background(), arg)
So(err, ShouldBeNil)
So(pos, ShouldNotBeNil)
So(pager, ShouldNotBeNil)
})
}

View File

@@ -0,0 +1,97 @@
package service
import (
"context"
"sync"
"time"
"go-common/app/admin/main/usersuit/conf"
"go-common/app/admin/main/usersuit/dao"
"go-common/library/log"
"go-common/library/queue/databus"
account "go-common/app/service/main/account/api"
)
// Service struct of service.
type Service struct {
d *dao.Dao
// wait group
wg sync.WaitGroup
// conf
c *conf.Config
accountClient account.AccountClient
// databus pub
accountNotifyPub *databus.Databus
Managers map[int64]string
asynch chan func()
}
// New create service instance and return.
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
d: dao.New(c),
asynch: make(chan func(), 102400),
accountNotifyPub: databus.New(c.AccountNotify),
}
var err error
if s.accountClient, err = account.NewClient(c.AccountGRPC); err != nil {
panic(err)
}
s.loadManager()
s.wg.Add(1)
go s.asynproc()
go s.loadmanagerproc()
return
}
func (s *Service) loadmanagerproc() {
for {
time.Sleep(1 * time.Hour)
s.loadManager()
}
}
func (s *Service) loadManager() {
managers, err := s.d.Managers(context.TODO())
if err != nil {
log.Error("s.Managers error(%v)", err)
return
}
s.Managers = managers
}
// Close dao.
func (s *Service) Close() {
s.d.Close()
close(s.asynch)
time.Sleep(1 * time.Second)
s.wg.Wait()
}
// Ping check server ok.
func (s *Service) Ping(c context.Context) (err error) {
err = s.d.Ping(c)
return
}
func (s *Service) addAsyn(f func()) {
select {
case s.asynch <- f:
default:
log.Warn("asynproc chan full")
}
}
// cacheproc is a routine for executing closure.
func (s *Service) asynproc() {
defer s.wg.Done()
for {
f, ok := <-s.asynch
if !ok {
return
}
f()
}
}

View File

@@ -0,0 +1,19 @@
package service
import (
"flag"
"path/filepath"
"time"
"go-common/app/admin/main/usersuit/conf"
)
var s *Service
func init() {
dir, _ := filepath.Abs("../cmd/convey-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
time.Sleep(time.Second)
}

View File

@@ -0,0 +1,16 @@
package service
import (
"context"
"io"
"go-common/library/log"
)
// Upload http upload file.
func (s *Service) Upload(c context.Context, fileName, fileType string, expire int64, body io.Reader) (location string, err error) {
if location, err = s.d.Upload(c, fileName, fileType, expire, body); err != nil {
log.Error("s.upload.Upload() error(%v)", err)
}
return
}