diff --git a/src/space-model/dtos/tag-model-dtos/create-tag-model.dto.ts b/src/space-model/dtos/tag-model-dtos/create-tag-model.dto.ts index 5f4ec66..c271eef 100644 --- a/src/space-model/dtos/tag-model-dtos/create-tag-model.dto.ts +++ b/src/space-model/dtos/tag-model-dtos/create-tag-model.dto.ts @@ -1,5 +1,5 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { IsNotEmpty, IsString } from 'class-validator'; +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; +import { IsNotEmpty, IsOptional, IsString } from 'class-validator'; export class CreateTagModelDto { @ApiProperty({ @@ -10,6 +10,14 @@ export class CreateTagModelDto { @IsString() tag: string; + @ApiPropertyOptional({ + description: 'UUID of the tag model (required for update/delete)', + example: '123e4567-e89b-12d3-a456-426614174000', + }) + @IsOptional() + @IsString() + uuid?: string; + @ApiProperty({ description: 'ID of the product associated with the tag', example: '123e4567-e89b-12d3-a456-426614174000', diff --git a/src/space-model/services/space-model.service.ts b/src/space-model/services/space-model.service.ts index 5ef531c..98d6c78 100644 --- a/src/space-model/services/space-model.service.ts +++ b/src/space-model/services/space-model.service.ts @@ -89,6 +89,8 @@ export class SpaceModelService { statusCode: HttpStatus.CREATED, }); } catch (error) { + console.log(JSON.stringify(createSpaceModelDto)); + await queryRunner.rollbackTransaction(); const errorMessage = @@ -177,7 +179,6 @@ export class SpaceModelService { async update(dto: UpdateSpaceModelDto, param: SpaceModelParam) { const queryRunner = this.dataSource.createQueryRunner(); - await this.validateProject(param.projectUuid); const spaceModel = await this.validateSpaceModel(param.spaceModelUuid); await queryRunner.connect(); @@ -201,6 +202,12 @@ export class SpaceModelService { ); } + const spaceTagsAfterMove = this.tagModelService.getSubspaceTagsToBeAdded( + dto.tags, + dto.subspaceModels, + ); + console.log(spaceTagsAfterMove); + if (dto.subspaceModels) { modifiedSubspaceModels = await this.subSpaceModelService.modifySubSpaceModels( @@ -212,9 +219,10 @@ export class SpaceModelService { if (dto.tags) { modifiedTagsModelPayload = await this.tagModelService.modifyTags( - dto.tags, + spaceTagsAfterMove, queryRunner, spaceModel, + null, ); } @@ -235,8 +243,8 @@ export class SpaceModelService { message: 'SpaceModel updated successfully', }); } catch (error) { + console.log(JSON.stringify(dto)); await queryRunner.rollbackTransaction(); - if (error instanceof HttpException) { throw error; } diff --git a/src/space-model/services/subspace/subspace-model.service.ts b/src/space-model/services/subspace/subspace-model.service.ts index f309856..dd3fe91 100644 --- a/src/space-model/services/subspace/subspace-model.service.ts +++ b/src/space-model/services/subspace/subspace-model.service.ts @@ -50,8 +50,7 @@ export class SubSpaceModelService { const otherDtoTags = subSpaceModelDtos .filter((_, i) => i !== index) .flatMap((otherDto) => otherDto.tags || []); - - if (dto.tags?.length) { + if (dto.tags && dto.tags.length > 0) { subspace.tags = await this.tagModelService.createTags( dto.tags, queryRunner, @@ -174,6 +173,7 @@ export class SubSpaceModelService { const createTagDtos: CreateTagModelDto[] = subspace.tags?.map((tag) => ({ tag: tag.tag, + uuid: tag.uuid, productUuid: tag.productUuid, })) || []; diff --git a/src/space-model/services/tag-model.service.ts b/src/space-model/services/tag-model.service.ts index 14f2cf2..abb0d3a 100644 --- a/src/space-model/services/tag-model.service.ts +++ b/src/space-model/services/tag-model.service.ts @@ -6,7 +6,11 @@ import { } 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 { CreateTagModelDto, ModifyTagModelDto } from '../dtos'; +import { + CreateTagModelDto, + ModifySubspaceModelDto, + ModifyTagModelDto, +} from '../dtos'; import { ProductService } from 'src/product/services'; import { ModifyAction } from '@app/common/constants/modify-action.enum'; import { ModifiedTagsModelPayload } from '../interfaces'; @@ -39,11 +43,55 @@ 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, + ); + + // Update existing tags + const updatedTags = await this.moveTags( + tagEntitiesToUpdate, + queryRunner, + spaceModel, + subspaceModel, + ); + + // Combine created and updated tags + return [...createdTags, ...updatedTags]; + } catch (error) { + if (error instanceof HttpException) { + throw error; + } + + throw new HttpException( + `Failed to create tag models due to an unexpected error.: ${error}`, + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + + async bulkSaveTags( + tags: CreateTagModelDto[], + queryRunner: QueryRunner, + spaceModel?: SpaceModelEntity, + subspaceModel?: SubspaceModelEntity, + ): Promise { + if (!tags.length) { + return []; + } + const tagEntities = await Promise.all( - tags.map(async (tagDto) => + tags.map((tagDto) => this.prepareTagEntity(tagDto, queryRunner, spaceModel, subspaceModel), ), ); + try { return await queryRunner.manager.save(tagEntities); } catch (error) { @@ -52,12 +100,46 @@ export class TagModelService { } throw new HttpException( - 'Failed to save tag models due to an unexpected error.', + `Failed to save tag models due to an unexpected error: ${error.message}`, HttpStatus.INTERNAL_SERVER_ERROR, ); } } + async moveTags( + tags: CreateTagModelDto[], + queryRunner: QueryRunner, + spaceModel?: SpaceModelEntity, + subspaceModel?: SubspaceModelEntity, + ): Promise { + if (!tags.length) { + 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, + ); + } + + if (subspaceModel && subspaceModel.spaceModel) { + await queryRunner.manager.update( + this.tagModelRepository.target, + { uuid: tag.uuid }, + { subspaceModel }, + ); + tag.subspaceModel = subspaceModel; + } + + return tag; + }), + ); + } + async updateTag( tag: ModifyTagModelDto, queryRunner: QueryRunner, @@ -153,6 +235,7 @@ export class TagModelService { if (tag.action === ModifyAction.ADD) { const createTagDto: CreateTagModelDto = { tag: tag.tag as string, + uuid: tag.uuid, productUuid: tag.productUuid as string, }; @@ -268,7 +351,6 @@ export class TagModelService { HttpStatus.BAD_REQUEST, ); } - return queryRunner.manager.create(TagModel, { tag: tagDto.tag, product: product.data, @@ -333,4 +415,38 @@ export class TagModelService { return existingTag; } + + getSubspaceTagsToBeAdded( + spaceTags: ModifyTagModelDto[], + 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) => + spaceTagsToDelete.some( + (tagToDelete) => tagToAdd.uuid === tagToDelete.uuid, + ), + ) + .map((tag) => tag.uuid), + ); + + const remainingTags = spaceTags.filter( + (tag) => + !tag.uuid || commonTagUuids.size === 0 || commonTagUuids.has(tag.uuid), + ); + + return remainingTags; + } }