From b8590841a8efa148930417280a47b397f6a56de3 Mon Sep 17 00:00:00 2001 From: hannathkadher Date: Thu, 12 Dec 2024 14:37:44 +0400 Subject: [PATCH] aadded product item to space --- .../src/modules/space/entities/index.ts | 4 +- .../entities/space-product-item.entity.ts | 3 +- .../space/entities/space-product.entity.ts | 2 +- .../modules/space/entities/space.entity.ts | 2 +- .../modules/space/entities/subspace/index.ts | 1 + .../{ => subspace}/subspace.entity.ts | 10 +- libs/common/src/modules/space/index.ts | 4 + .../space/repositories/space.repository.ts | 14 +- .../space-product-item-model.service.ts | 7 - src/space/services/index.ts | 1 + .../services/space-product-items/index.ts | 1 + .../space-product-items.service.ts | 112 +++++++++ .../space-products/space-products.service.ts | 212 ++++++++++++------ .../services/space-validation.service.ts | 7 +- src/space/services/space.service.ts | 35 ++- .../services/subspace/subspace.service.ts | 11 +- src/space/space.module.ts | 4 + 17 files changed, 328 insertions(+), 102 deletions(-) create mode 100644 libs/common/src/modules/space/entities/subspace/index.ts rename libs/common/src/modules/space/entities/{ => subspace}/subspace.entity.ts (74%) create mode 100644 libs/common/src/modules/space/index.ts create mode 100644 src/space/services/space-product-items/index.ts create mode 100644 src/space/services/space-product-items/space-product-items.service.ts diff --git a/libs/common/src/modules/space/entities/index.ts b/libs/common/src/modules/space/entities/index.ts index d09bdac..f07ec93 100644 --- a/libs/common/src/modules/space/entities/index.ts +++ b/libs/common/src/modules/space/entities/index.ts @@ -1,5 +1,5 @@ export * from './space.entity'; -export * from './subspace.entity'; -export * from './space-product-item.entity'; +export * from './subspace'; export * from './space-product.entity'; +export * from './space-product-item.entity'; export * from './space-link.entity'; diff --git a/libs/common/src/modules/space/entities/space-product-item.entity.ts b/libs/common/src/modules/space/entities/space-product-item.entity.ts index 70e7c1f..c53dfd4 100644 --- a/libs/common/src/modules/space/entities/space-product-item.entity.ts +++ b/libs/common/src/modules/space/entities/space-product-item.entity.ts @@ -14,14 +14,13 @@ export class SpaceProductItemEntity extends AbstractEntity @ManyToOne(() => SpaceProductEntity, (spaceProduct) => spaceProduct.items, { nullable: false, }) - public spaceProducts: SpaceProductEntity; + public spaceProduct: SpaceProductEntity; @ManyToOne( () => SpaceProductItemModelEntity, (spaceProductItemModel) => spaceProductItemModel.items, { nullable: true, - onDelete: 'SET NULL', }, ) public spaceProductItemModel?: SpaceProductItemModelEntity; diff --git a/libs/common/src/modules/space/entities/space-product.entity.ts b/libs/common/src/modules/space/entities/space-product.entity.ts index 8fa0c4f..5f8a062 100644 --- a/libs/common/src/modules/space/entities/space-product.entity.ts +++ b/libs/common/src/modules/space/entities/space-product.entity.ts @@ -27,7 +27,7 @@ export class SpaceProductEntity extends AbstractEntity { }) productCount: number; - @OneToMany(() => SpaceProductItemEntity, (item) => item.spaceProducts, { + @OneToMany(() => SpaceProductItemEntity, (item) => item.spaceProduct, { cascade: true, }) public items: SpaceProductItemEntity[]; diff --git a/libs/common/src/modules/space/entities/space.entity.ts b/libs/common/src/modules/space/entities/space.entity.ts index 9d6e6fd..1b972f6 100644 --- a/libs/common/src/modules/space/entities/space.entity.ts +++ b/libs/common/src/modules/space/entities/space.entity.ts @@ -11,7 +11,7 @@ import { AbstractEntity } from '../../abstract/entities/abstract.entity'; import { UserSpaceEntity } from '../../user/entities'; import { DeviceEntity } from '../../device/entities'; import { CommunityEntity } from '../../community/entities'; -import { SubspaceEntity } from './subspace.entity'; +import { SubspaceEntity } from './subspace'; import { SpaceLinkEntity } from './space-link.entity'; import { SpaceProductEntity } from './space-product.entity'; import { SceneEntity } from '../../scene/entities'; diff --git a/libs/common/src/modules/space/entities/subspace/index.ts b/libs/common/src/modules/space/entities/subspace/index.ts new file mode 100644 index 0000000..be13961 --- /dev/null +++ b/libs/common/src/modules/space/entities/subspace/index.ts @@ -0,0 +1 @@ +export * from './subspace.entity'; diff --git a/libs/common/src/modules/space/entities/subspace.entity.ts b/libs/common/src/modules/space/entities/subspace/subspace.entity.ts similarity index 74% rename from libs/common/src/modules/space/entities/subspace.entity.ts rename to libs/common/src/modules/space/entities/subspace/subspace.entity.ts index ccb5118..8f0d15d 100644 --- a/libs/common/src/modules/space/entities/subspace.entity.ts +++ b/libs/common/src/modules/space/entities/subspace/subspace.entity.ts @@ -1,9 +1,9 @@ +import { AbstractEntity } from '@app/common/modules/abstract/entities/abstract.entity'; +import { DeviceEntity } from '@app/common/modules/device/entities'; +import { SubspaceModelEntity } from '@app/common/modules/space-model'; import { Column, Entity, JoinColumn, ManyToOne, OneToMany } from 'typeorm'; -import { AbstractEntity } from '../../abstract/entities/abstract.entity'; -import { DeviceEntity } from '../../device/entities'; -import { SpaceEntity } from './space.entity'; -import { SubspaceDto } from '../dtos'; -import { SubspaceModelEntity } from '../../space-model'; +import { SubspaceDto } from '../../dtos'; +import { SpaceEntity } from '../space.entity'; @Entity({ name: 'subspace' }) export class SubspaceEntity extends AbstractEntity { diff --git a/libs/common/src/modules/space/index.ts b/libs/common/src/modules/space/index.ts new file mode 100644 index 0000000..b797801 --- /dev/null +++ b/libs/common/src/modules/space/index.ts @@ -0,0 +1,4 @@ +export * from './dtos'; +export * from './entities'; +export * from './repositories'; +export * from './space.repository.module'; diff --git a/libs/common/src/modules/space/repositories/space.repository.ts b/libs/common/src/modules/space/repositories/space.repository.ts index 43ce45e..677db0e 100644 --- a/libs/common/src/modules/space/repositories/space.repository.ts +++ b/libs/common/src/modules/space/repositories/space.repository.ts @@ -1,7 +1,12 @@ import { DataSource, Repository } from 'typeorm'; import { Injectable } from '@nestjs/common'; import { SpaceProductEntity } from '../entities/space-product.entity'; -import { SpaceEntity, SpaceLinkEntity, SubspaceEntity } from '../entities'; +import { + SpaceEntity, + SpaceLinkEntity, + SpaceProductItemEntity, + SubspaceEntity, +} from '../entities'; @Injectable() export class SpaceRepository extends Repository { @@ -28,3 +33,10 @@ export class SpaceProductRepository extends Repository { super(SpaceProductEntity, dataSource.createEntityManager()); } } + +@Injectable() +export class SpaceProductItemRepository extends Repository { + constructor(private dataSource: DataSource) { + super(SpaceProductItemEntity, dataSource.createEntityManager()); + } +} diff --git a/src/space-model/services/space-product-item-model.service.ts b/src/space-model/services/space-product-item-model.service.ts index ac9c0d8..9f40efa 100644 --- a/src/space-model/services/space-product-item-model.service.ts +++ b/src/space-model/services/space-product-item-model.service.ts @@ -20,13 +20,6 @@ export class SpaceProductItemModelService { queryRunner: QueryRunner, ) { await this.validateTags(itemModelDtos, queryRunner, spaceModel); - - if (!spaceProductModel) { - throw new HttpException( - 'Space product model is required to create product items.', - HttpStatus.BAD_REQUEST, - ); - } try { const productItems = itemModelDtos.map((dto) => queryRunner.manager.create(this.spaceProductItemRepository.target, { diff --git a/src/space/services/index.ts b/src/space/services/index.ts index 79eb32f..6a3beeb 100644 --- a/src/space/services/index.ts +++ b/src/space/services/index.ts @@ -5,3 +5,4 @@ export * from './subspace'; export * from './space-link'; export * from './space-scene.service'; export * from './space-products'; +export * from './space-product-items'; diff --git a/src/space/services/space-product-items/index.ts b/src/space/services/space-product-items/index.ts new file mode 100644 index 0000000..fff8634 --- /dev/null +++ b/src/space/services/space-product-items/index.ts @@ -0,0 +1 @@ +export * from './space-product-items.service'; diff --git a/src/space/services/space-product-items/space-product-items.service.ts b/src/space/services/space-product-items/space-product-items.service.ts new file mode 100644 index 0000000..4dbe0ff --- /dev/null +++ b/src/space/services/space-product-items/space-product-items.service.ts @@ -0,0 +1,112 @@ +import { + SpaceEntity, + SpaceProductEntity, + SpaceProductItemRepository, +} from '@app/common/modules/space'; +import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; +import { CreateSpaceProductItemDto } from '../../dtos'; +import { QueryRunner } from 'typeorm'; +import { SpaceProductModelEntity } from '@app/common/modules/space-model'; + +@Injectable() +export class SpaceProductItemService { + constructor( + private readonly spaceProductItemRepository: SpaceProductItemRepository, + ) {} + + async createProductItem( + itemModelDtos: CreateSpaceProductItemDto[], + spaceProduct: SpaceProductEntity, + space: SpaceEntity, + queryRunner: QueryRunner, + ) { + await this.validateTags(itemModelDtos, queryRunner, space); + + try { + const productItems = itemModelDtos.map((dto) => + queryRunner.manager.create(this.spaceProductItemRepository.target, { + tag: dto.tag, + spaceProduct, + }), + ); + + await queryRunner.manager.save(productItems); + } catch (error) { + if (error instanceof HttpException) { + throw error; + } + + throw new HttpException( + error.message || + 'An unexpected error occurred while creating product items.', + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + + async createSpaceProductItemFromModel( + spaceProduct: SpaceProductEntity, + spaceProductModel: SpaceProductModelEntity, + queryRunner: QueryRunner, + ) { + const spaceProductItemModels = spaceProductModel.items; + + try { + const productItems = spaceProductItemModels.map((model) => + queryRunner.manager.create(this.spaceProductItemRepository.target, { + tag: model.tag, + spaceProduct, + }), + ); + + await queryRunner.manager.save(productItems); + } catch (error) { + if (error instanceof HttpException) { + throw error; + } + + throw new HttpException( + error.message || + 'An unexpected error occurred while creating product items.', + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + + private async validateTags( + itemModelDtos: CreateSpaceProductItemDto[], + queryRunner: QueryRunner, + space: SpaceEntity, + ) { + const incomingTags = itemModelDtos.map((item) => item.tag); + + const duplicateTags = incomingTags.filter( + (tag, index) => incomingTags.indexOf(tag) !== index, + ); + if (duplicateTags.length > 0) { + throw new HttpException( + `Duplicate tags found in the request: ${[...new Set(duplicateTags)].join(', ')}`, + HttpStatus.BAD_REQUEST, + ); + } + + const existingTags = await queryRunner.manager.find( + this.spaceProductItemRepository.target, + { + where: { spaceProduct: { space } }, + select: ['tag'], + }, + ); + const existingTagSet = new Set(existingTags.map((item) => item.tag)); + + const conflictingTags = incomingTags.filter((tag) => + existingTagSet.has(tag), + ); + if (conflictingTags.length > 0) { + throw new HttpException( + `Tags already exist in the model: ${conflictingTags.join(', ')}`, + HttpStatus.CONFLICT, + ); + } + } +} diff --git a/src/space/services/space-products/space-products.service.ts b/src/space/services/space-products/space-products.service.ts index 5b218e4..895053f 100644 --- a/src/space/services/space-products/space-products.service.ts +++ b/src/space/services/space-products/space-products.service.ts @@ -2,96 +2,98 @@ import { Injectable, HttpException, HttpStatus } from '@nestjs/common'; import { ProductRepository } from '@app/common/modules/product/repositories'; import { SpaceEntity } from '@app/common/modules/space/entities'; import { SpaceProductEntity } from '@app/common/modules/space/entities/space-product.entity'; -import { SpaceProductRepository } from '@app/common/modules/space/repositories'; -import { In } from 'typeorm'; +import { In, QueryRunner } from 'typeorm'; +import { ProductAssignmentDto } from '../../dtos'; +import { SpaceProductItemService } from '../space-product-items'; +import { SpaceModelEntity } from '@app/common/modules/space-model'; @Injectable() export class SpaceProductService { constructor( private readonly productRepository: ProductRepository, - private readonly spaceProductRepository: SpaceProductRepository, + private readonly spaceProductItemService: SpaceProductItemService, ) {} + async createProductItemFromModel( + spaceModel: SpaceModelEntity, + space: SpaceEntity, + queryRunner: QueryRunner, + ) { + const spaceProductModels = spaceModel.spaceProductModels; + if (!spaceProductModels?.length) return; + const newSpaceProducts = []; + + spaceProductModels.map((spaceProductModel) => { + newSpaceProducts.push( + queryRunner.manager.create(SpaceProductEntity, { + space: space, + product: spaceProductModel.product, + productCount: spaceProductModel.productCount, + spaceProductModel: spaceProductModel, + }), + ); + }); + if (newSpaceProducts.length > 0) { + await queryRunner.manager.save(SpaceProductEntity, newSpaceProducts); + await Promise.all( + newSpaceProducts.map((spaceProduct, index) => { + const spaceProductModel = spaceProductModels[index]; + return this.spaceProductItemService.createSpaceProductItemFromModel( + spaceProduct, + spaceProductModel, + queryRunner, + ); + }), + ); + } + } + async assignProductsToSpace( space: SpaceEntity, - products: { productId: string; count: number }[], + products: ProductAssignmentDto[], + queryRunner: QueryRunner, ): Promise { + let updatedProducts: SpaceProductEntity[] = []; + try { const uniqueProducts = this.validateUniqueProducts(products); const productEntities = await this.getProductEntities(uniqueProducts); + const existingSpaceProducts = await this.getExistingSpaceProducts( + space, + queryRunner, + ); - // Fetch existing space products - const existingSpaceProducts = await this.spaceProductRepository.find({ - where: { - space: { - uuid: space.uuid, - }, - }, - relations: ['product'], - }); - - const updatedProducts = []; - const newProducts = []; - - for (const { productId, count } of uniqueProducts) { - const product = productEntities.get(productId); - if (!product) { - throw new HttpException( - `Product with ID ${productId} not found`, - HttpStatus.NOT_FOUND, - ); - } - - // Check if product already exists in the space - const existingProduct = existingSpaceProducts.find( - (spaceProduct) => spaceProduct.product.uuid === productId, + if (existingSpaceProducts) { + updatedProducts = await this.updateExistingProducts( + existingSpaceProducts, + uniqueProducts, + productEntities, + queryRunner, ); - - if (existingProduct) { - // If count is different, update the existing record - if (existingProduct.productCount !== count) { - existingProduct.productCount = count; - updatedProducts.push(existingProduct); - } - } else { - // Add new product if it doesn't exist - newProducts.push( - this.spaceProductRepository.create({ - space, - product, - productCount: count, - }), - ); - } } - // Save updates and new records - if (updatedProducts.length > 0) { - await this.spaceProductRepository.save(updatedProducts); - } - - if (newProducts.length > 0) { - await this.spaceProductRepository.save(newProducts); - } + const newProducts = await this.createNewProducts( + uniqueProducts, + productEntities, + space, + queryRunner, + ); return [...updatedProducts, ...newProducts]; } catch (error) { - console.error('Error assigning products to space:', error); - if (!(error instanceof HttpException)) { throw new HttpException( - 'An error occurred while assigning products to the space', + `An error occurred while assigning products to the space ${error}`, HttpStatus.INTERNAL_SERVER_ERROR, ); } - throw error; } } private validateUniqueProducts( - products: { productId: string; count: number }[], - ): { productId: string; count: number }[] { + products: ProductAssignmentDto[], + ): ProductAssignmentDto[] { const productIds = new Set(); const uniqueProducts = []; @@ -110,15 +112,13 @@ export class SpaceProductService { } private async getProductEntities( - products: { productId: string; count: number }[], + products: ProductAssignmentDto[], ): Promise> { try { const productIds = products.map((p) => p.productId); - const productEntities = await this.productRepository.find({ where: { uuid: In(productIds) }, }); - return new Map(productEntities.map((p) => [p.uuid, p])); } catch (error) { console.error('Error fetching product entities:', error); @@ -128,4 +128,90 @@ export class SpaceProductService { ); } } + + private async getExistingSpaceProducts( + space: SpaceEntity, + queryRunner: QueryRunner, + ): Promise { + return queryRunner.manager.find(SpaceProductEntity, { + where: { space: { uuid: space.uuid } }, + relations: ['product'], + }); + } + + private async updateExistingProducts( + existingSpaceProducts: SpaceProductEntity[], + uniqueProducts: ProductAssignmentDto[], + productEntities: Map, + queryRunner: QueryRunner, + ): Promise { + const updatedProducts = []; + + for (const { productId, count } of uniqueProducts) { + productEntities.get(productId); + const existingProduct = existingSpaceProducts.find( + (spaceProduct) => spaceProduct.product.uuid === productId, + ); + + if (existingProduct && existingProduct.productCount !== count) { + existingProduct.productCount = count; + updatedProducts.push(existingProduct); + } + } + + if (updatedProducts.length > 0) { + await queryRunner.manager.save(SpaceProductEntity, updatedProducts); + } + + return updatedProducts; + } + + private async createNewProducts( + uniqueSpaceProducts: ProductAssignmentDto[], + productEntities: Map, + space: SpaceEntity, + queryRunner: QueryRunner, + ): Promise { + const newProducts = []; + + for (const uniqueSpaceProduct of uniqueSpaceProducts) { + const product = productEntities.get(uniqueSpaceProduct.productId); + this.validateProductCount(uniqueSpaceProduct); + + newProducts.push( + queryRunner.manager.create(SpaceProductEntity, { + space, + product, + productCount: uniqueSpaceProduct.count, + }), + ); + } + if (newProducts.length > 0) { + await queryRunner.manager.save(SpaceProductEntity, newProducts); + + await Promise.all( + uniqueSpaceProducts.map((dto, index) => { + const spaceProduct = newProducts[index]; + return this.spaceProductItemService.createProductItem( + dto.items, + spaceProduct, + space, + queryRunner, + ); + }), + ); + } + + return newProducts; + } + + private validateProductCount(dto: ProductAssignmentDto) { + const productItemCount = dto.items.length; + if (dto.count !== productItemCount) { + throw new HttpException( + `Product count (${dto.count}) does not match the number of items (${productItemCount}) for product ID ${dto.productId}.`, + HttpStatus.BAD_REQUEST, + ); + } + } } diff --git a/src/space/services/space-validation.service.ts b/src/space/services/space-validation.service.ts index 56e6532..cd80387 100644 --- a/src/space/services/space-validation.service.ts +++ b/src/space/services/space-validation.service.ts @@ -59,7 +59,12 @@ export class ValidationService { async validateSpaceModel(spaceModelUuid: string): Promise { const spaceModel = await this.spaceModelRepository.findOne({ where: { uuid: spaceModelUuid }, - relations: ['subspaceModels'], + relations: [ + 'subspaceModels', + 'spaceProductModels', + 'spaceProductModels.product', + 'spaceProductModels.items', + ], }); if (!spaceModel) { diff --git a/src/space/services/space.service.ts b/src/space/services/space.service.ts index 135f2e5..5481d19 100644 --- a/src/space/services/space.service.ts +++ b/src/space/services/space.service.ts @@ -63,7 +63,7 @@ export class SpaceService { : null; try { - const newSpace = this.spaceRepository.create({ + const newSpace = queryRunner.manager.create(SpaceEntity, { ...addSpaceDto, spaceModel, parent: parentUuid ? parent : null, @@ -80,13 +80,13 @@ export class SpaceService { ); } - if (subspaces) { + if (subspaces?.length) { await this.subSpaceService.createSubspacesFromNames( subspaces, newSpace, queryRunner, ); - } else { + } else if (spaceModel && spaceModel.subspaceModels.length) { await this.subSpaceService.createSubSpaceFromModel( spaceModel, newSpace, @@ -98,6 +98,13 @@ export class SpaceService { await this.spaceProductService.assignProductsToSpace( newSpace, products, + queryRunner, + ); + } else if (spaceModel && spaceModel.spaceProductModels.length) { + await this.spaceProductService.createProductItemFromModel( + spaceModel, + newSpace, + queryRunner, ); } await queryRunner.commitTransaction(); @@ -216,7 +223,12 @@ export class SpaceService { updateSpaceDto: UpdateSpaceDto, ): Promise { const { communityUuid, spaceUuid, projectUuid } = params; + const queryRunner = this.dataSource.createQueryRunner(); + try { + await queryRunner.connect(); + await queryRunner.startTransaction(); + const space = await this.validationService.validateSpaceWithinCommunityAndProject( communityUuid, @@ -234,14 +246,16 @@ export class SpaceService { Object.assign(space, updateSpaceDto, { parent }); // Save the updated space - const updatedSpace = await this.spaceRepository.save(space); + const updatedSpace = await queryRunner.manager.save(space); if (products && products.length > 0) { await this.spaceProductService.assignProductsToSpace( updatedSpace, products, + queryRunner, ); } + await queryRunner.commitTransaction(); return new SuccessResponseDto({ message: `Space with ID ${spaceUuid} successfully updated`, @@ -249,6 +263,8 @@ export class SpaceService { statusCode: HttpStatus.OK, }); } catch (error) { + await queryRunner.rollbackTransaction(); + if (error instanceof HttpException) { throw error; } @@ -256,6 +272,8 @@ export class SpaceService { 'An error occurred while updating the space', HttpStatus.INTERNAL_SERVER_ERROR, ); + } finally { + await queryRunner.release(); } } @@ -348,13 +366,6 @@ export class SpaceService { return rootSpaces; } - private throwNotFound(entity: string, uuid: string) { - throw new HttpException( - `${entity} with ID ${uuid} not found`, - HttpStatus.NOT_FOUND, - ); - } - private validateSpaceCreation( spaceModelUuid?: string, products?: ProductAssignmentDto[], @@ -362,7 +373,7 @@ export class SpaceService { ) { if (spaceModelUuid && (products?.length || subSpaces?.length)) { throw new HttpException( - 'Space model cannot be assigned with products or subspaces.', + 'For space creation choose either space model or products and subspace', HttpStatus.CONFLICT, ); } diff --git a/src/space/services/subspace/subspace.service.ts b/src/space/services/subspace/subspace.service.ts index dae280b..4e9b2e3 100644 --- a/src/space/services/subspace/subspace.service.ts +++ b/src/space/services/subspace/subspace.service.ts @@ -49,9 +49,7 @@ export class SubSpaceService { ): Promise { const subSpaces = spaceModel.subspaceModels; - if (!subSpaces || subSpaces.length === 0) { - return; - } + if (!subSpaces?.length) return; const subspaceData = subSpaces.map((subSpaceModel) => ({ subspaceName: subSpaceModel.subspaceName, @@ -79,12 +77,11 @@ export class SubSpaceService { addSubspaceDto: AddSubspaceDto, params: GetSpaceParam, ): Promise { - const { communityUuid, spaceUuid, projectUuid } = params; const space = await this.validationService.validateSpaceWithinCommunityAndProject( - communityUuid, - projectUuid, - spaceUuid, + params.projectUuid, + params.projectUuid, + params.spaceUuid, ); try { diff --git a/src/space/space.module.ts b/src/space/space.module.ts index 3a52f7b..40a72d3 100644 --- a/src/space/space.module.ts +++ b/src/space/space.module.ts @@ -12,6 +12,7 @@ import { import { SpaceDeviceService, SpaceLinkService, + SpaceProductItemService, SpaceProductService, SpaceSceneService, SpaceService, @@ -24,6 +25,7 @@ import { SpaceRepository, SubspaceRepository, SpaceLinkRepository, + SpaceProductItemRepository, } from '@app/common/modules/space/repositories'; import { CommunityRepository } from '@app/common/modules/community/repositories'; import { @@ -87,6 +89,8 @@ import { ValidationService } from './services/space-validation.service'; ProjectRepository, SpaceModelRepository, SubspaceRepository, + SpaceProductItemService, + SpaceProductItemRepository, ], exports: [SpaceService], })