mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-11-26 13:44:55 +00:00
update in tag service
This commit is contained in:
@ -13,7 +13,7 @@ export class CreateSubspaceModelDto {
|
|||||||
subspaceName: string;
|
subspaceName: string;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'List of tags associated with the subspace',
|
description: 'List of tag models associated with the subspace',
|
||||||
type: [CreateTagModelDto],
|
type: [CreateTagModelDto],
|
||||||
})
|
})
|
||||||
@IsArray()
|
@IsArray()
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { IsNotEmpty, IsString } from 'class-validator';
|
|||||||
|
|
||||||
export class CreateTagModelDto {
|
export class CreateTagModelDto {
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'Tag associated with the space or subspace',
|
description: 'Tag models associated with the space or subspace models',
|
||||||
example: 'Temperature Control',
|
example: 'Temperature Control',
|
||||||
})
|
})
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
|
|||||||
@ -11,7 +11,7 @@ export class ModifyTagModelDto {
|
|||||||
action: ModifyAction;
|
action: ModifyAction;
|
||||||
|
|
||||||
@ApiPropertyOptional({
|
@ApiPropertyOptional({
|
||||||
description: 'UUID of the tag (required for update/delete)',
|
description: 'UUID of the tag model (required for update/delete)',
|
||||||
example: '123e4567-e89b-12d3-a456-426614174000',
|
example: '123e4567-e89b-12d3-a456-426614174000',
|
||||||
})
|
})
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ -19,7 +19,7 @@ export class ModifyTagModelDto {
|
|||||||
uuid?: string;
|
uuid?: string;
|
||||||
|
|
||||||
@ApiPropertyOptional({
|
@ApiPropertyOptional({
|
||||||
description: 'Name of the tag (required for add/update)',
|
description: 'Name of the tag model (required for add/update)',
|
||||||
example: 'Temperature Sensor',
|
example: 'Temperature Sensor',
|
||||||
})
|
})
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
|
|||||||
@ -152,6 +152,14 @@ export class SpaceModelService {
|
|||||||
queryRunner,
|
queryRunner,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dto.tags) {
|
||||||
|
await this.tagModelService.modifyTags(
|
||||||
|
dto.tags,
|
||||||
|
queryRunner,
|
||||||
|
spaceModel,
|
||||||
|
);
|
||||||
|
}
|
||||||
await queryRunner.commitTransaction();
|
await queryRunner.commitTransaction();
|
||||||
|
|
||||||
return new SuccessResponseDto({
|
return new SuccessResponseDto({
|
||||||
|
|||||||
@ -4,16 +4,9 @@ import {
|
|||||||
SubspaceModelRepository,
|
SubspaceModelRepository,
|
||||||
} 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 {
|
import { CreateSubspaceModelDto, CreateTagModelDto } from '../../dtos';
|
||||||
CreateSubspaceModelDto,
|
|
||||||
UpdateSubspaceModelDto,
|
|
||||||
CreateTagModelDto,
|
|
||||||
} from '../../dtos';
|
|
||||||
import { QueryRunner } from 'typeorm';
|
import { QueryRunner } from 'typeorm';
|
||||||
import {
|
import { IDeletedSubsaceModelInterface } from 'src/space-model/interfaces';
|
||||||
IDeletedSubsaceModelInterface,
|
|
||||||
IUpdateSubspaceModelInterface,
|
|
||||||
} from 'src/space-model/interfaces';
|
|
||||||
import {
|
import {
|
||||||
DeleteSubspaceModelDto,
|
DeleteSubspaceModelDto,
|
||||||
ModifySubspaceModelDto,
|
ModifySubspaceModelDto,
|
||||||
@ -63,33 +56,6 @@ export class SubSpaceModelService {
|
|||||||
return savedSubspaces;
|
return savedSubspaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateSubspaceModels(
|
|
||||||
updateDtos: UpdateSubspaceModelDto[],
|
|
||||||
queryRunner: QueryRunner,
|
|
||||||
): Promise<IUpdateSubspaceModelInterface[]> {
|
|
||||||
const updateResults: IUpdateSubspaceModelInterface[] = [];
|
|
||||||
|
|
||||||
for (const dto of updateDtos) {
|
|
||||||
await this.findOne(dto.subspaceUuid);
|
|
||||||
const updateResult: IUpdateSubspaceModelInterface = {
|
|
||||||
uuid: dto.subspaceUuid,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (dto.subspaceName) {
|
|
||||||
await this.updateSubspaceName(
|
|
||||||
dto.subspaceUuid,
|
|
||||||
dto.subspaceName,
|
|
||||||
queryRunner,
|
|
||||||
);
|
|
||||||
updateResult.subspaceName = dto.subspaceName;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateResults.push(updateResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
return updateResults;
|
|
||||||
}
|
|
||||||
|
|
||||||
async deleteSubspaceModels(
|
async deleteSubspaceModels(
|
||||||
deleteDtos: DeleteSubspaceModelDto[],
|
deleteDtos: DeleteSubspaceModelDto[],
|
||||||
queryRunner: QueryRunner,
|
queryRunner: QueryRunner,
|
||||||
@ -167,22 +133,23 @@ export class SubSpaceModelService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async handleUpdateAction(
|
private async handleUpdateAction(
|
||||||
subspace: ModifySubspaceModelDto,
|
modifyDto: ModifySubspaceModelDto,
|
||||||
queryRunner: QueryRunner,
|
queryRunner: QueryRunner,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const existingSubspace = await this.findOne(subspace.uuid);
|
const subspace = await this.findOne(modifyDto.uuid);
|
||||||
|
|
||||||
if (subspace.subspaceName) {
|
await this.updateSubspaceName(
|
||||||
existingSubspace.subspaceName = subspace.subspaceName;
|
queryRunner,
|
||||||
await queryRunner.manager.save(existingSubspace);
|
subspace,
|
||||||
}
|
modifyDto.subspaceName,
|
||||||
|
);
|
||||||
|
|
||||||
if (subspace.tags?.length) {
|
if (modifyDto.tags?.length) {
|
||||||
await this.tagModelService.modifyTags(
|
await this.tagModelService.modifyTags(
|
||||||
subspace.tags,
|
modifyDto.tags,
|
||||||
queryRunner,
|
queryRunner,
|
||||||
null,
|
null,
|
||||||
existingSubspace,
|
subspace,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -258,14 +225,13 @@ export class SubSpaceModelService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async updateSubspaceName(
|
private async updateSubspaceName(
|
||||||
uuid: string,
|
|
||||||
subspaceName: string,
|
|
||||||
queryRunner: QueryRunner,
|
queryRunner: QueryRunner,
|
||||||
|
subSpaceModel: SubspaceModelEntity,
|
||||||
|
subspaceName?: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await queryRunner.manager.update(
|
if (subspaceName) {
|
||||||
this.subspaceModelRepository.target,
|
subSpaceModel.subspaceName = subspaceName;
|
||||||
{ uuid },
|
await queryRunner.manager.save(subSpaceModel);
|
||||||
{ subspaceName },
|
}
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -169,7 +169,7 @@ export class TagModelService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
`An error occurred while modifying tags: ${error.message}`,
|
`An error occurred while modifying tag models: ${error.message}`,
|
||||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -236,7 +236,7 @@ export class TagModelService {
|
|||||||
});
|
});
|
||||||
if (!tag) {
|
if (!tag) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
`Tag with ID ${uuid} not found.`,
|
`Tag model with ID ${uuid} not found.`,
|
||||||
HttpStatus.NOT_FOUND,
|
HttpStatus.NOT_FOUND,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import {
|
|||||||
ValidateNested,
|
ValidateNested,
|
||||||
} from 'class-validator';
|
} from 'class-validator';
|
||||||
import { AddSubspaceDto } from './subspace';
|
import { AddSubspaceDto } from './subspace';
|
||||||
|
import { CreateTagDto } from './tag';
|
||||||
|
|
||||||
export class AddSpaceDto {
|
export class AddSpaceDto {
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
@ -77,6 +78,15 @@ export class AddSpaceDto {
|
|||||||
@ValidateNested({ each: true })
|
@ValidateNested({ each: true })
|
||||||
@Type(() => AddSubspaceDto)
|
@Type(() => AddSubspaceDto)
|
||||||
subspaces?: AddSubspaceDto[];
|
subspaces?: AddSubspaceDto[];
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'List of tags associated with the space model',
|
||||||
|
type: [CreateTagDto],
|
||||||
|
})
|
||||||
|
@IsArray()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@Type(() => CreateTagDto)
|
||||||
|
tags?: CreateTagDto[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AddUserSpaceDto {
|
export class AddUserSpaceDto {
|
||||||
|
|||||||
@ -5,3 +5,4 @@ export * from './user-space.param';
|
|||||||
export * from './subspace';
|
export * from './subspace';
|
||||||
export * from './project.param.dto';
|
export * from './project.param.dto';
|
||||||
export * from './update.space.dto';
|
export * from './update.space.dto';
|
||||||
|
export * from './tag';
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { IsNotEmpty, IsString } from 'class-validator';
|
import { IsArray, IsNotEmpty, IsString, ValidateNested } from 'class-validator';
|
||||||
|
import { CreateTagDto } from '../tag';
|
||||||
|
import { Type } from 'class-transformer';
|
||||||
|
|
||||||
export class AddSubspaceDto {
|
export class AddSubspaceDto {
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
@ -9,4 +11,13 @@ export class AddSubspaceDto {
|
|||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@IsString()
|
@IsString()
|
||||||
subspaceName: string;
|
subspaceName: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'List of tags associated with the subspace',
|
||||||
|
type: [CreateTagDto],
|
||||||
|
})
|
||||||
|
@IsArray()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@Type(() => CreateTagDto)
|
||||||
|
tags?: CreateTagDto[];
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/space/dtos/subspace/delete.subspace.dto.ts
Normal file
12
src/space/dtos/subspace/delete.subspace.dto.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class DeleteSubspaceDto {
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'Uuid of the subspace model need to be deleted',
|
||||||
|
example: '982fc3a3-64dc-4afb-a5b5-65ee8fef0424',
|
||||||
|
})
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsString()
|
||||||
|
subspaceUuid: string;
|
||||||
|
}
|
||||||
@ -1,3 +1,6 @@
|
|||||||
export * from './add.subspace.dto';
|
export * from './add.subspace.dto';
|
||||||
export * from './get.subspace.param';
|
export * from './get.subspace.param';
|
||||||
export * from './add.subspace-device.param';
|
export * from './add.subspace-device.param';
|
||||||
|
export * from './update.subspace.dto';
|
||||||
|
export * from './delete.subspace.dto';
|
||||||
|
export * from './modify.subspace.dto';
|
||||||
|
|||||||
47
src/space/dtos/subspace/modify.subspace.dto.ts
Normal file
47
src/space/dtos/subspace/modify.subspace.dto.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import { ModifyAction } from '@app/common/constants/modify-action.enum';
|
||||||
|
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||||
|
import { Type } from 'class-transformer';
|
||||||
|
import {
|
||||||
|
IsEnum,
|
||||||
|
IsOptional,
|
||||||
|
IsString,
|
||||||
|
IsArray,
|
||||||
|
ValidateNested,
|
||||||
|
} from 'class-validator';
|
||||||
|
import { ModifyTagDto } from '../tag/modify-tag.dto';
|
||||||
|
|
||||||
|
export class ModifySubspaceDto {
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'Action to perform: add, update, or delete',
|
||||||
|
example: ModifyAction.ADD,
|
||||||
|
})
|
||||||
|
@IsEnum(ModifyAction)
|
||||||
|
action: ModifyAction;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description: 'UUID of the subspace (required for update/delete)',
|
||||||
|
example: '123e4567-e89b-12d3-a456-426614174000',
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
uuid?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description: 'Name of the subspace (required for add/update)',
|
||||||
|
example: 'Living Room',
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
subspaceName?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description:
|
||||||
|
'List of tag modifications (add/update/delete) for the subspace',
|
||||||
|
type: [ModifyTagDto],
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsArray()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@Type(() => ModifyTagDto)
|
||||||
|
tags?: ModifyTagDto[];
|
||||||
|
}
|
||||||
16
src/space/dtos/subspace/update.subspace.dto.ts
Normal file
16
src/space/dtos/subspace/update.subspace.dto.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class UpdateSubspaceDto {
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'Name of the subspace',
|
||||||
|
example: 'Living Room',
|
||||||
|
})
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsString()
|
||||||
|
subspaceName?: string;
|
||||||
|
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsString()
|
||||||
|
subspaceUuid: string;
|
||||||
|
}
|
||||||
20
src/space/dtos/tag/create-tag-dto.ts
Normal file
20
src/space/dtos/tag/create-tag-dto.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class CreateTagDto {
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'Tag associated with the space or subspace',
|
||||||
|
example: 'Temperature Control',
|
||||||
|
})
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsString()
|
||||||
|
tag: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'ID of the product associated with the tag',
|
||||||
|
example: '123e4567-e89b-12d3-a456-426614174000',
|
||||||
|
})
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsString()
|
||||||
|
productUuid: string;
|
||||||
|
}
|
||||||
1
src/space/dtos/tag/index.ts
Normal file
1
src/space/dtos/tag/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './create-tag-dto';
|
||||||
37
src/space/dtos/tag/modify-tag.dto.ts
Normal file
37
src/space/dtos/tag/modify-tag.dto.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { ModifyAction } from '@app/common/constants/modify-action.enum';
|
||||||
|
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||||
|
import { IsEnum, IsOptional, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class ModifyTagDto {
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'Action to perform: add, update, or delete',
|
||||||
|
example: ModifyAction.ADD,
|
||||||
|
})
|
||||||
|
@IsEnum(ModifyAction)
|
||||||
|
action: ModifyAction;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description: 'UUID of the tag (required for update/delete)',
|
||||||
|
example: '123e4567-e89b-12d3-a456-426614174000',
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
uuid?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description: 'Name of the tag (required for add/update)',
|
||||||
|
example: 'Temperature Sensor',
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
tag?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description:
|
||||||
|
'UUID of the product associated with the tag (required for add)',
|
||||||
|
example: 'c789a91e-549a-4753-9006-02f89e8170e0',
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
productUuid?: string;
|
||||||
|
}
|
||||||
@ -1,4 +1,59 @@
|
|||||||
import { PartialType } from '@nestjs/swagger';
|
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||||
import { AddSpaceDto } from './add.space.dto';
|
import {
|
||||||
|
IsArray,
|
||||||
|
IsNumber,
|
||||||
|
IsOptional,
|
||||||
|
IsString,
|
||||||
|
ValidateNested,
|
||||||
|
} from 'class-validator';
|
||||||
|
import { ModifySubspaceDto } from './subspace';
|
||||||
|
import { Type } from 'class-transformer';
|
||||||
|
import { ModifyTagDto } from './tag/modify-tag.dto';
|
||||||
|
|
||||||
export class UpdateSpaceDto extends PartialType(AddSpaceDto) {}
|
export class UpdateSpaceDto {
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'Updated name of the space ',
|
||||||
|
example: 'New Space Name',
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
spaceName?: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'Icon identifier for the space',
|
||||||
|
example: 'assets/location',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
public icon?: string;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'X position on canvas', example: 120 })
|
||||||
|
@IsNumber()
|
||||||
|
x: number;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Y position on canvas', example: 200 })
|
||||||
|
@IsNumber()
|
||||||
|
y: number;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description: 'List of subspace modifications (add/update/delete)',
|
||||||
|
type: [ModifySubspaceDto],
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsArray()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@Type(() => ModifySubspaceDto)
|
||||||
|
subspaceModels?: ModifySubspaceDto[];
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description:
|
||||||
|
'List of tag modifications (add/update/delete) for the space model',
|
||||||
|
type: [ModifyTagDto],
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsArray()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@Type(() => ModifyTagDto)
|
||||||
|
tags?: ModifyTagDto[];
|
||||||
|
}
|
||||||
|
|||||||
@ -16,11 +16,11 @@ import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
|||||||
import { SpaceEntity } from '@app/common/modules/space/entities';
|
import { SpaceEntity } from '@app/common/modules/space/entities';
|
||||||
import { generateRandomString } from '@app/common/helper/randomString';
|
import { generateRandomString } from '@app/common/helper/randomString';
|
||||||
import { SpaceLinkService } from './space-link';
|
import { SpaceLinkService } from './space-link';
|
||||||
import { CreateSubspaceModelDto } from 'src/space-model/dtos';
|
|
||||||
import { SubSpaceService } from './subspace';
|
import { SubSpaceService } from './subspace';
|
||||||
import { DataSource, Not } from 'typeorm';
|
import { DataSource, Not } from 'typeorm';
|
||||||
import { ValidationService } from './space-validation.service';
|
import { ValidationService } from './space-validation.service';
|
||||||
import { ORPHAN_SPACE_NAME } from '@app/common/constants/orphan-constant';
|
import { ORPHAN_SPACE_NAME } from '@app/common/constants/orphan-constant';
|
||||||
|
import { TagService } from './tag';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SpaceService {
|
export class SpaceService {
|
||||||
@ -30,13 +30,15 @@ export class SpaceService {
|
|||||||
private readonly spaceLinkService: SpaceLinkService,
|
private readonly spaceLinkService: SpaceLinkService,
|
||||||
private readonly subSpaceService: SubSpaceService,
|
private readonly subSpaceService: SubSpaceService,
|
||||||
private readonly validationService: ValidationService,
|
private readonly validationService: ValidationService,
|
||||||
|
private readonly tagService: TagService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async createSpace(
|
async createSpace(
|
||||||
addSpaceDto: AddSpaceDto,
|
addSpaceDto: AddSpaceDto,
|
||||||
params: CommunitySpaceParam,
|
params: CommunitySpaceParam,
|
||||||
): Promise<BaseResponseDto> {
|
): Promise<BaseResponseDto> {
|
||||||
const { parentUuid, direction, spaceModelUuid, subspaces } = addSpaceDto;
|
const { parentUuid, direction, spaceModelUuid, subspaces, tags } =
|
||||||
|
addSpaceDto;
|
||||||
const { communityUuid, projectUuid } = params;
|
const { communityUuid, projectUuid } = params;
|
||||||
|
|
||||||
if (addSpaceDto.spaceName === ORPHAN_SPACE_NAME) {
|
if (addSpaceDto.spaceName === ORPHAN_SPACE_NAME) {
|
||||||
@ -67,14 +69,14 @@ export class SpaceService {
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const newSpace = queryRunner.manager.create(SpaceEntity, {
|
const space = queryRunner.manager.create(SpaceEntity, {
|
||||||
...addSpaceDto,
|
...addSpaceDto,
|
||||||
spaceModel,
|
spaceModel,
|
||||||
parent: parentUuid ? parent : null,
|
parent: parentUuid ? parent : null,
|
||||||
community,
|
community,
|
||||||
});
|
});
|
||||||
|
|
||||||
await queryRunner.manager.save(newSpace);
|
const newSpace = await queryRunner.manager.save(space);
|
||||||
|
|
||||||
if (direction && parent) {
|
if (direction && parent) {
|
||||||
await this.spaceLinkService.saveSpaceLink(
|
await this.spaceLinkService.saveSpaceLink(
|
||||||
@ -90,11 +92,14 @@ export class SpaceService {
|
|||||||
newSpace,
|
newSpace,
|
||||||
queryRunner,
|
queryRunner,
|
||||||
);
|
);
|
||||||
} else if (spaceModel && spaceModel.subspaceModels.length) {
|
}
|
||||||
await this.subSpaceService.createSubSpaceFromModel(
|
|
||||||
spaceModel,
|
if (tags?.length) {
|
||||||
newSpace,
|
newSpace.tags = await this.tagService.createTags(
|
||||||
|
tags,
|
||||||
queryRunner,
|
queryRunner,
|
||||||
|
newSpace,
|
||||||
|
null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,19 +247,32 @@ export class SpaceService {
|
|||||||
HttpStatus.BAD_REQUEST,
|
HttpStatus.BAD_REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (updateSpaceDto.spaceName) space.spaceName = updateSpaceDto.spaceName;
|
||||||
|
|
||||||
// If a parentId is provided, check if the parent exists
|
if (updateSpaceDto.x) space.x = updateSpaceDto.x;
|
||||||
const { parentUuid } = updateSpaceDto;
|
|
||||||
const parent = parentUuid
|
|
||||||
? await this.validationService.validateSpace(parentUuid)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
// Update other space properties from updateSpaceDto
|
if (updateSpaceDto.y) space.y = updateSpaceDto.y;
|
||||||
Object.assign(space, updateSpaceDto, { parent });
|
if (updateSpaceDto.icon) space.icon = updateSpaceDto.icon;
|
||||||
|
if (updateSpaceDto.icon) space.icon = updateSpaceDto.icon;
|
||||||
|
|
||||||
// Save the updated space
|
|
||||||
await queryRunner.manager.save(space);
|
await queryRunner.manager.save(space);
|
||||||
|
|
||||||
|
if (updateSpaceDto.subspaceModels) {
|
||||||
|
await this.subSpaceService.modifySubSpace(
|
||||||
|
updateSpaceDto.subspaceModels,
|
||||||
|
space,
|
||||||
|
queryRunner,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateSpaceDto.tags) {
|
||||||
|
await this.tagService.modifyTags(
|
||||||
|
updateSpaceDto.tags,
|
||||||
|
queryRunner,
|
||||||
|
space,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
await queryRunner.commitTransaction();
|
await queryRunner.commitTransaction();
|
||||||
|
|
||||||
return new SuccessResponseDto({
|
return new SuccessResponseDto({
|
||||||
|
|||||||
@ -1,6 +1,13 @@
|
|||||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||||
import { AddSubspaceDto, GetSpaceParam, GetSubSpaceParam } from '../../dtos';
|
import {
|
||||||
|
AddSubspaceDto,
|
||||||
|
CreateTagDto,
|
||||||
|
DeleteSubspaceDto,
|
||||||
|
GetSpaceParam,
|
||||||
|
GetSubSpaceParam,
|
||||||
|
ModifySubspaceDto,
|
||||||
|
} from '../../dtos';
|
||||||
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
||||||
import {
|
import {
|
||||||
TypeORMCustomModel,
|
TypeORMCustomModel,
|
||||||
@ -19,12 +26,15 @@ import {
|
|||||||
} from '@app/common/modules/space-model';
|
} from '@app/common/modules/space-model';
|
||||||
import { ValidationService } from '../space-validation.service';
|
import { ValidationService } from '../space-validation.service';
|
||||||
import { SubspaceRepository } from '@app/common/modules/space/repositories/subspace.repository';
|
import { SubspaceRepository } from '@app/common/modules/space/repositories/subspace.repository';
|
||||||
|
import { TagService } from '../tag';
|
||||||
|
import { ModifyAction } from '@app/common/constants/modify-action.enum';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SubSpaceService {
|
export class SubSpaceService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly subspaceRepository: SubspaceRepository,
|
private readonly subspaceRepository: SubspaceRepository,
|
||||||
private readonly validationService: ValidationService,
|
private readonly validationService: ValidationService,
|
||||||
|
private readonly tagService: TagService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async createSubspaces(
|
async createSubspaces(
|
||||||
@ -71,6 +81,7 @@ export class SubSpaceService {
|
|||||||
addSubspaceDtos: AddSubspaceDto[],
|
addSubspaceDtos: AddSubspaceDto[],
|
||||||
space: SpaceEntity,
|
space: SpaceEntity,
|
||||||
queryRunner: QueryRunner,
|
queryRunner: QueryRunner,
|
||||||
|
otherTags?: CreateTagDto[],
|
||||||
): Promise<SubspaceEntity[]> {
|
): Promise<SubspaceEntity[]> {
|
||||||
try {
|
try {
|
||||||
const subspaceData = addSubspaceDtos.map((dto) => ({
|
const subspaceData = addSubspaceDtos.map((dto) => ({
|
||||||
@ -80,6 +91,20 @@ export class SubSpaceService {
|
|||||||
|
|
||||||
const subspaces = await this.createSubspaces(subspaceData, queryRunner);
|
const subspaces = await this.createSubspaces(subspaceData, queryRunner);
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
addSubspaceDtos.map(async (dto, index) => {
|
||||||
|
const subspace = subspaces[index];
|
||||||
|
if (dto.tags?.length) {
|
||||||
|
subspace.tags = await this.tagService.createTags(
|
||||||
|
dto.tags,
|
||||||
|
queryRunner,
|
||||||
|
null,
|
||||||
|
subspace,
|
||||||
|
otherTags,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
return subspaces;
|
return subspaces;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@ -144,43 +169,6 @@ export class SubSpaceService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async findOne(params: GetSubSpaceParam): Promise<BaseResponseDto> {
|
|
||||||
const { communityUuid, subSpaceUuid, spaceUuid, projectUuid } = params;
|
|
||||||
await this.validationService.validateSpaceWithinCommunityAndProject(
|
|
||||||
communityUuid,
|
|
||||||
projectUuid,
|
|
||||||
spaceUuid,
|
|
||||||
);
|
|
||||||
try {
|
|
||||||
const subSpace = await this.subspaceRepository.findOne({
|
|
||||||
where: {
|
|
||||||
uuid: subSpaceUuid,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// If space is not found, throw a NotFoundException
|
|
||||||
if (!subSpace) {
|
|
||||||
throw new HttpException(
|
|
||||||
`Sub Space with UUID ${subSpaceUuid} not found`,
|
|
||||||
HttpStatus.NOT_FOUND,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return new SuccessResponseDto({
|
|
||||||
message: `Subspace with ID ${subSpaceUuid} successfully fetched`,
|
|
||||||
data: subSpace,
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
if (error instanceof HttpException) {
|
|
||||||
throw error; // If it's an HttpException, rethrow it
|
|
||||||
} else {
|
|
||||||
throw new HttpException(
|
|
||||||
'An error occurred while deleting the subspace',
|
|
||||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async updateSubSpace(
|
async updateSubSpace(
|
||||||
params: GetSubSpaceParam,
|
params: GetSubSpaceParam,
|
||||||
updateSubSpaceDto: AddSubspaceDto,
|
updateSubSpaceDto: AddSubspaceDto,
|
||||||
@ -256,4 +244,153 @@ export class SubSpaceService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async deleteSubspaces(
|
||||||
|
deleteDtos: DeleteSubspaceDto[],
|
||||||
|
queryRunner: QueryRunner,
|
||||||
|
) {
|
||||||
|
const deleteResults: { uuid: string }[] = [];
|
||||||
|
|
||||||
|
for (const dto of deleteDtos) {
|
||||||
|
const subspaceModel = await this.findOne(dto.subspaceUuid);
|
||||||
|
|
||||||
|
await queryRunner.manager.update(
|
||||||
|
this.subspaceRepository.target,
|
||||||
|
{ uuid: dto.subspaceUuid },
|
||||||
|
{ disabled: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
if (subspaceModel.tags?.length) {
|
||||||
|
const modifyTagDtos = subspaceModel.tags.map((tag) => ({
|
||||||
|
uuid: tag.uuid,
|
||||||
|
action: ModifyAction.DELETE,
|
||||||
|
}));
|
||||||
|
await this.tagService.modifyTags(
|
||||||
|
modifyTagDtos,
|
||||||
|
queryRunner,
|
||||||
|
null,
|
||||||
|
subspaceModel,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteResults.push({ uuid: dto.subspaceUuid });
|
||||||
|
}
|
||||||
|
|
||||||
|
return deleteResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
async modifySubSpace(
|
||||||
|
subspaceDtos: ModifySubspaceDto[],
|
||||||
|
space: SpaceEntity,
|
||||||
|
queryRunner: QueryRunner,
|
||||||
|
): Promise<void> {
|
||||||
|
for (const subspace of subspaceDtos) {
|
||||||
|
switch (subspace.action) {
|
||||||
|
case ModifyAction.ADD:
|
||||||
|
await this.handleAddAction(subspace, space, queryRunner);
|
||||||
|
break;
|
||||||
|
case ModifyAction.UPDATE:
|
||||||
|
await this.handleUpdateAction(subspace, queryRunner);
|
||||||
|
break;
|
||||||
|
case ModifyAction.DELETE:
|
||||||
|
await this.handleDeleteAction(subspace, queryRunner);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new HttpException(
|
||||||
|
`Invalid action "${subspace.action}".`,
|
||||||
|
HttpStatus.BAD_REQUEST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleAddAction(
|
||||||
|
subspace: ModifySubspaceDto,
|
||||||
|
space: SpaceEntity,
|
||||||
|
queryRunner: QueryRunner,
|
||||||
|
): Promise<void> {
|
||||||
|
const createTagDtos: CreateTagDto[] =
|
||||||
|
subspace.tags?.map((tag) => ({
|
||||||
|
tag: tag.tag as string,
|
||||||
|
productUuid: tag.productUuid as string,
|
||||||
|
})) || [];
|
||||||
|
await this.createSubspacesFromDto(
|
||||||
|
[{ subspaceName: subspace.subspaceName, tags: createTagDtos }],
|
||||||
|
space,
|
||||||
|
queryRunner,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleUpdateAction(
|
||||||
|
modifyDto: ModifySubspaceDto,
|
||||||
|
queryRunner: QueryRunner,
|
||||||
|
): Promise<void> {
|
||||||
|
const subspace = await this.findOne(modifyDto.uuid);
|
||||||
|
|
||||||
|
await this.updateSubspaceName(
|
||||||
|
queryRunner,
|
||||||
|
subspace,
|
||||||
|
modifyDto.subspaceName,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (modifyDto.tags?.length) {
|
||||||
|
await this.tagService.modifyTags(
|
||||||
|
modifyDto.tags,
|
||||||
|
queryRunner,
|
||||||
|
null,
|
||||||
|
subspace,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleDeleteAction(
|
||||||
|
subspace: ModifySubspaceDto,
|
||||||
|
queryRunner: QueryRunner,
|
||||||
|
): Promise<void> {
|
||||||
|
const subspaceModel = await this.findOne(subspace.uuid);
|
||||||
|
|
||||||
|
await queryRunner.manager.update(
|
||||||
|
this.subspaceRepository.target,
|
||||||
|
{ uuid: subspace.uuid },
|
||||||
|
{ disabled: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
if (subspaceModel.tags?.length) {
|
||||||
|
const modifyTagDtos = subspaceModel.tags.map((tag) => ({
|
||||||
|
uuid: tag.uuid,
|
||||||
|
action: ModifyAction.DELETE,
|
||||||
|
}));
|
||||||
|
await this.tagService.modifyTags(
|
||||||
|
modifyTagDtos,
|
||||||
|
queryRunner,
|
||||||
|
null,
|
||||||
|
subspaceModel,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async findOne(subspaceUuid: string): Promise<SubspaceEntity> {
|
||||||
|
const subspace = await this.subspaceRepository.findOne({
|
||||||
|
where: { uuid: subspaceUuid },
|
||||||
|
relations: ['tags'],
|
||||||
|
});
|
||||||
|
if (!subspace) {
|
||||||
|
throw new HttpException(
|
||||||
|
`SubspaceModel with UUID ${subspaceUuid} not found.`,
|
||||||
|
HttpStatus.NOT_FOUND,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return subspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async updateSubspaceName(
|
||||||
|
queryRunner: QueryRunner,
|
||||||
|
subSpace: SubspaceEntity,
|
||||||
|
subspaceName?: string,
|
||||||
|
): Promise<void> {
|
||||||
|
if (subspaceName) {
|
||||||
|
subSpace.subspaceName = subspaceName;
|
||||||
|
await queryRunner.manager.save(subSpace);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
src/space/services/tag/index.ts
Normal file
1
src/space/services/tag/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './tag.service';
|
||||||
237
src/space/services/tag/tag.service.ts
Normal file
237
src/space/services/tag/tag.service.ts
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
import { ModifyAction } from '@app/common/constants/modify-action.enum';
|
||||||
|
import {
|
||||||
|
SpaceEntity,
|
||||||
|
SubspaceEntity,
|
||||||
|
TagEntity,
|
||||||
|
TagRepository,
|
||||||
|
} from '@app/common/modules/space';
|
||||||
|
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||||
|
import { ProductService } from 'src/product/services';
|
||||||
|
import { CreateTagDto } from 'src/space/dtos';
|
||||||
|
import { ModifyTagDto } from 'src/space/dtos/tag/modify-tag.dto';
|
||||||
|
import { QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TagService {
|
||||||
|
constructor(
|
||||||
|
private readonly tagRepository: TagRepository,
|
||||||
|
private readonly productService: ProductService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async createTags(
|
||||||
|
tags: CreateTagDto[],
|
||||||
|
queryRunner: QueryRunner,
|
||||||
|
space?: SpaceEntity,
|
||||||
|
subspace?: SubspaceEntity,
|
||||||
|
additionalTags?: CreateTagDto[],
|
||||||
|
): Promise<TagEntity[]> {
|
||||||
|
if (!tags.length) {
|
||||||
|
throw new HttpException('Tags cannot be empty.', HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
const combinedTags = additionalTags ? [...tags, ...additionalTags] : tags;
|
||||||
|
const duplicateTags = this.findDuplicateTags(combinedTags);
|
||||||
|
|
||||||
|
if (duplicateTags.length > 0) {
|
||||||
|
throw new HttpException(
|
||||||
|
`Duplicate tags found for the same product: ${duplicateTags.join(', ')}`,
|
||||||
|
HttpStatus.BAD_REQUEST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const tagEntities = await Promise.all(
|
||||||
|
tags.map(async (tagDto) =>
|
||||||
|
this.prepareTagEntity(tagDto, queryRunner, space, subspace),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
return await queryRunner.manager.save(tagEntities);
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof HttpException) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new HttpException(
|
||||||
|
'Failed to save tag models due to an unexpected error.',
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateTag(
|
||||||
|
tag: ModifyTagDto,
|
||||||
|
queryRunner: QueryRunner,
|
||||||
|
space?: SpaceEntity,
|
||||||
|
subspace?: SubspaceEntity,
|
||||||
|
): Promise<TagEntity> {
|
||||||
|
try {
|
||||||
|
const existingTag = await this.getTagByUuid(tag.uuid);
|
||||||
|
|
||||||
|
if (space) {
|
||||||
|
await this.checkTagReuse(tag.tag, existingTag.product.uuid, space);
|
||||||
|
} else {
|
||||||
|
await this.checkTagReuse(
|
||||||
|
tag.tag,
|
||||||
|
existingTag.product.uuid,
|
||||||
|
subspace.space,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag.tag) {
|
||||||
|
existingTag.tag = tag.tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
return await queryRunner.manager.save(existingTag);
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof HttpException) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
throw new HttpException(
|
||||||
|
error.message || 'Failed to update tags',
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteTags(tagUuids: string[], queryRunner: QueryRunner) {
|
||||||
|
try {
|
||||||
|
const deletePromises = tagUuids.map((id) =>
|
||||||
|
queryRunner.manager.softDelete(this.tagRepository.target, id),
|
||||||
|
);
|
||||||
|
|
||||||
|
await Promise.all(deletePromises);
|
||||||
|
return { message: 'Tags deleted successfully', tagUuids };
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof HttpException) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
throw new HttpException(
|
||||||
|
error.message || 'Failed to delete tags',
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private findDuplicateTags(tags: CreateTagDto[]): string[] {
|
||||||
|
const seen = new Map<string, boolean>();
|
||||||
|
const duplicates: string[] = [];
|
||||||
|
|
||||||
|
tags.forEach((tagDto) => {
|
||||||
|
const key = `${tagDto.productUuid}-${tagDto.tag}`;
|
||||||
|
if (seen.has(key)) {
|
||||||
|
duplicates.push(`${tagDto.tag} for Product: ${tagDto.productUuid}`);
|
||||||
|
} else {
|
||||||
|
seen.set(key, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return duplicates;
|
||||||
|
}
|
||||||
|
|
||||||
|
async modifyTags(
|
||||||
|
tags: ModifyTagDto[],
|
||||||
|
queryRunner: QueryRunner,
|
||||||
|
space?: SpaceEntity,
|
||||||
|
subspace?: SubspaceEntity,
|
||||||
|
): Promise<void> {
|
||||||
|
try {
|
||||||
|
console.log(tags);
|
||||||
|
for (const tag of tags) {
|
||||||
|
if (tag.action === ModifyAction.ADD) {
|
||||||
|
const createTagDto: CreateTagDto = {
|
||||||
|
tag: tag.tag as string,
|
||||||
|
productUuid: tag.productUuid as string,
|
||||||
|
};
|
||||||
|
|
||||||
|
await this.createTags([createTagDto], queryRunner, space, subspace);
|
||||||
|
} else if (tag.action === ModifyAction.UPDATE) {
|
||||||
|
await this.updateTag(tag, queryRunner, space, subspace);
|
||||||
|
} else if (tag.action === ModifyAction.DELETE) {
|
||||||
|
await queryRunner.manager.update(
|
||||||
|
this.tagRepository.target,
|
||||||
|
{ uuid: tag.uuid },
|
||||||
|
{ disabled: true },
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw new HttpException(
|
||||||
|
`Invalid action "${tag.action}" provided.`,
|
||||||
|
HttpStatus.BAD_REQUEST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof HttpException) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new HttpException(
|
||||||
|
`An error occurred while modifying tags: ${error.message}`,
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async checkTagReuse(
|
||||||
|
tag: string,
|
||||||
|
productUuid: string,
|
||||||
|
space: SpaceEntity,
|
||||||
|
): Promise<void> {
|
||||||
|
const isTagInSpace = await this.tagRepository.exists({
|
||||||
|
where: { tag, space, product: { uuid: productUuid } },
|
||||||
|
});
|
||||||
|
const isTagInSubspace = await this.tagRepository.exists({
|
||||||
|
where: {
|
||||||
|
tag,
|
||||||
|
subspace: { space },
|
||||||
|
product: { uuid: productUuid },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isTagInSpace || isTagInSubspace) {
|
||||||
|
throw new HttpException(`Tag can't be reused`, HttpStatus.CONFLICT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async prepareTagEntity(
|
||||||
|
tagDto: CreateTagDto,
|
||||||
|
queryRunner: QueryRunner,
|
||||||
|
space?: SpaceEntity,
|
||||||
|
subspace?: SubspaceEntity,
|
||||||
|
): Promise<TagEntity> {
|
||||||
|
const product = await this.productService.findOne(tagDto.productUuid);
|
||||||
|
|
||||||
|
if (!product) {
|
||||||
|
throw new HttpException(
|
||||||
|
`Product with UUID ${tagDto.productUuid} not found.`,
|
||||||
|
HttpStatus.NOT_FOUND,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (space) {
|
||||||
|
await this.checkTagReuse(tagDto.tag, tagDto.productUuid, space);
|
||||||
|
} else {
|
||||||
|
await this.checkTagReuse(tagDto.tag, tagDto.productUuid, subspace.space);
|
||||||
|
}
|
||||||
|
|
||||||
|
return queryRunner.manager.create(TagEntity, {
|
||||||
|
tag: tagDto.tag,
|
||||||
|
product: product.data,
|
||||||
|
space,
|
||||||
|
subspace,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getTagByUuid(uuid: string): Promise<TagEntity> {
|
||||||
|
const tag = await this.tagRepository.findOne({
|
||||||
|
where: { uuid },
|
||||||
|
relations: ['product'],
|
||||||
|
});
|
||||||
|
if (!tag) {
|
||||||
|
throw new HttpException(
|
||||||
|
`Tag with ID ${uuid} not found.`,
|
||||||
|
HttpStatus.NOT_FOUND,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -21,6 +21,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
SpaceRepository,
|
SpaceRepository,
|
||||||
SpaceLinkRepository,
|
SpaceLinkRepository,
|
||||||
|
TagRepository,
|
||||||
} from '@app/common/modules/space/repositories';
|
} from '@app/common/modules/space/repositories';
|
||||||
import { CommunityRepository } from '@app/common/modules/community/repositories';
|
import { CommunityRepository } from '@app/common/modules/community/repositories';
|
||||||
import {
|
import {
|
||||||
@ -40,10 +41,14 @@ import { DeviceStatusFirebaseService } from '@app/common/firebase/devices-status
|
|||||||
import { DeviceStatusLogRepository } from '@app/common/modules/device-status-log/repositories';
|
import { DeviceStatusLogRepository } from '@app/common/modules/device-status-log/repositories';
|
||||||
import { SceneDeviceRepository } from '@app/common/modules/scene-device/repositories';
|
import { SceneDeviceRepository } from '@app/common/modules/scene-device/repositories';
|
||||||
import { ProjectRepository } from '@app/common/modules/project/repositiories';
|
import { ProjectRepository } from '@app/common/modules/project/repositiories';
|
||||||
import { SpaceModelRepository } from '@app/common/modules/space-model';
|
import {
|
||||||
|
SpaceModelRepository,
|
||||||
|
TagModelRepository,
|
||||||
|
} from '@app/common/modules/space-model';
|
||||||
import { CommunityModule } from 'src/community/community.module';
|
import { CommunityModule } from 'src/community/community.module';
|
||||||
import { ValidationService } from './services';
|
import { ValidationService } from './services';
|
||||||
import { SubspaceRepository } from '@app/common/modules/space/repositories/subspace.repository';
|
import { SubspaceRepository } from '@app/common/modules/space/repositories/subspace.repository';
|
||||||
|
import { TagService } from './services/tag';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [ConfigModule, SpaceRepositoryModule, CommunityModule],
|
imports: [ConfigModule, SpaceRepositoryModule, CommunityModule],
|
||||||
@ -57,8 +62,11 @@ import { SubspaceRepository } from '@app/common/modules/space/repositories/subsp
|
|||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
ValidationService,
|
ValidationService,
|
||||||
|
TagModelRepository,
|
||||||
|
TagRepository,
|
||||||
SpaceService,
|
SpaceService,
|
||||||
TuyaService,
|
TuyaService,
|
||||||
|
TagService,
|
||||||
ProductRepository,
|
ProductRepository,
|
||||||
SubSpaceService,
|
SubSpaceService,
|
||||||
SpaceDeviceService,
|
SpaceDeviceService,
|
||||||
|
|||||||
Reference in New Issue
Block a user