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,85 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"dialog_test.go",
"jointly_test.go",
"order_test.go",
"panel_test.go",
"privilege_test.go",
"push_test.go",
"resouce_test.go",
"service_test.go",
"tips_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/main/vip/conf:go_default_library",
"//app/admin/main/vip/model:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"business.go",
"dialog.go",
"jointly.go",
"month.go",
"order.go",
"panel.go",
"platform.go",
"privilege.go",
"push.go",
"resouce.go",
"service.go",
"tips.go",
"version.go",
"vip.go",
"welfare.go",
],
importpath = "go-common/app/admin/main/vip/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/main/vip/conf:go_default_library",
"//app/admin/main/vip/dao:go_default_library",
"//app/admin/main/vip/model:go_default_library",
"//app/service/main/vip/model:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/google/uuid:go_default_library",
"//vendor/github.com/jinzhu/gorm:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/golang.org/x/sync/errgroup:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,137 @@
package service
import (
"context"
"crypto/md5"
"encoding/hex"
"fmt"
"math/rand"
"time"
"go-common/app/admin/main/vip/model"
"go-common/library/ecode"
"go-common/library/log"
"github.com/pkg/errors"
)
// BusinessList business list.
func (s *Service) BusinessList(c context.Context, pn, ps, status int) (res []*model.VipBusinessInfo, count int64, err error) {
if count, err = s.dao.BussinessCount(c, status); err != nil {
log.Error("%+v", err)
return
}
if count == 0 {
return
}
if res, err = s.dao.BussinessList(c, pn, ps, status); err != nil {
log.Error("%+v", err)
return
}
return
}
// UpdateBusinessInfo update business info.
func (s *Service) UpdateBusinessInfo(c context.Context, req *model.VipBusinessInfo) (err error) {
var (
business *model.VipBusinessInfo
appkey string
businessName string
)
if business, err = s.dao.SelBusiness(c, req.ID); err != nil {
err = errors.WithStack(err)
return
}
if business == nil {
err = ecode.VipBusinessNotExitErr
return
}
req.Secret = business.Secret
appkey = business.AppKey
businessName = business.BusinessName
arg := new(model.QueryBusinessInfo)
if appkey != req.AppKey {
arg.Appkey = req.AppKey
if business, err = s.dao.SelBusinessByQuery(c, arg); err != nil {
err = errors.WithStack(err)
return
}
if business != nil {
err = ecode.VipAppkeyExitErr
return
}
req.Secret = s.makeSecret(req.AppKey)
}
if businessName != req.BusinessName {
arg = new(model.QueryBusinessInfo)
arg.Name = req.BusinessName
if business, err = s.dao.SelBusinessByQuery(c, arg); err != nil {
err = errors.WithStack(err)
return
}
if business != nil {
err = ecode.VipBusinessNameExitErr
return
}
}
if _, err = s.dao.UpdateBusiness(c, req); err != nil {
log.Error("%+v", err)
return
}
return
}
// AddBusinessInfo add business info.
func (s *Service) AddBusinessInfo(c context.Context, req *model.VipBusinessInfo) (err error) {
var (
business *model.VipBusinessInfo
)
arg := new(model.QueryBusinessInfo)
arg.Appkey = req.AppKey
if business, err = s.dao.SelBusinessByQuery(c, arg); err != nil {
err = errors.WithStack(err)
return
}
if business != nil {
err = ecode.VipAppkeyExitErr
return
}
arg = new(model.QueryBusinessInfo)
arg.Name = req.BusinessName
if business, err = s.dao.SelBusinessByQuery(c, arg); err != nil {
err = errors.WithStack(err)
return
}
if business != nil {
err = ecode.VipBusinessNameExitErr
return
}
req.Secret = s.makeSecret(req.AppKey)
if _, err = s.dao.AddBusiness(c, req); err != nil {
log.Error("%+v", err)
return
}
return
}
func (s *Service) makeSecret(appkey string) string {
key := fmt.Sprintf("%v,%v,%v", appkey, time.Now().UnixNano(), rand.Intn(100000000))
hash := md5.New()
hash.Write([]byte(key))
sum := hash.Sum(nil)
return hex.EncodeToString(sum)
}
// BusinessInfo business info
func (s *Service) BusinessInfo(c context.Context, id int) (r *model.VipBusinessInfo, err error) {
if r, err = s.dao.SelBusiness(c, id); err != nil {
log.Error("%+v", err)
return
}
return
}

View File

@@ -0,0 +1,91 @@
package service
import (
"context"
"time"
"go-common/app/admin/main/vip/model"
"go-common/library/ecode"
"go-common/library/log"
)
// DialogAll .
func (s *Service) DialogAll(c context.Context, appID, platform int64, status string) (res []*model.ConfDialogList, err error) {
var list []*model.ConfDialog
if list, err = s.dao.DialogAll(c, appID, platform, status); err != nil {
return
}
res = make([]*model.ConfDialogList, len(list))
for i, v := range list {
res[i] = &model.ConfDialogList{ConfDialog: v, Status: dialogStatus(v)}
}
return
}
func dialogStatus(v *model.ConfDialog) (status string) {
curr := time.Now()
switch {
case v.Stage && v.StartTime.Time().After(curr):
return "padding"
case v.Stage && v.StartTime.Time().Before(curr) && (int64(v.EndTime) == 0 || v.EndTime.Time().After(curr)):
return "active"
case !v.Stage || (int64(v.EndTime) > 0 && v.EndTime.Time().Before(curr)):
return "inactive"
default:
return ""
}
}
// DialogByID .
func (s *Service) DialogByID(c context.Context, arg *model.ArgID) (dlg *model.ConfDialog, err error) {
return s.dao.DialogByID(c, arg.ID)
}
// DialogSave .
func (s *Service) DialogSave(c context.Context, arg *model.ConfDialog) (eff int64, err error) {
var db *model.ConfDialog
if arg.ID != 0 {
if db, err = s.dao.DialogByID(c, arg.ID); err != nil {
return
}
if db != nil {
arg.Ctime = db.Ctime
arg.Stage = db.Stage
}
}
// PRD: 如果平台、app_id完全相同时生效时间不可冲突否则不允许保存
var exist []*model.ConfDialog
if exist, err = s.dao.DialogBy(c, arg.AppID, arg.Platform, arg.ID); err != nil {
return
}
for _, v := range exist {
if v.StartTime.Time().Unix() <= arg.EndTime.Time().Unix() && v.EndTime.Time().Unix() >= arg.StartTime.Time().Unix() {
err = ecode.VipDialogConflictErr
return
}
}
return s.dao.DialogSave(c, arg)
}
// DialogEnable .
func (s *Service) DialogEnable(c context.Context, arg *model.ConfDialog) (eff int64, err error) {
var db *model.ConfDialog
if arg.ID != 0 {
if db, err = s.dao.DialogByID(c, arg.ID); err != nil {
return
}
}
if db == nil || db.StartTime.Time().After(time.Now()) {
err = ecode.VipDialogTimeErr
return
}
return s.dao.DialogEnable(c, arg)
}
// DialogDel .
func (s *Service) DialogDel(c context.Context, arg *model.ArgID, operator string) (eff int64, err error) {
eff, err = s.dao.DialogDel(c, arg.ID)
log.Warn("user(%s) delete dialog(%d) effect row(%d)", operator, arg.ID, eff)
return
}

View File

@@ -0,0 +1,78 @@
package service
import (
"context"
"go-common/app/admin/main/vip/model"
"go-common/library/ecode"
xtime "go-common/library/time"
"testing"
"time"
"github.com/smartystreets/goconvey/convey"
)
func TestServiceDialogSave(t *testing.T) {
curr := xtime.Time(time.Now().Unix())
convey.Convey("DialogSave", t, func() {
dlg1 := &model.ConfDialog{ID: 1, StartTime: curr, Operator: "tommy"}
eff, err := s.DialogSave(context.TODO(), dlg1)
convey.So(err, convey.ShouldBeNil)
convey.So(eff, convey.ShouldNotBeNil)
})
convey.Convey("DialogSave2", t, func() {
dlg2 := &model.ConfDialog{ID: 2, StartTime: xtime.Time(time.Now().Unix() + 1), Operator: "tommy"}
_, err := s.DialogSave(context.TODO(), dlg2)
convey.So(err, convey.ShouldEqual, ecode.VipDialogConflictErr)
})
convey.Convey("DialogByID", t, func() {
dlg, err := s.DialogByID(context.TODO(), &model.ArgID{ID: 1})
convey.So(err, convey.ShouldBeNil)
convey.So(dlg, convey.ShouldNotBeNil)
})
convey.Convey("DialogEnable", t, func() {
eff, err := s.DialogEnable(context.TODO(), &model.ConfDialog{ID: 1, Stage: true})
convey.So(err, convey.ShouldBeNil)
convey.So(eff, convey.ShouldNotBeNil)
})
convey.Convey("DialogAll", t, func() {
res, err := s.DialogAll(context.TODO(), 0, 0, "active")
convey.So(err, convey.ShouldBeNil)
convey.So(res, convey.ShouldNotBeNil)
})
}
func TestServiceDialogDel(t *testing.T) {
convey.Convey("DialogDel", t, func() {
eff, err := s.DialogDel(context.TODO(), nil, "")
convey.So(err, convey.ShouldBeNil)
convey.So(eff, convey.ShouldNotBeNil)
})
}
func TestServiceDialogStatus(t *testing.T) {
convey.Convey("dialogStatus padding", t, func() {
v := &model.ConfDialog{Stage: true, StartTime: xtime.Time(time.Now().AddDate(1, 1, 1).Unix())}
res := dialogStatus(v)
convey.So(res, convey.ShouldEqual, "padding")
})
convey.Convey("dialogStatus active", t, func() {
v := &model.ConfDialog{Stage: true}
res := dialogStatus(v)
convey.So(res, convey.ShouldEqual, "active")
v.StartTime = xtime.Time(time.Now().AddDate(-1, 1, 1).Unix())
res = dialogStatus(v)
convey.So(res, convey.ShouldEqual, "active")
v.EndTime = xtime.Time(time.Now().AddDate(1, 1, 1).Unix())
res = dialogStatus(v)
convey.So(res, convey.ShouldEqual, "active")
})
convey.Convey("dialogStatus inactive", t, func() {
v := &model.ConfDialog{Stage: false}
res := dialogStatus(v)
convey.So(res, convey.ShouldEqual, "inactive")
v.EndTime = xtime.Time(time.Now().AddDate(-1, 1, 1).Unix())
res = dialogStatus(v)
convey.So(res, convey.ShouldEqual, "inactive")
})
}

View File

@@ -0,0 +1,85 @@
package service
import (
"context"
"time"
"go-common/app/admin/main/vip/model"
"go-common/library/ecode"
)
// JointlysByState jointlys by state.
func (s *Service) JointlysByState(c context.Context, state int8) (res []*model.Jointly, err error) {
now := time.Now().Unix()
res, err = s.dao.JointlysByState(c, state, time.Now().Unix())
for _, v := range res {
switch {
case v.StartTime > now:
v.State = model.WillEffect
case v.StartTime < now && v.EndTime > now:
v.State = model.Effect
case v.EndTime < now:
v.State = model.LoseEffect
}
}
return
}
// AddJointly add jointly.
func (s *Service) AddJointly(c context.Context, j *model.ArgAddJointly) (err error) {
if j.StartTime >= j.EndTime {
err = ecode.VipStartTimeErr
return
}
if len(j.Title) > _maxTitleLen {
err = ecode.VipTitleTooLongErr
return
}
if len(j.Content) > _maxContentLen {
err = ecode.VipContentTooLongErr
return
}
_, err = s.dao.AddJointly(c, &model.Jointly{
Title: j.Title,
Content: j.Content,
Operator: j.Operator,
StartTime: j.StartTime,
EndTime: j.EndTime,
Link: j.Link,
IsHot: j.IsHot,
})
return
}
// ModifyJointly modify jointly.
func (s *Service) ModifyJointly(c context.Context, j *model.ArgModifyJointly) (err error) {
if j.StartTime >= j.EndTime {
err = ecode.VipStartTimeErr
return
}
if len(j.Title) > _maxTitleLen {
err = ecode.VipTitleTooLongErr
return
}
if len(j.Content) > _maxContentLen {
err = ecode.VipContentTooLongErr
return
}
_, err = s.dao.UpdateJointly(c, &model.Jointly{
Title: j.Title,
Content: j.Content,
Operator: j.Operator,
Link: j.Link,
IsHot: j.IsHot,
ID: j.ID,
StartTime: j.StartTime,
EndTime: j.EndTime,
})
return
}
// DeleteJointly delete jointly .
func (s *Service) DeleteJointly(c context.Context, id int64) (err error) {
_, err = s.dao.DeleteJointly(c, id)
return
}

View File

@@ -0,0 +1,49 @@
package service
import (
"testing"
"go-common/app/admin/main/vip/model"
. "github.com/smartystreets/goconvey/convey"
)
// go test -test.v -test.run TestServiceAddJointly
func TestServiceAddJointly(t *testing.T) {
Convey("TestServiceAddJointly", t, func() {
err := s.AddJointly(c, &model.ArgAddJointly{
Title: "这是一条被修改的",
Content: "内容",
StartTime: 1433202904,
EndTime: 1433202905,
Link: "http://www.baidu.com",
IsHot: 1,
Operator: "admin",
})
So(err, ShouldBeNil)
})
}
// go test -test.v -test.run TestServiceModifyJointly
func TestServiceModifyJointly(t *testing.T) {
Convey("TestServiceModifyJointly", t, func() {
err := s.ModifyJointly(c, &model.ArgModifyJointly{
ID: 2,
Title: "无效的记录,修改",
Content: "修改内容",
Link: "http://www.baidu.com",
IsHot: 1,
Operator: "admin",
})
So(err, ShouldBeNil)
})
}
// go test -test.v -test.run TestServiceJointlysByState
func TestServiceJointlysByState(t *testing.T) {
Convey("TestServiceJointlysByState", t, func() {
res, err := s.JointlysByState(c, 2)
t.Logf("count %+v", len(res))
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,60 @@
package service
import (
"context"
"go-common/app/admin/main/vip/model"
"go-common/library/ecode"
"github.com/pkg/errors"
)
// MonthList .
func (s *Service) MonthList(c context.Context) (res []*model.VipMonth, err error) {
return s.dao.MonthList(c)
}
// MonthEdit .
func (s *Service) MonthEdit(c context.Context, id int64, status int8, op string) (err error) {
var (
m *model.VipMonth
)
if m, err = s.dao.GetMonth(c, id); err != nil {
err = errors.WithStack(err)
return
}
if m == nil {
err = ecode.VipMonthErr
return
}
_, err = s.dao.MonthEdit(c, id, status, op)
return
}
// PriceList .
func (s *Service) PriceList(c context.Context, mID int64) (res []*model.VipMonthPrice, err error) {
return s.dao.PriceList(c, mID)
}
// PriceAdd .
func (s *Service) PriceAdd(c context.Context, mp *model.VipMonthPrice) (err error) {
_, err = s.dao.PriceAdd(c, mp)
return
}
// PriceEdit .
func (s *Service) PriceEdit(c context.Context, mp *model.VipMonthPrice) (err error) {
var (
vmp *model.VipMonthPrice
)
if vmp, err = s.dao.GetPrice(c, mp.ID); err != nil {
err = errors.WithStack(err)
return
}
if vmp == nil {
err = ecode.VipMonthPriceErr
return
}
_, err = s.dao.PriceEdit(c, mp)
return
}

View File

@@ -0,0 +1,83 @@
package service
import (
"context"
"strings"
"time"
"go-common/app/admin/main/vip/model"
vipmol "go-common/app/service/main/vip/model"
"go-common/library/ecode"
"github.com/google/uuid"
"github.com/pkg/errors"
)
//OrderList order list.
func (s *Service) OrderList(c context.Context, arg *model.ArgPayOrder) (res []*model.PayOrder, count int64, err error) {
if count, err = s.dao.OrderCount(c, arg); err != nil {
err = errors.WithStack(err)
return
}
if res, err = s.dao.OrderList(c, arg); err != nil {
err = errors.WithStack(err)
}
return
}
//Refund refund order.
func (s *Service) Refund(c context.Context, orderNo, username string, refundAmount float64) (err error) {
var (
order *model.PayOrder
)
if order, err = s.dao.SelOrder(c, orderNo); err != nil {
err = errors.WithStack(err)
return
}
if order == nil {
err = ecode.VipOrderNoErr
return
}
if order.Status != model.SUCCESS {
err = ecode.VipOrderStatusErr
return
}
if order.ToMid > 0 {
err = ecode.VipOrderToMidErr
return
}
if order.AppID == vipmol.EleAppID {
return ecode.VipEleOrderCanNotReFundErr
}
if order.Money < refundAmount {
err = ecode.VipOrderMoneyErr
return
}
if order.Money < refundAmount+order.RefundAmount {
err = ecode.VipOrderMoneyErr
return
}
var timefmt = time.Now().Format("20060102150405")
if len(order.ThirdTradeNo) <= 0 || order.ThirdTradeNo[0:len(timefmt)] == timefmt {
err = ecode.VipOldOrderErr
return
}
refundID := strings.Replace(uuid.New().String(), "-", "", -1)[4:20]
if err = s.dao.PayRefund(c, order, refundAmount, refundID); err != nil {
err = errors.WithStack(err)
return
}
olog := new(model.PayOrderLog)
olog.OrderNo = order.OrderNo
olog.Mid = order.Mid
olog.RefundID = refundID
olog.Status = model.REFUNDING
olog.Operator = username
olog.RefundAmount = refundAmount
if err = s.dao.AddPayOrderLog(c, olog); err != nil {
err = errors.WithStack(err)
}
return
}

View File

@@ -0,0 +1,27 @@
package service
import (
"context"
"testing"
"go-common/app/admin/main/vip/model"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_OrderList(t *testing.T) {
Convey("test order list", t, func() {
order := new(model.ArgPayOrder)
order.Mid = 1001
res, count, err := s.OrderList(context.TODO(), order)
t.Logf("orderlist len:%+v count:%v", res, count)
So(err, ShouldBeNil)
})
}
func TestService_Refund(t *testing.T) {
Convey("test refund ", t, func() {
err := s.Refund(context.TODO(), "93035846180822184113", "zhaozhihao", 10)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,304 @@
package service
import (
"context"
"go-common/app/admin/main/vip/model"
"go-common/library/ecode"
)
// VipPriceConfigs get vip price configs.
func (s *Service) VipPriceConfigs(c context.Context, arg *model.ArgVipPrice) (res []*model.VipPriceConfig, err error) {
var (
vpcs []*model.VipPriceConfig
mvd map[int64]*model.VipDPriceConfig
)
if vpcs, err = s.dao.VipPriceConfigs(c); err != nil {
return
}
if mvd, err = s.dao.VipPriceDiscountConfigs(c); err != nil {
return
}
for _, item := range vpcs {
if arg.Plat != -1 && item.Plat != arg.Plat {
continue
}
if arg.Month != -1 && item.Month != arg.Month {
continue
}
if arg.SubType != -1 && item.SubType != arg.SubType {
continue
}
if arg.SuitType != -1 && item.SuitType != arg.SuitType {
continue
}
if vdc, ok := mvd[item.ID]; ok {
item.NPrice = vdc.DPrice
item.PdID = vdc.PdID
} else {
item.NPrice = item.OPrice
}
res = append(res, item)
}
return
}
// VipPriceConfigID get vip price config by id.
func (s *Service) VipPriceConfigID(c context.Context, arg *model.ArgVipPriceID) (res *model.VipPriceConfig, err error) {
res, err = s.dao.VipPriceConfigID(c, arg)
return
}
// AddVipPriceConfig add vip price config.
func (s *Service) AddVipPriceConfig(c context.Context, arg *model.ArgAddOrUpVipPrice) (err error) {
var count int64
if len(arg.Superscript) > 18 {
err = ecode.VipPanelSuperscriptTooLongErr
return
}
// 平台校验
platForm, err := s.dao.PlatformByID(c, int64(arg.Plat))
if err != nil || platForm == nil {
err = ecode.VipPanelPlatNotExitErr
return
}
// 价格校验
if arg.OPrice <= 0 {
err = ecode.VipPanelValidOPriceErr
return
}
// 面版冲突
if count, err = s.dao.VipPriceConfigUQCheck(c, arg); err != nil {
return
}
if count > 0 {
err = ecode.VipPanelConfNotUQErr
return
}
vpc := &model.VipPriceConfig{
Plat: arg.Plat,
PdName: arg.PdName,
PdID: arg.PdID,
SuitType: arg.SuitType,
Month: arg.Month,
SubType: arg.SubType,
OPrice: arg.OPrice,
Remark: arg.Remark,
Status: model.VipPriceConfigStatusON,
Operator: arg.Operator,
OpID: arg.OpID,
Superscript: arg.Superscript,
Selected: arg.Selected,
StartBuild: arg.StartBuild,
EndBuild: arg.EndBuild,
}
err = s.dao.AddVipPriceConfig(c, vpc)
return
}
// UpVipPriceConfig update vip price config.
func (s *Service) UpVipPriceConfig(c context.Context, arg *model.ArgAddOrUpVipPrice) (err error) {
var (
count int64
max float64
ovpc *model.VipPriceConfig
)
if len(arg.Superscript) > 18 {
err = ecode.VipPanelSuperscriptTooLongErr
return
}
if ovpc, err = s.dao.VipPriceConfigID(c, &model.ArgVipPriceID{ID: arg.ID}); err != nil {
return
}
if max, err = s.dao.VipMaxPriceDiscount(c, arg); err != nil {
return
}
if ovpc == nil {
err = ecode.VipPanelConfNotExistErr
return
}
// 价格校验
if arg.OPrice <= 0 {
err = ecode.VipPanelValidOPriceErr
return
}
if arg.OPrice < max {
err = ecode.VipPanelValidDPriceErr
return
}
if arg.Plat != ovpc.Plat || arg.Month != ovpc.Month || arg.SubType != ovpc.SubType || arg.SuitType != ovpc.SuitType ||
arg.StartBuild != ovpc.StartBuild || arg.EndBuild != ovpc.EndBuild {
// 面版冲突
if count, err = s.dao.VipPriceConfigUQCheck(c, arg); err != nil {
return
}
if count > 0 {
err = ecode.VipPanelConfNotUQErr
return
}
}
vpc := &model.VipPriceConfig{
ID: arg.ID,
Plat: arg.Plat,
PdName: arg.PdName,
PdID: arg.PdID,
SuitType: arg.SuitType,
Month: arg.Month,
SubType: arg.SubType,
OPrice: arg.OPrice,
Remark: arg.Remark,
Status: model.VipPriceConfigStatusON,
Operator: arg.Operator,
OpID: arg.OpID,
Superscript: arg.Superscript,
Selected: arg.Selected,
StartBuild: arg.StartBuild,
EndBuild: arg.EndBuild,
}
err = s.dao.UpVipPriceConfig(c, vpc)
return
}
// DelVipPriceConfig delete vip price config.
func (s *Service) DelVipPriceConfig(c context.Context, arg *model.ArgVipPriceID) (err error) {
err = s.dao.DelVipPriceConfig(c, arg)
return
}
// VipDPriceConfigs get discount price config list.
func (s *Service) VipDPriceConfigs(c context.Context, arg *model.ArgVipPriceID) (res []*model.VipDPriceConfig, err error) {
res, err = s.dao.VipDPriceConfigs(c, arg)
return
}
// VipDPriceConfigID get discount price config by id.
func (s *Service) VipDPriceConfigID(c context.Context, arg *model.ArgVipDPriceID) (res *model.VipDPriceConfig, err error) {
res, err = s.dao.VipDPriceConfigID(c, arg)
return
}
// AddVipDPriceConfig add vip discount price config.
func (s *Service) AddVipDPriceConfig(c context.Context, arg *model.ArgAddOrUpVipDPrice) (err error) {
var (
vpc *model.VipPriceConfig
mvd map[int64]*model.VipDPriceConfig
)
if vpc, err = s.dao.VipPriceConfigID(c, &model.ArgVipPriceID{ID: arg.ID}); err != nil {
return
}
if vpc == nil {
err = ecode.VipPanelConfNotExistErr
return
}
// if vpc.CheckProductID(arg) {
// err = ecode.VipPanelProductIDNotNilErr
// return
// }
if vpc.OPrice < arg.DPrice {
err = ecode.VipPanelValidDPriceErr
return
}
if vpc.SubType != model.AutoRenew && arg.FirstPrice > 0 {
return ecode.VipPanelFirstPriceNotSupportErr
}
if arg.ETime != 0 && arg.STime >= arg.ETime {
err = ecode.VipPanelSTGeqETErr
return
}
// 面版冲突
if mvd, err = s.dao.VipDPriceConfigUQTime(c, arg); err != nil {
return
}
if len(mvd) > 0 {
err = ecode.VipPanelValidTimeErr
return
}
nvdc := &model.VipDPriceConfig{
ID: arg.ID,
PdID: arg.PdID,
DPrice: arg.DPrice,
STime: arg.STime,
ETime: arg.ETime,
Remark: arg.Remark,
Operator: arg.Operator,
OpID: arg.OpID,
FirstPrice: arg.FirstPrice,
}
err = s.dao.AddVipDPriceConfig(c, nvdc)
return
}
// UpVipDPriceConfig update vip discount price config.
func (s *Service) UpVipDPriceConfig(c context.Context, arg *model.ArgAddOrUpVipDPrice) (err error) {
var (
ovpc *model.VipPriceConfig
ovdc *model.VipDPriceConfig
mvd map[int64]*model.VipDPriceConfig
)
if ovpc, err = s.dao.VipPriceConfigID(c, &model.ArgVipPriceID{ID: arg.ID}); err != nil {
return
}
if ovpc == nil {
err = ecode.VipPanelConfNotExistErr
return
}
if ovdc, err = s.dao.VipDPriceConfigID(c, &model.ArgVipDPriceID{DisID: arg.DisID}); err != nil {
return
}
// if ovpc.CheckProductID(arg) {
// err = ecode.VipPanelProductIDNotNilErr
// return
// }
if ovpc.SubType != model.AutoRenew && arg.FirstPrice > 0 {
return ecode.VipPanelFirstPriceNotSupportErr
}
if ovpc.OPrice < arg.DPrice {
err = ecode.VipPanelValidDPriceErr
return
}
if arg.ETime != 0 && arg.STime >= arg.ETime {
err = ecode.VipPanelSTGeqETErr
return
}
if arg.STime != ovdc.STime || arg.ETime != ovdc.ETime {
// 面版冲突
if mvd, err = s.dao.VipDPriceConfigUQTime(c, arg); err != nil {
return
}
if _, ok := mvd[arg.DisID]; ok {
delete(mvd, arg.DisID)
}
if len(mvd) > 0 {
err = ecode.VipPanelValidTimeErr
return
}
}
vdc := &model.VipDPriceConfig{
DisID: arg.DisID,
ID: arg.ID,
PdID: arg.PdID,
DPrice: arg.DPrice,
STime: arg.STime,
ETime: arg.ETime,
Remark: arg.Remark,
Operator: arg.Operator,
OpID: arg.OpID,
FirstPrice: arg.FirstPrice,
}
err = s.dao.UpVipDPriceConfig(c, vdc)
return
}
// DelVipDPriceConfig delete vip discount price config.
func (s *Service) DelVipDPriceConfig(c context.Context, arg *model.ArgVipDPriceID) (err error) {
err = s.dao.DelVipDPriceConfig(c, arg)
return
}
// PanelPlatFormTypes .
func (s *Service) PanelPlatFormTypes(c context.Context) (res []*model.TypePlatform, err error) {
if res, err = s.dao.PlatformTypes(c); err != nil {
return
}
return
}

View File

@@ -0,0 +1,144 @@
package service
import (
"context"
"fmt"
"go-common/app/admin/main/vip/model"
xtime "go-common/library/time"
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
)
func TestServiceVipPriceConfigs(t *testing.T) {
Convey("Test_VipPriceConfigs", t, func() {
av := &model.ArgVipPrice{
Plat: 1,
Month: 1,
SubType: 1,
SuitType: 1,
}
res, err := s.VipPriceConfigs(context.TODO(), av)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func TestServiceVipPriceConfigID(t *testing.T) {
Convey("Test_VipPriceConfigID", t, func() {
res, err := s.VipPriceConfigID(context.TODO(), &model.ArgVipPriceID{ID: 1})
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func TestServiceAddVipPriceConfig(t *testing.T) {
Convey("Test_AddVipPriceConfig", t, func() {
aavpc := &model.ArgAddOrUpVipPrice{
Plat: 1,
PdName: "xxx",
PdID: "xxx",
Month: 1,
SubType: 1,
SuitType: 0,
OPrice: 1,
}
err := s.AddVipPriceConfig(context.TODO(), aavpc)
So(err, ShouldBeNil)
})
}
func TestServiceUpVipPriceConfig(t *testing.T) {
Convey("Test_UpVipPriceConfig", t, func() {
aavpc := &model.ArgAddOrUpVipPrice{
ID: 235,
Plat: 1,
PdName: "xxx",
PdID: "xxx",
Month: 1,
SubType: 1,
SuitType: 1,
OPrice: 1,
StartBuild: 0,
EndBuild: 103,
}
err := s.UpVipPriceConfig(context.TODO(), aavpc)
So(err, ShouldBeNil)
})
}
func TestServiceDelVipPriceConfig(t *testing.T) {
advp := &model.ArgVipPriceID{ID: 1}
Convey("Test_DelVipPriceConfig", t, func() {
err := s.DelVipPriceConfig(context.TODO(), advp)
So(err, ShouldBeNil)
})
}
func TestServiceVipDPriceConfigs(t *testing.T) {
Convey("Test_VipDPriceConfigs", t, func() {
av := &model.ArgVipPriceID{
ID: 155,
}
res, err := s.VipDPriceConfigs(context.TODO(), av)
fmt.Println("res", res)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func TestServiceVipDPriceConfigID(t *testing.T) {
Convey("Test_VipDPriceConfigID", t, func() {
res, err := s.VipDPriceConfigID(context.TODO(), &model.ArgVipDPriceID{DisID: 10})
fmt.Println("res", res.FirstPrice)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func TestServiceAddVipDPriceConfig(t *testing.T) {
Convey("Test_AddVipDPriceConfig", t, func() {
aavpc := &model.ArgAddOrUpVipDPrice{
DisID: 1,
ID: 155,
PdID: "tv.danmaku.bilianimexAuto3VIP",
DPrice: 15,
STime: xtime.Time(time.Now().Unix()) + 100000000000,
ETime: xtime.Time(time.Now().Unix()) + 200000000000,
Remark: "test2",
Operator: "admin",
OpID: 11,
FirstPrice: 13,
}
err := s.AddVipDPriceConfig(context.TODO(), aavpc)
So(err, ShouldBeNil)
})
}
func TestServiceUpVipDPriceConfig(t *testing.T) {
Convey("Test_UpVipDPriceConfig", t, func() {
aavpc := &model.ArgAddOrUpVipDPrice{
DisID: 11,
ID: 155,
PdID: "tv.danmaku.bilianimexAuto3VIP",
DPrice: 1.1,
STime: xtime.Time(time.Now().Unix()) + 100000000000,
ETime: xtime.Time(time.Now().Unix()) + 200000000000,
Remark: "test2",
Operator: "admin",
OpID: 11,
FirstPrice: 11,
}
err := s.UpVipDPriceConfig(context.TODO(), aavpc)
So(err, ShouldBeNil)
})
}
func TestServiceDelVipDPriceConfig(t *testing.T) {
advp := &model.ArgVipDPriceID{DisID: 1}
Convey("Test_DelVipDPriceConfig", t, func() {
err := s.DelVipDPriceConfig(context.TODO(), advp)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,46 @@
package service
import (
"context"
"go-common/app/admin/main/vip/model"
"go-common/library/ecode"
"go-common/library/log"
)
// PlatformAll .
func (s *Service) PlatformAll(c context.Context, order string) (res []*model.ConfPlatform, err error) {
if res, err = s.dao.PlatformAll(c, order); err != nil {
return
}
return
}
// PlatformByID .
func (s *Service) PlatformByID(c context.Context, arg *model.ArgID) (dlg *model.ConfPlatform, err error) {
return s.dao.PlatformByID(c, arg.ID)
}
// PlatformSave .
func (s *Service) PlatformSave(c context.Context, arg *model.ConfPlatform) (eff int64, err error) {
return s.dao.PlatformSave(c, arg)
}
// PlatformDel .
func (s *Service) PlatformDel(c context.Context, arg *model.ArgID, operator string) (eff int64, err error) {
pcount, err := s.dao.CountVipPriceConfigByPlat(c, arg.ID)
if err != nil {
return
}
dcount, err := s.dao.CountDialogByPlatID(c, arg.ID)
if err != nil {
return
}
if pcount > 0 || dcount > 0 {
err = ecode.VipPlatformConfDelErr
return
}
eff, err = s.dao.PlatformDel(c, arg.ID, operator)
log.Warn("user(%s) delete dialog(%d) effect row(%d)", operator, arg.ID, eff)
return
}

View File

@@ -0,0 +1,266 @@
package service
import (
"context"
"go-common/app/admin/main/vip/model"
"go-common/library/ecode"
"go-common/library/log"
"github.com/jinzhu/gorm"
"github.com/pkg/errors"
"golang.org/x/sync/errgroup"
)
// Privileges Privilege list.
func (s *Service) Privileges(c context.Context, langType int8) (res []*model.PrivilegeResp, err error) {
var (
ps []*model.Privilege
prs []*model.PrivilegeResources
)
if ps, err = s.dao.PrivilegeList(c, langType); err != nil {
err = errors.WithStack(err)
return
}
if prs, err = s.dao.PrivilegeResourcesList(c); err != nil {
err = errors.WithStack(err)
return
}
prmap := make(map[int64]map[int8]*model.PrivilegeResources, len(prs))
for _, v := range prs {
if prmap[v.PID] == nil {
prmap[v.PID] = map[int8]*model.PrivilegeResources{}
}
prmap[v.PID][v.Type] = v
}
for i, v := range ps {
r := &model.PrivilegeResp{
ID: v.ID,
Name: v.Name,
Title: v.Title,
Explain: v.Explain,
Type: v.Type,
Operator: v.Operator,
State: v.State,
IconURL: v.IconURL,
IconGrayURL: v.IconGrayURL,
LangType: v.LangType,
Order: int64(i),
}
if prmap[v.ID] != nil && prmap[v.ID][model.WebResources] != nil {
r.WebLink = prmap[v.ID][model.WebResources].Link
r.WebImageURL = prmap[v.ID][model.WebResources].ImageURL
}
if prmap[v.ID] != nil && prmap[v.ID][model.AppResources] != nil {
r.AppLink = prmap[v.ID][model.AppResources].Link
r.AppImageURL = prmap[v.ID][model.AppResources].ImageURL
}
res = append(res, r)
}
return
}
// UpdatePrivilegeState update privilege state.
func (s *Service) UpdatePrivilegeState(c context.Context, p *model.Privilege) (err error) {
if _, err = s.dao.UpdateStatePrivilege(c, p); err != nil {
err = errors.WithStack(err)
}
return
}
// DeletePrivilege delete privilege .
func (s *Service) DeletePrivilege(c context.Context, id int64) (err error) {
if _, err = s.dao.DeletePrivilege(c, id); err != nil {
err = errors.WithStack(err)
}
return
}
// AddPrivilege add privilege.
func (s *Service) AddPrivilege(c context.Context, req *model.ArgAddPrivilege, img *model.ArgImage) (err error) {
var (
iconURL string
iconGrayURL string
order int64
webImageURL string
appImageURL string
id int64
tx *gorm.DB
)
if iconURL, iconGrayURL, webImageURL, appImageURL, err = s.uploadImage(c, img); err != nil {
err = errors.WithStack(err)
return
}
if iconURL == "" || iconGrayURL == "" {
err = ecode.VipFileUploadFaildErr
return
}
if order, err = s.dao.MaxOrder(c); err != nil {
err = errors.WithStack(err)
return
}
order++
tx = s.dao.BeginGormTran(c)
defer func() {
if err != nil {
if err1 := tx.Rollback(); err1 != nil {
err = errors.Wrapf(err, "tx.Rollback(%+v)", req)
}
return
}
if err = tx.Commit().Error; err != nil {
err = errors.Wrapf(err, "tx.Commit(%+v)", req)
}
}()
if id, err = s.dao.AddPrivilege(tx, &model.Privilege{
Name: req.Name,
Title: req.Title,
Explain: req.Explain,
Type: req.Type,
Operator: req.Operator,
State: model.NormalPrivilege,
IconURL: iconURL,
IconGrayURL: iconGrayURL,
Order: order,
LangType: req.LangType,
}); err != nil {
err = errors.WithStack(err)
return
}
if _, err = s.dao.AddPrivilegeResources(tx, &model.PrivilegeResources{
PID: id,
Link: req.AppLink,
ImageURL: appImageURL,
Type: model.AppResources,
}); err != nil {
err = errors.WithStack(err)
return
}
if _, err = s.dao.AddPrivilegeResources(tx, &model.PrivilegeResources{
PID: id,
Link: req.WebLink,
ImageURL: webImageURL,
Type: model.WebResources,
}); err != nil {
err = errors.WithStack(err)
return
}
return
}
// UpdatePrivilege update privilege.
func (s *Service) UpdatePrivilege(c context.Context, req *model.ArgUpdatePrivilege, img *model.ArgImage) (err error) {
var (
iconURL string
iconGrayURL string
webImageURL string
appImageURL string
tx *gorm.DB
)
if iconURL, iconGrayURL, webImageURL, appImageURL, err = s.uploadImage(c, img); err != nil {
err = errors.WithStack(err)
return
}
tx = s.dao.BeginGormTran(c)
defer func() {
if err != nil {
if err1 := tx.Rollback().Error; err1 != nil {
err = errors.Wrapf(err, "tx.Rollback(%+v)", req)
}
return
}
if err = tx.Commit().Error; err != nil {
err = errors.Wrapf(err, "tx.Commit(%+v)", req)
}
}()
if _, err = s.dao.UpdatePrivilege(tx, &model.Privilege{
ID: req.ID,
Name: req.Name,
Title: req.Title,
Explain: req.Explain,
Type: req.Type,
Operator: req.Operator,
State: model.NormalPrivilege,
IconURL: iconURL,
IconGrayURL: iconGrayURL,
}); err != nil {
err = errors.WithStack(err)
return
}
if _, err = s.dao.UpdatePrivilegeResources(tx, &model.PrivilegeResources{
PID: req.ID,
Link: req.AppLink,
ImageURL: appImageURL,
Type: model.AppResources,
}); err != nil {
err = errors.WithStack(err)
return
}
if _, err = s.dao.UpdatePrivilegeResources(tx, &model.PrivilegeResources{
PID: req.ID,
Link: req.WebLink,
ImageURL: webImageURL,
Type: model.WebResources,
}); err != nil {
err = errors.WithStack(err)
return
}
return
}
func (s *Service) uploadImage(c context.Context, req *model.ArgImage) (iconURL, iconGrayURL, webImageURL, appImageURL string, err error) {
var g errgroup.Group
if req.IconFileType == "" &&
req.IconGrayFileType == "" &&
req.WebImageFileType == "" &&
req.AppImageFileType == "" {
return
}
if req.IconFileType != "" {
g.Go(func() (err error) {
//update icon.
if iconURL, err = s.dao.Upload(c, "", req.IconFileType, req.IconBody, s.c.Bfs); err != nil {
log.Error("d.Upload iconURL(%+v) error(%v)", req, err)
}
return
})
}
if req.IconGrayFileType != "" {
g.Go(func() (err error) {
//update gray icon.
if iconGrayURL, err = s.dao.Upload(c, "", req.IconGrayFileType, req.IconGrayBody, s.c.Bfs); err != nil {
log.Error("d.Upload iconGrayURL(%+v) error(%v)", req, err)
}
return
})
}
if req.WebImageFileType != "" {
g.Go(func() (err error) {
if webImageURL, err = s.dao.Upload(c, "", req.WebImageFileType, req.WebImageBody, s.c.Bfs); err != nil {
log.Error("d.Upload webImageURL(%+v) error(%v)", req, err)
}
return
})
}
if req.AppImageFileType != "" {
g.Go(func() (err error) {
if appImageURL, err = s.dao.Upload(c, "", req.AppImageFileType, req.AppImageBody, s.c.Bfs); err != nil {
log.Error("d.Upload appImageURL(%+v) error(%v)", req, err)
}
return
})
}
if err = g.Wait(); err != nil {
log.Error("g.Wait error(%v)", err)
return
}
return
}
// UpdateOrder update order.
func (s *Service) UpdateOrder(c context.Context, a *model.ArgOrder) (err error) {
if _, err = s.dao.UpdateOrder(c, a.AID, a.BID); err != nil {
err = errors.WithStack(err)
}
return
}

View File

@@ -0,0 +1,132 @@
package service
import (
"bytes"
"context"
"image/png"
"os"
"testing"
"go-common/app/admin/main/vip/model"
. "github.com/smartystreets/goconvey/convey"
)
// go test -test.v -test.run TestServicePrivileges
func TestServicePrivileges(t *testing.T) {
Convey("TestServicePrivileges", t, func() {
res, err := s.Privileges(context.TODO(), 0)
for _, v := range res {
t.Logf("%+v", v)
}
So(err, ShouldBeNil)
})
}
// go test -test.v -test.run TestUpdatePrivilegeState
func TestUpdatePrivilegeState(t *testing.T) {
Convey("TestUpdatePrivilegeState", t, func() {
err := s.UpdatePrivilegeState(context.TODO(), &model.Privilege{
ID: 4,
State: 1,
})
So(err, ShouldBeNil)
})
}
// go test -test.v -test.run TestDeletePrivilege
func TestDeletePrivilege(t *testing.T) {
Convey("TestDeletePrivilege", t, func() {
err := s.DeletePrivilege(context.TODO(), 4)
So(err, ShouldBeNil)
})
}
// go test -test.v -test.run TestUpdateOrder
func TestUpdateOrder(t *testing.T) {
Convey("TestUpdateOrder", t, func() {
err := s.UpdateOrder(context.TODO(), &model.ArgOrder{
AID: 5,
BID: 4,
})
So(err, ShouldBeNil)
})
}
// go test -test.v -test.run TestServiceUpload
func TestServiceUpload(t *testing.T) {
Convey("TestServiceUpload", t, func() {
file, _ := os.Open("/Users/baihai/Documents/test.png")
So(file, ShouldNotBeNil)
buf := new(bytes.Buffer)
img, _ := png.Decode(file)
png.Encode(buf, img)
bys := buf.Bytes()
t.Logf("conf %+v", s.c.Bfs)
iconURL, iconGrayURL, webImageURL, appImageURL, err := s.uploadImage(context.TODO(), &model.ArgImage{
IconBody: bys,
IconFileType: "image/png",
IconGrayBody: bys,
IconGrayFileType: "image/png",
})
t.Logf("url iconURL:%s iconGrayURL:%s webImageURL:%s appImageURL:%s", iconURL, iconGrayURL, webImageURL, appImageURL)
So(err, ShouldBeNil)
})
}
// go test -test.v -test.run TestServiceAddPrivilege
func TestServiceAddPrivilege(t *testing.T) {
Convey("TestServiceAddPrivilege", t, func() {
file, _ := os.Open("/Users/baihai/Documents/test.png")
So(file, ShouldNotBeNil)
buf := new(bytes.Buffer)
img, _ := png.Decode(file)
png.Encode(buf, img)
bys := buf.Bytes()
t.Logf("conf %+v", s.c.Bfs)
err := s.AddPrivilege(context.TODO(), &model.ArgAddPrivilege{
Name: "超级",
Title: "超级标题",
Explain: "超级内容",
Type: 0,
Operator: "admin",
WebLink: "http://www.baidu.com",
AppLink: "http://www.baidu.com",
}, &model.ArgImage{
IconBody: bys,
IconFileType: "image/png",
IconGrayBody: bys,
IconGrayFileType: "image/png",
})
So(err, ShouldBeNil)
})
}
// go test -test.v -test.run TestServiceUpdatePrivilege
func TestServiceUpdatePrivilege(t *testing.T) {
Convey("TestServiceUpdatePrivilege", t, func() {
file, _ := os.Open("/Users/baihai/Documents/test.png")
So(file, ShouldNotBeNil)
buf := new(bytes.Buffer)
img, _ := png.Decode(file)
png.Encode(buf, img)
bys := buf.Bytes()
t.Logf("conf %+v", s.c.Bfs)
err := s.UpdatePrivilege(context.TODO(), &model.ArgUpdatePrivilege{
ID: 3,
Name: "超级",
Title: "超级标题",
Explain: "超级内容",
Type: 0,
Operator: "admin",
WebLink: "http://www.baidu.com",
AppLink: "http://www.baidu.com",
}, &model.ArgImage{
IconBody: bys,
IconFileType: "image/png",
IconGrayBody: bys,
IconGrayFileType: "image/png",
})
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,264 @@
package service
import (
"context"
"encoding/json"
"fmt"
"time"
"go-common/app/admin/main/vip/model"
"go-common/library/ecode"
"go-common/library/log"
xtime "go-common/library/time"
"github.com/pkg/errors"
)
// const .
const (
_linkTypeH5 = 7
_linkTypeApp = 10
)
// SavePushData save push data
func (s *Service) SavePushData(c context.Context, arg *model.VipPushData) (err error) {
if err = s.checkPushData(arg); err != nil {
err = errors.WithStack(err)
return
}
if arg.ID == 0 {
arg.ProgressStatus = model.NotStart
arg.Status = model.Normal
if _, err = s.dao.AddPushData(c, arg); err != nil {
err = errors.WithStack(err)
}
return
}
var pushData *model.VipPushData
if pushData, err = s.dao.GetPushData(c, arg.ID); err != nil {
err = errors.WithStack(err)
return
}
if pushData == nil {
err = ecode.VipPushDataNotExitErr
return
}
if pushData.Status == model.Fail {
err = ecode.VipPushDataUpdateErr
return
}
if pushData.ProgressStatus == model.Started {
err = ecode.VipPushDataUpdateErr
return
}
if pushData.GroupName != arg.GroupName || !pushData.EffectStartDate.Time().Equal(arg.EffectStartDate.Time()) {
if !(pushData.Status == model.Normal && pushData.ProgressStatus == model.NotStart) {
err = ecode.VipPushDataUpdateErr
return
}
}
arg.ProgressStatus = pushData.ProgressStatus
if pushData.PushedCount == arg.PushTotalCount {
arg.ProgressStatus = model.Started
}
if _, err = s.dao.UpdatePushData(c, arg); err != nil {
err = errors.WithStack(err)
}
return
}
func (s *Service) checkPushData(arg *model.VipPushData) (err error) {
if len(arg.GroupName) > 10 {
err = ecode.VipPushGroupLenErr
return
}
if len(arg.Title) > 30 {
err = ecode.VipPushTitleLenErr
return
}
if len(arg.Content) > 200 {
err = ecode.VipPushContentLenErr
return
}
if arg.LinkType != _linkTypeH5 && arg.LinkType != _linkTypeApp {
err = ecode.VipPushLinkTypeErr
return
}
if arg.EffectEndDate.Time().Before(arg.EffectStartDate.Time()) {
err = ecode.VipPushEffectTimeErr
return
}
duration := arg.EffectEndDate.Time().Sub(arg.EffectStartDate.Time())
day := duration.Hours() / 24
arg.PushTotalCount = int32(day) + 1
if _, err = time.Parse("15:04:05", arg.PushStartTime); err != nil {
err = ecode.VipPushFmtTimeErr
return
}
if _, err = time.Parse("15:04:05", arg.PushEndTime); err != nil {
err = ecode.VipPushFmtTimeErr
return
}
platformMap := make(map[string]*model.PushDataPlatform)
platformArr := make([]*model.PushDataPlatform, 0)
var (
data []byte
key string
condition string
ok bool
)
if err = json.Unmarshal([]byte(arg.Platform), &platformArr); err != nil {
log.Error("error(%+v)", err)
err = ecode.VipPushPlatformErr
return
}
for _, v := range platformArr {
if key, ok = model.PushPlatformNameMap[v.Name]; !ok {
err = ecode.VipPushPlatformErr
return
}
if condition, ok = model.ConditionNameMap[v.Condition]; !ok {
err = ecode.VipPushPlatformErr
return
}
v.Condition = condition
platformMap[key] = v
}
if data, err = json.Marshal(platformMap); err != nil {
err = errors.WithStack(err)
return
}
arg.Platform = string(data)
return
}
// GetPushData get push data
func (s *Service) GetPushData(c context.Context, id int64) (res *model.VipPushData, err error) {
if res, err = s.dao.GetPushData(c, id); err != nil {
err = errors.WithStack(err)
return
}
if res == nil {
return
}
res.PushProgress = fmt.Sprintf("%v/%v", res.PushedCount, res.PushTotalCount)
if err = s.fmtPushDataPlatform(res); err != nil {
err = errors.WithStack(err)
}
return
}
// DisablePushData .
func (s *Service) DisablePushData(c context.Context, id int64) (err error) {
var (
res *model.VipPushData
now = time.Now()
)
if res, err = s.dao.GetPushData(c, id); err != nil {
err = errors.WithStack(err)
return
}
if res == nil {
err = ecode.VipPushDataNotExitErr
return
}
if !(res.ProgressStatus == model.Starting && res.Status == model.Normal && res.DisableType == model.UnDisable) {
err = ecode.VipPushDataDisableErr
return
}
duration := now.Sub(res.EffectStartDate.Time())
day := duration.Hours() / 24
res.PushTotalCount = int32(day) + 1
res.EffectEndDate = xtime.Time(now.Unix())
if res.PushTotalCount > res.PushedCount {
res.PushTotalCount--
}
if res.PushTotalCount == res.PushedCount {
res.ProgressStatus = model.Started
}
if err = s.dao.DisablePushData(c, res); err != nil {
err = errors.WithStack(err)
}
return
}
// DelPushData .
func (s *Service) DelPushData(c context.Context, id int64) (err error) {
var res *model.VipPushData
if res, err = s.dao.GetPushData(c, id); err != nil {
err = errors.WithStack(err)
return
}
if res == nil {
err = ecode.VipPushDataNotExitErr
return
}
if !(res.ProgressStatus == model.NotStart && res.Status == model.Normal) {
err = ecode.VipPushDataDelErr
return
}
if err = s.dao.DelPushData(c, id); err != nil {
err = errors.WithStack(err)
}
return
}
// PushDatas get push datas
func (s *Service) PushDatas(c context.Context, arg *model.ArgPushData) (res []*model.VipPushData, count int64, err error) {
if count, err = s.dao.PushDataCount(c, arg); err != nil {
err = errors.WithStack(err)
return
}
if res, err = s.dao.PushDatas(c, arg); err != nil {
err = errors.WithStack(err)
return
}
for _, v := range res {
v.PushProgress = fmt.Sprintf("%v/%v", v.PushedCount, v.PushTotalCount)
}
return
}
func (s *Service) fmtPushDataPlatform(res *model.VipPushData) (err error) {
var platformArr []*model.PushDataPlatform
platform := make(map[string]*model.PushDataPlatform)
if err = json.Unmarshal([]byte(res.Platform), &platform); err != nil {
err = errors.WithStack(err)
return
}
for k, v := range platform {
r := new(model.PushDataPlatform)
r.Name = model.PushPlatformMap[k]
r.Build = v.Build
r.Condition = model.ConditionMap[v.Condition]
platformArr = append(platformArr, r)
}
res.PlatformArr = platformArr
return
}

View File

@@ -0,0 +1,57 @@
package service
import (
"context"
"encoding/json"
"testing"
"time"
xtime "go-common/library/time"
"go-common/app/admin/main/vip/model"
. "github.com/smartystreets/goconvey/convey"
)
func TestService_GetPushData(t *testing.T) {
Convey("getpushData should be nil", t, func() {
id := 1
res, err := s.GetPushData(context.TODO(), int64(id))
bytes, _ := json.Marshal(res)
t.Logf("%+v", string(bytes))
So(err, ShouldBeNil)
})
}
func TestService_SavePushData(t *testing.T) {
Convey("save push data should be nil", t, func() {
arg := new(model.VipPushData)
arg.ID = 1
arg.GroupName = "test01"
arg.Title = "title"
arg.Content = "content"
arg.Platform = "[{\"name\":\"Android\",\"condition\":\"=\",\"build\":1},{\"name\":\"iPhone\",\"condition\":\"<=\",\"build\":2},{\"name\":\"iPad\",\"condition\":\"=\",\"build\":3}]"
arg.LinkType = 10
arg.ExpiredDayStart = -1
arg.ExpiredDayEnd = 10
arg.EffectStartDate = xtime.Time(time.Now().Unix())
arg.EffectEndDate = xtime.Time(time.Now().AddDate(0, 0, 7).Unix())
arg.PushStartTime = "18:00:00"
arg.PushEndTime = "20:00:00"
err := s.SavePushData(context.TODO(), arg)
So(err, ShouldBeNil)
})
}
func TestService_PushDatas(t *testing.T) {
Convey("push data should be nil", t, func() {
arg := new(model.ArgPushData)
arg.Status = 0
arg.ProgressStatus = 0
res, count, err := s.PushDatas(context.TODO(), arg)
bytes, _ := json.Marshal(res)
t.Logf("res(%+v) count(%v) ", string(bytes), count)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,680 @@
package service
import (
"context"
"crypto/md5"
"encoding/hex"
"fmt"
"math"
"math/rand"
"time"
"go-common/app/admin/main/vip/model"
"go-common/library/database/sql"
"go-common/library/ecode"
"go-common/library/log"
xtime "go-common/library/time"
"github.com/pkg/errors"
)
// QueryPool query pool
func (s *Service) QueryPool(c context.Context, r *model.ResoucePoolBo) (res []*model.VipResourcePool, count int, err error) {
var (
batch *model.VipResourceBatch
PN int
PS int
)
PN = r.PN
PS = r.PS
if batch, err = s.dao.SelBatchRow(c, r.BatchID); err != nil {
return
}
if r.BatchID != 0 {
r.ID = -1
}
if batch != nil {
r.ID = batch.PoolID
}
if count, err = s.dao.SelCountPool(c, r); err != nil || count == 0 {
return
}
if res, err = s.dao.SelPool(c, r, PN, PS); err != nil {
return
}
return
}
// PoolInfo pool info
func (s *Service) PoolInfo(c context.Context, id int) (res *model.VipResourcePool, err error) {
if res, err = s.dao.SelPoolRow(c, id); err != nil {
return
}
return
}
// AddPool .
func (s *Service) AddPool(c context.Context, r *model.ResoucePoolBo) (err error) {
var (
p *model.VipResourcePool
)
if err = s.verificationPool(r); err != nil {
return
}
if p, err = s.dao.SelPoolByName(c, r.PoolName); err != nil {
return
}
if p != nil {
err = ecode.VipPoolNameExitErr
return
}
if _, err = s.dao.AddPool(c, r); err != nil {
return
}
return
}
func (s *Service) verificationPool(r *model.ResoucePoolBo) (err error) {
var (
business *model.VipBusinessInfo
)
if len(r.PoolName) == 0 {
err = ecode.VipPoolNameErr
return
}
if len(r.Reason) == 0 {
err = ecode.VipPoolReasonErr
return
}
if r.StartTime <= 0 {
err = ecode.VipPoolStartTimeErr
return
}
if r.EndTime <= 0 {
err = ecode.VipPoolEndTimeErr
return
}
if r.EndTime < r.StartTime {
err = ecode.VipPoolValidityTimeErr
return
}
if business, err = s.dao.SelBusiness(context.TODO(), r.BusinessID); err != nil {
return
}
if business == nil {
err = ecode.VipBusinessNotExitErr
return
}
return
}
// UpdatePool .
func (s *Service) UpdatePool(c context.Context, r *model.ResoucePoolBo) (err error) {
var (
pool *model.VipResourcePool
p *model.VipResourcePool
batchs []*model.VipResourceBatch
)
if err = s.verificationPool(r); err != nil {
return
}
if pool, err = s.dao.SelPoolRow(c, r.ID); err != nil {
return
}
if pool == nil {
err = ecode.VipPoolIDErr
return
}
if p, err = s.dao.SelPoolByName(c, r.PoolName); err != nil {
return
}
if p != nil && pool.PoolName != p.PoolName {
err = ecode.VipPoolNameExitErr
return
}
if batchs, err = s.dao.SelBatchRows(context.TODO(), r.ID); err != nil {
return
}
for _, v := range batchs {
if !(r.StartTime <= v.StartTime && r.EndTime >= v.EndTime) {
err = ecode.VipPoolValidityTimeErr
return
}
}
if _, err = s.dao.UpdatePool(c, r); err != nil {
return
}
return
}
// BatchInfo .
func (s *Service) BatchInfo(c context.Context, id int) (res *model.VipResourceBatch, err error) {
if res, err = s.dao.SelBatchRow(c, id); err != nil {
return
}
return
}
// BatchInfoOfPool .
func (s *Service) BatchInfoOfPool(c context.Context, poolID int) (res []*model.VipResourceBatch, err error) {
if res, err = s.dao.SelBatchRows(c, poolID); err != nil {
return
}
return
}
// AddBatch .
func (s *Service) AddBatch(c context.Context, r *model.ResouceBatchBo) (err error) {
if err = s.verificationBatch(r); err != nil {
return
}
r.SurplusCount = r.Count
if _, err = s.dao.AddBatch(c, r); err != nil {
return
}
return
}
// UpdateBatch .
func (s *Service) UpdateBatch(c context.Context, id, increment int, startTime, endTime xtime.Time) (err error) {
var (
batch *model.VipResourceBatch
r = new(model.ResouceBatchBo)
)
r.ID = id
r.StartTime = startTime
r.EndTime = endTime
if batch, err = s.dao.SelBatchRow(c, id); err != nil {
return
}
if batch == nil {
err = ecode.VipBatchIDErr
return
}
r.PoolID = batch.PoolID
if err = s.verifBatchTime(r); err != nil {
return
}
if increment < 0 {
err = ecode.VipBatchPlusResouceErr
return
}
if batch.Count+increment > math.MaxInt32 || batch.Count+increment < 0 {
err = ecode.VipBatchCountErr
return
}
batch.Count += increment
batch.SurplusCount += increment
batch.StartTime = r.StartTime
batch.EndTime = r.EndTime
ver := batch.Ver
batch.Ver++
if _, err = s.dao.UpdateBatch(c, batch, ver); err != nil {
return
}
return
}
func (s *Service) verifBatchTime(r *model.ResouceBatchBo) (err error) {
var (
pool *model.VipResourcePool
)
if pool, err = s.dao.SelPoolRow(context.TODO(), r.PoolID); err != nil {
return
}
if pool == nil {
err = ecode.VipPoolIDErr
return
}
if pool.StartTime > r.StartTime || pool.EndTime < r.EndTime {
err = ecode.VipPoolValidityTimeErr
return
}
return
}
func (s *Service) verificationBatch(r *model.ResouceBatchBo) (err error) {
if r.Unit <= 0 || r.Unit > 3660 {
err = ecode.VipBatchUnitErr
return
}
if r.Count <= 0 {
err = ecode.VipBatchCountErr
return
}
if err = s.verifBatchTime(r); err != nil {
return
}
return
}
// GrandResouce grand resouce mid
func (s *Service) GrandResouce(c context.Context, remark string, batchID int64, mids []int, username string) (failMid []int, err error) {
var (
batch *model.VipResourceBatch
)
if len(remark) == 0 {
err = ecode.VipRemarkErr
return
}
if batch, err = s.dao.SelBatchRow(c, int(batchID)); err != nil {
return
}
if batch == nil {
err = ecode.VipBatchIDErr
return
}
if err = s.checkBatchValid(batch); err != nil {
return
}
for _, v := range mids {
if err = s.grandMidOfResouce(c, v, int(batchID), username, remark); err != nil {
log.Error("GrandResouce grandMidOfResouce(mid:%v,batchID:%v,username:%v,remark:%v error(%v))", v, batchID, username, remark, err)
failMid = append(failMid, v)
}
}
return
}
func (s *Service) grandMidOfResouce(c context.Context, mid, batchID int, username, remark string) (err error) {
//var (
// batch *model.VipResourceBatch
// tx *sql.Tx
// a int64
// hv *inModel.HandlerVip
//)
//if batch, err = s.dao.SelBatchRow(c, batchID); err != nil {
// return
//}
//if batch.SurplusCount-1 < 0 {
// err = ecode.VipBatchNotEnoughErr
// return
//}
//batch.DirectUseCount++
//batch.SurplusCount--
//ver := batch.Ver
//batch.Ver++
//if tx, err = s.dao.BeginTran(context.TODO()); err != nil {
// return
//}
//defer func() {
// if err != nil {
// if err = tx.Commit(); err != nil {
// tx.Rollback()
// }
// } else {
// tx.Rollback()
// }
//}()
//if a, err = s.dao.UseBatch(tx, batch, ver); err != nil {
// return
//}
//if a > 0 {
// if hv, err = s.exchangeVip(context.TODO(), tx, int(mid), batch.ID, batch.Unit, remark, username); err != nil {
// return
// }
// s.asyncBcoin(func() {
// s.vipRPC.BcoinProcesserHandler(context.TODO(), hv)
// })
//}
return
}
func (s *Service) checkBatchValid(batch *model.VipResourceBatch) (err error) {
var (
pool *model.VipResourcePool
business *model.VipBusinessInfo
ct = time.Now()
)
if !(batch.StartTime.Time().Unix() <= ct.Unix() && ct.Unix() <= batch.EndTime.Time().Unix()) {
err = ecode.VipBatchTTLErr
return
}
if pool, err = s.dao.SelPoolRow(context.TODO(), batch.PoolID); err != nil {
return
}
if pool == nil {
err = ecode.VipPoolIDErr
return
}
if !(pool.StartTime.Time().Unix() <= ct.Unix() && ct.Unix() <= pool.EndTime.Time().Unix()) {
err = ecode.VipPoolValidityTimeErr
return
}
if business, err = s.dao.SelBusiness(context.TODO(), pool.BusinessID); err != nil {
return
}
if business == nil {
err = ecode.VipBusinessNotExitErr
return
}
if business.Status == 1 {
err = ecode.VipBusinessStatusErr
return
}
return
}
// SaveBatchCode .
func (s *Service) SaveBatchCode(c context.Context, arg *model.BatchCode) (err error) {
var batchID int64
if arg.ID == 0 {
if err = s.checkBatchCodeValid(c, arg); err != nil {
return
}
arg.SurplusCount = arg.Count
var tx *sql.Tx
if tx, err = s.dao.BeginTran(c); err != nil {
err = errors.WithStack(err)
return
}
defer func() {
if err == nil {
if err = tx.Commit(); err != nil {
log.Error("commimt error(%+v)", err)
}
} else {
tx.Rollback()
}
}()
arg.Status = 1
if batchID, err = s.dao.TxAddBatchCode(tx, arg); err != nil {
err = errors.WithStack(err)
return
}
if err = s.createCode(tx, batchID, int(arg.Count)); err != nil {
err = errors.WithStack(err)
return
}
} else {
var (
bc *model.BatchCode
bc1 *model.BatchCode
)
if bc, err = s.dao.SelBatchCodeID(c, arg.ID); err != nil {
err = errors.WithStack(err)
return
}
if bc == nil {
err = ecode.VipBatchIDErr
return
}
if bc.BatchName != arg.BatchName {
if bc1, err = s.dao.SelBatchCodeName(c, arg.BatchName); err != nil {
err = errors.WithStack(err)
return
}
if bc1 != nil {
err = ecode.VipBatchCodeNameErr
return
}
}
bc.BatchName = arg.BatchName
bc.Reason = arg.Reason
bc.Price = arg.Price
bc.Contacts = arg.Contacts
bc.ContactsNumber = arg.ContactsNumber
bc.Type = arg.Type
bc.MaxCount = arg.MaxCount
bc.LimitDay = arg.LimitDay
if _, err = s.dao.UpdateBatchCode(c, bc); err != nil {
err = errors.WithStack(err)
return
}
}
return
}
func (s *Service) checkBatchCodeValid(c context.Context, arg *model.BatchCode) (err error) {
var (
b *model.VipBusinessInfo
p *model.VipResourcePool
bc *model.BatchCode
)
if b, err = s.BusinessInfo(c, int(arg.BusinessID)); err != nil {
err = errors.WithStack(err)
return
}
if b == nil {
err = ecode.VipBusinessNotExitErr
return
}
if p, err = s.PoolInfo(c, int(arg.PoolID)); err != nil {
err = errors.WithStack(err)
return
}
if p == nil {
err = ecode.VipPoolIDErr
return
}
if p.EndTime.Time().Before(arg.EndTime.Time()) || p.StartTime.Time().After(arg.StartTime.Time()) {
err = ecode.VipPoolValidityTimeErr
return
}
if bc, err = s.dao.SelBatchCodeName(c, arg.BatchName); err != nil {
err = errors.WithStack(err)
return
}
if bc != nil {
err = ecode.VipBatchCodeNameErr
return
}
if arg.Unit <= 0 || arg.Unit > 3660 {
err = ecode.VipBatchUnitErr
return
}
if arg.Count <= 0 || arg.Count > 200000 {
err = ecode.VipBatchCodeCountErr
}
if arg.Price > 10000 || arg.Price < 0 {
err = ecode.VipBatchPriceErr
return
}
return
}
// FrozenCode .
func (s *Service) FrozenCode(c context.Context, codeID int64, status int8) (err error) {
var (
code *model.ResourceCode
)
if code, err = s.dao.SelCodeID(c, codeID); err != nil {
err = errors.WithStack(err)
return
}
if code == nil {
err = ecode.VipCodeIDErr
return
}
code.Status = status
if _, err = s.dao.UpdateCode(c, codeID, status); err != nil {
err = errors.WithStack(err)
return
}
return
}
// FrozenBatchCode .
func (s *Service) FrozenBatchCode(c context.Context, BatchCodeID int64, status int8) (err error) {
var bc *model.BatchCode
if bc, err = s.dao.SelBatchCodeID(c, BatchCodeID); err != nil {
err = errors.WithStack(err)
return
}
if bc == nil {
err = ecode.VipBatchIDErr
return
}
bc.Status = status
if _, err = s.dao.UpdateBatchCode(c, bc); err != nil {
err = errors.WithStack(err)
return
}
return
}
func (s *Service) createCode(tx *sql.Tx, batchCodeID int64, size int) (err error) {
var (
hash = md5.New()
batchSize = 2000
codes = make([]*model.ResourceCode, 0)
)
for i := 1; i <= size; i++ {
unix := time.Now().UnixNano()
key := fmt.Sprintf("%v,%v,%v,%v", unix, batchCodeID, i, rand.Intn(10000000))
hash.Write([]byte(key))
sum := hash.Sum(nil)
code := hex.EncodeToString(sum)
code = code[8:24]
r := new(model.ResourceCode)
r.Code = code
r.Status = model.NOTUSER
r.BatchCodeID = batchCodeID
codes = append(codes, r)
if i%batchSize == 0 || i == size {
if err = s.dao.BatchAddCode(tx, codes); err != nil {
log.Error("batch add code %+v", err)
return
}
codes = make([]*model.ResourceCode, 0)
}
}
return
}
// SelBatchCodes .
func (s *Service) SelBatchCodes(c context.Context, batchIDs []int64) (res []*model.BatchCode, err error) {
if res, err = s.dao.SelBatchCodes(c, batchIDs); err != nil {
err = errors.WithStack(err)
return
}
return
}
// SelCode .
func (s *Service) SelCode(c context.Context, arg *model.ArgCode, username string, curID int64, ps int) (res []*model.CodeVo, cursor int64, pre int64, err error) {
var (
codes []*model.ResourceCode
batchIDs []int64
batchMap = make(map[int64]*model.BatchCode)
batchCodes []*model.BatchCode
linkmap map[int64]int64
)
if linkmap, err = s.dao.GetSelCode(c, username); err != nil {
err = errors.WithStack(err)
return
}
fmt.Printf("cur link map(%+v) \n", linkmap)
if len(linkmap) == 0 {
linkmap = make(map[int64]int64)
}
if codes, err = s.dao.SelCode(c, arg, curID, ps); err != nil {
err = errors.WithStack(err)
return
}
if len(codes) > 0 {
cursor = codes[len(codes)-1].ID
} else {
return
}
linkmap[cursor] = curID
pre = linkmap[curID]
if err = s.dao.SetSelCode(c, username, linkmap); err != nil {
err = errors.WithStack(err)
return
}
for _, v := range codes {
batchIDs = append(batchIDs, v.BatchCodeID)
}
if batchCodes, err = s.dao.SelBatchCodes(c, batchIDs); err != nil {
err = errors.WithStack(err)
return
}
for _, v := range batchCodes {
batchMap[v.ID] = v
}
for _, v := range codes {
r := new(model.CodeVo)
r.ID = v.ID
r.BatchCodeID = v.BatchCodeID
r.Mid = v.Mid
r.Ctime = v.Ctime
r.Code = v.Code
r.Status = v.Status
r.UseTime = v.UseTime
batchCode := batchMap[v.BatchCodeID]
if batchCode == nil {
err = ecode.VipBatchIDErr
res = nil
return
}
r.Unit = batchCode.Unit
r.BatchName = batchCode.BatchName
r.BatchStatus = batchCode.Status
r.StartTime = batchCode.StartTime
r.EndTime = batchCode.EndTime
res = append(res, r)
}
return
}
// ExportCode .
func (s *Service) ExportCode(c context.Context, batchID int64) (codes []string, err error) {
var (
rc []*model.ResourceCode
curID int64
ps = 2000
)
arg := new(model.ArgCode)
arg.BatchCodeID = batchID
arg.Status = model.NOTUSER
for {
if rc, err = s.dao.SelCode(c, arg, curID, ps); err != nil {
err = errors.WithStack(err)
return
}
if len(rc) == 0 {
return
}
for _, v := range rc {
codes = append(codes, v.Code)
}
curID = rc[len(rc)-1].ID
}
}
// SelBatchCode .
func (s *Service) SelBatchCode(c context.Context, arg *model.ArgBatchCode, pn, ps int) (res []*model.BatchCode, total int64, err error) {
if total, err = s.dao.SelBatchCodeCount(c, arg); err != nil {
err = errors.WithStack(err)
return
}
if res, err = s.dao.SelBatchCode(c, arg, pn, ps); err != nil {
err = errors.WithStack(err)
return
}
return
}

View File

@@ -0,0 +1,109 @@
package service
import (
"context"
"testing"
"time"
"go-common/app/admin/main/vip/model"
xtime "go-common/library/time"
. "github.com/smartystreets/goconvey/convey"
)
func Test_GrandResouce(t *testing.T) {
Convey("should return true err == nil and failMids is empty", t, func() {
var (
mids []int
remark = "系统备注"
batchID = 5
username = "system"
)
mids = append(mids, 110)
failMids, err := s.GrandResouce(context.TODO(), remark, int64(batchID), mids, username)
So(err, ShouldBeNil)
So(failMids, ShouldBeEmpty)
})
}
func TestService_BatchInfo(t *testing.T) {
Convey("batch info", t, func() {
id := 12
_, err := s.BatchInfo(context.TODO(), id)
So(err, ShouldBeNil)
})
}
func TestService_PoolInfo(t *testing.T) {
Convey("pool info", t, func() {
id := 12
_, err := s.PoolInfo(context.TODO(), id)
So(err, ShouldBeNil)
})
}
func Test_UpdateResouce(t *testing.T) {
Convey("should ", t, func() {
pojo := new(model.ResoucePoolBo)
pojo.ID = 25
pojo.PoolName = "test123123112311"
pojo.BusinessID = 3
pojo.Reason = "zhaozhihao"
pojo.CodeExpireTime = xtime.Time(time.Now().Unix())
pojo.StartTime = xtime.Time(time.Now().AddDate(0, 0, -1).Unix())
pojo.EndTime = xtime.Time(time.Now().AddDate(0, 0, 10).Unix())
pojo.Contacts = "阿斯顿发"
pojo.ContactsNumber = "123124123"
err := s.UpdatePool(context.TODO(), pojo)
So(err, ShouldBeNil)
})
}
func Test_SaveBatchCode(t *testing.T) {
Convey("testing ", t, func() {
arg := new(model.BatchCode)
arg.ID = 26
arg.PoolID = 25
arg.Type = 1
arg.BusinessID = 3
arg.BatchName = "测试123"
arg.SurplusCount = 100000
arg.Count = 20000
arg.Unit = 366
arg.LimitDay = 9
arg.MaxCount = 5
arg.StartTime = xtime.Time(time.Now().Unix())
arg.EndTime = xtime.Time(time.Now().AddDate(0, 0, 1).Unix())
arg.Price = 10
arg.Reason = "zhaozhihao"
err := s.SaveBatchCode(context.TODO(), arg)
So(err, ShouldBeNil)
})
}
func Test_vipInfo(t *testing.T) {
Convey("testing", t, func() {
mid := 123
res, err := s.VipInfo(context.TODO(), int64(mid))
t.Logf("%+v", res)
So(err, ShouldBeNil)
})
}
func Test_drawback(t *testing.T) {
Convey("drawback", t, func() {
mid := 2089809
username := "zhaozhihao"
remark := "zhaozhihao"
day := 10
err := s.Drawback(context.TODO(), day, int64(mid), username, remark)
So(err, ShouldBeNil)
})
}
func TestService_ExportCode(t *testing.T) {
Convey(" export code", t, func() {
codes, err := s.ExportCode(context.TODO(), 13)
So(codes, ShouldNotBeEmpty)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,57 @@
package service
import (
"context"
"go-common/app/admin/main/vip/conf"
"go-common/app/admin/main/vip/dao"
)
var (
_maxTipLen = 28
_maxTitleLen = 36
_maxContentLen = 36
)
// Service struct
type Service struct {
c *conf.Config
dao *dao.Dao
sendBcoin chan func()
}
// New init
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
dao: dao.New(c),
sendBcoin: make(chan func(), 10240),
}
go s.bcoinproc()
return s
}
// Ping check db live
func (s *Service) Ping(c context.Context) (err error) {
return s.dao.Ping(c)
}
// func (s *Service) asyncBcoin(f func()) {
// select {
// case s.sendBcoin <- f:
// default:
// log.Warn("bcoinproc chan full")
// }
// }
func (s *Service) bcoinproc() {
for {
f := <-s.sendBcoin
f()
}
}
// Close Service
func (s *Service) Close() {
s.dao.Close()
}

View File

@@ -0,0 +1,103 @@
package service
import (
"context"
"flag"
"testing"
"time"
"go-common/app/admin/main/vip/conf"
"go-common/app/admin/main/vip/model"
"go-common/library/log"
. "github.com/smartystreets/goconvey/convey"
)
var (
//once sync.Once
s *Service
c = context.TODO()
)
func init() {
flag.Set("conf", "../cmd/vip-admin-test.toml")
if err := conf.Init(); err != nil {
panic(err)
}
log.Init(conf.Conf.Log)
defer log.Close()
s = New(conf.Conf)
time.Sleep(time.Second)
}
func Test_ScanUserInfo(t *testing.T) {
Convey("should return true err == nil", t, func() {
})
}
func TestService_FrozenCode(t *testing.T) {
Convey("frozenCode", t, func() {
codeID := 12
status := 1
err := s.FrozenCode(context.TODO(), int64(codeID), int8(status))
So(err, ShouldBeNil)
})
}
func TestService_FrozenBatchCode(t *testing.T) {
Convey("frozen batch code", t, func() {
batchCodeID := 12
status := 2
err := s.FrozenBatchCode(context.TODO(), int64(batchCodeID), int8(status))
So(err, ShouldBeNil)
})
}
func TestService_BusinessInfo(t *testing.T) {
Convey("businessInfo", t, func() {
id := 12
_, err := s.BusinessInfo(context.TODO(), id)
So(err, ShouldBeNil)
})
}
func TestService_AllVersion(t *testing.T) {
Convey("version", t, func() {
_, err := s.AllVersion(context.TODO())
So(err, ShouldBeNil)
})
}
func TestService_SelCode(t *testing.T) {
Convey("sel code", t, func() {
arg := new(model.ArgCode)
arg.ID = 12
cursor := 1
ps := 20
res, _, _, err := s.SelCode(context.TODO(), arg, "zhaozhihao", int64(cursor), ps)
So(res, ShouldNotBeEmpty)
So(err, ShouldBeNil)
})
}
func TestService_VipInfo(t *testing.T) {
Convey("vip info", t, func() {
mid := 1233
_, err := s.VipInfo(context.TODO(), int64(mid))
So(err, ShouldBeNil)
})
}
func TestService_BatchInfoOfPool(t *testing.T) {
Convey("batchn info ", t, func() {
poolID := 12
_, err := s.BatchInfoOfPool(context.TODO(), poolID)
So(err, ShouldBeNil)
})
}
func TestService_BusinessList(t *testing.T) {
Convey("business list", t, func() {
res, _, err := s.BusinessList(context.TODO(), 1, 20, -1)
So(res, ShouldNotBeNil)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,131 @@
package service
import (
"context"
"time"
"unicode/utf8"
"go-common/app/admin/main/vip/model"
"go-common/library/ecode"
xtime "go-common/library/time"
"github.com/pkg/errors"
)
// TipList tip list.
func (s *Service) TipList(c context.Context, platform int8, state int8, position int8) (ts []*model.Tips, err error) {
var now = time.Now().Unix()
if ts, err = s.dao.TipList(c, platform, state, now, position); err != nil {
err = errors.WithStack(err)
}
for _, v := range ts {
v.TipState(v.StartTime, v.EndTime, now)
}
return
}
// TipByID tip by id.
func (s *Service) TipByID(c context.Context, id int64) (t *model.Tips, err error) {
if t, err = s.dao.TipByID(c, id); err != nil {
err = errors.WithStack(err)
}
if t == nil {
err = ecode.VipTipNotFoundErr
return
}
t.TipState(t.StartTime, t.EndTime, time.Now().Unix())
return
}
// AddTip add tip.
func (s *Service) AddTip(c context.Context, t *model.Tips) (err error) {
if t.StartTime >= t.EndTime {
err = ecode.RequestErr
return
}
if utf8.RuneCountInString(t.Tip) > _maxTipLen {
err = ecode.VipTipTooLoogErr
return
}
t.Ctime = xtime.Time(time.Now().Unix())
if _, err = s.dao.AddTip(c, t); err != nil {
err = errors.WithStack(err)
}
return
}
// TipUpdate update tip.
func (s *Service) TipUpdate(c context.Context, t *model.Tips) (err error) {
var (
old *model.Tips
now = time.Now().Unix()
)
if t.ID == 0 {
err = ecode.RequestErr
return
}
if old, err = s.TipByID(c, t.ID); err != nil {
err = errors.WithStack(err)
return
}
if t.StartTime >= t.EndTime {
err = ecode.VipTipTimeErr
return
}
if utf8.RuneCountInString(t.Tip) > _maxTipLen {
err = ecode.VipTipTooLoogErr
return
}
if old.StartTime != t.StartTime && old.StartTime < now {
err = ecode.VipTipStartTimeCatNotModifyErr
return
}
if old.EndTime != t.EndTime && old.EndTime < now {
err = ecode.VipTipEndTimeCatNotModifyErr
return
}
if _, err = s.dao.TipUpdate(c, t); err != nil {
err = errors.WithStack(err)
}
return
}
// DeleteTip delete tip.
func (s *Service) DeleteTip(c context.Context, id int64, operator string) (err error) {
var (
old *model.Tips
now = time.Now().Unix()
)
if old, err = s.TipByID(c, id); err != nil {
err = errors.WithStack(err)
return
}
if old.StartTime <= now {
err = ecode.VipTipCatNotDeleteErr
return
}
if _, err = s.dao.DeleteTip(c, id, model.Delete, operator); err != nil {
err = errors.WithStack(err)
}
return
}
// ExpireTip expire tip.
func (s *Service) ExpireTip(c context.Context, id int64, operator string) (err error) {
var (
old *model.Tips
now = time.Now().Unix()
)
if old, err = s.TipByID(c, id); err != nil {
err = errors.WithStack(err)
return
}
if old.StartTime > now || old.EndTime < now {
err = ecode.VipTipCatNotExpireErr
return
}
if _, err = s.dao.ExpireTip(c, id, operator, now); err != nil {
err = errors.WithStack(err)
}
return
}

View File

@@ -0,0 +1,101 @@
package service
import (
"testing"
"go-common/app/admin/main/vip/model"
. "github.com/smartystreets/goconvey/convey"
)
// go test -test.v -test.run TestServiceTipList
func TestServiceTipList(t *testing.T) {
Convey("TestServiceTipList", t, func() {
var (
platform = int8(0)
state = int8(0)
position = int8(2)
)
res, err := s.TipList(c, platform, state, position)
for _, v := range res {
t.Logf("%+v", v)
}
So(len(res) != 0, ShouldBeTrue)
So(err, ShouldBeNil)
})
}
// go test -test.v -test.run TestServiceTipByID
func TestServiceTipByID(t *testing.T) {
Convey("TestServiceTipByID", t, func() {
var (
id int64 = 1
)
res, err := s.TipByID(c, id)
t.Logf("%+v", res)
So(err, ShouldBeNil)
})
}
// go test -test.v -test.run TestServiceAddTip
func TestServiceAddTip(t *testing.T) {
Convey("TestServiceAddTip", t, func() {
t := &model.Tips{
Platform: 2,
Version: 4000,
Tip: "一样",
Link: "http://www.baidu.com",
StartTime: 1528315928,
EndTime: 1538315928,
Level: 2,
JudgeType: 1,
Operator: "baihai",
Position: 2,
}
err := s.AddTip(c, t)
So(err, ShouldBeNil)
})
}
// go test -test.v -test.run TestServiceUpdateTip
func TestServiceUpdateTip(t *testing.T) {
Convey("TestServiceUpdateTip", t, func() {
t := &model.Tips{
ID: 1,
Platform: 2,
Version: 4000,
Tip: "一样2",
Link: "http://www.baidu.com",
StartTime: 1528315928,
EndTime: 1538315928,
Level: 2,
JudgeType: 1,
Position: 1,
Operator: "baihai",
}
err := s.TipUpdate(c, t)
So(err, ShouldBeNil)
})
}
// go test -test.v -test.run TestServiceDeleteTip
func TestServiceDeleteTip(t *testing.T) {
Convey("TestServiceDeleteTip", t, func() {
var (
id int64 = 2
)
err := s.DeleteTip(c, id, "baihai")
So(err, ShouldBeNil)
})
}
// go test -test.v -test.run TestServiceExpireTip
func TestServiceExpireTip(t *testing.T) {
Convey("TestServiceExpireTip", t, func() {
var (
id int64 = 3
)
err := s.ExpireTip(c, id, "baihai")
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,26 @@
package service
import (
"context"
"go-common/app/admin/main/vip/model"
"go-common/library/log"
)
// AllVersion all version.
func (s *Service) AllVersion(c context.Context) (res []*model.VipAppVersion, err error) {
if res, err = s.dao.AllVersion(c); err != nil {
log.Error("%+v", err)
return
}
return
}
// UpdateVersion update version.
func (s *Service) UpdateVersion(c context.Context, v *model.VipAppVersion) (err error) {
if _, err = s.dao.UpdateVersion(c, v); err != nil {
log.Error("%+v", err)
return
}
return
}

View File

@@ -0,0 +1,127 @@
package service
import (
"context"
"time"
"go-common/app/admin/main/vip/model"
"go-common/library/database/sql"
"go-common/library/ecode"
"go-common/library/log"
xtime "go-common/library/time"
"github.com/pkg/errors"
)
// Drawback Drawback
func (s *Service) Drawback(c context.Context, days int, mid int64, usename, remark string) (err error) {
var (
userInfo *model.VipUserInfo
history *model.VipChangeHistory
ot time.Time
tx *sql.Tx
affected int64
)
if userInfo, err = s.dao.SelVipUserInfo(c, mid); err != nil {
return
}
if userInfo == nil {
err = ecode.VipUserInfoNotExit
return
}
ct := time.Now()
overdueTIme := userInfo.VipOverdueTime
ot = overdueTIme.Time().AddDate(0, 0, -days)
if ot.Before(ct) {
ot = ct
userInfo.VipStatus = model.VipStatusOverTime
}
userInfo.VipOverdueTime = xtime.Time(ot.Unix())
if userInfo.AnnualVipOverdueTime.Time().After(ot) && userInfo.VipType == model.AnnualVip {
userInfo.VipType = model.Vip
userInfo.AnnualVipOverdueTime = xtime.Time(ot.Unix())
}
history = new(model.VipChangeHistory)
history.Mid = mid
history.ChangeTime = xtime.Time(time.Now().Unix())
history.Days = -days
history.ChangeType = model.ChangeTypeSystemDrawback
history.OperatorID = usename
history.Remark = remark
if tx, err = s.dao.BeginTran(context.TODO()); err != nil {
return
}
defer func() {
if err == nil {
if err = tx.Commit(); err != nil {
tx.Rollback()
}
} else {
tx.Rollback()
}
}()
if affected, err = s.dao.UpdateVipUserInfo(tx, userInfo); err != nil {
return
}
if affected > 0 {
if _, err = s.dao.InsertVipChangeHistory(tx, history); err != nil {
return
}
if err = s.dao.DelBcoinSalary(tx, mid, userInfo.VipOverdueTime); err != nil {
return
}
}
return
}
// ExchangeVipByDays exchange vip days
//func (s *Service) exchangeVip(c context.Context, tx *sql.Tx, mid, batchID, unit int, remark, username string) (hv *inModel.HandlerVip, err error) {
// var r = new(inModel.VipChangeBo)
// if mid == 0 {
// err = ecode.VipMidErr
// return
// }
// if len(remark) == 0 || len(remark) > 200 {
// err = ecode.VipRemarkErr
// return
// }
// r.BatchID = int64(batchID)
// r.ChangeType = model.ChangeTypeSystem
// r.Remark = remark
// r.OperatorID = username
// r.Days = int32(unit)
// r.Mid = int64(mid)
// log.Info("%+v ", r)
// if hv, err = s.vipRPC.UpdateVipWithHistory(context.TODO(), r); err != nil {
// fmt.Printf("rpc %+v err(%+v) \n", hv, err)
// log.Error("rpc %+v err(%+v) ", hv, err)
// return
// }
// return
//}
// HistoryPage history page.
func (s *Service) HistoryPage(c context.Context, u *model.UserChangeHistoryReq) (res []*model.VipChangeHistory, count int, err error) {
if count, err = s.dao.HistoryCount(c, u); err != nil {
log.Error("%+v", err)
return
}
if count == 0 {
return
}
if res, err = s.dao.HistoryList(c, u); err != nil {
log.Error("%+v", err)
return
}
return
}
// VipInfo .
func (s *Service) VipInfo(c context.Context, mid int64) (res *model.VipUserInfo, err error) {
if res, err = s.dao.SelVipUserInfo(c, mid); err != nil {
err = errors.WithStack(err)
return
}
return
}

View File

@@ -0,0 +1,228 @@
package service
import (
"context"
"fmt"
"math/rand"
"net/url"
"strings"
"go-common/app/admin/main/vip/model"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/time"
)
const (
_delete = 1
_maxRows = 20000
)
// WelfareTypeSave save welfare type
func (s *Service) WelfareTypeSave(id int, name, username string) (err error) {
wt := new(model.WelfareType)
wt.ID = id
wt.Name = name
wt.OperName = username
if id == 0 {
if err = s.dao.WelfareTypeAdd(wt); err != nil {
log.Error("WelfareTypeAdd(%v) Error(%v)", wt, err)
}
} else {
if err = s.dao.WelfareTypeUpd(wt); err != nil {
log.Error("WelfareTypeUpd(%v) Error(%v)", wt, err)
}
}
return
}
// WelfareTypeState delete welfare type
func (s *Service) WelfareTypeState(c context.Context, id int, username string) (err error) {
tx := s.dao.BeginGormTran(c)
if err = s.dao.WelfareTypeState(tx, id, _delete, 0, username); err != nil {
log.Error("WelfareTypeState id(%v) Error(%v)", id, err)
tx.Rollback()
return
}
if err = s.dao.ResetWelfareTid(tx, id); err != nil {
log.Error("ResetWelfareTid tid(%v) Error(%v)", id, err)
tx.Rollback()
return
}
return tx.Commit().Error
}
// WelfareTypeList get welfare type list
func (s *Service) WelfareTypeList() (wts []*model.WelfareTypeRes, err error) {
if wts, err = s.dao.WelfareTypeList(); err != nil {
log.Error("WelfareTypeList Error(%v)", err)
}
return
}
// WelfareSave save welfare
func (s *Service) WelfareSave(username string, req *model.WelfareReq) (err error) {
var (
burl string
hurl string
)
wf := new(model.Welfare)
copyFiled(wf, req)
wf.OperName = username
if burl, err = getRelativePath(wf.BackdropUri); err != nil {
return
}
wf.BackdropUri = burl
if hurl, err = getRelativePath(wf.HomepageUri); err != nil {
return
}
wf.HomepageUri = hurl
if req.ID == 0 {
if err = s.dao.WelfareAdd(wf); err != nil {
log.Error("WelfareAdd(%v) Error(%v)", wf, err)
}
} else {
req.BackdropUri = burl
req.HomepageUri = hurl
if err = s.dao.WelfareUpd(req); err != nil {
log.Error("WelfareUpd(%v) Error(%v)", wf, err)
}
}
return
}
// WelfareState delete welfare
func (s *Service) WelfareState(id int, username string) (err error) {
if err = s.dao.WelfareState(id, _delete, 0, username); err != nil {
log.Error("WelfareState(%v) Error(%v)", id, err)
}
return
}
// WelfareList get welfare list
func (s *Service) WelfareList(tid int) (ws []*model.WelfareRes, err error) {
if ws, err = s.dao.WelfareList(tid); err != nil {
log.Error("WelfareList tid(%v) Error(%v)", tid, err)
return
}
randomBFSHost := fmt.Sprintf(s.c.Property.WelfareBgHost, rand.Intn(3))
for _, w := range ws {
wbs, err := s.dao.WelfareBatchList(w.ID)
if err != nil {
log.Error("WelfareBatchList wid(%v) Error(%v)", w.ID, err)
return ws, err
}
w.HomepageUri = fmt.Sprintf("%v%v", randomBFSHost, w.HomepageUri)
w.BackdropUri = fmt.Sprintf("%v%v", randomBFSHost, w.BackdropUri)
for _, wb := range wbs {
w.ReceivedCount += wb.ReceivedCount
w.Count += wb.Count
}
}
return
}
// WelfareBatchUpload save upload welfare code
func (s *Service) WelfareBatchUpload(body []byte, name, username string, wid, vtime int) (err error) {
wcb := new(model.WelfareCodeBatch)
wcb.BatchName = name
wcb.Wid = wid
wcb.Vtime = time.Time(vtime)
wcb.OperName = username
wcs := make([]*model.WelfareCode, 0)
str := string(body)
for _, lineStr := range strings.Split(str, "\n") {
lineStr = strings.TrimSpace(lineStr)
if lineStr == "" {
continue
}
wc := new(model.WelfareCode)
wc.Wid = wid
wc.Code = lineStr
wcs = append(wcs, wc)
}
wcb.Count = len(wcs)
if wcb.Count > _maxRows {
err = ecode.VipWelfareUploadMaxErr
return
}
if err = s.dao.WelfareBatchSave(wcb); err != nil {
log.Error("WelfareBatchSave (%v) Error(%v)", wcb, err)
return
}
for _, wc := range wcs {
wc.Bid = wcb.ID
}
if err = s.dao.WelfareCodeBatchInsert(wcs); err != nil {
log.Error("WelfareBatchSave Error(%v)", err)
}
return
}
// WelfareBatchList get welfare batch list
func (s *Service) WelfareBatchList(wid int) (wbs []*model.WelfareBatchRes, err error) {
if wbs, err = s.dao.WelfareBatchList(wid); err != nil {
log.Error("WelfareBatchList wid(%v) Error(%v)", wid, err)
}
return
}
// WelfareBatchState delete welfare batch
func (s *Service) WelfareBatchState(c context.Context, id int, username string) (err error) {
tx := s.dao.BeginGormTran(c)
if err = s.dao.WelfareBatchState(tx, id, _delete, 0, username); err != nil {
log.Error("WelfareBatchState(%v) Error(%v)", id, err)
tx.Rollback()
return
}
if err = s.dao.WelfareCodeStatus(tx, id, _delete); err != nil {
log.Error("WelfareCodeStatus bid(%v) Error(%v)", id, err)
tx.Rollback()
return
}
return tx.Commit().Error
}
func copyFiled(wf *model.Welfare, req *model.WelfareReq) {
wf.ID = req.ID
wf.WelfareName = req.WelfareName
wf.WelfareDesc = req.WelfareDesc
wf.HomepageUri = req.HomepageUri
wf.BackdropUri = req.BackdropUri
wf.Recommend = req.Recommend
wf.Rank = req.Rank
wf.Tid = req.Tid
wf.Stime = req.Stime
wf.Etime = req.Etime
wf.UsageForm = req.UsageForm
wf.ReceiveRate = req.ReceiveRate
wf.VipType = req.VipType
}
// getRelativePath get relative path
func getRelativePath(absolutePath string) (relativePath string, err error) {
u, err := url.Parse(absolutePath)
if err != nil {
err = ecode.VipWelfareUrlUnvalid
log.Error("hostChange ParseURL(%v) error (%v)", absolutePath, err)
return
}
relativePath = u.Path
return
}