mh_goadmin_server/app/admin/models/user.go
chenlin 55b2ddd8ef 1.修复缺陷;
2.新增系统生成串码接口;
2024-04-22 09:51:41 +08:00

3920 lines
135 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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普通会员所以这里的范围改成123, 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普通会员所以这里的范围改成123, 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<?", end)
//qs = qs.Where("action=2").Where("spend_type=2")
//err := qs.Find(&userInvites).Error
//if err != nil && err != RecordNotFound {
// logger.Error("cooperative err:",logger.Field("err",err))
// return
//}
//reportTime := start.Format("2006-01")
//m.SetMemberDeductConfig()
m.SetAssistantMemberDeductConfig(uint32(userInfo.StoreId))
if m.CooperativeAssistantMemberDeduct == nil {
logger.Error("cooperative assistant member deduct is nil")
return
}
exist, err := QueryRecordExist(fmt.Sprintf(
"SELECT * FROM invite_member_report WHERE cooperative_business_id=%d AND date='%s' AND store_id=%d AND uid=%d",
userInfo.CooperativeBusinessId, reportTime, userInfo.StoreId, userInfo.Uid))
if err != nil {
logger.Error("cooperative member promotion record exist err:", logger.Field("err", err))
return
}
report := &InviteMemberReport{
Uid: userInfo.Uid,
StoreId: uint32(userInfo.StoreId),
GoldCount: 0,
PlatinumCount: 0,
BlackGoldCount: 0,
Date: reportTime,
DeductAmount: 0,
CooperativeBusinessId: userInfo.CooperativeBusinessId,
CooperativeName: userInfo.CooperativeName,
GoldDeduct: m.CooperativeAssistantMemberDeduct.GoldDeduct,
PlatinumDeduct: m.CooperativeAssistantMemberDeduct.PlatinumDeduct,
BlackGoldDeduct: m.CooperativeAssistantMemberDeduct.BlackGoldDeduct,
}
//for i, _ := range userInvites {
// switch userInvites[i].MemberLevel {
// case 2:
// report.GoldCount += 1
// case 4:
// report.PlatinumCount += 1
// case 5:
// report.BlackGoldCount += 1
// }
//}
//report.DeductAmount += report.GoldCount * m.CooperativeAssistantMemberDeduct.GoldDeduct
//report.DeductAmount += report.PlatinumCount * m.CooperativeAssistantMemberDeduct.PlatinumDeduct
//report.DeductAmount += report.BlackGoldCount * m.CooperativeAssistantMemberDeduct.BlackGoldDeduct
if exist {
//err = orm.Eloquent.Save(report).Error
//if err != nil {
// logger.Error("invite member report err:",logger.Field("err",err))
//}
logger.Error("member report exist ")
return
}
//if len(userInvites) == 0 {
// err = orm.Eloquent.Create(report).Error
// if err != nil {
// logger.Error("Create report err:",logger.Field("err",err))
// }
// return
//}
err = orm.Eloquent.Create(report).Error
if err != nil {
logger.Error("Create report err:", logger.Field("err", err))
}
}
func GetSysUser(suid interface{}) (SysUser, error) {
fmt.Println("sysUid:", suid)
var sUser SysUser
err := orm.Eloquent.Table("sys_user").Where(fmt.Sprintf("user_id=%.0f", suid.(float64))).Find(&sUser).Error
if err != nil {
logger.Error("invite member report err:", logger.Field("err", err))
return sUser, err
}
return sUser, nil
}
type AssistantInviteMemberReportReq struct {
CooperativeBusinessId uint32 `json:"cooperative_business_id"` // 合作商id
StoreId uint32 `json:"store_id"` // 门店id
Uid uint32 `json:"uid"` // 店员小程序id
InviteName string `json:"invite_name"` // 邀请人昵称
Date string `json:"date"` // 日期
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 每页数量
IsExport uint32 `json:"is_export"` // 1-导出
SysUser SysUser `json:"sys_user"` //
}
type AssistantInviteMemberReportListResp struct {
List []InviteMemberReport `json:"list"`
Total int64 `json:"total"` // 数据总条数
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 每页展示条数
ExportUrl string `json:"export_url"` // 导出excel地址
}
func (m *AssistantInviteMemberReportReq) List() (*AssistantInviteMemberReportListResp, error) {
resp := new(AssistantInviteMemberReportListResp)
var memberReport []InviteMemberReport
var users []UserInfo
err := orm.Eloquent.Table("user").Where("user_type=2").Find(&users).Error
if err != nil {
logger.Error("err:", logger.Field("err", err))
return nil, err
}
uids := make(map[string]uint32, 0)
for i, _ := range users {
uids[users[i].ShopAssistantName] = users[i].Uid
}
qs := orm.Eloquent.Table("invite_member_report")
if m.SysUser.UserId != 1 {
qs = qs.Where("cooperative_business_id=?", m.SysUser.CooperativeBusinessId)
} else {
qs = qs.Where("cooperative_business_id=?", m.CooperativeBusinessId)
}
//if len(uids) > 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<?", end).Find(&users).Error
if err != nil {
logger.Error("cooperative err:", logger.Field("err", err))
return
}
tels := make([]string, 0)
uids := make([]uint32, 0, len(users))
for i, _ := range users {
if users[i].Tel != "" {
tels = append(tels, users[i].Tel)
fmt.Println("user:", users[i].Uid, users[i].Tel)
uids = append(uids, users[i].Uid)
}
}
if len(tels) > 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<?", endDate).Count(&increase).Error
if err != nil {
logger.Error("increase err:", logger.Field("err", err))
}
err = orm.Eloquent.Table("user").Where("member_level=?", level).
Where("member_expire>?", startDate).
Where("member_expire<?", endDate).Count(&expire).Error
if err != nil {
logger.Error("increase err:%#v", logger.Field("err", err))
}
//// TODO
//var statisticDaily MemberStatisticDaily
//err = orm.Eloquent.Table("member_statistic_daily").Where("member_level=?", level).
// //Where("open_member_time>?", 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<?", endDate).Count(&origination).Error
if err != nil {
logger.Error("origination err:", logger.Field("err", err))
}
}
increase += origination
net = increase - expire
//accumulative = statisticDaily.Accumulative + increase
err = orm.Eloquent.Table("user").Where("member_level=?", level).
Where("member_expire>?", 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
}