import { ProjectRepository } from '@app/common/modules/project/repositiories'; import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import { CreateProjectDto } from '../dto'; import { BaseResponseDto } from '@app/common/dto/base.response.dto'; import { SuccessResponseDto } from '@app/common/dto/success.response.dto'; import { ProjectEntity } from '@app/common/modules/project/entities'; import { TypeORMCustomModel, TypeORMCustomModelFindAllQuery, } from '@app/common/models/typeOrmCustom.model'; import { ProjectDto } from '@app/common/modules/project/dtos'; import { PageResponse } from '@app/common/dto/pagination.response.dto'; import { CommandBus } from '@nestjs/cqrs'; import { CreateOrphanSpaceCommand } from '../command/create-orphan-space-command'; import { InviteUserRepository } from '@app/common/modules/Invite-user/repositiories'; import { UserRepository } from '@app/common/modules/user/repositories'; import { UserStatusEnum } from '@app/common/constants/user-status.enum'; import { RoleType } from '@app/common/constants/role.type.enum'; @Injectable() export class ProjectService { constructor( private readonly projectRepository: ProjectRepository, private readonly inviteUserRepository: InviteUserRepository, private readonly userRepository: UserRepository, private commandBus: CommandBus, ) {} async createProject( createProjectDto: CreateProjectDto, ): Promise { const { name } = createProjectDto; try { // Check if the project name already exists const isNameExist = await this.validate(name); if (isNameExist) { throw new HttpException( `Project with name ${name} already exists`, HttpStatus.CONFLICT, ); } const newProject = this.projectRepository.create(createProjectDto); const savedProject = await this.projectRepository.save(newProject); await this.commandBus.execute(new CreateOrphanSpaceCommand(savedProject)); return new SuccessResponseDto({ message: `Project with ID ${savedProject.uuid} successfully created`, data: savedProject, statusCode: HttpStatus.CREATED, }); } catch (error) { if (error instanceof HttpException) { throw error; } throw new HttpException( `An error occurred while creating the project. Please try again later. ${error}`, HttpStatus.INTERNAL_SERVER_ERROR, ); } } async deleteProject(uuid: string): Promise { try { // Find the project by UUID const project = await this.findOne(uuid); if (!project) { throw new HttpException( `Project with ID ${uuid} not found`, HttpStatus.NOT_FOUND, ); } // Delete the project await this.projectRepository.delete({ uuid }); return new SuccessResponseDto({ message: `Project with ID ${uuid} successfully deleted`, statusCode: HttpStatus.OK, }); } catch (error) { if (error instanceof HttpException) { throw error; } throw new HttpException( `An error occurred while deleting the project ${uuid}`, HttpStatus.INTERNAL_SERVER_ERROR, ); } } async listProjects( pageable: Partial, ): Promise { try { pageable.modelName = 'project'; const customModel = TypeORMCustomModel(this.projectRepository); const { baseResponseDto, paginationResponseDto } = await customModel.findAll(pageable); return new PageResponse( baseResponseDto, paginationResponseDto, ); } catch (error) { throw new HttpException(error.message, HttpStatus.INTERNAL_SERVER_ERROR); } } async getProject(uuid: string): Promise { try { // Find the project by UUID const project = await this.findOne(uuid); if (!project) { throw new HttpException( `Project with ID ${uuid} not found`, HttpStatus.NOT_FOUND, ); } return new SuccessResponseDto({ message: `Project with ID ${uuid} retrieved successfully`, data: project, statusCode: HttpStatus.OK, }); } catch (error) { if (error instanceof HttpException) { throw error; } throw new HttpException( `An error occurred while retrieving the project with id ${uuid}`, HttpStatus.INTERNAL_SERVER_ERROR, ); } } async updateProject( uuid: string, updateProjectDto: CreateProjectDto, ): Promise { try { // Find the project by UUID const project = await this.findOne(uuid); if (!project) { throw new HttpException( `Project with ID ${uuid} not found`, HttpStatus.NOT_FOUND, ); } if (updateProjectDto.name && updateProjectDto.name !== project.name) { const isNameExist = await this.validate(updateProjectDto.name); if (isNameExist) { throw new HttpException( `Project with name ${updateProjectDto.name} already exists`, HttpStatus.CONFLICT, ); } } // Update the project details Object.assign(project, updateProjectDto); const updatedProject = await this.projectRepository.save(project); return new SuccessResponseDto({ message: `Project with ID ${uuid} successfully updated`, data: updatedProject, statusCode: HttpStatus.OK, }); } catch (error) { if (error instanceof HttpException) { throw error; } throw new HttpException( `An error occurred while updating the project with ID ${uuid}`, HttpStatus.INTERNAL_SERVER_ERROR, ); } } async getUsersByProject(uuid: string): Promise { try { // Fetch invited users const invitedUsers = await this.inviteUserRepository.find({ where: { project: { uuid }, isActive: true }, select: [ 'firstName', 'lastName', 'email', 'createdAt', 'status', 'phoneNumber', 'jobTitle', 'invitedBy', 'isEnabled', ], relations: ['roleType'], }); // Fetch project users const users = await this.userRepository.find({ where: { project: { uuid }, isActive: true }, select: ['firstName', 'lastName', 'email', 'createdAt'], relations: ['roleType'], }); // Combine both arrays const allUsers = [...users, ...invitedUsers]; const normalizedUsers = allUsers.map((user) => { const createdAt = new Date(user.createdAt); const createdDate = createdAt.toLocaleDateString(); const createdTime = createdAt.toLocaleTimeString(); // Normalize user properties const normalizedProps = this.normalizeUserProperties(user); // Return the normalized user object return { ...user, createdDate, createdTime, ...normalizedProps, }; }); return new SuccessResponseDto({ message: `Users in project with ID ${uuid} retrieved successfully`, data: normalizedUsers, statusCode: HttpStatus.OK, }); } catch (error) { if (error instanceof HttpException) { throw error; } throw new HttpException( `An error occurred while retrieving users in the project with id ${uuid}`, HttpStatus.INTERNAL_SERVER_ERROR, ); } } normalizeUserProperties(user: any) { return { status: user.status ?? UserStatusEnum.ACTIVE, invitedBy: user.invitedBy ?? RoleType.SPACE_MEMBER, isEnabled: user.isEnabled ?? true, phoneNumber: user.phoneNumber ?? null, jobTitle: user.jobTitle ?? null, roleType: user.roleType?.type ?? null, }; } async findOne(uuid: string): Promise { const project = await this.projectRepository.findOne({ where: { uuid } }); return project; } async validate(name: string): Promise { return await this.projectRepository.exists({ where: { name } }); } }