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-白金→黑金(自动) ) const ( MemberLevelConsumer = 10 // 普通用户 MemberLevelUser = 1 // 普通会员 MemberLevelGold = 2 // 黄金会员 MemberLevelPeriod = 3 // 短期会员 MemberLevelPlatinum = 4 // 白金会员 MemberLevelBlackGold = 5 // 黑金会员 ) const ( UserTypeConsumer = 1 // 普通用户 UserTypeShopAssistant = 2 // 店员 ) // 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-黑金会员 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://dev.admin.deovo.com/load/export/" ) 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 int `json:"order_amount"` // 消费金额 } 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) (*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 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, 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)) 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, 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)) 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 := ExportUrl 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"` // 黑金数量 //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"` // 续费黑金会员数量(自动) 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 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 ExportUrl + fileName } // gen:qs type UserInviteRecord struct { Model ToUid uint32 `json:"to_uid"` // 用户ID FromUid uint32 `json:"from_uid"` // 邀请人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-黑金 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-白金→黑金(自动) 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"` // 租卡会员到期时间 } func (m *NewUserInviteRecordReq) NewList() (*UserInviteRecordListResp, error) { resp := new(UserInviteRecordListResp) var records []struct { UserInviteRecord StoreId uint32 InviteUserName string UserTel string CreateTime time.Time MemberExpire time.Time } 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.store_id, B1.Shop_assistant_name AS InviteUserName, " + "B2.tel AS UserTel, B2.created_at AS CreateTime, B2.member_expire AS MemberExpire"). Joins("JOIN user B1 ON user_invite_record.from_uid = B1.uid"). Joins("JOIN user B2 ON user_invite_record.to_uid = B2.uid") if m.StoreId != 0 { qs = qs.Where("B1.store_id=?", m.StoreId) countQuery = countQuery.Where("B1.store_id=?", m.StoreId) } if m.InviteUserName != "" { qs = qs.Where("B1.Shop_assistant_name=?", m.InviteUserName) countQuery = countQuery.Where("B1.Shop_assistant_name=?", m.InviteUserName) } if m.FromUid != 0 { qs = qs.Where("from_uid=?", m.FromUid) countQuery = countQuery.Where("from_uid=?", m.FromUid) } if m.ToUid != 0 { qs = qs.Where("to_uid=?", m.ToUid) countQuery = countQuery.Where("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 { // for _, recordType := range m.RecordType { // switch recordType { // case 1: // 首次邀请 // qs = qs.Where("first=1").Where("spend_type=1") // countQuery = countQuery.Where("first=1").Where("spend_type=1") // case 2: // 开通年费黄金 // qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=2") // countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=2") // case 3: // 开通季度黄金 // qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=2").Where("user_invite_record.member_genre=201") // countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=2").Where("user_invite_record.member_genre=201") // case 4: // 开通半年黄金 // qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=2").Where("user_invite_record.member_genre=202") // countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=2").Where("user_invite_record.member_genre=202") // case 5: // 开通年费白金 // qs = qs.Where("user_invite_record.member_level=4").Where("spend_type=2") // countQuery = countQuery.Where("user_invite_record.member_level=4").Where("spend_type=2") // case 6: // 开通年费黑金 // qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=2") // countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=2") // // case 7: // 续费年费黄金(干预) // qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=0") // countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=0") // case 8: // 续费年费白金(干预) // qs = qs.Where("user_invite_record.member_level=4").Where("spend_type=3").Where("renew_hide=0") // countQuery = countQuery.Where("user_invite_record.member_level=4").Where("spend_type=3").Where("renew_hide=0") // case 9: // 续费年费黑金(干预) // qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=3").Where("renew_hide=0") // countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=3").Where("renew_hide=0") // // case 10: // 续费年费黄金(自动) // qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=1") // countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=1") // case 11: // 续费季度黄金(自动) // qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=1"). // Where("user_invite_record.member_genre=201") // countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=1"). // Where("user_invite_record.member_genre=201") // case 12: // 续费半年黄金(自动) // qs = qs.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=1"). // Where("user_invite_record.member_genre=202") // countQuery = countQuery.Where("user_invite_record.member_level=2").Where("spend_type=3").Where("renew_hide=1"). // Where("user_invite_record.member_genre=202") // case 13: // 续费年费白金(自动) // qs = qs.Where("user_invite_record.member_level=4").Where("spend_type=3").Where("renew_hide=1") // countQuery = countQuery.Where("user_invite_record.member_level=4").Where("spend_type=3").Where("renew_hide=1") // case 14: // 续费年费黑金(自动) // qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=3").Where("renew_hide=1") // countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=3").Where("renew_hide=1") // // case 15: //黄金→白金(干预) // qs = qs.Where("user_invite_record.member_level=4").Where("spend_type=4").Where("renew_hide=0") // countQuery = countQuery.Where("user_invite_record.member_level=4").Where("spend_type=4").Where("renew_hide=0") // case 16: //黄金→黑金(干预) // qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=0"). // Where("user_invite_record.member_genre in (200,201,202)") // countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=0"). // Where("user_invite_record.member_genre in (200,201,202)") // case 17: //白金→黑金(干预) // qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=0"). // Where("user_invite_record.member_genre not in (200,201,202)") // countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=0"). // Where("user_invite_record.member_genre not in (200,201,202)") // // case 18: //黄金→白金(自动) // qs = qs.Where("user_invite_record.member_level=4").Where("spend_type=4").Where("renew_hide=1") // countQuery = countQuery.Where("user_invite_record.member_level=4").Where("spend_type=4").Where("renew_hide=1") // case 19: //黄金→黑金(自动) // qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=1"). // Where("user_invite_record.member_genre in (200,201,202)") // countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=1"). // Where("user_invite_record.member_genre in (200,201,202)") // case 20: //白金→黑金(自动) // qs = qs.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=1"). // Where("user_invite_record.member_genre not in (200,201,202)") // countQuery = countQuery.Where("user_invite_record.member_level=5").Where("spend_type=4").Where("renew_hide=1"). // Where("user_invite_record.member_genre not in (200,201,202)") // } // } //} 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))") } } // 拼接多选条件 if len(recordTypeConditions) > 0 { recordTypeQuery := strings.Join(recordTypeConditions, " OR ") qs = qs.Where(recordTypeQuery) countQuery = countQuery.Where(recordTypeQuery) } } if !m.RecordStartTime.IsZero() { qs = qs.Where("action_time > ?", m.RecordStartTime) countQuery = countQuery.Where("action_time > ?", m.RecordStartTime) } if !m.RecordEndTime.IsZero() { qs = qs.Where("action_time < ?", m.RecordEndTime) countQuery = countQuery.Where("action_time < ?", m.RecordEndTime) } if m.MemberLevel != 0 { qs = qs.Where("user_invite_record.member_level = ?", m.MemberLevel) countQuery = countQuery.Where("user_invite_record.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.store_id, B1.Shop_assistant_name AS InviteUserName, " + "B2.tel AS UserTel, B2.created_at AS CreateTime, B2.member_expire AS MemberExpire"). Joins("JOIN user B1 ON user_invite_record.from_uid = B1.uid"). Joins("JOIN user B2 ON user_invite_record.to_uid = B2.uid"). Order("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.store_id, B1.Shop_assistant_name AS InviteUserName, " + "B2.tel AS UserTel, B2.created_at AS CreateTime, B2.member_expire AS MemberExpire"). Joins("JOIN user B1 ON user_invite_record.from_uid = B1.uid"). Joins("JOIN user B2 ON user_invite_record.to_uid = B2.uid"). 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 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.MemberLevel, MemberExpire: item.MemberExpire, } 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 "黑金会员" } return "" } // 导出会员邀请记录excel func userInviteRecordExport(list []UserInviteRecordListData) (string, error) { file := excelize.NewFile() fSheet := "Sheet1" url := ExportUrl 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: switch memberLevel { case 2: return OpenAnnualGold case 4: return OpenAnnualPlatinum case 5: return OpenAnnualBlack } 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 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 } 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 } return Unknown } 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 ExportUrl + 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"` Count uint32 `json:"count"` PageNum int `json:"pageIndex"` } 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) } page := m.PageNum - 1 if page < 0 { page = 0 } if m.PageSize == 0 { m.PageSize = 10 } resp := &UserDepositRefundRecordListResp{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 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=2").Find(&users).Error if err != nil { logger.Error("cooperative err:", logger.Field("err", err)) return } for i, _ := range users { m.UserInviteReport(users[i]) } } func (m *CooperativeBusiness) UserInviteReport(userInfo UserInfo) { //end := InDayZero(1) //start := end.AddDate(0, -1, 0) reportTime := time.Now().AddDate(0, 0, 1).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 (?)", uids) //} if m.InviteName != "" { m.Uid = uids[m.InviteName] if m.Uid == 0 { qs = qs.Where("uid=?", m.Uid) } } if m.Uid != 0 { qs = qs.Where("uid=?", m.Uid) } if m.StoreId != 0 { qs = qs.Where("store_id=?", m.StoreId) } 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("store_id DESC,id DESC").Find(&memberReport).Error if err != nil && err != RecordNotFound { logger.Error("err:", logger.Field("err", err)) return nil, err } } else { err = qs.Order("store_id DESC,id DESC").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 } } //assistant := GetUserByUid(m.Uid) //cooperative := new(CooperativeBusiness) //cooperative.ID = assistant.CooperativeBusinessId //cooperative.SetAssistantMemberDeductConfig(uint32(assistant.StoreId)) //fmt.Println("CooperativeBusinessId:", assistant.CooperativeBusinessId, assistant.StoreId) //fmt.Println("CooperativeAssistantMemberDeduct:", cooperative.CooperativeAssistantMemberDeduct) //if len(memberReport) > 0 { // memberReport[len(memberReport)-1].GoldDeduct = cooperative.CooperativeAssistantMemberDeduct.GoldDeduct // memberReport[len(memberReport)-1].PlatinumDeduct = cooperative.CooperativeAssistantMemberDeduct.PlatinumDeduct // memberReport[len(memberReport)-1].BlackGoldDeduct = cooperative.CooperativeAssistantMemberDeduct.BlackGoldDeduct // // report := memberReport[len(memberReport)-1] // fmt.Println("report:", report) // memberReport[len(memberReport)-1].DeductAmount += report.GoldCount * report.GoldDeduct // memberReport[len(memberReport)-1].DeductAmount += report.PlatinumCount * report.PlatinumDeduct // memberReport[len(memberReport)-1].DeductAmount += report.BlackGoldCount * report.BlackGoldDeduct //} 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 := ExportUrl 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].Store != nil { storeName = list[i].Store.Name } shopAssistantName := "" if list[i].User != nil { shopAssistantName = list[i].User.ShopAssistantName } 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).Count() 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 ExportUrl + 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"` // 结束时间 PageNum int `json:"page_num"` PageSize int `json:"page_size"` } type ExpireMemberSmsSendListResp struct { List []ExpireMemberSmsSend `json:"list"` Count uint32 `json:"count"` PageNum int `json:"pageIndex"` } func (m *ExpireMemberSmsSendListReq) List() (*ExpireMemberSmsSendListResp, error) { resp := &ExpireMemberSmsSendListResp{PageNum: m.PageNum} 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.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.Count = uint32(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": 1, }).Error; err != nil { logger.Errorf("UpdateExpireMemberLevel err,", err.Error()) continue } } } // 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 }