import { BadRequestException, ConflictException, Injectable, NotFoundException, } from "@nestjs/common"; import { TeamMemberRole } from "@prisma/client"; import { PrismaService } from "../prisma/prisma.service"; import { CreateTeamDto } from "./dto/create-team.dto"; import { ManageTeamMemberDto } from "./dto/manage-team-member.dto"; @Injectable() export class TeamsService { constructor(private readonly prisma: PrismaService) {} async create(workspaceId: string, createTeamDto: CreateTeamDto) { return this.prisma.team.create({ data: { workspaceId, name: createTeamDto.name, description: createTeamDto.description ?? null, }, }); } async findAll(workspaceId: string) { return this.prisma.team.findMany({ where: { workspaceId }, include: { _count: { select: { members: true }, }, }, orderBy: { createdAt: "asc" }, }); } async addMember(workspaceId: string, teamId: string, dto: ManageTeamMemberDto) { await this.ensureTeamInWorkspace(workspaceId, teamId); const workspaceMember = await this.prisma.workspaceMember.findUnique({ where: { workspaceId_userId: { workspaceId, userId: dto.userId, }, }, select: { userId: true }, }); if (!workspaceMember) { throw new BadRequestException( `User ${dto.userId} must be a workspace member before being added to a team` ); } const existingTeamMember = await this.prisma.teamMember.findUnique({ where: { teamId_userId: { teamId, userId: dto.userId, }, }, select: { userId: true }, }); if (existingTeamMember) { throw new ConflictException(`User ${dto.userId} is already a member of team ${teamId}`); } return this.prisma.teamMember.create({ data: { teamId, userId: dto.userId, role: dto.role ?? TeamMemberRole.MEMBER, }, include: { user: { select: { id: true, name: true, email: true, }, }, }, }); } async removeMember(workspaceId: string, teamId: string, userId: string): Promise { await this.ensureTeamInWorkspace(workspaceId, teamId); const result = await this.prisma.teamMember.deleteMany({ where: { teamId, userId, }, }); if (result.count === 0) { throw new NotFoundException(`User ${userId} is not a member of team ${teamId}`); } } async remove(workspaceId: string, teamId: string): Promise { const result = await this.prisma.team.deleteMany({ where: { id: teamId, workspaceId, }, }); if (result.count === 0) { throw new NotFoundException(`Team with ID ${teamId} not found`); } } private async ensureTeamInWorkspace(workspaceId: string, teamId: string): Promise { const team = await this.prisma.team.findFirst({ where: { id: teamId, workspaceId, }, select: { id: true }, }); if (!team) { throw new NotFoundException(`Team with ID ${teamId} not found`); } } }