mirror of
https://github.com/SyncrowIOT/backend.git
synced 2026-10-23 08:07:55 +00:00
Merge pull request #292 from SyncrowIOT:feat/remove-tag
removed old tags
This commit is contained in:
@@ -6,7 +6,6 @@ import {
|
||||
Unique,
|
||||
Index,
|
||||
JoinColumn,
|
||||
OneToOne,
|
||||
JoinTable,
|
||||
} from 'typeorm';
|
||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||
@@ -18,7 +17,6 @@ import { PermissionTypeEntity } from '../../permission/entities';
|
||||
import { SceneDeviceEntity } from '../../scene-device/entities';
|
||||
import { SpaceEntity } from '../../space/entities/space.entity';
|
||||
import { SubspaceEntity } from '../../space/entities/subspace/subspace.entity';
|
||||
import { TagEntity } from '../../space/entities/tag.entity';
|
||||
import { NewTagEntity } from '../../tag';
|
||||
|
||||
@Entity({ name: 'device' })
|
||||
@@ -79,14 +77,10 @@ export class DeviceEntity extends AbstractEntity<DeviceDto> {
|
||||
@OneToMany(() => SceneDeviceEntity, (sceneDevice) => sceneDevice.device, {})
|
||||
sceneDevices: SceneDeviceEntity[];
|
||||
|
||||
@OneToOne(() => TagEntity, (tag) => tag.device, {
|
||||
nullable: true,
|
||||
})
|
||||
tag: TagEntity;
|
||||
|
||||
@OneToMany(() => NewTagEntity, (tag) => tag.devices)
|
||||
@JoinTable({ name: 'device_tags' })
|
||||
public tags: NewTagEntity[];
|
||||
public tag: NewTagEntity[];
|
||||
|
||||
constructor(partial: Partial<DeviceEntity>) {
|
||||
super();
|
||||
|
||||
@@ -1546,4 +1546,21 @@ export class DeviceService {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async moveDevicesToSpace(
|
||||
targetSpace: SpaceEntity,
|
||||
deviceIds: string[],
|
||||
): Promise<void> {
|
||||
if (!deviceIds || deviceIds.length === 0) {
|
||||
throw new HttpException(
|
||||
'No device IDs provided for transfer',
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
|
||||
await this.deviceRepository.update(
|
||||
{ uuid: In(deviceIds) },
|
||||
{ spaceDevice: targetSpace },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export * from './propogate-subspace-update-command';
|
||||
export * from './propagate-space-model-deletion.command';
|
||||
export * from './propagate-subspace-model-update-command';
|
||||
|
||||
+4
-4
@@ -1,14 +1,14 @@
|
||||
import { ICommand } from '@nestjs/cqrs';
|
||||
import { SpaceModelEntity } from '@app/common/modules/space-model';
|
||||
import { ModifyspaceModelPayload } from '../interfaces';
|
||||
import { QueryRunner } from 'typeorm';
|
||||
import { ISingleSubspaceModel } from '../interfaces';
|
||||
import { SpaceEntity } from '@app/common/modules/space/entities/space.entity';
|
||||
|
||||
export class PropogateUpdateSpaceModelCommand implements ICommand {
|
||||
constructor(
|
||||
public readonly param: {
|
||||
spaceModel: SpaceModelEntity;
|
||||
modifiedSpaceModels: ModifyspaceModelPayload;
|
||||
queryRunner: QueryRunner;
|
||||
subspaceModels: ISingleSubspaceModel[];
|
||||
spaces: SpaceEntity[];
|
||||
},
|
||||
) {}
|
||||
}
|
||||
@@ -2,18 +2,16 @@ import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
|
||||
import { PropogateUpdateSpaceModelCommand } from '../commands';
|
||||
import { SpaceRepository } from '@app/common/modules/space';
|
||||
import { SubspaceRepository } from '@app/common/modules/space/repositories/subspace.repository';
|
||||
import {
|
||||
SpaceModelEntity,
|
||||
SubspaceModelEntity,
|
||||
TagModel,
|
||||
} from '@app/common/modules/space-model';
|
||||
import { SpaceModelEntity, TagModel } from '@app/common/modules/space-model';
|
||||
import { DataSource, QueryRunner } from 'typeorm';
|
||||
import { SubSpaceService } from 'src/space/services';
|
||||
import { TagService } from 'src/space/services/tag';
|
||||
import { UpdatedSubspaceModelPayload } from '../interfaces';
|
||||
import { ModifyAction } from '@app/common/constants/modify-action.enum';
|
||||
import { ModifySubspaceDto } from 'src/space/dtos';
|
||||
import {
|
||||
ISingleSubspaceModel,
|
||||
UpdatedSubspaceModelPayload,
|
||||
} from '../interfaces';
|
||||
import { SpaceEntity } from '@app/common/modules/space/entities/space.entity';
|
||||
import { ModifyAction } from '@app/common/constants/modify-action.enum';
|
||||
|
||||
@CommandHandler(PropogateUpdateSpaceModelCommand)
|
||||
export class PropogateUpdateSpaceModelHandler
|
||||
@@ -28,86 +26,27 @@ export class PropogateUpdateSpaceModelHandler
|
||||
) {}
|
||||
|
||||
async execute(command: PropogateUpdateSpaceModelCommand): Promise<void> {
|
||||
const { spaceModel, modifiedSpaceModels, queryRunner } = command.param;
|
||||
console.log("propagate");
|
||||
const { spaceModel, subspaceModels, spaces } = command.param;
|
||||
|
||||
try {
|
||||
const spaces = await queryRunner.manager.find(SpaceEntity, {
|
||||
where: { spaceModel },
|
||||
});
|
||||
if (!subspaceModels || subspaceModels.length === 0) return;
|
||||
|
||||
const { modifiedSubspaceModels = {}, modifiedTags = {} } =
|
||||
modifiedSpaceModels;
|
||||
if (!spaces) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
addedSubspaceModels = [],
|
||||
updatedSubspaceModels = [],
|
||||
deletedSubspaceModels = [],
|
||||
} = modifiedSubspaceModels;
|
||||
|
||||
const { added = [], updated = [], deleted = [] } = modifiedTags;
|
||||
|
||||
if (addedSubspaceModels.length > 0) {
|
||||
await this.addSubspaceModels(
|
||||
modifiedSpaceModels.modifiedSubspaceModels.addedSubspaceModels,
|
||||
spaces,
|
||||
queryRunner,
|
||||
);
|
||||
} else if (updatedSubspaceModels.length > 0) {
|
||||
await this.updateSubspaceModels(
|
||||
modifiedSpaceModels.modifiedSubspaceModels.updatedSubspaceModels,
|
||||
queryRunner,
|
||||
);
|
||||
for (const subspaceModel of subspaceModels) {
|
||||
if (subspaceModel.action === ModifyAction.ADD) {
|
||||
await this.addSubspaceModel(subspaceModel, spaces);
|
||||
}
|
||||
if (deletedSubspaceModels.length > 0) {
|
||||
const dtos: ModifySubspaceDto[] =
|
||||
modifiedSpaceModels.modifiedSubspaceModels.deletedSubspaceModels.map(
|
||||
(model) => ({
|
||||
action: ModifyAction.DELETE,
|
||||
uuid: model,
|
||||
}),
|
||||
);
|
||||
await this.subSpaceService.modifySubSpace(dtos, queryRunner);
|
||||
}
|
||||
|
||||
if (added.length > 0) {
|
||||
await this.createTags(
|
||||
modifiedSpaceModels.modifiedTags.added,
|
||||
queryRunner,
|
||||
null,
|
||||
spaceModel,
|
||||
);
|
||||
}
|
||||
|
||||
if (updated.length > 0) {
|
||||
await this.updateTags(
|
||||
modifiedSpaceModels.modifiedTags.updated,
|
||||
queryRunner,
|
||||
);
|
||||
}
|
||||
|
||||
if (deleted.length > 0) {
|
||||
await this.deleteTags(
|
||||
modifiedSpaceModels.modifiedTags.deleted,
|
||||
queryRunner,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async addSubspaceModels(
|
||||
subspaceModels: SubspaceModelEntity[],
|
||||
async addSubspaceModel(
|
||||
subspaceModel: ISingleSubspaceModel,
|
||||
spaces: SpaceEntity[],
|
||||
queryRunner: QueryRunner,
|
||||
) {
|
||||
for (const space of spaces) {
|
||||
await this.subSpaceService.createSubSpaceFromModel(
|
||||
subspaceModels,
|
||||
space,
|
||||
queryRunner,
|
||||
);
|
||||
}
|
||||
console.log(`subspace is ${JSON.stringify(subspaceModel)}`);
|
||||
}
|
||||
|
||||
async updateSubspaceModels(
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import { SubspaceModelProductAllocationEntity } from '@app/common/modules/space-model';
|
||||
import { NewTagEntity } from '@app/common/modules/tag';
|
||||
|
||||
export type IUpdatedAllocations = {
|
||||
allocation?: SubspaceModelProductAllocationEntity;
|
||||
tagsRemoved?: NewTagEntity[];
|
||||
tagsAdded?: NewTagEntity[];
|
||||
newAllocation?: SubspaceModelProductAllocationEntity;
|
||||
deletedAllocation?: SubspaceModelProductAllocationEntity;
|
||||
};
|
||||
|
||||
export interface ISubspaceProductAllocationUpdateResult {
|
||||
createdAllocations: ICreatedAllocation[];
|
||||
updatedAllocations: IUpdatedAllocation[];
|
||||
deletedAllocations: IDeletedAllocation[];
|
||||
}
|
||||
|
||||
export interface ICreatedAllocation {
|
||||
allocation: SubspaceModelProductAllocationEntity;
|
||||
tags: NewTagEntity[];
|
||||
}
|
||||
|
||||
export interface IUpdatedAllocation {
|
||||
allocation: SubspaceModelProductAllocationEntity;
|
||||
tagsAdded: NewTagEntity[];
|
||||
tagsRemoved: NewTagEntity[];
|
||||
}
|
||||
|
||||
export interface IDeletedAllocation {
|
||||
allocation: SubspaceModelProductAllocationEntity;
|
||||
tagsRemoved: NewTagEntity[];
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import { NewTagEntity } from '@app/common/modules/tag';
|
||||
import { ProductEntity } from '@app/common/modules/product/entities';
|
||||
import { SpaceRepository } from '@app/common/modules/space';
|
||||
import { SpaceEntity } from '@app/common/modules/space/entities/space.entity';
|
||||
import { ProjectEntity } from '@app/common/modules/project/entities';
|
||||
|
||||
@Injectable()
|
||||
export class SpaceModelProductAllocationService {
|
||||
@@ -128,7 +129,7 @@ export class SpaceModelProductAllocationService {
|
||||
|
||||
async updateProductAllocations(
|
||||
dtos: ModifyTagModelDto[],
|
||||
projectUuid: string,
|
||||
project: ProjectEntity,
|
||||
spaceModel: SpaceModelEntity,
|
||||
queryRunner: QueryRunner,
|
||||
modifySubspaceModels?: ModifySubspaceModelDto[],
|
||||
@@ -148,7 +149,7 @@ export class SpaceModelProductAllocationService {
|
||||
|
||||
const processedTags = await this.tagService.processTags(
|
||||
addTagDtos,
|
||||
projectUuid,
|
||||
project.uuid,
|
||||
queryRunner,
|
||||
);
|
||||
const addTagUuidMap = new Map<string, ModifyTagModelDto>();
|
||||
@@ -179,13 +180,19 @@ export class SpaceModelProductAllocationService {
|
||||
await Promise.all([
|
||||
this.processAddActions(
|
||||
filteredDtos,
|
||||
projectUuid,
|
||||
project.uuid,
|
||||
spaceModel,
|
||||
queryRunner,
|
||||
modifySubspaceModels,
|
||||
spaces,
|
||||
),
|
||||
this.processDeleteActions(filteredDtos, queryRunner, spaceModel),
|
||||
this.processDeleteActions(
|
||||
filteredDtos,
|
||||
queryRunner,
|
||||
spaceModel,
|
||||
project,
|
||||
spaces,
|
||||
),
|
||||
]);
|
||||
} catch (error) {
|
||||
throw this.handleError(error, 'Error while updating product allocations');
|
||||
@@ -291,6 +298,8 @@ export class SpaceModelProductAllocationService {
|
||||
dtos: ModifyTagModelDto[],
|
||||
queryRunner: QueryRunner,
|
||||
spaceModel: SpaceModelEntity,
|
||||
project: ProjectEntity,
|
||||
spaces?: SpaceEntity[],
|
||||
): Promise<SpaceModelProductAllocationEntity[]> {
|
||||
try {
|
||||
if (!dtos || dtos.length === 0) {
|
||||
@@ -312,7 +321,11 @@ export class SpaceModelProductAllocationService {
|
||||
uuid: spaceModel.uuid,
|
||||
},
|
||||
},
|
||||
relations: ['tags'],
|
||||
relations: [
|
||||
'tags',
|
||||
'inheritedSpaceAllocations',
|
||||
'inheritedSpaceAllocations.tags',
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -25,7 +25,10 @@ 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 { PropogateDeleteSpaceModelCommand } from '../commands';
|
||||
import {
|
||||
PropogateDeleteSpaceModelCommand,
|
||||
PropogateUpdateSpaceModelCommand,
|
||||
} from '../commands';
|
||||
import {
|
||||
SpaceProductAllocationRepository,
|
||||
SpaceRepository,
|
||||
@@ -44,6 +47,7 @@ import { SpaceProductAllocationEntity } from '@app/common/modules/space/entities
|
||||
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';
|
||||
import { ISingleSubspaceModel } from '../interfaces';
|
||||
|
||||
@Injectable()
|
||||
export class SpaceModelService {
|
||||
@@ -189,13 +193,13 @@ export class SpaceModelService {
|
||||
|
||||
async update(dto: UpdateSpaceModelDto, param: SpaceModelParam) {
|
||||
const queryRunner = this.dataSource.createQueryRunner();
|
||||
await this.validateProject(param.projectUuid);
|
||||
const project = await this.validateProject(param.projectUuid);
|
||||
const spaceModel = await this.validateSpaceModel(
|
||||
param.spaceModelUuid,
|
||||
param.projectUuid,
|
||||
);
|
||||
await queryRunner.connect();
|
||||
|
||||
let modifiedSubspaces: ISingleSubspaceModel[] = [];
|
||||
try {
|
||||
await queryRunner.startTransaction();
|
||||
const spaces = await this.fetchModelSpaces(spaceModel);
|
||||
@@ -215,19 +219,20 @@ export class SpaceModelService {
|
||||
}
|
||||
|
||||
if (dto.subspaceModels) {
|
||||
await this.subSpaceModelService.modifySubspaceModels(
|
||||
dto.subspaceModels,
|
||||
spaceModel,
|
||||
queryRunner,
|
||||
param.projectUuid,
|
||||
dto.tags,
|
||||
);
|
||||
modifiedSubspaces =
|
||||
await this.subSpaceModelService.modifySubspaceModels(
|
||||
dto.subspaceModels,
|
||||
spaceModel,
|
||||
queryRunner,
|
||||
param.projectUuid,
|
||||
dto.tags,
|
||||
);
|
||||
}
|
||||
|
||||
if (dto.tags) {
|
||||
await this.spaceModelProductAllocationService.updateProductAllocations(
|
||||
dto.tags,
|
||||
param.projectUuid,
|
||||
project,
|
||||
spaceModel,
|
||||
queryRunner,
|
||||
dto.subspaceModels,
|
||||
@@ -236,6 +241,14 @@ export class SpaceModelService {
|
||||
}
|
||||
await queryRunner.commitTransaction();
|
||||
|
||||
await this.commandBus.execute(
|
||||
new PropogateUpdateSpaceModelCommand({
|
||||
spaceModel: spaceModel,
|
||||
subspaceModels: modifiedSubspaces,
|
||||
spaces: spaces,
|
||||
}),
|
||||
);
|
||||
|
||||
return new SuccessResponseDto({
|
||||
message: 'SpaceModel updated successfully',
|
||||
});
|
||||
|
||||
@@ -11,6 +11,7 @@ import { NewTagEntity } from '@app/common/modules/tag';
|
||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import { ModifyTagModelDto } from 'src/space-model/dtos';
|
||||
import { ISingleSubspaceModel } from 'src/space-model/interfaces';
|
||||
import { IUpdatedAllocations } from 'src/space-model/interfaces/subspace-product-allocation-update-result.interface';
|
||||
import { ProcessTagDto } from 'src/tags/dtos';
|
||||
import { TagService as NewTagService } from 'src/tags/services';
|
||||
import { In, QueryRunner } from 'typeorm';
|
||||
@@ -29,8 +30,10 @@ export class SubspaceModelProductAllocationService {
|
||||
tags: NewTagEntity[],
|
||||
queryRunner?: QueryRunner,
|
||||
spaceAllocationsToExclude?: SpaceModelProductAllocationEntity[],
|
||||
): Promise<SubspaceModelProductAllocationEntity[]> {
|
||||
): Promise<IUpdatedAllocations[]> {
|
||||
try {
|
||||
const updatedAllocations: IUpdatedAllocations[] = [];
|
||||
|
||||
const allocations: SubspaceModelProductAllocationEntity[] = [];
|
||||
|
||||
for (const tag of tags) {
|
||||
@@ -140,7 +143,6 @@ export class SubspaceModelProductAllocationService {
|
||||
product: tag.product,
|
||||
tags: [tag],
|
||||
});
|
||||
|
||||
allocations.push(allocation);
|
||||
} else {
|
||||
//If allocation exists, add the tag to it
|
||||
@@ -155,6 +157,10 @@ export class SubspaceModelProductAllocationService {
|
||||
existingAllocationsForProduct[0],
|
||||
);
|
||||
}
|
||||
updatedAllocations.push({
|
||||
allocation: existingAllocationsForProduct[0],
|
||||
tagsAdded: [tag],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,9 +174,13 @@ export class SubspaceModelProductAllocationService {
|
||||
} else {
|
||||
await this.subspaceModelProductAllocationRepository.save(allocations);
|
||||
}
|
||||
|
||||
allocations.forEach((allocation) => {
|
||||
updatedAllocations.push({ newAllocation: allocation });
|
||||
});
|
||||
}
|
||||
|
||||
return allocations;
|
||||
return updatedAllocations;
|
||||
} catch (error) {
|
||||
throw new HttpException(
|
||||
`An unexpected error occurred while creating subspace product allocations ${error}`,
|
||||
@@ -267,6 +277,7 @@ export class SubspaceModelProductAllocationService {
|
||||
spaceTagUpdateDtos?: ModifyTagModelDto[],
|
||||
) {
|
||||
const spaceAllocationToExclude: SpaceModelProductAllocationEntity[] = [];
|
||||
const updatedAllocations: IUpdatedAllocations[] = [];
|
||||
|
||||
for (const subspaceModel of subspaceModels) {
|
||||
const tagDtos = subspaceModel.tags;
|
||||
@@ -332,6 +343,11 @@ export class SubspaceModelProductAllocationService {
|
||||
(tag) => tag.uuid !== deletedTag.tagUuid,
|
||||
);
|
||||
|
||||
updatedAllocations.push({
|
||||
allocation,
|
||||
tagsRemoved: [tagEntity],
|
||||
});
|
||||
|
||||
await queryRunner.manager.save(allocation);
|
||||
|
||||
const productAllocationExistInSubspace =
|
||||
@@ -350,6 +366,12 @@ export class SubspaceModelProductAllocationService {
|
||||
|
||||
if (productAllocationExistInSubspace) {
|
||||
productAllocationExistInSubspace.tags.push(tagEntity);
|
||||
|
||||
updatedAllocations.push({
|
||||
allocation: productAllocationExistInSubspace,
|
||||
tagsAdded: [tagEntity],
|
||||
});
|
||||
|
||||
await queryRunner.manager.save(
|
||||
productAllocationExistInSubspace,
|
||||
);
|
||||
@@ -363,6 +385,10 @@ export class SubspaceModelProductAllocationService {
|
||||
},
|
||||
);
|
||||
|
||||
updatedAllocations.push({
|
||||
allocation: newProductAllocation,
|
||||
});
|
||||
|
||||
await queryRunner.manager.save(newProductAllocation);
|
||||
}
|
||||
|
||||
@@ -406,6 +432,11 @@ export class SubspaceModelProductAllocationService {
|
||||
),
|
||||
);
|
||||
|
||||
updatedAllocations.push({
|
||||
allocation: allocation,
|
||||
tagsRemoved: repeatedTags,
|
||||
});
|
||||
|
||||
await queryRunner.manager.save(allocation);
|
||||
|
||||
const productAllocationExistInSubspace =
|
||||
@@ -421,6 +452,11 @@ export class SubspaceModelProductAllocationService {
|
||||
);
|
||||
|
||||
if (productAllocationExistInSubspace) {
|
||||
updatedAllocations.push({
|
||||
allocation: productAllocationExistInSubspace,
|
||||
tagsAdded: repeatedTags,
|
||||
});
|
||||
|
||||
productAllocationExistInSubspace.tags.push(...repeatedTags);
|
||||
await queryRunner.manager.save(
|
||||
productAllocationExistInSubspace,
|
||||
@@ -435,19 +471,12 @@ export class SubspaceModelProductAllocationService {
|
||||
},
|
||||
);
|
||||
|
||||
updatedAllocations.push({
|
||||
newAllocation: newProductAllocation,
|
||||
});
|
||||
|
||||
await queryRunner.manager.save(newProductAllocation);
|
||||
}
|
||||
|
||||
const newAllocation = queryRunner.manager.create(
|
||||
SubspaceModelProductAllocationEntity,
|
||||
{
|
||||
subspaceModel: subspaceModel.subspaceModel,
|
||||
product: allocation.product,
|
||||
tags: repeatedTags,
|
||||
},
|
||||
);
|
||||
|
||||
await queryRunner.manager.save(newAllocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -479,13 +508,14 @@ export class SubspaceModelProductAllocationService {
|
||||
}
|
||||
|
||||
// Create new product allocations
|
||||
await this.createProductAllocations(
|
||||
const newAllocations = await this.createProductAllocations(
|
||||
subspaceModel.subspaceModel,
|
||||
spaceModel,
|
||||
processedTags,
|
||||
queryRunner,
|
||||
spaceAllocationToExclude,
|
||||
);
|
||||
return [...updatedAllocations, ...newAllocations];
|
||||
}
|
||||
if (tagsToDeleteDto.length > 0) {
|
||||
await this.processDeleteActions(tagsToDeleteDto, queryRunner);
|
||||
|
||||
@@ -14,6 +14,8 @@ import { ProcessTagDto } from 'src/tags/dtos';
|
||||
import { TagService } from 'src/tags/services';
|
||||
import { SubspaceModelProductAllocationService } from './subspace-model-product-allocation.service';
|
||||
import { ISingleSubspaceModel } from 'src/space-model/interfaces';
|
||||
import { SpaceEntity } from '@app/common/modules/space/entities/space.entity';
|
||||
import { SubSpaceService } from 'src/space/services/subspace';
|
||||
|
||||
@Injectable()
|
||||
export class SubSpaceModelService {
|
||||
@@ -21,6 +23,7 @@ export class SubSpaceModelService {
|
||||
private readonly subspaceModelRepository: SubspaceModelRepository,
|
||||
private readonly tagService: TagService,
|
||||
private readonly productAllocationService: SubspaceModelProductAllocationService,
|
||||
private readonly subspaceService: SubSpaceService,
|
||||
) {}
|
||||
|
||||
async createModels(
|
||||
@@ -74,6 +77,7 @@ export class SubSpaceModelService {
|
||||
dtos: ModifySubspaceModelDto[],
|
||||
spaceModel: SpaceModelEntity,
|
||||
queryRunner: QueryRunner,
|
||||
spaces?: SpaceEntity[],
|
||||
): Promise<ISingleSubspaceModel[]> {
|
||||
if (!dtos.length) return [];
|
||||
|
||||
@@ -89,6 +93,14 @@ export class SubSpaceModelService {
|
||||
|
||||
const savedSubspaces = await queryRunner.manager.save(subspaceEntities);
|
||||
|
||||
if (spaces) {
|
||||
await this.subspaceService.createSubSpaceFromModel(
|
||||
savedSubspaces,
|
||||
spaces,
|
||||
queryRunner,
|
||||
);
|
||||
}
|
||||
|
||||
return savedSubspaces.map((subspace, index) => ({
|
||||
subspaceModel: subspace,
|
||||
action: ModifyAction.ADD,
|
||||
@@ -102,7 +114,8 @@ export class SubSpaceModelService {
|
||||
queryRunner: QueryRunner,
|
||||
projectUuid: string,
|
||||
spaceTagUpdateDtos?: ModifyTagModelDto[],
|
||||
) {
|
||||
spaces?: SpaceEntity[],
|
||||
): Promise<ISingleSubspaceModel[]> {
|
||||
try {
|
||||
if (!dtos || dtos.length === 0) {
|
||||
return;
|
||||
@@ -116,17 +129,18 @@ export class SubSpaceModelService {
|
||||
(dto) => dto.action === ModifyAction.DELETE,
|
||||
);
|
||||
|
||||
const updatedModels = await this.updateSubspaceModel(
|
||||
const updatedSubspaces = await this.updateSubspaceModel(
|
||||
combinedDtos,
|
||||
spaceModel,
|
||||
queryRunner,
|
||||
);
|
||||
const addedModels = await this.handleAddAction(
|
||||
const createdSubspaces = await this.handleAddAction(
|
||||
addDtos,
|
||||
spaceModel,
|
||||
queryRunner,
|
||||
spaces,
|
||||
);
|
||||
const combineModels = [...addedModels, ...updatedModels];
|
||||
const combineModels = [...createdSubspaces, ...updatedSubspaces];
|
||||
|
||||
await this.productAllocationService.updateAllocations(
|
||||
combineModels,
|
||||
@@ -136,7 +150,18 @@ export class SubSpaceModelService {
|
||||
spaceTagUpdateDtos,
|
||||
);
|
||||
|
||||
await this.deleteSubspaceModels(deleteDtos, queryRunner, spaceModel);
|
||||
const deletedSubspaces = await this.deleteSubspaceModels(
|
||||
deleteDtos,
|
||||
queryRunner,
|
||||
spaceModel,
|
||||
);
|
||||
return [
|
||||
createdSubspaces ?? [],
|
||||
updatedSubspaces ?? [],
|
||||
deletedSubspaces ?? [],
|
||||
]
|
||||
.filter((arr) => arr.length > 0)
|
||||
.flat();
|
||||
} catch (error) {
|
||||
console.error('Error in modifySubspaceModels:', error);
|
||||
throw new HttpException(
|
||||
@@ -154,7 +179,7 @@ export class SubSpaceModelService {
|
||||
deleteDtos: ModifySubspaceModelDto[],
|
||||
queryRunner: QueryRunner,
|
||||
spaceModel: SpaceModelEntity,
|
||||
) {
|
||||
): Promise<ISingleSubspaceModel[]> {
|
||||
try {
|
||||
if (!deleteDtos || deleteDtos.length === 0) {
|
||||
return;
|
||||
@@ -261,7 +286,11 @@ export class SubSpaceModelService {
|
||||
|
||||
deleteResults.push(...subspaceUuids.map((uuid) => ({ uuid })));
|
||||
|
||||
return deleteResults;
|
||||
return subspaces.map((subspace) => ({
|
||||
subspaceModel: subspace,
|
||||
action: ModifyAction.DELETE,
|
||||
tags: [],
|
||||
}));
|
||||
} catch (error) {
|
||||
if (error instanceof QueryFailedError) {
|
||||
throw new HttpException(
|
||||
|
||||
@@ -46,6 +46,16 @@ import { SpaceModelProductAllocationService } from './services/space-model-produ
|
||||
import { SubspaceModelProductAllocationService } from './services/subspace/subspace-model-product-allocation.service';
|
||||
import { SpaceProductAllocationService } from 'src/space/services/space-product-allocation.service';
|
||||
import { SubspaceProductAllocationService } from 'src/space/services/subspace/subspace-product-allocation.service';
|
||||
import { DeviceService } from 'src/device/services';
|
||||
import { SceneDeviceRepository } from '@app/common/modules/scene-device/repositories';
|
||||
import { DeviceStatusFirebaseService } from '@app/common/firebase/devices-status/services/devices-status.service';
|
||||
import { SceneService } from 'src/scene/services';
|
||||
import { DeviceStatusLogRepository } from '@app/common/modules/device-status-log/repositories';
|
||||
import {
|
||||
SceneIconRepository,
|
||||
SceneRepository,
|
||||
} from '@app/common/modules/scene/repositories';
|
||||
import { AutomationRepository } from '@app/common/modules/automation/repositories';
|
||||
|
||||
const CommandHandlers = [
|
||||
PropogateUpdateSpaceModelHandler,
|
||||
@@ -80,6 +90,14 @@ const CommandHandlers = [
|
||||
SpaceLinkRepository,
|
||||
InviteSpaceRepository,
|
||||
NewTagService,
|
||||
DeviceService,
|
||||
DeviceStatusFirebaseService,
|
||||
DeviceStatusLogRepository,
|
||||
SceneService,
|
||||
SceneIconRepository,
|
||||
SceneDeviceRepository,
|
||||
SceneRepository,
|
||||
AutomationRepository,
|
||||
SpaceModelProductAllocationRepoitory,
|
||||
SubspaceModelProductAllocationRepoitory,
|
||||
NewTagRepository,
|
||||
@@ -90,6 +108,7 @@ const CommandHandlers = [
|
||||
SubspaceProductAllocationService,
|
||||
SpaceProductAllocationRepository,
|
||||
SubspaceProductAllocationRepository,
|
||||
SubSpaceService,
|
||||
],
|
||||
exports: [CqrsModule, SpaceModelService],
|
||||
})
|
||||
|
||||
@@ -13,12 +13,16 @@ import { ModifySubspaceDto } from '../dtos';
|
||||
import { ProcessTagDto } from 'src/tags/dtos';
|
||||
import { TagService as NewTagService } from 'src/tags/services';
|
||||
import { SpaceModelProductAllocationEntity } from '@app/common/modules/space-model';
|
||||
import { DeviceEntity } from '@app/common/modules/device/entities';
|
||||
import { ProjectEntity } from '@app/common/modules/project/entities';
|
||||
import { ValidationService } from './space-validation.service';
|
||||
|
||||
@Injectable()
|
||||
export class SpaceProductAllocationService {
|
||||
constructor(
|
||||
private readonly tagService: NewTagService,
|
||||
private readonly spaceProductAllocationRepository: SpaceProductAllocationRepository,
|
||||
private readonly spaceService: ValidationService,
|
||||
) {}
|
||||
|
||||
async createSpaceProductAllocations(
|
||||
@@ -220,6 +224,114 @@ export class SpaceProductAllocationService {
|
||||
}
|
||||
}
|
||||
|
||||
async propagateDeleteToInheritedAllocations(
|
||||
queryRunner: QueryRunner,
|
||||
allocationsToUpdate: SpaceModelProductAllocationEntity[],
|
||||
tagUuidsToDelete: string[],
|
||||
project: ProjectEntity,
|
||||
spaces?: SpaceEntity[],
|
||||
): Promise<void> {
|
||||
try {
|
||||
const inheritedAllocationUpdates: SpaceProductAllocationEntity[] = [];
|
||||
const inheritedAllocationsToDelete: SpaceProductAllocationEntity[] = [];
|
||||
|
||||
for (const allocation of allocationsToUpdate) {
|
||||
for (const inheritedAllocation of allocation.inheritedSpaceAllocations) {
|
||||
const updatedInheritedTags = inheritedAllocation.tags.filter(
|
||||
(tag) => !tagUuidsToDelete.includes(tag.uuid),
|
||||
);
|
||||
|
||||
if (updatedInheritedTags.length === inheritedAllocation.tags.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (updatedInheritedTags.length === 0) {
|
||||
inheritedAllocationsToDelete.push(inheritedAllocation);
|
||||
} else {
|
||||
inheritedAllocation.tags = updatedInheritedTags;
|
||||
inheritedAllocationUpdates.push(inheritedAllocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inheritedAllocationUpdates.length > 0) {
|
||||
await queryRunner.manager.save(
|
||||
SpaceProductAllocationEntity,
|
||||
inheritedAllocationUpdates,
|
||||
);
|
||||
}
|
||||
|
||||
if (inheritedAllocationsToDelete.length > 0) {
|
||||
await queryRunner.manager.remove(
|
||||
SpaceProductAllocationEntity,
|
||||
inheritedAllocationsToDelete,
|
||||
);
|
||||
}
|
||||
|
||||
if (spaces && spaces.length > 0) {
|
||||
await this.moveDevicesToOrphanSpace(
|
||||
queryRunner,
|
||||
spaces,
|
||||
tagUuidsToDelete,
|
||||
project,
|
||||
);
|
||||
}
|
||||
|
||||
await queryRunner.manager
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from('space_product_tags')
|
||||
.where(
|
||||
'space_product_allocation_uuid NOT IN (' +
|
||||
queryRunner.manager
|
||||
.createQueryBuilder()
|
||||
.select('allocation.uuid')
|
||||
.from(SpaceProductAllocationEntity, 'allocation')
|
||||
.getQuery() +
|
||||
')',
|
||||
)
|
||||
.execute();
|
||||
} catch (error) {
|
||||
throw this.handleError(
|
||||
error,
|
||||
`Failed to propagate tag deletion to inherited allocations`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async moveDevicesToOrphanSpace(
|
||||
queryRunner: QueryRunner,
|
||||
spaces: SpaceEntity[],
|
||||
tagUuidsToDelete: string[],
|
||||
project: ProjectEntity,
|
||||
): Promise<void> {
|
||||
try {
|
||||
const orphanSpace = await this.spaceService.getOrphanSpace(project);
|
||||
|
||||
const devicesToMove = await queryRunner.manager
|
||||
.createQueryBuilder(DeviceEntity, 'device')
|
||||
.leftJoinAndSelect('device.tag', 'tag')
|
||||
.where('device.spaceDevice IN (:...spaceUuids)', {
|
||||
spaceUuids: spaces.map((space) => space.uuid),
|
||||
})
|
||||
.andWhere('tag.uuid IN (:...tagUuidsToDelete)', { tagUuidsToDelete })
|
||||
.getMany();
|
||||
|
||||
if (devicesToMove.length === 0) return;
|
||||
|
||||
await queryRunner.manager
|
||||
.createQueryBuilder()
|
||||
.update(DeviceEntity)
|
||||
.set({ spaceDevice: orphanSpace })
|
||||
.where('uuid IN (:...deviceUuids)', {
|
||||
deviceUuids: devicesToMove.map((device) => device.uuid),
|
||||
})
|
||||
.execute();
|
||||
} catch (error) {
|
||||
throw this.handleError(error, `Failed to move devices to orphan space`);
|
||||
}
|
||||
}
|
||||
|
||||
private async processDeleteActions(
|
||||
dtos: ModifyTagDto[],
|
||||
queryRunner: QueryRunner,
|
||||
|
||||
@@ -19,6 +19,11 @@ import { ValidateSpacesDto } from '../dtos/validation.space.dto';
|
||||
import { ProjectParam } from '../dtos';
|
||||
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
||||
import { In } from 'typeorm';
|
||||
import {
|
||||
ORPHAN_COMMUNITY_NAME,
|
||||
ORPHAN_SPACE_NAME,
|
||||
} from '@app/common/constants/orphan-constant';
|
||||
import { ProjectEntity } from '@app/common/modules/project/entities';
|
||||
|
||||
@Injectable()
|
||||
export class ValidationService {
|
||||
@@ -286,4 +291,24 @@ export class ValidationService {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async getOrphanSpace(project: ProjectEntity): Promise<SpaceEntity> {
|
||||
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,
|
||||
);
|
||||
}
|
||||
|
||||
return orphanSpace;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ import { ProcessTagDto } from 'src/tags/dtos';
|
||||
import { SpaceProductAllocationService } from './space-product-allocation.service';
|
||||
import { SubspaceProductAllocationService } from './subspace/subspace-product-allocation.service';
|
||||
import { SubspaceEntity } from '@app/common/modules/space/entities/subspace/subspace.entity';
|
||||
import { DeviceRepository } from '@app/common/modules/device/repositories';
|
||||
import { DeviceService } from 'src/device/services';
|
||||
@Injectable()
|
||||
export class SpaceService {
|
||||
constructor(
|
||||
@@ -53,6 +55,8 @@ export class SpaceService {
|
||||
private commandBus: CommandBus,
|
||||
private readonly spaceProductAllocationService: SpaceProductAllocationService,
|
||||
private readonly subspaceProductAllocationService: SubspaceProductAllocationService,
|
||||
private readonly deviceRepository: DeviceRepository,
|
||||
private readonly deviceSevice: DeviceService,
|
||||
) {}
|
||||
|
||||
async createSpace(
|
||||
@@ -186,40 +190,6 @@ export class SpaceService {
|
||||
}
|
||||
}
|
||||
}
|
||||
async createFromModel(
|
||||
spaceModelUuid: string,
|
||||
queryRunner: QueryRunner,
|
||||
space: SpaceEntity,
|
||||
) {
|
||||
try {
|
||||
const spaceModel =
|
||||
await this.spaceModelService.validateSpaceModel(spaceModelUuid);
|
||||
|
||||
space.spaceModel = spaceModel;
|
||||
await queryRunner.manager.save(SpaceEntity, space);
|
||||
|
||||
await this.subSpaceService.createSubSpaceFromModel(
|
||||
spaceModel.subspaceModels,
|
||||
space,
|
||||
queryRunner,
|
||||
);
|
||||
|
||||
await this.tagService.createTagsFromModel(
|
||||
queryRunner,
|
||||
spaceModel.tags,
|
||||
space,
|
||||
null,
|
||||
);
|
||||
} catch (error) {
|
||||
if (error instanceof HttpException) {
|
||||
throw error;
|
||||
}
|
||||
throw new HttpException(
|
||||
'An error occurred while creating the space from space model',
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async getSpacesHierarchyForCommunity(
|
||||
params: CommunitySpaceParam,
|
||||
|
||||
@@ -81,24 +81,6 @@ export class SubspaceDeviceService {
|
||||
const subspace = await this.findSubspace(subSpaceUuid);
|
||||
const device = await this.findDevice(deviceUuid);
|
||||
|
||||
if (device.tag?.subspace?.uuid !== subspace.uuid) {
|
||||
await this.tagRepository.update(
|
||||
{ uuid: device.tag.uuid },
|
||||
{ subspace, space: null },
|
||||
);
|
||||
}
|
||||
|
||||
if (!device.tag) {
|
||||
const tag = this.tagRepository.create({
|
||||
tag: `Tag ${this.findNextTag()}`,
|
||||
product: device.productDevice,
|
||||
subspace: subspace,
|
||||
device: device,
|
||||
});
|
||||
await this.tagRepository.save(tag);
|
||||
device.tag = tag;
|
||||
}
|
||||
|
||||
device.subspace = subspace;
|
||||
|
||||
const newDevice = await this.deviceRepository.save(device);
|
||||
@@ -140,26 +122,6 @@ export class SubspaceDeviceService {
|
||||
);
|
||||
}
|
||||
|
||||
if (device.tag?.subspace !== null) {
|
||||
await this.tagRepository.update(
|
||||
{ uuid: device.tag.uuid },
|
||||
{ subspace: null, space: device.spaceDevice },
|
||||
);
|
||||
}
|
||||
|
||||
if (!device.tag) {
|
||||
const tag = this.tagRepository.create({
|
||||
tag: `Tag ${this.findNextTag()}`,
|
||||
product: device.productDevice,
|
||||
subspace: null,
|
||||
space: device.spaceDevice,
|
||||
device: device,
|
||||
});
|
||||
|
||||
await this.tagRepository.save(tag);
|
||||
device.tag = tag;
|
||||
}
|
||||
|
||||
device.subspace = null;
|
||||
const updatedDevice = await this.deviceRepository.save(device);
|
||||
|
||||
|
||||
@@ -70,29 +70,23 @@ export class SubSpaceService {
|
||||
|
||||
async createSubSpaceFromModel(
|
||||
subspaceModels: SubspaceModelEntity[],
|
||||
space: SpaceEntity,
|
||||
spaces: SpaceEntity[],
|
||||
queryRunner: QueryRunner,
|
||||
): Promise<void> {
|
||||
if (!subspaceModels?.length) return;
|
||||
if (!subspaceModels?.length || !spaces?.length) return;
|
||||
|
||||
const subspaceData = subspaceModels.map((subSpaceModel) => ({
|
||||
subspaceName: subSpaceModel.subspaceName,
|
||||
space,
|
||||
subSpaceModel,
|
||||
}));
|
||||
const subspaceData = [];
|
||||
|
||||
const subspaces = await this.createSubspaces(subspaceData, queryRunner);
|
||||
|
||||
await Promise.all(
|
||||
subspaceModels.map((model, index) =>
|
||||
this.tagService.createTagsFromModel(
|
||||
queryRunner,
|
||||
model.tags || [],
|
||||
null,
|
||||
subspaces[index],
|
||||
),
|
||||
),
|
||||
);
|
||||
for (const space of spaces) {
|
||||
for (const subSpaceModel of subspaceModels) {
|
||||
subspaceData.push({
|
||||
subspaceName: subSpaceModel.subspaceName,
|
||||
space,
|
||||
subSpaceModel,
|
||||
});
|
||||
}
|
||||
}
|
||||
await this.createSubspaces(subspaceData, queryRunner);
|
||||
}
|
||||
|
||||
async createSubspacesFromDto(
|
||||
|
||||
@@ -118,6 +118,7 @@ export const CommandHandlers = [DisableSpaceHandler];
|
||||
UserRepository,
|
||||
SpaceUserService,
|
||||
SpaceSceneService,
|
||||
DeviceService,
|
||||
SceneService,
|
||||
SceneIconRepository,
|
||||
SceneRepository,
|
||||
|
||||
Reference in New Issue
Block a user