import { ConflictException, Injectable, NotFoundException, } from '@nestjs/common'; import { Prisma } from '@prisma/client'; import type { Team, TeamCreate, TeamsResponse, TeamUpdate } from '@siop/shared'; import { PrismaService } from '../prisma/prisma.service'; const teamInclude = { members: { include: { role: true }, orderBy: { displayName: 'asc' } }, } satisfies Prisma.TeamInclude; type TeamRow = Prisma.TeamGetPayload<{ include: typeof teamInclude }>; @Injectable() export class TeamsService { constructor(private readonly prisma: PrismaService) {} async list(): Promise { const rows = await this.prisma.team.findMany({ include: teamInclude, orderBy: { name: 'asc' }, }); return { teams: rows.map((t) => this.toDto(t)) }; } async create(dto: TeamCreate): Promise { try { const created = await this.prisma.team.create({ data: { name: dto.name, description: dto.description, members: dto.memberIds?.length ? { connect: dto.memberIds.map((id) => ({ id })) } : undefined, }, include: teamInclude, }); return this.toDto(created); } catch (e) { if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === 'P2002') { throw new ConflictException('Ce nom d’équipe existe déjà'); } throw e; } } async update(id: string, dto: TeamUpdate): Promise { try { const updated = await this.prisma.team.update({ where: { id }, data: { name: dto.name, description: dto.description, members: dto.memberIds ? { set: dto.memberIds.map((memberId) => ({ id: memberId })) } : undefined, }, include: teamInclude, }); return this.toDto(updated); } catch (e) { if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === 'P2025') { throw new NotFoundException('Équipe inconnue'); } if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === 'P2002') { throw new ConflictException('Ce nom d’équipe existe déjà'); } throw e; } } private toDto(row: TeamRow): Team { return { id: row.id, name: row.name, description: row.description, members: row.members.map((m) => ({ id: m.id, displayName: m.displayName, roleName: m.role.name, initials: m.displayName .split(/\s+/) .filter(Boolean) .slice(0, 2) .map((w) => w[0]!.toUpperCase()) .join(''), })), }; } }