104 lines
3.5 KiB
Go
104 lines
3.5 KiB
Go
package model
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
|
||
"qnc-server/common/globalkey"
|
||
|
||
"github.com/Masterminds/squirrel"
|
||
"github.com/pkg/errors"
|
||
"github.com/zeromicro/go-zero/core/stores/cache"
|
||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||
)
|
||
|
||
var _ AgentModel = (*customAgentModel)(nil)
|
||
|
||
type (
|
||
// AgentModel is an interface to be customized, add more methods here,
|
||
// and implement the added methods in customAgentModel.
|
||
AgentModel interface {
|
||
agentModel
|
||
// UpdateInTransaction 在事务中更新刚插入的记录,避免 UpdateWithVersion 中的 FindOne 缓存问题
|
||
UpdateInTransaction(ctx context.Context, session sqlx.Session, data *Agent) error
|
||
// CountSubordinatesByTeamLeaderIds 按团队首领 id 统计未删除的直属代理数量(team_leader_id = 传入 id)
|
||
CountSubordinatesByTeamLeaderIds(ctx context.Context, leaderIds []string) (map[string]int64, error)
|
||
}
|
||
|
||
customAgentModel struct {
|
||
*defaultAgentModel
|
||
}
|
||
)
|
||
|
||
// NewAgentModel returns a model for the database table.
|
||
func NewAgentModel(conn sqlx.SqlConn, c cache.CacheConf) AgentModel {
|
||
return &customAgentModel{
|
||
defaultAgentModel: newAgentModel(conn, c),
|
||
}
|
||
}
|
||
|
||
// UpdateInTransaction 在事务中更新刚插入的记录,避免 UpdateWithVersion 中的 FindOne 缓存问题
|
||
// 注意:此方法假设记录刚插入,version 为 0,更新后 version 为 1
|
||
func (m *customAgentModel) UpdateInTransaction(ctx context.Context, session sqlx.Session, data *Agent) error {
|
||
if session == nil {
|
||
return errors.New("session is required for UpdateInTransaction")
|
||
}
|
||
|
||
// 直接执行 SQL UPDATE,避免 FindOne 的缓存问题
|
||
// 字段顺序:user_id, level, region, mobile, wechat_id, team_leader_id, delete_time, del_state, version
|
||
query := fmt.Sprintf("update %s set `user_id`=?, `level`=?, `region`=?, `mobile`=?, `wechat_id`=?, `team_leader_id`=?, `delete_time`=?, `del_state`=?, `version`=? where `id`=? and `version`=?", m.table)
|
||
|
||
// 确保 version 从 0 增加到 1
|
||
oldVersion := data.Version
|
||
data.Version = oldVersion + 1
|
||
|
||
result, err := session.ExecCtx(ctx, query, data.UserId, data.Level, data.Region, data.Mobile, data.WechatId, data.TeamLeaderId, data.DeleteTime, data.DelState, data.Version, data.Id, oldVersion)
|
||
if err != nil {
|
||
return errors.Wrapf(err, "UpdateInTransaction failed")
|
||
}
|
||
|
||
rowsAffected, err := result.RowsAffected()
|
||
if err != nil {
|
||
return errors.Wrapf(err, "UpdateInTransaction failed to get rows affected")
|
||
}
|
||
|
||
if rowsAffected == 0 {
|
||
return errors.Wrapf(ErrNoRowsUpdate, "UpdateInTransaction: no rows updated, version may not match")
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
type teamLeaderSubCountRow struct {
|
||
TeamLeaderId string `db:"team_leader_id"`
|
||
Cnt int64 `db:"cnt"`
|
||
}
|
||
|
||
func (m *customAgentModel) CountSubordinatesByTeamLeaderIds(ctx context.Context, leaderIds []string) (map[string]int64, error) {
|
||
out := make(map[string]int64)
|
||
if len(leaderIds) == 0 {
|
||
return out, nil
|
||
}
|
||
// 不含「自己挂在自己名下」的记录,否则首领会在自己的下级列表里且下级数量虚高
|
||
qb := squirrel.Select("team_leader_id", "COUNT(*) AS cnt").
|
||
From(m.table).
|
||
Where(squirrel.Eq{"del_state": globalkey.DelStateNo}).
|
||
Where(squirrel.Eq{"team_leader_id": leaderIds}).
|
||
Where("`id` <> `team_leader_id`").
|
||
GroupBy("team_leader_id")
|
||
query, args, err := qb.ToSql()
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
var rows []teamLeaderSubCountRow
|
||
if err := m.QueryRowsNoCacheCtx(ctx, &rows, query, args...); err != nil {
|
||
return nil, err
|
||
}
|
||
for _, r := range rows {
|
||
if r.TeamLeaderId != "" {
|
||
out[r.TeamLeaderId] = r.Cnt
|
||
}
|
||
}
|
||
return out, nil
|
||
}
|