fixed moving tags

This commit is contained in:
hannathkadher
2025-01-27 12:54:38 +04:00
parent c1aa5232c7
commit be60e02b99
3 changed files with 140 additions and 42 deletions

View File

@ -1,11 +1,4 @@
import {
Column,
Entity,
JoinColumn,
ManyToOne,
OneToMany,
Unique,
} from 'typeorm';
import { Column, Entity, JoinColumn, ManyToOne, OneToMany } from 'typeorm';
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
import { TagModelDto } from '../dtos/tag-model.dto';
import { SpaceModelEntity } from './space-model.entity';
@ -14,7 +7,6 @@ import { ProductEntity } from '../../product/entities';
import { TagEntity } from '../../space/entities/tag.entity';
@Entity({ name: 'tag_model' })
@Unique(['tag', 'product', 'spaceModel', 'subspaceModel'])
export class TagModel extends AbstractEntity<TagModelDto> {
@Column({ type: 'varchar', length: 255 })
tag: string;

View File

@ -89,8 +89,6 @@ export class SpaceModelService {
statusCode: HttpStatus.CREATED,
});
} catch (error) {
console.log(JSON.stringify(createSpaceModelDto));
await queryRunner.rollbackTransaction();
const errorMessage =
@ -206,12 +204,16 @@ export class SpaceModelService {
dto.tags,
dto.subspaceModels,
);
console.log(spaceTagsAfterMove);
const modifiedSubspaces = this.tagModelService.getModifiedSubspaces(
dto.tags,
dto.subspaceModels,
);
if (dto.subspaceModels) {
modifiedSubspaceModels =
await this.subSpaceModelService.modifySubSpaceModels(
dto.subspaceModels,
modifiedSubspaces,
spaceModel,
queryRunner,
);
@ -243,7 +245,6 @@ export class SpaceModelService {
message: 'SpaceModel updated successfully',
});
} catch (error) {
console.log(JSON.stringify(dto));
await queryRunner.rollbackTransaction();
if (error instanceof HttpException) {
throw error;

View File

@ -28,6 +28,7 @@ export class TagModelService {
spaceModel?: SpaceModelEntity,
subspaceModel?: SubspaceModelEntity,
additionalTags?: CreateTagModelDto[],
tagsToDelete?: ModifyTagModelDto[],
): Promise<TagModel[]> {
if (!tags.length) {
throw new HttpException('Tags cannot be empty.', HttpStatus.BAD_REQUEST);
@ -46,12 +47,14 @@ export class TagModelService {
const tagEntitiesToCreate = tags.filter((tagDto) => tagDto.uuid === null);
const tagEntitiesToUpdate = tags.filter((tagDto) => tagDto.uuid !== null);
try {
const createdTags = await this.bulkSaveTags(
tagEntitiesToCreate,
queryRunner,
spaceModel,
subspaceModel,
tagsToDelete,
);
// Update existing tags
@ -81,6 +84,7 @@ export class TagModelService {
queryRunner: QueryRunner,
spaceModel?: SpaceModelEntity,
subspaceModel?: SubspaceModelEntity,
tagsToDelete?: ModifyTagModelDto[],
): Promise<TagModel[]> {
if (!tags.length) {
return [];
@ -88,7 +92,13 @@ export class TagModelService {
const tagEntities = await Promise.all(
tags.map((tagDto) =>
this.prepareTagEntity(tagDto, queryRunner, spaceModel, subspaceModel),
this.prepareTagEntity(
tagDto,
queryRunner,
spaceModel,
subspaceModel,
tagsToDelete,
),
),
);
@ -116,28 +126,53 @@ export class TagModelService {
return [];
}
return await Promise.all(
tags.map(async (tagDto) => {
const tag = await this.getTagByUuid(tagDto.uuid);
if (!tag) {
throw new HttpException(
`Tag with UUID ${tagDto.uuid} not found.`,
HttpStatus.NOT_FOUND,
);
}
try {
return await Promise.all(
tags.map(async (tagDto) => {
try {
const tag = await this.getTagByUuid(tagDto.uuid);
if (!tag) {
throw new HttpException(
`Tag with UUID ${tagDto.uuid} not found.`,
HttpStatus.NOT_FOUND,
);
}
if (subspaceModel && subspaceModel.spaceModel) {
await queryRunner.manager.update(
this.tagModelRepository.target,
{ uuid: tag.uuid },
{ subspaceModel },
);
tag.subspaceModel = subspaceModel;
}
if (subspaceModel && subspaceModel.spaceModel) {
await queryRunner.manager.update(
this.tagModelRepository.target,
{ uuid: tag.uuid },
{ subspaceModel, spaceModel: null },
);
tag.subspaceModel = subspaceModel;
}
return tag;
}),
);
if (subspaceModel === null && spaceModel) {
await queryRunner.manager.update(
this.tagModelRepository.target,
{ uuid: tag.uuid },
{ subspaceModel: null, spaceModel: spaceModel },
);
tag.subspaceModel = null;
tag.spaceModel = spaceModel;
}
return tag;
} catch (error) {
console.error(
`Error moving tag with UUID ${tagDto.uuid}: ${error.message}`,
);
throw error; // Re-throw the error to propagate it to the parent Promise.all
}
}),
);
} catch (error) {
console.error(`Error in moveTags: ${error.message}`);
throw new HttpException(
`Failed to move tags due to an unexpected error: ${error.message}`,
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async updateTag(
@ -231,6 +266,10 @@ export class TagModelService {
deleted: [],
};
try {
const tagsToDelete = tags.filter(
(tag) => tag.action === ModifyAction.DELETE,
);
for (const tag of tags) {
if (tag.action === ModifyAction.ADD) {
const createTagDto: CreateTagModelDto = {
@ -239,11 +278,14 @@ export class TagModelService {
productUuid: tag.productUuid as string,
};
const newModel = await this.createTags(
[createTagDto],
queryRunner,
spaceModel,
subspaceModel,
null,
tagsToDelete,
);
modifiedTagModels.added.push(...newModel);
} else if (tag.action === ModifyAction.UPDATE) {
@ -285,9 +327,11 @@ export class TagModelService {
tag: string,
productUuid: string,
spaceModel: SpaceModelEntity,
tagsToDelete?: ModifyTagModelDto[],
): Promise<void> {
try {
const tagExists = await this.tagModelRepository.exists({
// Query to find existing tags
const tagExists = await this.tagModelRepository.find({
where: [
{
tag,
@ -304,16 +348,29 @@ export class TagModelService {
],
});
if (tagExists) {
// Remove tags that are marked for deletion
const filteredTagExists = tagExists.filter(
(existingTag) =>
!tagsToDelete?.some(
(deleteTag) => deleteTag.uuid === existingTag.uuid,
),
);
// If any tags remain, throw an exception
if (filteredTagExists.length > 0) {
throw new HttpException(
`Tag ${tag} can't be reused`,
HttpStatus.CONFLICT,
);
}
} catch (error) {
if (error instanceof HttpException) {
throw error;
}
console.error(`Error while checking tag reuse: ${error.message}`);
throw new HttpException(
`An error occurred while checking tag reuse: ${error.message}`,
HttpStatus.INTERNAL_SERVER_ERROR,
@ -326,6 +383,7 @@ export class TagModelService {
queryRunner: QueryRunner,
spaceModel?: SpaceModelEntity,
subspaceModel?: SubspaceModelEntity,
tagsToDelete?: ModifyTagModelDto[],
): Promise<TagModel> {
try {
const product = await this.productService.findOne(tagDto.productUuid);
@ -338,7 +396,12 @@ export class TagModelService {
}
if (spaceModel) {
await this.checkTagReuse(tagDto.tag, tagDto.productUuid, spaceModel);
await this.checkTagReuse(
tagDto.tag,
tagDto.productUuid,
spaceModel,
tagsToDelete,
);
} else if (subspaceModel && subspaceModel.spaceModel) {
await this.checkTagReuse(
tagDto.tag,
@ -351,11 +414,14 @@ export class TagModelService {
HttpStatus.BAD_REQUEST,
);
}
const tagSpace =
spaceModel !== null ? spaceModel : subspaceModel.spaceModel;
return queryRunner.manager.create(TagModel, {
tag: tagDto.tag,
product: product.data,
spaceModel,
subspaceModel,
spaceModel: tagSpace,
subspaceModel: subspaceModel,
});
} catch (error) {
if (error instanceof HttpException) {
@ -421,17 +487,21 @@ export class TagModelService {
subspaceModels: ModifySubspaceModelDto[],
): ModifyTagModelDto[] {
if (!subspaceModels || subspaceModels.length === 0) {
return spaceTags;
}
const spaceTagsToDelete = spaceTags.filter(
(tag) => tag.action === 'delete',
);
const tagsToAdd = subspaceModels.flatMap(
(subspace) => subspace.tags?.filter((tag) => tag.action === 'add') || [],
);
const commonTagUuids = new Set(
tagsToAdd
.filter((tagToAdd) =>
@ -443,10 +513,45 @@ export class TagModelService {
);
const remainingTags = spaceTags.filter(
(tag) =>
!tag.uuid || commonTagUuids.size === 0 || commonTagUuids.has(tag.uuid),
(tag) => !commonTagUuids.has(tag.uuid), // Exclude tags in commonTagUuids
);
return remainingTags;
}
getModifiedSubspaces(
spaceTags: ModifyTagModelDto[],
subspaceModels: ModifySubspaceModelDto[],
): ModifySubspaceModelDto[] {
if (!subspaceModels || subspaceModels.length === 0) {
return [];
}
// Extract tags marked for addition in spaceTags
const spaceTagsToAdd = spaceTags.filter((tag) => tag.action === 'add');
// Find UUIDs of tags that are common between spaceTagsToAdd and subspace tags marked for deletion
const commonTagUuids = new Set(
spaceTagsToAdd
.flatMap((tagToAdd) =>
subspaceModels.flatMap(
(subspace) =>
subspace.tags?.filter(
(tagToDelete) =>
tagToDelete.action === 'delete' &&
tagToAdd.uuid === tagToDelete.uuid,
) || [],
),
)
.map((tag) => tag.uuid),
);
// Modify subspaceModels by removing tags with UUIDs present in commonTagUuids
const modifiedSubspaces = subspaceModels.map((subspace) => ({
...subspace,
tags: subspace.tags?.filter((tag) => !commonTagUuids.has(tag.uuid)) || [],
}));
return modifiedSubspaces;
}
}