From 7833151b7094a830b5b049cf579830aa5e685c7c Mon Sep 17 00:00:00 2001 From: hannathkadher Date: Wed, 18 Dec 2024 11:40:45 +0400 Subject: [PATCH] list space-model --- libs/common/src/constants/controller-route.ts | 4 ++ .../src/constants/permissions-mapping.ts | 1 + libs/common/src/constants/role-permissions.ts | 2 + libs/common/src/models/typeOrmCustom.model.ts | 5 ++- .../src/util/buildTypeORMIncludeQuery.ts | 45 +++++++++++++++---- .../controllers/space-model.controller.ts | 27 ++++++++++- .../services/space-model.service.ts | 38 ++++++++++++++++ 7 files changed, 111 insertions(+), 11 deletions(-) diff --git a/libs/common/src/constants/controller-route.ts b/libs/common/src/constants/controller-route.ts index c26deca..f6cbfe1 100644 --- a/libs/common/src/constants/controller-route.ts +++ b/libs/common/src/constants/controller-route.ts @@ -273,6 +273,10 @@ export class ControllerRoute { 'Create a New Space Model'; public static readonly CREATE_SPACE_MODEL_DESCRIPTION = 'This endpoint allows you to create a new space model within a specified project. A space model defines the structure of spaces, including subspaces, products, and product items, and is uniquely identifiable within the project.'; + + public static readonly LIST_SPACE_MODEL_SUMMARY = 'List Space Models'; + public static readonly LIST_SPACE_MODEL_DESCRIPTION = + 'This endpoint allows you to retrieve a list of space models within a specified project. Each space model includes its structure, associated subspaces, products, and product items.'; }; }; diff --git a/libs/common/src/constants/permissions-mapping.ts b/libs/common/src/constants/permissions-mapping.ts index a9db542..e940933 100644 --- a/libs/common/src/constants/permissions-mapping.ts +++ b/libs/common/src/constants/permissions-mapping.ts @@ -13,6 +13,7 @@ export const PermissionMapping = { 'UPDATE', 'DELETE', 'MODULE_ADD', + 'MODEL_VIEW', 'ASSIGN_USER_TO_SPACE', 'DELETE_USER_FROM_SPACE', ], diff --git a/libs/common/src/constants/role-permissions.ts b/libs/common/src/constants/role-permissions.ts index ed61e5d..aae658a 100644 --- a/libs/common/src/constants/role-permissions.ts +++ b/libs/common/src/constants/role-permissions.ts @@ -17,6 +17,7 @@ export const RolePermissions = { 'SPACE_UPDATE', 'SPACE_DELETE', 'SPACE_MODULE_ADD', + 'SPACE_MODEL_VIEW', 'ASSIGN_USER_TO_SPACE', 'DELETE_USER_FROM_SPACE', 'SUBSPACE_VIEW', @@ -60,6 +61,7 @@ export const RolePermissions = { 'SPACE_UPDATE', 'SPACE_DELETE', 'SPACE_MODULE_ADD', + 'SPACE_MODEL_VIEW', 'ASSIGN_USER_TO_SPACE', 'DELETE_USER_FROM_SPACE', 'SUBSPACE_VIEW', diff --git a/libs/common/src/models/typeOrmCustom.model.ts b/libs/common/src/models/typeOrmCustom.model.ts index 0f3abbc..2f11102 100644 --- a/libs/common/src/models/typeOrmCustom.model.ts +++ b/libs/common/src/models/typeOrmCustom.model.ts @@ -31,7 +31,7 @@ interface FindAllQueryWithDefaults extends CustomFindAllQuery { function getDefaultQueryOptions( query: Partial, ): FindManyOptions & FindAllQueryWithDefaults { - const { page, size, includeDisable, modelName, ...rest } = query; + const { page, size, includeDisable, include, modelName, ...rest } = query; // Set default if undefined or null const returnPage = page ? Number(page) : 1; @@ -48,7 +48,9 @@ function getDefaultQueryOptions( }, page: returnPage, size: returnSize, + include: include || undefined, includeDisable: returnIncludeDisable, + modelName: modelName || query.modelName, // Ensure modelName is passed through }; } @@ -97,7 +99,6 @@ export function TypeORMCustomModel(repository: Repository) { // Use the where clause directly, without wrapping it under 'where' const whereClause = buildTypeORMWhereClause({ where }); - console.log('Final where clause:', whereClause); // Ensure the whereClause is passed directly to findAndCount const [data, count] = await repository.findAndCount({ diff --git a/libs/common/src/util/buildTypeORMIncludeQuery.ts b/libs/common/src/util/buildTypeORMIncludeQuery.ts index 029bd67..bffd5be 100644 --- a/libs/common/src/util/buildTypeORMIncludeQuery.ts +++ b/libs/common/src/util/buildTypeORMIncludeQuery.ts @@ -19,6 +19,19 @@ const mappingInclude: { [key: string]: any } = { project: { project: true, }, + 'space-model': { + subspaceModels: 'subspace-model', + spaceProductModels: 'space-product-model', + }, + 'subspace-model': { + productModels: 'subspace-product-model', + }, + 'subspace-product-model': { + itemModels: true, + }, + 'space-product-model': { + items: true, + }, }; export function buildTypeORMIncludeQuery( @@ -30,17 +43,33 @@ export function buildTypeORMIncludeQuery( const fieldsToInclude: string[] = includeParam.split(','); fieldsToInclude.forEach((field: string) => { - if (mappingInclude[field]) { - relations.push(field); // Push mapped field - } else { - console.warn( - `Field ${field} not found in mappingInclude for ${modelName}`, - ); + const nestedFields = field.split('.'); + let currentModelName = modelName; + let isValid = true; + + nestedFields.forEach((nestedField, index) => { + const currentMapping = mappingInclude[currentModelName]; + if (currentMapping?.[nestedField]) { + currentModelName = + typeof currentMapping[nestedField] === 'string' + ? currentMapping[nestedField] + : currentModelName; + } else { + console.warn( + `Field "${nestedFields.slice(0, index + 1).join('.')}" not found in mappingInclude for model "${currentModelName}"`, + ); + isValid = false; + return; + } + }); + + if (isValid) { + relations.push(field); } }); - return relations; + return relations.length ? relations : undefined; } - return undefined; // If no includes, return undefined + return undefined; } diff --git a/src/space-model/controllers/space-model.controller.ts b/src/space-model/controllers/space-model.controller.ts index bedb81e..d994ba6 100644 --- a/src/space-model/controllers/space-model.controller.ts +++ b/src/space-model/controllers/space-model.controller.ts @@ -1,5 +1,13 @@ import { ControllerRoute } from '@app/common/constants/controller-route'; -import { Body, Controller, Param, Post, UseGuards } from '@nestjs/common'; +import { + Body, + Controller, + Get, + Param, + Post, + Query, + UseGuards, +} from '@nestjs/common'; import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; import { SpaceModelService } from '../services'; import { CreateSpaceModelDto } from '../dtos'; @@ -7,6 +15,7 @@ import { ProjectParam } from 'src/community/dtos'; import { BaseResponseDto } from '@app/common/dto/base.response.dto'; import { PermissionsGuard } from 'src/guards/permissions.guard'; import { Permissions } from 'src/decorators/permissions.decorator'; +import { PaginationRequestGetListDto } from '@app/common/dto/pagination.request.dto'; @ApiTags('Space Model Module') @Controller({ @@ -34,4 +43,20 @@ export class SpaceModelController { projectParam, ); } + + @ApiBearerAuth() + @UseGuards(PermissionsGuard) + @Permissions('SPACE_MODEL_VIEW') + @ApiOperation({ + summary: ControllerRoute.SPACE_MODEL.ACTIONS.LIST_SPACE_MODEL_SUMMARY, + description: + ControllerRoute.SPACE_MODEL.ACTIONS.LIST_SPACE_MODEL_DESCRIPTION, + }) + @Get() + async listSpaceModel( + @Param() projectParam: ProjectParam, + @Query() query: PaginationRequestGetListDto, + ): Promise { + return await this.spaceModelService.list(projectParam, query); + } } diff --git a/src/space-model/services/space-model.service.ts b/src/space-model/services/space-model.service.ts index 0423c42..0ce4083 100644 --- a/src/space-model/services/space-model.service.ts +++ b/src/space-model/services/space-model.service.ts @@ -7,6 +7,12 @@ import { SuccessResponseDto } from '@app/common/dto/success.response.dto'; import { SubSpaceModelService } from './subspace/subspace-model.service'; import { SpaceProductModelService } from './space-product-model.service'; import { DataSource } from 'typeorm'; +import { + TypeORMCustomModel, + TypeORMCustomModelFindAllQuery, +} from '@app/common/models/typeOrmCustom.model'; +import { PageResponse } from '@app/common/dto/pagination.response.dto'; +import { SpaceModelDto } from '@app/common/modules/space-model/dtos'; @Injectable() export class SpaceModelService { @@ -87,6 +93,38 @@ export class SpaceModelService { } } + async list( + param: ProjectParam, + pageable: Partial, + ) { + await this.validateProject(param.projectUuid); + + try { + pageable.modelName = 'space-model'; + pageable.where = { + project: { uuid: param.projectUuid }, + }; + pageable.include = + 'subspaceModels,spaceProductModels,subspaceModels.productModels,subspaceModels.productModels.itemModels,spaceProductModels.items'; + + const customModel = TypeORMCustomModel(this.spaceModelRepository); + + const { baseResponseDto, paginationResponseDto } = + await customModel.findAll(pageable); + + return new PageResponse( + baseResponseDto, + paginationResponseDto, + ); + } catch (error) { + throw new HttpException( + error.message || + 'An error occurred while fetching space models in project.', + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + async validateProject(projectUuid: string) { const project = await this.projectRepository.findOne({ where: {