From 5964a9b20de4d580e6a8e30c3fa8e428190026dc Mon Sep 17 00:00:00 2001 From: realrafi Date: Mon, 6 Jul 2026 14:05:38 +0330 Subject: [PATCH] feat: added project detail API --- src/common/enums/message.enum.ts | 1 + .../controllers/project.controller.ts | 12 +++++++++ .../task-manager/providers/project.service.ts | 25 +++++++++++++++++-- .../repositories/project.repository.ts | 15 +++++++++++ 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/common/enums/message.enum.ts b/src/common/enums/message.enum.ts index 7658080..9489ec2 100755 --- a/src/common/enums/message.enum.ts +++ b/src/common/enums/message.enum.ts @@ -929,4 +929,5 @@ export const enum ProjectMessage { PROJECT_EXISTS = "پروژه مورد نظر شما از قبل وجود دارد!", PROJECT_NOT_FOUND = "پروژه مورد نظر شما وجود ندارد!", PROJECT_CONTAINS_TASK_PHASES = "پروژه شامل فاز تسک است. لطفا ابتدا فاز تسک های این پروژه را حذف کنید.", + NOT_MEMBER_OF_PROJECT = "شما عضو این پروژه نیستید!" } \ No newline at end of file diff --git a/src/modules/task-manager/controllers/project.controller.ts b/src/modules/task-manager/controllers/project.controller.ts index 9199203..783b99e 100644 --- a/src/modules/task-manager/controllers/project.controller.ts +++ b/src/modules/task-manager/controllers/project.controller.ts @@ -79,4 +79,16 @@ export class ProjectController { ): Promise<{ projects: TMProject[]; count: number; paginate: true }> { return this.projectService.findUserProjects(userId, paramDto.id, pagination); } + + @Get("project/:id") + @ApiOperation({summary: "Get project detail"}) + @ApiResponse({status: 200, description: "Got Project Detail Successfully!"}) + @ApiResponse({status: 400, description: "Bad request!"}) + @ApiResponse({status: 404, description: "The project was not found!"}) + getProjectDetail(@Param() paramDto: ParamDto, + @UserDec('id') userId: string +): Promise { + return this.projectService.getProjectDetail(paramDto.id, userId); + } + } diff --git a/src/modules/task-manager/providers/project.service.ts b/src/modules/task-manager/providers/project.service.ts index 8a192b5..df8054e 100644 --- a/src/modules/task-manager/providers/project.service.ts +++ b/src/modules/task-manager/providers/project.service.ts @@ -1,4 +1,4 @@ -import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common"; +import { BadRequestException, ForbiddenException, Injectable, NotFoundException } from "@nestjs/common"; import { InjectRepository } from "@nestjs/typeorm"; import { In, Repository } from "typeorm"; import { ProjectRepository } from "../repositories/project.repository"; @@ -124,7 +124,11 @@ export class ProjectService { return project; } - async findUserProjects(userId: string, wsId: string, pagination: PaginationDto): Promise<{ projects: TMProject[]; count: number; paginate: true }> { + async findUserProjects( + userId: string, + wsId: string, + pagination: PaginationDto, + ): Promise<{ projects: TMProject[]; count: number; paginate: true }> { const page = pagination.page ?? 1; const limit = pagination.limit ?? 10; const skip = (page - 1) * limit; @@ -133,4 +137,21 @@ export class ProjectService { return { projects, count, paginate: true }; } + + async getProjectDetail(projectId: string, userId: string): Promise { + const project = await this.projectRepository.findOne({ + where: { id: projectId }, + relations: { + users: true, + }, + }); + if (!project) throw new NotFoundException(ProjectMessage.PROJECT_NOT_FOUND); + + const isUserMember = project.users.some(user => user.id === userId); + if(!isUserMember) throw new ForbiddenException(ProjectMessage.NOT_MEMBER_OF_PROJECT); + + const projectDetail = await this.projectRepository.getProjectDetail(projectId); + + return projectDetail; + } } diff --git a/src/modules/task-manager/repositories/project.repository.ts b/src/modules/task-manager/repositories/project.repository.ts index ad87f20..4175ab4 100644 --- a/src/modules/task-manager/repositories/project.repository.ts +++ b/src/modules/task-manager/repositories/project.repository.ts @@ -21,4 +21,19 @@ export class ProjectRepository extends Repository { .take(take ?? 10) .getManyAndCount(); } + + async getProjectDetail(projectId: string): Promise { + return this.createQueryBuilder('project') + .leftJoinAndSelect('project.taskPhases', 'taskPhase') + .leftJoinAndSelect('taskPhase.tasks', 'task') + .where('project.id = :projectId', {projectId}) + .select([ + "project.id", + "project.name", + "taskPhase.id", + "taskPhase.name", + "task.id", + "task.title" + ]).getOne(); + } }