Files
APIPark/module/my-team/iml.go
T
2024-08-16 20:55:16 +08:00

397 lines
10 KiB
Go

package my_team
import (
"context"
"errors"
"fmt"
"github.com/eolinker/ap-account/service/role"
"gorm.io/gorm"
department_member "github.com/eolinker/ap-account/service/department-member"
"github.com/eolinker/go-common/auto"
"github.com/eolinker/ap-account/service/user"
"github.com/eolinker/go-common/store"
"github.com/APIParkLab/APIPark/service/service"
team_member "github.com/APIParkLab/APIPark/service/team-member"
team_dto "github.com/APIParkLab/APIPark/module/my-team/dto"
"github.com/APIParkLab/APIPark/service/team"
"github.com/eolinker/go-common/utils"
)
var (
_ ITeamModule = (*imlTeamModule)(nil)
)
type imlTeamModule struct {
teamService team.ITeamService `autowired:""`
teamMemberService team_member.ITeamMemberService `autowired:""`
roleService role.IRoleService `autowired:""`
roleMemberService role.IRoleMemberService `autowired:""`
userService user.IUserService `autowired:""`
departmentMemberService department_member.IMemberService `autowired:""`
serviceService service.IServiceService `autowired:""`
transaction store.ITransaction `autowired:""`
}
func (m *imlTeamModule) SimpleTeams(ctx context.Context, keyword string) ([]*team_dto.SimpleTeam, error) {
teams, err := m.teamService.Search(ctx, keyword, nil)
if err != nil {
return nil, err
}
projects, err := m.serviceService.Search(ctx, "", nil)
projectCount := make(map[string]int64)
appCount := make(map[string]int64)
for _, p := range projects {
if p.AsServer {
if _, ok := projectCount[p.Team]; !ok {
projectCount[p.Team] = 0
}
projectCount[p.Team]++
}
if p.AsApp {
if _, ok := appCount[p.Team]; !ok {
appCount[p.Team] = 0
}
appCount[p.Team]++
}
}
return utils.SliceToSlice(teams, func(s *team.Team) *team_dto.SimpleTeam {
return &team_dto.SimpleTeam{
Id: s.Id,
Name: s.Name,
Description: s.Description,
ServiceNum: projectCount[s.Id],
AppNum: appCount[s.Id],
}
}), nil
}
func (m *imlTeamModule) UpdateMemberRole(ctx context.Context, id string, input *team_dto.UpdateMemberRole) error {
_, err := m.teamService.Get(ctx, id)
if err != nil {
return err
}
supperRole, err := m.roleService.GetSupperRole(ctx, role.GroupTeam)
if err != nil {
return err
}
return m.transaction.Transaction(ctx, func(ctx context.Context) error {
if len(input.Roles) < 1 {
return errors.New("at least one role")
}
err = m.roleMemberService.RemoveUserRole(ctx, role.TeamTarget(id), input.Users...)
if err != nil {
return err
}
for _, roleId := range input.Roles {
for _, userId := range input.Users {
err = m.roleMemberService.Add(ctx, &role.AddMember{
Role: roleId,
User: userId,
Target: role.TeamTarget(id),
})
if err != nil {
return err
}
}
}
count, err := m.roleMemberService.CountByRole(ctx, role.TeamTarget(id), supperRole.Id)
if err != nil {
return err
}
if count < 1 {
return fmt.Errorf("role(%s) must have at least one member", supperRole.Name)
}
return nil
})
}
func (m *imlTeamModule) GetTeam(ctx context.Context, id string) (*team_dto.Team, error) {
tv, err := m.teamService.Get(ctx, id)
if err != nil {
return nil, err
}
return &team_dto.Team{
Id: tv.Id,
Name: tv.Name,
Description: tv.Description,
CreateTime: auto.TimeLabel(tv.CreateTime),
UpdateTime: auto.TimeLabel(tv.UpdateTime),
Creator: auto.UUID(tv.Creator),
Updater: auto.UUID(tv.Updater),
}, nil
}
func (m *imlTeamModule) Search(ctx context.Context, keyword string) ([]*team_dto.Item, error) {
userID := utils.UserId(ctx)
memberMap, err := m.teamMemberService.FilterMembersForUser(ctx, userID)
if err != nil {
return nil, err
}
teamIDs, ok := memberMap[userID]
if !ok || len(teamIDs) == 0 {
return make([]*team_dto.Item, 0), nil
}
list, err := m.teamService.Search(ctx, keyword, map[string]interface{}{
"uuid": teamIDs,
})
if err != nil {
return nil, err
}
serviceNumMap, err := m.serviceService.ServiceCountByTeam(ctx, teamIDs...)
if err != nil {
return nil, err
}
appNumMap, err := m.serviceService.AppCountByTeam(ctx, teamIDs...)
if err != nil {
return nil, err
}
outList := make([]*team_dto.Item, 0, len(list))
for _, v := range list {
outList = append(outList, team_dto.ToItem(v, serviceNumMap[v.Id], appNumMap[v.Id]))
}
return outList, nil
}
func (m *imlTeamModule) Edit(ctx context.Context, id string, input *team_dto.EditTeam) (*team_dto.Team, error) {
err := m.transaction.Transaction(ctx, func(ctx context.Context) error {
if input.Master != nil {
// 负责人是否在团队内,若不在,则新增
members, err := m.teamMemberService.Members(ctx, []string{id}, []string{*input.Master})
if err != nil {
return err
}
if len(members) == 0 {
err = m.teamMemberService.AddMemberTo(ctx, id, *input.Master)
if err != nil {
return err
}
}
}
return m.teamService.Save(ctx, id, &team.EditTeam{
Name: input.Name,
Description: input.Description,
})
})
if err != nil {
return nil, err
}
return m.GetTeam(ctx, id)
}
func (m *imlTeamModule) MySimpleTeams(ctx context.Context, keyword string) ([]*team_dto.SimpleTeam, error) {
userID := utils.UserId(ctx)
memberMap, err := m.teamMemberService.FilterMembersForUser(ctx, userID)
if err != nil {
return nil, err
}
teamIDs, ok := memberMap[userID]
if !ok || len(teamIDs) == 0 {
return make([]*team_dto.SimpleTeam, 0), nil
}
list, err := m.teamService.Search(ctx, keyword, map[string]interface{}{
"uuid": teamIDs,
})
if err != nil {
return nil, err
}
projects, err := m.serviceService.Search(ctx, "", map[string]interface{}{
"team": teamIDs,
})
projectCount := make(map[string]int64)
appCount := make(map[string]int64)
for _, p := range projects {
if p.AsServer {
if _, ok := projectCount[p.Team]; !ok {
projectCount[p.Team] = 0
}
projectCount[p.Team]++
}
if p.AsApp {
if _, ok := appCount[p.Team]; !ok {
appCount[p.Team] = 0
}
appCount[p.Team]++
}
}
outList := utils.SliceToSlice(list, func(s *team.Team) *team_dto.SimpleTeam {
return &team_dto.SimpleTeam{
Id: s.Id,
Name: s.Name,
Description: s.Description,
ServiceNum: projectCount[s.Id],
AppNum: appCount[s.Id],
}
})
return outList, nil
}
func (m *imlTeamModule) AddMember(ctx context.Context, id string, uuids ...string) error {
_, err := m.teamService.Get(ctx, id)
if err != nil {
return err
}
return m.transaction.Transaction(ctx, func(ctx context.Context) error {
err = m.teamMemberService.AddMemberTo(ctx, id, uuids...)
if err != nil {
return err
}
r, err := m.roleService.GetDefaultRole(ctx, role.GroupTeam)
if err != nil {
return err
}
for _, uid := range uuids {
err = m.roleMemberService.Add(ctx, &role.AddMember{Role: r.Id, User: uid, Target: role.TeamTarget(id)})
if err != nil {
return err
}
}
return nil
})
}
func (m *imlTeamModule) RemoveMember(ctx context.Context, id string, uuids ...string) error {
_, err := m.teamService.Get(ctx, id)
if err != nil {
return err
}
supperRole, err := m.roleService.GetSupperRole(ctx, role.GroupTeam)
if err != nil {
return err
}
count, err := m.roleMemberService.CountByRole(ctx, role.TeamTarget(id), supperRole.Id)
if err != nil {
return err
}
members, err := m.roleMemberService.List(ctx, role.TeamTarget(id), uuids...)
if err != nil {
return err
}
if len(members) >= int(count) {
supperRoleCount := 0
for _, member := range members {
if member.Role == supperRole.Id {
supperRoleCount++
}
}
if supperRoleCount == int(count) {
return errors.New("can not delete all team admin")
}
}
return m.transaction.Transaction(ctx, func(ctx context.Context) error {
err = m.roleMemberService.RemoveUserRole(ctx, role.TeamTarget(id), uuids...)
if err != nil {
return err
}
return m.teamMemberService.RemoveMemberFrom(ctx, id, uuids...)
})
}
func (m *imlTeamModule) Members(ctx context.Context, id string, keyword string) ([]*team_dto.Member, error) {
_, err := m.teamService.Get(ctx, id)
if err != nil {
return nil, err
}
users, err := m.userService.Search(ctx, keyword, -1)
if err != nil {
return nil, err
}
if len(users) == 0 {
return make([]*team_dto.Member, 0), nil
}
userIds := utils.SliceToSlice(users, func(s *user.User) string {
return s.UID
})
members, err := m.teamMemberService.Members(ctx, []string{id}, userIds)
if err != nil {
return nil, err
}
roleMembers, err := m.roleMemberService.List(ctx, role.TeamTarget(id))
if err != nil {
return nil, err
}
roleMemberMap := utils.SliceToMapArrayO(roleMembers, func(r *role.Member) (string, string) {
return r.User, r.Role
})
uId := utils.UserId(ctx)
out := make([]*team_dto.Member, 0, len(members))
for _, member := range members {
out = append(out, team_dto.ToMember(member, uId, roleMemberMap[member.UID]...))
}
return out, nil
}
func (m *imlTeamModule) SimpleMembers(ctx context.Context, id string, keyword string) ([]*team_dto.SimpleMember, error) {
if id == "" {
return nil, fmt.Errorf("team id is empty")
}
teamInfo, err := m.teamService.Get(ctx, id)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, err
}
if teamInfo == nil {
return nil, fmt.Errorf("team %s not extist", id)
}
users, err := m.userService.Search(ctx, keyword, -1)
if err != nil {
return nil, err
}
userMap := make(map[string]*user.User)
userIds := make([]string, 0, len(users))
for _, u := range users {
userIds = append(userIds, u.UID)
userMap[u.UID] = u
}
teamMembers, err := m.teamMemberService.Members(ctx, []string{id}, userIds)
if err != nil {
return nil, err
}
departmentMembers, err := m.departmentMemberService.Members(ctx, nil, userIds)
if err != nil {
return nil, err
}
departmentMemberMap := make(map[string][]string)
for _, member := range departmentMembers {
if _, ok := departmentMemberMap[member.UID]; !ok {
departmentMemberMap[member.UID] = make([]string, 0)
}
departmentMemberMap[member.UID] = append(departmentMemberMap[member.UID], member.Come)
}
out := make([]*team_dto.SimpleMember, 0, len(teamMembers))
for _, member := range teamMembers {
u, ok := userMap[member.UID]
if !ok {
continue
}
out = append(out, &team_dto.SimpleMember{
User: auto.UUID(u.UID),
Mail: u.Email,
Department: auto.List(departmentMemberMap[member.UID]),
})
}
return out, nil
}