package models import ( "encoding/csv" "errors" "fmt" "github.com/gin-gonic/gin" "github.com/xuri/excelize/v2" "go-admin/app/admin/apis/pay" utils "go-admin/app/admin/models/tools" orm "go-admin/common/global" "go-admin/logger" "go-admin/pkg/jwtauth" "go-admin/tools" "go-admin/tools/app" "go-admin/tools/config" "log" "net/http" "os" "sort" "strconv" "strings" "time" ) type MemberType int const ( Unknown MemberType = iota FirstInvite // 1-首次邀请 OpenAnnualGold // 2-开通年费黄金 OpenQuarterGold // 3-开通季度黄金 OpenHalfYearGold // 4-开通半年黄金 OpenAnnualPlatinum // 5-开通年费白金 OpenAnnualBlack // 6-开通年费黑金 RenewAnnualGoldIntervene // 7-续费年费黄金(干预) RenewAnnualPlatinumIntervene // 8-续费年费白金(干预) RenewAnnualBlackIntervene // 9-续费年费黑金(干预) RenewAnnualGoldAuto // 10-续费年费黄金(自动) RenewQuarterGoldAuto // 11-续费季度黄金(自动) RenewHalfYearGoldAuto // 12-续费半年黄金(自动) RenewAnnualPlatinumAuto // 13-续费年费白金(自动) RenewAnnualBlackAuto // 14-续费年费黑金(自动) UpgradeGoldToPlatinumIntervene // 15-黄金→白金(干预) UpgradeGoldToBlackIntervene // 16-黄金→黑金(干预) UpgradePlatinumToBlackIntervene // 17-白金→黑金(干预) UpgradeGoldToPlatinumAuto // 18-黄金→白金(自动) UpgradeGoldToBlackAuto // 19-黄金→黑金(自动) UpgradePlatinumToBlackAuto // 20-白金→黑金(自动) OpenAnnualPrivilege // 21 开通年费尊享会员 RenewAnnualPrivilegeAuto // 22 续费年费尊享会员(自动) ) const ( MemberLevelConsumer = 10 // 普通用户:有开过零售单,留了手机号,但是小程序端未登陆过的,仍然是普通用户 MemberLevelUser = 1 // 普通会员:仅进入了小程序且授权过手机号的为会员用户,未开通租卡会员的为“普通会员” MemberLevelGold = 2 // 黄金会员 MemberLevelPeriod = 3 // 短期会员 MemberLevelPlatinum = 4 // 白金会员 MemberLevelBlackGold = 5 // 黑金会员 MemberLevelPrivilege = 6 // 尊享会员 ) const ( UserTypeConsumer = 1 // 普通用户 UserTypeShopAssistant = 2 // 店员 ) const ( // 尊享会员延保状态 ExtendExpire = 1 // 已过期 ExtendWaitActive = 2 // 待激活 ExtendEffectivity = 3 // 已激活 ) // gen:qs // //go:generate goqueryset -in user.go type UserInfo struct { Model Uid uint32 `json:"uid" gorm:"column:uid;unique_index"` // MemberLevel uint32 `json:"member_level"` // 当前会员等级:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员 MemberGenre uint32 `json:"member_genre"` // 会员类型 200-黄金年费 201-黄金季度 202-黄金半年 MemberExpire *time.Time `json:"member_expire"` // 会员到期时间 OpenMemberTime *time.Time `json:"open_member_time"` // 开通会员时间 Bond uint32 `json:"bond"` // 保证金 WxName string `json:"wxName"` // 昵称 WxAvatar string `json:"wxAvatar"` // 头像 WxOpenID string `json:"wxOpenID"` // 微信openid AppOpenID string `json:"appOpenID"` // WxUnionID string `json:"wxUnionID"` // 微信unionId Tel string `json:"tel"` // 电话 Gender uint8 `json:"gender"` // 性别 City string `json:"city"` // 城市 Province string `json:"province"` // 省 Country string `json:"country"` // 市 Deposit uint32 `json:"deposit"` // 押金 UserType uint8 `json:"user_type"` // 用户类型 1-普通用户 2-店员 XcxRoleId uint32 `json:"xcx_role_id"` // 角色id OpenMemberChannel string `json:"open_member_channel" ` // 开通会员渠道: -门店推广 -用户邀请 -兑换码 StoreId uint64 `json:"store_id"` // 门店id InviteCodeUrl string `json:"invite_code_url"` // 分享二维码 MemberOpenTime *time.Time `json:"member_open_time" gorm:"-"` // LastLoginAt *time.Time `json:"last_login_at"` // 最近登录时间 IP string `json:"-" gorm:"type:varchar(60)"` // ip InBlack bool `json:"in_black"` // 是否在黑名单 CooperativeBusinessId uint32 `json:"cooperative_business_id" gorm:"index"` // 合作商id CooperativeName string `json:"cooperative_name"` // 合作商名称 Version uint32 `json:"-"` // MemberStatus uint8 `json:"member_status" gorm:"-"` // InviteTime *time.Time `json:"invite_time"` // OpenMemberLevel uint32 `json:"open_member_level"` // 开通会员级别:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员 ShopAssistantName string `json:"shop_assistant_name"` // 店员名称 Mark int8 `json:"mark"` // 标记 FirstRetailOrder *time.Time `json:"first_retail_order"` // 首次零售开单时间 Store *Store `json:"store" gorm:"-"` // OrderCards []OrderCard `json:"order_cards" gorm:"foreignKey:uid;references:uid"` // ForfeitPenalty int `json:"forfeit_penalty" gorm:"-"` // 滞纳金 //RenewalTime *time.Time `json:"renewal_time"` // //RenewalMemberLevel uint32 `json:"renewal_member_level"` // //MemberLevelString string `json:"member_level_string" gorm:"-"` // 会员类型 } func (m *UserInfo) TableName() string { return "user" } const ( UNMARK = iota MARK ) const ( OpenMemberChannelStorePromotion = "store_promotion" // 门店推荐 OpenMemberChannelUserInvite = "user_invite" OpenMemberChannelRedeemCode = "redeem_code" ) const DateTimeFormat = "2006-01-02" const TimeFormat = "2006-01-02 15-04-05" const QueryTimeFormat = "2006-01-02T15:04:05+08:00" const StoreDateTimeFormat = "2006.01.02" const ( // ExportUrl = "https://admin.deovo.com/load/export/" // ExportUrl = "https://dev.admin.deovo.com/load/export/" // dev环境 // ExportUrl = "/Users/max/Documents/" // 本地环境 ) type UserInvite struct { Model FromUid uint32 `json:"from_uid"` // 邀请用户id UserType uint8 `json:"user_type"` // 用户类型 StoreId uint64 `json:"store_id"` // 门店id MemberOpenTime time.Time `json:"member_open_time"` // 开通会员 MemberType uint8 `json:"member_type"` // 被邀请用户 1-普通用户 2-会员 MemberStatus uint8 `json:"member_status"` // 被邀请用户 1-未开通 2-已开通 3-已取消会员 ToUid uint32 `json:"to_uid"` // 被邀请用户 StoreType uint32 `json:"store_type"` // 门店类型 Action uint32 `json:"action"` // 2-激活邀请 SpendType uint32 `json:"spend_type"` // 1-开通会员 2-续费 3-升级 MemberLevel uint32 `json:"member_level"` // 会员等级 } func (m *UserInvite) TableName() string { return "user_invite" } const ( DepositRefundStatusUnconfirmed = 1 // 待确认 DepositRefundStatusConfirmed = 2 // 已确认 DepositRefundStatusRefunded = 3 // 已退款 DepositRefundStatusRefused = 4 // 已拒绝 ) // gen:qs type DepositRefundRecord struct { Model Uid uint32 `json:"uid"` Status uint32 `json:"status"` // unconfirmed confirmed refunded Amount uint32 `json:"amount"` Operator uint32 `json:"operator"` // 操作者 ConfirmTime time.Time `json:"confirm_time"` User User `json:"user" gorm:"-"` } const ( //FundTypeMemberGold = "member_gold" // 黄金会员 //FundTypeMemberPlatinum = "member_platinum" // 白金会员 //FundTypeMemberBlackGold = "member_black_gold" // 黑金会员 //FundTypeMemberGoldDeposit = "member_gold_deposit" // 黄金会员押金 //FundTypeMemberPlatinumDeposit = "member_platinum_deposit" // 白金会员押金 //FundTypeMemberBlackGoldDeposit = "member_black_gold_platinum" // 黑金会员押金 //FundTypeExpressFee = "express_fee" // 邮费 //FundTypeUpgradeMember = "upgrade_member" // 升级会员 //FundTypeMemberExpireDelay = "member_expire_delay" // 滞纳金 FundTypeMemberFee = "member_fee" // 会员费 FundTypeMemberDeposit = "member_deposit" // 押金 FundTypeExpressFee = "express_fee" // 邮费 FundTypeUpgradeMember = "upgrade_member" // 升级会员 FundTypeMemberExpireDelay = "member_expire_delay" // 滞纳金 FundTypeDepositRefund = "deposit_refund" // 退押金 FundTypeExpressFeeRefund = "express_fee_refund" // 退邮费 FundTypeRecycleCard = "recycle_card" // 回收卡带 ) // gen:qs type FundRecord struct { Model Uid uint32 `json:"uid" gorm:"index"` FundType string `json:"fund_type" gorm:"index"` // -member_gold -member_platinum -member_black_gold Amount int64 `json:"amount"` TransactionId string `json:"transaction_id" gorm:"index"` // 支付单号 OutTradeNo string `json:"out_trade_no" gorm:"index"` RefundId string `json:"refund_id" gorm:"index"` PaymentNo string `json:"payment_no" gorm:"index"` // 付款单号 Status uint32 `json:"status"` // 1-待支付 2-已支付 3-已退款 Remark string `json:"remark"` // 备注 // fund_record } type XcxRole struct { Model RoleName string `json:"role_name" gorm:"size:255;"` // 角色名称 RoleKey string `json:"role_key" gorm:"size:255;"` // 角色代码 RoleSort int `json:"role_sort" gorm:""` // 角色排序 Status string `json:"status" gorm:"size:255;"` // 状态:1-停用 2-正常 Flag string `json:"flag" gorm:"size:255;"` // CreateBy string `json:"create_by" gorm:"size:255;"` // UpdateBy string `json:"update_by" gorm:"size:255;"` // Remark string `json:"remark" gorm:"size:255;"` // 备注 Params string `json:"params" gorm:"-"` MenuIds []int `json:"menuIds" gorm:"-"` DeptIds []int `json:"deptIds" gorm:"-"` // xcx_role } const ( OperationTypeRentCardRevert = "rent_card_revert" OperationTypeRentCardDeliver = "rent_card_deliver" OperationTypeMallOrderRefundSendReceive = "mall_goods_order_refund_receive" // 退货入库 ) // gen:qs type OperationLog struct { Model Uid uint32 `json:"uid" gorm:"index"` // 店员id SysUid uint32 `json:"sys_uid" gorm:"index"` Description string `json:"description"` // 描述 OperationType string `json:"operation_type" gorm:"index"` // 操作类型 CorrelationId uint32 `json:"correlation_id" gorm:"index"` // 关联id CorrelationName string `json:"correlation_name" gorm:"index"` // 关联name StoreId uint32 `json:"store_id" gorm:"index"` // 门店id StoreName string `json:"store_name"` // 门店名称 CooperativeName string `json:"cooperative_name"` // 合作商名称 CooperativeBusinessId uint32 `json:"cooperative_business_id" gorm:"index"` // 合作商id SerialNumber string `json:"serial_number" gorm:"index"` // 卡编号 Detail string `json:"detail"` // 详情 Remark string `json:"remark"` // 备注 } type U struct { UserInfo MemberExpireDays uint32 `json:"member_expire_days"` // 会员过期天数 OrderCount int `json:"order_count"` // 消费次数 OrderAmount float64 `json:"order_amount"` // 消费金额 Vm uint32 `json:"vm"` // 用户积分 } type NewUserListReq struct { PageIndex int `json:"pageIndex"` // 页码 PageSize int `json:"pageSize"` // 页面条数 Uid int `json:"uid"` // 用户id Tel string `json:"tel"` // 手机号 StoreId int `json:"store_id"` // 门店id UserType int `json:"user_type"` // 用户类型 用户类型 1-普通用户 2-店员 OpenMemberLevel []int `json:"open_member_level"` // 首次开通租卡会员等级:2-黄金会员 4-白金会员 5-黑金会员 MemberLevel []int `json:"member_level"` // 当前会员等级:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员 CreateStartTime string `json:"create_startTime"` // 注册小程序-开始时间 CreateEndTime string `json:"create_endTime"` // 注册小程序-结束时间 OrderStartTime string `json:"order_startTime"` // 首次零售开单-开始时间 OrderEndTime string `json:"order_endTime"` // 首次零售开单-结束时间 OpenStartTime string `json:"open_startTime"` // 首次开通租卡会员-开始时间 OpenEndTime string `json:"open_endTime"` // 首次开通租卡会员-结束时间 Filter bool `json:"filter"` // 是否过滤无滞纳金已标记用户 SortField string `json:"sort_field"` // 排序字段:滞纳金传"forfeit_penalty" SortType string `json:"sort_type"` // 排序类型:desc 降序、asc 升序 IsExport uint32 `json:"is_export"` // 1-导出 } type NewUserListResp struct { List []U `json:"list"` // 用户数据 Total int `json:"total"` // 总条数 PageIndex int `json:"pageIndex"` // 页码 PageSize int `json:"pageSize"` // 每页展示条数 ExportUrl string `json:"export_url"` // 导出excel地址 } func GetNewUserList(req *NewUserListReq, c *gin.Context) (*NewUserListResp, error) { resp := &NewUserListResp{ PageIndex: req.PageIndex, PageSize: req.PageSize, } req.PageIndex -= 1 if req.PageIndex < 0 { req.PageIndex = 0 } if req.PageSize == 0 { req.PageSize = 10 } if req.SortField == "forfeit_penalty" { return GetUserListByForfeitPenalty(req) } users := make([]U, 0) if req.SortField == "" { req.SortField = "id" } if req.SortType == "" { req.SortType = "DESC" } qs := orm.Eloquent.Model(&UserInfo{}).Debug() // 非管理员才判断所属门店 if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") { sysUser, err := GetSysUserByCtx(c) if err != nil { return nil, err } var storeList []uint32 // 返回sysUser未过期的门店id列表 storeList = GetValidStoreIDs(sysUser.StoreData) if req.StoreId != 0 { if !Contains(storeList, uint32(req.StoreId)) { return nil, errors.New("您没有该门店权限") } } else { if len(storeList) > 0 { if len(storeList) == 1 { qs = qs.Where("store_id = ?", storeList[0]) } else { qs = qs.Where("store_id IN (?)", storeList) } } else { return nil, errors.New("用户未绑定门店") } } } if req.Tel != "" { qs = qs.Where("user.tel", req.Tel) } if req.Uid != 0 { qs = qs.Where("user.uid", req.Uid) } if len(req.OpenMemberLevel) != 0 { qs = qs.Where("user.open_member_level in (?)", req.OpenMemberLevel) } if len(req.MemberLevel) != 0 { qs = qs.Where("user.member_level in (?)", req.MemberLevel) } if req.StoreId != 0 { qs = qs.Where("user.store_id", req.StoreId) } if req.UserType != 0 { qs = qs.Where("user.user_type", req.UserType) } if req.CreateStartTime != "" { parse, err := time.Parse(QueryTimeFormat, req.CreateStartTime) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } qs = qs.Where("user.created_at > ?", parse) } if req.CreateEndTime != "" { parse, err := time.Parse(QueryTimeFormat, req.CreateEndTime) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } qs = qs.Where("user.created_at < ?", parse) } if req.OrderStartTime != "" { parse, err := time.Parse(QueryTimeFormat, req.OrderStartTime) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } qs = qs.Where("user.first_retail_order > ?", parse) } if req.OrderEndTime != "" { parse, err := time.Parse(QueryTimeFormat, req.OrderEndTime) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } qs = qs.Where("user.first_retail_order < ?", parse) } if req.OpenStartTime != "" { parse, err := time.Parse(QueryTimeFormat, req.OpenStartTime) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } qs = qs.Where("user.open_member_time > ?", parse) } if req.OpenEndTime != "" { parse, err := time.Parse(QueryTimeFormat, req.OpenEndTime) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } qs = qs.Where("user.open_member_time < ?", parse) } var count int64 err := qs.Count(&count).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } currentTime := time.Now() // 子查询,查询消费次数和消费金额 //subQuery := fmt.Sprintf(`SELECT uid, COUNT(*) as order_count, SUM(amount) as order_amount // FROM fund_record // WHERE fund_type NOT IN ('deposit_refund', 'express_fee_refund', 'member_expire_delay', 'recycle_card') // GROUP BY uid // HAVING COUNT(uid) > 0`) subQuery := fmt.Sprintf(`SELECT uid, COUNT(*) as order_count, SUM(total_amount) as order_amount FROM erp_order WHERE pay_status = 2 GROUP BY uid HAVING COUNT(uid) > 0`) // 查询用户数据,过期天数,消费次数,消费金额---20240308修改:过期会员等级会自动改成1普通会员,所以这里的范围改成,1,2,3, 4, 5 qs = qs.Select("user.*, COALESCE(fr.order_count, 0) as order_count, COALESCE(fr.order_amount, 0) as "+ "order_amount, COALESCE(uv.vm, 0) as vm, CASE WHEN (user.member_level IN (1, 2, 3, 4, 5) AND user.member_expire < ?) "+ "THEN DATEDIFF(?, user.member_expire) ELSE 0 END AS member_expire_days", currentTime, currentTime). Joins(fmt.Sprintf("LEFT JOIN (%s) fr ON user.uid = fr.uid", subQuery)). Joins("LEFT JOIN user_vm uv ON user.uid = uv.uid") if req.Filter { qs = orm.Eloquent.Table("(?) as a", qs) qs = qs.Select("a.*"). Joins("inner join order_card as oc on a.uid=oc.uid"). Where("pay_status = ? AND card_status IN (?)", HavePaid, []int{1, 2, 3}). Group("oc.uid"). Having("count(oc.uid) > 0") qs = qs.Where("member_expire_days > 0").Where("mark = ?", UNMARK) err = qs.Find(&users).Error if err != nil && err != RecordNotFound { logger.Errorf("err:", logger.Field("err", err)) return nil, err } count = int64(len(users)) users = nil } if req.IsExport == 1 { // 导出excel err = qs.Order(fmt.Sprintf("%s %s", req.SortField, req.SortType)).Find(&users).Error if err != nil && err != RecordNotFound { logger.Errorf("err:", logger.Field("err", err)) return nil, err } } else { err = qs.Order(fmt.Sprintf("%s %s", req.SortField, req.SortType)).Offset(req.PageIndex * req.PageSize).Limit(req.PageSize).Find(&users).Error if err != nil && err != RecordNotFound { logger.Errorf("err:", logger.Field("err", err)) return nil, err } } resp.Total = int(count) //查询卡片 var uids []uint32 for _, u := range users { if u.MemberExpireDays > 0 { uids = append(uids, u.Uid) } } //未归还卡带 cards, err := GetUserExpiredCards(uids) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } // 查询门店信息 storeList := make(map[uint32]Store) storeList = GetStoreMap() for i, u := range users { c, ok := cards[u.Uid] if ok { users[i].OrderCards = c //滞纳金 一个卡带一天2块钱 users[i].ForfeitPenalty = len(c) * 200 * int(users[i].MemberExpireDays) } // 添加门店信息 //users[i].Store, _ = setStore(u.StoreId) store := storeList[uint32(u.StoreId)] users[i].Store = &store // 校验时间,如果为01-01-01 08:05,则赋值为空 validateZeroTime(&users[i].MemberExpire) validateZeroTime(&users[i].OpenMemberTime) validateZeroTime(&users[i].MemberOpenTime) validateZeroTime(&users[i].LastLoginAt) validateZeroTime(&users[i].InviteTime) validateZeroTime(&users[i].FirstRetailOrder) } if req.IsExport == 1 { exportFile, err := newUserListExport(users) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } resp.ExportUrl = exportFile } else { resp.List = users } return resp, nil } // GetUserListByForfeitPenalty 滞纳金排序 func GetUserListByForfeitPenalty(req *NewUserListReq) (*NewUserListResp, error) { resp := &NewUserListResp{ PageIndex: req.PageIndex + 1, PageSize: req.PageSize, } allUsers := make([]U, 0) qs := orm.Eloquent.Model(&UserInfo{}) var count int64 err := qs.Count(&count).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } subQuery := fmt.Sprintf(`SELECT uid, COUNT(*) as order_count, SUM(total_amount) as order_amount FROM erp_order WHERE pay_status = 2 GROUP BY uid HAVING COUNT(uid) > 0`) currentTime := time.Now() // 查询用户数据,过期天数,消费次数,消费金额---20240308修改:过期会员等级会自动改成1普通会员,所以这里的范围改成,1,2,3, 4, 5 qs = qs.Select("user.*, COALESCE(fr.order_count, 0) as order_count, COALESCE(fr.order_amount, 0) as "+ "order_amount, COALESCE(uv.vm, 0) as vm, CASE WHEN (user.member_level IN (1, 2, 3, 4, 5) AND user.member_expire < ?) "+ "THEN DATEDIFF(?, user.member_expire) ELSE 0 END AS member_expire_days", currentTime, currentTime). Joins(fmt.Sprintf("LEFT JOIN (%s) fr ON user.uid = fr.uid", subQuery)). Joins("LEFT JOIN user_vm uv ON user.uid = uv.uid") if req.Filter { qs = orm.Eloquent.Table("(?) as a", qs) qs = qs.Select("a.*"). Joins("inner join order_card as oc on a.uid=oc.uid"). Where("pay_status = ? AND card_status IN (?)", HavePaid, []int{1, 2, 3}). Group("oc.uid"). Having("count(oc.uid) > 0") qs = qs.Where("member_expire_days > 0").Where("mark = ?", UNMARK) err := qs.Find(&allUsers).Error if err != nil && err != RecordNotFound { logger.Errorf("err:", logger.Field("err", err)) return nil, err } count = int64(len(allUsers)) allUsers = nil } err = qs.Find(&allUsers).Error if err != nil && err != RecordNotFound { logger.Errorf("err:", logger.Field("err", err)) return nil, err } // Fetch expired cards for users with positive MemberExpireDays var uids []uint32 for _, u := range allUsers { if u.MemberExpireDays > 0 { uids = append(uids, u.Uid) } } cards, err := GetUserExpiredCards(uids) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } // 查询门店信息 storeList := make(map[uint32]Store) storeList = GetStoreMap() // Calculate forfeit penalty and update user data for i, u := range allUsers { allUsers[i].OrderCards = cards[u.Uid] allUsers[i].ForfeitPenalty = calculateForfeitPenalty(allUsers[i]) store := storeList[uint32(u.StoreId)] allUsers[i].Store = &store // Validate and adjust zero time values validateZeroTime(&allUsers[i].MemberExpire) validateZeroTime(&allUsers[i].OpenMemberTime) validateZeroTime(&allUsers[i].MemberOpenTime) validateZeroTime(&allUsers[i].LastLoginAt) validateZeroTime(&allUsers[i].InviteTime) validateZeroTime(&allUsers[i].FirstRetailOrder) } // Sorting by forfeit penalty sort.Slice(allUsers, func(i, j int) bool { return allUsers[i].ForfeitPenalty < allUsers[j].ForfeitPenalty }) if req.SortType == "DESC" || req.SortType == "desc" { reverseUsers(allUsers) } // Paginate results startIndex := req.PageIndex * req.PageSize endIndex := startIndex + req.PageSize if endIndex > len(allUsers) { endIndex = len(allUsers) } // Slice the users based on pagination pagedUsers := allUsers[startIndex:endIndex] resp.Total = len(allUsers) resp.List = pagedUsers return resp, nil } // Function to calculate forfeit penalty for a user func calculateForfeitPenalty(user U) int { return len(user.OrderCards) * 200 * int(user.MemberExpireDays) } // Function to reverse a slice of users func reverseUsers(users []U) { for i := len(users)/2 - 1; i >= 0; i-- { opp := len(users) - 1 - i users[i], users[opp] = users[opp], users[i] } } // Function to validate and adjust zero time values func validateZeroTime(t **time.Time) { if *t != nil && (*t).IsZero() { *t = nil } } func setStore(storeId uint64) (*Store, error) { storeInfo := new(Store) err := orm.Eloquent.Table("store").Where("id=?", storeId).Find(storeInfo).Error if err != nil && err != RecordNotFound { logger.Error("set store err:", logger.Field("err", err)) return nil, err } return storeInfo, nil } func GetUserList(page, pageSize, uid, memberLevel, storeId, userType, cooperativeBusinessId int, tel, startTime, endTime, nameKey, sortFiled, sortType string, filter bool) ([]U, uint32, uint32, error) { var ( users = make([]U, 0) totalPage uint32 ) fmt.Println("tel:", tel) fmt.Println("nameKey:", nameKey) page -= 1 if page < 0 { page = 0 } if sortFiled == "" { sortFiled = "id" } if sortType == "" { sortType = "DESC" } user := &UserInfo{} qs := orm.Eloquent.Table(user.TableName()).Debug() if tel != "" { qs = qs.Where("tel", tel) } if uid != 0 { qs = qs.Where("uid", uid) } if memberLevel != 0 { qs = qs.Where("member_level", memberLevel) } if storeId != 0 { qs = qs.Where("store_id", storeId) } if userType != 0 { qs = qs.Where("user_type", userType) } if cooperativeBusinessId != 0 { qs = qs.Where("cooperative_business_id=?", cooperativeBusinessId) } if startTime != "" { parse, err := time.Parse(DateTimeFormat, startTime) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return users, 0, 0, err } qs = qs.Where("created_at > ?", parse) } if endTime != "" { parse, err := time.Parse(DateTimeFormat, endTime) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return users, 0, 0, err } qs = qs.Where("created_at < ?", parse) } if nameKey != "" { qs = qs.Where("wx_name LIKE ?", "%"+nameKey+"%") } var count int64 err := qs.Count(&count).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return users, 0, 0, err } currentTime := time.Now() //计算过期天数 qs = qs.Select("*, CASE WHEN (member_level IN (2, 4, 5) AND member_expire < ?) THEN DATEDIFF(?,member_expire) ELSE 0 END AS member_expire_days", currentTime, currentTime) if filter { qs = orm.Eloquent.Table("(?) as a", qs) //qs = qs.Preload("OrderCards", func(db *gorm.DB) *gorm.DB { // return db.Where("pay_status = ? AND card_status IN (?)", 2, []int{1, 2, 3}). // Group("uid"). // Having("count(uid) > 0") //}) qs = qs.Select("a.*"). Joins("inner join order_card as oc on a.uid=oc.uid"). Where("pay_status = ? AND card_status IN (?)", 2, []int{1, 2, 3}). Group("oc.uid"). Having("count(oc.uid) > 0") qs = qs.Where("member_expire_days > 0").Where("mark = ?", UNMARK) } err = qs.Order(fmt.Sprintf("%s %s", sortFiled, sortType)).Offset(page * pageSize).Limit(pageSize).Find(&users).Error if err != nil && err != RecordNotFound { logger.Errorf("err:", logger.Field("err", err)) return users, 0, 0, err } totalPage = uint32(int(count)/pageSize + 1) return users, totalPage, uint32(count), nil } // 导出所有用户excel func newUserListExport(list []U) (string, error) { file := excelize.NewFile() fSheet := "Sheet1" url := config.ExportConfig.Url fileName := time.Now().Format(TimeFormat) + "所有会员" + ".xlsx" fmt.Println("url fileName:", url+fileName) title := []interface{}{"用户ID", "手机号", "所属门店", "消费次数", "消费金额", "注册小程序时间", "首次零售开单时间", "首次开通租卡会员等级", "当前会员等级", "首次开通租卡会员时间", "租卡会员到期时间", "保证金", "租卡会员过期天数", "滞纳金", "未归还卡带名称", "未归还卡带串码"} for i, _ := range title { cell, _ := excelize.CoordinatesToCellName(1+i, 1) err := file.SetCellValue(fSheet, cell, title[i]) if err != nil { logger.Error("file set value err:", logger.Field("err", err)) } } var row []interface{} nExcelStartRow := 0 // 查询门店信息 var storeList []Store err := orm.Eloquent.Table("store").Find(&storeList).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return "", err } storeMap := make(map[uint32]string, 0) for i, _ := range storeList { storeMap[storeList[i].ID] = storeList[i].Name } fmt.Println("storeMap is:", storeMap[13]) for i := 0; i < len(list); i++ { // 未归还卡带名称和串码 var cardNames, cardNums []string var cardNamesResult, cardNumsResult string if list[i].MemberExpireDays > 0 { for _, item := range list[i].OrderCards { // 未归还卡带名称 if item.GameCard != nil { cardNames = append(cardNames, item.GameCard.Name) } // 未归还卡带串码 cardNums = append(cardNums, item.SerialNumber) } if len(cardNames) != 0 { cardNamesResult = strings.Join(cardNames, ",") } if len(cardNums) != 0 { cardNumsResult = strings.Join(cardNums, ",") } } row = []interface{}{ list[i].Uid, // 用户ID list[i].Tel, // 手机号 storeMap[uint32(list[i].StoreId)], // 所属门店 list[i].OrderCount, // 消费次数 list[i].OrderAmount, // 消费金额 tools.ConvertTimeToString(list[i].CreatedAt), // 注册小程序时间 tools.ConvertTimeToStringByPoint(list[i].FirstRetailOrder), // 首次零售开单时间 getMemberLevelChineseDescription(list[i].OpenMemberLevel), // 首次开通租卡会员等级 getMemberLevelChineseDescription(list[i].MemberLevel), // 当前会员等级 tools.ConvertTimeToStringByPoint(list[i].OpenMemberTime), // 首次开通租卡会员时间 tools.ConvertTimeToStringByPoint(list[i].MemberExpire), // 租卡会员到期时间 float32(list[i].Deposit) / 100, // 保证金(数据库存储的是分) list[i].MemberExpireDays, // 租卡会员过期天数 list[i].ForfeitPenalty, // 滞纳金 cardNamesResult, // 未归还卡带名称 cardNumsResult, // 未归还卡带串码 } for j, _ := range row { cell, _ := excelize.CoordinatesToCellName(1+j, nExcelStartRow+2) err := file.SetCellValue(fSheet, cell, row[j]) if err != nil { logger.Error("file set value err:", logger.Field("err", err)) } } nExcelStartRow++ } // 设置所有单元格的样式: 居中、加边框 style, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"}, "border":[{"type":"left","color":"000000","style":1}, {"type":"top","color":"000000","style":1}, {"type":"right","color":"000000","style":1}, {"type":"bottom","color":"000000","style":1}]}`) // 设置单元格的样式: 居中、加边框、自动换行 style1, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center","wrap_text":true}, "border":[{"type":"left","color":"000000","style":1}, {"type":"top","color":"000000","style":1}, {"type":"right","color":"000000","style":1}, {"type":"bottom","color":"000000","style":1}]}`) endRow := fmt.Sprintf("P%d", nExcelStartRow+1) // 应用样式到整个表格 file.SetColWidth("Sheet1", "F", "F", 18) file.SetColWidth("Sheet1", "G", "G", 18) file.SetColWidth("Sheet1", "J", "J", 18) file.SetColWidth("Sheet1", "K", "K", 18) _ = file.SetCellStyle("Sheet1", "A1", "P1", style1) _ = file.SetCellStyle("Sheet1", "A2", endRow, style) fmt.Println("save fileName:", config.ExportConfig.Path+fileName) if err := file.SaveAs(config.ExportConfig.Path + fileName); err != nil { fmt.Println(err) } return url + fileName, nil } type CommonProblem struct { Model Question string `json:"question"` Answer string `json:"answer" gorm:"type:text"` Sort uint32 `json:"sort" gorm:"index"` } func (*CommonProblem) TableName() string { return "common_problem" } type GroupSendMessageTemplate struct { Model Title string `json:"title" ` Message string `json:"message"` UserType uint32 `json:"user_type" gorm:"index,column:user_type"` // 1-所有用户 2-会员 3-非会员 4-指定用户 SendTime time.Time `json:"send_time"` Tels string `json:"tels"` Status uint32 `json:"status"` // 1-待发送 2-已发送 } func (*GroupSendMessageTemplate) TableName() string { return "group_send_message_template" } type ExpireMemberSmsSend struct { Model Message string `json:"message"` SendTime time.Time `json:"send_time"` Tel string `json:"tel" gorm:"index"` Status uint32 `json:"status"` // 1-发送成功 2-发送失败 } func GetUserInfoMap(uids []uint32) (map[uint32]UserInfo, error) { userInfoMap := make(map[uint32]UserInfo, 0) if len(uids) == 0 { return userInfoMap, nil } var userInfos []UserInfo err := orm.Eloquent.Table("user").Where("uid in (?)", uids).Find(&userInfos).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return userInfoMap, err } for i, _ := range userInfos { userInfoMap[userInfos[i].Uid] = userInfos[i] } return userInfoMap, nil } func (m *CommonProblem) List() ([]CommonProblem, error) { commons := make([]CommonProblem, 0) err := orm.Eloquent.Table("common_problem").Order("sort desc").Find(&commons).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return commons, err } return commons, nil } func (m *CommonProblem) Add() error { err := orm.Eloquent.Table("common_problem").Create(m).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return err } return nil } func (m *CommonProblem) Modify() error { err := orm.Eloquent.Table("common_problem").Save(m).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return err } return nil } func (m *CommonProblem) Del() error { err := orm.Eloquent.Table("common_problem").Where("id", m.ID).Delete(m).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return err } return nil } type UserAddress struct { Model Uid uint32 `json:"uid" gorm:"index"` ReceiverName string `json:"receiver_name"` Tel string `json:"tel" gorm:"type:varchar(20)"` Province string `json:"province" gorm:"type:varchar(100)"` City string `json:"city" gorm:"type:varchar(100)"` District string `json:"district" gorm:"type:varchar(100)"` Address string `json:"address" gorm:"type:varchar(100)"` State uint8 `json:"state"` IsDefault uint8 `json:"is_default"` } func (m *UserAddress) TableName() string { return `user_address` } // gen:qs //type InviteMemberReport struct { // Model // Uid uint32 `json:"uid" gorm:"index"` // StoreId uint32 `json:"store_id" gorm:"index"` // 门店id // GoldCount uint32 `json:"gold_count"` // 黄金数量 // PlatinumCount uint32 `json:"platinum_count"` // 白金数量 // BlackGoldCount uint32 `json:"black_gold_count"` // 黑金数量 // Date string `json:"date" gorm:"index"` // 业绩时间 // DeductAmount uint32 `json:"deduct_amount"` // 店员提成 // CooperativeBusinessId uint32 `json:"cooperative_business_id" gorm:"index"` // 合作商id // CooperativeName string `json:"cooperative_name"` // 合作商名称 // GoldDeduct uint32 `json:"gold_deduct"` // 黄金会员提成 // PlatinumDeduct uint32 `json:"platinum_deduct"` // 白金会员提成 // BlackGoldDeduct uint32 `json:"black_gold_deduct"` // 黑金会员提成 // UserInfo *UserInfo `json:"user_info" gorm:"-"` // 用户 // Store *Store `json:"store" gorm:"-"` // 门店 // // ReportTime string `json:"report_time" gorm:"index"` // 业绩时间 // // invite_member_report //} type InviteMemberReport struct { Model Uid uint32 `json:"uid" gorm:"index"` // 店员uid StoreId uint32 `json:"store_id" gorm:"index"` // 门店id GoldCount uint32 `json:"gold_count"` // 黄金数量 GoldCountHalf uint32 `json:"gold_count_half"` // 半年黄金数量 GoldCountQuarter uint32 `json:"gold_count_quarter"` // 季度黄金数量 PlatinumCount uint32 `json:"platinum_count"` // 白金数量 BlackGoldCount uint32 `json:"black_gold_count"` // 黑金数量 PrivilegeCount uint32 `json:"privilege_count"` // 尊享会员数量 //ReportTime string `json:"report_time" gorm:"index"` // 业绩时间 Date string `json:"date" gorm:"index"` // 业绩时间 DeductAmount uint32 `json:"deduct_amount"` // 店员提成 CooperativeBusinessId uint32 `json:"cooperative_business_id" gorm:"index"` // 合作商id CooperativeName string `json:"cooperative_name"` // 合作商名称 GoldDeduct uint32 `json:"gold_deduct"` // 黄金会员提成 PlatinumDeduct uint32 `json:"platinum_deduct"` // 白金会员提成 BlackGoldDeduct uint32 `json:"black_gold_deduct"` // 黑金会员提成 RenewalGoldCount uint32 `json:"renewal_gold_count"` // 续费年度黄金会员数量(自动) RenewalGoldCountHalf uint32 `json:"renewal_gold_count_half"` // 续费半年黄金会员数量(自动) RenewalGoldCountQuarter uint32 `json:"renewal_gold_count_quarter"` // 续费季度黄金会员数量(自动) RenewalPlatinumCount uint32 `json:"renewal_platinum_count"` // 续费白金会员数量(自动) RenewalBlackGoldCount uint32 `json:"renewal_black_gold_count"` // 续费黑金会员数量(自动) RenewalPrivilegeCount uint32 `json:"renewal_privilege_count"` // 续费尊享会员数量 UpgradeGoldToPlatinumCount uint32 `json:"upgrade_gold_to_platinum_count" gorm:"default:0"` // 升级:黄金->白金数量(自动) UpgradeGoldToBlackCount uint32 `json:"upgrade_gold_to_black_count" gorm:"default:0"` // 升级:黄金->黑金数量(自动) UpgradePlatinumToBlackCount uint32 `json:"upgrade_platinum_to_black_count" gorm:"default:0"` // 升级:白金->黑金数量(自动) InviteRenewalGoldCount uint32 `json:"invite_renewal_gold_count"` // 续费黄金会员数量(干预) InviteRenewalPlatinumCount uint32 `json:"invite_renewal_platinum_count"` // 续费白金会员数量(干预) InviteRenewalBlackGoldCount uint32 `json:"invite_renewal_black_gold_count"` // 续费黑金会员数量(干预) InviteUpgradeGoldToPlatinumCount uint32 `json:"invite_upgrade_gold_to_platinum_count" gorm:"default:0"` // 升级:黄金->白金数量(干预) InviteUpgradeGoldToBlackCount uint32 `json:"invite_upgrade_gold_to_black_count" gorm:"default:0"` // 升级:黄金->黑金数量(干预) InviteUpgradePlatinumToBlackCount uint32 `json:"invite_upgrade_platinum_to_black_count" gorm:"default:0"` // 升级:白金->黑金数量(干预) // invite_member_report SystemUser *SysUser `json:"system_user" gorm:"-"` // 系统用户 //User *UserInfo `json:"user" gorm:"-"` // //Store *Store `json:"store" gorm:"-"` // 门店 } type UserInviteListReq struct { //StoreId uint32 `json:"store_id"` // 门店id Uid uint32 `json:"uid"` // 用户id Page int `json:"pageIndex"` PageSize int `json:"pageSize"` MemberType int `json:"memberType"` // 0-全部 1-普通用户 2-会员 StartTime string `json:"startTime"` // 开始时间 EndTime string `json:"endTime"` // 结束时间 } func (m *UserInfo) InitUserInvite(invite UserInvite) { m.MemberOpenTime = &invite.MemberOpenTime m.MemberStatus = invite.MemberStatus m.InviteTime = &invite.CreatedAt m.MemberLevel = invite.MemberLevel } func (m *UserInviteListReq) InviteList() ([]UserInfo, int, error) { var ( users = make([]UserInfo, 0) totalPage uint32 page = m.Page - 1 pageSize = m.PageSize ) if page < 0 { page = 0 } if pageSize == 0 { pageSize = 10 } //user := &UserInfo{} //UserInvite{} var userInvites []UserInvite qs := orm.Eloquent.Table("user_invite").Where("from_uid", m.Uid) if m.MemberType != 0 { qs = qs.Where("member_type=?", m.MemberType) } if m.StartTime != "" { parse, err := time.Parse(DateTimeFormat, m.StartTime) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return users, 0, err } if m.MemberType == 2 { qs = qs.Where("member_open_time > ?", parse) } else { qs = qs.Where("created_at > ?", parse) } } if m.EndTime != "" { parse, err := time.Parse(DateTimeFormat, m.EndTime) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return users, 0, err } parse = parse.AddDate(0, 0, 1) if m.MemberType == 2 { qs = qs.Where("member_open_time < ?", parse) } else { qs = qs.Where("created_at < ?", parse) } } var count int64 err := qs.Count(&count).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return users, 0, err } err = qs.Order("id DESC").Offset(page * pageSize).Limit(pageSize).Find(&userInvites).Error if err != nil && err != RecordNotFound { logger.Errorf("err:", logger.Field("err", err)) return users, 0, err } totalPage = uint32(int(count)/pageSize + 1) uids := make([]uint32, 0) userInviteMap := make(map[uint32]UserInvite, 0) for i, _ := range userInvites { uids = append(uids, userInvites[i].ToUid) userInviteMap[userInvites[i].ToUid] = userInvites[i] } err = orm.Eloquent.Table("user").Debug().Where("uid in (?)", uids).Find(&users).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return users, 0, err } fmt.Println("totalPage", totalPage) userMap := make(map[uint32]UserInfo, 0) for i, _ := range users { userMap[users[i].Uid] = users[i] } list := make([]UserInfo, 0, len(users)) for i, _ := range uids { invite, ok1 := userInviteMap[uids[i]] if !ok1 { continue } userInfo, ok2 := userMap[uids[i]] if !ok2 { continue } userInfo.InitUserInvite(invite) list = append(list, userInfo) } return list, int(count), nil } type UserInviteMember struct { FromUserInfo UserInfo ToUserInfo UserInfo Store Store UserInvite UserInviteRecord UserInviteRecord } func MemberLevelToString(memberLevel uint32) string { switch memberLevel { case 2: return "黄金会员" case 4: return "白金会员" case 5: return "黑金会员" } return "" } func ExportUserMember(storeId uint32, startTime, endTime string) string { var userInvites []UserInvite qs := orm.Eloquent.Table("invite") if storeId != 0 { qs = qs.Where("store_id", storeId) } if startTime != "" { parse, err := time.Parse(DateTimeFormat, startTime) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return "" } qs = qs.Where("member_open_time > ?", parse) } if endTime != "" { parse, err := time.Parse(DateTimeFormat, endTime) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return "" } parse = parse.AddDate(0, 0, 1) qs = qs.Where("member_open_time < ?", parse) } err := qs.Order("id DESC,store_id DESC,from_uid DESC").Find(&userInvites).Error if err != nil && err != RecordNotFound { logger.Errorf("err:", logger.Field("err", err)) return "" } storeIds := make([]uint64, 0) fromUids := make([]uint32, 0) toUids := make([]uint32, 0) for i, _ := range userInvites { storeIds = append(storeIds, userInvites[i].StoreId) fromUids = append(fromUids, userInvites[i].FromUid) toUids = append(toUids, userInvites[i].ToUid) } var stores []Store err = orm.Eloquent.Table("store").Where("id in (?)", storeIds).Find(&stores).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return "" } storeMap := make(map[uint32]Store) for i, _ := range stores { storeMap[stores[i].ID] = stores[i] } fromUids = append(fromUids, toUids...) var userInfos []UserInfo err = orm.Eloquent.Table("user").Where("uid in (?)", fromUids).Find(&userInfos).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return "" } userInfoMap := make(map[uint32]UserInfo, 0) for i, _ := range userInfos { userInfoMap[userInfos[i].Uid] = userInfos[i] } inviteMembers := make([]UserInviteMember, 0, len(userInvites)) for i, _ := range userInvites { fromUser, _ := userInfoMap[userInvites[i].FromUid] toUser, ok2 := userInfoMap[userInvites[i].ToUid] if !ok2 { continue } store, ok1 := storeMap[uint32(userInvites[i].StoreId)] if !ok1 { store = storeMap[uint32(toUser.StoreId)] } invite := UserInviteMember{ FromUserInfo: fromUser, Store: store, ToUserInfo: toUser, UserInvite: userInvites[i], } inviteMembers = append(inviteMembers, invite) } fileName := "邀请会员" if storeId == 0 { fileName = "全部门店邀请会员" } else { if len(stores) > 0 { fileName = stores[0].Name } } //url := "http://switch.deovo.com:8000/img/export/" //url := "http://39.108.188.218:8000/img/export/" //fileName = fileName + time.Now().Format("2006-01-02 15:04:05") + ".csv" //f, err := os.OpenFile(fmt.Sprintf("./")+fileName, os.O_CREATE|os.O_TRUNC|os.O_APPEND|os.O_RDWR, 0644) f, err := os.OpenFile(fmt.Sprintf("/www/server/images/export/")+fileName, os.O_CREATE|os.O_TRUNC|os.O_APPEND|os.O_RDWR, 0644) if err != nil { fmt.Println(err) return fileName } defer f.Close() w := csv.NewWriter(f) //headline := []string{"门店名称", "店员id", "店员昵称","姓名", "会员id", "会员昵称", "注册会员时间", "会员状态"} headline := []string{"门店名称", "店员id", "姓名", "会员id", "会员昵称", "会员等级", "会员手机号", "注册会员时间", "会员状态"} if err := w.Write(headline); err != nil { log.Fatalln("error writing record to csv:", logger.Field("err", err)) } for _, invite := range inviteMembers { //fmt.Println("MemberOpenTime",invite.UserInvite.MemberOpenTime) //fmt.Println("MemberOpenTime",invite.UserInvite.MemberOpenTime.Format("2006-01-02 15:04:05")) record := []string{invite.Store.Name, fmt.Sprintf("%d", invite.FromUserInfo.Uid), invite.FromUserInfo.ShopAssistantName, fmt.Sprintf("%d", invite.ToUserInfo.Uid), invite.ToUserInfo.WxName, MemberLevelToString(invite.UserInvite.MemberLevel), invite.ToUserInfo.Tel, invite.UserInvite.MemberOpenTime.Format("2006-01-02 15:04:05"), GetUserInviteStatus(invite.MemberStatus)} if err := w.Write(record); err != nil { log.Fatalln("error writing record to csv:", logger.Field("err", err)) } } w.Flush() if err := w.Error(); err != nil { log.Fatal(err) } return config.ExportConfig.Url + fileName } // gen:qs type UserInviteRecord struct { Model ToUid uint32 `json:"to_uid"` // 用户ID FromUid uint32 `json:"from_uid"` // 邀请人ID StoreId uint64 `json:"store_id"` // 门店id 邀请用户门店 Action uint32 `json:"action"` // 1-未激活 2-激活邀请 SpendType uint32 `json:"spend_type"` // 1-未开通 2-开通会员 3-续费 4-升级 MemberLevel uint32 `json:"member_level"` // 会员等级 0-未开通 1-普通 2-黄金 3-短期 4-白金 5-黑金 6-尊享会员 MemberGenre uint32 `json:"member_genre"` // 会员类型 200-黄金年费 201-黄金季度 202-黄金半年 First uint32 `json:"first"` // 首次 Scan uint32 `json:"scan"` // 扫码 ActionTime time.Time `json:"action_time"` // 激活时间 RenewHide uint32 `json:"renew_hide"` // 自动续费 1-自动 0-干预 ShopAssistantName string `json:"shop_assistant_name" gorm:"-"` // 店员名称 // user_invite_record } type UserInviteRecordReq struct { PageNum int `json:"pageIndex"` PageSize int `json:"pageSize"` MemberType int `json:"member_type"` // 1-首次邀请 2-开通黄金 3-开通白金 4-开通黑金 5-续费黄金 6-续费白金 7-续费黑金 FromUid uint32 `json:"from_uid"` ToUid uint32 `json:"to_uid"` StartTime time.Time `json:"startTime"` // 开始时间 EndTime time.Time `json:"endTime"` // 结束时间 } func (m *UserInviteRecordReq) List() ([]UserInviteRecord, int64, error) { var records []UserInviteRecord err := UpdateUserInviteRecordRenewHide() if err != nil { logger.Errorf("err:", logger.Field("err", err)) return records, 0, err } page := m.PageNum - 1 pageSize := m.PageSize if page < 0 { page = 0 } if pageSize == 0 { pageSize = 10 } qs := orm.Eloquent.Table("user_invite_record").Where("action=2").Where("renew_hide!=1") //qs := orm.Eloquent.Table("user_invite_record") if m.MemberType != 0 { switch m.MemberType { case 1: // 首次邀请 qs = qs.Where("first=1").Where("spend_type=1") case 2: // 开通年费黄金 qs = qs.Where("member_level=2").Where("spend_type=2") case 3: // 开通年费白金 qs = qs.Where("member_level=4").Where("spend_type=2") case 4: // 开通年费黑金 qs = qs.Where("member_level=5").Where("spend_type=2") case 5: // 续费年费黄金 qs = qs.Where("member_level=2").Where("spend_type=3") case 6: // 续费年费白金 qs = qs.Where("member_level=4").Where("spend_type=3") case 7: // 续费年费黑金 qs = qs.Where("member_level=5").Where("spend_type=3") } } if m.FromUid != 0 { qs = qs.Where("from_uid=?", m.FromUid) } if m.ToUid != 0 { qs = qs.Where("to_uid=?", m.ToUid) } if !m.StartTime.IsZero() { //qs = qs.Where("created_at > ?", m.StartTime) qs = qs.Where("action_time > ?", m.StartTime) } if !m.EndTime.IsZero() { //qs = qs.Where("created_at < ?", m.EndTime) qs = qs.Where("action_time < ?", m.EndTime) } var count int64 err = qs.Count(&count).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return records, 0, err } err = qs.Order("action_time DESC").Offset(page * pageSize).Limit(pageSize).Find(&records).Error if err != nil && err != RecordNotFound { logger.Errorf("err:", logger.Field("err", err)) return records, 0, err } return records, count, nil } type NewUserInviteRecordReq struct { PageNum int `json:"pageIndex"` PageSize int `json:"pageSize"` StoreId uint32 `json:"store_id"` // 邀请人所属门店id InviteUserName string `json:"invite_user_name"` // 邀请人昵称 FromUid uint32 `json:"from_uid"` // 邀请人ID ToUid uint32 `json:"to_uid"` // 用户ID UserTel string `json:"user_tel"` // 用户手机号 CreateStartTime time.Time `json:"create_start_time"` // 注册小程序时间-开始时间 CreateEndTime time.Time `json:"create_end_time"` // 注册小程序时间-结束时间 RecordType []uint32 `json:"record_type"` // 记录类型 1-首次邀请,2-开通年费黄金,3-开通季度黄金,4-开通半年黄金, 5-开通年费白金,6-开通年费黑金,7-续费年费黄金(干预),8-续费年费白金(干预),9-续费年费黑金(干预),10-续费年费黄金(自动), 11-续费季度黄金(自动),12-续费半年黄金(自动),13-续费年费白金(自动),14-续费年费黑金(自动),15-黄金→白金(干预), 16-黄金→黑金(干预),17-白金→黑金(干预),18-黄金→白金(自动),19-黄金→黑金(自动),20-白金→黑金(自动),21-开通尊享会员, 22-续费尊享会员 RecordStartTime time.Time `json:"record_start_time"` // 记录时间-开始时间 RecordEndTime time.Time `json:"record_end_time"` // 记录时间-结束时间 MemberLevel uint32 `json:"member_level"` // 当前类型:10-普通用户 1-普通会员 2-黄金会员 4-白金会员 5-黑金会员 IsExport uint32 `json:"is_export"` // 1-导出 } type UserInviteRecordListResp struct { List []UserInviteRecordListData `json:"list"` Total int64 `json:"total"` // 总条数 PageIndex int `json:"pageIndex"` // 页码 PageSize int `json:"pageSize"` // 每页展示条数 ExportUrl string `json:"export_url"` // 导出excel地址 } type UserInviteRecordListData struct { StoreId uint32 `json:"store_id"` // 邀请人所属门店id StoreName string `json:"store_name"` // 邀请人所属门店名称 InviteUserName string `json:"invite_user_name"` // 邀请人昵称 InviteUid uint32 `json:"invite_uid"` // 邀请人ID UserUid uint32 `json:"user_uid"` // 用户ID UserTel string `json:"user_tel"` // 用户手机号 CreateTime time.Time `json:"create_time"` // 注册小程序时间 RecordType uint32 `json:"record_type"` // 记录类型 RecordTime time.Time `json:"record_time"` // 记录时间 MemberLevel uint32 `json:"member_level"` // 当前租卡会员类型:1-普通 2-黄金 4-白金 5-黑金 MemberExpire time.Time `json:"memberExpire"` // 租卡会员到期时间 PrivilegeMemberLevel uint32 `json:"privilege_member_level"` // 当前尊享会员类型:1-普通 6-尊享会员 PrivilegeMemberExpire time.Time `json:"privilege_memberExpire"` // 尊享会员到期时间 } func (m *NewUserInviteRecordReq) NewList(c *gin.Context) (*UserInviteRecordListResp, error) { resp := new(UserInviteRecordListResp) var records []struct { UserInviteRecord StoreId uint32 InviteUserName string UserTel string CreateTime time.Time MemberExpire time.Time UserMemberLevel uint32 PrivilegeMemberExpire time.Time PrivilegeMemberLevel uint32 } err := UpdateUserInviteRecordRenewHide() if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } // 查询门店信息 var storeList []Store err = orm.Eloquent.Table("store").Find(&storeList).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } storeMap := make(map[uint32]string, 0) for i, _ := range storeList { storeMap[storeList[i].ID] = storeList[i].Name } fmt.Println("storeMap is:", storeMap[13]) page := m.PageNum - 1 pageSize := m.PageSize if page < 0 { page = 0 } if pageSize == 0 { pageSize = 10 } qs := orm.Eloquent.Table("user_invite_record").Where("action=2") countQuery := orm.Eloquent.Table("user_invite_record").Where("action=2"). Select("user_invite_record.*, B1.nick_name AS InviteUserName, " + "B2.tel AS UserTel, B2.created_at AS CreateTime, B2.member_expire AS MemberExpire, B2.member_level AS UserMemberLevel, " + "B3.member_expire AS PrivilegeMemberExpire, B3.member_level AS PrivilegeMemberLevel"). Joins("Left JOIN sys_user B1 ON user_invite_record.from_uid = B1.uid and B1.uid != 0"). Joins("Left JOIN user B2 ON user_invite_record.to_uid = B2.uid"). Joins("Left JOIN privilege_member B3 ON user_invite_record.to_uid = B3.uid"). Group("user_invite_record.id"). Order("MAX(user_invite_record.action_time) DESC") // 非管理员才判断所属门店 if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") { sysUser, err := GetSysUserByCtx(c) if err != nil { return nil, err } // 返回sysUser未过期的门店id列表 validStoreList := GetValidStoreIDs(sysUser.StoreData) if m.StoreId != 0 { if !Contains(validStoreList, m.StoreId) { return nil, errors.New("您没有该门店权限") } } else { if len(validStoreList) > 0 { if len(validStoreList) == 1 { qs = qs.Where("user_invite_record.store_id = ?", validStoreList[0]) countQuery = countQuery.Where("user_invite_record.store_id = ?", validStoreList[0]) } else { qs = qs.Where("user_invite_record.store_id IN (?)", validStoreList) countQuery = countQuery.Where("user_invite_record.store_id IN (?)", validStoreList) } } else { return nil, errors.New("用户未绑定门店") } } } if m.StoreId != 0 { qs = qs.Where("user_invite_record.store_id=?", m.StoreId) countQuery = countQuery.Where("user_invite_record.store_id=?", m.StoreId) } if m.InviteUserName != "" { qs = qs.Where("B1.nick_name=?", m.InviteUserName) countQuery = countQuery.Where("B1.nick_name=?", m.InviteUserName) } if m.FromUid != 0 { qs = qs.Where("user_invite_record.from_uid=?", m.FromUid) countQuery = countQuery.Where("user_invite_record.from_uid=?", m.FromUid) } if m.ToUid != 0 { qs = qs.Where("user_invite_record.to_uid=?", m.ToUid) countQuery = countQuery.Where("user_invite_record.to_uid=?", m.ToUid) } if m.UserTel != "" { qs = qs.Where("B2.tel=?", m.UserTel) countQuery = countQuery.Where("B2.tel=?", m.UserTel) } if !m.CreateStartTime.IsZero() { qs = qs.Where("B2.created_at > ?", m.CreateStartTime) countQuery = countQuery.Where("B2.created_at > ?", m.CreateStartTime) } if !m.CreateEndTime.IsZero() { qs = qs.Where("B2.created_at < ?", m.CreateEndTime) countQuery = countQuery.Where("B2.created_at < ?", m.CreateEndTime) } if len(m.RecordType) != 0 { var recordTypeConditions []string for _, t := range m.RecordType { switch t { case 1: // 首次邀请 recordTypeConditions = append(recordTypeConditions, "(first=1 AND spend_type=1)") case 2: // 开通年费黄金 recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=2 AND spend_type=2)") case 3: // 开通季度黄金 recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=2 AND spend_type=2 AND user_invite_record.member_genre=201)") case 4: // 开通半年黄金 recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=2 AND spend_type=2 AND user_invite_record.member_genre=202)") case 5: // 开通年费白金 recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=4 AND spend_type=2)") case 6: // 开通年费黑金 recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=5 AND spend_type=2)") case 7: // 续费年费黄金(干预) recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=2 AND spend_type=3 AND renew_hide=0)") case 8: // 续费年费白金(干预) recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=4 AND spend_type=3 AND renew_hide=0)") case 9: // 续费年费黑金(干预) recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=5 AND spend_type=3 AND renew_hide=0)") case 10: // 续费年费黄金(自动) recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=2 AND spend_type=3 AND renew_hide=1)") case 11: // 续费季度黄金(自动) recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=2 AND spend_type=3 AND renew_hide=1 AND user_invite_record.member_genre=201)") case 12: // 续费半年黄金(自动) recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=2 AND spend_type=3 AND renew_hide=1 AND user_invite_record.member_genre=202)") case 13: // 续费年费白金(自动) recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=4 AND spend_type=3 AND renew_hide=1)") case 14: // 续费年费黑金(自动) recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=5 AND spend_type=3 AND renew_hide=1)") case 15: // 黄金→白金(干预) recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=4 AND spend_type=4 AND renew_hide=0)") case 16: // 黄金→黑金(干预) recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=5 AND spend_type=4 AND renew_hide=0 AND user_invite_record.member_genre in (200,201,202))") case 17: // 白金→黑金(干预) recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=5 AND spend_type=4 AND renew_hide=0 AND user_invite_record.member_genre not in (200,201,202))") case 18: // 黄金→白金(自动) recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=4 AND spend_type=4 AND renew_hide=1)") case 19: // 黄金→黑金(自动) recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=5 AND spend_type=4 AND renew_hide=1 AND user_invite_record.member_genre in (200,201,202))") case 20: // 白金→黑金(自动) recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=5 AND spend_type=4 AND renew_hide=1 AND user_invite_record.member_genre not in (200,201,202))") case 21: // 开通年费尊享会员 recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=6 AND spend_type=2)") case 22: // 续费年费尊享会员(自动) recordTypeConditions = append(recordTypeConditions, "(user_invite_record.member_level=6 AND spend_type=3 AND renew_hide=1)") } } // 拼接多选条件 if len(recordTypeConditions) > 0 { recordTypeQuery := strings.Join(recordTypeConditions, " OR ") qs = qs.Where(recordTypeQuery) countQuery = countQuery.Where(recordTypeQuery) } } if !m.RecordStartTime.IsZero() { qs = qs.Where("user_invite_record.action_time > ?", m.RecordStartTime) countQuery = countQuery.Where("user_invite_record.action_time > ?", m.RecordStartTime) } if !m.RecordEndTime.IsZero() { qs = qs.Where("user_invite_record.action_time < ?", m.RecordEndTime) countQuery = countQuery.Where("user_invite_record.action_time < ?", m.RecordEndTime) } if m.MemberLevel != 0 { qs = qs.Where("B2.member_level = ?", m.MemberLevel) countQuery = countQuery.Where("B2.member_level = ?", m.MemberLevel) } var count int64 err = countQuery.Count(&count).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } if m.IsExport == 1 { // 导出excel err = qs.Select("user_invite_record.*, B1.nick_name AS InviteUserName, " + "B2.tel AS UserTel, B2.created_at AS CreateTime, B2.member_expire AS MemberExpire, B2.member_level AS UserMemberLevel, " + "B3.member_expire AS PrivilegeMemberExpire, B3.member_level AS PrivilegeMemberLevel"). Joins("Left JOIN sys_user B1 ON user_invite_record.from_uid = B1.uid and B1.uid != 0"). Joins("Left JOIN user B2 ON user_invite_record.to_uid = B2.uid"). Joins("Left JOIN privilege_member B3 ON user_invite_record.to_uid = B3.uid"). Group("user_invite_record.id"). Order("MAX(user_invite_record.action_time) DESC"). Find(&records).Error if err != nil && err != RecordNotFound { logger.Errorf("err:", logger.Field("err", err)) return nil, err } } else { err = qs.Select("user_invite_record.*, B1.nick_name AS InviteUserName, " + "B2.tel AS UserTel, B2.created_at AS CreateTime, B2.member_expire AS MemberExpire, B2.member_level AS UserMemberLevel, " + "B3.member_expire AS PrivilegeMemberExpire, B3.member_level AS PrivilegeMemberLevel"). Joins("Left JOIN sys_user B1 ON user_invite_record.from_uid = B1.uid and B1.uid != 0"). Joins("Left JOIN user B2 ON user_invite_record.to_uid = B2.uid"). Joins("Left JOIN privilege_member B3 ON user_invite_record.to_uid = B3.uid"). Group("user_invite_record.id"). Order("MAX(user_invite_record.action_time) DESC"). Offset(page * pageSize). Limit(pageSize). Find(&records).Error if err != nil && err != RecordNotFound { logger.Errorf("err:", logger.Field("err", err)) return nil, err } } var listData []UserInviteRecordListData for _, item := range records { data := UserInviteRecordListData{ StoreId: item.StoreId, StoreName: storeMap[item.StoreId], InviteUserName: item.InviteUserName, InviteUid: item.FromUid, UserUid: item.ToUid, UserTel: item.UserTel, CreateTime: item.CreateTime, RecordType: uint32(CalculateMemberType(item.SpendType, item.RenewHide, item.MemberGenre, item.MemberLevel)), RecordTime: item.ActionTime, MemberLevel: item.UserMemberLevel, MemberExpire: item.MemberExpire, PrivilegeMemberLevel: item.PrivilegeMemberLevel, PrivilegeMemberExpire: item.PrivilegeMemberExpire, } if item.FromUid == 0 { data.InviteUserName = "" } listData = append(listData, data) } if m.IsExport == 1 { fileName, err := userInviteRecordExport(listData) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } resp.ExportUrl = fileName } else { resp.List = listData resp.PageIndex = m.PageNum resp.PageSize = m.PageSize resp.Total = count } return resp, nil } // getMemberTypeChineseDescription 根据整数参数返回对应中文描述 func getMemberTypeChineseDescription(memberType MemberType) string { switch memberType { case FirstInvite: return "首次邀请" case OpenAnnualGold: return "开通年费黄金" case OpenQuarterGold: return "开通季度黄金" case OpenHalfYearGold: return "开通半年黄金" case OpenAnnualPlatinum: return "开通年费白金" case OpenAnnualBlack: return "开通年费黑金" case RenewAnnualGoldIntervene: return "续费年费黄金(干预)" case RenewAnnualPlatinumIntervene: return "续费年费白金(干预)" case RenewAnnualBlackIntervene: return "续费年费黑金(干预)" case RenewAnnualGoldAuto: return "续费年费黄金(自动)" case RenewQuarterGoldAuto: return "续费季度黄金(自动)" case RenewHalfYearGoldAuto: return "续费半年黄金(自动)" case RenewAnnualPlatinumAuto: return "续费年费白金(自动)" case RenewAnnualBlackAuto: return "续费年费黑金(自动)" case UpgradeGoldToPlatinumIntervene: return "黄金→白金(干预)" case UpgradeGoldToBlackIntervene: return "黄金→黑金(干预)" case UpgradePlatinumToBlackIntervene: return "白金→黑金(干预)" case UpgradeGoldToPlatinumAuto: return "黄金→白金(自动)" case UpgradeGoldToBlackAuto: return "黄金→黑金(自动)" case UpgradePlatinumToBlackAuto: return "白金→黑金(自动)" default: return "" } } // getMemberLevelChineseDescription 根据整数参数返回对应中文描述 func getMemberLevelChineseDescription(memberLevel uint32) string { switch memberLevel { case 1: return "普通会员" case 2, 3: return "黄金会员" case 4: return "白金会员" case 5: return "黑金会员" case 6: return "尊享会员" } return "" } // 导出会员邀请记录excel func userInviteRecordExport(list []UserInviteRecordListData) (string, error) { file := excelize.NewFile() fSheet := "Sheet1" url := config.ExportConfig.Url fileName := time.Now().Format(TimeFormat) + "会员邀请记录" + ".xlsx" fmt.Println("url fileName:", url+fileName) title := []interface{}{"邀请人所属门店", "邀请人昵称", "邀请人ID", "用户ID", "手机号", "注册小程序时间", "记录类型", "记录时间", "当前类型", "租卡会员到期时间"} for i, _ := range title { cell, _ := excelize.CoordinatesToCellName(1+i, 1) err := file.SetCellValue(fSheet, cell, title[i]) if err != nil { logger.Error("file set value err:", logger.Field("err", err)) } } var row []interface{} nExcelStartRow := 0 for i := 0; i < len(list); i++ { row = []interface{}{ list[i].StoreName, // 邀请人所属门店 list[i].InviteUserName, // 邀请人昵称 list[i].InviteUid, // 邀请人ID list[i].UserUid, // 用户ID list[i].UserTel, // 手机号 tools.ConvertTimeToString(list[i].CreateTime), // 注册小程序时间 getMemberTypeChineseDescription(MemberType(list[i].RecordType)), // 记录类型 tools.ConvertTimeToString(list[i].RecordTime), // 记录时间 getMemberLevelChineseDescription(list[i].MemberLevel), // 当前类型 tools.ConvertTimeToString(list[i].MemberExpire), // 租卡会员到期时间 } for j, _ := range row { cell, _ := excelize.CoordinatesToCellName(1+j, nExcelStartRow+2) err := file.SetCellValue(fSheet, cell, row[j]) if err != nil { logger.Error("file set value err:", logger.Field("err", err)) } } nExcelStartRow++ } // 设置所有单元格的样式: 居中、加边框 style, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"}, "border":[{"type":"left","color":"000000","style":1}, {"type":"top","color":"000000","style":1}, {"type":"right","color":"000000","style":1}, {"type":"bottom","color":"000000","style":1}]}`) // 设置单元格的样式: 居中、加边框、自动换行 style1, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center","wrap_text":true}, "border":[{"type":"left","color":"000000","style":1}, {"type":"top","color":"000000","style":1}, {"type":"right","color":"000000","style":1}, {"type":"bottom","color":"000000","style":1}]}`) endRow := fmt.Sprintf("J%d", nExcelStartRow+1) // 设置单元格大小 file.SetColWidth("Sheet1", "A", "A", 30) file.SetColWidth("Sheet1", "B", "B", 12) file.SetColWidth("Sheet1", "E", "E", 15) file.SetColWidth("Sheet1", "F", "F", 20) file.SetColWidth("Sheet1", "G", "G", 20) file.SetColWidth("Sheet1", "H", "H", 20) file.SetColWidth("Sheet1", "J", "J", 20) // 应用样式到整个表格 _ = file.SetCellStyle("Sheet1", "A1", "J1", style1) _ = file.SetCellStyle("Sheet1", "A2", endRow, style) fmt.Println("save fileName:", config.ExportConfig.Path+fileName) if err := file.SaveAs(config.ExportConfig.Path + fileName); err != nil { fmt.Println(err) } return url + fileName, nil } // CalculateMemberType 匹配记录类型 func CalculateMemberType(spendType, renewHide, memberGenre, memberLevel uint32) MemberType { switch { case spendType == 1: return FirstInvite case spendType == 2 && memberLevel == 2 && memberGenre == 201: return OpenQuarterGold case spendType == 2 && memberLevel == 2 && memberGenre == 202: return OpenHalfYearGold case spendType == 3 && renewHide == 1 && memberLevel == 2 && memberGenre == 201: return RenewQuarterGoldAuto case spendType == 3 && renewHide == 1 && memberLevel == 2 && memberGenre == 202: return RenewHalfYearGoldAuto case spendType == 2: switch memberLevel { case 2: return OpenAnnualGold case 4: return OpenAnnualPlatinum case 5: return OpenAnnualBlack case 6: return OpenAnnualPrivilege } case spendType == 3 && renewHide == 0: switch memberLevel { case 2: return RenewAnnualGoldIntervene case 4: return RenewAnnualPlatinumIntervene case 5: return RenewAnnualBlackIntervene } case spendType == 3 && renewHide == 1: switch memberLevel { case 2: return RenewAnnualGoldAuto case 4: return RenewAnnualPlatinumAuto case 5: return RenewAnnualBlackAuto case 6: return RenewAnnualPrivilegeAuto } case spendType == 4 && renewHide == 0: switch memberLevel { case 4: return UpgradeGoldToPlatinumIntervene case 5: if memberGenre == 200 || memberGenre == 201 || memberGenre == 202 { return UpgradeGoldToBlackIntervene } return UpgradePlatinumToBlackIntervene } case spendType == 4 && renewHide == 1: switch memberLevel { case 4: return UpgradeGoldToPlatinumAuto case 5: if memberGenre == 200 { return UpgradeGoldToBlackAuto } return UpgradePlatinumToBlackAuto } } return Unknown } // UpdateUserInviteRecordRenewHide 更新用户邀请记录:如果不是店员干预的续费用户,则更新为1-自动续费 func UpdateUserInviteRecordRenewHide() error { err := orm.Eloquent.Exec("UPDATE user_invite_record SET renew_hide=1 WHERE spend_type=3 AND scan=0 AND renew_hide!=1;").Error if err != nil { logger.Errorf("update renew_hide err:", logger.Field("err", err)) return err } return nil } //func ExportUserMemberList(storeId, memberType uint32, startTime, endTime string) string { // var userInvites []UserInvite // qs := orm.Eloquent.Table("user_11invite").Where("from_uid > 0") // if memberType == 1 { // qs = qs.Where("member_type=?", 1) // } else if memberType == 2 { // qs = qs.Where("member_type in (?)", []uint32{2, 4, 5}) // } else if memberType == 3 { // qs = qs.Where("member_type=?", 3) // } // // if storeId != 0 { // qs = qs.Where("store_id", storeId) // } // if startTime != "" { // parse, err := time.Parse(DateTimeFormat, startTime) // if err != nil { // logger.Errorf("err:",logger.Field("err",err)) // return "" // } // qs = qs.Where("member_open_time > ?", parse) // } // if endTime != "" { // parse, err := time.Parse(DateTimeFormat, endTime) // if err != nil { // logger.Errorf("err:",logger.Field("err",err)) // return "" // } // parse = parse.AddDate(0, 0, 1) // qs = qs.Where("member_open_time < ?", parse) // } // // err := qs.Order("id DESC,store_id DESC,from_uid DESC").Find(&userInvites).Error // if err != nil && err != RecordNotFound { // logger.Errorf("err:",logger.Field("err",err)) // return "" // } // // storeIds := make([]uint64, 0) // fromUids := make([]uint32, 0) // toUids := make([]uint32, 0) // for i, _ := range userInvites { // storeIds = append(storeIds, userInvites[i].StoreId) // fromUids = append(fromUids, userInvites[i].FromUid) // toUids = append(toUids, userInvites[i].ToUid) // } // // var stores []Store // err = orm.Eloquent.Table("store").Where("id in (?)", storeIds).Find(&stores).Error // if err != nil { // logger.Error("err:",logger.Field("err",err)) // return "" // } // storeMap := make(map[uint32]Store) // for i, _ := range stores { // storeMap[stores[i].ID] = stores[i] // } // // fromUids = append(fromUids, toUids...) // var userInfos []UserInfo // err = orm.Eloquent.Table("user").Where("uid in (?)", fromUids).Find(&userInfos).Error // if err != nil { // logger.Error("err:",logger.Field("err",err)) // return "" // } // userInfoMap := make(map[uint32]UserInfo, 0) // for i, _ := range userInfos { // userInfoMap[userInfos[i].Uid] = userInfos[i] // } // // inviteMembers := make([]UserInviteMember, 0, len(userInvites)) // for i, _ := range userInvites { // fromUser, _ := userInfoMap[userInvites[i].FromUid] // toUser, ok2 := userInfoMap[userInvites[i].ToUid] // if !ok2 { // continue // } // store, ok1 := storeMap[uint32(userInvites[i].StoreId)] // if !ok1 { // store = storeMap[uint32(toUser.StoreId)] // } // invite := UserInviteMember{ // FromUserInfo: fromUser, // Store: store, // ToUserInfo: toUser, // UserInvite: userInvites[i], // } // inviteMembers = append(inviteMembers, invite) // } // // fileName := "邀请会员" // if storeId == 0 { // fileName = "全部门店邀请会员" // } else { // if len(stores) > 0 { // fileName = stores[0].Name // } // } // //url := "http://switch.deovo.com:8000/img/export/" // url := "http://39.108.188.218:8000/img/export/" // // fileName = fileName + time.Now().Format("2006-01-02 15:04:05") + ".csv" // //f, err := os.OpenFile(fmt.Sprintf("./")+fileName, os.O_CREATE|os.O_TRUNC|os.O_APPEND|os.O_RDWR, 0644) // f, err := os.OpenFile(fmt.Sprintf("/www/server/images/export/")+fileName, os.O_CREATE|os.O_TRUNC|os.O_APPEND|os.O_RDWR, 0644) // if err != nil { // fmt.Println(err) // return fileName // } // defer f.Close() // // w := csv.NewWriter(f) // // //headline := []string{"门店名称", "店员id", "店员昵称","姓名", "会员id", "会员昵称", "注册会员时间", "会员状态"} // headline := []string{"门店名称", "店员id", "姓名", "会员id", "会员昵称", "会员等级", "注册会员时间", "会员状态"} // if err := w.Write(headline); err != nil { // log.Fatalln("error writing record to csv:",logger.Field("err",err)) // } // // for _, invite := range inviteMembers { // //fmt.Println("MemberOpenTime",invite.UserInvite.MemberOpenTime) // //fmt.Println("MemberOpenTime",invite.UserInvite.MemberOpenTime.Format("2006-01-02 15:04:05")) // record := []string{invite.Store.Name, fmt.Sprintf("%d", invite.FromUserInfo.Uid), invite.FromUserInfo.ShopAssistantName, // fmt.Sprintf("%d", invite.ToUserInfo.Uid), invite.ToUserInfo.WxName, MemberLevelToString(invite.UserInvite.MemberLevel), invite.UserInvite.MemberOpenTime.Format("2006-01-02 15:04:05"), // GetUserInviteStatus(invite.MemberStatus)} // if err := w.Write(record); err != nil { // log.Fatalln("error writing record to csv:",logger.Field("err",err)) // } // } // // w.Flush() // if err := w.Error(); err != nil { // log.Fatal(err) // } // // return url + fileName //} // 导出用户 func ExportUserMemberList(storeId, memberType, cooperativeId uint32, startTime, endTime, renewalStartTime, renewalEndTime string) string { var userInfos []UserInfo qs := orm.Eloquent.Table("user") if memberType == 1 { qs = qs.Where("member_level=?", 1) } else if memberType == 2 { qs = qs.Where("member_level in (?)", []uint32{2, 4, 5}) } else if memberType == 3 { qs = qs.Where("member_level=?", 3) } if storeId != 0 { qs = qs.Where("store_id=?", storeId) } if startTime != "" { parse, err := time.Parse(DateTimeFormat, startTime) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return "" } //qs = qs.Where("created_at > ?", parse) qs = qs.Where("open_member_time > ?", parse) } if endTime != "" { parse, err := time.Parse(DateTimeFormat, endTime) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return "" } parse = parse.AddDate(0, 0, 1) //qs = qs.Where("created_at < ?", parse) qs = qs.Where("open_member_time < ?", parse) } if cooperativeId != 0 { qs = qs.Where("cooperative_business_id=?", cooperativeId) } //err := qs.Order("id DESC,store_id DESC,from_uid DESC").Find(&userInvites).Error err := qs.Order("id DESC,store_id DESC,uid DESC").Find(&userInfos).Error //err := qs.Order("id DESC").Find(&userInfos).Error if err != nil && err != RecordNotFound { logger.Errorf("err:", logger.Field("err", err)) return "" } storeIds := make([]uint32, 0) fromUids := make([]uint32, 0) toUids := make([]uint32, 0) for i, _ := range userInfos { storeIds = append(storeIds, uint32(userInfos[i].StoreId)) //fromUids = append(fromUids, userInvites[i].FromUid) toUids = append(toUids, userInfos[i].Uid) } //var stores []Store //err = orm.Eloquent.Table("store").Where("id in (?)", storeIds).Find(&stores).Error //if err != nil { // logger.Error("err:",logger.Field("err",err)) // return "" //} //storeMap := make(map[uint32]Store) //for i, _ := range stores { // storeMap[stores[i].ID] = stores[i] //} //fromUids = append(fromUids, toUids...) var userInvites []UserInvite inviteQs := orm.Eloquent.Table("user_invite").Where("to_uid in (?)", toUids) if memberType == 1 { } if memberType == 2 { inviteQs = inviteQs.Where("action=2").Where("spend_type=2") } err = inviteQs.Find(&userInvites).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return "" } userInviteMap := make(map[uint32]UserInvite, 0) for i, _ := range userInvites { userInviteMap[userInvites[i].ToUid] = userInvites[i] fromUids = append(fromUids, userInvites[i].FromUid) } var fromUserInfos []UserInfo err = orm.Eloquent.Table("user").Where("uid in (?)", fromUids).Find(&fromUserInfos).Error if err != nil { logger.Error("from user infos err:", logger.Field("err", err)) return "" } fromUserMap := make(map[uint32]UserInfo, 0) for i, _ := range fromUserInfos { fromUserMap[fromUserInfos[i].Uid] = fromUserInfos[i] // storeIds = append(storeIds, uint32(fromUserInfos[i].StoreId)) } storeMap := StoreMapByIds(storeIds) isRenewal := false var inviteRecords []UserInviteRecord //err = orm.Eloquent.Table("user_invite_record").Where("to_uid in (?)", toUids).Where("first!=1"). // Where("scan=1").Order("id DESC").Find(&inviteRecords).Error qsInviteRecords := orm.Eloquent.Table("user_invite_record").Where("to_uid in (?)", toUids). Where("first!=1").Where("action=2") if renewalStartTime != "" { isRenewal = true parse, err := time.Parse(DateTimeFormat, renewalStartTime) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return "" } //qs = qs.Where("created_at > ?", parse) qsInviteRecords = qsInviteRecords.Where("action_time > ?", parse).Where("spend_type=3") } if renewalEndTime != "" { isRenewal = true parse, err := time.Parse(DateTimeFormat, renewalEndTime) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return "" } parse = parse.AddDate(0, 0, 1) //qs = qs.Where("created_at < ?", parse) qsInviteRecords = qsInviteRecords.Where("action_time < ?", parse).Where("spend_type=3") } err = qsInviteRecords.Order("id ASC").Find(&inviteRecords).Error if err != nil { logger.Error("invite record err:", logger.Field("err", err)) return "" } UserInviteRecordListSetAssistantName(inviteRecords) inviteRecordMap := make(map[uint32][]UserInviteRecord, 0) for i, _ := range inviteRecords { fromUser, ok3 := fromUserMap[inviteRecords[i].FromUid] if ok3 { inviteRecords[i].ShopAssistantName = fromUser.ShopAssistantName } //inviteRecordMap[inviteRecords[i].ToUid] = inviteRecords[i] v, ok := inviteRecordMap[inviteRecords[i].ToUid] if ok { if len(v) >= 2 { continue } } if inviteRecords[i].SpendType == 3 && inviteRecords[i].Scan == 0 { inviteRecords[i].ShopAssistantName = "自动续费" } inviteRecordMap[inviteRecords[i].ToUid] = append(inviteRecordMap[inviteRecords[i].ToUid], inviteRecords[i]) } inviteMembers := make([]UserInviteMember, 0, len(userInvites)) for i, _ := range userInfos { //toUser, ok2 := userInfoMap[userInvites[i].ToUid] store, ok1 := storeMap[(userInfos[i].StoreId)] userInfoMember := UserInviteMember{ FromUserInfo: UserInfo{}, Store: store, ToUserInfo: userInfos[i], UserInvite: UserInvite{ToUid: userInfos[i].Uid}, } if isRenewal { v, ok := inviteRecordMap[userInfos[i].Uid] if !ok { continue } if len(v) > 0 { userInfoMember.UserInviteRecord = v[len(v)-1] } } userInvite, ok2 := userInviteMap[userInfos[i].Uid] if ok2 { userInfoMember.UserInvite = userInvite if !ok1 { store = storeMap[(userInvite.StoreId)] userInfoMember.Store = store } fromUser, ok3 := fromUserMap[userInvite.FromUid] if ok3 { userInfoMember.FromUserInfo = fromUser } } fromStore, ok4 := storeMap[userInfoMember.FromUserInfo.StoreId] if ok4 { userInfoMember.FromUserInfo.Store = &fromStore } inviteMembers = append(inviteMembers, userInfoMember) } if isRenewal { sort.Sort(ExportUserInviteMemberList(inviteMembers)) } //UserInviteRecordListSetAssistantName(inviteRecords) // //inviteRecordMap := make(map[uint32][]UserInviteRecord, 0) //for i, _ := range inviteRecords { // v, ok := inviteRecordMap[inviteRecords[i].ToUid] // if ok { // if len(v) >= 2 { // continue // } // } // if inviteRecords[i].SpendType == 3 && inviteRecords[i].Scan == 0 { // inviteRecords[i].ShopAssistantName = "自动续费" // } // // inviteRecordMap[inviteRecords[i].ToUid] = append(inviteRecordMap[inviteRecords[i].ToUid], inviteRecords[i]) //} fileName := "邀请会员" if storeId == 0 { fileName = "全部门店邀请会员" } else { store, err := GetStore(storeId) if err != nil { logger.Error("get store err:", logger.Field("err", err)) return "" } fileName = store.Name } //url := "http://39.108.188.218:8000/img/export/" //url := "https://dev.admin.deovo.com/img/export/" styleBorder := &excelize.Style{ Border: []excelize.Border{{ Type: "left", Color: "000000", Style: 1, }, { Type: "top", Color: "000000", Style: 1, }, { Type: "right", Color: "000000", Style: 1, }, { Type: "bottom", Color: "000000", Style: 1, }}, } styleFill1 := &excelize.Style{ Border: []excelize.Border{{ Type: "left", Color: "000000", Style: 1, }, { Type: "top", Color: "000000", Style: 1, }, { Type: "right", Color: "000000", Style: 1, }, { Type: "bottom", Color: "000000", Style: 1, }}, Fill: excelize.Fill{ Type: "pattern", Pattern: 1, Color: []string{"FFFF00"}, }, } styleFill2 := &excelize.Style{ Border: []excelize.Border{{ Type: "left", Color: "000000", Style: 1, }, { Type: "top", Color: "000000", Style: 1, }, { Type: "right", Color: "000000", Style: 1, }, { Type: "bottom", Color: "000000", Style: 1, }}, Fill: excelize.Fill{ Type: "pattern", Pattern: 1, Color: []string{"FFEFDB"}, }, } //url := "https://dev.admin.deovo.com/load/export/" fileName = time.Now().Format(TimeFormat) + fileName + ".xlsx" fSheet := "Sheet1" file := excelize.NewFile() //streamWriter, err := file.NewStreamWriter("Sheet1") //if err != nil { // fmt.Println(err) //} styleBorderId, err := file.NewStyle(styleBorder) if err != nil { logger.Error("err:", logger.Field("err", err)) } styleFillId1, err := file.NewStyle(styleFill1) if err != nil { logger.Error("err:", logger.Field("err", err)) } styleFillId2, err := file.NewStyle(styleFill2) if err != nil { logger.Error("err:", logger.Field("err", err)) } //headline := []string{"门店名称", "店员id", "店员姓名", "用户注册时间", "最近登录时间", "会员id", "会员昵称", "用户手机号", "会员等级", "注册会员时间", "会员状态"} headline := []interface{}{"门店名称", "店员id", "店员姓名", "店员门店", "用户注册时间", "最近登录时间", "用户id", "用户昵称", "用户手机号", "会员等级", "注册会员时间", "开通_店员id", "开通_店员名称", "开通_扫码时间", "续费_店员id", "续费_店员名称", "续费_扫码时间"} if cooperativeId != 0 { headline = []interface{}{"门店名称", "店员id", "店员姓名", "店员门店", "用户注册时间", "最近登录时间", "用户id", "会员等级", "注册会员时间", "开通_店员id", "开通_店员名称", "开通_扫码时间", "续费_店员id", "续费_店员名称", "续费_扫码时间"} } headLength := len(headline) for i, _ := range headline { cell, _ := excelize.CoordinatesToCellName(1+i, 1) err = file.SetCellValue(fSheet, cell, headline[i]) if err != nil { logger.Error("file set value err:", logger.Field("err", err)) } idx := i if cooperativeId == 0 { if idx+1 > 11 && idx+1 <= 14 { err = file.SetCellStyle(fSheet, cell, cell, styleFillId1) if err != nil { logger.Error("file set value err:", logger.Field("err", err)) } } else if idx+1 > 14 && idx+1 <= 17 { err = file.SetCellStyle(fSheet, cell, cell, styleFillId2) if err != nil { logger.Error("file set value err:", logger.Field("err", err)) } } else { err = file.SetCellStyle(fSheet, cell, cell, styleBorderId) if err != nil { logger.Error("file set value err:", logger.Field("err", err)) } } } else { if idx+1 > 9 && idx+1 <= 12 { err = file.SetCellStyle(fSheet, cell, cell, styleFillId1) if err != nil { logger.Error("file set value err:", logger.Field("err", err)) } } else if idx+1 > 12 && idx+1 <= 15 { err = file.SetCellStyle(fSheet, cell, cell, styleFillId2) if err != nil { logger.Error("file set value err:", logger.Field("err", err)) } } else { err = file.SetCellStyle(fSheet, cell, cell, styleBorderId) if err != nil { logger.Error("file set value err:", logger.Field("err", err)) } } } } //if err = streamWriter.SetRow(cell, headline); err != nil { // fmt.Println(err) //} for rowId := 0; rowId < len(inviteMembers); rowId++ { invite := inviteMembers[rowId] fromStoreName := "" if invite.FromUserInfo.Store != nil { fromStoreName = invite.FromUserInfo.Store.Name } record := []interface{}{} if cooperativeId != 0 { record = []interface{}{invite.Store.Name, fmt.Sprintf("%d", invite.FromUserInfo.Uid), invite.FromUserInfo.ShopAssistantName, fromStoreName, invite.ToUserInfo.CreatedAt.Format(TimeFormat), invite.ToUserInfo.LastLoginAt.Format(TimeFormat), fmt.Sprintf("%d", invite.ToUserInfo.Uid), MemberLevelToString(invite.UserInvite.MemberLevel), invite.UserInvite.MemberOpenTime.Format(TimeFormat), //GetUserInviteStatus(invite.MemberStatus), } } else { record = []interface{}{invite.Store.Name, fmt.Sprintf("%d", invite.FromUserInfo.Uid), invite.FromUserInfo.ShopAssistantName, fromStoreName, invite.ToUserInfo.CreatedAt.Format(TimeFormat), invite.ToUserInfo.LastLoginAt.Format(TimeFormat), fmt.Sprintf("%d", invite.ToUserInfo.Uid), invite.ToUserInfo.WxName, invite.ToUserInfo.Tel, MemberLevelToString(invite.ToUserInfo.MemberLevel), invite.ToUserInfo.OpenMemberTime.Format(TimeFormat), //GetUserInviteStatus(invite.ToUserInfo.MemberStatus), } //MemberLevelToString(invite.UserInvite.MemberLevel), //invite.UserInvite.MemberOpenTime.Format(TimeFormat), //GetUserInviteStatus(invite.MemberStatus)} } userInviteRecordList, ok := inviteRecordMap[invite.ToUid] if ok { for i, _ := range userInviteRecordList { if i == 0 && userInviteRecordList[i].SpendType != 2 { record = append(record, []interface{}{"", "", ""}...) } record = append(record, []interface{}{userInviteRecordList[i].FromUid, userInviteRecordList[i].ShopAssistantName, userInviteRecordList[i].CreatedAt.Format(TimeFormat)}...) } } if len(record) < headLength { record = append(record, make([]interface{}, headLength-len(record))...) } for i, _ := range record { cell, _ := excelize.CoordinatesToCellName(1+i, rowId+2) err = file.SetCellValue(fSheet, cell, record[i]) if err != nil { logger.Error("file set value err:", logger.Field("err", err)) } err = file.SetCellStyle(fSheet, cell, cell, styleBorderId) if err != nil { logger.Error("file set value err:", logger.Field("err", err)) } } //if err := streamWriter.SetRow(cell, record); err != nil { // fmt.Println(err) //} } //if err := streamWriter.Flush(); err != nil { // fmt.Println(err) //} if err := file.SaveAs("/www/server/images/export/" + fileName); err != nil { //if err := file.SaveAs("./" + fileName); err != nil { fmt.Println(err) } return config.ExportConfig.Url + fileName } type ExportUserInviteMemberList []UserInviteMember func (s ExportUserInviteMemberList) Len() int { //返回传入数据的总数 return len(s) } func (s ExportUserInviteMemberList) Swap(i, j int) { //两个对象满足Less()则位置对换 //表示执行交换数组中下标为i的数据和下标为j的数据 s[i], s[j] = s[j], s[i] } func (s ExportUserInviteMemberList) Less(i, j int) bool { //按字段比较大小,此处是降序排序 //返回数组中下标为i的数据是否小于下标为j的数据 return s[i].UserInviteRecord.ActionTime.After(s[j].UserInviteRecord.ActionTime) } func GetUserInviteStatus(status uint8) string { switch status { case 1: return "未注册" case 2: return "已注册" case 3: return "取消会员" } return "" } func IsUserInfoByUid(uid uint32) (bool, error) { //userInfo := new(UserInfo) var count int64 err := orm.Eloquent.Debug().Table("user").Where("uid = ?", uid).Count(&count).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return false, err } if count == 0 { return true, errors.New("user not exist") } return true, nil } func GetUserInfoByUid(uid uint32) (UserInfo, error) { //userInfo := new(UserInfo) var userInfo UserInfo err := orm.Eloquent.Debug().Table("user").Where("uid = ?", uid).Find(&userInfo).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return userInfo, err } return userInfo, nil } func GetSysUserInfoByUid(uid uint32) (SysUser, error) { //userInfo := new(UserInfo) var userInfo SysUser err := orm.Eloquent.Debug().Table("sys_user").Where("uid = ?", uid).Find(&userInfo).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return userInfo, err } return userInfo, nil } func countDigits(n uint32) int { str := strconv.FormatUint(uint64(n), 10) return len(str) } func GetSysUserInfoById(id uint32) (SysUser, error) { var userInfo SysUser if countDigits(id) == 8 { //历史数据为8位的uid err := orm.Eloquent.Debug().Table("sys_user").Where("uid = ?", id).Find(&userInfo).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return userInfo, err } } else { err := orm.Eloquent.Debug().Table("sys_user").Where("user_id = ?", id).Find(&userInfo).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return userInfo, err } } return userInfo, nil } type UserDepositRefundRecordListReq struct { //StoreId uint32 `json:"store_id"` // 门店id Uid uint32 `json:"uid"` // 用户id PageNum int `json:"pageIndex"` PageSize int `json:"pageSize"` Status uint32 `json:"status"` } type UserDepositRefundRecordListResp struct { List []DepositRefundRecord `json:"list"` Total int `json:"total"` // 总条数 PageIndex int `json:"pageIndex"` // 页码 PageSize int `json:"pageSize"` // 每页展示条数 } func (m *UserDepositRefundRecordListReq) DepositRefundRecordList() (*UserDepositRefundRecordListResp, error) { qs := orm.Eloquent.Table("deposit_refund_record") if m.Status != 0 { qs = qs.Where("status=?", m.Status) } if m.Uid != 0 { qs = qs.Where("uid=?", m.Uid) } resp := &UserDepositRefundRecordListResp{ PageIndex: m.PageNum, PageSize: m.PageSize, } page := m.PageNum - 1 if page < 0 { page = 0 } if m.PageSize == 0 { m.PageSize = 10 } var count int64 err := qs.Count(&count).Error if err != nil { logger.Error("count err:", logger.Field("err", err)) return resp, err } resp.Total = int(count) var depositRefunds []DepositRefundRecord err = qs.Order("status ASC").Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&depositRefunds).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return resp, err } resp.List = depositRefunds return resp, nil } type GroupSendMessageCreateTemplateListReq struct { Status uint32 `json:"status"` // 1-待发送 2-已发送 Title string `json:"title"` PageNum int `json:"pageIndex"` PageSize int `json:"pageSize"` } type GroupSendMessageCreateTemplateListResp struct { List []GroupSendMessageTemplate `json:"list"` SmsRemainingNumber int `json:"sms_remaining_number"` // 本月短信剩余数量 Count uint32 `json:"count"` PageNum int `json:"pageIndex"` } func (m *GroupSendMessageCreateTemplateListReq) List() (*GroupSendMessageCreateTemplateListResp, error) { qs := orm.Eloquent.Table("group_send_message_template") if m.Status != 0 { qs = qs.Where("status=?", m.Status) } if m.Title != "" { qs = qs.Where("title LIKE '%" + m.Title + "%'") } page := m.PageNum - 1 if page < 0 { page = 0 } if m.PageSize == 0 { m.PageSize = 10 } resp := &GroupSendMessageCreateTemplateListResp{PageNum: m.PageNum} var count int64 err := qs.Count(&count).Error if err != nil { logger.Error("count err:", logger.Field("err", err)) return resp, err } resp.Count = uint32(count) var groupSends []GroupSendMessageTemplate err = qs.Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&groupSends).Error if err != nil && err != RecordNotFound { logger.Error("err:", logger.Field("err", err)) return resp, err } resp.List = groupSends resp.SmsRemainingNumber = GetSmsNumberRemaining() return resp, nil } func CreateInviteMemberReport() { date := time.Now().AddDate(0, 0, 1) if date.Day() != 1 { return } var cooperatives []CooperativeBusiness err := orm.Eloquent.Table("cooperative_business").Find(&cooperatives).Error if err != nil { logger.Error("cooperative err:", logger.Field("err", err)) return } for i, _ := range cooperatives { cooperatives[i].InviteMemberReport() } } func (m *CooperativeBusiness) InviteMemberReport() { var users []UserInfo err := orm.Eloquent.Table("user").Where("cooperative_business_id=?", m.ID). Where("user_type=?", UserTypeShopAssistant).Find(&users).Error if err != nil { logger.Error("cooperative err:", logger.Field("err", err)) return } for i, _ := range users { m.UserInviteReport(users[i]) } } // UserInviteReport // 每个月1号统计上个月的数据 func (m *CooperativeBusiness) UserInviteReport(userInfo UserInfo) { //end := InDayZero(1) //start := end.AddDate(0, -1, 0) reportTime := time.Now().AddDate(0, -1, 0).Format("2006-01") //var userInvites []UserInvite //qs := orm.Eloquent.Table("user_invite").Where("from_uid=?", userInfo.Uid). // Where("member_status=?", 2).Where("user_type=?", 2). // Where("member_open_time>?", start).Where("member_open_time 0 { // qs = qs.Where("uid NOT IN (?)", ids) //} if m.InviteName != "" { m.Uid = ids[m.InviteName] if m.Uid == 0 { qs = qs.Where("uid=?", m.Uid) } } if m.Uid != 0 { qs = qs.Where("uid=?", m.Uid) } if m.Date != "" { qs = qs.Where("date=?", m.Date) } //qs := NewInviteMemberReportQuerySet(DB).UidEq(m.Uid) var count int64 err = qs.Count(&count).Error if err != nil { logger.Error("count err:", logger.Field("err", err)) return nil, err } page := m.PageIndex - 1 if page < 0 { page = 0 } if m.PageSize == 0 { m.PageSize = 10 } //totalPage := int(count)/m.PageSize + 1 if m.IsExport == 1 { // 导出excel err = qs.Order("STR_TO_DATE(date, '%Y-%m-%d') DESC, store_id ASC").Find(&memberReport).Error if err != nil && err != RecordNotFound { logger.Error("err:", logger.Field("err", err)) return nil, err } } else { err = qs.Order("STR_TO_DATE(date, '%Y-%m-%d') DESC, store_id ASC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&memberReport).Error if err != nil && err != RecordNotFound { logger.Error("err:", logger.Field("err", err)) return nil, err } } for i, item := range memberReport { memberReport[i].SystemUser = sysUserMap[item.Uid] storeInfo, _ := GetUserEffectiveStore(item.Uid) memberReport[i].SystemUser.StoreList = storeInfo if len(storeInfo) != 0 { memberReport[i].StoreId = uint32(storeInfo[0].StoreID) } memberReport[i].CooperativeBusinessId = sysUserMap[item.Uid].CooperativeBusinessId memberReport[i].CooperativeName = sysUserMap[item.Uid].CooperativeName } //memberReport = InviteMemberReportListSetUser(memberReport) //memberReport = InviteMemberReportListSetStore(memberReport) if m.IsExport == 1 { fileName, err := inviteMemberReport(memberReport) if err != nil { logger.Error("err:", logger.Field("err", err)) return nil, err } resp.ExportUrl = fileName } else { resp.List = memberReport resp.Total = count resp.PageSize = m.PageSize resp.PageIndex = m.PageIndex } return resp, nil } // 店员绩效导出excel func inviteMemberReport(list []InviteMemberReport) (string, error) { file := excelize.NewFile() fSheet := "Sheet1" url := config.ExportConfig.Url fileName := time.Now().Format(TimeFormat) + "店员绩效" + ".xlsx" fmt.Println("url fileName:", url+fileName) title1 := []interface{}{"昵称", "小程序ID", "合作商", "门店", "月份", "开通会员数", "开通会员数", "开通会员数", "开通会员数", "开通会员数", "续费会员数(干预)", "续费会员数(干预)", "续费会员数(干预)", "升级会员数(干预)", "升级会员数(干预)", "升级会员数(干预)", "续费会员数(自动)", "续费会员数(自动)", "续费会员数(自动)", "续费会员数(自动)", "续费会员数(自动)", "升级会员数(自动)", "升级会员数(自动)", "升级会员数(自动)"} title2 := []interface{}{"昵称", "小程序ID", "合作商", "门店", "月份", "年费黄金", "半年黄金", "季度黄金", "年费白金", "年费黑金", "年费黄金", "年费白金", "年费黑金", "黄金->白金", "黄金->黑金", "白金->黑金", "年费黄金", "半年黄金", "季度黄金", "年费白金", "年费黑金", "黄金->白金", "黄金->黑金", "白金->黑金"} for i, _ := range title1 { cell, _ := excelize.CoordinatesToCellName(1+i, 1) err := file.SetCellValue(fSheet, cell, title1[i]) if err != nil { logger.Error("file set value err:", logger.Field("err", err)) } } for i, _ := range title2 { cell, _ := excelize.CoordinatesToCellName(1+i, 2) err := file.SetCellValue(fSheet, cell, title2[i]) if err != nil { logger.Error("file set value err:", logger.Field("err", err)) } } var row []interface{} nExcelStartRow := 0 for i := 0; i < len(list); i++ { storeName := "" if list[i].SystemUser.StoreList != nil { for _, item := range list[i].SystemUser.StoreList { if storeName != "" { storeName += "," } storeName += item.StoreName } } shopAssistantName := "" if list[i].SystemUser != nil { shopAssistantName = list[i].SystemUser.NickName } row = []interface{}{ shopAssistantName, // 昵称 list[i].Uid, // 小程序ID list[i].CooperativeName, // 合作商名称 storeName, // 门店名称 list[i].Date, // 月份 list[i].GoldCount, // 开通会员:年费黄金 list[i].GoldCountHalf, //开通会员:半年黄金 list[i].GoldCountQuarter, //开通会员:季度黄金 list[i].PlatinumCount, // 开通会员:年费白金 list[i].BlackGoldCount, // 开通会员:年费黑金 list[i].InviteRenewalGoldCount, // 续费会员(干预):年费黄金 list[i].InviteRenewalPlatinumCount, // 续费会员(干预):白金 list[i].InviteRenewalBlackGoldCount, // 续费会员(干预):黑金 list[i].InviteUpgradeGoldToPlatinumCount, // 升级(干预):黄金->白金数量 list[i].InviteUpgradeGoldToBlackCount, // 升级(干预):黄金->黑金数量 list[i].InviteUpgradePlatinumToBlackCount, // 升级(干预):白金->黑金数量 list[i].RenewalGoldCount, // 续费会员(自动):年费黄金 list[i].RenewalGoldCountHalf, // 续费会员(自动):半年黄金 list[i].RenewalGoldCountQuarter, // 续费会员(自动):季度黄金 list[i].RenewalPlatinumCount, // 续费会员(自动):白金 list[i].RenewalBlackGoldCount, // 续费会员(自动):黑金 list[i].UpgradeGoldToPlatinumCount, // 升级(自动):黄金->白金数量 list[i].UpgradeGoldToBlackCount, // 升级(自动):黄金->黑金数量 list[i].UpgradePlatinumToBlackCount, // 升级(自动):白金->黑金数量 } for j, _ := range row { cell, _ := excelize.CoordinatesToCellName(1+j, nExcelStartRow+3) err := file.SetCellValue(fSheet, cell, row[j]) if err != nil { logger.Error("file set value err:", logger.Field("err", err)) } } nExcelStartRow++ } // 设置所有单元格的样式: 居中、加边框 style, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"}, "border":[{"type":"left","color":"000000","style":1}, {"type":"top","color":"000000","style":1}, {"type":"right","color":"000000","style":1}, {"type":"bottom","color":"000000","style":1}]}`) // 设置单元格的样式: 居中、加边框、自动换行 style1, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center","wrap_text":true}, "border":[{"type":"left","color":"000000","style":1}, {"type":"top","color":"000000","style":1}, {"type":"right","color":"000000","style":1}, {"type":"bottom","color":"000000","style":1}]}`) endRow := fmt.Sprintf("X%d", nExcelStartRow+2) // 合并单元格 _ = file.MergeCell(fSheet, "A1", "A2") _ = file.MergeCell(fSheet, "B1", "B2") _ = file.MergeCell(fSheet, "C1", "C2") _ = file.MergeCell(fSheet, "D1", "D2") _ = file.MergeCell(fSheet, "E1", "E2") _ = file.MergeCell(fSheet, "F1", "J1") _ = file.MergeCell(fSheet, "K1", "M1") _ = file.MergeCell(fSheet, "N1", "P1") _ = file.MergeCell(fSheet, "Q1", "U1") _ = file.MergeCell(fSheet, "V1", "X1") //设置单元格高度 file.SetRowHeight("Sheet1", 1, 20) file.SetRowHeight("Sheet1", 2, 20) // 从列 C 到列 K,逐一设置宽度为 20 for col := 'F'; col <= 'X'; col++ { colName := string(col) file.SetColWidth("Sheet1", colName, colName, 9) } // 应用样式到整个表格 _ = file.SetCellStyle("Sheet1", "A1", "X1", style1) _ = file.SetCellStyle("Sheet1", "A2", endRow, style) fmt.Println("save fileName:", config.ExportConfig.Path+fileName) if err := file.SaveAs(config.ExportConfig.Path + fileName); err != nil { fmt.Println(err) } return url + fileName, nil } //func InviteMemberReportListSetUser(list []InviteMemberReport) []InviteMemberReport { // ids := make([]uint32, 0, len(list)) // for i, _ := range list { // ids = append(ids, list[i].Uid) // } // if len(ids) == 0 { // return list // } // // infoMap, err := GetUserInfoMap(ids) // if err != nil { // logger.Error("user info map err:", logger.Field("err", err)) // return list // } // // for i, _ := range list { // v, ok := infoMap[list[i].Uid] // if ok { // list[i].User = &v // } // fmt.Println("UserInfo:", v) // } // // return list //} // //func InviteMemberReportListSetStore(list []InviteMemberReport) []InviteMemberReport { // ids := make([]uint32, 0, len(list)) // for i, _ := range list { // ids = append(ids, list[i].StoreId) // } // if len(ids) == 0 { // return list // } // storeMap := GetStoreMapByIds(ids) // //infoMap, err := GetUserInfoMap(ids) // //if err != nil { // // logger.Error("user info map err:",logger.Field("err",err)) // // return list // //} // // for i, _ := range list { // v, ok := storeMap[uint64(list[i].StoreId)] // if ok { // list[i].Store = v // } // fmt.Println("UserInfo:", v) // } // // return list //} func GetCooperativeBusinessId(c *gin.Context) (uint32, error) { data, _ := c.Get(jwtauth.JwtPayloadKey) sysUid, ok := data.(jwtauth.MapClaims)["identity"] if !ok { logger.Error("sys uid err") app.Error(c, http.StatusInternalServerError, errors.New("sys uid err"), "查询失败") return 0, errors.New("sys uid err") } sysUser, err := GetSysUser(sysUid) if err != nil { logger.Error("sys user err:", logger.Field("err", err)) app.Error(c, http.StatusInternalServerError, err, "查询失败") return 0, err } //req.CooperativeBusinessId = sysUser.CooperativeBusinessId return sysUser.CooperativeBusinessId, nil } func GetSysUserByCtx(c *gin.Context) (*SysUser, error) { //data, _ := c.Get(jwtauth.JwtPayloadKey) //sysUid, ok := data.(jwtauth.MapClaims)["identity"] //if !ok { // logger.Error("sys uid err") // app.Error(c, http.StatusInternalServerError, errors.New("sys uid err"), "查询失败") // return nil, errors.New("sys uid err") //} //sysUser, err := GetSysUser(sysUid) //if err != nil { // logger.Error("sys user err:",logger.Field("err",err)) // app.Error(c, http.StatusInternalServerError, err, "查询失败") // return nil, err //} //req.CooperativeBusinessId = sysUser.CooperativeBusinessId //return &sysUser, nil data, _ := c.Get(jwtauth.JwtPayloadKey) mapClaims := data.(jwtauth.MapClaims) sysUid := float64(0) if v, ok := mapClaims["identity"]; ok { sysUid = v.(float64) } //fmt.Println("sysUid:", sysUid) //req.SysUid = fmt.Sprintf("%.0f", sysUid) var sysUser SysUser err := orm.Eloquent.Table("sys_user").Where("user_id=?", uint32(sysUid)).Find(&sysUser).Error if err != nil { logger.Error("sys user err:", logger.Field("err", err)) app.Error(c, http.StatusInternalServerError, err, "操作失败") return &sysUser, err } return &sysUser, nil } //type CooperativeStockExportReq struct { // CooperativeBusinessId uint32 `json:"cooperative_business_id"` // StoreId uint32 `json:"store_id"` // 门店id //} // //func (r *CooperativeStockExportReq) Export() { // //} //OrderType: 1-物流支付 2-取消物流租卡 3-滞纳金 4-收回卡 5-退物流费 6-商城购物 7-购买商品取消订单 8-购买商品订单退货 // gen:qs type UserOpenMemberRecord struct { Model Uid uint32 `json:"uid" gorm:"index"` OpenNo string `json:"open_no" gorm:"index"` OrderId uint32 `json:"order_id" gorm:"index"` OrderType uint32 `json:"order_type"` MemberLevel uint32 `json:"member_level"` MemberExpire time.Time `json:"member_expire"` // 会员到期时间 Order *Order `json:"order" gorm:"-"` ShareCardRetrieve *ShareCardRetrieve `json:"share_card_retrieve" gorm:"-"` GoodsOrder *GoodsOrder `json:"goods_order" gorm:"-"` //Attach string `json:"attach"` } func (o *UserOpenMemberRecord) TableName() string { return "user_open_member_record" } func (m *UserOpenMemberRecord) Refund(outTradeNo string, amount uint32) error { configInfo, err := PayConfigInfo() if err != nil { logger.Error("config info err:", logger.Field("err", err)) return err } //configInfo.NotifyUrl = "https://dev.switch.deovo.com:8004/api/v1/wxpay_refund/notice" err = orm.Eloquent.Create(m).Error //err = m.Insert() if err != nil { logger.Error("insert user open member record err:", logger.Field("err", err)) return err } orderRefund := pay.OrderRefund{ OutTradeNo: outTradeNo, OutRefundNo: m.OpenNo, NotifyUrl: configInfo.RefundNotifyUrl, Amount: pay.OrderRefundAmount{ Refund: amount, Total: amount, Currency: "CNY", }, } err = pay.TransactionOrderRefund(orderRefund) if err != nil { logger.Error("err:", logger.Field("err", err)) return err } return nil } func (m *UserOpenMemberRecord) MallGoodsOrderRefund(outTradeNo string) error { if m.GoodsOrder == nil { return errors.New("goods order is nil") } if m.OpenNo == "" { m.OpenNo = GetOrderSn() } m.Uid = uint32(m.GoodsOrder.Uid) m.OrderId = m.GoodsOrder.ID err := m.Refund(outTradeNo, m.GoodsOrder.Rm) if err != nil { logger.Error("refund err:", logger.Field("err", err)) return err } return nil } func GetOrderSn() string { var orderSn string for { //orderSn = utils.GetSerialNo32HEXString() orderSn = utils.GenSerialNo() var count int64 err := orm.Eloquent.Table("user_open_member_record").Where("open_no=?", orderSn).Count(&count) //count, err := NewUserOpenMemberRecordQuerySet(DB).OpenNoEq(orderSn).Total() if err != nil { logger.Error("err:", logger.Field("err", err)) } if count == 0 { break } } return orderSn } func (m *OperationLog) AddLog() { defer func() { if err := recover(); err != nil { fmt.Println("recover err:", logger.Field("err", err)) } }() go func() { err := orm.Eloquent.Create(m).Error if err != nil { logger.Error("create operation log err:") } }() } func SendMessageMemberRenewal() { //user.MemberExpire.Before(utils.Now().AddDate(0, 1, 0)) //start := TodayZero().AddDate(0, 1, 0) ////end := start.AddDate(0, 0, 1) //end := start //fmt.Println("end:", end.Format(TimeFormat)) //var users []UserInfo //err := orm.Eloquent.Table("user").Where("member_level IN (2,4,5)").Where("member_expire < ?", end).Find(&users).Error //if err != nil { // logger.Error("cooperative err:",logger.Field("err",err)) // return //} fmt.Println("发送续费短息开始:") start := TodayZero().AddDate(0, 0, GetActivityRenewalConfig().PopTrap) end := start.AddDate(0, 0, 1) var users []UserInfo err := orm.Eloquent.Table("user").Where("member_level IN (2,4,5)"). Where("member_expire>?", start).Where("member_expire 0 { message := "【go2switch】提醒:您的租卡会员时长仅剩余一个月,现在续费最高立减200元!赶快进入小程序领取优惠吧~" err = GtSendMessage(tels, message) if err != nil { logger.Errorf("SmsSend err:", logger.Field("err", err)) return } //fmt.Println("tels:", tels) //fmt.Printf("uids:", uids) renewalLogs, err := GetActionUserRenewalLogMulti(uids, UserRenewalLogSendMessage) if err != nil { logger.Error("renewalLogs err:", logger.Field("err", err)) } renewalLogMap := make(map[uint32]UserRenewalLog, 0) for i, _ := range renewalLogs { renewalLogMap[renewalLogs[i].Uid] = renewalLogs[i] } for i, _ := range users { renewalLog := &UserRenewalLog{ Uid: users[i].Uid, Action: UserRenewalLogSendMessage, MemberExpire: *users[i].MemberExpire, Type: 0, Serial: uint32(users[i].MemberExpire.Unix()), } v, _ := renewalLogMap[users[i].Uid] renewalLog.RenewalNum = v.RenewalNum + 1 err = orm.Eloquent.Create(renewalLog).Error if err != nil { logger.Error("create renewal log err:", logger.Field("err", err)) } } } fmt.Println("发送续费短息完成...") } //func PayConfigInfo() (*PayConfig, error) { // payConfig := new(PayConfig) // var configAllocation Config // err := NewConfigQuerySet(DB).NameEq(ConfigNamePay).One(&configAllocation) // if err != nil { // logger.Error("err:",logger.Field("err",err)) // return payConfig, err // } // // err = json.Unmarshal([]byte(configAllocation.Value), payConfig) // if err != nil { // logger.Error("err:",logger.Field("err",err)) // return payConfig, err // } // // return payConfig, nil //} //type PayConfig struct { // MemberFee uint32 `json:"member_fee"` // DepositFee uint32 `json:"deposit_fee"` // NotifyUrl string `json:"notify_url"` // RefundNotifyUrl string `json:"refund_notify_url"` //} type MemberStatisticDaily struct { Model MemberLevel uint32 `json:"member_level"` Date string `json:"date"` DateTime time.Time `json:"date_time"` Increase int64 `json:"increase"` Expire int64 `json:"expire"` Net int64 `json:"net"` Accumulative int64 `json:"accumulative"` // member_statistic_daily } func IndexMemberStatistic() { fmt.Println("会员数据统计开始") levels := []uint32{2, 4, 5} today := TodayZero() //today, _ = time.Parse(TimeFormat, "2022-08-09 00:00:00") for i, _ := range levels { IndexMemberLevelStatistic(levels[i], today) } fmt.Println("会员数据统计完成...") } func IndexMemberLevelStatistic(level uint32, date time.Time) { var ( increase, expire, net, accumulative, origination int64 ) startDate := date.AddDate(0, 0, -1) endDate := date err := orm.Eloquent.Table("user").Where("member_level=?", level). Where("open_member_time>?", startDate). Where("open_member_time?", startDate). Where("member_expire?", time.Time{}). // Where("date=?", startDate.AddDate(0, 0, -1).Format(DateFormat)). // Find(&statisticDaily).Error //if err != nil { // logger.Error("increase err:",logger.Field("err",err)) //} //fmt.Println("increase:", increase) //fmt.Println("expire:", expire) memberRecordType := 0 if level == 2 { memberRecordType = 4 } else if level == 4 { memberRecordType = 5 } else if level == 5 { memberRecordType = 6 } if memberRecordType != 0 { err = orm.Eloquent.Table("user_member_record").Where("type=?", memberRecordType). Where("created_at>?", startDate).Where("created_at?", time.Now()).Count(&accumulative).Error if err != nil { logger.Error("increase err:%#v", logger.Field("err", err)) } fmt.Println("net:", net) daily := &MemberStatisticDaily{ MemberLevel: level, Date: startDate.Format(DateFormat), DateTime: startDate, Increase: increase, Expire: expire, Net: net, Accumulative: accumulative, } err = orm.Eloquent.Create(&daily).Error if err != nil { logger.Error("create member statistic daily err:", logger.Field("err", err)) } } type MemberStatisticDailyListReq struct { MemberLevel uint32 `json:"member_level"` //StartDate string `json:"start_date"` //EndDate string `json:"end_date"` StartDate time.Time `json:"start_date"` EndDate time.Time `json:"end_date"` Days uint32 `json:"days"` IsExport uint32 `json:"is_export"` // 1-导出 PageNum int `json:"pageIndex"` PageSize int `json:"pageSize"` } type MemberStatisticDailyListRsp struct { Count int64 `json:"count"` List []MemberStatisticDaily `json:"list"` PageIndex int `json:"pageIndex"` Url string `json:"url"` } func (m *MemberStatisticDailyListReq) List() (*MemberStatisticDailyListRsp, error) { rsp := &MemberStatisticDailyListRsp{ PageIndex: m.PageNum, } m.PageNum = m.PageNum - 1 if m.PageNum < 0 { m.PageNum = 0 } if m.Days > 0 { m.PageSize = int(m.Days) } qs := orm.Eloquent.Table("member_statistic_daily") //if m.StartDate != "" { // start, _ := time.Parse(DateTimeFormat, m.StartDate) // qs = qs.Where("date_time>=?", start) //} //if m.EndDate != "" { // end, _ := time.Parse(DateTimeFormat, m.EndDate) // qs = qs.Where("date_time<=?", end) //} if !m.StartDate.IsZero() { qs = qs.Where("date_time>=?", m.StartDate) } if !m.EndDate.IsZero() { qs = qs.Where("date_time<=?", m.EndDate) } if m.Days > 0 { //end := TodayZero() //start := end.AddDate(0, 0, int(m.Days)*(-1)) qs = qs.Where("date_time>=?", m.StartDate) qs = qs.Where("date_time<=?", m.EndDate) } if m.MemberLevel != 0 { qs = qs.Where("member_level=?", m.MemberLevel) } var dailys []MemberStatisticDaily var count int64 err := qs.Count(&count).Error if err != nil { logger.Error("count err:", logger.Field("err", err)) return rsp, err } rsp.Count = count //err = qs.Order("id DESC").Offset(m.PageNum * m.PageSize).Limit(m.PageSize).Find(&dailys).Error if m.IsExport == 1 { err = qs.Order("date_time DESC").Find(&dailys).Error if err != nil && err != RecordNotFound { logger.Error("dailys err:", logger.Field("err", err)) return rsp, err } listExport, err := MemberStatisticDailyListExport(dailys) if err != nil { logger.Error("list export err:", logger.Field("err", err)) } rsp.Url = listExport } else { err = qs.Order("date_time DESC").Offset(m.PageNum * m.PageSize).Limit(m.PageSize).Find(&dailys).Error if err != nil && err != RecordNotFound { logger.Error("dailys err:", logger.Field("err", err)) return rsp, err } rsp.List = dailys } return rsp, nil } func MemberStatisticDailyListExport(dailys []MemberStatisticDaily) (string, error) { file := excelize.NewFile() streamWriter, err := file.NewStreamWriter("Sheet1") if err != nil { fmt.Println(err) } //url := "http://39.108.188.218:8000/img/export/" fileName := "会员统计" + time.Now().Format("2006-01-02 15:04:05") + ".xlsx" title := []interface{}{"时间", "新增会员数", "会员过期数", "净增会员数", "累计会员数"} cell, _ := excelize.CoordinatesToCellName(1, 1) if err = streamWriter.SetRow(cell, title); err != nil { fmt.Println(err) } var row []interface{} for rowId := 0; rowId < len(dailys); rowId++ { row = []interface{}{dailys[rowId].Date, dailys[rowId].Increase, dailys[rowId].Expire, dailys[rowId].Net, dailys[rowId].Accumulative} cell, _ := excelize.CoordinatesToCellName(1, rowId+2) if err := streamWriter.SetRow(cell, row); err != nil { fmt.Println(err) } } if err := streamWriter.Flush(); err != nil { fmt.Println(err) } if err := file.SaveAs("/www/server/images/export/" + fileName); err != nil { fmt.Println(err) } return config.ExportConfig.Url + fileName, nil } func UserInviteRecordListSetAssistantName(records []UserInviteRecord) { uids := make([]uint32, 0, len(records)) for i, _ := range records { if records[i].ShopAssistantName == "" { uids = append(uids, records[i].FromUid) } } infoMap, err := GetUserInfoMap(uids) if err != nil { logger.Error("info map err:", logger.Field("err", err)) } for i, _ := range records { v, ok := infoMap[records[i].FromUid] if ok && records[i].ShopAssistantName == "" { records[i].ShopAssistantName = v.ShopAssistantName } } } type ExpireMemberSmsSendListReq struct { Status uint32 `json:"status"` // 1-待发送 2-已发送 Tel string `json:"tel"` //StartTime string `json:"start_time"` // 开始时间 //EndTime string `json:"end_time"` // 结束时间 StartTime time.Time `json:"start_time"` // 开始时间 EndTime time.Time `json:"end_time"` // 结束时间 PageIndex int `json:"pageIndex"` PageSize int `json:"pageSize"` } type ExpireMemberSmsSendListResp struct { List []ExpireMemberSmsSend `json:"list"` Total int `json:"total"` // 总条数 PageIndex int `json:"pageIndex"` // 页码 PageSize int `json:"pageSize"` // 每页展示条数 } func (m *ExpireMemberSmsSendListReq) List() (*ExpireMemberSmsSendListResp, error) { resp := &ExpireMemberSmsSendListResp{ PageIndex: m.PageIndex, PageSize: m.PageSize, } qs := orm.Eloquent.Table("expire_member_sms_send") if m.Status != 0 { qs = qs.Where("status=?", m.Status) } if m.Tel != "" { qs = qs.Where("tel LIKE '%" + m.Tel + "%'") } //if m.StartTime != "" { // parse, err := time.Parse(DateTimeFormat, m.StartTime) // if err != nil { // logger.Errorf("err:",logger.Field("err",err)) // return resp, err // } // qs = qs.Where("send_time > ?", parse) //} //if m.EndTime != "" { // parse, err := time.Parse(DateTimeFormat, m.EndTime) // if err != nil { // logger.Errorf("err:",logger.Field("err",err)) // return resp, err // } // parse = parse.AddDate(0, 0, 1) // qs = qs.Where("send_time < ?", parse) //} if !m.StartTime.IsZero() { qs = qs.Where("send_time > ?", m.StartTime) } if !m.EndTime.IsZero() { parse := m.EndTime.AddDate(0, 0, 1) qs = qs.Where("send_time < ?", parse) } page := m.PageIndex - 1 if page < 0 { page = 0 } if m.PageSize == 0 { m.PageSize = 10 } var count int64 err := qs.Count(&count).Error if err != nil { logger.Error("count err:", logger.Field("err", err)) return resp, err } resp.Total = int(count) var smsSends []ExpireMemberSmsSend err = qs.Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&smsSends).Error if err != nil && err != RecordNotFound { logger.Error("err:", logger.Field("err", err)) return resp, err } resp.List = smsSends return resp, nil } //func (m *MemberStatisticDailyListReq) Export() (string, error) { // qs := orm.Eloquent.Table("member_statistic_daily") // if !m.StartDate.IsZero() { // qs = qs.Where("date_time>=?", m.StartDate) // } // if !m.EndDate.IsZero() { // qs = qs.Where("date_time<=?", m.EndDate) // } // if m.Days > 0 { // qs = qs.Where("date_time>=?", m.StartDate) // qs = qs.Where("date_time<=?", m.EndDate) // } // if m.MemberLevel != 0 { // qs = qs.Where("member_level=?", m.MemberLevel) // } // var dailys []MemberStatisticDaily // err := qs.Order("date_time DESC").Find(&dailys).Error // if err != nil && err != RecordNotFound { // logger.Error("dailys err:",logger.Field("err",err)) // return "", err // } // // file := excelize.NewFile() // streamWriter, err := file.NewStreamWriter("Sheet1") // if err != nil { // fmt.Println(err) // } // // url := "http://39.108.188.218:8000/img/export/" // fileName := "/www/server/images/export/" + "会员统计" + time.Now().Format("2006-01-02 15:04:05") + ".xlsx" // // title := []interface{}{"时间", "新增会员数", "会员过期数", "净增会员数", "累计会员数"} // cell, _ := excelize.CoordinatesToCellName(1, 1) // if err = streamWriter.SetRow(cell, title); err != nil { // fmt.Println(err) // } // var row []interface{} // for rowId := 0; rowId < len(dailys); rowId++ { // row = []interface{}{dailys[rowId].Date, dailys[rowId].Increase, dailys[rowId].Expire, dailys[rowId].Net, dailys[rowId].Accumulative} // cell, _ := excelize.CoordinatesToCellName(1, rowId+2) // if err := streamWriter.SetRow(cell, row); err != nil { // fmt.Println(err) // } // } // if err := streamWriter.Flush(); err != nil { // fmt.Println(err) // } // if err := file.SaveAs(fileName); err != nil { // fmt.Println(err) // } // return url + fileName, nil //} func MarkUser(uid []uint32, mark int8) error { return orm.Eloquent.Table("user"). Where("uid in (?)", uid). Update("mark", mark).Error } // CheckPhoneExt 检测手机尾号是否一致 func (m *UserInfo) CheckPhoneExt(ext string, length int) bool { if ext == "" || m.Tel == "" { return false } total := len(m.Tel) if total >= length { sub := m.Tel[total-4:] return sub == ext } else { return false } } type TelListReq struct { PhoneNum string `json:"phone_num" binding:"required"` PageIndex int `json:"pageIndex"` // 页码 PageSize int `json:"pageSize"` // 页面条数 } type TelListResp struct { List []UserInfo `json:"list"` Total int `json:"total"` // 总条数 PageIndex int `json:"pageIndex"` // 页码 PageSize int `json:"pageSize"` // 每页展示条数 } func (m *TelListReq) GetTelList() (*TelListResp, error) { resp := &TelListResp{ PageIndex: m.PageIndex, PageSize: m.PageSize, } page := m.PageIndex - 1 if page < 0 { page = 0 } if m.PageSize == 0 { m.PageSize = 10 } var count int64 qs := orm.Eloquent.Table("user").Where("tel like ?", "%"+m.PhoneNum+"%") qs = qs.Where("member_level in (?)", []uint32{MemberLevelUser, MemberLevelGold, MemberLevelPeriod, MemberLevelPlatinum, MemberLevelBlackGold}) err := qs.Count(&count).Error if err != nil { logger.Error("count err:", logger.Field("err", err)) return nil, err } var userInfo []UserInfo err = qs.Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&userInfo).Error if err != nil { logger.Error("find err:", logger.Field("err", err)) return nil, err } resp.List = userInfo //跟之前保持一致 resp.Total = int(count) resp.PageIndex = page + 1 resp.PageSize = m.PageSize return resp, nil } // UpdateExpireMemberLevel 更新过期用户的当前会员等级 func UpdateExpireMemberLevel() { var users []UserInfo err := orm.Eloquent.Table("user").Where("member_expire < ?", time.Now()). Where("member_level in (?)", []uint32{2, 3, 4, 5}).Find(&users).Error if err != nil { logger.Error(err.Error()) return } if len(users) == 0 { logger.Info("UpdateExpireMemberLevel users is null") return } for i, _ := range users { if err = orm.Eloquent.Model(&UserInfo{}).Where("id = ?", users[i].ID).Updates(map[string]interface{}{ "member_level": MemberLevelUser, "updated_at": time.Now(), }).Error; err != nil { logger.Errorf("UpdateExpireMemberLevel err,", err.Error()) continue } } } // UpdateExpirePrivilegeMemberLevel 更新过期尊享会员等级 func UpdateExpirePrivilegeMemberLevel() { var users []PrivilegeMember err := orm.Eloquent.Table("privilege_member").Where("member_expire < ?", time.Now()). Where("member_level = ?", MemberLevelPrivilege).Find(&users).Error if err != nil { logger.Error(err.Error()) return } if len(users) == 0 { logger.Info("UpdateExpirePrivilegeMemberLevel users is null") return } for i, _ := range users { if err = orm.Eloquent.Model(&PrivilegeMember{}).Where("id = ?", users[i].ID).Updates(map[string]interface{}{ "member_level": MemberLevelUser, "updated_at": time.Now(), }).Error; err != nil { logger.Errorf("UpdateExpirePrivilegeMemberLevel err,", err.Error()) continue } } } // UpdateExpireUserVm 扣减用户过期积分 func UpdateExpireUserVm() { var userVmRecords []UserVmRecord // 查找需要处理的用户积分记录 err := orm.Eloquent.Table("user_vm_record"). Where("`alter` > 0 AND `alter` != `used_vm` AND `expiry_date` IS NOT NULL AND `expiry_date` < ?", time.Now()). Find(&userVmRecords).Error if err != nil { log.Printf("Failed to query user_vm_records: %v", err) return } for _, record := range userVmRecords { // 计算需要扣除的积分 pointsToDeduct := record.Alter - record.UsedVm if pointsToDeduct > 0 { // 更新 UserVm 表,防止 vm 变为负值,并更新 updated_at 字段 sql := ` UPDATE user_vm SET vm = IF(vm - ? >= 0, vm - ?, 0), updated_at = ? WHERE uid = ? ` err = orm.Eloquent.Exec(sql, pointsToDeduct, pointsToDeduct, time.Now(), record.Uid).Error if err != nil { log.Printf("Failed to update user_vm for uid %d: %v", record.Uid, err) continue } // 更新原有的 UserVmRecord,更新 used_vm 的值为 alter err = orm.Eloquent.Table("user_vm_record").Where("id=?", record.ID). Updates(map[string]interface{}{ "used_vm": record.Alter, "updated_at": time.Now(), }).Error if err != nil { log.Printf("Failed to update user_vm_record (used_vm) for record id %d: %v", record.ID, err) continue } // 创建新的 UserVmRecord 记录扣除过期积分 newRecord := UserVmRecord{ Uid: record.Uid, BeforeVm: record.AfterVm, AfterVm: record.AfterVm - uint32(pointsToDeduct), Alter: -pointsToDeduct, Event: VmEventExpired, Describe: "积分过期扣减", BillSn: record.BillSn, } err = orm.Eloquent.Table("user_vm_record").Create(&newRecord).Error if err != nil { log.Printf("Failed to create new user_vm_record for uid %d: %v", record.Uid, err) } } } } // GetUserInfoByTel 通过手机号获取用户信息 func GetUserInfoByTel(tel string) (UserInfo, error) { var userInfo UserInfo err := orm.Eloquent.Table("user").Where("tel = ?", tel).Find(&userInfo).Error if err != nil { logger.Error("err:", logger.Field("err", err)) return userInfo, err } return userInfo, nil } // CreateUid 找一个可以用的Uid func CreateUid() uint32 { for { uid := utils.GenUid() var count int64 if err := orm.Eloquent.Table("user").Where("uid = ?", uid).Count(&count).Error; err == nil && count > 0 { continue } return uid } } // IsInMemberLevels 判断用户是不是会员 func IsInMemberLevels(memberLevel uint32) bool { if memberLevel == MemberLevelUser || memberLevel == MemberLevelGold || memberLevel == MemberLevelPeriod || memberLevel == MemberLevelPlatinum || memberLevel == MemberLevelBlackGold { return true } return false } // PrivilegeMember 零售尊享会员 type PrivilegeMember struct { Model Uid uint32 `json:"uid" gorm:"column:uid;unique_index"` // 用户id Tel string `json:"tel"` // 电话 StoreId uint64 `json:"store_id"` // 门店id MemberLevel uint32 `json:"member_level"` // 当前会员等级:1-普通用户,6-尊享会员 MemberExpire *time.Time `json:"member_expire"` // 会员到期时间 OpenMemberTime *time.Time `json:"open_member_time"` // 开通会员时间 ExtendStatus uint32 `json:"extend_status"` // 延保状态:0-非会员, 1-已过期,2-待激活、3-已激活 HostCode string `json:"host_code"` // 主机编码 Images string `json:"images"` // 图片凭证 AuditorId uint32 `json:"auditor_id" gorm:"index"` // 审核人id AuditorName string `json:"auditor_name"` // 审核人姓名 AuditTime *time.Time `json:"audit_time"` // 审核时间 Remark string `json:"remark"` // 备注 Store *Store `json:"store" gorm:"-"` // 门店信息 } // PrivilegeMemberListReq 查询零售尊享会员列表入参 type PrivilegeMemberListReq struct { Uid uint32 `json:"uid"` // 用户ID Tel string `json:"tel"` // 手机号 HostCode string `json:"host_code"` // 主机编码 StoreId []uint32 `json:"store_id"` // 门店列表(支持复选) MemberLevel uint32 `json:"member_level"` // 当前会员等级 AuditorId uint32 `json:"auditor_id"` // 审核人 ExtendStatus uint32 `json:"extend_status"` // 延保状态 OpenMemberStart string `json:"open_member_start"` // 首次开通尊享会员-开始时间 OpenMemberEnd string `json:"open_member_end"` // 首次开通尊享会员-结束时间 MemberExpireStart string `json:"member_expire_start"` // 尊享会员到期时间-开始时间 MemberExpireEnd string `json:"member_expire_end"` // 尊享会员到期时间-结束时间 AuditTimeStart string `json:"audit_time_start"` // 审核开始时间 AuditTimeEnd string `json:"audit_time_end"` // 审核结束时间 IsExport uint32 `json:"is_export"` // 1-导出excel PageIndex int `json:"pageIndex"` // 页码 PageSize int `json:"pageSize"` // 页面条数 } // PrivilegeMemberListResp 查询零售尊享会员列表出参 type PrivilegeMemberListResp struct { Total int64 `json:"total"` // 总条数 PageIndex int `json:"pageIndex"` // 页码 PageSize int `json:"pageSize"` // 页面条数 ExportUrl string `json:"export_url"` // 导出excel路径 List []PrivilegeMember `json:"list"` // 零售尊享会员信息 } func (m *PrivilegeMemberListReq) PrivilegeMemberList(c *gin.Context) (*PrivilegeMemberListResp, error) { // 非管理员才判断所属门店 if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") { sysUser, err := GetSysUserByCtx(c) if err != nil { return nil, errors.New("操作失败:" + err.Error()) } // 返回sysUser未过期的门店id列表 storeList := GetValidStoreIDs(sysUser.StoreData) if len(storeList) > 0 { m.StoreId = CompareLists(storeList, m.StoreId) if len(m.StoreId) == 0 { // 没有匹配的数据,表示入参门店不是用户有权限的门店 return &PrivilegeMemberListResp{}, nil } m.StoreId = append(m.StoreId, 0) } else { return nil, errors.New("用户未绑定门店") } } page := m.PageIndex - 1 if page < 0 { page = 0 } if m.PageSize == 0 { m.PageSize = 10 } resp := &PrivilegeMemberListResp{ PageIndex: page + 1, PageSize: m.PageSize, } var memberList []PrivilegeMember qs := orm.Eloquent.Model(&PrivilegeMember{}).Debug() if m.Uid != 0 { qs = qs.Where("uid = ?", m.Uid) } if m.Tel != "" { qs = qs.Where("tel = ?", m.Tel) } if m.HostCode != "" { qs = qs.Where("host_code = ?", m.HostCode) } if len(m.StoreId) != 0 { if len(m.StoreId) == 1 { qs = qs.Where("store_id = ?", m.StoreId[0]) } else { qs = qs.Where("store_id IN (?)", m.StoreId) } } if m.MemberLevel != 0 { qs = qs.Where("member_level = ?", m.MemberLevel) } if m.AuditorId != 0 { qs = qs.Where("auditor_id = ?", m.AuditorId) } if m.ExtendStatus != 0 { qs = qs.Where("extend_status = ?", m.ExtendStatus) } if m.OpenMemberStart != "" { parse, err := time.Parse(QueryTimeFormat, m.OpenMemberStart) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } qs = qs.Where("open_member_time > ?", parse) } if m.OpenMemberEnd != "" { parse, err := time.Parse(QueryTimeFormat, m.OpenMemberEnd) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } qs = qs.Where("open_member_time < ?", parse) } if m.MemberExpireStart != "" { parse, err := time.Parse(QueryTimeFormat, m.MemberExpireStart) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } qs = qs.Where("member_expire > ?", parse) } if m.MemberExpireEnd != "" { parse, err := time.Parse(QueryTimeFormat, m.MemberExpireEnd) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } qs = qs.Where("member_expire < ?", parse) } if m.AuditTimeStart != "" { parse, err := time.Parse(QueryTimeFormat, m.AuditTimeStart) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } qs = qs.Where("audit_time > ?", parse) } if m.AuditTimeEnd != "" { parse, err := time.Parse(QueryTimeFormat, m.AuditTimeEnd) if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } qs = qs.Where("audit_time < ?", parse) } var count int64 err := qs.Count(&count).Error if err != nil { logger.Error("count err:", logger.Field("err", err)) return nil, err } if m.IsExport == 1 { // 导出excel err = qs.Order("id DESC").Find(&memberList).Error if err != nil && err != RecordNotFound { logger.Error("err:", logger.Field("err", err)) return nil, err } } else { err = qs.Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&memberList).Error if err != nil && err != RecordNotFound { logger.Error("err:", logger.Field("err", err)) return nil, err } } // 查询门店信息 storeList := make(map[uint32]Store) storeList = GetStoreMap() for i, u := range memberList { if u.StoreId == 0 { continue } // 添加门店信息 store := storeList[uint32(u.StoreId)] memberList[i].Store = &store // 校验时间,如果为01-01-01 08:05,则赋值为空 validateZeroTime(&memberList[i].AuditTime) } if m.IsExport == 1 { fileName, err := PrivilegeMemberExport(memberList) if err != nil { logger.Error("err:", logger.Field("err", err)) return nil, err } resp.ExportUrl = fileName } else { resp.List = memberList resp.Total = count resp.PageSize = m.PageSize resp.PageIndex = m.PageIndex } return resp, nil } // PrivilegeMemberExport 尊享会员导出excel func PrivilegeMemberExport(list []PrivilegeMember) (string, error) { file := excelize.NewFile() fSheet := "Sheet1" url := config.ExportConfig.Url fileName := time.Now().Format(TimeFormat) + "零售尊享会员" + ".xlsx" fmt.Println("url fileName:", url+fileName) //title := []interface{}{"用户ID", "手机号", "所属门店", "当前会员等级", "首次开通尊享会员时间", "尊享会员到期时间", "延保状态", // "主机编码", "图片凭证", "审核人", "审核时间"} title := []interface{}{"用户ID", "手机号", "所属门店", "当前会员等级", "首次开通尊享会员时间", "尊享会员到期时间", "延保状态", "主机编码", "审核人", "审核时间"} for i, _ := range title { cell, _ := excelize.CoordinatesToCellName(1+i, 1) err := file.SetCellValue(fSheet, cell, title[i]) if err != nil { logger.Error("file set value err:", logger.Field("err", err)) } } var row []interface{} nExcelStartRow := 0 // 查询门店信息 var storeList []Store err := orm.Eloquent.Table("store").Find(&storeList).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return "", err } storeMap := make(map[uint32]string, 0) for i, _ := range storeList { storeMap[storeList[i].ID] = storeList[i].Name } fmt.Println("storeMap is:", storeMap) for i := 0; i < len(list); i++ { var strExtendStatus string switch list[i].ExtendStatus { case 1: strExtendStatus = "已过期" case 2: strExtendStatus = "待激活" case 3: strExtendStatus = "已激活" default: strExtendStatus = "" } row = []interface{}{ list[i].Uid, // 用户ID list[i].Tel, // 手机号 storeMap[uint32(list[i].StoreId)], // 所属门店 getMemberLevelChineseDescription(list[i].MemberLevel), // 当前会员等级 tools.ConvertTimeToStringByPoint(list[i].OpenMemberTime), // 首次开通尊享会员时间 tools.ConvertTimeToStringByPoint(list[i].MemberExpire), // 尊享会员到期时间 strExtendStatus, // 延保状态 list[i].HostCode, // 主机编码 //list[i].Images, // 图片凭证 list[i].AuditorName, // 审核人 tools.ConvertTimeToStringByPoint(list[i].AuditTime), // 审核时间 } for j, _ := range row { cell, _ := excelize.CoordinatesToCellName(1+j, nExcelStartRow+2) err = file.SetCellValue(fSheet, cell, row[j]) if err != nil { logger.Error("file set value err:", logger.Field("err", err)) } } nExcelStartRow++ } // 设置所有单元格的样式: 居中、加边框 style, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"}, "border":[{"type":"left","color":"000000","style":1}, {"type":"top","color":"000000","style":1}, {"type":"right","color":"000000","style":1}, {"type":"bottom","color":"000000","style":1}]}`) // 设置单元格的样式: 居中、加边框、自动换行 style1, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center","wrap_text":true}, "border":[{"type":"left","color":"000000","style":1}, {"type":"top","color":"000000","style":1}, {"type":"right","color":"000000","style":1}, {"type":"bottom","color":"000000","style":1}]}`) endRow := fmt.Sprintf("J%d", nExcelStartRow+1) // 应用样式到整个表格 file.SetColWidth("Sheet1", "A", "A", 12) file.SetColWidth("Sheet1", "B", "B", 15) file.SetColWidth("Sheet1", "C", "C", 30) file.SetColWidth("Sheet1", "D", "D", 18) file.SetColWidth("Sheet1", "F", "E", 18) file.SetColWidth("Sheet1", "F", "F", 18) file.SetColWidth("Sheet1", "G", "G", 15) file.SetColWidth("Sheet1", "H", "H", 18) file.SetColWidth("Sheet1", "I", "I", 15) file.SetColWidth("Sheet1", "J", "J", 18) _ = file.SetCellStyle("Sheet1", "A1", "J1", style1) _ = file.SetCellStyle("Sheet1", "A2", endRow, style) fmt.Println("save fileName:", config.ExportConfig.Path+fileName) if err := file.SaveAs(config.ExportConfig.Path + fileName); err != nil { fmt.Println(err) } return url + fileName, nil } type ActivateExtendedWarrantyReq struct { Uid uint32 `json:"uid" binding:"required"` // 用户ID HostCode string `json:"host_code" binding:"required"` // 主机编码 Images string `json:"images" binding:"required"` // 图片凭证 Remark string `json:"remark"` // 备注 } func (m *ActivateExtendedWarrantyReq) ActivateExtendedWarranty(c *gin.Context) error { sysUser, err := GetSysUserByCtx(c) if err != nil { logger.Errorf("err:%#v", err) return err } var userStoreId uint64 // 查询用户尊享会员记录 var memberInfo PrivilegeMember err = orm.Eloquent.Model(&PrivilegeMember{}).Debug().Where("uid = ?", m.Uid).Find(&memberInfo).Error if err != nil { return err } if memberInfo.StoreId == 0 { // 获取店员有效门店 storeInfo, _ := GetUserEffectiveStore(uint32(sysUser.Uid)) if len(storeInfo) != 0 { userStoreId = uint64(storeInfo[0].StoreID) } } else { userStoreId = memberInfo.StoreId } err = orm.Eloquent.Table("privilege_member").Where("uid = ?", m.Uid).Updates(map[string]interface{}{ "store_id": userStoreId, "extend_status": ExtendEffectivity, "host_code": m.HostCode, "images": m.Images, "remark": m.Remark, "audit_time": time.Now(), "auditor_name": sysUser.NickName, "auditor_id": sysUser.UserId, "updated_at": time.Now(), }).Error if err != nil { logger.Error("order err:", logger.Field("err", err)) return err } return nil } type CancelPrivilegeMembersReq struct { Uid uint32 `json:"uid" binding:"required"` // 用户ID } func (m *CancelPrivilegeMembersReq) CancelPrivilegeMembers() (*PrivilegeMember, error) { var userInfo PrivilegeMember err := orm.Eloquent.Table("privilege_member").Where("uid", m.Uid).Find(&userInfo).Error if err != nil { logger.Errorf("err:", logger.Field("err", err)) return nil, err } if userInfo.MemberLevel != MemberLevelPrivilege { logger.Errorf("err:", logger.Field("err", "用户不是尊享会员"), logger.Field("uid", m.Uid)) return nil, errors.New("取消失败,用户不是尊享会员") } nowTime := time.Now() userInfo.MemberLevel = MemberLevelUser userInfo.MemberExpire = &nowTime userInfo.ExtendStatus = ExtendExpire begin := orm.Eloquent.Begin() sql := fmt.Sprintf("UPDATE `privilege_member` SET member_level = 1,member_expire=?,updated_at=?,extend_status=1 WHERE uid = ?;") err = begin.Exec(sql, nowTime, nowTime, m.Uid).Error if err != nil { begin.Rollback() logger.Errorf("err:", logger.Field("err", err)) return nil, err } //var userInvite UserInvite //orm.Eloquent.Table("user_invite").Where("to_uid=?", m.Uid).Where("spend_type=2"). // Order("id DESC").Limit(1).Find(&userInvite) //sqlInvite := fmt.Sprintf("UPDATE user_invite SET member_status=3,action=1,spend_type=1 WHERE id= ? ;") //err = orm.Eloquent.Exec(sqlInvite, userInvite.ID).Error //if err != nil { // logger.Errorf("err:", logger.Field("err", err)) // return nil, err //} // 修改尊享会员优惠券,改为过期状态 var userCoupon []UserCoupon err = orm.Eloquent.Table("user_coupon").Where("uid = ? and activity_id = 6", m.Uid).Find(&userCoupon).Error if err != nil || err == RecordNotFound { logger.Errorf("err:", logger.Field("err", err)) } for i, _ := range userCoupon { err = begin.Table("user_coupon").Where("id = ?", userCoupon[i].ID).Updates(map[string]interface{}{ "state": 3, "updated_at": time.Now(), }).Error if err != nil { begin.Rollback() logger.Error("UpdateCoupon err:", logger.Field("err", err)) return nil, err } } // 更新用户积分 err = UserVmUpdate(begin, "", uint32(m.Uid), -199, VmEventCancelPrivilegeMember, "取消尊享会员") if err != nil { begin.Rollback() logger.Errorf("err:", err) return nil, err } err = begin.Commit().Error if err != nil { begin.Rollback() logger.Error("CancelPrivilegeMember err:", logger.Field("err", err)) return nil, err } return &userInfo, nil }