Files
qnc-server-v3/app/main/model/agentModel.go
2026-05-13 14:43:10 +08:00

104 lines
3.5 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 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
}