diff --git a/src/space-model/services/space-model.service.ts b/src/space-model/services/space-model.service.ts index 2abfde5..d628a1c 100644 --- a/src/space-model/services/space-model.service.ts +++ b/src/space-model/services/space-model.service.ts @@ -1,26 +1,24 @@ import { SpaceModelEntity, + SpaceModelProductAllocationEntity, SpaceModelRepository, + SubspaceModelProductAllocationEntity, } from '@app/common/modules/space-model'; import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import { CreateSpaceModelDto, UpdateSpaceModelDto } from '../dtos'; import { ProjectParam } from 'src/community/dtos'; import { SuccessResponseDto } from '@app/common/dto/success.response.dto'; import { SubSpaceModelService } from './subspace/subspace-model.service'; -import { DataSource, QueryRunner } from 'typeorm'; +import { DataSource, QueryRunner, SelectQueryBuilder } from 'typeorm'; import { TypeORMCustomModel, TypeORMCustomModelFindAllQuery, } from '@app/common/models/typeOrmCustom.model'; -import { PageResponse } from '@app/common/dto/pagination.response.dto'; import { SpaceModelParam } from '../dtos/space-model-param'; 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 { SpaceModelDto } from '@app/common/modules/space-model/dtos'; -import { TagService as NewTagService } from 'src/tags/services'; import { ProcessTagDto } from 'src/tags/dtos'; import { SpaceModelProductAllocationService } from './space-model-product-allocation.service'; @@ -31,9 +29,7 @@ export class SpaceModelService { private readonly spaceModelRepository: SpaceModelRepository, private readonly projectService: ProjectService, private readonly subSpaceModelService: SubSpaceModelService, - private readonly tagModelService: TagModelService, private commandBus: CommandBus, - private readonly tagService: NewTagService, private readonly spaceModelProductAllocationService: SpaceModelProductAllocationService, ) {} @@ -130,37 +126,7 @@ export class SpaceModelService { pageable.include = 'subspaceModels.productAllocations,subspaceModelProductAllocations.tags,subspaceModels, productAllocations, productAllocations.tags'; - const queryBuilder = this.spaceModelRepository - .createQueryBuilder('spaceModel') - .leftJoinAndSelect( - 'spaceModel.subspaceModels', - 'subspaceModels', - 'subspaceModels.disabled = false', - ) - .leftJoinAndSelect( - 'subspaceModels.productAllocations', - 'subspaceModelProductAllocations', - ) - // Ensure correct aliasing for the ManyToMany relation - .leftJoinAndSelect( - 'subspaceModelProductAllocations.tags', - 'subspaceModelTags', - ) - .leftJoinAndSelect( - 'subspaceModelTags.product', - 'subspaceModelTagProduct', - ) - .leftJoinAndSelect( - 'spaceModel.productAllocations', - 'productAllocations', - ) - .leftJoinAndSelect('productAllocations.product', 'allocatedProduct') - .leftJoinAndSelect('productAllocations.tags', 'productTags') - .leftJoinAndSelect('productTags.product', 'productTagProduct') - .where('spaceModel.disabled = false') - .andWhere('spaceModel.project = :projectUuid', { - projectUuid: param.projectUuid, - }); + const queryBuilder = this.buildSpaceModelQuery(param.projectUuid); const customModel = TypeORMCustomModel(this.spaceModelRepository); const { baseResponseDto, paginationResponseDto } = @@ -173,86 +139,13 @@ export class SpaceModelService { queryBuilder, ); - // Ensure baseResponseDto is an array - const spaceModelsArray = Array.isArray(baseResponseDto.data) - ? baseResponseDto.data - : [baseResponseDto.data]; - - // Log to verify correct data retrieval - console.log( - 'SpaceModelsArray:', - JSON.stringify(spaceModelsArray, null, 2), - ); - - // Format response - const formattedData = spaceModelsArray.map((spaceModel) => ({ - uuid: spaceModel.uuid, - createdAt: spaceModel.createdAt, - updatedAt: spaceModel.updatedAt, - modelName: spaceModel.modelName, - disabled: spaceModel.disabled, - subspaceModels: (spaceModel.subspaceModels ?? []).map((subspace) => ({ - uuid: subspace.uuid, - createdAt: subspace.createdAt, - updatedAt: subspace.updatedAt, - subspaceName: subspace.subspaceName, - disabled: subspace.disabled, - tags: (subspace.productAllocations ?? []) - .flatMap((allocation) => allocation.tags ?? []) - .map((tag) => ({ - uuid: tag.uuid, - createdAt: tag.createdAt, - updatedAt: tag.updatedAt, - tag: tag.tag, - disabled: tag.disabled, - product: tag.product - ? { - uuid: tag.product.uuid, - createdAt: tag.product.createdAt, - updatedAt: tag.product.updatedAt, - catName: tag.product.catName, - prodId: tag.product.prodId, - name: tag.product.name, - prodType: tag.product.prodType, - } - : null, - })), - })), - tags: (spaceModel.productAllocations ?? []) - .flatMap((allocation) => allocation.tags ?? []) - .map((tag) => ({ - uuid: tag.uuid, - createdAt: tag.createdAt, - updatedAt: tag.updatedAt, - tag: tag.tag, - disabled: tag.disabled, - product: tag.product - ? { - uuid: tag.product.uuid, - createdAt: tag.product.createdAt, - updatedAt: tag.product.updatedAt, - catName: tag.product.catName, - prodId: tag.product.prodId, - name: tag.product.name, - prodType: tag.product.prodType, - } - : null, - })), - })); - - // Log to verify formatted response - console.log('FormattedData:', JSON.stringify(formattedData, null, 2)); + const formattedData = this.transformSpaceModelData(baseResponseDto.data); return { code: 200, data: formattedData, message: 'Success get list spaceModel', - page: paginationResponseDto.page, - size: paginationResponseDto.size, - totalItem: paginationResponseDto.totalItem, - totalPage: paginationResponseDto.totalPage, - hasNext: paginationResponseDto.hasNext, - hasPrevious: paginationResponseDto.hasPrevious, + ...paginationResponseDto, }; } catch (error) { throw new HttpException( @@ -269,7 +162,10 @@ 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); + const spaceModel = await this.validateSpaceModel( + param.spaceModelUuid, + param.projectUuid, + ); await queryRunner.connect(); try { @@ -335,7 +231,10 @@ export class SpaceModelService { try { await this.validateProject(param.projectUuid); - const spaceModel = await this.validateSpaceModel(param.spaceModelUuid); + const spaceModel = await this.validateSpaceModel( + param.spaceModelUuid, + param.projectUuid, + ); if (spaceModel.subspaceModels?.length) { const deleteSubspaceUuids = spaceModel.subspaceModels.map( @@ -348,10 +247,11 @@ export class SpaceModelService { ); } - if (spaceModel.tags?.length) { - const deleteSpaceTagsDtos = spaceModel.tags.map((tag) => tag.uuid); - - await this.tagModelService.deleteTags(deleteSpaceTagsDtos, queryRunner); + if (spaceModel.productAllocations?.length) { + await this.spaceModelProductAllocationService.clearAllAllocations( + spaceModel.uuid, + queryRunner, + ); } await queryRunner.manager.update( @@ -417,11 +317,15 @@ export class SpaceModelService { async findOne(params: SpaceModelParam): Promise { try { await this.validateProject(params.projectUuid); - const spaceModel = await this.validateSpaceModel(params.spaceModelUuid); + const spaceModel = await this.validateSpaceModel( + params.spaceModelUuid, + params.projectUuid, + ); + const response = this.formatSpaceModelResponse(spaceModel); return new SuccessResponseDto({ message: 'SpaceModel retrieved successfully', - data: spaceModel, + data: response, }); } catch (error) { throw new HttpException( @@ -431,38 +335,19 @@ export class SpaceModelService { } } - async validateSpaceModel(uuid: string): Promise { - const spaceModel = await this.spaceModelRepository - .createQueryBuilder('spaceModel') - .leftJoinAndSelect( - 'spaceModel.subspaceModels', - 'subspaceModels', - 'subspaceModels.disabled = :subspaceDisabled', - { subspaceDisabled: false }, - ) - .leftJoinAndSelect( - 'spaceModel.tags', - 'tags', - 'tags.disabled = :tagsDisabled', - { tagsDisabled: false }, - ) - .leftJoinAndSelect('tags.product', 'spaceTagproduct') - .leftJoinAndSelect( - 'subspaceModels.tags', - 'subspaceModelTags', - 'subspaceModelTags.disabled = :subspaceModelTagsDisabled', - { subspaceModelTagsDisabled: false }, - ) - .leftJoinAndSelect('subspaceModelTags.product', 'subspaceTagproduct') - .where('spaceModel.disabled = :disabled', { disabled: false }) - .where('spaceModel.disabled = :disabled', { disabled: false }) + async validateSpaceModel( + uuid: string, + projectUuid?: string, + ): Promise { + const query = this.buildSpaceModelQuery(projectUuid); + const result = await query .andWhere('spaceModel.uuid = :uuid', { uuid }) .getOne(); - if (!spaceModel) { + if (!result) { throw new HttpException('space model not found', HttpStatus.NOT_FOUND); } - return spaceModel; + return result; } private validateUniqueTags(allTags: ProcessTagDto[]) { @@ -490,4 +375,103 @@ export class SpaceModelService { } } } + + private buildSpaceModelQuery( + projectUuid: string, + ): SelectQueryBuilder { + return this.spaceModelRepository + .createQueryBuilder('spaceModel') + .leftJoinAndSelect( + 'spaceModel.subspaceModels', + 'subspaceModels', + 'subspaceModels.disabled = :subspaceDisabled', + { subspaceDisabled: false }, + ) + .leftJoinAndSelect( + 'subspaceModels.productAllocations', + 'subspaceModelProductAllocations', + ) + .leftJoinAndSelect( + 'subspaceModelProductAllocations.tags', + 'subspaceModelTags', + ) + .leftJoinAndSelect('subspaceModelTags.product', 'subspaceModelTagProduct') + .leftJoinAndSelect('spaceModel.productAllocations', 'productAllocations') + .leftJoinAndSelect('productAllocations.product', 'allocatedProduct') + .leftJoinAndSelect('productAllocations.tags', 'productTags') + .leftJoinAndSelect('productTags.product', 'productTagProduct') + .where('spaceModel.disabled = false') + .andWhere('spaceModel.project = :projectUuid', { projectUuid }); + } + + private transformSpaceModelData(spaceModelsArray: SpaceModelEntity[]): any[] { + if (!Array.isArray(spaceModelsArray)) return []; + + return spaceModelsArray.map((spaceModel) => ({ + uuid: spaceModel.uuid, + createdAt: spaceModel.createdAt, + updatedAt: spaceModel.updatedAt, + modelName: spaceModel.modelName, + disabled: spaceModel.disabled, + subspaceModels: (spaceModel.subspaceModels ?? []).map((subspace) => ({ + uuid: subspace.uuid, + createdAt: subspace.createdAt, + updatedAt: subspace.updatedAt, + subspaceName: subspace.subspaceName, + disabled: subspace.disabled, + tags: this.extractTags(subspace.productAllocations), + })), + tags: this.extractTags(spaceModel.productAllocations), + })); + } + + private extractTags( + productAllocations: + | SpaceModelProductAllocationEntity[] + | SubspaceModelProductAllocationEntity[] + | undefined, + ): any[] { + if (!productAllocations) return []; + + return productAllocations + .flatMap((allocation) => allocation.tags ?? []) + .map((tag) => ({ + uuid: tag.uuid, + createdAt: tag.createdAt, + updatedAt: tag.updatedAt, + tag: tag.tag, + disabled: tag.disabled, + product: tag.product + ? { + uuid: tag.product.uuid, + createdAt: tag.product.createdAt, + updatedAt: tag.product.updatedAt, + catName: tag.product.catName, + prodId: tag.product.prodId, + name: tag.product.name, + prodType: tag.product.prodType, + } + : null, + })); + } + + private formatSpaceModelResponse(spaceModel: SpaceModelEntity): any { + return { + uuid: spaceModel.uuid, + createdAt: spaceModel.createdAt, + updatedAt: spaceModel.updatedAt, + modelName: spaceModel.modelName, + disabled: spaceModel.disabled, + subspaceModels: + spaceModel.subspaceModels?.map((subspace) => ({ + uuid: subspace.uuid, + createdAt: subspace.createdAt, + updatedAt: subspace.updatedAt, + subspaceName: subspace.subspaceName, + disabled: subspace.disabled, + tags: this.extractTags(subspace.productAllocations), + })) ?? [], + tags: this.extractTags(spaceModel.productAllocations), + }; + } }