368 lines
11 KiB
Go
368 lines
11 KiB
Go
package managercenter
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"time"
|
|
|
|
"chatapp3-golang/internal/utils"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type bdLeaderRow struct {
|
|
ID int64 `gorm:"column:id;primaryKey"`
|
|
Origin string `gorm:"column:sys_origin"`
|
|
UserID int64 `gorm:"column:user_id"`
|
|
Contact string `gorm:"column:contact"`
|
|
RegionID string `gorm:"column:region_id"`
|
|
CreateTime time.Time `gorm:"column:create_time"`
|
|
UpdateTime time.Time `gorm:"column:update_time"`
|
|
CreateUser int64 `gorm:"column:create_user"`
|
|
UpdateUser int64 `gorm:"column:update_user"`
|
|
}
|
|
|
|
func (bdLeaderRow) TableName() string {
|
|
return "room_bd_lead_base_info"
|
|
}
|
|
|
|
type businessDevelopmentBaseInfoRow struct {
|
|
ID int64 `gorm:"column:id;primaryKey"`
|
|
Origin string `gorm:"column:sys_origin"`
|
|
BDLeadUserID *int64 `gorm:"column:bd_lead_user_id"`
|
|
UserID int64 `gorm:"column:user_id"`
|
|
Contact string `gorm:"column:contact"`
|
|
Region string `gorm:"column:region"`
|
|
MemberQuantity int64 `gorm:"column:member_quantity"`
|
|
CreateTime time.Time `gorm:"column:create_time"`
|
|
UpdateTime time.Time `gorm:"column:update_time"`
|
|
CreateUser int64 `gorm:"column:create_user"`
|
|
UpdateUser int64 `gorm:"column:update_user"`
|
|
}
|
|
|
|
func (businessDevelopmentBaseInfoRow) TableName() string {
|
|
return "room_business_development_base_info"
|
|
}
|
|
|
|
type userHistoryIdentityRow struct {
|
|
UserID int64 `gorm:"column:user_id;primaryKey"`
|
|
IsBD bool `gorm:"column:is_bd"`
|
|
IsAgent bool `gorm:"column:is_agent"`
|
|
IsHost bool `gorm:"column:is_host"`
|
|
IsManager bool `gorm:"column:is_manager"`
|
|
CreateTime time.Time `gorm:"column:create_time"`
|
|
UpdateTime time.Time `gorm:"column:update_time"`
|
|
CreateUser int64 `gorm:"column:create_user"`
|
|
UpdateUser int64 `gorm:"column:update_user"`
|
|
}
|
|
|
|
func (userHistoryIdentityRow) TableName() string {
|
|
return "user_history_identity"
|
|
}
|
|
|
|
type administratorRow struct {
|
|
ID int64 `gorm:"column:id;primaryKey"`
|
|
UserID int64 `gorm:"column:user_id"`
|
|
Status bool `gorm:"column:status"`
|
|
}
|
|
|
|
func (administratorRow) TableName() string {
|
|
return "sys_administrator"
|
|
}
|
|
|
|
type bdLeaderListRow struct {
|
|
ID int64 `gorm:"column:id"`
|
|
UserID int64 `gorm:"column:user_id"`
|
|
Origin string `gorm:"column:sys_origin"`
|
|
Contact string `gorm:"column:contact"`
|
|
RegionID string `gorm:"column:region_id"`
|
|
CreateTime time.Time `gorm:"column:create_time"`
|
|
UpdateTime time.Time `gorm:"column:update_time"`
|
|
Account string `gorm:"column:account"`
|
|
UserAvatar string `gorm:"column:user_avatar"`
|
|
UserNickname string `gorm:"column:user_nickname"`
|
|
}
|
|
|
|
func (s *Service) ListBDLeaders(ctx context.Context, user AuthUser) (*BDLeaderListResponse, error) {
|
|
manager, err := s.requireManagerInfo(ctx, user)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
query := s.db.WithContext(ctx).
|
|
Table("room_bd_lead_base_info AS leader").
|
|
Select(strings.Join([]string{
|
|
"leader.id",
|
|
"leader.user_id",
|
|
"leader.sys_origin",
|
|
"leader.contact",
|
|
"leader.region_id",
|
|
"leader.create_time",
|
|
"leader.update_time",
|
|
"user_info.account",
|
|
"user_info.user_avatar",
|
|
"user_info.user_nickname",
|
|
}, ", ")).
|
|
Joins("LEFT JOIN user_base_info AS user_info ON user_info.id = leader.user_id AND user_info.is_del = ?", false).
|
|
Where("leader.create_user = ?", user.UserID)
|
|
|
|
if origin := managerSysOrigin(manager, user); origin != "" {
|
|
query = query.Where("leader.sys_origin = ?", origin)
|
|
}
|
|
|
|
var rows []bdLeaderListRow
|
|
if err := query.Order("leader.create_time DESC, leader.id DESC").Find(&rows).Error; err != nil {
|
|
return nil, serverError("bd_leader_query_failed", err.Error())
|
|
}
|
|
|
|
records := make([]BDLeaderView, 0, len(rows))
|
|
for _, row := range rows {
|
|
records = append(records, bdLeaderListRowToView(row))
|
|
}
|
|
return &BDLeaderListResponse{Count: len(records), Records: records}, nil
|
|
}
|
|
|
|
func (s *Service) AddBDLeader(ctx context.Context, user AuthUser, req AddBDLeaderRequest) (*AddBDLeaderResponse, error) {
|
|
manager, err := s.requireManagerInfo(ctx, user)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if req.UserID.Int64() <= 0 {
|
|
return nil, badRequest("user_required", "userId is required")
|
|
}
|
|
|
|
target, err := s.loadUserRowByID(ctx, req.UserID.Int64())
|
|
if err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, notFound("user_not_found", "user not found")
|
|
}
|
|
return nil, serverError("user_query_failed", err.Error())
|
|
}
|
|
|
|
sysOrigin := managerSysOrigin(manager, user)
|
|
if sysOrigin == "" {
|
|
sysOrigin = normalizeSysOrigin(target.OriginSys)
|
|
}
|
|
if target.OriginSys != "" && sysOrigin != "" && !strings.EqualFold(target.OriginSys, sysOrigin) {
|
|
return nil, badRequest("bd_leader_origin_mismatch", "target user sysOrigin does not match manager")
|
|
}
|
|
|
|
regionID := strings.TrimSpace(req.RegionID)
|
|
if regionID == "" {
|
|
regionID = strings.TrimSpace(manager.RegionID)
|
|
}
|
|
if regionID == "" {
|
|
return nil, badRequest("manager_region_required", "manager region is required")
|
|
}
|
|
|
|
if exists, err := s.userIsAdministrator(ctx, target.ID); err != nil {
|
|
return nil, err
|
|
} else if exists {
|
|
return nil, badRequest("user_is_admin", "administrator cannot be added as BD leader")
|
|
}
|
|
|
|
if exists, err := s.userIsBDLeader(ctx, target.ID); err != nil {
|
|
return nil, err
|
|
} else if exists {
|
|
return nil, badRequest("user_already_bd_leader", "user is already a BD leader")
|
|
}
|
|
|
|
leaderID, err := utils.NextID()
|
|
if err != nil {
|
|
return nil, serverError("id_generate_failed", err.Error())
|
|
}
|
|
now := time.Now()
|
|
contact := strings.TrimSpace(req.Contact)
|
|
leader := bdLeaderRow{
|
|
ID: leaderID,
|
|
Origin: sysOrigin,
|
|
UserID: target.ID,
|
|
Contact: contact,
|
|
RegionID: regionID,
|
|
CreateTime: now,
|
|
UpdateTime: now,
|
|
CreateUser: user.UserID,
|
|
UpdateUser: user.UserID,
|
|
}
|
|
|
|
if err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
|
if err := tx.Create(&leader).Error; err != nil {
|
|
return serverError("bd_leader_create_failed", err.Error())
|
|
}
|
|
if err := upsertBDBaseInfo(tx, leader, user.UserID, now); err != nil {
|
|
return err
|
|
}
|
|
if err := upsertUserHistoryBD(tx, target.ID, user.UserID, now); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &AddBDLeaderResponse{
|
|
Success: true,
|
|
Leader: bdLeaderRowToView(leader, target),
|
|
}, nil
|
|
}
|
|
|
|
func (s *Service) requireManagerInfo(ctx context.Context, user AuthUser) (teamManagerInfoRow, error) {
|
|
if user.UserID <= 0 {
|
|
return teamManagerInfoRow{}, unauthorized("invalid_user", "authenticated user is required")
|
|
}
|
|
if s.db == nil {
|
|
return teamManagerInfoRow{}, serviceUnavailable("database_unavailable", "database is unavailable")
|
|
}
|
|
|
|
var row teamManagerInfoRow
|
|
err := s.db.WithContext(ctx).
|
|
Table("team_manager_base_info").
|
|
Where("user_id = ?", user.UserID).
|
|
First(&row).Error
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return teamManagerInfoRow{}, forbidden("not_manager", "user is not manager")
|
|
}
|
|
if err != nil {
|
|
return teamManagerInfoRow{}, serverError("manager_query_failed", err.Error())
|
|
}
|
|
return row, nil
|
|
}
|
|
|
|
func managerSysOrigin(manager teamManagerInfoRow, user AuthUser) string {
|
|
if origin := strings.TrimSpace(manager.Origin); origin != "" {
|
|
return origin
|
|
}
|
|
return strings.TrimSpace(user.SysOrigin)
|
|
}
|
|
|
|
func (s *Service) userIsAdministrator(ctx context.Context, userID int64) (bool, error) {
|
|
var count int64
|
|
if err := s.db.WithContext(ctx).
|
|
Table("sys_administrator").
|
|
Where("user_id = ? AND status = ?", userID, true).
|
|
Count(&count).Error; err != nil {
|
|
return false, serverError("administrator_query_failed", err.Error())
|
|
}
|
|
return count > 0, nil
|
|
}
|
|
|
|
func (s *Service) userIsBDLeader(ctx context.Context, userID int64) (bool, error) {
|
|
var count int64
|
|
if err := s.db.WithContext(ctx).
|
|
Table("room_bd_lead_base_info").
|
|
Where("user_id = ?", userID).
|
|
Count(&count).Error; err != nil {
|
|
return false, serverError("bd_leader_query_failed", err.Error())
|
|
}
|
|
return count > 0, nil
|
|
}
|
|
|
|
func upsertBDBaseInfo(tx *gorm.DB, leader bdLeaderRow, operatorID int64, now time.Time) error {
|
|
var row businessDevelopmentBaseInfoRow
|
|
err := tx.Where("user_id = ?", leader.UserID).First(&row).Error
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
id, idErr := utils.NextID()
|
|
if idErr != nil {
|
|
return serverError("id_generate_failed", idErr.Error())
|
|
}
|
|
leadUserID := leader.UserID
|
|
return tx.Create(&businessDevelopmentBaseInfoRow{
|
|
ID: id,
|
|
Origin: leader.Origin,
|
|
BDLeadUserID: &leadUserID,
|
|
UserID: leader.UserID,
|
|
Contact: leader.Contact,
|
|
Region: leader.RegionID,
|
|
MemberQuantity: 0,
|
|
CreateTime: now,
|
|
UpdateTime: now,
|
|
CreateUser: operatorID,
|
|
UpdateUser: operatorID,
|
|
}).Error
|
|
}
|
|
if err != nil {
|
|
return serverError("bd_info_query_failed", err.Error())
|
|
}
|
|
if row.BDLeadUserID != nil && *row.BDLeadUserID > 0 {
|
|
return badRequest("user_already_bound_bd_leader", "user already has a BD leader")
|
|
}
|
|
|
|
updates := map[string]any{
|
|
"bd_lead_user_id": leader.UserID,
|
|
"region": leader.RegionID,
|
|
"update_time": now,
|
|
"update_user": operatorID,
|
|
}
|
|
if leader.Contact != "" {
|
|
updates["contact"] = leader.Contact
|
|
}
|
|
if leader.Origin != "" {
|
|
updates["sys_origin"] = leader.Origin
|
|
}
|
|
if err := tx.Model(&businessDevelopmentBaseInfoRow{}).
|
|
Where("id = ?", row.ID).
|
|
Updates(updates).Error; err != nil {
|
|
return serverError("bd_info_update_failed", err.Error())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func upsertUserHistoryBD(tx *gorm.DB, userID int64, operatorID int64, now time.Time) error {
|
|
var row userHistoryIdentityRow
|
|
err := tx.Where("user_id = ?", userID).First(&row).Error
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return tx.Create(&userHistoryIdentityRow{
|
|
UserID: userID,
|
|
IsBD: true,
|
|
CreateTime: now,
|
|
UpdateTime: now,
|
|
CreateUser: operatorID,
|
|
UpdateUser: operatorID,
|
|
}).Error
|
|
}
|
|
if err != nil {
|
|
return serverError("history_identity_query_failed", err.Error())
|
|
}
|
|
if err := tx.Model(&userHistoryIdentityRow{}).
|
|
Where("user_id = ?", userID).
|
|
Updates(map[string]any{
|
|
"is_bd": true,
|
|
"update_time": now,
|
|
"update_user": operatorID,
|
|
}).Error; err != nil {
|
|
return serverError("history_identity_update_failed", err.Error())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func bdLeaderRowToView(leader bdLeaderRow, user userBaseInfoRow) BDLeaderView {
|
|
return BDLeaderView{
|
|
ID: ID(leader.ID),
|
|
UserID: ID(leader.UserID),
|
|
Account: user.Account,
|
|
UserAvatar: user.UserAvatar,
|
|
UserNickname: user.UserNickname,
|
|
Contact: leader.Contact,
|
|
RegionID: leader.RegionID,
|
|
OriginSys: leader.Origin,
|
|
CreateTime: leader.CreateTime,
|
|
UpdateTime: leader.UpdateTime,
|
|
}
|
|
}
|
|
|
|
func bdLeaderListRowToView(row bdLeaderListRow) BDLeaderView {
|
|
return BDLeaderView{
|
|
ID: ID(row.ID),
|
|
UserID: ID(row.UserID),
|
|
Account: row.Account,
|
|
UserAvatar: row.UserAvatar,
|
|
UserNickname: row.UserNickname,
|
|
Contact: row.Contact,
|
|
RegionID: row.RegionID,
|
|
OriginSys: row.Origin,
|
|
CreateTime: row.CreateTime,
|
|
UpdateTime: row.UpdateTime,
|
|
}
|
|
}
|