diff --git a/libs/common/src/constants/controller-route.ts b/libs/common/src/constants/controller-route.ts index 5471fc7..753bb41 100644 --- a/libs/common/src/constants/controller-route.ts +++ b/libs/common/src/constants/controller-route.ts @@ -307,6 +307,11 @@ export class ControllerRoute { public static readonly DELETE_SPACE_MODEL_SUMMARY = 'Delete Space Model'; public static readonly DELETE_SPACE_MODEL_DESCRIPTION = 'This endpoint allows you to delete a specified Space Model within a project. Deleting a Space Model disables the model and all its associated subspaces and tags, ensuring they are no longer active but remain in the system for auditing.'; + + public static readonly LINK_SPACE_MODEL_SUMMARY = + 'Link a Space Model to spaces'; + public static readonly LINK_SPACE_MODEL_DESCRIPTION = + 'This endpoint allows you to link a specified Space Model within a project to multiple spaces. Linking a Space Model applies the model and all its associated subspaces and tags, to the spaces.'; }; }; diff --git a/libs/common/src/constants/role-permissions.ts b/libs/common/src/constants/role-permissions.ts index 96655f7..f4c077d 100644 --- a/libs/common/src/constants/role-permissions.ts +++ b/libs/common/src/constants/role-permissions.ts @@ -23,6 +23,7 @@ export const RolePermissions = { 'SPACE_MODEL_VIEW', 'SPACE_MODEL_UPDATE', 'SPACE_MODEL_DELETE', + 'SPACE_MODEL_LINK', 'SPACE_ASSIGN_USER_TO_SPACE', 'SPACE_DELETE_USER_FROM_SPACE', 'SUBSPACE_VIEW', @@ -75,6 +76,7 @@ export const RolePermissions = { 'SPACE_MODEL_VIEW', 'SPACE_MODEL_UPDATE', 'SPACE_MODEL_DELETE', + 'SPACE_MODEL_LINK', 'SPACE_ASSIGN_USER_TO_SPACE', 'SPACE_DELETE_USER_FROM_SPACE', 'SUBSPACE_VIEW', diff --git a/src/space-model/dtos/index.ts b/src/space-model/dtos/index.ts index 3a04fe1..a49d8b0 100644 --- a/src/space-model/dtos/index.ts +++ b/src/space-model/dtos/index.ts @@ -4,3 +4,4 @@ export * from './update-space-model.dto'; export * from './space-model-param'; export * from './subspaces-model-dtos'; export * from './tag-model-dtos'; +export * from './link-space-model.dto'; diff --git a/src/space-model/dtos/link-space-model.dto.ts b/src/space-model/dtos/link-space-model.dto.ts new file mode 100644 index 0000000..07f7674 --- /dev/null +++ b/src/space-model/dtos/link-space-model.dto.ts @@ -0,0 +1,25 @@ +import { IsArray, ArrayNotEmpty, IsUUID, IsBoolean } from 'class-validator'; +import { ApiProperty } from '@nestjs/swagger'; + +export class LinkSpacesToModelDto { + @ApiProperty({ + description: 'List of space UUIDs to be linked to the space model', + type: [String], + example: [ + '550e8400-e29b-41d4-a716-446655440000', + 'f47ac10b-58cc-4372-a567-0e02b2c3d479', + ], + }) + @IsArray() + @ArrayNotEmpty() + @IsUUID() + spaceUuids: string[]; + + @ApiProperty({ + description: 'Whether to overwrite existing space model links', + type: Boolean, + example: false, + }) + @IsBoolean() + overwrite: boolean; +} diff --git a/src/space-model/services/space-model.service.ts b/src/space-model/services/space-model.service.ts index b68f82e..26dd6fe 100644 --- a/src/space-model/services/space-model.service.ts +++ b/src/space-model/services/space-model.service.ts @@ -3,11 +3,15 @@ import { SpaceModelRepository, } from '@app/common/modules/space-model'; import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; -import { CreateSpaceModelDto, UpdateSpaceModelDto } from '../dtos'; +import { + CreateSpaceModelDto, + LinkSpacesToModelDto, + UpdateSpaceModelDto, +} from '../dtos'; import { ProjectParam } from 'src/community/dtos'; import { SuccessResponseDto } from '@app/common/dto/success.response.dto'; import { SubSpaceModelService } from './subspace/subspace-model.service'; -import { DataSource, QueryRunner } from 'typeorm'; +import { DataSource, In, QueryRunner } from 'typeorm'; import { TypeORMCustomModel, TypeORMCustomModelFindAllQuery, @@ -23,6 +27,7 @@ import { SpaceModelDto } from '@app/common/modules/space-model/dtos'; import { TagService as NewTagService } from 'src/tags/services'; import { ProcessTagDto } from 'src/tags/dtos'; import { SpaceModelProductAllocationService } from './space-model-product-allocation.service'; +import { SpaceRepository } from '@app/common/modules/space'; @Injectable() export class SpaceModelService { @@ -35,6 +40,7 @@ export class SpaceModelService { private commandBus: CommandBus, private readonly tagService: NewTagService, private readonly spaceModelProductAllocationService: SpaceModelProductAllocationService, + private readonly spaceRepository: SpaceRepository, ) {} async createSpaceModel( @@ -408,4 +414,34 @@ export class SpaceModelService { } } } + + async linkSpacesToModel(params: SpaceModelParam, dto: LinkSpacesToModelDto) { + await this.validateProject(params.projectUuid); + const spaceModel = await this.validateSpaceModel(params.spaceModelUuid); + + const spaces = await this.spaceRepository.find({ + where: { uuid: In(dto.spaceUuids) }, + relations: [ + 'spaceModel', + 'devices', + 'subspaces', + 'productAllocations', + 'subspace.productAllocations', + ], + }); + + if (!spaces.length) { + throw new HttpException( + `No spaces found for the given UUIDs`, + HttpStatus.NOT_FOUND, + ); + } + + for (const space of spaces) { + const hasDependencies = + space.devices.length > 0 || + space.subspaces.length > 0 || + space.productAllocations.length > 0; + } + } }