mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-11-26 08:54:54 +00:00
added linking
This commit is contained in:
@ -5,11 +5,15 @@ import {
|
|||||||
SubspaceModelProductAllocationEntity,
|
SubspaceModelProductAllocationEntity,
|
||||||
} from '@app/common/modules/space-model';
|
} from '@app/common/modules/space-model';
|
||||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
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 { ProjectParam } from 'src/community/dtos';
|
||||||
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
||||||
import { SubSpaceModelService } from './subspace/subspace-model.service';
|
import { SubSpaceModelService } from './subspace/subspace-model.service';
|
||||||
import { DataSource, QueryRunner, SelectQueryBuilder } from 'typeorm';
|
import { DataSource, In, QueryRunner, SelectQueryBuilder } from 'typeorm';
|
||||||
import {
|
import {
|
||||||
TypeORMCustomModel,
|
TypeORMCustomModel,
|
||||||
TypeORMCustomModelFindAllQuery,
|
TypeORMCustomModelFindAllQuery,
|
||||||
@ -21,7 +25,20 @@ import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
|||||||
import { CommandBus } from '@nestjs/cqrs';
|
import { CommandBus } from '@nestjs/cqrs';
|
||||||
import { ProcessTagDto } from 'src/tags/dtos';
|
import { ProcessTagDto } from 'src/tags/dtos';
|
||||||
import { SpaceModelProductAllocationService } from './space-model-product-allocation.service';
|
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()
|
@Injectable()
|
||||||
export class SpaceModelService {
|
export class SpaceModelService {
|
||||||
@ -33,6 +50,10 @@ export class SpaceModelService {
|
|||||||
private commandBus: CommandBus,
|
private commandBus: CommandBus,
|
||||||
private readonly spaceModelProductAllocationService: SpaceModelProductAllocationService,
|
private readonly spaceModelProductAllocationService: SpaceModelProductAllocationService,
|
||||||
private readonly spaceRepository: SpaceRepository,
|
private readonly spaceRepository: SpaceRepository,
|
||||||
|
private readonly spaceProductAllocationRepository: SpaceProductAllocationRepository,
|
||||||
|
private readonly subspaceRepository: SubspaceRepository,
|
||||||
|
private readonly subspaceProductAllocationRepository: SubspaceProductAllocationRepository,
|
||||||
|
private readonly deviceRepository: DeviceRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async createSpaceModel(
|
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> {
|
async validateName(modelName: string, projectUuid: string): Promise<void> {
|
||||||
const isModelExist = await this.spaceModelRepository.findOne({
|
const isModelExist = await this.spaceModelRepository.findOne({
|
||||||
where: { modelName, project: { uuid: projectUuid }, disabled: false },
|
where: { modelName, project: { uuid: projectUuid }, disabled: false },
|
||||||
|
|||||||
Reference in New Issue
Block a user