import { BadRequestException, ForbiddenException, Injectable, NotFoundException } from "@nestjs/common"; import { InjectRepository } from "@nestjs/typeorm"; import { In, Repository } from "typeorm"; import { TaskRepository } from "../repositories/task.repository"; import { TMTask } from "../entities/task.entity"; import { CreateTaskDto } from "../dto/task/create-task.dto"; import { UpdateTaskDto } from "../dto/task/update-task.dto"; import { ChangeTaskPhaseDto } from "../dto/task/change-task-phase.dto"; import { User } from "../../users/entities/user.entity"; import { TaskMessage, TaskPhaseMessage } from "../../../common/enums/message.enum"; import { TaskPhaseRepository } from "../repositories/task-phase.repository"; import { TMTaskPhase } from "../entities/task-phase.entity"; @Injectable() export class TaskService { constructor( private readonly taskRepository: TaskRepository, private readonly taskPhaseRepository: TaskPhaseRepository, @InjectRepository(User) private readonly userRepository: Repository, ) {} async findAll(): Promise { return this.taskRepository.find({ relations: ["taskPhase", "remarks", "attachments", "checkListItems", "users"], }); } async findByPhase(taskPhaseId: string): Promise { return this.taskRepository.find({ where: { taskPhaseId } }); } async findOneOrFail(id: string): Promise { const task = await this.taskRepository.findOne({ where: { id }, relations: { taskPhase: true, users: true }, }); if (!task) throw new NotFoundException(TaskMessage.TASK_NOT_FOUND); return task; } async findTaskPhaseOrFail(taskPhaseId: string): Promise { const taskPhase = await this.taskPhaseRepository.findOne({ where: { id: taskPhaseId }, relations: { project: { users: true, }, }, }); if (!taskPhase) throw new NotFoundException(TaskPhaseMessage.TASK_PHASE_NOT_FOUND); return taskPhase; } async create(dto: CreateTaskDto): Promise { const { userIds, startDate, endDate, ...rest } = dto; const taskPhase = await this.findTaskPhaseOrFail(dto.taskPhaseId); if (userIds?.length) { const isUsersValid = userIds.every((userId) => taskPhase.project.users.some((user) => user.id === userId)); if (!isUsersValid) throw new BadRequestException(TaskMessage.USERS_ASSIGNED_TO_TASK_NOT_PROJECT_MEMBER); } const task = this.taskRepository.create({ ...rest, startDate: startDate ? new Date(startDate) : undefined, endDate: endDate ? new Date(endDate) : undefined, }); if (userIds?.length) { task.users = await this.userRepository.findBy({ id: In(userIds) }); } return this.taskRepository.save(task); } async update(id: string, dto: UpdateTaskDto): Promise { const task = await this.findOneOrFail(id); const { userIds, startDate, endDate, ...rest } = dto; if (dto.taskPhaseId) { const taskPhase = await this.findTaskPhaseOrFail(dto.taskPhaseId); if (userIds?.length) { const isUsersValid = userIds.every((userId) => taskPhase.project.users.some((user) => user.id === userId)); if (!isUsersValid) throw new BadRequestException(TaskMessage.USERS_ASSIGNED_TO_TASK_NOT_PROJECT_MEMBER); } } Object.assign(task, { ...rest, startDate: startDate ? new Date(startDate) : task.startDate, endDate: endDate ? new Date(endDate) : task.endDate, }); if (userIds) { task.users = userIds.length ? await this.userRepository.findBy({ id: In(userIds) }) : []; } return this.taskRepository.save(task); } async changePhase(id: string, dto: ChangeTaskPhaseDto): Promise { const task = await this.findOneOrFail(id); const newPhase = await this.findTaskPhaseOrFail(dto.taskPhaseId); if (task.taskPhase.projectId !== newPhase.projectId) { throw new BadRequestException(TaskPhaseMessage.TASK_PHASE_NOT_SAME_PROJECT); } task.taskPhaseId = dto.taskPhaseId; task.taskPhase = newPhase; return this.taskRepository.save(task); } async remove(id: string): Promise { await this.findOneOrFail(id); await this.taskRepository.delete(id); } async getTaskDetail(userId: string, taskId: string): Promise { const task = await this.findOneOrFail(taskId); const isTaskMember = task.users.some((user) => user.id === userId); if(!isTaskMember) throw new ForbiddenException(TaskMessage.USER_NOT_TASK_MEMBER); const taskDetail = await this.taskRepository.getTaskDetail(taskId); return taskDetail; } }