235 lines
6.1 KiB
Go
235 lines
6.1 KiB
Go
package srv_viporder
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"time"
|
|
"videoweb/pub/common/srvdef"
|
|
"videoweb/pub/models/usermod"
|
|
"videoweb/pub/models/vipordermod"
|
|
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
)
|
|
|
|
// GetVipOrders 分页查询会员购买记录(固定 OrderType=会员)
|
|
func GetVipOrders(ctx context.Context, req *VipOrderReq) (*VipOrderResp, *srvdef.SrvErr) {
|
|
orderType := vipordermod.OrderTypeVip
|
|
reqCopy := *req
|
|
reqCopy.OrderType = &orderType
|
|
return GetOrders(ctx, &reqCopy)
|
|
}
|
|
|
|
// GetOrders 分页查询充值订单,支持按 OrderType 筛选(不传则查全部类型)
|
|
func GetOrders(ctx context.Context, req *VipOrderReq) (*VipOrderResp, *srvdef.SrvErr) {
|
|
filter := bson.M{}
|
|
if req.OrderType != nil {
|
|
filter[vipordermod.FN.VipOrder.OrderType] = *req.OrderType
|
|
}
|
|
if req.UserId != nil && *req.UserId > 0 {
|
|
filter[vipordermod.FN.VipOrder.UserId] = *req.UserId
|
|
}
|
|
if req.Status != nil {
|
|
filter[vipordermod.FN.VipOrder.Status] = *req.Status
|
|
}
|
|
if req.TradeNo != nil && *req.TradeNo != "" {
|
|
filter[vipordermod.FN.VipOrder.TradeNo] = *req.TradeNo
|
|
}
|
|
if districtCode := strings.TrimSpace(req.DistrictCode); districtCode != "" {
|
|
filter[vipordermod.FN.VipOrder.DistrictCode] = districtCode
|
|
}
|
|
|
|
timeFilter := bson.M{}
|
|
if req.StartTime != nil && *req.StartTime != "" {
|
|
if t, ok := parseTime(*req.StartTime); ok {
|
|
timeFilter["$gte"] = t
|
|
}
|
|
}
|
|
if req.EndTime != nil && *req.EndTime != "" {
|
|
if t, ok := parseTime(*req.EndTime); ok {
|
|
timeFilter["$lte"] = t
|
|
}
|
|
}
|
|
if len(timeFilter) > 0 {
|
|
filter[vipordermod.FN.VipOrder.CreatedAt] = timeFilter
|
|
}
|
|
|
|
total, serr := vipordermod.CountVipOrder(ctx, filter)
|
|
if serr != nil {
|
|
return nil, serr
|
|
}
|
|
resp := &VipOrderResp{Total: total}
|
|
if total == 0 {
|
|
resp.List = vipordermod.VipOrderList{}
|
|
return resp, nil
|
|
}
|
|
|
|
opt := options.Find().
|
|
SetSort(bson.D{{Key: vipordermod.FN.VipOrder.CreatedAt, Value: -1}}).
|
|
SetSkip((req.PageNum - 1) * req.PageSize).
|
|
SetLimit(req.PageSize)
|
|
|
|
list, serr := vipordermod.FindManyVipOrder(ctx, filter, opt)
|
|
if serr != nil {
|
|
return nil, serr
|
|
}
|
|
resp.List = list
|
|
return resp, nil
|
|
}
|
|
|
|
const (
|
|
syncDistrictDefaultSize = int64(500)
|
|
syncDistrictMaxSize = int64(2000)
|
|
syncDistrictBatchSize = int64(200)
|
|
)
|
|
|
|
// SyncDistrictCode 将历史订单中空的渠道码,按用户当前 districtCode 回填。
|
|
func SyncDistrictCode(ctx context.Context, req *SyncDistrictCodeReq) (*SyncDistrictCodeResp, *srvdef.SrvErr) {
|
|
maxSize := syncDistrictDefaultSize
|
|
if req != nil && req.MaxSize > 0 {
|
|
maxSize = req.MaxSize
|
|
}
|
|
if maxSize > syncDistrictMaxSize {
|
|
maxSize = syncDistrictMaxSize
|
|
}
|
|
|
|
resp := &SyncDistrictCodeResp{}
|
|
lastId := int64(0)
|
|
updatedUsers := make(map[int64]struct{})
|
|
skippedUsers := make(map[int64]struct{})
|
|
|
|
for resp.Scanned < maxSize {
|
|
limit := syncDistrictBatchSize
|
|
if remain := maxSize - resp.Scanned; remain < limit {
|
|
limit = remain
|
|
}
|
|
filter := emptyDistrictSyncFilter(lastId, skippedUsers)
|
|
list, serr := vipordermod.FindManyVipOrder(ctx, filter, options.Find().
|
|
SetProjection(bson.D{
|
|
{Key: vipordermod.FN.VipOrder.Id, Value: 1},
|
|
{Key: vipordermod.FN.VipOrder.UserId, Value: 1},
|
|
}).
|
|
SetSort(bson.D{{Key: vipordermod.FN.VipOrder.Id, Value: 1}}).
|
|
SetLimit(limit))
|
|
if serr != nil {
|
|
return nil, serr
|
|
}
|
|
if len(list) == 0 {
|
|
break
|
|
}
|
|
resp.Scanned += int64(len(list))
|
|
lastId = list[len(list)-1].Id
|
|
if int64(len(list)) == limit && resp.Scanned >= maxSize {
|
|
resp.HasMore = true
|
|
}
|
|
|
|
userIds := make([]int64, 0, len(list))
|
|
seen := make(map[int64]struct{}, len(list))
|
|
for _, order := range list {
|
|
if order == nil || order.UserId <= 0 {
|
|
continue
|
|
}
|
|
if _, ok := seen[order.UserId]; ok {
|
|
continue
|
|
}
|
|
seen[order.UserId] = struct{}{}
|
|
userIds = append(userIds, order.UserId)
|
|
}
|
|
if len(userIds) == 0 {
|
|
continue
|
|
}
|
|
|
|
users, serr := usermod.FindManyUser(ctx, bson.M{
|
|
usermod.FN.User.Id: bson.M{"$in": userIds},
|
|
}, options.Find().SetProjection(bson.D{
|
|
{Key: usermod.FN.User.Id, Value: 1},
|
|
{Key: usermod.FN.User.DistrictCode, Value: 1},
|
|
}))
|
|
if serr != nil {
|
|
return nil, serr
|
|
}
|
|
userMap := make(map[int64]*usermod.User, len(users))
|
|
for _, user := range users {
|
|
if user != nil {
|
|
userMap[user.Id] = user
|
|
}
|
|
}
|
|
|
|
now := time.Now()
|
|
for _, userId := range userIds {
|
|
user := userMap[userId]
|
|
code := ""
|
|
if user != nil {
|
|
code = strings.TrimSpace(user.DistrictCode)
|
|
}
|
|
if code == "" {
|
|
skippedUsers[userId] = struct{}{}
|
|
continue
|
|
}
|
|
modified, serr := vipordermod.UpdateManyVipOrder(ctx,
|
|
mergeEmptyDistrictFilter(bson.M{vipordermod.FN.VipOrder.UserId: userId}),
|
|
bson.M{"$set": bson.M{
|
|
vipordermod.FN.VipOrder.DistrictCode: code,
|
|
vipordermod.FN.VipOrder.UpdatedAt: now,
|
|
}},
|
|
)
|
|
if serr != nil {
|
|
return nil, serr
|
|
}
|
|
if modified > 0 {
|
|
updatedUsers[userId] = struct{}{}
|
|
resp.OrderUpdated += modified
|
|
}
|
|
}
|
|
}
|
|
|
|
resp.UserUpdated = int64(len(updatedUsers))
|
|
resp.UserSkipped = int64(len(skippedUsers))
|
|
if !resp.HasMore {
|
|
remain, serr := vipordermod.FindManyVipOrder(ctx, emptyDistrictSyncFilter(lastId, skippedUsers),
|
|
options.Find().SetProjection(bson.D{{Key: vipordermod.FN.VipOrder.Id, Value: 1}}).SetLimit(1))
|
|
if serr != nil {
|
|
return nil, serr
|
|
}
|
|
resp.HasMore = len(remain) > 0
|
|
}
|
|
return resp, nil
|
|
}
|
|
|
|
func emptyDistrictSyncFilter(lastId int64, skippedUsers map[int64]struct{}) bson.M {
|
|
conds := []bson.M{vipordermod.EmptyDistrictFilter()}
|
|
if lastId > 0 {
|
|
conds = append(conds, bson.M{vipordermod.FN.VipOrder.Id: bson.M{"$gt": lastId}})
|
|
}
|
|
if skipIds := mapKeys(skippedUsers); len(skipIds) > 0 {
|
|
conds = append(conds, bson.M{vipordermod.FN.VipOrder.UserId: bson.M{"$nin": skipIds}})
|
|
}
|
|
if len(conds) == 1 {
|
|
return conds[0]
|
|
}
|
|
return bson.M{"$and": conds}
|
|
}
|
|
|
|
func mergeEmptyDistrictFilter(extra bson.M) bson.M {
|
|
filter := vipordermod.EmptyDistrictFilter()
|
|
if len(extra) == 0 {
|
|
return filter
|
|
}
|
|
conds := []bson.M{filter}
|
|
for key, value := range extra {
|
|
conds = append(conds, bson.M{key: value})
|
|
}
|
|
return bson.M{"$and": conds}
|
|
}
|
|
|
|
func mapKeys(m map[int64]struct{}) []int64 {
|
|
if len(m) == 0 {
|
|
return nil
|
|
}
|
|
keys := make([]int64, 0, len(m))
|
|
for id := range m {
|
|
keys = append(keys, id)
|
|
}
|
|
return keys
|
|
}
|