sysProductMemberModel.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package productmember
  2. import (
  3. "context"
  4. "fmt"
  5. "strings"
  6. "perms-system-server/internal/consts"
  7. "github.com/zeromicro/go-zero/core/stores/cache"
  8. "github.com/zeromicro/go-zero/core/stores/sqlx"
  9. )
  10. var _ SysProductMemberModel = (*customSysProductMemberModel)(nil)
  11. type (
  12. SysProductMemberModel interface {
  13. sysProductMemberModel
  14. FindListByProductCode(ctx context.Context, productCode string, page, pageSize int64) ([]*SysProductMember, int64, error)
  15. FindMapByProductCodeUserIds(ctx context.Context, productCode string, userIds []int64) (map[int64]*SysProductMember, error)
  16. CountActiveAdmins(ctx context.Context, productCode string) (int64, error)
  17. CountActiveAdminsTx(ctx context.Context, session sqlx.Session, productCode string) (int64, error)
  18. CountOtherActiveAdminsTx(ctx context.Context, session sqlx.Session, productCode string, excludeId int64) (int64, error)
  19. FindOneForUpdateTx(ctx context.Context, session sqlx.Session, id int64) (*SysProductMember, error)
  20. }
  21. customSysProductMemberModel struct {
  22. *defaultSysProductMemberModel
  23. }
  24. )
  25. func NewSysProductMemberModel(conn sqlx.SqlConn, c cache.CacheConf, cachePrefix string, opts ...cache.Option) SysProductMemberModel {
  26. return &customSysProductMemberModel{
  27. defaultSysProductMemberModel: newSysProductMemberModel(conn, c, cachePrefix, opts...),
  28. }
  29. }
  30. func (m *customSysProductMemberModel) FindListByProductCode(ctx context.Context, productCode string, page, pageSize int64) ([]*SysProductMember, int64, error) {
  31. var total int64
  32. countQuery := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE `productCode` = ?", m.table)
  33. if err := m.QueryRowNoCacheCtx(ctx, &total, countQuery, productCode); err != nil {
  34. return nil, 0, err
  35. }
  36. var list []*SysProductMember
  37. query := fmt.Sprintf("SELECT %s FROM %s WHERE `productCode` = ? ORDER BY id DESC LIMIT ?,?", sysProductMemberRows, m.table)
  38. if err := m.QueryRowsNoCacheCtx(ctx, &list, query, productCode, (page-1)*pageSize, pageSize); err != nil {
  39. return nil, 0, err
  40. }
  41. return list, total, nil
  42. }
  43. func (m *customSysProductMemberModel) CountActiveAdmins(ctx context.Context, productCode string) (int64, error) {
  44. var count int64
  45. query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE `productCode` = ? AND `memberType` = ? AND `status` = ?", m.table)
  46. if err := m.QueryRowNoCacheCtx(ctx, &count, query, productCode, consts.MemberTypeAdmin, consts.StatusEnabled); err != nil {
  47. return 0, err
  48. }
  49. return count, nil
  50. }
  51. func (m *customSysProductMemberModel) CountActiveAdminsTx(ctx context.Context, session sqlx.Session, productCode string) (int64, error) {
  52. var ids []int64
  53. query := fmt.Sprintf("SELECT `id` FROM %s WHERE `productCode` = ? AND `memberType` = ? AND `status` = ? FOR UPDATE", m.table)
  54. if err := session.QueryRowsCtx(ctx, &ids, query, productCode, consts.MemberTypeAdmin, consts.StatusEnabled); err != nil {
  55. return 0, err
  56. }
  57. return int64(len(ids)), nil
  58. }
  59. // CountOtherActiveAdminsTx 统计"除 excludeId 这一行以外"的启用 ADMIN 数量。调用方一般把即将被删除
  60. // 或即将被降级的目标行 id 传进来;返回 0 即表示目标是最后一个 active admin,不能动。相比
  61. // CountActiveAdminsTx + adminCount <= 1 的反向推理,语义更贴合业务(见审计 L-5)。
  62. // 仍然使用 FOR UPDATE 锁住扫描范围,串行化与并发降级/删除的冲突。
  63. func (m *customSysProductMemberModel) CountOtherActiveAdminsTx(ctx context.Context, session sqlx.Session, productCode string, excludeId int64) (int64, error) {
  64. var ids []int64
  65. query := fmt.Sprintf("SELECT `id` FROM %s WHERE `productCode` = ? AND `memberType` = ? AND `status` = ? AND `id` != ? FOR UPDATE", m.table)
  66. if err := session.QueryRowsCtx(ctx, &ids, query, productCode, consts.MemberTypeAdmin, consts.StatusEnabled, excludeId); err != nil {
  67. return 0, err
  68. }
  69. return int64(len(ids)), nil
  70. }
  71. func (m *customSysProductMemberModel) FindOneForUpdateTx(ctx context.Context, session sqlx.Session, id int64) (*SysProductMember, error) {
  72. var data SysProductMember
  73. query := fmt.Sprintf("SELECT %s FROM %s WHERE `id` = ? FOR UPDATE", sysProductMemberRows, m.table)
  74. if err := session.QueryRowCtx(ctx, &data, query, id); err != nil {
  75. return nil, err
  76. }
  77. return &data, nil
  78. }
  79. func (m *customSysProductMemberModel) FindMapByProductCodeUserIds(ctx context.Context, productCode string, userIds []int64) (map[int64]*SysProductMember, error) {
  80. if len(userIds) == 0 {
  81. return make(map[int64]*SysProductMember), nil
  82. }
  83. placeholders := make([]string, len(userIds))
  84. args := make([]interface{}, 0, len(userIds)+1)
  85. args = append(args, productCode)
  86. for i, id := range userIds {
  87. placeholders[i] = "?"
  88. args = append(args, id)
  89. }
  90. var list []*SysProductMember
  91. query := fmt.Sprintf("SELECT %s FROM %s WHERE `productCode` = ? AND `userId` IN (%s)", sysProductMemberRows, m.table, strings.Join(placeholders, ","))
  92. if err := m.QueryRowsNoCacheCtx(ctx, &list, query, args...); err != nil {
  93. return nil, err
  94. }
  95. result := make(map[int64]*SysProductMember, len(list))
  96. for _, pm := range list {
  97. result[pm.UserId] = pm
  98. }
  99. return result, nil
  100. }