community controller

This commit is contained in:
hannathkadher
2024-10-15 11:01:56 +04:00
parent a157444897
commit 2292c01220
23 changed files with 822 additions and 259 deletions

View File

@ -2,7 +2,9 @@ import { CommunityService } from '../services/community.service';
import {
Body,
Controller,
Delete,
Get,
HttpException,
HttpStatus,
Param,
Post,
@ -10,23 +12,25 @@ import {
Query,
UseGuards,
} from '@nestjs/common';
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger';
import {
AddCommunityDto,
AddUserCommunityDto,
} from '../dtos/add.community.dto';
import { GetCommunityChildDto } from '../dtos/get.community.dto';
import { GetCommunityParams } from '../dtos/get.community.dto';
import { UpdateCommunityNameDto } from '../dtos/update.community.dto';
// import { CheckUserCommunityGuard } from 'src/guards/user.community.guard';
import { AdminRoleGuard } from 'src/guards/admin.role.guard';
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
import { EnableDisableStatusEnum } from '@app/common/constants/days.enum';
import { SpaceType } from '@app/common/constants/space-type.enum';
import { ControllerRoute } from '@app/common/constants/controller-route';
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
import { PaginationRequestGetListDto } from '@app/common/dto/pagination.request.dto';
// import { CommunityPermissionGuard } from 'src/guards/community.permission.guard';
@ApiTags('Community Module')
@Controller({
version: EnableDisableStatusEnum.ENABLED,
path: SpaceType.COMMUNITY,
version: '1',
path: ControllerRoute.COMMUNITY.ROUTE,
})
export class CommunityController {
constructor(private readonly communityService: CommunityService) {}
@ -34,73 +38,103 @@ export class CommunityController {
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Post()
async addCommunity(@Body() addCommunityDto: AddCommunityDto) {
const community = await this.communityService.addCommunity(addCommunityDto);
return {
statusCode: HttpStatus.CREATED,
success: true,
message: 'Community added successfully',
data: community,
};
@ApiOperation({
summary: ControllerRoute.COMMUNITY.ACTIONS.CREATE_COMMUNITY_SUMMARY,
description: ControllerRoute.COMMUNITY.ACTIONS.CREATE_COMMUNITY_DESCRIPTION,
})
async createCommunity(
@Body() addCommunityDto: AddCommunityDto,
): Promise<BaseResponseDto> {
return await this.communityService.createCommunity(addCommunityDto);
}
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Get(':communityUuid')
async getCommunityByUuid(@Param('communityUuid') communityUuid: string) {
const community =
await this.communityService.getCommunityByUuid(communityUuid);
return community;
@ApiOperation({
summary: ControllerRoute.COMMUNITY.ACTIONS.GET_COMMUNITY_BY_ID_SUMMARY,
description:
ControllerRoute.COMMUNITY.ACTIONS.GET_COMMUNITY_BY_ID_DESCRIPTION,
})
@Get('/:communityId')
async getCommunityByUuid(
@Param() params: GetCommunityParams,
): Promise<BaseResponseDto> {
return await this.communityService.getCommunityById(params.communityId);
}
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@ApiOperation({
summary: ControllerRoute.COMMUNITY.ACTIONS.LIST_COMMUNITY_SUMMARY,
description: ControllerRoute.COMMUNITY.ACTIONS.LIST_COMMUNITY_DESCRIPTION,
})
@Get()
async getCommunities() {
const communities = await this.communityService.getCommunities();
return communities;
async getCommunities(
@Query() query: PaginationRequestGetListDto,
): Promise<BaseResponseDto> {
return this.communityService.getCommunities(query);
}
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Get('child/:communityUuid')
async getCommunityChildByUuid(
@Param('communityUuid') communityUuid: string,
@Query() query: GetCommunityChildDto,
@ApiOperation({
summary: ControllerRoute.COMMUNITY.ACTIONS.UPDATE_COMMUNITY_SUMMARY,
description: ControllerRoute.COMMUNITY.ACTIONS.UPDATE_COMMUNITY_DESCRIPTION,
})
@Put('/:communityId')
async updateCommunity(
@Param() param: GetCommunityParams,
@Body() updateCommunityDto: UpdateCommunityNameDto,
) {
const community = await this.communityService.getCommunityChildByUuid(
communityUuid,
query,
return this.communityService.updateCommunity(
param.communityId,
updateCommunityDto,
);
return community;
}
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Delete('/:communityId')
@ApiOperation({
summary: ControllerRoute.COMMUNITY.ACTIONS.DELETE_COMMUNITY_SUMMARY,
description: ControllerRoute.COMMUNITY.ACTIONS.DELETE_COMMUNITY_DESCRIPTION,
})
async deleteCommunity(
@Param() param: GetCommunityParams,
): Promise<BaseResponseDto> {
return this.communityService.deleteCommunity(param.communityId);
}
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Get('user/:userUuid')
async getCommunitiesByUserId(@Param('userUuid') userUuid: string) {
return await this.communityService.getCommunitiesByUserId(userUuid);
try {
return await this.communityService.getCommunitiesByUserId(userUuid);
} catch (error) {
throw new HttpException(
error.message || 'Internal server error',
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
@ApiBearerAuth()
@UseGuards(AdminRoleGuard)
@Post('user')
async addUserCommunity(@Body() addUserCommunityDto: AddUserCommunityDto) {
await this.communityService.addUserCommunity(addUserCommunityDto);
return {
statusCode: HttpStatus.CREATED,
success: true,
message: 'user community added successfully',
};
}
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Put(':communityUuid')
async renameCommunityByUuid(
@Param('communityUuid') communityUuid: string,
@Body() updateCommunityDto: UpdateCommunityNameDto,
) {
const community = await this.communityService.renameCommunityByUuid(
communityUuid,
updateCommunityDto,
);
return community;
try {
await this.communityService.addUserCommunity(addUserCommunityDto);
return {
statusCode: HttpStatus.CREATED,
success: true,
message: 'user community added successfully',
};
} catch (error) {
throw new HttpException(
error.message || 'Internal server error',
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
}

View File

@ -1,19 +1,38 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsString } from 'class-validator';
import { IsNotEmpty, IsOptional, IsString, IsUUID } from 'class-validator';
export class AddCommunityDto {
@ApiProperty({
description: 'communityName',
description: 'The name of the community',
example: 'Community A',
required: true,
})
@IsString()
@IsNotEmpty()
public communityName: string;
public name: string;
@ApiProperty({
description: 'A description of the community',
example: 'This is a community for developers.',
required: false,
})
@IsString()
@IsOptional()
public description?: string;
@ApiProperty({
description: 'The UUID of the region this community belongs to',
example: 'b6fa62c5-4fcf-4872-89a0-571cf431a6c7',
})
@IsUUID()
@IsNotEmpty()
public regionId: string;
constructor(dto: Partial<AddCommunityDto>) {
Object.assign(this, dto);
}
}
export class AddUserCommunityDto {
@ApiProperty({
description: 'communityUuid',

View File

@ -7,6 +7,7 @@ import {
IsNotEmpty,
IsOptional,
IsString,
IsUUID,
Min,
} from 'class-validator';
@ -20,6 +21,18 @@ export class GetCommunityDto {
public communityUuid: string;
}
export class GetCommunityParams {
@ApiProperty({
description: 'Community id of the specific community',
required: true,
name: 'communityId',
})
@IsUUID()
@IsString()
@IsNotEmpty()
public communityId: string;
}
export class GetCommunityChildDto {
@ApiProperty({ example: 1, description: 'Page number', required: true })
@IsInt({ message: 'Page must be a number' })

View File

@ -3,12 +3,12 @@ import { IsNotEmpty, IsString } from 'class-validator';
export class UpdateCommunityNameDto {
@ApiProperty({
description: 'communityName',
description: 'community name',
required: true,
})
@IsString()
@IsNotEmpty()
public communityName: string;
public name: string;
constructor(dto: Partial<UpdateCommunityNameDto>) {
Object.assign(this, dto);

View File

@ -1,183 +1,173 @@
import { GetCommunityChildDto } from './../dtos/get.community.dto';
import { SpaceTypeRepository } from './../../../libs/common/src/modules/space/repositories/space.repository';
import {
Injectable,
HttpException,
HttpStatus,
BadRequestException,
} from '@nestjs/common';
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
import { SpaceRepository } from '@app/common/modules/space/repositories';
import { AddCommunityDto, AddUserCommunityDto } from '../dtos';
import {
CommunityChildInterface,
GetCommunitiesInterface,
GetCommunityByUserUuidInterface,
GetCommunityByUuidInterface,
RenameCommunityByUuidInterface,
} from '../interface/community.interface';
import { SpaceEntity } from '@app/common/modules/space/entities';
import { GetCommunityByUserUuidInterface } from '../interface/community.interface';
import { UpdateCommunityNameDto } from '../dtos/update.community.dto';
import { UserSpaceRepository } from '@app/common/modules/user/repositories';
import { SpaceType } from '@app/common/constants/space-type.enum';
import { CommonErrorCodes } from '@app/common/constants/error-codes.enum';
import { RegionRepository } from '@app/common/modules/region/repositories';
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
import {
TypeORMCustomModel,
TypeORMCustomModelFindAllQuery,
} from '@app/common/models/typeOrmCustom.model';
import { PageResponse } from '@app/common/dto/pagination.response.dto';
import { CommunityRepository } from '@app/common/modules/community/repositories';
import { CommunityDto } from '@app/common/modules/community/dtos';
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
@Injectable()
export class CommunityService {
constructor(
private readonly spaceRepository: SpaceRepository,
private readonly spaceTypeRepository: SpaceTypeRepository,
private readonly userSpaceRepository: UserSpaceRepository,
private readonly communityRepository: CommunityRepository,
private readonly regionRepository: RegionRepository,
) {}
async addCommunity(addCommunityDto: AddCommunityDto) {
try {
const spaceType = await this.spaceTypeRepository.findOne({
where: {
type: SpaceType.COMMUNITY,
},
});
async createCommunity(dto: AddCommunityDto): Promise<BaseResponseDto> {
const { regionId, name, description } = dto;
// Find the region by the provided regionId
const region = await this.regionRepository.findOneBy({ uuid: regionId });
const community = await this.spaceRepository.save({
spaceName: addCommunityDto.communityName,
spaceType: { uuid: spaceType.uuid },
});
return community;
} catch (err) {
throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
async getCommunityByUuid(
communityUuid: string,
): Promise<GetCommunityByUuidInterface> {
try {
const community = await this.spaceRepository.findOne({
where: {
uuid: communityUuid,
spaceType: {
type: SpaceType.COMMUNITY,
},
},
relations: ['spaceType'],
});
if (
!community ||
!community.spaceType ||
community.spaceType.type !== SpaceType.COMMUNITY
) {
throw new BadRequestException('Invalid community UUID');
}
return {
uuid: community.uuid,
createdAt: community.createdAt,
updatedAt: community.updatedAt,
name: community.spaceName,
type: community.spaceType.type,
};
} catch (err) {
if (err instanceof BadRequestException) {
throw err; // Re-throw BadRequestException
} else {
throw new HttpException('Community not found', HttpStatus.NOT_FOUND);
}
}
}
async getCommunities(): Promise<GetCommunitiesInterface> {
try {
const community = await this.spaceRepository.find({
where: { spaceType: { type: SpaceType.COMMUNITY } },
relations: ['spaceType'],
});
return community.map((community) => ({
uuid: community.uuid,
createdAt: community.createdAt,
updatedAt: community.updatedAt,
name: community.spaceName,
type: community.spaceType.type,
}));
} catch (err) {
throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
async getCommunityChildByUuid(
communityUuid: string,
getCommunityChildDto: GetCommunityChildDto,
): Promise<CommunityChildInterface> {
try {
const { includeSubSpaces, page, pageSize } = getCommunityChildDto;
const space = await this.spaceRepository.findOneOrFail({
where: { uuid: communityUuid },
relations: ['children', 'spaceType'],
});
if (
!space ||
!space.spaceType ||
space.spaceType.type !== SpaceType.COMMUNITY
) {
throw new BadRequestException('Invalid community UUID');
}
const totalCount = await this.spaceRepository.count({
where: { parent: { uuid: space.uuid } },
});
const children = await this.buildHierarchy(
space,
includeSubSpaces,
page,
pageSize,
if (!region) {
throw new HttpException(
`Region with ID ${dto.regionId} not found.`,
HttpStatus.NOT_FOUND,
);
return {
uuid: space.uuid,
name: space.spaceName,
type: space.spaceType.type,
totalCount,
children,
};
} catch (err) {
if (err instanceof BadRequestException) {
throw err; // Re-throw BadRequestException
} else {
throw new HttpException('Community not found', HttpStatus.NOT_FOUND);
}
}
}
private async buildHierarchy(
space: SpaceEntity,
includeSubSpaces: boolean,
page: number,
pageSize: number,
): Promise<CommunityChildInterface[]> {
const children = await this.spaceRepository.find({
where: { parent: { uuid: space.uuid } },
relations: ['spaceType'],
skip: (page - 1) * pageSize,
take: pageSize,
// Create the new community entity
const community = this.communityRepository.create({
name: name,
description: description,
region: region, // Associate with the found region
});
if (!children || children.length === 0 || !includeSubSpaces) {
return children
.filter((child) => child.spaceType.type !== SpaceType.COMMUNITY) // Filter remaining community type
.map((child) => ({
uuid: child.uuid,
name: child.spaceName,
type: child.spaceType.type,
}));
// Save the community to the database
try {
await this.communityRepository.save(community);
return new SuccessResponseDto({
statusCode: HttpStatus.CREATED,
success: true,
data: community,
message: 'Community created successfully',
});
} catch (error) {
throw new HttpException(error.message, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
async getCommunityById(id: string): Promise<BaseResponseDto> {
const community = await this.communityRepository.findOneBy({ uuid: id });
// If the community is not found, throw a 404 NotFoundException
if (!community) {
throw new HttpException(
`Community with ID ${id} not found.`,
HttpStatus.NOT_FOUND,
);
}
const childHierarchies = await Promise.all(
children
.filter((child) => child.spaceType.type !== SpaceType.COMMUNITY) // Filter remaining community type
.map(async (child) => ({
uuid: child.uuid,
name: child.spaceName,
type: child.spaceType.type,
children: await this.buildHierarchy(child, true, 1, pageSize),
})),
);
// Return a success response
return new SuccessResponseDto({
data: community,
message: 'Community fetched successfully',
});
}
return childHierarchies;
async getCommunities(
pageable: Partial<TypeORMCustomModelFindAllQuery>,
): Promise<BaseResponseDto> {
pageable.modelName = 'community';
const customModel = TypeORMCustomModel(this.communityRepository);
const { baseResponseDto, paginationResponseDto } =
await customModel.findAll(pageable);
return new PageResponse<CommunityDto>(
baseResponseDto,
paginationResponseDto,
);
}
async updateCommunity(
id: string,
updateCommunityDto: UpdateCommunityNameDto,
): Promise<BaseResponseDto> {
const community = await this.communityRepository.findOne({
where: { uuid: id },
});
// If the community doesn't exist, throw a 404 error
if (!community) {
throw new HttpException(
`Community with ID ${id} not found`,
HttpStatus.NOT_FOUND,
);
}
try {
const { name } = updateCommunityDto;
// Find the community by its UUID
// Update the community name
community.name = name;
// Save the updated community back to the database
const updatedCommunity = await this.communityRepository.save(community);
// Return a SuccessResponseDto with the updated community data
return new SuccessResponseDto<CommunityDto>({
message: 'Success update Community',
data: updatedCommunity,
});
} catch (err) {
// Catch and handle any errors
if (err instanceof HttpException) {
throw err; // If it's an HttpException, rethrow it
} else {
// Throw a generic 404 error if anything else goes wrong
throw new HttpException('Community not found', HttpStatus.NOT_FOUND);
}
}
}
async deleteCommunity(id: string): Promise<BaseResponseDto> {
const community = await this.communityRepository.findOne({
where: { uuid: id },
});
// If the community is not found, throw an error
if (!community) {
throw new HttpException(
`Community with ID ${id} not found`,
HttpStatus.NOT_FOUND,
);
}
try {
// Find the community by its uuid
// Remove the community from the database
await this.communityRepository.remove(community);
// Return success response
return new SuccessResponseDto({
message: `Community with ID ${id} successfully deleted`,
data: null,
});
} catch (err) {
// Catch and handle any errors
if (err instanceof HttpException) {
throw err; // If it's an HttpException, rethrow it
} else {
throw new HttpException(
'An error occurred while deleting the community',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
}
async getCommunitiesByUserId(
@ -188,7 +178,6 @@ export class CommunityService {
relations: ['space', 'space.spaceType'],
where: {
user: { uuid: userUuid },
space: { spaceType: { type: SpaceType.COMMUNITY } },
},
});
@ -200,7 +189,7 @@ export class CommunityService {
}
const spaces = communities.map((community) => ({
uuid: community.space.uuid,
name: community.space.spaceName,
name: community.space.name,
type: community.space.spaceType.type,
}));
@ -221,7 +210,7 @@ export class CommunityService {
space: { uuid: addUserCommunityDto.communityUuid },
});
} catch (err) {
if (err.code === CommonErrorCodes.DUPLICATE_ENTITY) {
if (err.code === '23505') {
throw new HttpException(
'User already belongs to this community',
HttpStatus.BAD_REQUEST,
@ -233,46 +222,4 @@ export class CommunityService {
);
}
}
async renameCommunityByUuid(
communityUuid: string,
updateCommunityDto: UpdateCommunityNameDto,
): Promise<RenameCommunityByUuidInterface> {
try {
const community = await this.spaceRepository.findOneOrFail({
where: { uuid: communityUuid },
relations: ['spaceType'],
});
if (
!community ||
!community.spaceType ||
community.spaceType.type !== SpaceType.COMMUNITY
) {
throw new BadRequestException('Invalid community UUID');
}
await this.spaceRepository.update(
{ uuid: communityUuid },
{ spaceName: updateCommunityDto.communityName },
);
// Fetch the updated community
const updatedCommunity = await this.spaceRepository.findOneOrFail({
where: { uuid: communityUuid },
relations: ['spaceType'],
});
return {
uuid: updatedCommunity.uuid,
name: updatedCommunity.spaceName,
type: updatedCommunity.spaceType.type,
};
} catch (err) {
if (err instanceof BadRequestException) {
throw err; // Re-throw BadRequestException
} else {
throw new HttpException('Community not found', HttpStatus.NOT_FOUND);
}
}
}
}