mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-11-26 12:34:54 +00:00
added tag action
This commit is contained in:
5
libs/common/src/constants/modify-action.enum.ts
Normal file
5
libs/common/src/constants/modify-action.enum.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export enum ModifyAction {
|
||||||
|
ADD = 'add',
|
||||||
|
UPDATE = 'update',
|
||||||
|
DELETE = 'delete',
|
||||||
|
}
|
||||||
@ -26,4 +26,10 @@ export class TagModel extends AbstractEntity<TagModelDto> {
|
|||||||
})
|
})
|
||||||
@JoinColumn({ name: 'subspace_id' })
|
@JoinColumn({ name: 'subspace_id' })
|
||||||
subspaceModel: SubspaceModelEntity;
|
subspaceModel: SubspaceModelEntity;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
nullable: false,
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
|
public disabled: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
export * from './delete-subspace-model.dto';
|
export * from './delete-subspace-model.dto';
|
||||||
export * from './create-subspace-model.dto';
|
export * from './create-subspace-model.dto';
|
||||||
export * from './update-subspace-model.dto';
|
export * from './update-subspace-model.dto';
|
||||||
|
export * from './modify-subspace-model.dto';
|
||||||
|
|||||||
@ -0,0 +1,40 @@
|
|||||||
|
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||||
|
import { Type } from 'class-transformer';
|
||||||
|
import { IsString, IsOptional, IsArray, ValidateNested } from 'class-validator';
|
||||||
|
import { ModifyTagModelDto } from '../tag-model-dtos';
|
||||||
|
|
||||||
|
export class ModifySubspaceModelDto {
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'Action to perform: add, update, or delete',
|
||||||
|
example: 'add',
|
||||||
|
})
|
||||||
|
@IsString()
|
||||||
|
action: 'add' | 'update' | 'delete';
|
||||||
|
|
||||||
|
@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: [ModifyTagModelDto],
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsArray()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@Type(() => ModifyTagModelDto)
|
||||||
|
tags?: ModifyTagModelDto[];
|
||||||
|
}
|
||||||
@ -1,2 +1,3 @@
|
|||||||
export * from './create-tag-model.dto';
|
export * from './create-tag-model.dto';
|
||||||
export * from './update-tag-model.dto';
|
export * from './update-tag-model.dto';
|
||||||
|
export * from './modify-tag-model.dto';
|
||||||
|
|||||||
37
src/space-model/dtos/tag-model-dtos/modify-tag-model.dto.ts
Normal file
37
src/space-model/dtos/tag-model-dtos/modify-tag-model.dto.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { ModifyAction } from '@app/common/constants/modify-action.enum';
|
||||||
|
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||||
|
import { IsString, IsOptional, IsEnum } from 'class-validator';
|
||||||
|
|
||||||
|
export class ModifyTagModelDto {
|
||||||
|
@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,11 +1,13 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||||
import { IsArray, IsOptional, IsString, ValidateNested } from 'class-validator';
|
import { IsArray, IsOptional, IsString, ValidateNested } from 'class-validator';
|
||||||
import { CreateSubspaceModelDto } from './subspaces-model-dtos/create-subspace-model.dto';
|
import { CreateSubspaceModelDto } from './subspaces-model-dtos/create-subspace-model.dto';
|
||||||
import { Type } from 'class-transformer';
|
import { Type } from 'class-transformer';
|
||||||
import {
|
import {
|
||||||
DeleteSubspaceModelDto,
|
DeleteSubspaceModelDto,
|
||||||
|
ModifySubspaceModelDto,
|
||||||
UpdateSubspaceModelDto,
|
UpdateSubspaceModelDto,
|
||||||
} from './subspaces-model-dtos';
|
} from './subspaces-model-dtos';
|
||||||
|
import { ModifyTagModelDto } from './tag-model-dtos';
|
||||||
|
|
||||||
export class ModifySubspacesModelDto {
|
export class ModifySubspacesModelDto {
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
@ -51,6 +53,24 @@ export class UpdateSpaceModelDto {
|
|||||||
@IsString()
|
@IsString()
|
||||||
modelName?: string;
|
modelName?: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description: 'List of subspace modifications (add/update/delete)',
|
||||||
|
type: [ModifySubspaceModelDto],
|
||||||
|
})
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
subspaceModels?: ModifySubspacesModelDto;
|
@IsArray()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@Type(() => ModifySubspaceModelDto)
|
||||||
|
subspaceModels?: ModifySubspaceModelDto[];
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description:
|
||||||
|
'List of tag modifications (add/update/delete) for the space model',
|
||||||
|
type: [ModifyTagModelDto],
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsArray()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@Type(() => ModifyTagModelDto)
|
||||||
|
tags?: ModifyTagModelDto[];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,16 +42,7 @@ export class SpaceModelService {
|
|||||||
try {
|
try {
|
||||||
const project = await this.validateProject(params.projectUuid);
|
const project = await this.validateProject(params.projectUuid);
|
||||||
|
|
||||||
const isModelExist = await this.validateName(
|
await this.validateName(modelName, params.projectUuid);
|
||||||
modelName,
|
|
||||||
params.projectUuid,
|
|
||||||
);
|
|
||||||
if (isModelExist) {
|
|
||||||
throw new HttpException(
|
|
||||||
`Model name "${modelName}" already exists in this project ${params.projectUuid}.`,
|
|
||||||
HttpStatus.CONFLICT,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const spaceModel = this.spaceModelRepository.create({
|
const spaceModel = this.spaceModelRepository.create({
|
||||||
modelName,
|
modelName,
|
||||||
@ -148,9 +139,11 @@ export class SpaceModelService {
|
|||||||
await queryRunner.startTransaction();
|
await queryRunner.startTransaction();
|
||||||
try {
|
try {
|
||||||
const { modelName } = dto;
|
const { modelName } = dto;
|
||||||
if (modelName) spaceModel.modelName = modelName;
|
if (modelName) {
|
||||||
|
await this.validateName(modelName, param.projectUuid);
|
||||||
await queryRunner.manager.save(spaceModel);
|
spaceModel.modelName = modelName;
|
||||||
|
await queryRunner.manager.save(spaceModel);
|
||||||
|
}
|
||||||
|
|
||||||
if (dto.subspaceModels) {
|
if (dto.subspaceModels) {
|
||||||
await this.subSpaceModelService.modifySubSpaceModels(
|
await this.subSpaceModelService.modifySubSpaceModels(
|
||||||
@ -159,7 +152,6 @@ export class SpaceModelService {
|
|||||||
queryRunner,
|
queryRunner,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await queryRunner.commitTransaction();
|
await queryRunner.commitTransaction();
|
||||||
|
|
||||||
return new SuccessResponseDto({
|
return new SuccessResponseDto({
|
||||||
@ -177,11 +169,17 @@ export class SpaceModelService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async validateName(modelName: string, projectUuid: string): Promise<boolean> {
|
async validateName(modelName: string, projectUuid: string): Promise<void> {
|
||||||
const isModelExist = await this.spaceModelRepository.exists({
|
const isModelExist = await this.spaceModelRepository.findOne({
|
||||||
where: { modelName, project: { uuid: projectUuid } },
|
where: { modelName, project: { uuid: projectUuid } },
|
||||||
});
|
});
|
||||||
return isModelExist;
|
|
||||||
|
if (isModelExist) {
|
||||||
|
throw new HttpException(
|
||||||
|
`Model name ${modelName} already exists in the project with UUID ${projectUuid}.`,
|
||||||
|
HttpStatus.CONFLICT,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async validateSpaceModel(uuid: string): Promise<SpaceModelEntity> {
|
async validateSpaceModel(uuid: string): Promise<SpaceModelEntity> {
|
||||||
|
|||||||
@ -7,16 +7,17 @@ import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
|||||||
import {
|
import {
|
||||||
CreateSubspaceModelDto,
|
CreateSubspaceModelDto,
|
||||||
UpdateSubspaceModelDto,
|
UpdateSubspaceModelDto,
|
||||||
ModifySubspacesModelDto,
|
|
||||||
CreateTagModelDto,
|
CreateTagModelDto,
|
||||||
} from '../../dtos';
|
} from '../../dtos';
|
||||||
import { QueryRunner } from 'typeorm';
|
import { QueryRunner } from 'typeorm';
|
||||||
import {
|
import {
|
||||||
IDeletedSubsaceModelInterface,
|
IDeletedSubsaceModelInterface,
|
||||||
IModifySubspaceModelInterface,
|
|
||||||
IUpdateSubspaceModelInterface,
|
IUpdateSubspaceModelInterface,
|
||||||
} from 'src/space-model/interfaces';
|
} from 'src/space-model/interfaces';
|
||||||
import { DeleteSubspaceModelDto } from 'src/space-model/dtos/subspaces-model-dtos';
|
import {
|
||||||
|
DeleteSubspaceModelDto,
|
||||||
|
ModifySubspaceModelDto,
|
||||||
|
} from 'src/space-model/dtos/subspaces-model-dtos';
|
||||||
import { TagModelService } from '../tag-model.service';
|
import { TagModelService } from '../tag-model.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -25,11 +26,12 @@ export class SubSpaceModelService {
|
|||||||
private readonly subspaceModelRepository: SubspaceModelRepository,
|
private readonly subspaceModelRepository: SubspaceModelRepository,
|
||||||
private readonly tagModelService: TagModelService,
|
private readonly tagModelService: TagModelService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async createSubSpaceModels(
|
async createSubSpaceModels(
|
||||||
subSpaceModelDtos: CreateSubspaceModelDto[],
|
subSpaceModelDtos: CreateSubspaceModelDto[],
|
||||||
spaceModel: SpaceModelEntity,
|
spaceModel: SpaceModelEntity,
|
||||||
queryRunner: QueryRunner,
|
queryRunner: QueryRunner,
|
||||||
otherTags: CreateTagModelDto[],
|
otherTags?: CreateTagModelDto[],
|
||||||
): Promise<SubspaceModelEntity[]> {
|
): Promise<SubspaceModelEntity[]> {
|
||||||
this.validateInputDtos(subSpaceModelDtos);
|
this.validateInputDtos(subSpaceModelDtos);
|
||||||
|
|
||||||
@ -62,6 +64,9 @@ export class SubSpaceModelService {
|
|||||||
|
|
||||||
return savedSubspaces;
|
return savedSubspaces;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
if (error instanceof HttpException) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
error.message || 'Failed to create subspaces.',
|
error.message || 'Failed to create subspaces.',
|
||||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
@ -183,7 +188,6 @@ export class SubSpaceModelService {
|
|||||||
where: {
|
where: {
|
||||||
uuid: subspaceUuid,
|
uuid: subspaceUuid,
|
||||||
},
|
},
|
||||||
relations: ['productModels', 'productModels.itemModels'],
|
|
||||||
});
|
});
|
||||||
if (!subspace) {
|
if (!subspace) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
@ -226,43 +230,49 @@ export class SubSpaceModelService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async modifySubSpaceModels(
|
async modifySubSpaceModels(
|
||||||
dto: ModifySubspacesModelDto,
|
subspaceDtos: ModifySubspaceModelDto[],
|
||||||
spaceModel: SpaceModelEntity,
|
spaceModel: SpaceModelEntity,
|
||||||
queryRunner: QueryRunner,
|
queryRunner: QueryRunner,
|
||||||
): Promise<IModifySubspaceModelInterface> {
|
) {
|
||||||
const subspaces: IModifySubspaceModelInterface = {
|
|
||||||
spaceModelUuid: spaceModel.uuid,
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const actions = [];
|
for (const subspace of subspaceDtos) {
|
||||||
|
if (subspace.action === 'add') {
|
||||||
|
const createTagDtos: CreateTagModelDto[] =
|
||||||
|
subspace.tags?.map((tag) => ({
|
||||||
|
tag: tag.tag as string,
|
||||||
|
productUuid: tag.productUuid as string,
|
||||||
|
})) || [];
|
||||||
|
await this.createSubSpaceModels(
|
||||||
|
[{ subspaceName: subspace.subspaceName, tags: createTagDtos }],
|
||||||
|
spaceModel,
|
||||||
|
queryRunner,
|
||||||
|
);
|
||||||
|
} else if (subspace.action === 'update') {
|
||||||
|
const existingSubspace = await this.findOne(subspace.uuid);
|
||||||
|
|
||||||
if (dto.add) {
|
if (!existingSubspace) {
|
||||||
|
throw new HttpException(
|
||||||
|
`Subspace with ID ${subspace.uuid} not found.`,
|
||||||
|
HttpStatus.NOT_FOUND,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
existingSubspace.subspaceName =
|
||||||
|
subspace.subspaceName || existingSubspace.subspaceName;
|
||||||
|
|
||||||
|
const updatedSubspace =
|
||||||
|
await queryRunner.manager.save(existingSubspace);
|
||||||
|
|
||||||
|
if (subspace.tags) {
|
||||||
|
await this.tagModelService.modifyTags(
|
||||||
|
subspace.tags,
|
||||||
|
queryRunner,
|
||||||
|
null,
|
||||||
|
updatedSubspace,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dto.update) {
|
|
||||||
actions.push(
|
|
||||||
this.updateSubspaceModels(dto.update, spaceModel, queryRunner).then(
|
|
||||||
(updatedSubspaces) => {
|
|
||||||
subspaces.update = updatedSubspaces;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dto.delete) {
|
|
||||||
actions.push(
|
|
||||||
this.deleteSubspaceModels(dto.delete, queryRunner).then(
|
|
||||||
(deletedSubspaces) => {
|
|
||||||
subspaces.delete = deletedSubspaces;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await Promise.all(actions);
|
|
||||||
|
|
||||||
return subspaces;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
error.message || 'Failed to modify SpaceModels',
|
error.message || 'Failed to modify SpaceModels',
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import {
|
|||||||
} from '@app/common/modules/space-model/entities';
|
} from '@app/common/modules/space-model/entities';
|
||||||
import { SubspaceModelEntity } from '@app/common/modules/space-model/entities';
|
import { SubspaceModelEntity } from '@app/common/modules/space-model/entities';
|
||||||
import { TagModelRepository } from '@app/common/modules/space-model';
|
import { TagModelRepository } from '@app/common/modules/space-model';
|
||||||
import { CreateTagModelDto, UpdateTagModelDto } from '../dtos';
|
import { CreateTagModelDto, ModifyTagModelDto } from '../dtos';
|
||||||
import { ProductService } from 'src/product/services';
|
import { ProductService } from 'src/product/services';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -21,44 +21,34 @@ export class TagModelService {
|
|||||||
queryRunner: QueryRunner,
|
queryRunner: QueryRunner,
|
||||||
spaceModel?: SpaceModelEntity,
|
spaceModel?: SpaceModelEntity,
|
||||||
subspaceModel?: SubspaceModelEntity,
|
subspaceModel?: SubspaceModelEntity,
|
||||||
otherTags?: CreateTagModelDto[],
|
additionalTags?: CreateTagModelDto[],
|
||||||
): Promise<TagModel[]> {
|
): Promise<TagModel[]> {
|
||||||
let alltags: CreateTagModelDto[] = [];
|
|
||||||
if (!tags.length) {
|
if (!tags.length) {
|
||||||
throw new HttpException('Tags cannot be empty.', HttpStatus.BAD_REQUEST);
|
throw new HttpException('Tags cannot be empty.', HttpStatus.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
if (otherTags) {
|
|
||||||
alltags = [...tags, ...otherTags];
|
const combinedTags = additionalTags ? [...tags, ...additionalTags] : tags;
|
||||||
}
|
const duplicateTags = this.findDuplicateTags(combinedTags);
|
||||||
const duplicates = this.checkForDuplicates(alltags);
|
|
||||||
if (duplicates.length > 0) {
|
if (duplicateTags.length > 0) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
`Duplicate tags found for the same product: ${duplicates.join(', ')}`,
|
`Duplicate tags found for the same product: ${duplicateTags.join(', ')}`,
|
||||||
HttpStatus.BAD_REQUEST,
|
HttpStatus.BAD_REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const tagEntities = await Promise.all(
|
const tagEntities = await Promise.all(
|
||||||
tags.map(async (tagDto) => {
|
tags.map(async (tagDto) =>
|
||||||
const product = await this.productService.findOne(tagDto.productUuid);
|
this.prepareTagEntity(tagDto, queryRunner, spaceModel, subspaceModel),
|
||||||
if (!product) {
|
),
|
||||||
throw new HttpException(
|
|
||||||
`Product with UUID ${tagDto.productUuid} not found.`,
|
|
||||||
HttpStatus.NOT_FOUND,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return queryRunner.manager.create(TagModel, {
|
|
||||||
tag: tagDto.tag,
|
|
||||||
product: product.data,
|
|
||||||
spaceModel,
|
|
||||||
subspaceModel,
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return await queryRunner.manager.save(tagEntities);
|
return await queryRunner.manager.save(tagEntities);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
if (error instanceof HttpException) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
'Failed to save tag models due to an unexpected error.',
|
'Failed to save tag models due to an unexpected error.',
|
||||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
@ -66,27 +56,34 @@ export class TagModelService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateTags(tags: UpdateTagModelDto[], queryRunner: QueryRunner) {
|
async updateTag(
|
||||||
|
tag: ModifyTagModelDto,
|
||||||
|
queryRunner: QueryRunner,
|
||||||
|
spaceModel?: SpaceModelEntity,
|
||||||
|
subspaceModel?: SubspaceModelEntity,
|
||||||
|
): Promise<TagModel> {
|
||||||
try {
|
try {
|
||||||
const updatePromises = tags.map(async (tagDto) => {
|
const existingTag = await this.getTagByUuid(tag.uuid);
|
||||||
const existingTag = await this.tagModelRepository.findOne({
|
|
||||||
where: { uuid: tagDto.uuid },
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!existingTag) {
|
if (spaceModel) {
|
||||||
throw new HttpException(
|
await this.checkTagReuse(tag.tag, existingTag.product.uuid, spaceModel);
|
||||||
`Tag with ID ${tagDto.uuid} not found`,
|
} else {
|
||||||
HttpStatus.NOT_FOUND,
|
await this.checkTagReuse(
|
||||||
);
|
tag.tag,
|
||||||
}
|
existingTag.product.uuid,
|
||||||
|
subspaceModel.spaceModel,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
existingTag.tag = tagDto.tag || existingTag.tag;
|
if (tag.tag) {
|
||||||
|
existingTag.tag = tag.tag;
|
||||||
|
}
|
||||||
|
|
||||||
return queryRunner.manager.save(existingTag);
|
return await queryRunner.manager.save(existingTag);
|
||||||
});
|
|
||||||
|
|
||||||
return await Promise.all(updatePromises);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
if (error instanceof HttpException) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
error.message || 'Failed to update tags',
|
error.message || 'Failed to update tags',
|
||||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
@ -103,6 +100,9 @@ export class TagModelService {
|
|||||||
await Promise.all(deletePromises);
|
await Promise.all(deletePromises);
|
||||||
return { message: 'Tags deleted successfully', tagUuids };
|
return { message: 'Tags deleted successfully', tagUuids };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
if (error instanceof HttpException) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
error.message || 'Failed to delete tags',
|
error.message || 'Failed to delete tags',
|
||||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
@ -110,7 +110,7 @@ export class TagModelService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private checkForDuplicates(tags: CreateTagModelDto[]): string[] {
|
private findDuplicateTags(tags: CreateTagModelDto[]): string[] {
|
||||||
const seen = new Map<string, boolean>();
|
const seen = new Map<string, boolean>();
|
||||||
const duplicates: string[] = [];
|
const duplicates: string[] = [];
|
||||||
|
|
||||||
@ -125,4 +125,119 @@ export class TagModelService {
|
|||||||
|
|
||||||
return duplicates;
|
return duplicates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async modifyTags(
|
||||||
|
tags: ModifyTagModelDto[],
|
||||||
|
queryRunner: QueryRunner,
|
||||||
|
spaceModel?: SpaceModelEntity,
|
||||||
|
subspaceModel?: SubspaceModelEntity,
|
||||||
|
): Promise<void> {
|
||||||
|
try {
|
||||||
|
for (const tag of tags) {
|
||||||
|
if (tag.action === 'add') {
|
||||||
|
const createTagDto: CreateTagModelDto = {
|
||||||
|
tag: tag.tag as string,
|
||||||
|
productUuid: tag.productUuid as string,
|
||||||
|
};
|
||||||
|
|
||||||
|
await this.createTags(
|
||||||
|
[createTagDto],
|
||||||
|
queryRunner,
|
||||||
|
spaceModel,
|
||||||
|
subspaceModel,
|
||||||
|
);
|
||||||
|
} else if (tag.action === 'update') {
|
||||||
|
await this.updateTag(tag, queryRunner, spaceModel, subspaceModel);
|
||||||
|
} else if (tag.action === 'delete') {
|
||||||
|
await queryRunner.manager.update(
|
||||||
|
this.tagModelRepository.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,
|
||||||
|
spaceModel: SpaceModelEntity,
|
||||||
|
): Promise<void> {
|
||||||
|
const isTagInSpaceModel = await this.tagModelRepository.exists({
|
||||||
|
where: { tag, spaceModel, product: { uuid: productUuid } },
|
||||||
|
});
|
||||||
|
const isTagInSubspaceModel = await this.tagModelRepository.exists({
|
||||||
|
where: {
|
||||||
|
tag,
|
||||||
|
subspaceModel: { spaceModel },
|
||||||
|
product: { uuid: productUuid },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isTagInSpaceModel || isTagInSubspaceModel) {
|
||||||
|
throw new HttpException(`Tag can't be reused`, HttpStatus.CONFLICT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async prepareTagEntity(
|
||||||
|
tagDto: CreateTagModelDto,
|
||||||
|
queryRunner: QueryRunner,
|
||||||
|
spaceModel?: SpaceModelEntity,
|
||||||
|
subspaceModel?: SubspaceModelEntity,
|
||||||
|
): Promise<TagModel> {
|
||||||
|
const product = await this.productService.findOne(tagDto.productUuid);
|
||||||
|
|
||||||
|
if (!product) {
|
||||||
|
throw new HttpException(
|
||||||
|
`Product with UUID ${tagDto.productUuid} not found.`,
|
||||||
|
HttpStatus.NOT_FOUND,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spaceModel) {
|
||||||
|
await this.checkTagReuse(tagDto.tag, tagDto.productUuid, spaceModel);
|
||||||
|
} else {
|
||||||
|
await this.checkTagReuse(
|
||||||
|
tagDto.tag,
|
||||||
|
tagDto.productUuid,
|
||||||
|
subspaceModel.spaceModel,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return queryRunner.manager.create(TagModel, {
|
||||||
|
tag: tagDto.tag,
|
||||||
|
product: product.data,
|
||||||
|
spaceModel,
|
||||||
|
subspaceModel,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getTagByUuid(uuid: string): Promise<TagModel> {
|
||||||
|
const tag = await this.tagModelRepository.findOne({
|
||||||
|
where: { uuid },
|
||||||
|
relations: ['product'],
|
||||||
|
});
|
||||||
|
if (!tag) {
|
||||||
|
throw new HttpException(
|
||||||
|
`Tag with ID ${uuid} not found.`,
|
||||||
|
HttpStatus.NOT_FOUND,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user