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 }