zhangqian
2023-11-13 a8849056eebef42a33353e8652de13822f440632
merge
1个文件已添加
50个文件已修改
820 ■■■■ 已修改文件
api/v1/assign.go 93 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/client.go 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/contact.go 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/contract.go 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/followRecord.go 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/getAllData.go 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/invoice.go 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/masterOrder.go 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/plan.go 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/quotation.go 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/receipt.go 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/saleChance.go 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/salesDetails.go 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/salesLeads.go 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/salesRefund.go 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/salesReturn.go 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/serviceContract.go 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/serviceFollowup.go 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/serviceOrder.go 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/subOrder.go 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
constvar/const.go 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main.go 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
middleware/jwt.go 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
middleware/refresh_user.go 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
middleware/user.go 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
model/client.go 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
model/contact.go 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
model/contract.go 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
model/followRecord.go 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
model/invoice.go 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
model/masterOrder.go 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
model/plan.go 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
model/quotation.go 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
model/receipt.go 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
model/request/invoice.go 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
model/request/jwt.go 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
model/request/receipt.go 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
model/saleChance.go 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
model/salesLeads.go 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
model/serviceFeeManage.go 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
model/serviceOrder.go 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
model/subOrder.go 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
model/user.go 62 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
proto/user.proto 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
proto/user/user.pb.go 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/assign.go 84 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/dataServer.go 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/invoice.go 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/lru.go 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/receipt.go 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/user.go 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/v1/assign.go
@@ -1,49 +1,44 @@
package v1
import (
    "aps_crm/model/request"
    "aps_crm/pkg/contextx"
    "aps_crm/pkg/ecode"
    "github.com/gin-gonic/gin"
)
type AssignApi struct{}
// Assign
//
//    @Tags        Assign
//    @Summary    分配
//    @Produce    application/json
//    @Param        object    body        request.Assign true    "查询参数"
//    @Success    200        {object}    contextx.Response{}
//    @Router        /api/assign/assign [post]
func (au *AssignApi) Assign(c *gin.Context) {
    var params request.Assign
    ctx, ok := contextx.NewContext(c, &params)
    if !ok {
        return
    }
    if params.MemberId == 0 {
        ctx.Fail(ecode.AssignWrongMemberId)
        return
    }
    if len(params.Ids) == 0 {
        ctx.Fail(ecode.AssignWrongId)
        return
    }
    if params.Type == "" {
        ctx.Fail(ecode.AssignWrongModelType)
        return
    }
    errCode := assignService.Assign(params.MemberId, params.Ids, params.Type)
    if errCode != ecode.OK {
        ctx.Fail(errCode)
        return
    }
    ctx.Ok()
}
package v1
import (
    "aps_crm/model/request"
    "aps_crm/pkg/contextx"
    "aps_crm/pkg/ecode"
    "github.com/gin-gonic/gin"
)
type AssignApi struct{}
// Assign
//
//    @Tags        Assign
//    @Summary    分配
//    @Produce    application/json
//    @Param        object    body        request.Assign true    "查询参数"
//    @Success    200        {object}    contextx.Response{}
//    @Router        /api/assign/assign [post]
func (au *AssignApi) Assign(c *gin.Context) {
    var params request.Assign
    ctx, ok := contextx.NewContext(c, &params)
    if !ok {
        return
    }
    if len(params.Ids) == 0 {
        ctx.Fail(ecode.AssignWrongId)
        return
    }
    if params.Type == "" {
        ctx.Fail(ecode.AssignWrongModelType)
        return
    }
    errCode := assignService.Assign(params.MemberId, params.Ids, params.Type)
    if errCode != ecode.OK {
        ctx.Fail(errCode)
        return
    }
    ctx.Ok()
}
api/v1/client.go
@@ -28,13 +28,6 @@
        return
    }
    if params.MemberId == 0 {
        userInfo := utils.GetUserInfo(c)
        if userInfo.UserType == constvar.UserTypeSub {
            params.MemberId = userInfo.CrmUserId
        }
    }
    errCode, client := checkClientParams(params.Client)
    if errCode != ecode.OK {
        ctx.Fail(errCode)
@@ -116,12 +109,7 @@
    client.Business.IndustryId = params.IndustryId
    client.Business.EnterpriseNatureId = params.EnterpriseNatureId
    client.Business.EnterpriseScaleId = params.EnterpriseScaleId
    //销售负责人为空时为公海客户
    if params.MemberId == 0 {
        client.MemberId = 1
    } else {
        client.MemberId = params.MemberId
    }
    client.MemberId = params.MemberId
    client.CodeStandID = params.CodeStandID
    //if params.Contact.Name != "" {
@@ -215,12 +203,20 @@
        return
    }
    userInfo := utils.GetUserInfo(c)
    if userInfo.UserType == constvar.UserTypeSub {
        if params.SearchMap == nil {
            params.SearchMap = make(map[string]interface{}, 0)
    var isPublic bool
    if params.SearchMap != nil && params.SearchMap["is_public"] != nil {
        if v, ok := params.SearchMap["is_public"].(bool); ok {
            isPublic = v
        }
        params.SearchMap["member_id"] = userInfo.CrmUserId
    }
    if !isPublic {
        userInfo := utils.GetUserInfo(c)
        if userInfo.UserType == constvar.UserTypeSub {
            if params.SearchMap == nil {
                params.SearchMap = make(map[string]interface{}, 0)
            }
            params.SearchMap["member_ids"] = userInfo.SubUserIds
        }
    }
    clients, total, errCode := clientService.GetClientList(params.Page, params.PageSize, params.SearchMap)
api/v1/contact.go
@@ -181,7 +181,7 @@
        if params.SearchMap == nil {
            params.SearchMap = make(map[string]interface{}, 0)
        }
        params.SearchMap["member_id"] = userInfo.CrmUserId
        params.SearchMap["member_ids"] = userInfo.SubUserIds
    }
    contacts, total, errCode := contactService.GetContactList(params.Page, params.PageSize, params.SearchMap, params.ClientId)
api/v1/contract.go
@@ -166,7 +166,7 @@
        if params.SearchMap == nil {
            params.SearchMap = make(map[string]interface{}, 0)
        }
        params.SearchMap["member_id"] = userInfo.CrmUserId
        params.SearchMap["member_ids"] = userInfo.SubUserIds
    }
    contracts, total, errCode := contractService.GetContractList(params.Page, params.PageSize, params.SearchMap)
api/v1/followRecord.go
@@ -246,7 +246,7 @@
        if params.SearchMap == nil {
            params.SearchMap = make(map[string]interface{}, 0)
        }
        params.SearchMap["member_id"] = userInfo.CrmUserId
        params.SearchMap["member_ids"] = userInfo.SubUserIds
    }
    followRecords, total, errCode := followRecordService.GetFollowRecordList(params.Page, params.PageSize, params.SearchMap)
api/v1/getAllData.go
@@ -21,7 +21,7 @@
        return
    }
    errCode, data := allDataServer.GetAllData()
    errCode, data := allDataServer.GetAllData(c)
    if errCode != ecode.OK {
        ctx.Fail(errCode)
        return
api/v1/invoice.go
@@ -1,6 +1,7 @@
package v1
import (
    "aps_crm/constvar"
    "aps_crm/model"
    "aps_crm/model/request"
    "aps_crm/model/response"
@@ -8,6 +9,7 @@
    "aps_crm/pkg/ecode"
    "aps_crm/pkg/structx"
    "aps_crm/service"
    "aps_crm/utils"
    "github.com/gin-gonic/gin"
    "strconv"
)
@@ -123,6 +125,11 @@
        return
    }
    userInfo := utils.GetUserInfo(c)
    if userInfo.UserType == constvar.UserTypeSub {
        params.PrincipalIds = userInfo.SubUserIds
    }
    invoice, total, errCode := service.NewInvoiceService().GetInvoiceList(params)
    if errCode != ecode.OK {
        ctx.Fail(errCode)
api/v1/masterOrder.go
@@ -168,7 +168,7 @@
        if params.SearchMap == nil {
            params.SearchMap = make(map[string]interface{}, 0)
        }
        params.SearchMap["member_id"] = userInfo.CrmUserId
        params.SearchMap["member_ids"] = userInfo.SubUserIds
    }
    masterOrders, total, errCode := masterOrderService.GetMasterOrderList(params.Page, params.PageSize, params.SearchMap)
api/v1/plan.go
@@ -98,7 +98,6 @@
    ctx.Ok()
}
func checkPlanParams(plan request.Plan) (errCode int, p model.Plan) {
    //if plan.Number == "" {
    //    return ecode.InvalidParams, p
@@ -155,7 +154,7 @@
    }
    ctx.OkWithDetailed(response.PlanResponse{
        List: plans,
        List:  plans,
        Count: int(total),
    })
}
}
api/v1/quotation.go
@@ -186,7 +186,7 @@
        if params.SearchMap == nil {
            params.SearchMap = make(map[string]interface{}, 0)
        }
        params.SearchMap["member_id"] = userInfo.CrmUserId
        params.SearchMap["member_ids"] = userInfo.SubUserIds
    }
    quotations, total, errCode := quotationService.GetQuotationList(params.Page, params.PageSize, params.SearchMap)
api/v1/receipt.go
@@ -1,11 +1,13 @@
package v1
import (
    "aps_crm/constvar"
    "aps_crm/model/request"
    "aps_crm/model/response"
    "aps_crm/pkg/contextx"
    "aps_crm/pkg/ecode"
    "aps_crm/service"
    "aps_crm/utils"
    "github.com/gin-gonic/gin"
    "strconv"
)
@@ -99,6 +101,11 @@
        return
    }
    userInfo := utils.GetUserInfo(c)
    if userInfo.UserType == constvar.UserTypeSub {
        params.PrincipleIds = userInfo.SubUserIds
    }
    receipt, total, errCode := service.NewReceiptService().GetReceiptList(params)
    if errCode != ecode.OK {
        ctx.Fail(errCode)
api/v1/saleChance.go
@@ -226,7 +226,7 @@
        if params.SearchMap == nil {
            params.SearchMap = make(map[string]interface{}, 0)
        }
        params.SearchMap["member_id"] = userInfo.CrmUserId
        params.SearchMap["member_ids"] = userInfo.SubUserIds
    }
    saleChances, total, errCode := saleChanceService.GetSaleChanceList(params.Page, params.PageSize, params.SearchMap)
api/v1/salesDetails.go
@@ -189,7 +189,7 @@
    var memberIds []int
    userInfo := utils.GetUserInfo(c)
    if userInfo.UserType == constvar.UserTypeSub {
        memberIds = []int{userInfo.CrmUserId}
        memberIds = userInfo.SubUserIds
    }
    salesDetailss, total, errCode := salesDetailsService.GetSalesDetailsList(params, memberIds)
api/v1/salesLeads.go
@@ -175,7 +175,7 @@
        if params.SearchMap == nil {
            params.SearchMap = make(map[string]interface{}, 0)
        }
        params.SearchMap["member_id"] = userInfo.CrmUserId
        params.SearchMap["member_ids"] = userInfo.SubUserIds
    }
    salesLeadss, total, errCode := salesLeadsService.GetSalesLeadsList(params.Page, params.PageSize, params.SearchMap)
api/v1/salesRefund.go
@@ -184,7 +184,7 @@
    var memberIds []int
    userInfo := utils.GetUserInfo(c)
    if userInfo.UserType == constvar.UserTypeSub {
        memberIds = []int{userInfo.CrmUserId}
        memberIds = userInfo.SubUserIds
    }
    salesRefunds, total, errCode := salesRefundService.GetSalesRefundList(params.Page, params.PageSize, params.KeywordType, params.Keyword, params.SourceId, memberIds)
api/v1/salesReturn.go
@@ -179,7 +179,7 @@
    var memberIds []int
    userInfo := utils.GetUserInfo(c)
    if userInfo.UserType == constvar.UserTypeSub {
        memberIds = []int{userInfo.CrmUserId}
        memberIds = userInfo.SubUserIds
    }
    salesReturns, total, errCode := salesReturnService.GetSalesReturnList(params, memberIds)
api/v1/serviceContract.go
@@ -134,7 +134,7 @@
    var memberIds []int
    userInfo := utils.GetUserInfo(c)
    if userInfo.UserType == constvar.UserTypeSub {
        memberIds = []int{userInfo.CrmUserId}
        memberIds = userInfo.SubUserIds
    }
    serviceContracts, total, errCode := serviceContractService.GetServiceContractList(params, memberIds)
api/v1/serviceFollowup.go
@@ -165,7 +165,7 @@
    var memberIds []int
    userInfo := utils.GetUserInfo(c)
    if userInfo.UserType == constvar.UserTypeSub {
        memberIds = []int{userInfo.CrmUserId}
        memberIds = userInfo.SubUserIds
    }
    serviceFollowups, total, errCode := serviceFollowupService.GetServiceFollowupList(params.Page, params.PageSize, params.KeywordType, params.Keyword, params.ServiceOrderId, memberIds)
api/v1/serviceOrder.go
@@ -153,7 +153,7 @@
    var memberIds []int
    userInfo := utils.GetUserInfo(c)
    if userInfo.UserType == constvar.UserTypeSub {
        memberIds = []int{userInfo.CrmUserId}
        memberIds = userInfo.SubUserIds
    }
    serviceOrder, total, errCode := service.NewServiceOrderService().GetServiceOrderList(params.Page, params.PageSize, params.QueryClass, params.KeywordType, params.Keyword, params.ServiceContractId, params.SalesDetailsId, memberIds)
api/v1/subOrder.go
@@ -157,7 +157,7 @@
        if params.SearchMap == nil {
            params.SearchMap = make(map[string]interface{}, 0)
        }
        params.SearchMap["member_id"] = userInfo.CrmUserId
        params.SearchMap["member_ids"] = userInfo.SubUserIds
    }
    subOrders, total, errCode := subOrderService.GetSubOrderList(params.Page, params.PageSize, params.SearchMap)
constvar/const.go
@@ -32,13 +32,6 @@
    UserTypeSub                         // 子账户
)
type NotAdmin int
const (
    NotAdminAll NotAdmin = iota // 公海
    NotAdminYes                 // 我的客户
)
type SalesStatus int
const (
main.go
@@ -48,7 +48,6 @@
        ReadTimeout:  5 * time.Second,
        WriteTimeout: 5 * time.Second,
    }
    //启动grpc客户端
    go v1.InitProductServiceConn()
    go middleware.InitUserConn()
@@ -70,9 +69,9 @@
            panic(fmt.Sprintf("grpc server init error: %v", err.Error()))
        }
    }()
    //c := cron.New()
    //c.AddFunc("@every 15s", service.SyncUserInfo) // 每15秒同步一次
    //c.Start()
    middleware.InitRefreshUserManager(5, 5, 3600)
    middleware.RunRefreshUser() ///定时对活跃用户更新用户详情
    logx.Error(server.ListenAndServe().Error())
}
@@ -82,6 +81,7 @@
    signal.Notify(quit, syscall.SIGKILL, syscall.SIGQUIT, syscall.SIGINT, syscall.SIGTERM)
    <-quit
    middleware.StopRefreshUser()
    v1.CloseProductServiceConn()
    v1.CloseCodeServiceConn()
    v1.CloseProductInventoryServiceConn()
middleware/jwt.go
@@ -98,20 +98,26 @@
        // parseToken 解析token包含的信息
        claims, err := j.ParseToken(token)
        if err != nil {
            if err == utils.TokenExpired {
                c.Next()
                return
            }
            c.Next()
            ctx.Fail(ecode.JWTDisabled)
            c.Abort()
            return
        }
        userInfo := service.GetUserBaseCache(claims.UserId)
        if userInfo == nil {
            SyncUserInfo(claims.UserId)
            SyncUserInfo([]string{claims.UserId})
            userInfo = service.GetUserBaseCache(claims.UserId)
        }
        if userInfo == nil {
            ctx.Fail(ecode.JWTDisabled)
            c.Abort()
            return
        }
        SetActiveTime(claims.UserId)
        claims.CrmUserId = userInfo.UserId
        claims.NickName = userInfo.NickName
        claims.SubUserIds = userInfo.SubUserIds
        c.Set("claims", claims)
        if CheckAuth(c.Request.URL.Path, token) {
            c.Next()
middleware/refresh_user.go
New file
@@ -0,0 +1,138 @@
package middleware
import (
    "aps_crm/pkg/logx"
    "context"
    "fmt"
    "sync"
    "sync/atomic"
    "time"
)
// RefreshUserManager 定时拉取活跃用户的信息(包含下属id)
type RefreshUserManager struct {
    RunFlag                   int32
    StartRemoveUserFlag       int32
    StartRefreshUserFlag      int32
    Users                     map[string]*CurrentActiveUser
    mu                        sync.RWMutex
    ctx                       context.Context
    expireSecond              int64
    intervalRemoveUserMinute  int
    intervalRefreshUserMinute int
    cancel                    func()
}
type CurrentActiveUser struct {
    UserID         string
    lastActiveTime int64
}
var defaultRefreshUserManager *RefreshUserManager
func InitRefreshUserManager(intervalRefreshUserMinute, intervalRemoveMinute int, expireSecond int64) {
    if intervalRefreshUserMinute == 0 {
        intervalRefreshUserMinute = 5
    }
    if intervalRemoveMinute > 0 && expireSecond == 0 {
        expireSecond = int64(intervalRemoveMinute * 60 * 12)
    }
    ctx, cancel := context.WithCancel(context.Background())
    defaultRefreshUserManager = &RefreshUserManager{
        expireSecond:              expireSecond,
        intervalRemoveUserMinute:  intervalRemoveMinute,
        intervalRefreshUserMinute: intervalRefreshUserMinute,
        ctx:                       ctx,
        cancel:                    cancel,
        Users:                     map[string]*CurrentActiveUser{},
    }
}
func RunRefreshUser() {
    if !atomic.CompareAndSwapInt32(&defaultRefreshUserManager.RunFlag, 0, 1) {
        return
    }
    go defaultRefreshUserManager.refreshUserInfo()
    go defaultRefreshUserManager.removeInActiveUser()
}
func StopRefreshUser() {
    defaultRefreshUserManager.cancel()
}
func SetActiveTime(userID string) {
    defaultRefreshUserManager.setActiveTime(userID)
}
// RefreshActiveTime 更新用户活跃时间
func (r *RefreshUserManager) setActiveTime(userID string) {
    r.mu.Lock()
    defer r.mu.Unlock()
    if r.Users[userID] == nil {
        r.Users[userID] = &CurrentActiveUser{
            UserID:         userID,
            lastActiveTime: time.Now().Unix(),
        }
        logx.Infof("add active user :%+v", r.Users[userID])
    } else {
        r.Users[userID].lastActiveTime = time.Now().Unix()
        logx.Infof("refresh active time, user:%+v", r.Users[userID])
    }
}
func (r *RefreshUserManager) removeInActiveUser() {
    if !atomic.CompareAndSwapInt32(&r.StartRemoveUserFlag, 0, 1) {
        return
    }
    if r.intervalRemoveUserMinute == 0 { //不清理
        return
    }
    ticker := time.NewTicker(time.Minute * time.Duration(r.intervalRemoveUserMinute))
    for {
        select {
        case <-ticker.C:
            nowTs := time.Now().Unix()
            var users []*CurrentActiveUser
            r.mu.RLock()
            for _, user := range r.Users {
                users = append(users, user)
            }
            r.mu.RUnlock()
            for _, user := range users {
                if nowTs-user.lastActiveTime > r.expireSecond {
                    r.mu.Lock()
                    logx.Infof("removed in active user:%+v", user)
                    delete(r.Users, user.UserID)
                    r.mu.Unlock()
                }
            }
        case <-r.ctx.Done():
            fmt.Println("stop RemoveInActiveUser.")
            return
        }
    }
}
func (r *RefreshUserManager) refreshUserInfo() {
    if !atomic.CompareAndSwapInt32(&r.StartRefreshUserFlag, 0, 1) {
        return
    }
    ticker := time.NewTicker(time.Minute * time.Duration(r.intervalRefreshUserMinute))
    for {
        select {
        case <-ticker.C:
            r.mu.RLock()
            userIds := make([]string, len(r.Users))
            for userID := range r.Users {
                userIds = append(userIds, userID)
            }
            r.mu.RUnlock()
            if len(userIds) != 0 {
                logx.Infof("RefreshUserInfo, user ids: ", userIds)
                SyncUserInfo(userIds)
            }
        case <-r.ctx.Done():
            fmt.Println("stop RefreshUserInfo.")
            return
        }
    }
}
middleware/user.go
@@ -7,9 +7,9 @@
    "aps_crm/pkg/logx"
    "aps_crm/proto/user"
    "context"
    "fmt"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/insecure"
    "strings"
    "time"
)
@@ -59,10 +59,13 @@
    return rsp.Result
}
func SyncUserInfo(uuid string) {
func SyncUserInfo(uuid []string) {
    cli := user.NewUserServiceClient(userConn)
    var users = []*user.User{
        {Uuid: uuid},
    var users []*user.User
    for _, id := range uuid {
        users = append(users, &user.User{
            Uuid: id,
        })
    }
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()
@@ -72,15 +75,19 @@
        return
    }
    fmt.Printf("Synced: %v, Message: %s", r.List, r.Message)
    logx.Infof("Synced: %v, Message: %s", r.List, r.Message)
    for _, member := range r.List {
        err = model.NewUserSearch(nil).Upsert(model.User{
        userRecord := model.User{
            UUID:     member.Uuid,
            Username: member.Username,
            UserType: constvar.UserType(member.Usertype),
            NickName: member.Nickname,
        })
        }
        if member.SubUserIds != nil {
            userRecord.SubUserIds = strings.Join(member.SubUserIds, ",")
        }
        err = model.NewUserSearch(nil).Upsert(userRecord, member.SubUserQueried)
        if err != nil {
            logx.Errorf("sync user error: %v", err.Error())
            continue
model/client.go
@@ -117,18 +117,22 @@
                    db = db.Joins("Member").Where("Member.username LIKE ?", "%"+v+"%")
                }
            case int, uint, int64, float64:
            case int, uint, int64, float64, bool:
                if key == "id" || key == "client_type_id" || key == "client_status_id" || key == "member_id" {
                    db = db.Where(key+" = ?", v)
                }
                if key == "not_admin" {
                    if v == float64(constvar.NotAdminYes) {
                        db = db.Where("clients.member_id != ?", constvar.UserTypeSuper)
                    } else {
                        db = db.Where("clients.member_id = ?", constvar.UserTypeSuper)
                if key == "is_public" {
                    if val, ok := v.(bool); ok {
                        if val {
                            db = db.Where("clients.member_id = ?", 0)
                        }
                    }
                }
            case []int:
                if key == "member_ids" {
                    db = db.Where("clients.member_id in ?", v)
                }
            }
        }
model/contact.go
@@ -100,6 +100,10 @@
                if key == "client_id" {
                    db = db.Where("client_id = ? and is_first = true", v)
                }
            case []int:
                if key == "member_ids" {
                    db = db.Where("contacts.member_id in ?", v)
                }
            }
        }
    }
model/contract.go
@@ -80,6 +80,10 @@
                if key == "member_id" {
                    db = db.Where(key+"= ?", v)
                }
            case []int:
                if key == "member_ids" {
                    db = db.Where("contract.member_id in ?", v)
                }
            }
        }
    }
model/followRecord.go
@@ -106,6 +106,10 @@
                if key == "client_id" || key == "contact_id" || key == "sales_leads_id" || key == "sale_chance_id" || key == "member_id" {
                    db = db.Where(key+" = ?", v)
                }
            case []int:
                if key == "member_ids" {
                    db = db.Where("follow_records.member_id in ?", v)
                }
            }
        }
    }
model/invoice.go
@@ -36,12 +36,13 @@
    // InvoiceSearch 销售发票搜索条件
    InvoiceSearch struct {
        Invoice
        Orm         *gorm.DB
        QueryClass  constvar.InvoiceQueryClass
        KeywordType constvar.InvoiceKeywordType
        Keyword     string
        PageNum     int
        PageSize    int
        Orm          *gorm.DB
        QueryClass   constvar.InvoiceQueryClass
        KeywordType  constvar.InvoiceKeywordType
        Keyword      string
        PageNum      int
        PageSize     int
        PrincipalIds []int
    }
)
@@ -65,6 +66,11 @@
    return slf
}
func (slf *InvoiceSearch) SetPrincipalIds(principalIds []int) *InvoiceSearch {
    slf.PrincipalIds = principalIds
    return slf
}
func (slf *InvoiceSearch) build() *gorm.DB {
    var db = slf.Orm.Model(&Invoice{})
    if slf.Id != 0 {
@@ -81,6 +87,9 @@
    if slf.Number != "" {
        db.Where("number = ?", slf.Number)
    }
    if len(slf.PrincipalIds) > 0 {
        db = db.Where("principal_id in ?", slf.PrincipalIds)
    }
    return db
}
model/masterOrder.go
@@ -72,6 +72,10 @@
                if key == "client_id" || key == "member_id" || key == "money" {
                    db = db.Where(key+" = ?", v)
                }
            case []int:
                if key == "member_ids" {
                    db = db.Where("master_order.member_id in ?", v)
                }
            }
        }
    }
model/plan.go
@@ -25,11 +25,12 @@
    PlanSearch struct {
        Plan
        Orm      *gorm.DB
        Keyword  string
        OrderBy  string
        PageNum  int
        PageSize int
        Orm       *gorm.DB
        Keyword   string
        OrderBy   string
        PageNum   int
        PageSize  int
        MemberIds []int
    }
)
@@ -50,6 +51,9 @@
    }
    if slf.Id != 0 {
        db = db.Where("id = ?", slf.Id)
    }
    if len(slf.MemberIds) != 0 {
        db = db.Where("member_id in ?", slf.MemberIds)
    }
    return db
@@ -97,6 +101,11 @@
    return slf
}
func (slf *PlanSearch) SetMemberIds(ids []int) *PlanSearch {
    slf.MemberIds = ids
    return slf
}
func (slf *PlanSearch) SetKeyword(keyword string) *PlanSearch {
    slf.Keyword = keyword
    return slf
model/quotation.go
@@ -88,6 +88,10 @@
                if key == "client_id" || key == "sale_chance_id" || key == "member_id" {
                    db = db.Where(key+" = ?", v)
                }
            case []int:
                if key == "member_ids" {
                    db = db.Where("quotation.member_id in ?", v)
                }
            }
        }
    }
model/receipt.go
@@ -34,12 +34,13 @@
    // ReceiptSearch 收款单搜索条件
    ReceiptSearch struct {
        Receipt
        Orm         *gorm.DB
        QueryClass  constvar.ReceiptQueryClass
        KeywordType constvar.ReceiptKeywordType
        Keyword     string
        PageNum     int
        PageSize    int
        Orm          *gorm.DB
        QueryClass   constvar.ReceiptQueryClass
        KeywordType  constvar.ReceiptKeywordType
        Keyword      string
        PageNum      int
        PageSize     int
        PrincipalIds []int
    }
)
@@ -72,6 +73,11 @@
    return slf
}
func (slf *ReceiptSearch) SetPrincipalIds(principalIds []int) *ReceiptSearch {
    slf.PrincipalIds = principalIds
    return slf
}
func (slf *ReceiptSearch) SetPage(page, size int) *ReceiptSearch {
    slf.PageNum, slf.PageSize = page, size
    return slf
@@ -91,6 +97,9 @@
    if slf.ClientId != 0 {
        db = db.Where("client_id = ?", slf.ClientId)
    }
    if len(slf.PrincipalIds) != 0 {
        db = db.Where("principal_id in ?", slf.PrincipalIds)
    }
    return db
}
model/request/invoice.go
@@ -44,6 +44,7 @@
type GetInvoiceList struct {
    PageInfo
    SourceId   int                        `json:"sourceId"`
    SourceType constvar.InvoiceSourceType `json:"sourceType"` // 源单类型(1销售明细单2服务合同)
    SourceId     int                        `json:"sourceId"`
    SourceType   constvar.InvoiceSourceType `json:"sourceType"` // 源单类型(1销售明细单2服务合同)
    PrincipalIds []int
}
model/request/jwt.go
@@ -10,8 +10,9 @@
    BaseClaims
    BufferTime int64
    jwt.StandardClaims
    CrmUserId int
    NickName  string
    CrmUserId  int
    NickName   string
    SubUserIds []int //包含自身的id
}
type BaseClaims struct {
model/request/receipt.go
@@ -16,7 +16,8 @@
type GetReceiptList struct {
    PageInfo
    SourceType constvar.ReceiptSourceType `json:"sourceType" form:"sourceType"` //来源类型(1销售明细单2服务合同3销售发票4收款计划5出库单)
    SourceId   int                        `json:"sourceId" form:"sourceId"`
    ClientId   int                        `json:"clientId"  form:"clientId"` //客户id
    SourceType   constvar.ReceiptSourceType `json:"sourceType" form:"sourceType"` //来源类型(1销售明细单2服务合同3销售发票4收款计划5出库单)
    SourceId     int                        `json:"sourceId" form:"sourceId"`
    ClientId     int                        `json:"clientId"  form:"clientId"` //客户id
    PrincipleIds []int
}
model/saleChance.go
@@ -121,6 +121,10 @@
                if key == "member_id" || key == "budget" || key == "projected_amount" || key == "client_id" {
                    db = db.Where(key+" = ?", v)
                }
            case []int:
                if key == "member_ids" {
                    db = db.Where("sale_chance.member_id in ?", v)
                }
            }
        }
    }
model/salesLeads.go
@@ -92,8 +92,9 @@
                }
            case int:
                if key == "member_id" {
                    db = db.Where("sales_leads.member_id = ?", v)
            case []int:
                if key == "member_ids" {
                    db = db.Where("sales_leads.member_id in ?", v)
                }
            }
        }
model/serviceFeeManage.go
@@ -28,6 +28,7 @@
        OrderBy     string
        PageNum     int
        PageSize    int
        MemberIds   []int
    }
)
@@ -53,6 +54,11 @@
    if slf.ClientId != 0 {
        db.Where("client_id = ?", slf.ClientId)
    }
    if len(slf.MemberIds) > 0 {
        db.Where("service_fee_manage.member_id in ?", slf.MemberIds)
    }
    switch slf.QueryClass {
    case constvar.ServiceFeeQueryClassExpireLessThen60Days:
        db = db.Where("latest_date > ? and latest_date < ?", time.Now(), time.Now().AddDate(0, 0, 60))
@@ -120,6 +126,11 @@
    return slf
}
func (slf *ServiceFeeManageSearch) SetMemberIds(ids []int) *ServiceFeeManageSearch {
    slf.MemberIds = ids
    return slf
}
func (slf *ServiceFeeManageSearch) SetKeywordType(keyword constvar.ServiceFeeKeywordType) *ServiceFeeManageSearch {
    slf.KeywordType = keyword
    return slf
model/serviceOrder.go
@@ -132,7 +132,7 @@
    }
    if len(slf.ServiceManIds) > 0 {
        db = db.Where("service_man_id in ?", slf.ServiceManIds)
        db = db.Where("service_order.service_man_id in ?", slf.ServiceManIds)
    }
    if slf.ServiceNumber != "" {
        db = db.Where("service_number = ?", slf.ServiceNumber)
model/subOrder.go
@@ -81,6 +81,10 @@
                if key == "member_id" {
                    db = db.Where("sub_order.member_id = ?", v)
                }
            case []int:
                if key == "member_ids" {
                    db = db.Where("sub_order.member_id in ?", v)
                }
            }
        }
    }
model/user.go
@@ -5,14 +5,13 @@
    "aps_crm/pkg/mysqlx"
    "fmt"
    "gorm.io/gorm"
    "gorm.io/gorm/clause"
)
type (
    // User token里边把用户ID、父用户ID、角色都带上
    User struct {
        ID           int               `json:"id" gorm:"column:id;primary_key;AUTO_INCREMENT"`
        UUID         string            `json:"uuid" gorm:"unique;type:varchar(255);comment:用户ID"`
        UUID         string            `json:"uuid" gorm:"uniqueIndex;type:varchar(255);comment:用户ID"`
        Username     string            `json:"username" gorm:"index;type:varchar(255);comment:用户登录名"`
        UserType     constvar.UserType `json:"userType" gorm:"type:int(11);comment:用户类型 1超级管理员 2主账户 3子账户"`
        Password     string            `json:"-"  gorm:"type:varchar(255);comment:用户登录密码"`
@@ -27,6 +26,7 @@
        MenuIds      []uint            `json:"menuIds" gorm:"-"`                              // 菜单ID列表
        AuthorityId  uint              `json:"authorityId" gorm:"default:888;comment:用户角色ID"` // 用户角色ID
        Authority    Authority         `json:"authority" gorm:"foreignKey:AuthorityId"`
        SubUserIds   string            `json:"subUserIds" gorm:"sub_user_ids"` //下属员工用户id,用逗号分开
        gorm.Model   `json:"-"`
    }
@@ -37,6 +37,7 @@
        PageNum  int
        PageSize int
        Orm      *gorm.DB
        IDs      []int
    }
)
@@ -76,6 +77,11 @@
    return slf
}
func (slf *UserSearch) SetUserIds(userIds []int) *UserSearch {
    slf.IDs = userIds
    return slf
}
func (slf *UserSearch) SetUserName(username string) *UserSearch {
    slf.Username = username
    return slf
@@ -103,6 +109,14 @@
    if slf.Order != "" {
        db = db.Order(slf.Order)
    }
    if slf.ID != 0 {
        db = db.Where("id = ?", slf.ID)
    }
    if len(slf.IDs) > 0 {
        db = db.Where("id in ?", slf.IDs)
    }
    return db
@@ -278,15 +292,45 @@
    return records, nil
}
func (slf *UserSearch) Upsert(record User) error {
    var db = slf.build()
func (slf *UserSearch) Upsert(record User, SubUserQueried bool) error {
    if err := db.Clauses(clause.OnConflict{
        Columns:   []clause.Column{{Name: "uuid"}},
        DoUpdates: clause.AssignmentColumns([]string{"uuid", "username", "user_type", "nick_name"}),
    }).Create(&record).Error; err != nil {
        return fmt.Errorf("first or create err: %v, record: %+v", err, record)
    var db = slf.SetId(record.UUID).build()
    old, err := slf.First()
    if err == gorm.ErrRecordNotFound {
        if err := db.Create(&record).Error; err != nil {
            return fmt.Errorf("create user err: %v, record: %+v", err, record)
        }
    } else if old.Username != record.Username ||
        old.UserType != record.UserType ||
        old.NickName != record.NickName ||
        SubUserQueried && old.SubUserIds != record.SubUserIds {
        old.Username = record.Username
        old.UserType = record.UserType
        old.NickName = record.NickName
        old.SubUserIds = record.SubUserIds
        if err := db.Save(&old).Error; err != nil {
            return fmt.Errorf("update user err: %v, old record: %+v", err, old)
        }
    }
    return nil
}
type IdPair struct {
    ID   int    `json:"id" gorm:"column:id;primary_key;AUTO_INCREMENT"`
    UUID string `json:"uuid" gorm:"unique;type:varchar(255);comment:用户ID"`
}
func (slf *UserSearch) UUID2CrmUserId(userIds []string) ([]*IdPair, error) {
    var (
        records = make([]*IdPair, 0)
        db      = slf.Orm.Model(&User{})
    )
    db = db.Where("uuid in ?", userIds)
    if err := db.Select("user.id, user.uuid").Find(&records).Error; err != nil {
        return records, fmt.Errorf("find all err: %v", err)
    }
    return records, nil
}
proto/user.proto
@@ -14,7 +14,8 @@
  string username = 2;
  int32 usertype = 3;
  string nickname = 4;
  // ... other fields
  repeated string sub_user_ids = 5;
  bool sub_user_queried = 6;
}
message UserRequest {
proto/user/user.pb.go
@@ -25,10 +25,12 @@
    sizeCache     protoimpl.SizeCache
    unknownFields protoimpl.UnknownFields
    Uuid     string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"`
    Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
    Usertype int32  `protobuf:"varint,3,opt,name=usertype,proto3" json:"usertype,omitempty"`
    Nickname string `protobuf:"bytes,4,opt,name=nickname,proto3" json:"nickname,omitempty"` // ... other fields
    Uuid           string   `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"`
    Username       string   `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
    Usertype       int32    `protobuf:"varint,3,opt,name=usertype,proto3" json:"usertype,omitempty"`
    Nickname       string   `protobuf:"bytes,4,opt,name=nickname,proto3" json:"nickname,omitempty"`
    SubUserIds     []string `protobuf:"bytes,5,rep,name=sub_user_ids,json=subUserIds,proto3" json:"sub_user_ids,omitempty"`
    SubUserQueried bool     `protobuf:"varint,6,opt,name=sub_user_queried,json=subUserQueried,proto3" json:"sub_user_queried,omitempty"`
}
func (x *User) Reset() {
@@ -89,6 +91,20 @@
        return x.Nickname
    }
    return ""
}
func (x *User) GetSubUserIds() []string {
    if x != nil {
        return x.SubUserIds
    }
    return nil
}
func (x *User) GetSubUserQueried() bool {
    if x != nil {
        return x.SubUserQueried
    }
    return false
}
type UserRequest struct {
@@ -331,43 +347,48 @@
var file_user_proto_rawDesc = []byte{
    0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x75, 0x73,
    0x65, 0x72, 0x22, 0x6e, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75,
    0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x1a,
    0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
    0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73,
    0x65, 0x72, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x75, 0x73,
    0x65, 0x72, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61,
    0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61,
    0x6d, 0x65, 0x22, 0x2f, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
    0x74, 0x12, 0x20, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
    0x32, 0x0a, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73,
    0x65, 0x72, 0x73, 0x22, 0x72, 0x0a, 0x0c, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f,
    0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
    0x05, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61,
    0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
    0x65, 0x12, 0x1e, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32,
    0x0a, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x4c, 0x69, 0x73,
    0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03,
    0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0x48, 0x0a, 0x0c, 0x43, 0x68, 0x65, 0x63, 0x6b,
    0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, 0x69, 0x50, 0x61,
    0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x69, 0x50, 0x61, 0x74,
    0x68, 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x18,
    0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x79, 0x70,
    0x65, 0x22, 0x55, 0x0a, 0x0d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
    0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
    0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
    0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
    0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
    0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x32, 0x7a, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72,
    0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x53, 0x79, 0x6e, 0x63, 0x55,
    0x73, 0x65, 0x72, 0x12, 0x11, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52,
    0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73,
    0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0d, 0x55, 0x73,
    0x65, 0x72, 0x4d, 0x65, 0x6e, 0x75, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x12, 0x2e, 0x75, 0x73,
    0x65, 0x72, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
    0x13, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70,
    0x6f, 0x6e, 0x73, 0x65, 0x42, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x62, 0x06,
    0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
    0x65, 0x72, 0x22, 0xba, 0x01, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x75,
    0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12,
    0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
    0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x75,
    0x73, 0x65, 0x72, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x75,
    0x73, 0x65, 0x72, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e,
    0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e,
    0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f,
    0x69, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x75, 0x62, 0x55, 0x73,
    0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x75, 0x62, 0x5f, 0x75, 0x73, 0x65,
    0x72, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52,
    0x0e, 0x73, 0x75, 0x62, 0x55, 0x73, 0x65, 0x72, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x64, 0x22,
    0x2f, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20,
    0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e,
    0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73,
    0x22, 0x72, 0x0a, 0x0c, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
    0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04,
    0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18,
    0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1e,
    0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x75,
    0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14,
    0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74,
    0x6f, 0x74, 0x61, 0x6c, 0x22, 0x48, 0x0a, 0x0c, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71,
    0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, 0x69, 0x50, 0x61, 0x74, 0x68, 0x18,
    0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x69, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1e,
    0x0a, 0x0a, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01,
    0x28, 0x05, 0x52, 0x0a, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x22, 0x55,
    0x0a, 0x0d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
    0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63,
    0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02,
    0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a,
    0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72,
    0x65, 0x73, 0x75, 0x6c, 0x74, 0x32, 0x7a, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72,
    0x76, 0x69, 0x63, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x53, 0x79, 0x6e, 0x63, 0x55, 0x73, 0x65, 0x72,
    0x12, 0x11, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75,
    0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52,
    0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0d, 0x55, 0x73, 0x65, 0x72, 0x4d,
    0x65, 0x6e, 0x75, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x12, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e,
    0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x75,
    0x73, 0x65, 0x72, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
    0x65, 0x42, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f,
    0x74, 0x6f, 0x33,
}
var (
service/assign.go
@@ -1,41 +1,43 @@
package service
import (
    "aps_crm/model"
    "aps_crm/pkg/ecode"
)
type AssignService struct{}
type Assign interface {
    Assign(id int) error
}
func (AssignService) Assign(memberId int, ids []int, modelType string) int {
    // check member exist
    _, err := model.NewUserSearch(nil).SetUserId(memberId).First()
    if err != nil {
        return ecode.UserNotExist
    }
    var errCode int
    switch modelType {
    case "client":
        errCode = ClientService{}.Assign(ids, memberId)
    case "salesLead":
        errCode = SalesLeadsService{}.Assign(ids, memberId)
    case "contact":
        errCode = ContactService{}.Assign(ids, memberId)
    case "followRecord":
        errCode = FollowRecordService{}.Assign(ids, memberId)
    default:
        errCode = ecode.AssignWrongModelType
    }
    if errCode != ecode.OK {
        return errCode
    }
    return ecode.OK
}
package service
import (
    "aps_crm/model"
    "aps_crm/pkg/ecode"
)
type AssignService struct{}
type Assign interface {
    Assign(id int) error
}
func (AssignService) Assign(memberId int, ids []int, modelType string) int {
    // check member exist
    if memberId != 0 {
        _, err := model.NewUserSearch(nil).SetUserId(memberId).First()
        if err != nil {
            return ecode.UserNotExist
        }
    }
    var errCode int
    switch modelType {
    case "client":
        errCode = ClientService{}.Assign(ids, memberId)
    case "salesLead":
        errCode = SalesLeadsService{}.Assign(ids, memberId)
    case "contact":
        errCode = ContactService{}.Assign(ids, memberId)
    case "followRecord":
        errCode = FollowRecordService{}.Assign(ids, memberId)
    default:
        errCode = ecode.AssignWrongModelType
    }
    if errCode != ecode.OK {
        return errCode
    }
    return ecode.OK
}
service/dataServer.go
@@ -1,13 +1,16 @@
package service
import (
    "aps_crm/constvar"
    "aps_crm/model/response"
    "aps_crm/pkg/ecode"
    "aps_crm/utils"
    "github.com/gin-gonic/gin"
)
type DataServer struct{}
func (DataServer) GetAllData() (errCode int, data response.DataResponse) {
func (DataServer) GetAllData(c *gin.Context) (errCode int, data response.DataResponse) {
    // get country list
    countryList, _ := ServiceGroup.GetCountryList()
    data.Country = countryList
@@ -73,7 +76,14 @@
    data.RegularCustomers = regularCustomerList
    // get Member list
    memberList, _ := ServiceGroup.GetUserList()
    var memberIds []int
    userInfo := utils.GetUserInfo(c)
    if userInfo.UserType == constvar.UserTypeSub {
        memberIds = userInfo.SubUserIds
    }
    memberList, _ := ServiceGroup.GetUserList(memberIds)
    data.Member = memberList
    // get Department list
service/invoice.go
@@ -140,7 +140,7 @@
}
func (InvoiceService) GetInvoiceList(params request.GetInvoiceList) ([]*model.Invoice, int64, int) {
    list, total, err := model.NewInvoiceSearch().SetSourceId(params.SourceId).SetSourceType(params.SourceType).Find()
    list, total, err := model.NewInvoiceSearch().SetSourceId(params.SourceId).SetSourceType(params.SourceType).SetPrincipalIds(params.PrincipalIds).Find()
    if err != nil {
        return nil, 0, ecode.DBErr
    }
service/lru.go
@@ -2,37 +2,50 @@
import (
    "github.com/hashicorp/golang-lru/v2/expirable"
    "strings"
    "time"
)
type UserBaseInfo struct {
    UserId   int
    NickName string
    UserId     int
    NickName   string
    SubUserIds []int
}
var userCache *expirable.LRU[string, *UserBaseInfo]
func init() {
    //make cache with 5 minutes TTL and 100 max keys
    userCache = expirable.NewLRU[string, *UserBaseInfo](100, nil, time.Minute*5)
    userCache = expirable.NewLRU[string, *UserBaseInfo](100, nil, time.Minute*1) //todo zq 暂时改成 1分钟
}
func GetUserBaseCache(adminUserId string) *UserBaseInfo {
    userCache, ok := userCache.Get(adminUserId)
    cache, ok := userCache.Get(adminUserId)
    if !ok {
        userService := UserService{}
        userRecord, err := userService.GetUserInfo(adminUserId)
        if err != nil {
            return nil
        }
        var subIds []int
        if userRecord.SubUserIds != "" {
            subIds, _, err = userService.UUID2CrmUserId(strings.Split(userRecord.SubUserIds, ","))
            if err != nil {
                return nil
            }
        }
        subIds = append(subIds, userRecord.ID)
        baseInfo := &UserBaseInfo{
            UserId:   userRecord.ID,
            NickName: userRecord.NickName,
            UserId:     userRecord.ID,
            NickName:   userRecord.NickName,
            SubUserIds: subIds,
        }
        SetUserBaseCache(adminUserId, baseInfo)
        return baseInfo
    }
    return userCache
    return cache
}
func SetUserBaseCache(adminUserId string, user *UserBaseInfo) {
service/receipt.go
@@ -136,6 +136,7 @@
        SetSourceType(params.SourceType).
        SetSourceId(params.SourceId).
        SetClientId(params.ClientId).
        SetPrincipalIds(params.PrincipleIds).
        Find()
    if err != nil {
        return nil, 0, ecode.DBErr
service/user.go
@@ -90,6 +90,20 @@
    })
}
func (userService *UserService) GetUserList() (userList []*model.User, err error) {
    return model.NewUserSearch(nil).FindAll()
func (userService *UserService) GetUserList(userIds []int) (userList []*model.User, err error) {
    return model.NewUserSearch(nil).SetUserIds(userIds).FindAll()
}
func (userService *UserService) UUID2CrmUserId(uuids []string) (crmUserIds []int, m map[string]int, err error) {
    idPairs, err := model.NewUserSearch(nil).UUID2CrmUserId(uuids)
    if err != nil {
        return
    }
    crmUserIds = make([]int, 0, len(idPairs))
    m = make(map[string]int, len(idPairs))
    for _, idPair := range idPairs {
        crmUserIds = append(crmUserIds, idPair.ID)
        m[idPair.UUID] = idPair.ID
    }
    return
}