enhance(user):基本完成用户系列的Repository功能迁移。

This commit is contained in:
徐涛 2023-06-01 13:56:06 +08:00
parent afc0114181
commit 6efe16e2fe
2 changed files with 200 additions and 20 deletions

View File

@ -55,6 +55,15 @@ func (m ManagementAccountCreationForm) IntoUserDetail() *UserDetail {
} }
} }
type UserModificationForm struct {
Name string
Region *string
Address *string
Contact *string
Phone *string
UnitServiceFee *decimal.Decimal
}
type User struct { type User struct {
Id string Id string
Username string Username string

View File

@ -9,9 +9,12 @@ import (
"electricity_bill_calc/tools" "electricity_bill_calc/tools"
"electricity_bill_calc/tools/time" "electricity_bill_calc/tools/time"
"fmt" "fmt"
"strings"
stdTime "time"
"github.com/doug-martin/goqu/v9" "github.com/doug-martin/goqu/v9"
_ "github.com/doug-martin/goqu/v9/dialect/postgres" _ "github.com/doug-martin/goqu/v9/dialect/postgres"
"github.com/fufuok/utils"
"github.com/georgysavva/scany/v2/pgxscan" "github.com/georgysavva/scany/v2/pgxscan"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -223,9 +226,9 @@ func (ur _UserRepository) CreateUser(user model.User, detail model.UserDetail, o
} }
// 根据给定的条件检索用户 // 根据给定的条件检索用户
func (ur _UserRepository) FindUser(keyword *string, userType int16, state *bool, page uint) (*[]model.UserWithDetail, int64, error) { func (ur _UserRepository) FindUser(keyword *string, userType int16, state *bool, page uint) ([]model.UserWithDetail, int64, error) {
ur.log.Info("根据给定的条件检索用户。", zap.Uint("page", page), zap.Stringp("keyword", keyword), zap.Int16("user type", userType), zap.Boolp("state", state)) ur.log.Info("根据给定的条件检索用户。", zap.Uint("page", page), zap.Stringp("keyword", keyword), zap.Int16("user type", userType), zap.Boolp("state", state))
if users, total, err := cache.RetrievePagedSearch[[]model.UserWithDetail]("user_with_detail", []string{ cacheConditions := []string{
fmt.Sprintf("%d", page), fmt.Sprintf("%d", page),
tools.CondFn( tools.CondFn(
func(v int16) bool { func(v int16) bool {
@ -237,8 +240,9 @@ func (ur _UserRepository) FindUser(keyword *string, userType int16, state *bool,
), ),
tools.DefaultStrTo("%s", state, "UNDEF"), tools.DefaultStrTo("%s", state, "UNDEF"),
tools.DefaultTo(keyword, ""), tools.DefaultTo(keyword, ""),
}...); err == nil && users != nil && total != -1 { }
return users, total, nil if users, total, err := cache.RetrievePagedSearch[[]model.UserWithDetail]("user_with_detail", cacheConditions...); err == nil && users != nil && total != -1 {
return *users, total, nil
} }
ctx, cancel := global.TimeoutContext() ctx, cancel := global.TimeoutContext()
@ -299,30 +303,197 @@ func (ur _UserRepository) FindUser(keyword *string, userType int16, state *bool,
countSql, countParams, _ := countQuery.Prepared(true).ToSQL() countSql, countParams, _ := countQuery.Prepared(true).ToSQL()
if err := pgxscan.Select(ctx, global.DB, &userWithDetails, userSql, userParams...); err != nil { if err := pgxscan.Select(ctx, global.DB, &userWithDetails, userSql, userParams...); err != nil {
ur.log.Error("从数据库查询用户列表失败。", zap.Error(err)) ur.log.Error("从数据库查询用户列表失败。", zap.Error(err))
return nil, 0, err return make([]model.UserWithDetail, 0), 0, err
} }
if err := pgxscan.Get(ctx, global.DB, &userCount, countSql, countParams...); err != nil { if err := pgxscan.Get(ctx, global.DB, &userCount, countSql, countParams...); err != nil {
ur.log.Error("从数据库查询用户列表总数失败。", zap.Error(err)) ur.log.Error("从数据库查询用户列表总数失败。", zap.Error(err))
return nil, 0, err return make([]model.UserWithDetail, 0), 0, err
} }
cache.CachePagedSearch( cache.CachePagedSearch(
userWithDetails, userWithDetails,
userCount, userCount,
[]string{"user"}, []string{"user"},
"user_with_detail", "user_with_detail",
[]string{ cacheConditions...,
fmt.Sprintf("%d", page),
tools.CondFn(
func(v int16) bool {
return v != -1
},
userType,
fmt.Sprintf("%d", userType),
"UNDEF",
),
tools.DefaultStrTo("%s", state, "UNDEF"),
tools.DefaultTo(keyword, ""),
}...,
) )
return &userWithDetails, userCount, nil return userWithDetails, userCount, nil
}
// 更新指定用户的详细信息
func (ur _UserRepository) UpdateDetail(uid string, userDetail model.UserModificationForm, operator *string) (bool, error) {
ur.log.Info("更新指定用户的详细信息。", zap.String("user id", uid))
ctx, cancel := global.TimeoutContext()
defer cancel()
userDetailUpdateQuery := ur.ds.
Update("user_detail").
Set(goqu.Record{
"name": userDetail.Name, "abbr": tools.PinyinAbbr(userDetail.Name), "region": userDetail.Region,
"address": userDetail.Address, "contact": userDetail.Contact, "phone": userDetail.Phone,
"last_modified_at": time.Now(), "last_modified_by": operator,
}).
Where(goqu.Ex{"id": uid})
if userDetail.UnitServiceFee != nil {
userDetailUpdateQuery = userDetailUpdateQuery.Set(goqu.Record{"unit_service_fee": userDetail.UnitServiceFee})
}
userDetailSql, userDetailParams, _ := userDetailUpdateQuery.
Prepared(true).ToSQL()
if res, err := global.DB.Exec(ctx, userDetailSql, userDetailParams...); err != nil {
ur.log.Error("向数据库更新指定用户的详细信息失败。", zap.String("user id", uid), zap.Error(err))
return false, err
} else {
cache.AbolishRelation(fmt.Sprintf("user:%s", uid))
return res.RowsAffected() > 0, nil
}
}
// 更新指定用户的登录凭据
func (ur _UserRepository) UpdatePassword(uid, newCredential string, needReset bool) (bool, error) {
ur.log.Info("更新指定用户的登录凭据。", zap.String("user id", uid))
ctx, cancel := global.TimeoutContext()
defer cancel()
userUpdateQuery := ur.ds.
Update("user").
Set(goqu.Record{"password": utils.Sha512Hex(newCredential), "reset_needed": needReset}).
Where(goqu.Ex{"id": uid})
userSql, userParams, _ := userUpdateQuery.
Prepared(true).ToSQL()
if res, err := global.DB.Exec(ctx, userSql, userParams...); err != nil {
ur.log.Error("向数据库更新指定用户的登录凭据失败。", zap.String("user id", uid), zap.Error(err))
return false, err
} else {
cache.AbolishRelation(fmt.Sprintf("user:%s", uid))
return res.RowsAffected() > 0, nil
}
}
// 更新指定用户的可用性状态
func (ur _UserRepository) ChangeState(uid string, state bool) (bool, error) {
ur.log.Info("更新指定用户的可用性状态。", zap.String("user id", uid))
ctx, cancel := global.TimeoutContext()
defer cancel()
userUpdateQuery := ur.ds.
Update("user").
Set(goqu.Record{"enabled": state}).
Where(goqu.Ex{"id": uid})
userSql, userParams, _ := userUpdateQuery.
Prepared(true).ToSQL()
if res, err := global.DB.Exec(ctx, userSql, userParams...); err != nil {
ur.log.Error("向数据库更新指定用户的可用性状态失败。", zap.String("user id", uid), zap.Error(err))
return false, err
} else {
cache.AbolishRelation(fmt.Sprintf("user:%s", uid))
return res.RowsAffected() > 0, nil
}
}
// 检索条目数量有限的用户详细信息
func (ur _UserRepository) SearchUsersWithLimit(userType *int16, keyword *string, limit uint) (*[]model.UserDetail, error) {
ur.log.Info("检索条目数量有限的用户详细信息。", zap.Int16p("user type", userType), zap.Uint("limit", limit), zap.Stringp("keyword", keyword))
actualUserType := tools.DefaultTo(userType, model.USER_TYPE_ENT)
cacheConditions := []string{
fmt.Sprintf("%d", actualUserType),
tools.DefaultTo(keyword, ""),
fmt.Sprintf("%d", limit),
}
if users, err := cache.RetrieveSearch[[]model.UserDetail]("user_with_detail_limited", cacheConditions...); err == nil && users != nil {
return users, nil
}
ctx, cancel := global.TimeoutContext()
defer cancel()
var users []model.UserDetail
userQuery := ur.ds.
From(goqu.T("user").As("u")).
Join(goqu.T("user_detail").As("ud"), goqu.On(goqu.Ex{"ud.id": goqu.I("u.id")})).
Select(
"u.id", "u.username", "u.reset_needed", "u.type", "u.enabled",
"ud.name", "ud.abbr", "ud.region", "ud.address", "ud.contact", "ud.phone",
"ud.unit_service_fee", "ud.service_expiration",
"ud.created_at", "ud.created_by", "ud.last_modified_at", "ud.last_modified_by",
)
if keyword != nil && len(*keyword) > 0 {
pattern := fmt.Sprintf("%%%s%%", *keyword)
userQuery = userQuery.Where(
goqu.Or(
goqu.Ex{"u.username": goqu.Op{"like": pattern}},
goqu.Ex{"ud.name": goqu.Op{"like": pattern}},
goqu.Ex{"ud.abbr": goqu.Op{"like": pattern}},
),
)
}
userQuery = userQuery.Where(goqu.Ex{"u.type": actualUserType})
userQuery.Order(goqu.I("u.created_at").Desc()).Limit(limit)
userSql, userParams, _ := userQuery.Prepared(true).ToSQL()
if err := pgxscan.Select(ctx, global.DB, &users, userSql, userParams...); err != nil {
ur.log.Error("从数据库查询用户列表失败。", zap.Error(err))
return nil, err
}
cache.CacheSearch(users, []string{"user"}, "user_with_detail_limited", cacheConditions...)
return &users, nil
}
// 更新指定用户的服务有效期限
func (ur _UserRepository) UpdateServiceExpiration(uid string, expiration stdTime.Time) (bool, error) {
ur.log.Info("更新指定用户的服务有效期限。", zap.String("user id", uid))
ctx, cancel := global.TimeoutContext()
defer cancel()
userDetailUpdateQuery := ur.ds.
Update("user_detail").
Set(goqu.Record{"service_expiration": expiration}).
Where(goqu.Ex{"id": uid})
userDetailSql, userDetailParams, _ := userDetailUpdateQuery.
Prepared(true).ToSQL()
if res, err := global.DB.Exec(ctx, userDetailSql, userDetailParams...); err != nil {
ur.log.Error("向数据库更新指定用户的服务有效期限失败。", zap.String("user id", uid), zap.Error(err))
return false, err
} else {
cache.AbolishRelation(fmt.Sprintf("user:%s", uid))
return res.RowsAffected() > 0, nil
}
}
// 检索指定用户列表的详细信息
func (ur _UserRepository) RetrieveUsersDetail(uids []string) ([]model.UserDetail, error) {
ur.log.Info("检索指定用户列表的详细信息。", zap.Strings("user ids", uids))
if len(uids) == 0 {
return make([]model.UserDetail, 0), nil
}
cacheConditions := []string{
strings.Join(uids, ","),
}
if users, err := cache.RetrieveSearch[[]model.UserDetail]("user_detail", cacheConditions...); err == nil && users != nil {
return *users, nil
}
ctx, cancel := global.TimeoutContext()
defer cancel()
var users []model.UserDetail
userQuery := ur.ds.
From("user_detail").
Where(goqu.Ex{"id": goqu.Any(uids)})
userSql, userParams, _ := userQuery.Prepared(true).ToSQL()
if err := pgxscan.Select(ctx, global.DB, &users, userSql, userParams...); err != nil {
ur.log.Error("从数据库查询用户列表失败。", zap.Error(err))
return make([]model.UserDetail, 0), err
}
cache.CacheSearch(users, []string{"user", "user_detail"}, "user", cacheConditions...)
return users, nil
} }