From 6864e000b8b3956d6451a6d81567d6fb3f9b5b64 Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Thu, 6 Mar 2025 02:33:48 +0300 Subject: [PATCH 1/2] add space linking when create or update space --- .../services/space-model.service.ts | 40 ++++++++++++++--- src/space/dtos/update.space.dto.ts | 7 +++ src/space/services/space.service.ts | 44 +++++++++++++++++-- 3 files changed, 81 insertions(+), 10 deletions(-) diff --git a/src/space-model/services/space-model.service.ts b/src/space-model/services/space-model.service.ts index c25fcbd..f5d2cf3 100644 --- a/src/space-model/services/space-model.service.ts +++ b/src/space-model/services/space-model.service.ts @@ -40,6 +40,9 @@ import { ORPHAN_SPACE_NAME, } from '@app/common/constants/orphan-constant'; import { DeviceRepository } from '@app/common/modules/device/repositories'; +import { SpaceProductAllocationEntity } from '@app/common/modules/space/entities/space-product-allocation.entity'; +import { SubspaceEntity } from '@app/common/modules/space/entities/subspace/subspace.entity'; +import { SubspaceProductAllocationEntity } from '@app/common/modules/space/entities/subspace/subspace-product-allocation.entity'; @Injectable() export class SpaceModelService { @@ -387,10 +390,15 @@ export class SpaceModelService { async linkToSpace( space: SpaceEntity, spaceModel: SpaceModelEntity, + queryRunner?: QueryRunner, // Make queryRunner optional ): Promise { try { space.spaceModel = spaceModel; - await this.spaceRepository.save(space); + if (queryRunner) { + await queryRunner.manager.save(SpaceEntity, space); + } else { + await this.spaceRepository.save(space); + } const spaceProductAllocations = spaceModel.productAllocations.map( (modelAllocation) => @@ -401,8 +409,17 @@ export class SpaceModelService { tags: modelAllocation.tags, }), ); - await this.spaceProductAllocationRepository.save(spaceProductAllocations); + if (queryRunner) { + await queryRunner.manager.save( + SpaceProductAllocationEntity, + spaceProductAllocations, + ); + } else { + await this.spaceProductAllocationRepository.save( + spaceProductAllocations, + ); + } await Promise.all( spaceModel.subspaceModels.map(async (subspaceModel) => { const subspace = this.subspaceRepository.create({ @@ -411,7 +428,11 @@ export class SpaceModelService { space: space, }); - await this.subspaceRepository.save(subspace); + if (queryRunner) { + await queryRunner.manager.save(SubspaceEntity, subspace); + } else { + await this.subspaceRepository.save(subspace); + } const subspaceAllocations = subspaceModel.productAllocations.map( (modelAllocation) => @@ -424,9 +445,16 @@ export class SpaceModelService { ); if (subspaceAllocations.length) { - await this.subspaceProductAllocationRepository.save( - subspaceAllocations, - ); + if (queryRunner) { + await queryRunner.manager.save( + SubspaceProductAllocationEntity, + subspaceAllocations, + ); + } else { + await this.subspaceProductAllocationRepository.save( + subspaceAllocations, + ); + } } }), ); diff --git a/src/space/dtos/update.space.dto.ts b/src/space/dtos/update.space.dto.ts index 02efb86..31ff54f 100644 --- a/src/space/dtos/update.space.dto.ts +++ b/src/space/dtos/update.space.dto.ts @@ -58,4 +58,11 @@ export class UpdateSpaceDto { @ValidateNested({ each: true }) @Type(() => ModifyTagDto) tags?: ModifyTagDto[]; + @ApiProperty({ + description: 'UUID of the Space', + example: 'd290f1ee-6c54-4b01-90e6-d701748f0851', + }) + @IsString() + @IsOptional() + spaceModelUuid?: string; } diff --git a/src/space/services/space.service.ts b/src/space/services/space.service.ts index 53638c2..8df7cf5 100644 --- a/src/space/services/space.service.ts +++ b/src/space/services/space.service.ts @@ -104,10 +104,23 @@ export class SpaceService { this.subSpaceService.extractTagsFromSubspace(subspaces); const allTags = [...tags, ...subspaceTags]; this.validateUniqueTags(allTags); + if (spaceModelUuid) { + const hasDependencies = subspaces?.length > 0 || tags?.length > 0; + if (!hasDependencies && !newSpace.spaceModel) { + await this.spaceModelService.linkToSpace( + newSpace, + spaceModel, + queryRunner, + ); + } else if (hasDependencies) { + throw new HttpException( + `Space cannot be linked to a model because it has existing dependencies (subspaces or tags).`, + HttpStatus.BAD_REQUEST, + ); + } + } await Promise.all([ - spaceModelUuid && - this.createFromModel(spaceModelUuid, queryRunner, newSpace), direction && parent ? this.spaceLinkService.saveSpaceLink( parent.uuid, @@ -125,9 +138,8 @@ export class SpaceService { projectUuid, ) : Promise.resolve(), - tags?.length - ? this.createTags(tags, projectUuid, queryRunner, space) + ? this.createTags(tags, projectUuid, queryRunner, newSpace) : Promise.resolve(), ]); @@ -454,6 +466,30 @@ export class SpaceService { this.updateSpaceProperties(space, updateSpaceDto); + if (updateSpaceDto.spaceModelUuid) { + const spaceModel = await this.validationService.validateSpaceModel( + updateSpaceDto.spaceModelUuid, + ); + + const hasDependencies = + space.devices?.length > 0 || + space.subspaces?.length > 0 || + space.productAllocations?.length > 0; + + if (!hasDependencies && !space.spaceModel) { + await this.spaceModelService.linkToSpace( + space, + spaceModel, + queryRunner, + ); + } else if (hasDependencies) { + throw new HttpException( + `Space cannot be linked to a model because it has existing dependencies (devices, subspaces, or product allocations).`, + HttpStatus.BAD_REQUEST, + ); + } + } + const hasSubspace = updateSpaceDto.subspace?.length > 0; const hasTags = updateSpaceDto.tags?.length > 0; From 61692c70d142c3aa87f5884b40d80b4a36c387cf Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Thu, 6 Mar 2025 11:13:14 +0300 Subject: [PATCH 2/2] add overwrite when update spaces with spacesModel --- .../services/space-model.service.ts | 32 ++++++++++++++++--- src/space/services/space.service.ts | 15 +++++++-- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/space-model/services/space-model.service.ts b/src/space-model/services/space-model.service.ts index f5d2cf3..47a905c 100644 --- a/src/space-model/services/space-model.service.ts +++ b/src/space-model/services/space-model.service.ts @@ -43,6 +43,7 @@ import { DeviceRepository } from '@app/common/modules/device/repositories'; import { SpaceProductAllocationEntity } from '@app/common/modules/space/entities/space-product-allocation.entity'; import { SubspaceEntity } from '@app/common/modules/space/entities/subspace/subspace.entity'; import { SubspaceProductAllocationEntity } from '@app/common/modules/space/entities/subspace/subspace-product-allocation.entity'; +import { DeviceEntity } from '@app/common/modules/device/entities'; @Injectable() export class SpaceModelService { @@ -469,10 +470,31 @@ export class SpaceModelService { async overwriteSpace( space: SpaceEntity, project: ProjectEntity, + queryRunner?: QueryRunner, ): Promise { try { + const spaceProductAllocationRepository = queryRunner + ? queryRunner.manager.getRepository(SpaceProductAllocationEntity) + : this.spaceProductAllocationRepository; + + const subspaceRepository = queryRunner + ? queryRunner.manager.getRepository(SubspaceEntity) + : this.subspaceRepository; + + const subspaceProductAllocationRepository = queryRunner + ? queryRunner.manager.getRepository(SubspaceProductAllocationEntity) + : this.subspaceProductAllocationRepository; + + const spaceRepository = queryRunner + ? queryRunner.manager.getRepository(SpaceEntity) + : this.spaceRepository; + + const deviceRepository = queryRunner + ? queryRunner.manager.getRepository(DeviceEntity) + : this.deviceRepository; + if (space.productAllocations.length) { - await this.spaceProductAllocationRepository.delete({ + await spaceProductAllocationRepository.delete({ uuid: In( space.productAllocations.map((allocation) => allocation.uuid), ), @@ -481,13 +503,13 @@ export class SpaceModelService { await Promise.all( space.subspaces.map(async (subspace) => { - await this.subspaceRepository.update( + await subspaceRepository.update( { uuid: subspace.uuid }, { disabled: true }, ); if (subspace.productAllocations.length) { - await this.subspaceProductAllocationRepository.delete({ + await subspaceProductAllocationRepository.delete({ uuid: In( subspace.productAllocations.map( (allocation) => allocation.uuid, @@ -499,7 +521,7 @@ export class SpaceModelService { ); if (space.devices.length > 0) { - const orphanSpace = await this.spaceRepository.findOne({ + const orphanSpace = await spaceRepository.findOne({ where: { community: { name: `${ORPHAN_COMMUNITY_NAME}-${project.name}`, @@ -515,7 +537,7 @@ export class SpaceModelService { ); } - await this.deviceRepository.update( + await deviceRepository.update( { uuid: In(space.devices.map((device) => device.uuid)) }, { spaceDevice: orphanSpace }, ); diff --git a/src/space/services/space.service.ts b/src/space/services/space.service.ts index 8df7cf5..ef3ce18 100644 --- a/src/space/services/space.service.ts +++ b/src/space/services/space.service.ts @@ -449,6 +449,9 @@ export class SpaceService { try { await queryRunner.connect(); await queryRunner.startTransaction(); + const project = await this.spaceModelService.validateProject( + params.projectUuid, + ); const space = await this.validationService.validateSpaceWithinCommunityAndProject( @@ -483,9 +486,15 @@ export class SpaceService { queryRunner, ); } else if (hasDependencies) { - throw new HttpException( - `Space cannot be linked to a model because it has existing dependencies (devices, subspaces, or product allocations).`, - HttpStatus.BAD_REQUEST, + await this.spaceModelService.overwriteSpace( + space, + project, + queryRunner, + ); + await this.spaceModelService.linkToSpace( + space, + spaceModel, + queryRunner, ); } }