Files
dsc-api/src/modules/task-manager/providers/project.service.ts
T

152 lines
5.3 KiB
TypeScript

import { BadRequestException, ForbiddenException, Injectable, NotFoundException } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { In, Repository } from "typeorm";
import { ProjectRepository } from "../repositories/project.repository";
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 { User } from "../../users/entities/user.entity";
import { ProjectMessage, WorkSpaceMessage } from "../../../common/enums/message.enum";
import { WorkspaceService } from "./workspace.service";
import { PermissionEnum } from "../../users/enums/permission.enum";
@Injectable()
export class ProjectService {
constructor(
private readonly projectRepository: ProjectRepository,
private readonly workspaceService: WorkspaceService,
@InjectRepository(User)
private readonly userRepository: Repository<User>,
) {}
async findOneOrFail(id: string): Promise<TMProject> {
const project = await this.projectRepository.findOne({ where: { id } });
if (!project) throw new NotFoundException(ProjectMessage.PROJECT_NOT_FOUND);
return project;
}
async create(dto: CreateProjectDto): Promise<TMProject> {
const { userIds, startDate, ...rest } = dto;
const workspace = await this.workspaceService.findOneOrFail(dto.workspaceId);
const project = this.projectRepository.create({
...rest,
startDate: new Date(startDate),
});
if (userIds?.length) {
const workspaceUserIds = workspace.users.map((u) => u.id);
const invalidUsers = userIds.filter((id) => !workspaceUserIds.includes(id));
if (invalidUsers.length) {
throw new BadRequestException(WorkSpaceMessage.USERS_DONT_BELONG_TO_THIS_WORKSPACE);
}
project.users = await this.userRepository.findBy({ id: In(userIds) });
}
return this.projectRepository.save(project);
}
async update(id: string, dto: UpdateProjectDto): Promise<TMProject> {
const project = await this.findOneOrFail(id);
const { userIds, startDate, ...rest } = dto;
Object.assign(project, {
...rest,
startDate: startDate ? new Date(startDate) : project.startDate,
});
if (userIds) {
if (userIds.length) {
const workspaceId = dto.workspaceId ?? project.workspaceId;
const workspace = await this.workspaceService.findOneOrFail(workspaceId);
const workspaceUserIds = workspace.users.map((u) => u.id);
const invalidUsers = userIds.filter((uid) => !workspaceUserIds.includes(uid));
if (invalidUsers.length) {
throw new BadRequestException(WorkSpaceMessage.USERS_DONT_BELONG_TO_THIS_WORKSPACE);
}
project.users = await this.userRepository.findBy({ id: In(userIds) });
} else {
project.users = [];
}
}
return this.projectRepository.save(project);
}
async remove(id: string): Promise<TMProject> {
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;
}
async findUserProjectsByWorkspace(
userId: string,
permissions: PermissionEnum[],
wsId: string,
pagination: PaginationDto,
): Promise<{ projects: TMProject[]; count: number; paginate: true }> {
const workspace = await this.workspaceService.findOneOrFail(wsId);
const page = pagination.page ?? 1;
const limit = pagination.limit ?? 10;
const skip = (page - 1) * limit;
const isPermissionIncluded = permissions.includes(PermissionEnum.VIEW_ALL_PROJECTS);
const isUserMemeberOfWorkspace = workspace.users.some((user) => user.id === userId);
var res: [TMProject[], number];
if (isUserMemeberOfWorkspace) {
res = await this.projectRepository.findUserProjects(userId, wsId, skip, limit);
} else if (isPermissionIncluded) {
res = await this.projectRepository.findAndCount({ where: { workspaceId: wsId } });
} else {
throw new ForbiddenException(WorkSpaceMessage.FORBIDDEN);
}
const [projects, count] = res;
return { projects, count, paginate: true };
}
async getProjectDetail(projectId: string, userId: string, permissions: PermissionEnum[]): Promise<TMProject | null> {
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 && !permissions.includes(PermissionEnum.VIEW_ALL_PROJECTS))
throw new ForbiddenException(ProjectMessage.NOT_MEMBER_OF_PROJECT);
const projectDetail = await this.projectRepository.getProjectDetail(projectId);
return projectDetail;
}
}