780 lines
25 KiB
Go
780 lines
25 KiB
Go
package cms
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
"sync"
|
||
"time"
|
||
|
||
"git.rosy.net.cn/jx-callback/business/jxutils/smsmsg"
|
||
|
||
"git.rosy.net.cn/jx-callback/business/jxstore/event"
|
||
|
||
"git.rosy.net.cn/jx-callback/business/jxstore/financial"
|
||
|
||
"git.rosy.net.cn/baseapi/platformapi/dingdingapi"
|
||
"git.rosy.net.cn/baseapi/utils"
|
||
"git.rosy.net.cn/jx-callback/business/auth2"
|
||
"git.rosy.net.cn/jx-callback/business/auth2/authprovider/dingding"
|
||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||
"git.rosy.net.cn/jx-callback/business/jxutils/jsonerr"
|
||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||
"git.rosy.net.cn/jx-callback/business/model"
|
||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||
"git.rosy.net.cn/jx-callback/globals"
|
||
"git.rosy.net.cn/jx-callback/globals/api"
|
||
)
|
||
|
||
var (
|
||
ErrUserIDAndNameMustGiven = errors.New("用户ID2和用户名必须不为空")
|
||
)
|
||
|
||
var (
|
||
userProvider = &UserProvider{}
|
||
authTypeFieldMap = map[string]string{
|
||
auth2.UserIDID: "user_id",
|
||
auth2.UserIDID2: "user_id2",
|
||
auth2.UserIDMobile: "mobile",
|
||
auth2.UserIDEmail: "email",
|
||
}
|
||
jdUsersStruct GetJdUsersStruct
|
||
titleListJdUser = []string{
|
||
"用户名",
|
||
"关联门店",
|
||
"所属角色",
|
||
"状态",
|
||
}
|
||
)
|
||
|
||
type GetJdUsersStruct struct {
|
||
locker sync.RWMutex
|
||
userMap []JdUserStruct
|
||
}
|
||
|
||
type JdUserStruct struct {
|
||
UserName string `json:"用户名"`
|
||
StoreIDs string `json:"关联门店"`
|
||
RoleName string `json:"所属角色"`
|
||
Status string `json:"状态"`
|
||
}
|
||
|
||
type UserProvider struct {
|
||
}
|
||
|
||
func (*UserProvider) GetUser(authID, authIDType string) (user auth2.IUser) {
|
||
globals.SugarLogger.Debugf("GetUser, authID:%s, authIDType:%s", authID, authIDType)
|
||
fieldName := authTypeFieldMap[authIDType]
|
||
if fieldName != "" {
|
||
user2, err := dao.GetUserByID(dao.GetDB(), fieldName, authID)
|
||
if err == nil {
|
||
user = user2 // 这样写的原因是golang nil的比较问题
|
||
}
|
||
}
|
||
return user
|
||
}
|
||
|
||
func (*UserProvider) UpdateUserMobile(userID string, mobile string) (err error) {
|
||
_, err = dao.UpdateEntityLogically(dao.GetDB(), &model.User{}, map[string]interface{}{
|
||
"Mobile": mobile,
|
||
}, userID, map[string]interface{}{
|
||
"UserID": userID,
|
||
})
|
||
return err
|
||
}
|
||
|
||
func (*UserProvider) UpdateUserEmail(userID string, email string) (err error) {
|
||
_, err = dao.UpdateEntityLogically(dao.GetDB(), &model.User{}, map[string]interface{}{
|
||
"Email": email,
|
||
}, userID, map[string]interface{}{
|
||
"UserID": userID,
|
||
})
|
||
return err
|
||
}
|
||
|
||
func (*UserProvider) UpdateUserType(userID string, userTypeMask int8, updateType int) (err error) {
|
||
db := dao.GetDB()
|
||
user := &model.User{
|
||
UserID: userID,
|
||
}
|
||
if err = dao.GetEntity(db, user, "UserID"); err == nil {
|
||
if updateType == auth2.UpdateUserTypeAdd {
|
||
user.Type |= userTypeMask
|
||
} else if updateType == auth2.UpdateUserTypeDelete {
|
||
user.Type &= ^userTypeMask
|
||
} else {
|
||
user.Type = userTypeMask
|
||
}
|
||
dao.WrapUpdateULEntity(user, userID)
|
||
_, err = dao.UpdateEntity(db, user, "Type", model.FieldUpdatedAt, model.FieldLastOperator)
|
||
}
|
||
return err
|
||
}
|
||
|
||
func (*UserProvider) UpdateLastLogin(userID string, lastLoginType, fromIP string) (err error) {
|
||
_, err = dao.UpdateEntityLogically(dao.GetDB(), &model.User{}, map[string]interface{}{
|
||
"LastLoginAt": utils.Time2Pointer(time.Now()),
|
||
"LastLoginType": lastLoginType,
|
||
"LastLoginIP": fromIP,
|
||
}, userID, map[string]interface{}{
|
||
"UserID": userID,
|
||
})
|
||
return err
|
||
}
|
||
|
||
func init() {
|
||
auth2.Init(userProvider)
|
||
}
|
||
|
||
func RegisterUserWithMobile(ctx *jxcontext.Context, user *model.User, mobileVerifyCode string, inAuthInfo, manTokenInfo *auth2.AuthInfo) (outAuthInfo *auth2.AuthInfo, err error) {
|
||
var mobileAuth *auth2.AuthInfo
|
||
fakeMobile := false
|
||
createName := ctx.GetRealRemoteIP()
|
||
authType := auth2.AuthTypeMobile
|
||
if manTokenInfo != nil && mobileVerifyCode == "" {
|
||
_, err2 := dao.GetUserByID(dao.GetDB(), "user_id", manTokenInfo.GetID())
|
||
if err = err2; err != nil {
|
||
return nil, err
|
||
}
|
||
if utils.Pointer2String(user.Mobile) == "" {
|
||
return nil, fmt.Errorf("管理员添加必须指定用户手机号")
|
||
}
|
||
mobileVerifyCode = auth2.InternalAuthSecret
|
||
fakeMobile = true
|
||
createName = manTokenInfo.GetName()
|
||
}
|
||
|
||
if mobileVerifyCode != "" {
|
||
if fakeMobile {
|
||
mobileAuth, err = auth2.LoginInternal(ctx.Context, auth2.AuthTypeMobile, user.GetMobile(), auth2.UserIDMobile, mobileVerifyCode)
|
||
} else {
|
||
mobileAuth, err = auth2.Login(ctx.Context, auth2.AuthTypeMobile, user.GetMobile(), auth2.UserIDMobile, mobileVerifyCode)
|
||
}
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if mobileAuth != nil && !mobileAuth.IsUserEmpty() {
|
||
return nil, jsonerr.New(mobileAuth, model.ErrCodeJsonUserAlreadyExist)
|
||
|
||
// auth2.RemoveUserInfo(mobileAuth.Token)
|
||
// if newAuthInfo, err := auth2.BindUser(mobileAuth, user); err == nil {
|
||
// globals.SugarLogger.Debugf("testRegisterUserWithMobile", utils.Format4Output(mobileAuth, false), utils.Format4Output(newAuthInfo, false))
|
||
// return nil, jsonerr.New(newAuthInfo, model.ErrCodeJsonUserAlreadyExist)
|
||
// } else {
|
||
// return nil, err
|
||
// }
|
||
}
|
||
} else if inAuthInfo != nil {
|
||
// user.Mobile = nil
|
||
} else {
|
||
return nil, fmt.Errorf("短信验证码与其它认证方式至少要指定一种")
|
||
}
|
||
|
||
if inAuthInfo != nil {
|
||
createName += "," + inAuthInfo.GetAuthID()
|
||
authType = inAuthInfo.GetAuthType()
|
||
if user.Avatar == "" {
|
||
user.Avatar = inAuthInfo.GetAvatar()
|
||
}
|
||
}
|
||
if err = CreateUser(user, utils.LimitUTF8StringLen(createName, 32)); err == nil {
|
||
userProvider.UpdateLastLogin(user.GetID(), authType, ctx.GetRealRemoteIP())
|
||
// TryAddStoreBossRole4User(ctx, user)
|
||
if mobileAuth != nil {
|
||
if outAuthInfo, err = auth2.BindUser(mobileAuth, user); err == nil && inAuthInfo != nil {
|
||
err = auth2.AddAuthBind(&outAuthInfo.UserBasic, inAuthInfo)
|
||
}
|
||
} else {
|
||
outAuthInfo, err = auth2.BindUser(inAuthInfo, user)
|
||
}
|
||
//给用户添加一条账单记录
|
||
err = AddUserBill(user)
|
||
} else if dao.IsDuplicateError(err) {
|
||
err = auth2.ErrUserID2AlreadyExist
|
||
}
|
||
return outAuthInfo, err
|
||
}
|
||
|
||
func AddUserBill(user *model.User) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
userBill := &model.UserBill{
|
||
BillID: jxutils.GenBillID(),
|
||
UserID: user.UserID,
|
||
}
|
||
dao.WrapAddIDCULDEntity(userBill, jxcontext.AdminCtx.GetUserName())
|
||
return dao.CreateEntity(db, userBill)
|
||
}
|
||
|
||
func GetUserBindAuthInfo(ctx *jxcontext.Context) (authList []*model.AuthBind, err error) {
|
||
authInfo, err := ctx.GetV2AuthInfo()
|
||
if err == nil {
|
||
return auth2.GetUserBindAuthInfo(authInfo.GetID())
|
||
}
|
||
return nil, err
|
||
}
|
||
|
||
func CreateUser(user *model.User, creatorName string) (err error) {
|
||
globals.SugarLogger.Debugf("CreateUser user:%s, creatorName:%s", utils.Format4Output(user, true), creatorName)
|
||
|
||
if user == nil || user.UserID2 == "" || user.Name == "" {
|
||
return ErrUserIDAndNameMustGiven
|
||
}
|
||
if user.GetMobile() == "" {
|
||
user.Mobile = nil
|
||
}
|
||
if user.GetEmail() == "" {
|
||
user.Email = nil
|
||
}
|
||
dao.WrapAddIDCULDEntity(user, creatorName)
|
||
user.UserID = utils.GetUUID()
|
||
user.Status = model.UserStatusNormal
|
||
//推广码
|
||
popCode := ""
|
||
for {
|
||
popCode = jxutils.GenRandomString(6)
|
||
user2, _ := dao.GetUserByID(dao.GetDB(), "pop_code", popCode)
|
||
if user2 == nil {
|
||
user.PopCode = popCode
|
||
break
|
||
}
|
||
}
|
||
return dao.CreateEntity(nil, user)
|
||
}
|
||
|
||
func DisableUser(ctx *jxcontext.Context, userID string) (err error) {
|
||
userName := ctx.GetUserName()
|
||
if _, err = dao.UpdateEntityLogically(dao.GetDB(), &model.User{}, map[string]interface{}{
|
||
"Status": model.UserStatusDisabled,
|
||
}, userName, map[string]interface{}{
|
||
"UserID": userID,
|
||
}); err == nil {
|
||
auth2.DisableUser(userID, userName)
|
||
}
|
||
return err
|
||
}
|
||
|
||
func OnDingDingMsg(msg map[string]interface{}) (callbackResponse *dingdingapi.CallbackResponse) {
|
||
eventType := utils.Interface2String(msg[dingdingapi.KeyEventType])
|
||
if eventType == dingdingapi.CBTagUserLeaveOrg {
|
||
var (
|
||
authBind *model.AuthBind
|
||
err error
|
||
)
|
||
db := dao.GetDB()
|
||
for _, userID := range msg[dingdingapi.KeyUserID].([]interface{}) {
|
||
userIDStr := utils.Interface2String(userID)
|
||
globals.SugarLogger.Debugf("OnDingDingMsg dingding user:%s left company", userIDStr)
|
||
if authBind, err = dao.GetAuthBind(db, model.AuthBindTypeAuth, dingding.AuthTypeStaff, userIDStr); err == nil { // 直接找到了
|
||
globals.SugarLogger.Debugf("OnDingDingMsg dingding user:%s, userID:%s left company", userIDStr, authBind.UserID)
|
||
if err = DisableUser(jxcontext.AdminCtx, authBind.UserID); err != nil {
|
||
globals.SugarLogger.Errorf("OnDingDingMsg failed with error:%v", err)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return api.DingDingAPI.Err2CallbackResponse(nil)
|
||
}
|
||
|
||
func GetUsers(ctx *jxcontext.Context, keyword string, userID string, pop int, mobile string, fromTime, toTime string, timeType int, cityCodes, consumeTypes []int, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) {
|
||
return dao.GetUsers2(dao.GetDB(), keyword, userID, pop, mobile, utils.Str2Time(fromTime), utils.Str2Time(toTime), timeType, cityCodes, consumeTypes, offset, pageSize)
|
||
}
|
||
|
||
func GetUser(ctx *jxcontext.Context, userID string) (user *model.GetUserResult, err error) {
|
||
return dao.GetUser(dao.GetDB(), userID)
|
||
}
|
||
|
||
func checkUserType(userID string, userType int8) (err error) {
|
||
userList, _, err := dao.GetUsers(dao.GetDB(), 0, "", "", []string{userID}, nil, nil, 0, 0)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if len(userList) == 0 {
|
||
return fmt.Errorf("找不到用户:%s", userID)
|
||
}
|
||
if userList[0].Type&userType == 0 {
|
||
return fmt.Errorf("用户:%s不能用于当前操作", userID)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func getAddressInfoFromCoord(db *dao.DaoDB, lng, lat float64) (formattedAddress string, districtCode, cityCode int, err error) {
|
||
regeoInfo, err := api.AutonaviAPI.GeoCodeRegeoSingle(lng, lat, 0, false, nil, 0, 0)
|
||
if err == nil {
|
||
formattedAddress = regeoInfo.FormattedAddress
|
||
districtCode = int(utils.Str2Int64WithDefault(regeoInfo.AddressComponent.Adcode, 0))
|
||
if districtCode == 0 {
|
||
err = fmt.Errorf("坐标lng:%f,lat:%f找不到位置信息", lng, lat)
|
||
} else if districtInfo, err2 := dao.GetPlaceByCode(db, districtCode); err2 == nil {
|
||
cityCode = districtInfo.ParentCode
|
||
}
|
||
}
|
||
return formattedAddress, districtCode, cityCode, err
|
||
}
|
||
|
||
func AddMyDeliveryAddress(ctx *jxcontext.Context, address *model.UserDeliveryAddress) (outAddress *dao.UserDeliveryAddressEx, err error) {
|
||
globals.SugarLogger.Debugf("AddMyDeliveryAddress address:%s", utils.Format4Output(address, true))
|
||
_, address.UserID = ctx.GetMobileAndUserID()
|
||
out, err := AddUserDeliveryAddress(ctx, address)
|
||
list, _, err := dao.QueryUserDeliveryAddress(dao.GetDB(), int64(out.ID), nil, 0, 0, -1)
|
||
globals.SugarLogger.Debugf("AddMyDeliveryAddress2 address:%s, err:%v", utils.Format4Output(address, true), err)
|
||
return list[0], err
|
||
}
|
||
|
||
func DeleteUserDeliveryAddress(ctx *jxcontext.Context, userID string, addressID int) (err error) {
|
||
num, err := dao.DeleteEntityLogically(dao.GetDB(), &model.UserDeliveryAddress{}, nil, ctx.GetUserName(), map[string]interface{}{
|
||
model.FieldID: addressID,
|
||
"UserID": userID,
|
||
})
|
||
if err == nil {
|
||
if num == 0 {
|
||
err = fmt.Errorf("地址ID:%d不存在", addressID)
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
|
||
func DeleteMyDeliveryAddress(ctx *jxcontext.Context, addressID int) (err error) {
|
||
_, userID := ctx.GetMobileAndUserID()
|
||
return DeleteUserDeliveryAddress(ctx, userID, addressID)
|
||
}
|
||
|
||
func UpdateUserDeliveryAddress(ctx *jxcontext.Context, userID string, addressID int, payload map[string]interface{}) (err error) {
|
||
if userID == "" {
|
||
return fmt.Errorf("操作用户配送地址时必须指定UserID")
|
||
}
|
||
address := &model.UserDeliveryAddress{
|
||
UserID: userID,
|
||
}
|
||
address.ID = addressID
|
||
db := dao.GetDB()
|
||
if err = dao.GetEntity(db, address, model.FieldID, "UserID"); err == nil {
|
||
var outAddress *model.UserDeliveryAddress
|
||
valid := dao.StrictMakeMapByStructObject2(payload, address, &outAddress, ctx.GetUserName())
|
||
delete(valid, "autoAddress")
|
||
delete(valid, "districtCode")
|
||
delete(valid, "cityCode")
|
||
if len(valid) > 0 {
|
||
if valid["lng"] != nil || valid["lat"] != nil {
|
||
valid["autoAddress"], valid["districtCode"], valid["cityCode"], err = getAddressInfoFromCoord(db, outAddress.Lng, outAddress.Lat)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
txDB, _ := dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db, txDB)
|
||
panic(r)
|
||
}
|
||
}()
|
||
if utils.ForceInterface2Int64(valid["isDefault"]) == 1 {
|
||
if err = dao.ClearUserDeliveryAddressDefault(db, userID, 0); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return err
|
||
}
|
||
}
|
||
if _, err = dao.UpdateEntityLogically(db, address, valid, ctx.GetUserName(), nil); err == nil {
|
||
dao.Commit(db, txDB)
|
||
} else {
|
||
dao.Rollback(db, txDB)
|
||
}
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
|
||
func UpdateMyDeliveryAddress(ctx *jxcontext.Context, addressID int, payload map[string]interface{}) (err error) {
|
||
_, userID := ctx.GetMobileAndUserID()
|
||
return UpdateUserDeliveryAddress(ctx, userID, addressID, payload)
|
||
}
|
||
|
||
func QueryUserDeliveryAddress(ctx *jxcontext.Context, userIDs []string, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) {
|
||
addressList, totalCount, err := dao.QueryUserDeliveryAddress(dao.GetDB(), 0, userIDs, 0, offset, pageSize)
|
||
if err == nil {
|
||
pagedInfo = &model.PagedInfo{
|
||
TotalCount: totalCount,
|
||
Data: addressList,
|
||
}
|
||
}
|
||
return pagedInfo, err
|
||
}
|
||
|
||
func QueryMyDeliveryAddress(ctx *jxcontext.Context, addType int) (addressList []*dao.UserDeliveryAddressEx, err error) {
|
||
_, userID := ctx.GetMobileAndUserID()
|
||
addressList, _, err = dao.QueryUserDeliveryAddress(dao.GetDB(), 0, []string{userID}, addType, 0, model.UnlimitedPageSize)
|
||
return addressList, err
|
||
}
|
||
|
||
func AddUserDeliveryAddress(ctx *jxcontext.Context, address *model.UserDeliveryAddress) (outAddress *model.UserDeliveryAddress, err error) {
|
||
globals.SugarLogger.Debugf("AddUserDeliveryAddress1 address:%s", utils.Format4Output(address, true))
|
||
if address.UserID == "" {
|
||
return nil, fmt.Errorf("操作用户配送地址时必须指定UserID")
|
||
}
|
||
db := dao.GetDB()
|
||
lng := address.Lng
|
||
lat := address.Lat
|
||
address.AutoAddress, address.DistrictCode, address.CityCode, err = getAddressInfoFromCoord(db, lng, lat)
|
||
if err == nil {
|
||
globals.SugarLogger.Debugf("AddUserDeliveryAddress2 address:%s", utils.Format4Output(address, true))
|
||
txDB, _ := dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db, txDB)
|
||
panic(r)
|
||
}
|
||
}()
|
||
dao.WrapAddIDCULDEntity(address, ctx.GetUserName())
|
||
if address.IsDefault == 1 {
|
||
if err = dao.ClearUserDeliveryAddressDefault(db, address.UserID, 0); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return nil, err
|
||
}
|
||
}
|
||
if err = dao.CreateEntity(db, address); err == nil {
|
||
dao.Commit(db, txDB)
|
||
outAddress = address
|
||
} else {
|
||
dao.Rollback(db, txDB)
|
||
}
|
||
}
|
||
globals.SugarLogger.Debugf("AddUserDeliveryAddress3 address:%s", utils.Format4Output(address, true))
|
||
return outAddress, err
|
||
}
|
||
|
||
func SaveUserCart(ctx *jxcontext.Context, userID string, storeID int, cartItems []*model.UserCartItem) (err error) {
|
||
if userID == "" || storeID == 0 {
|
||
return fmt.Errorf("用户与门店必须要指定")
|
||
}
|
||
for _, v := range cartItems {
|
||
v.UserID = userID
|
||
v.StoreID = storeID
|
||
dao.WrapAddIDCULEntity(v, userID)
|
||
}
|
||
db := dao.GetDB()
|
||
txDB, _ := dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil || err != nil {
|
||
dao.Rollback(db, txDB)
|
||
if r != nil {
|
||
panic(r)
|
||
}
|
||
}
|
||
}()
|
||
_, err = dao.ExecuteSQL(db, `
|
||
DELETE t1
|
||
FROM user_cart_item t1
|
||
WHERE t1.user_id = ? AND t1.store_id = ?
|
||
`, userID, storeID)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if len(cartItems) > 0 {
|
||
err = dao.CreateMultiEntities(db, cartItems)
|
||
}
|
||
if err == nil {
|
||
dao.Commit(db, txDB)
|
||
}
|
||
return err
|
||
}
|
||
|
||
func LoadUserCart(ctx *jxcontext.Context, userID string, storeIDs []int) (cartItems []*model.UserCartItem, err error) {
|
||
if userID == "" || len(storeIDs) == 0 {
|
||
return nil, fmt.Errorf("用户与门店必须要指定")
|
||
}
|
||
sql := `
|
||
SELECT t1.*
|
||
FROM user_cart_item t1
|
||
WHERE t1.user_id = ? AND t1.store_id IN (` + dao.GenQuestionMarks(len(storeIDs)) + `)
|
||
ORDER BY t1.sku_id
|
||
`
|
||
err = dao.GetRows(dao.GetDB(), &cartItems, sql, userID, storeIDs)
|
||
return cartItems, err
|
||
}
|
||
|
||
func GetSelfInfo(ctx *jxcontext.Context) (getSelfInfoResult *dao.GetSelfInfoResult, err error) {
|
||
tokenInfo, err := auth2.GetTokenInfo(ctx.GetToken())
|
||
if err == nil {
|
||
if getSelfInfoResult, err = dao.GetUserByIDWithMembers(dao.GetDB(), "user_id", tokenInfo.GetID()); err == nil {
|
||
if userMembers, err3 := dao.GetUserMember(dao.GetDB(), getSelfInfoResult.User.UserID, 0); err3 == nil {
|
||
getSelfInfoResult.UserMembers = userMembers
|
||
} else {
|
||
err = err3
|
||
}
|
||
if price, err := dao.GetUserAllWaitCashPrice(dao.GetDB(), getSelfInfoResult.User.UserID); err == nil {
|
||
getSelfInfoResult.WaitCashPrice = price
|
||
}
|
||
if price, err := dao.GetUserAllWaitRealCashPrice(dao.GetDB(), getSelfInfoResult.User.UserID); err == nil {
|
||
getSelfInfoResult.WaitRealCashPrice = price
|
||
}
|
||
}
|
||
}
|
||
return getSelfInfoResult, err
|
||
}
|
||
|
||
func RefreshUserMemberStatus(ctx *jxcontext.Context) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
userMembers, err := dao.GetUserMember(db, "", 0)
|
||
for _, userMember := range userMembers {
|
||
if time.Now().Sub(userMember.EndAt) > 0 {
|
||
userMember.DeletedAt = time.Now()
|
||
dao.UpdateEntity(db, userMember, "DeletedAt")
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
|
||
func InvestMember(ctx *jxcontext.Context, memberID int, userID string, isFree bool) (errCode string, err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
memberCards []*model.MemberCard
|
||
memberCard *model.MemberCard
|
||
userIDReal string
|
||
)
|
||
if !isFree {
|
||
userIDReal = ctx.GetUserID()
|
||
} else {
|
||
userIDReal = userID
|
||
}
|
||
userMembers, err := dao.GetUserMember(db, userIDReal, model.MemberTypeNormal)
|
||
configList, err := dao.QueryConfigs(db, model.ConfigTypeName[model.ConfigTypeMemberCard], model.ConfigTypeMemberCard, "")
|
||
userBill, err := dao.GetUserBill(db, userIDReal, "")
|
||
if len(configList) <= 0 {
|
||
return "", fmt.Errorf("未找到会员卡配置!")
|
||
}
|
||
config := configList[0]
|
||
err = jxutils.Strings2Objs(config.Value, &memberCards)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
for _, v := range memberCards {
|
||
if v.ID == memberID {
|
||
memberCard = v
|
||
}
|
||
}
|
||
if !isFree {
|
||
//验证微信绑定
|
||
if err = auth2.CheckWeixinminiAuthBind(userIDReal); err != nil {
|
||
return "", err
|
||
}
|
||
if userBill.AccountBalance < memberCard.Price {
|
||
return model.ErrCodeAccountBalanceNotEnough, fmt.Errorf("用户余额不足,请充值!")
|
||
}
|
||
}
|
||
txDB, _ := dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db, txDB)
|
||
panic(r)
|
||
}
|
||
}()
|
||
//证明已经开了会员了,相当于续费
|
||
if len(userMembers) > 0 {
|
||
userMember := userMembers[0]
|
||
if memberID == model.MemberCardTypeMonth {
|
||
userMember.EndAt = userMember.EndAt.AddDate(0, 1, 0)
|
||
} else {
|
||
userMember.EndAt = userMember.EndAt.AddDate(1, 0, 0)
|
||
}
|
||
if _, err = dao.UpdateEntity(db, userMember, "EndAt"); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
} else {
|
||
userMember2 := &model.UserMember{
|
||
UserID: userIDReal,
|
||
MemberType: model.MemberTypeNormal,
|
||
MemberTypeID: memberID,
|
||
}
|
||
if memberID == model.MemberCardTypeMonth {
|
||
userMember2.EndAt = time.Now().AddDate(0, 1, 0)
|
||
} else {
|
||
userMember2.EndAt = time.Now().AddDate(1, 0, 0)
|
||
}
|
||
dao.WrapAddIDCULDEntity(userMember2, ctx.GetUserName())
|
||
if err = dao.CreateEntity(db, userMember2); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
}
|
||
if !isFree {
|
||
//支出明细
|
||
if err = financial.AddExpendUpdateAccount(txDB, userBill, model.BillTypeMember, memberCard.Price, 0); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
}
|
||
dao.Commit(db, txDB)
|
||
return errCode, err
|
||
}
|
||
|
||
func UpdateUser(ctx *jxcontext.Context, payload map[string]interface{}) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
userID string
|
||
)
|
||
if payload["userID"] != nil {
|
||
userID = payload["userID"].(string)
|
||
} else {
|
||
userID = ctx.GetUserID()
|
||
}
|
||
user := &model.User{
|
||
UserID: userID,
|
||
}
|
||
dao.GetEntity(db, user, "UserID")
|
||
if payload["lng"] != nil && payload["lat"] != nil {
|
||
if address, districtCode, cityCode, err := getAddressInfoFromCoord(db, utils.MustInterface2Float64(payload["lng"]), utils.MustInterface2Float64(payload["lat"])); err == nil {
|
||
delete(payload, "lng")
|
||
delete(payload, "lat")
|
||
payload["address"] = address
|
||
payload["districtCode"] = districtCode
|
||
payload["cityCode"] = cityCode
|
||
} else {
|
||
return err
|
||
}
|
||
}
|
||
//暂时用这个字段作为更新他的推广人
|
||
if payload["popCode"] != nil {
|
||
if user, err := dao.GetUserByID(db, "pop_code", payload["popCode"].(string)); err == nil {
|
||
if user != nil {
|
||
payload["popUser"] = user.UserID
|
||
delete(payload, "popCode")
|
||
} else {
|
||
return fmt.Errorf("未查询到此推广人!%v", payload["popCode"])
|
||
}
|
||
}
|
||
}
|
||
valid := dao.StrictMakeMapByStructObject(payload, user, ctx.GetUserName())
|
||
if len(valid) > 0 {
|
||
txDB, _ := dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db, txDB)
|
||
panic(r)
|
||
}
|
||
}()
|
||
if _, err = dao.UpdateEntityByKV(db, user, valid, nil); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return err
|
||
}
|
||
dao.Commit(db, txDB)
|
||
}
|
||
if payload["popUser"] != nil {
|
||
// InvestMemberAndUpdate := func(user *model.User) (err error) {
|
||
// if _, err = InvestMember(ctx, 1, user.UserID, true); err == nil {
|
||
|
||
// }
|
||
// user.PopFlag = model.YES
|
||
// _, err = dao.UpdateEntity(db, user, "PopFlag")
|
||
// return err
|
||
// }
|
||
user2, err2 := dao.GetUserByID(db, "user_id", payload["popUser"].(string))
|
||
err = err2
|
||
do := func(user *model.User, flag bool) (err error) {
|
||
if user.PopCount%4 == 0 && user.PopFlag == model.NO {
|
||
if _, err = InvestMember(ctx, 1, user.UserID, true); err == nil {
|
||
//发短信,公众号消息通知
|
||
smsmsg.SendSMSMsg([]string{*user.Mobile}, globals.SMSSignName, globals.SMSPopSuccessTemplate, nil)
|
||
// weixinmsg.SendMsgToUser(userID, templateID, data)
|
||
event.SendSysMessageSimple("您好,您已成功邀请4人加入我们,成功免费获得1个月会员!", user.UserID)
|
||
}
|
||
user.PopFlag = model.YES
|
||
dao.UpdateEntity(db, user, "PopFlag")
|
||
|
||
if flag {
|
||
if users, _, err := dao.GetUsers(db, 0, "", user.UserID, nil, nil, nil, 0, 999); err == nil {
|
||
for _, v := range users {
|
||
v.PopedFlag = model.YES
|
||
dao.UpdateEntity(db, v, "PopedFlag")
|
||
}
|
||
}
|
||
_, err = event.CreateMessageGroup(ctx, user.UserID, "", "", 5, 100)
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
if user2 != nil {
|
||
user2.PopCount++
|
||
messageGroupsResult, err3 := dao.GetMessageGroups(db, user2.UserID, 0, model.GroupTypeMulit, false, "")
|
||
err = err3
|
||
//如果他已经有群了,被邀请人直接进群
|
||
//如果他没群,在邀请到4个人的时候,自动创一个群,所有被邀请人打上标志
|
||
if len(messageGroupsResult) > 0 {
|
||
err = event.AddMessageGroup(ctx, messageGroupsResult[0].GroupID, user.UserID)
|
||
//邀请过4人直接开通一个月会员
|
||
do(user2, false)
|
||
} else {
|
||
//邀请过4人直接开通一个月会员并创建群组
|
||
do(user2, true)
|
||
}
|
||
dao.UpdateEntity(db, user2, "PopCount")
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
|
||
func AcceptAddGroup(ctx *jxcontext.Context, flag int) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
userID = ctx.GetUserID()
|
||
)
|
||
user, err := dao.GetUserByID(db, "user_id", userID)
|
||
if user == nil {
|
||
return fmt.Errorf("获取用户信息失败!")
|
||
}
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if user.PopedFlag == model.NO {
|
||
return fmt.Errorf("获取用户邀请信息失败")
|
||
}
|
||
//同意加入
|
||
if flag == model.YES {
|
||
//1、找到这个人的邀请人
|
||
//2、这个邀请人有群就直接进,没群就加入失败了
|
||
messageGroupsResult, err := dao.GetMessageGroups(db, user.PopUser, 0, model.GroupTypeMulit, false, "")
|
||
if err != nil {
|
||
return fmt.Errorf("获取邀请人群信息失败! %v", err)
|
||
}
|
||
if len(messageGroupsResult) > 0 {
|
||
err = event.AddMessageGroup(ctx, messageGroupsResult[0].GroupID, user.UserID)
|
||
} else {
|
||
return fmt.Errorf("获取邀请人群信息失败!")
|
||
}
|
||
}
|
||
//同步同意都清标志
|
||
user.PopedFlag = model.NO
|
||
dao.UpdateEntity(db, user, "PopedFlag")
|
||
return err
|
||
}
|
||
|
||
type GetUserSerachKeywordResult struct {
|
||
AllSpan []*model.UserSearch `json:"allSpan"`
|
||
UserSpan []*model.UserSearch `json:"userSpan"`
|
||
}
|
||
|
||
func GetUserSerachKeyword(ctx *jxcontext.Context) (getUserSerachKeywordResult *GetUserSerachKeywordResult, err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
userID = ctx.GetUserID()
|
||
userSearchAll []*model.UserSearch
|
||
userSearch []*model.UserSearch
|
||
)
|
||
getUserSerachKeywordResult = &GetUserSerachKeywordResult{}
|
||
sql := `
|
||
SELECT keyword, SUM(count) count FROM user_search WHERE created_at > ? GROUP BY 1 ORDER BY SUM(count) DESC LIMIT 20
|
||
`
|
||
sqlParams := []interface{}{time.Now().AddDate(0, -1, 0)}
|
||
err = dao.GetRows(db, &userSearchAll, sql, sqlParams)
|
||
getUserSerachKeywordResult.AllSpan = userSearchAll
|
||
sql2 := `
|
||
SELECT keyword, SUM(count) count FROM user_search WHERE created_at > ? AND user_id = ? GROUP BY 1 ORDER BY SUM(count) DESC LIMIT 20
|
||
`
|
||
sqlParams2 := []interface{}{time.Now().AddDate(0, -1, 0), userID}
|
||
err = dao.GetRows(db, &userSearch, sql2, sqlParams2)
|
||
getUserSerachKeywordResult.UserSpan = userSearch
|
||
return getUserSerachKeywordResult, err
|
||
}
|