diff --git a/src/space-model/services/space-model.service.ts b/src/space-model/services/space-model.service.ts index c25fcbd..47a905c 100644 --- a/src/space-model/services/space-model.service.ts +++ b/src/space-model/services/space-model.service.ts @@ -40,6 +40,10 @@ 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'; +import { DeviceEntity } from '@app/common/modules/device/entities'; @Injectable() export class SpaceModelService { @@ -387,10 +391,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 +410,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 +429,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 +446,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, + ); + } } }), ); @@ -441,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), ), @@ -453,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, @@ -471,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}`, @@ -487,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/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 614950f..11a94e8 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(), ]); @@ -435,6 +447,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( @@ -452,6 +467,36 @@ 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) { + await this.spaceModelService.overwriteSpace( + space, + project, + queryRunner, + ); + await this.spaceModelService.linkToSpace( + space, + spaceModel, + queryRunner, + ); + } + } + const hasSubspace = updateSpaceDto.subspace?.length > 0; const hasTags = updateSpaceDto.tags?.length > 0;