diff --git a/src/common/enums/message.enum.ts b/src/common/enums/message.enum.ts index 8759cba..cb1ac06 100755 --- a/src/common/enums/message.enum.ts +++ b/src/common/enums/message.enum.ts @@ -925,5 +925,6 @@ export const enum WorkSpaceMessage { export const enum ProjectMessage { PROJECT_EXISTS = "پروژه مورد نظر شما از قبل وجود دارد!", - PROJECT_NOT_FOUND = "پروژه مورد نظر شما وجود ندارد!" + PROJECT_NOT_FOUND = "پروژه مورد نظر شما وجود ندارد!", + PROJECT_CONTAINS_TASK_PHASES = "پروژه شامل فاز تسک است. لطفا ابتدا فاز تسک های این پروژه را حذف کنید." } \ No newline at end of file diff --git a/src/common/helpers/pagination.helper.ts b/src/common/helpers/pagination.helper.ts deleted file mode 100644 index df195a4..0000000 --- a/src/common/helpers/pagination.helper.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { IPageFormat } from "../interfaces/IPagination"; - -export function buildPageFormat( - page: number, - limit: number, - totalItems: number, - baseUrl: string, -): IPageFormat { - const totalPages = Math.ceil(totalItems / limit); - - const prevPage = - page > 1 - ? `${baseUrl}?page=${page - 1}&limit=${limit}` - : false; - - const nextPage = - page < totalPages - ? `${baseUrl}?page=${page + 1}&limit=${limit}` - : false; - - return { - page, - limit, - totalItems, - totalPages, - prevPage, - nextPage, - }; -} \ No newline at end of file diff --git a/src/common/interfaces/paginated-result.interface.ts b/src/common/interfaces/paginated-result.interface.ts deleted file mode 100644 index b9247fb..0000000 --- a/src/common/interfaces/paginated-result.interface.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { IPageFormat } from "./IPagination"; - -export interface PaginatedResult { - data: T[]; - meta: IPageFormat; -} \ 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 27f3788..2c0d43e 100644 --- a/src/modules/task-manager/controllers/project.controller.ts +++ b/src/modules/task-manager/controllers/project.controller.ts @@ -1,5 +1,5 @@ -import { Controller, Get, Post, Patch, Delete, Param, Body, Query, Headers } from "@nestjs/common"; -import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiQuery } from "@nestjs/swagger"; +import { Controller, Get, Post, Patch, Delete, Param, Body, Query } from "@nestjs/common"; +import { ApiTags, ApiOperation, ApiResponse, ApiParam } from "@nestjs/swagger"; import { ProjectService } from "../providers/project.service"; import { CreateProjectDto } from "../dto/project/create-project.dto"; import { UpdateProjectDto } from "../dto/project/update-project.dto"; @@ -18,18 +18,9 @@ export class ProjectController { @Get() @PermissionsDec(PermissionEnum.PROJECT) @ApiOperation({ summary: "Get all projects, optionally filtered by workspace" }) - @ApiQuery({ name: "workspaceId", required: false, description: "Filter projects by workspace ID" }) @ApiResponse({ status: 200, description: "Paginated list of projects" }) - findAll( - @Query() pagination: PaginationDto, - @Query("workspaceId") workspaceId: string, - @Headers("host") host: string, - @Headers("x-forwarded-proto") proto?: string, - ) { - const protocol = proto ?? "http"; - const baseUrl = `${protocol}://${host}/task-manager/projects`; - if (workspaceId) return this.projectService.findByWorkspace(workspaceId, pagination, baseUrl); - return this.projectService.findAll(pagination, baseUrl); + findAll(@Query() pagination: PaginationDto): Promise<{ projects: TMProject[]; count: number; paginate: true }> { + return this.projectService.findAll(pagination); } @Get(":id") @@ -74,11 +65,15 @@ export class ProjectController { } @Get("/workspace/:wsId") - @ApiOperation({summary: "Get projects of a specific workspace"}) + @PermissionsDec(PermissionEnum.PROJECT) + @ApiOperation({ summary: "Get projects of a specific workspace" }) @ApiParam({ name: "wsId", description: "Workspace ID" }) - @ApiResponse({ status: 200, description: "received projects successfully!"}) + @ApiResponse({ status: 200, description: "received projects successfully!" }) @ApiResponse({ status: 404, description: "WorkSpace not found" }) - findByWorkspace(@Param("wsId") wsId: string): Promise { - return this.findByWorkspace(wsId); + findByWorkspace( + @Param("wsId") wsId: string, + @Query() pagination: PaginationDto, + ): Promise<{ projects: TMProject[]; count: number; paginate: true }> { + return this.projectService.findByWorkspace(wsId, pagination); } } diff --git a/src/modules/task-manager/providers/project.service.ts b/src/modules/task-manager/providers/project.service.ts index 72cdb7b..523fd15 100644 --- a/src/modules/task-manager/providers/project.service.ts +++ b/src/modules/task-manager/providers/project.service.ts @@ -6,8 +6,6 @@ import { TMProject } from "../entities/project.entity"; import { CreateProjectDto } from "../dto/project/create-project.dto"; import { UpdateProjectDto } from "../dto/project/update-project.dto"; import { PaginationDto } from "../../../common/DTO/pagination.dto"; -import { PaginatedResult } from "../../../common/interfaces/paginated-result.interface"; -import { buildPageFormat } from "../../../common/helpers/pagination.helper"; import { User } from "../../users/entities/user.entity"; import { ProjectMessage, WorkSpaceMessage } from "../../../common/enums/message.enum"; import { WorkspaceService } from "./workspace.service"; @@ -21,37 +19,53 @@ export class ProjectService { private readonly userRepository: Repository, ) {} - async findAll(pagination: PaginationDto, baseUrl: string): Promise> { + async findAll(pagination: PaginationDto): Promise<{ projects: TMProject[]; count: number; paginate: true }> { const page = pagination.page ?? 1; const limit = pagination.limit ?? 10; const skip = (page - 1) * limit; - const [data, totalItems] = await this.projectRepository.findAndCount({ skip, take: limit }); + const [projects, count] = await this.projectRepository.findAndCount({ + skip: skip, + take: limit, + relations: { + users: true, + }, + select: { + users: { + id: true, + firstName: true, + lastName: true, + }, + }, + }); - return { - data, - meta: buildPageFormat(page, limit, totalItems, baseUrl), - }; + return { projects, count, paginate: true }; } - async findByWorkspace(workspaceId: string, pagination: PaginationDto, baseUrl: string): Promise> { + async findByWorkspace(workspaceId: string, pagination: PaginationDto): Promise<{ projects: TMProject[]; count: number; paginate: true }> { await this.workspaceService.findOneOrFail(workspaceId); const page = pagination.page ?? 1; const limit = pagination.limit ?? 10; const skip = (page - 1) * limit; - const [data, totalItems] = await this.projectRepository.findAndCount({ + const [projects, count] = await this.projectRepository.findAndCount({ where: { workspaceId }, - relations: ["taskPhases", "users"], + relations: { + users: true, + }, + select: { + users: { + id: true, + firstName: true, + lastName: true, + }, + }, skip, take: limit, }); - return { - data, - meta: buildPageFormat(page, limit, totalItems, baseUrl), - }; + return { projects, count, paginate: true }; } async findOneOrFail(id: string): Promise { @@ -112,7 +126,26 @@ export class ProjectService { } async remove(id: string): Promise { - const project = await this.findOneOrFail(id); + const project = await this.projectRepository.findOne({ + where: { + id, + }, + relations: { + taskPhases: true, + }, + select: { + taskPhases: { + id: true, + }, + }, + }); + + if(!project) throw new NotFoundException(ProjectMessage.PROJECT_NOT_FOUND); + + const taskPhases = project.taskPhases; + if (taskPhases !== undefined && taskPhases.length) { + throw new BadRequestException(ProjectMessage.PROJECT_CONTAINS_TASK_PHASES); + } await this.projectRepository.delete(id); return project; }