added linking

This commit is contained in:
hannathkadher
2025-03-02 00:08:28 +04:00
parent b6c305a6f7
commit 1d71be4b06

View File

@ -5,11 +5,15 @@ import {
SubspaceModelProductAllocationEntity,
} 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, SelectQueryBuilder } from 'typeorm';
import { DataSource, In, QueryRunner, SelectQueryBuilder } from 'typeorm';
import {
TypeORMCustomModel,
TypeORMCustomModelFindAllQuery,
@ -21,7 +25,20 @@ import { BaseResponseDto } from '@app/common/dto/base.response.dto';
import { CommandBus } from '@nestjs/cqrs';
import { ProcessTagDto } from 'src/tags/dtos';
import { SpaceModelProductAllocationService } from './space-model-product-allocation.service';
import { SpaceRepository } from '@app/common/modules/space';
import {
SpaceProductAllocationRepository,
SpaceRepository,
} from '@app/common/modules/space';
import { SpaceEntity } from '@app/common/modules/space/entities/space.entity';
import {
SubspaceProductAllocationRepository,
SubspaceRepository,
} from '@app/common/modules/space/repositories/subspace.repository';
import {
ORPHAN_COMMUNITY_NAME,
ORPHAN_SPACE_NAME,
} from '@app/common/constants/orphan-constant';
import { DeviceRepository } from '@app/common/modules/device/repositories';
@Injectable()
export class SpaceModelService {
@ -33,6 +50,10 @@ export class SpaceModelService {
private commandBus: CommandBus,
private readonly spaceModelProductAllocationService: SpaceModelProductAllocationService,
private readonly spaceRepository: SpaceRepository,
private readonly spaceProductAllocationRepository: SpaceProductAllocationRepository,
private readonly subspaceRepository: SubspaceRepository,
private readonly subspaceProductAllocationRepository: SubspaceProductAllocationRepository,
private readonly deviceRepository: DeviceRepository,
) {}
async createSpaceModel(
@ -286,6 +307,205 @@ export class SpaceModelService {
}
}
async linkSpaceModel(
params: SpaceModelParam,
dto: LinkSpacesToModelDto,
): Promise<BaseResponseDto> {
const project = await this.validateProject(params.projectUuid);
try {
const spaceModel = await this.spaceModelRepository.findOne({
where: { uuid: params.spaceModelUuid },
relations: [
'productAllocations',
'subspaceModels',
'subspaceModels.productAllocations',
],
});
if (!spaceModel) {
throw new HttpException(
`Space Model with UUID ${params.spaceModelUuid} not found`,
HttpStatus.NOT_FOUND,
);
}
if (!spaceModel.productAllocations.length) {
throw new HttpException(
`Space Model ${params.spaceModelUuid} has no product allocations`,
HttpStatus.BAD_REQUEST,
);
}
const spaces = await this.spaceRepository.find({
where: { uuid: In(dto.spaceUuids), disabled: false },
relations: [
'spaceModel',
'devices',
'subspaces',
'productAllocations',
'subspaces.productAllocations',
'community',
],
});
if (!spaces.length) {
throw new HttpException(
`No spaces found for the given UUIDs`,
HttpStatus.NOT_FOUND,
);
}
await Promise.all(
spaces.map(async (space) => {
const hasDependencies =
space.devices.length > 0 ||
space.subspaces.length > 0 ||
space.productAllocations.length > 0;
if (!hasDependencies && !space.spaceModel) {
await this.linkToSpace(space, spaceModel);
} else if (dto.overwrite) {
await this.overwriteSpace(space, project);
await this.linkToSpace(space, spaceModel);
}
}),
);
return new SuccessResponseDto({
message: 'Spaces linked successfully',
data: dto.spaceUuids,
});
} catch (error) {
throw new HttpException(
`Failed to link space model: ${error.message}`,
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async linkToSpace(
space: SpaceEntity,
spaceModel: SpaceModelEntity,
): Promise<void> {
try {
space.spaceModel = spaceModel;
await this.spaceRepository.save(space);
const spaceProductAllocations = spaceModel.productAllocations.map(
(modelAllocation) =>
this.spaceProductAllocationRepository.create({
space,
inheritedFromModel: modelAllocation,
product: modelAllocation.product,
tags: modelAllocation.tags,
}),
);
await this.spaceProductAllocationRepository.save(spaceProductAllocations);
if (!spaceModel.subspaceModels.length) {
throw new HttpException(
`Space Model ${spaceModel.uuid} has no subspaces`,
HttpStatus.BAD_REQUEST,
);
}
await Promise.all(
spaceModel.subspaceModels.map(async (subspaceModel) => {
const subspace = this.subspaceRepository.create({
subspaceName: subspaceModel.subspaceName,
subSpaceModel: subspaceModel,
space: space,
});
await this.subspaceRepository.save(subspace);
const subspaceAllocations = subspaceModel.productAllocations.map(
(modelAllocation) =>
this.subspaceProductAllocationRepository.create({
subspace,
inheritedFromModel: modelAllocation,
product: modelAllocation.product,
tags: modelAllocation.tags,
}),
);
if (subspaceAllocations.length) {
await this.subspaceProductAllocationRepository.save(
subspaceAllocations,
);
}
}),
);
} catch (error) {
throw new HttpException(
`Failed to link space ${space.uuid} to space model ${spaceModel.uuid}: ${error.message}`,
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async overwriteSpace(
space: SpaceEntity,
project: ProjectEntity,
): Promise<void> {
try {
if (space.productAllocations.length) {
await this.spaceProductAllocationRepository.delete({
uuid: In(
space.productAllocations.map((allocation) => allocation.uuid),
),
});
}
await Promise.all(
space.subspaces.map(async (subspace) => {
await this.subspaceRepository.update(
{ uuid: subspace.uuid },
{ disabled: true },
);
if (subspace.productAllocations.length) {
await this.subspaceProductAllocationRepository.delete({
uuid: In(
subspace.productAllocations.map(
(allocation) => allocation.uuid,
),
),
});
}
}),
);
if (space.devices.length > 0) {
const orphanSpace = await this.spaceRepository.findOne({
where: {
community: {
name: `${ORPHAN_COMMUNITY_NAME}-${project.name}`,
},
spaceName: ORPHAN_SPACE_NAME,
},
});
if (!orphanSpace) {
throw new HttpException(
`Orphan space not found in community ${project.name}`,
HttpStatus.NOT_FOUND,
);
}
await this.deviceRepository.update(
{ uuid: In(space.devices.map((device) => device.uuid)) },
{ spaceDevice: orphanSpace },
);
}
} catch (error) {
throw new Error(
`Failed to overwrite space ${space.uuid}: ${error.message}`,
);
}
}
async validateName(modelName: string, projectUuid: string): Promise<void> {
const isModelExist = await this.spaceModelRepository.findOne({
where: { modelName, project: { uuid: projectUuid }, disabled: false },