mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-11-26 21:14:54 +00:00
disable space
This commit is contained in:
@ -1 +1,2 @@
|
||||
export * from './propogate-subspace-update-command';
|
||||
export * from './propagate-space-model-deletion.command';
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
import { SpaceModelEntity } from '@app/common/modules/space-model';
|
||||
|
||||
export class PropogateDeleteSpaceModelCommand {
|
||||
constructor(
|
||||
public readonly param: {
|
||||
spaceModel: SpaceModelEntity;
|
||||
},
|
||||
) {}
|
||||
}
|
||||
@ -1,6 +1,12 @@
|
||||
import { ICommand } from '@nestjs/cqrs';
|
||||
import { IModifySubspaceModelInterface } from '../interfaces';
|
||||
import { SpaceModelEntity } from '@app/common/modules/space-model';
|
||||
import { ModifyspaceModelPayload } from '../interfaces';
|
||||
|
||||
export class PropogateSubspaceCommand implements ICommand {
|
||||
constructor(public readonly param: IModifySubspaceModelInterface) {}
|
||||
export class PropogateUpdateSpaceModelCommand implements ICommand {
|
||||
constructor(
|
||||
public readonly param: {
|
||||
spaceModel: SpaceModelEntity;
|
||||
modifiedSpaceModels: ModifyspaceModelPayload;
|
||||
},
|
||||
) {}
|
||||
}
|
||||
|
||||
@ -1 +1,2 @@
|
||||
export * from './propate-subspace-handler';
|
||||
export * from './propogate-space-model-deletion.handler';
|
||||
|
||||
@ -1,170 +1,250 @@
|
||||
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
|
||||
import { PropogateSubspaceCommand } from '../commands';
|
||||
import { Logger } from '@nestjs/common';
|
||||
import { PropogateUpdateSpaceModelCommand } from '../commands';
|
||||
import { SpaceEntity, SpaceRepository } from '@app/common/modules/space';
|
||||
import { SubspaceRepository } from '@app/common/modules/space/repositories/subspace.repository';
|
||||
import {
|
||||
IDeletedSubsaceModelInterface,
|
||||
IUpdateSubspaceModelInterface,
|
||||
} from '../interfaces';
|
||||
SpaceModelEntity,
|
||||
SubspaceModelEntity,
|
||||
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 { TagModelService } from '../services';
|
||||
import { UpdatedSubspaceModelPayload } from '../interfaces';
|
||||
import { ModifyAction } from '@app/common/constants/modify-action.enum';
|
||||
import { ModifySubspaceDto } from 'src/space/dtos';
|
||||
|
||||
@CommandHandler(PropogateSubspaceCommand)
|
||||
export class PropogateSubspaceHandler
|
||||
implements ICommandHandler<PropogateSubspaceCommand>
|
||||
@CommandHandler(PropogateUpdateSpaceModelCommand)
|
||||
export class PropogateUpdateSpaceModelHandler
|
||||
implements ICommandHandler<PropogateUpdateSpaceModelCommand>
|
||||
{
|
||||
private readonly logger = new Logger(PropogateSubspaceHandler.name);
|
||||
|
||||
constructor(
|
||||
private readonly spaceRepository: SpaceRepository,
|
||||
private readonly subspaceRepository: SubspaceRepository,
|
||||
private readonly dataSource: DataSource,
|
||||
private readonly subSpaceService: SubSpaceService,
|
||||
private readonly tagService: TagService,
|
||||
private readonly tagModelService: TagModelService,
|
||||
) {}
|
||||
|
||||
async execute(command: PropogateSubspaceCommand): Promise<void> {
|
||||
async execute(command: PropogateUpdateSpaceModelCommand): Promise<void> {
|
||||
const { spaceModel, modifiedSpaceModels } = command.param;
|
||||
const queryRunner = this.dataSource.createQueryRunner();
|
||||
|
||||
try {
|
||||
const newSubspaceModels = command.param?.new;
|
||||
const updateSubspaceModels = command.param?.update;
|
||||
const deleteSubspaceModels = command.param?.delete;
|
||||
|
||||
if (!newSubspaceModels && !updateSubspaceModels) {
|
||||
this.logger.warn('No new or updated subspace models provided.');
|
||||
return;
|
||||
}
|
||||
|
||||
const spaceModelUuid = command.param.spaceModelUuid;
|
||||
|
||||
if (!spaceModelUuid) {
|
||||
this.logger.error(
|
||||
'Space model UUID is missing in the command parameters.',
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
const spaces = await this.spaceRepository.find({
|
||||
where: { spaceModel },
|
||||
});
|
||||
if (
|
||||
modifiedSpaceModels.modifiedSubspaceModels.addedSubspaceModels.length >
|
||||
0
|
||||
) {
|
||||
await this.addSubspaceModels(
|
||||
modifiedSpaceModels.modifiedSubspaceModels.addedSubspaceModels,
|
||||
spaces,
|
||||
queryRunner,
|
||||
);
|
||||
return;
|
||||
} else if (
|
||||
modifiedSpaceModels.modifiedSubspaceModels.updatedSubspaceModels
|
||||
.length > 0
|
||||
) {
|
||||
await this.updateSubspaceModels(
|
||||
modifiedSpaceModels.modifiedSubspaceModels.updatedSubspaceModels,
|
||||
queryRunner,
|
||||
);
|
||||
}
|
||||
if (
|
||||
modifiedSpaceModels.modifiedSubspaceModels.deletedSubspaceModels?.length
|
||||
) {
|
||||
const dtos: ModifySubspaceDto[] =
|
||||
modifiedSpaceModels.modifiedSubspaceModels.deletedSubspaceModels.map(
|
||||
(model) => ({
|
||||
action: ModifyAction.DELETE,
|
||||
uuid: model,
|
||||
}),
|
||||
);
|
||||
await this.subSpaceService.modifySubSpace(dtos, queryRunner);
|
||||
}
|
||||
|
||||
const spaces = await this.getSpacesByModel(spaceModelUuid);
|
||||
|
||||
if (spaces.length === 0) {
|
||||
this.logger.warn(`No spaces found for model UUID: ${spaceModelUuid}`);
|
||||
return;
|
||||
if (modifiedSpaceModels.modifiedTags.added.length > 0) {
|
||||
await this.createTags(
|
||||
modifiedSpaceModels.modifiedTags.added,
|
||||
queryRunner,
|
||||
null,
|
||||
spaceModel,
|
||||
);
|
||||
}
|
||||
|
||||
if (newSubspaceModels && newSubspaceModels.length > 0) {
|
||||
await this.processNewSubspaces(newSubspaceModels, spaces);
|
||||
if (modifiedSpaceModels.modifiedTags.updated.length > 0) {
|
||||
await this.updateTags(
|
||||
modifiedSpaceModels.modifiedTags.updated,
|
||||
queryRunner,
|
||||
);
|
||||
}
|
||||
|
||||
if (updateSubspaceModels && updateSubspaceModels.length > 0) {
|
||||
await this.updateSubspaces(updateSubspaceModels);
|
||||
if (modifiedSpaceModels.modifiedTags.deleted.length > 0) {
|
||||
await this.deleteTags(
|
||||
modifiedSpaceModels.modifiedTags.deleted,
|
||||
queryRunner,
|
||||
);
|
||||
}
|
||||
|
||||
if (deleteSubspaceModels && deleteSubspaceModels.length > 0) {
|
||||
await this.deleteSubspaces(deleteSubspaceModels);
|
||||
}
|
||||
await queryRunner.commitTransaction();
|
||||
} catch (error) {
|
||||
this.logger.error(
|
||||
'Error in PropogateSubspaceHandler execution',
|
||||
error.stack,
|
||||
await queryRunner.rollbackTransaction();
|
||||
throw error;
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
|
||||
async addSubspaceModels(
|
||||
subspaceModels: SubspaceModelEntity[],
|
||||
spaces: SpaceEntity[],
|
||||
queryRunner: QueryRunner,
|
||||
) {
|
||||
for (const space of spaces) {
|
||||
await this.subSpaceService.createSubSpaceFromModel(
|
||||
subspaceModels,
|
||||
space,
|
||||
queryRunner,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async updateSubspaces(
|
||||
models: IUpdateSubspaceModelInterface[],
|
||||
async updateSubspaceModels(
|
||||
subspaceModels: UpdatedSubspaceModelPayload[],
|
||||
queryRunner: QueryRunner,
|
||||
): Promise<void> {
|
||||
try {
|
||||
const updatePromises = [];
|
||||
const subspaceUpdatePromises = subspaceModels.map(async (model) => {
|
||||
const {
|
||||
updated: tagsToUpdate,
|
||||
deleted: tagsToDelete,
|
||||
added: tagsToAdd,
|
||||
} = model.modifiedTags;
|
||||
|
||||
for (const model of models) {
|
||||
const { uuid: subspaceModelUuid, subspaceName } = model;
|
||||
// Perform tag operations concurrently
|
||||
await Promise.all([
|
||||
tagsToUpdate?.length && this.updateTags(tagsToUpdate, queryRunner),
|
||||
tagsToDelete?.length && this.deleteTags(tagsToDelete, queryRunner),
|
||||
tagsToAdd?.length &&
|
||||
this.createTags(
|
||||
tagsToAdd,
|
||||
queryRunner,
|
||||
model.subspaceModelUuid,
|
||||
null,
|
||||
),
|
||||
]);
|
||||
|
||||
if (subspaceName) {
|
||||
updatePromises.push(
|
||||
this.subspaceRepository
|
||||
.createQueryBuilder()
|
||||
.update()
|
||||
.set({ subspaceName })
|
||||
.where('subSpaceModelUuid = :uuid', { uuid: subspaceModelUuid })
|
||||
.execute(),
|
||||
);
|
||||
}
|
||||
// Update subspace names
|
||||
const subspaces = await queryRunner.manager.find(
|
||||
this.subspaceRepository.target,
|
||||
{
|
||||
where: {
|
||||
subSpaceModel: {
|
||||
uuid: model.subspaceModelUuid,
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (subspaces.length > 0) {
|
||||
const updateSubspacePromises = subspaces.map((subspace) =>
|
||||
queryRunner.manager.update(
|
||||
this.subspaceRepository.target,
|
||||
{ uuid: subspace.uuid },
|
||||
{ subspaceName: model.subspaceName },
|
||||
),
|
||||
);
|
||||
await Promise.all(updateSubspacePromises);
|
||||
}
|
||||
|
||||
await Promise.all(updatePromises);
|
||||
} catch (error) {
|
||||
this.logger.error('Error in updateSubspaces method', error.stack);
|
||||
}
|
||||
}
|
||||
|
||||
private async deleteSubspaces(models: IDeletedSubsaceModelInterface[]) {
|
||||
try {
|
||||
const updatePromises = [];
|
||||
|
||||
for (const model of models) {
|
||||
const { uuid: subspaceModelUuid } = model;
|
||||
|
||||
if (subspaceModelUuid) {
|
||||
updatePromises.push(
|
||||
this.subspaceRepository
|
||||
.createQueryBuilder()
|
||||
.update()
|
||||
.set({ disabled: true })
|
||||
.where('subSpaceModelUuid = :uuid', { uuid: subspaceModelUuid })
|
||||
.execute(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(updatePromises);
|
||||
} catch (error) {
|
||||
this.logger.error('Error in delete subspace models', error.stack);
|
||||
}
|
||||
}
|
||||
|
||||
private async processNewSubspaces(
|
||||
newSubspaceModels: any[],
|
||||
spaces: SpaceEntity[],
|
||||
) {
|
||||
for (const newSubspaceModel of newSubspaceModels) {
|
||||
for (const space of spaces) {
|
||||
try {
|
||||
await this.createSubspace(newSubspaceModel, space);
|
||||
|
||||
if (newSubspaceModel.productModels?.length > 0) {
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error(
|
||||
`Failed to create subspace for space ID: ${space.uuid}`,
|
||||
error.stack,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async createSubspace(newSubspaceModel: any, space: SpaceEntity) {
|
||||
const subspace = this.subspaceRepository.create({
|
||||
subspaceName: newSubspaceModel.subspaceModel.subspaceName,
|
||||
space,
|
||||
subSpaceModel: newSubspaceModel.subspaceModel,
|
||||
});
|
||||
|
||||
const createdSubspace = await this.subspaceRepository.save(subspace);
|
||||
this.logger.log(
|
||||
`Subspace created for space ${space.uuid} with name ${createdSubspace.subspaceName}`,
|
||||
// Wait for all subspace model updates to complete
|
||||
await Promise.all(subspaceUpdatePromises);
|
||||
}
|
||||
async updateTags(models: TagModel[], queryRunner: QueryRunner) {
|
||||
if (!models?.length) return;
|
||||
|
||||
const updatePromises = models.map((model) =>
|
||||
this.tagService.updateTagsFromModel(model, queryRunner),
|
||||
);
|
||||
return createdSubspace;
|
||||
await Promise.all(updatePromises);
|
||||
}
|
||||
|
||||
private async getSpacesByModel(uuid: string): Promise<SpaceEntity[]> {
|
||||
try {
|
||||
return await this.spaceRepository.find({
|
||||
where: {
|
||||
spaceModel: { uuid },
|
||||
async deleteTags(uuids: string[], queryRunner: QueryRunner) {
|
||||
const deletePromises = uuids.map((uuid) =>
|
||||
this.tagService.deleteTagFromModel(uuid, queryRunner),
|
||||
);
|
||||
await Promise.all(deletePromises);
|
||||
}
|
||||
|
||||
async createTags(
|
||||
models: TagModel[],
|
||||
queryRunner: QueryRunner,
|
||||
subspaceModelUuid?: string,
|
||||
spaceModel?: SpaceModelEntity,
|
||||
): Promise<void> {
|
||||
if (!models.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (subspaceModelUuid) {
|
||||
await this.processSubspaces(subspaceModelUuid, models, queryRunner);
|
||||
}
|
||||
|
||||
if (spaceModel) {
|
||||
await this.processSpaces(spaceModel.uuid, models, queryRunner);
|
||||
}
|
||||
}
|
||||
|
||||
private async processSubspaces(
|
||||
subspaceModelUuid: string,
|
||||
models: TagModel[],
|
||||
queryRunner: QueryRunner,
|
||||
): Promise<void> {
|
||||
const subspaces = await this.subspaceRepository.find({
|
||||
where: {
|
||||
subSpaceModel: {
|
||||
uuid: subspaceModelUuid,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
this.logger.error(
|
||||
`Failed to fetch spaces for model UUID: ${uuid}`,
|
||||
error.stack,
|
||||
},
|
||||
});
|
||||
|
||||
if (subspaces.length > 0) {
|
||||
const subspacePromises = subspaces.map((subspace) =>
|
||||
this.tagService.createTagsFromModel(
|
||||
queryRunner,
|
||||
models,
|
||||
null,
|
||||
subspace,
|
||||
),
|
||||
);
|
||||
throw error;
|
||||
await Promise.all(subspacePromises);
|
||||
}
|
||||
}
|
||||
|
||||
private async processSpaces(
|
||||
spaceModelUuid: string,
|
||||
models: TagModel[],
|
||||
queryRunner: QueryRunner,
|
||||
): Promise<void> {
|
||||
const spaces = await this.spaceRepository.find({
|
||||
where: {
|
||||
spaceModel: {
|
||||
uuid: spaceModelUuid,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (spaces.length > 0) {
|
||||
const spacePromises = spaces.map((space) =>
|
||||
this.tagService.createTagsFromModel(queryRunner, models, space, null),
|
||||
);
|
||||
await Promise.all(spacePromises);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
|
||||
import { Logger } from '@nestjs/common';
|
||||
|
||||
import { PropogateDeleteSpaceModelCommand } from '../commands';
|
||||
import { SpaceRepository } from '@app/common/modules/space';
|
||||
import { SpaceService } from '../../space/services/space.service';
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
@CommandHandler(PropogateDeleteSpaceModelCommand)
|
||||
export class PropogateDeleteSpaceModelHandler
|
||||
implements ICommandHandler<PropogateDeleteSpaceModelCommand>
|
||||
{
|
||||
private readonly logger = new Logger(PropogateDeleteSpaceModelHandler.name);
|
||||
|
||||
constructor(
|
||||
private readonly spaceRepository: SpaceRepository,
|
||||
private readonly spaceService: SpaceService,
|
||||
private readonly dataSource: DataSource,
|
||||
) {}
|
||||
|
||||
async execute(command: PropogateDeleteSpaceModelCommand): Promise<void> {
|
||||
const { spaceModel } = command.param;
|
||||
const queryRunner = this.dataSource.createQueryRunner();
|
||||
|
||||
try {
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
const spaces = await this.spaceRepository.find({
|
||||
where: {
|
||||
spaceModel: {
|
||||
uuid: spaceModel.uuid,
|
||||
},
|
||||
},
|
||||
relations: ['subspaces', 'tags', 'subspaces.tags'],
|
||||
});
|
||||
|
||||
for (const space of spaces) {
|
||||
try {
|
||||
await this.spaceService.unlinkSpaceFromModel(space, queryRunner);
|
||||
} catch (innerError) {
|
||||
this.logger.error(
|
||||
`Error unlinking space model for space with UUID ${space.uuid}:`,
|
||||
innerError.stack || innerError,
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
await queryRunner.rollbackTransaction();
|
||||
this.logger.error(
|
||||
'Error propagating delete space model:',
|
||||
error.stack || error,
|
||||
);
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1 +1,2 @@
|
||||
export * from './update-subspace.interface'
|
||||
export * from './update-subspace.interface';
|
||||
export * from './modify-subspace.interface';
|
||||
|
||||
24
src/space-model/interfaces/modify-subspace.interface.ts
Normal file
24
src/space-model/interfaces/modify-subspace.interface.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { SubspaceModelEntity, TagModel } from '@app/common/modules/space-model';
|
||||
|
||||
export interface ModifyspaceModelPayload {
|
||||
modifiedSubspaceModels?: ModifySubspaceModelPayload;
|
||||
modifiedTags?: ModifiedTagsModelPayload;
|
||||
}
|
||||
|
||||
export interface ModifySubspaceModelPayload {
|
||||
addedSubspaceModels?: SubspaceModelEntity[];
|
||||
updatedSubspaceModels?: UpdatedSubspaceModelPayload[];
|
||||
deletedSubspaceModels?: string[];
|
||||
}
|
||||
|
||||
export interface UpdatedSubspaceModelPayload {
|
||||
subspaceName?: string;
|
||||
modifiedTags?: ModifiedTagsModelPayload;
|
||||
subspaceModelUuid: string;
|
||||
}
|
||||
|
||||
export interface ModifiedTagsModelPayload {
|
||||
added?: TagModel[];
|
||||
updated?: TagModel[];
|
||||
deleted?: string[];
|
||||
}
|
||||
@ -19,6 +19,12 @@ import { ProjectService } from 'src/project/services';
|
||||
import { ProjectEntity } from '@app/common/modules/project/entities';
|
||||
import { TagModelService } from './tag-model.service';
|
||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||
import { CommandBus } from '@nestjs/cqrs';
|
||||
import { PropogateUpdateSpaceModelCommand } from '../commands';
|
||||
import {
|
||||
ModifiedTagsModelPayload,
|
||||
ModifySubspaceModelPayload,
|
||||
} from '../interfaces';
|
||||
|
||||
@Injectable()
|
||||
export class SpaceModelService {
|
||||
@ -28,6 +34,7 @@ export class SpaceModelService {
|
||||
private readonly projectService: ProjectService,
|
||||
private readonly subSpaceModelService: SubSpaceModelService,
|
||||
private readonly tagModelService: TagModelService,
|
||||
private commandBus: CommandBus,
|
||||
) {}
|
||||
|
||||
async createSpaceModel(
|
||||
@ -136,6 +143,9 @@ export class SpaceModelService {
|
||||
const queryRunner = this.dataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
let modifiedSubspaceModels: ModifySubspaceModelPayload = {};
|
||||
let modifiedTagsModelPayload: ModifiedTagsModelPayload = {};
|
||||
try {
|
||||
const { modelName } = dto;
|
||||
if (modelName) {
|
||||
@ -145,22 +155,34 @@ export class SpaceModelService {
|
||||
}
|
||||
|
||||
if (dto.subspaceModels) {
|
||||
await this.subSpaceModelService.modifySubSpaceModels(
|
||||
dto.subspaceModels,
|
||||
spaceModel,
|
||||
queryRunner,
|
||||
);
|
||||
modifiedSubspaceModels =
|
||||
await this.subSpaceModelService.modifySubSpaceModels(
|
||||
dto.subspaceModels,
|
||||
spaceModel,
|
||||
queryRunner,
|
||||
);
|
||||
}
|
||||
|
||||
if (dto.tags) {
|
||||
await this.tagModelService.modifyTags(
|
||||
modifiedTagsModelPayload = await this.tagModelService.modifyTags(
|
||||
dto.tags,
|
||||
queryRunner,
|
||||
spaceModel,
|
||||
);
|
||||
}
|
||||
|
||||
await queryRunner.commitTransaction();
|
||||
|
||||
await this.commandBus.execute(
|
||||
new PropogateUpdateSpaceModelCommand({
|
||||
spaceModel: spaceModel,
|
||||
modifiedSpaceModels: {
|
||||
modifiedSubspaceModels,
|
||||
modifiedTags: modifiedTagsModelPayload,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
return new SuccessResponseDto({
|
||||
message: 'SpaceModel updated successfully',
|
||||
data: spaceModel,
|
||||
|
||||
@ -6,7 +6,11 @@ import {
|
||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import { CreateSubspaceModelDto, CreateTagModelDto } from '../../dtos';
|
||||
import { In, QueryRunner } from 'typeorm';
|
||||
import { IDeletedSubsaceModelInterface } from 'src/space-model/interfaces';
|
||||
import {
|
||||
IDeletedSubsaceModelInterface,
|
||||
ModifySubspaceModelPayload,
|
||||
UpdatedSubspaceModelPayload,
|
||||
} from 'src/space-model/interfaces';
|
||||
import {
|
||||
DeleteSubspaceModelDto,
|
||||
ModifySubspaceModelDto,
|
||||
@ -99,17 +103,30 @@ export class SubSpaceModelService {
|
||||
subspaceDtos: ModifySubspaceModelDto[],
|
||||
spaceModel: SpaceModelEntity,
|
||||
queryRunner: QueryRunner,
|
||||
): Promise<void> {
|
||||
): Promise<ModifySubspaceModelPayload> {
|
||||
const modifiedSubspaceModels: ModifySubspaceModelPayload = {};
|
||||
for (const subspace of subspaceDtos) {
|
||||
switch (subspace.action) {
|
||||
case ModifyAction.ADD:
|
||||
await this.handleAddAction(subspace, spaceModel, queryRunner);
|
||||
const subspaceModel = await this.handleAddAction(
|
||||
subspace,
|
||||
spaceModel,
|
||||
queryRunner,
|
||||
);
|
||||
modifiedSubspaceModels.addedSubspaceModels.push(subspaceModel);
|
||||
break;
|
||||
case ModifyAction.UPDATE:
|
||||
await this.handleUpdateAction(subspace, queryRunner);
|
||||
const updatedSubspaceModel = await this.handleUpdateAction(
|
||||
subspace,
|
||||
queryRunner,
|
||||
);
|
||||
modifiedSubspaceModels.updatedSubspaceModels.push(
|
||||
updatedSubspaceModel,
|
||||
);
|
||||
break;
|
||||
case ModifyAction.DELETE:
|
||||
await this.handleDeleteAction(subspace, queryRunner);
|
||||
modifiedSubspaceModels.deletedSubspaceModels.push(subspace.uuid);
|
||||
break;
|
||||
default:
|
||||
throw new HttpException(
|
||||
@ -118,29 +135,42 @@ export class SubSpaceModelService {
|
||||
);
|
||||
}
|
||||
}
|
||||
return modifiedSubspaceModels;
|
||||
}
|
||||
|
||||
private async handleAddAction(
|
||||
subspace: ModifySubspaceModelDto,
|
||||
spaceModel: SpaceModelEntity,
|
||||
queryRunner: QueryRunner,
|
||||
): Promise<void> {
|
||||
): Promise<SubspaceModelEntity> {
|
||||
const createTagDtos: CreateTagModelDto[] =
|
||||
subspace.tags?.map((tag) => ({
|
||||
tag: tag.tag as string,
|
||||
productUuid: tag.productUuid as string,
|
||||
tag: tag.tag,
|
||||
productUuid: tag.productUuid,
|
||||
})) || [];
|
||||
await this.createSubSpaceModels(
|
||||
[{ subspaceName: subspace.subspaceName, tags: createTagDtos }],
|
||||
|
||||
const [createdSubspaceModel] = await this.createSubSpaceModels(
|
||||
[
|
||||
{
|
||||
subspaceName: subspace.subspaceName,
|
||||
tags: createTagDtos,
|
||||
},
|
||||
],
|
||||
spaceModel,
|
||||
queryRunner,
|
||||
);
|
||||
|
||||
return createdSubspaceModel;
|
||||
}
|
||||
|
||||
private async handleUpdateAction(
|
||||
modifyDto: ModifySubspaceModelDto,
|
||||
queryRunner: QueryRunner,
|
||||
): Promise<void> {
|
||||
): Promise<UpdatedSubspaceModelPayload> {
|
||||
const updatePayload: UpdatedSubspaceModelPayload = {
|
||||
subspaceModelUuid: modifyDto.uuid,
|
||||
};
|
||||
|
||||
const subspace = await this.findOne(modifyDto.uuid);
|
||||
|
||||
await this.updateSubspaceName(
|
||||
@ -148,21 +178,24 @@ export class SubSpaceModelService {
|
||||
subspace,
|
||||
modifyDto.subspaceName,
|
||||
);
|
||||
updatePayload.subspaceName = modifyDto.subspaceName;
|
||||
|
||||
if (modifyDto.tags?.length) {
|
||||
await this.tagModelService.modifyTags(
|
||||
updatePayload.modifiedTags = await this.tagModelService.modifyTags(
|
||||
modifyDto.tags,
|
||||
queryRunner,
|
||||
null,
|
||||
subspace,
|
||||
);
|
||||
}
|
||||
|
||||
return updatePayload;
|
||||
}
|
||||
|
||||
private async handleDeleteAction(
|
||||
subspace: ModifySubspaceModelDto,
|
||||
queryRunner: QueryRunner,
|
||||
): Promise<void> {
|
||||
) {
|
||||
const subspaceModel = await this.findOne(subspace.uuid);
|
||||
|
||||
await queryRunner.manager.update(
|
||||
|
||||
@ -9,6 +9,7 @@ import { TagModelRepository } from '@app/common/modules/space-model';
|
||||
import { CreateTagModelDto, ModifyTagModelDto } from '../dtos';
|
||||
import { ProductService } from 'src/product/services';
|
||||
import { ModifyAction } from '@app/common/constants/modify-action.enum';
|
||||
import { ModifiedTagsModelPayload } from '../interfaces';
|
||||
|
||||
@Injectable()
|
||||
export class TagModelService {
|
||||
@ -132,9 +133,9 @@ export class TagModelService {
|
||||
queryRunner: QueryRunner,
|
||||
spaceModel?: SpaceModelEntity,
|
||||
subspaceModel?: SubspaceModelEntity,
|
||||
): Promise<void> {
|
||||
): Promise<ModifiedTagsModelPayload> {
|
||||
const modifiedTagModels: ModifiedTagsModelPayload = {};
|
||||
try {
|
||||
console.log(tags);
|
||||
for (const tag of tags) {
|
||||
if (tag.action === ModifyAction.ADD) {
|
||||
const createTagDto: CreateTagModelDto = {
|
||||
@ -142,20 +143,28 @@ export class TagModelService {
|
||||
productUuid: tag.productUuid as string,
|
||||
};
|
||||
|
||||
await this.createTags(
|
||||
const newModel = await this.createTags(
|
||||
[createTagDto],
|
||||
queryRunner,
|
||||
spaceModel,
|
||||
subspaceModel,
|
||||
);
|
||||
modifiedTagModels.added.push(...newModel);
|
||||
} else if (tag.action === ModifyAction.UPDATE) {
|
||||
await this.updateTag(tag, queryRunner, spaceModel, subspaceModel);
|
||||
const updatedModel = await this.updateTag(
|
||||
tag,
|
||||
queryRunner,
|
||||
spaceModel,
|
||||
subspaceModel,
|
||||
);
|
||||
modifiedTagModels.updated.push(updatedModel);
|
||||
} else if (tag.action === ModifyAction.DELETE) {
|
||||
await queryRunner.manager.update(
|
||||
this.tagModelRepository.target,
|
||||
{ uuid: tag.uuid },
|
||||
{ disabled: true },
|
||||
);
|
||||
modifiedTagModels.deleted.push(tag.uuid);
|
||||
} else {
|
||||
throw new HttpException(
|
||||
`Invalid action "${tag.action}" provided.`,
|
||||
@ -163,6 +172,7 @@ export class TagModelService {
|
||||
);
|
||||
}
|
||||
}
|
||||
return modifiedTagModels;
|
||||
} catch (error) {
|
||||
if (error instanceof HttpException) {
|
||||
throw error;
|
||||
@ -235,7 +245,7 @@ export class TagModelService {
|
||||
});
|
||||
}
|
||||
|
||||
private async getTagByUuid(uuid: string): Promise<TagModel> {
|
||||
async getTagByUuid(uuid: string): Promise<TagModel> {
|
||||
const tag = await this.tagModelRepository.findOne({
|
||||
where: { uuid },
|
||||
relations: ['product'],
|
||||
@ -248,4 +258,38 @@ export class TagModelService {
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
async getTagByName(
|
||||
tag: string,
|
||||
subspaceUuid?: string,
|
||||
spaceUuid?: string,
|
||||
): Promise<TagModel> {
|
||||
const queryConditions: any = { tag };
|
||||
|
||||
if (spaceUuid) {
|
||||
queryConditions.spaceModel = { uuid: spaceUuid };
|
||||
} else if (subspaceUuid) {
|
||||
queryConditions.subspaceModel = { uuid: subspaceUuid };
|
||||
} else {
|
||||
throw new HttpException(
|
||||
'Either spaceUuid or subspaceUuid must be provided.',
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
queryConditions.disabled = false;
|
||||
|
||||
const existingTag = await this.tagModelRepository.findOne({
|
||||
where: queryConditions,
|
||||
relations: ['product'],
|
||||
});
|
||||
|
||||
if (!existingTag) {
|
||||
throw new HttpException(
|
||||
`Tag model with tag "${tag}" not found.`,
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return existingTag;
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,12 +14,34 @@ import {
|
||||
} from '@app/common/modules/space-model';
|
||||
import { ProjectRepository } from '@app/common/modules/project/repositiories';
|
||||
import { ProductRepository } from '@app/common/modules/product/repositories';
|
||||
import { PropogateSubspaceHandler } from './handlers';
|
||||
import {
|
||||
PropogateDeleteSpaceModelHandler,
|
||||
PropogateUpdateSpaceModelHandler,
|
||||
} from './handlers';
|
||||
import { CqrsModule } from '@nestjs/cqrs';
|
||||
import { SpaceRepository } from '@app/common/modules/space';
|
||||
import {
|
||||
SpaceLinkRepository,
|
||||
SpaceRepository,
|
||||
TagRepository,
|
||||
} from '@app/common/modules/space';
|
||||
import { SubspaceRepository } from '@app/common/modules/space/repositories/subspace.repository';
|
||||
import {
|
||||
SpaceLinkService,
|
||||
SpaceService,
|
||||
SubspaceDeviceService,
|
||||
SubSpaceService,
|
||||
ValidationService,
|
||||
} from 'src/space/services';
|
||||
import { TagService } from 'src/space/services/tag';
|
||||
import { CommunityService } from 'src/community/services';
|
||||
import { DeviceRepository } from '@app/common/modules/device/repositories';
|
||||
import { TuyaService } from '@app/common/integrations/tuya/services/tuya.service';
|
||||
import { CommunityRepository } from '@app/common/modules/community/repositories';
|
||||
|
||||
const CommandHandlers = [PropogateSubspaceHandler];
|
||||
const CommandHandlers = [
|
||||
PropogateUpdateSpaceModelHandler,
|
||||
PropogateDeleteSpaceModelHandler,
|
||||
];
|
||||
|
||||
@Module({
|
||||
imports: [ConfigModule, SpaceRepositoryModule, CqrsModule],
|
||||
@ -27,6 +49,7 @@ const CommandHandlers = [PropogateSubspaceHandler];
|
||||
providers: [
|
||||
...CommandHandlers,
|
||||
SpaceModelService,
|
||||
SpaceService,
|
||||
SpaceModelRepository,
|
||||
SpaceRepository,
|
||||
ProjectRepository,
|
||||
@ -36,6 +59,17 @@ const CommandHandlers = [PropogateSubspaceHandler];
|
||||
SubspaceRepository,
|
||||
TagModelService,
|
||||
TagModelRepository,
|
||||
SubSpaceService,
|
||||
ValidationService,
|
||||
TagService,
|
||||
SubspaceDeviceService,
|
||||
CommunityService,
|
||||
TagRepository,
|
||||
DeviceRepository,
|
||||
TuyaService,
|
||||
CommunityRepository,
|
||||
SpaceLinkService,
|
||||
SpaceLinkRepository,
|
||||
],
|
||||
exports: [CqrsModule, SpaceModelService],
|
||||
})
|
||||
|
||||
5
src/space/interfaces/add-subspace.interface.ts
Normal file
5
src/space/interfaces/add-subspace.interface.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { SubspaceEntity } from '@app/common/modules/space';
|
||||
|
||||
export interface ModifySubspacePayload {
|
||||
addedSubspaces?: SubspaceEntity[];
|
||||
}
|
||||
0
src/space/interfaces/index.ts
Normal file
0
src/space/interfaces/index.ts
Normal file
@ -317,8 +317,8 @@ export class SpaceService {
|
||||
if (hasSubspace) {
|
||||
await this.subSpaceService.modifySubSpace(
|
||||
updateSpaceDto.subspace,
|
||||
space,
|
||||
queryRunner,
|
||||
space,
|
||||
);
|
||||
}
|
||||
|
||||
@ -353,6 +353,37 @@ export class SpaceService {
|
||||
}
|
||||
}
|
||||
|
||||
async unlinkSpaceFromModel(
|
||||
space: SpaceEntity,
|
||||
queryRunner: QueryRunner,
|
||||
): Promise<void> {
|
||||
try {
|
||||
await queryRunner.manager.update(
|
||||
this.spaceRepository.target,
|
||||
{ uuid: space.uuid },
|
||||
{
|
||||
spaceModel: null,
|
||||
},
|
||||
);
|
||||
|
||||
// Unlink subspaces and tags if they exist
|
||||
if (space.subspaces || space.tags) {
|
||||
if (space.tags) {
|
||||
await this.tagService.unlinkModels(space.tags, queryRunner);
|
||||
}
|
||||
|
||||
if (space.subspaces) {
|
||||
await this.subSpaceService.unlinkModels(space.subspaces, queryRunner);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
throw new HttpException(
|
||||
`Failed to unlink space model: ${error.message}`,
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private updateSpaceProperties(
|
||||
space: SpaceEntity,
|
||||
updateSpaceDto: UpdateSpaceDto,
|
||||
|
||||
@ -26,6 +26,7 @@ import { SubspaceRepository } from '@app/common/modules/space/repositories/subsp
|
||||
import { TagService } from '../tag';
|
||||
import { ModifyAction } from '@app/common/constants/modify-action.enum';
|
||||
import { SubspaceDeviceService } from './subspace-device.service';
|
||||
import { ModifyTagDto } from 'src/space/dtos/tag/modify-tag.dto';
|
||||
|
||||
@Injectable()
|
||||
export class SubSpaceService {
|
||||
@ -317,9 +318,9 @@ export class SubSpaceService {
|
||||
|
||||
async modifySubSpace(
|
||||
subspaceDtos: ModifySubspaceDto[],
|
||||
space: SpaceEntity,
|
||||
queryRunner: QueryRunner,
|
||||
): Promise<void> {
|
||||
space?: SpaceEntity,
|
||||
) {
|
||||
for (const subspace of subspaceDtos) {
|
||||
switch (subspace.action) {
|
||||
case ModifyAction.ADD:
|
||||
@ -382,17 +383,18 @@ export class SubSpaceService {
|
||||
subspace: ModifySubspaceDto,
|
||||
space: SpaceEntity,
|
||||
queryRunner: QueryRunner,
|
||||
): Promise<void> {
|
||||
): Promise<SubspaceEntity> {
|
||||
const createTagDtos: CreateTagDto[] =
|
||||
subspace.tags?.map((tag) => ({
|
||||
tag: tag.tag as string,
|
||||
productUuid: tag.productUuid as string,
|
||||
})) || [];
|
||||
await this.createSubspacesFromDto(
|
||||
const subSpace = await this.createSubspacesFromDto(
|
||||
[{ subspaceName: subspace.subspaceName, tags: createTagDtos }],
|
||||
space,
|
||||
queryRunner,
|
||||
);
|
||||
return subSpace[0];
|
||||
}
|
||||
|
||||
private async handleUpdateAction(
|
||||
@ -400,16 +402,25 @@ export class SubSpaceService {
|
||||
queryRunner: QueryRunner,
|
||||
): Promise<void> {
|
||||
const subspace = await this.findOne(modifyDto.uuid);
|
||||
|
||||
await this.updateSubspaceName(
|
||||
await this.update(
|
||||
queryRunner,
|
||||
subspace,
|
||||
modifyDto.subspaceName,
|
||||
modifyDto.tags,
|
||||
);
|
||||
}
|
||||
|
||||
if (modifyDto.tags?.length) {
|
||||
async update(
|
||||
queryRunner: QueryRunner,
|
||||
subspace: SubspaceEntity,
|
||||
subspaceName?: string,
|
||||
modifyTagDto?: ModifyTagDto[],
|
||||
) {
|
||||
await this.updateSubspaceName(queryRunner, subspace, subspaceName);
|
||||
|
||||
if (modifyTagDto?.length) {
|
||||
await this.tagService.modifyTags(
|
||||
modifyDto.tags,
|
||||
modifyTagDto,
|
||||
queryRunner,
|
||||
null,
|
||||
subspace,
|
||||
@ -417,11 +428,11 @@ export class SubSpaceService {
|
||||
}
|
||||
}
|
||||
|
||||
private async handleDeleteAction(
|
||||
subspace: ModifySubspaceDto,
|
||||
async handleDeleteAction(
|
||||
modifyDto: ModifySubspaceDto,
|
||||
queryRunner: QueryRunner,
|
||||
): Promise<void> {
|
||||
const subspaceModel = await this.findOne(subspace.uuid);
|
||||
const subspace = await this.findOne(modifyDto.uuid);
|
||||
|
||||
await queryRunner.manager.update(
|
||||
this.subspaceRepository.target,
|
||||
@ -429,8 +440,8 @@ export class SubSpaceService {
|
||||
{ disabled: true },
|
||||
);
|
||||
|
||||
if (subspaceModel.tags?.length) {
|
||||
const modifyTagDtos = subspaceModel.tags.map((tag) => ({
|
||||
if (subspace.tags?.length) {
|
||||
const modifyTagDtos = subspace.tags.map((tag) => ({
|
||||
uuid: tag.uuid,
|
||||
action: ModifyAction.DELETE,
|
||||
}));
|
||||
@ -438,7 +449,14 @@ export class SubSpaceService {
|
||||
modifyTagDtos,
|
||||
queryRunner,
|
||||
null,
|
||||
subspaceModel,
|
||||
subspace,
|
||||
);
|
||||
}
|
||||
|
||||
if (subspace.devices.length > 0) {
|
||||
await this.deviceService.deleteSubspaceDevices(
|
||||
subspace.devices,
|
||||
queryRunner,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -446,7 +464,7 @@ export class SubSpaceService {
|
||||
private async findOne(subspaceUuid: string): Promise<SubspaceEntity> {
|
||||
const subspace = await this.subspaceRepository.findOne({
|
||||
where: { uuid: subspaceUuid },
|
||||
relations: ['tags', 'space'],
|
||||
relations: ['tags', 'space', 'devices', 'tags.product', 'tags.device'],
|
||||
});
|
||||
if (!subspace) {
|
||||
throw new HttpException(
|
||||
@ -457,7 +475,7 @@ export class SubSpaceService {
|
||||
return subspace;
|
||||
}
|
||||
|
||||
private async updateSubspaceName(
|
||||
async updateSubspaceName(
|
||||
queryRunner: QueryRunner,
|
||||
subSpace: SubspaceEntity,
|
||||
subspaceName?: string,
|
||||
|
||||
@ -63,6 +63,7 @@ export class TagService {
|
||||
|
||||
await queryRunner.manager.save(tags);
|
||||
}
|
||||
|
||||
async updateTag(
|
||||
tag: ModifyTagDto,
|
||||
queryRunner: QueryRunner,
|
||||
@ -90,6 +91,38 @@ export class TagService {
|
||||
}
|
||||
}
|
||||
|
||||
async updateTagsFromModel(
|
||||
model: TagModel,
|
||||
queryRunner: QueryRunner,
|
||||
): Promise<void> {
|
||||
try {
|
||||
const tags = await this.tagRepository.find({
|
||||
where: {
|
||||
model: {
|
||||
uuid: model.uuid,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!tags.length) return;
|
||||
|
||||
await queryRunner.manager.update(
|
||||
this.tagRepository.target,
|
||||
{ model: { uuid: model.uuid } },
|
||||
{ tag: model.tag },
|
||||
);
|
||||
} catch (error) {
|
||||
if (error instanceof HttpException) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
throw new HttpException(
|
||||
`Failed to update tags for model with UUID: ${model.uuid}. Reason: ${error.message}`,
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async deleteTags(tagUuids: string[], queryRunner: QueryRunner) {
|
||||
if (!tagUuids?.length) return;
|
||||
|
||||
@ -109,6 +142,34 @@ export class TagService {
|
||||
}
|
||||
}
|
||||
|
||||
async deleteTagFromModel(modelUuid: string, queryRunner: QueryRunner) {
|
||||
try {
|
||||
const tags = await this.tagRepository.find({
|
||||
where: {
|
||||
model: {
|
||||
uuid: modelUuid,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!tags.length) return;
|
||||
|
||||
await queryRunner.manager.update(
|
||||
this.tagRepository.target,
|
||||
{ model: { uuid: modelUuid } },
|
||||
{ disabled: true, device: null },
|
||||
);
|
||||
} catch (error) {
|
||||
if (error instanceof HttpException) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
throw new HttpException(
|
||||
`Failed to update tags for model with UUID: ${modelUuid}. Reason: ${error.message}`,
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
async modifyTags(
|
||||
tags: ModifyTagDto[],
|
||||
queryRunner: QueryRunner,
|
||||
|
||||
Reference in New Issue
Block a user