Merge pull request #175 from SyncrowIOT/create-orphan-space-for-project

Create-orphan-space-for-project
This commit is contained in:
hannathkadher
2024-12-19 12:05:08 +04:00
committed by GitHub
12 changed files with 1781 additions and 74 deletions
@@ -0,0 +1,4 @@
export const ORPHAN_COMMUNITY_NAME = 'orphan-community';
export const ORPHAN_COMMUNITY_DESCRIPTION =
'Default community for orphan spaces';
export const ORPHAN_SPACE_NAME = 'orphan-space';
@@ -3,10 +3,7 @@ import { Column, Entity, ManyToOne, OneToMany } from 'typeorm';
import { SubspaceEntity } from './subspace.entity';
import { AbstractEntity } from '@app/common/modules/abstract/entities/abstract.entity';
import { SubspaceProductItemEntity } from './subspace-product-item.entity';
import {
SubspaceProductItemModelEntity,
SubspaceProductModelEntity,
} from '@app/common/modules/space-model';
import { SubspaceProductModelEntity } from '@app/common/modules/space-model';
import { SpaceProductModelDto } from '../../dtos';
@Entity({ name: 'subspace-product' })
+1624 -51
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -23,6 +23,7 @@
"@nestjs/common": "^10.0.0",
"@nestjs/config": "^3.2.0",
"@nestjs/core": "^10.0.0",
"@nestjs/cqrs": "^10.2.8",
"@nestjs/jwt": "^10.2.0",
"@nestjs/passport": "^10.0.3",
"@nestjs/platform-express": "^10.0.0",
+40 -12
View File
@@ -12,6 +12,8 @@ import { CommunityDto } from '@app/common/modules/community/dtos';
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
import { TuyaService } from '@app/common/integrations/tuya/services/tuya.service';
import { ProjectRepository } from '@app/common/modules/project/repositiories';
import { ORPHAN_COMMUNITY_NAME } from '@app/common/constants/orphan-constant';
import { Not } from 'typeorm';
@Injectable()
export class CommunityService {
@@ -90,20 +92,31 @@ export class CommunityService {
param: ProjectParam,
pageable: Partial<TypeORMCustomModelFindAllQuery>,
): Promise<BaseResponseDto> {
await this.validateProject(param.projectUuid);
try {
const project = await this.validateProject(param.projectUuid);
pageable.modelName = 'community';
pageable.where = { project: { uuid: param.projectUuid } };
pageable.modelName = 'community';
pageable.where = {
project: { uuid: param.projectUuid },
name: Not(`${ORPHAN_COMMUNITY_NAME}-${project.name}`),
};
const customModel = TypeORMCustomModel(this.communityRepository);
const customModel = TypeORMCustomModel(this.communityRepository);
const { baseResponseDto, paginationResponseDto } =
await customModel.findAll(pageable);
const { baseResponseDto, paginationResponseDto } =
await customModel.findAll(pageable);
return new PageResponse<CommunityDto>(
baseResponseDto,
paginationResponseDto,
);
return new PageResponse<CommunityDto>(
baseResponseDto,
paginationResponseDto,
);
} catch (error) {
// Generic error handling
throw new HttpException(
error.message || 'An error occurred while fetching communities.',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async updateCommunity(
@@ -112,7 +125,7 @@ export class CommunityService {
): Promise<BaseResponseDto> {
const { communityUuid, projectUuid } = params;
await this.validateProject(projectUuid);
const project = await this.validateProject(projectUuid);
const community = await this.communityRepository.findOne({
where: { uuid: communityUuid },
@@ -126,6 +139,13 @@ export class CommunityService {
);
}
if (community.name === `${ORPHAN_COMMUNITY_NAME}-${project.name}`) {
throw new HttpException(
`Community with ID ${communityUuid} cannot be updated`,
HttpStatus.BAD_REQUEST,
);
}
try {
const { name } = updateCommunityDto;
@@ -151,7 +171,7 @@ export class CommunityService {
async deleteCommunity(params: GetCommunityParams): Promise<BaseResponseDto> {
const { communityUuid, projectUuid } = params;
await this.validateProject(projectUuid);
const project = await this.validateProject(projectUuid);
const community = await this.communityRepository.findOne({
where: { uuid: communityUuid },
@@ -164,6 +184,14 @@ export class CommunityService {
HttpStatus.NOT_FOUND,
);
}
if (community.name === `${ORPHAN_COMMUNITY_NAME}-${project.name}`) {
throw new HttpException(
`Community with ID ${communityUuid} cannot be deleted`,
HttpStatus.BAD_REQUEST,
);
}
try {
await this.communityRepository.remove(community);
@@ -0,0 +1,6 @@
import { ICommand } from '@nestjs/cqrs';
import { ProjectEntity } from '@app/common/modules/project/entities';
export class CreateOrphanSpaceCommand implements ICommand {
constructor(public readonly project: ProjectEntity) {}
}
View File
@@ -0,0 +1,54 @@
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
import { CreateOrphanSpaceCommand } from '../command/create-orphan-space-command';
import { SpaceRepository } from '@app/common/modules/space';
import { CommunityRepository } from '@app/common/modules/community/repositories';
import { Logger } from '@nestjs/common';
import {
ORPHAN_COMMUNITY_DESCRIPTION,
ORPHAN_COMMUNITY_NAME,
ORPHAN_SPACE_NAME,
} from '@app/common/constants/orphan-constant';
@CommandHandler(CreateOrphanSpaceCommand)
export class CreateOrphanSpaceHandler
implements ICommandHandler<CreateOrphanSpaceCommand>
{
private readonly logger = new Logger(CreateOrphanSpaceHandler.name);
constructor(
private readonly spaceRepository: SpaceRepository,
private readonly communityRepository: CommunityRepository,
) {}
async execute(command: CreateOrphanSpaceCommand): Promise<void> {
try {
const { project } = command;
const orphanCommunityName = `${ORPHAN_COMMUNITY_NAME}-${project.name}`;
let orphanCommunity = await this.communityRepository.findOne({
where: { name: orphanCommunityName, project },
});
if (!orphanCommunity) {
orphanCommunity = this.communityRepository.create({
name: orphanCommunityName,
description: ORPHAN_COMMUNITY_DESCRIPTION,
project,
});
orphanCommunity = await this.communityRepository.save(orphanCommunity);
}
const orphanSpace = this.spaceRepository.create({
spaceName: ORPHAN_SPACE_NAME,
community: orphanCommunity,
});
await this.spaceRepository.save(orphanSpace);
} catch (error) {
this.logger.error(
`Error when creating orphan space for project ${JSON.stringify(
command.project.uuid,
)} - ERROR ${error}.`,
);
}
}
}
+1
View File
@@ -0,0 +1 @@
export * from './create-orphan-space.handler.service'
+15 -3
View File
@@ -1,13 +1,25 @@
import { Global, Module } from '@nestjs/common';
import { CqrsModule } from '@nestjs/cqrs';
import { ProjectController } from './controllers';
import { ProjectService } from './services';
import { ProjectRepository } from '@app/common/modules/project/repositiories';
import { CreateOrphanSpaceHandler } from './handler';
import { SpaceRepository } from '@app/common/modules/space';
import { CommunityRepository } from '@app/common/modules/community/repositories';
const CommandHandlers = [CreateOrphanSpaceHandler];
@Global()
@Module({
imports: [],
imports: [CqrsModule],
controllers: [ProjectController],
providers: [ProjectService, ProjectRepository],
exports: [ProjectService],
providers: [
...CommandHandlers,
SpaceRepository,
CommunityRepository,
ProjectService,
ProjectRepository,
],
exports: [ProjectService, CqrsModule],
})
export class ProjectModule {}
+9 -2
View File
@@ -10,10 +10,15 @@ import {
} 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';
@Injectable()
export class ProjectService {
constructor(private readonly projectRepository: ProjectRepository) {}
constructor(
private readonly projectRepository: ProjectRepository,
private commandBus: CommandBus,
) {}
async createProject(
createProjectDto: CreateProjectDto,
@@ -33,6 +38,8 @@ export class ProjectService {
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,
@@ -44,7 +51,7 @@ export class ProjectService {
}
throw new HttpException(
'An error occurred while creating the project. Please try again later.',
`An error occurred while creating the project. Please try again later. ${error}`,
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
+26 -2
View File
@@ -20,8 +20,9 @@ import { SpaceLinkService } from './space-link';
import { SpaceProductService } from './space-products';
import { CreateSubspaceModelDto } from 'src/space-model/dtos';
import { SubSpaceService } from './subspace';
import { DataSource } from 'typeorm';
import { DataSource, Not } from 'typeorm';
import { ValidationService } from './space-validation.service';
import { ORPHAN_SPACE_NAME } from '@app/common/constants/orphan-constant';
@Injectable()
export class SpaceService {
@@ -42,6 +43,13 @@ export class SpaceService {
addSpaceDto;
const { communityUuid, projectUuid } = params;
if (addSpaceDto.spaceName === ORPHAN_SPACE_NAME) {
throw new HttpException(
`Name ${ORPHAN_SPACE_NAME} cannot be used`,
HttpStatus.BAD_REQUEST,
);
}
const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect();
@@ -137,7 +145,10 @@ export class SpaceService {
try {
// Get all spaces related to the community, including the parent-child relations
const spaces = await this.spaceRepository.find({
where: { community: { uuid: communityUuid } },
where: {
community: { uuid: communityUuid },
spaceName: Not(`${ORPHAN_SPACE_NAME}`),
},
relations: [
'parent',
'children',
@@ -200,6 +211,12 @@ export class SpaceService {
spaceUuid,
);
if (space.spaceName === ORPHAN_SPACE_NAME) {
throw new HttpException(
`space ${ORPHAN_SPACE_NAME} cannot be deleted`,
HttpStatus.BAD_REQUEST,
);
}
// Delete the space
await this.spaceRepository.remove(space);
@@ -236,6 +253,13 @@ export class SpaceService {
spaceUuid,
);
if (space.spaceName === ORPHAN_SPACE_NAME) {
throw new HttpException(
`space ${ORPHAN_SPACE_NAME} cannot be updated`,
HttpStatus.BAD_REQUEST,
);
}
// If a parentId is provided, check if the parent exists
const { parentUuid, products } = updateSpaceDto;
const parent = parentUuid