From 11564eece780f565876f3eef7bb2bd7852762f26 Mon Sep 17 00:00:00 2001 From: hannathkadher Date: Wed, 20 Nov 2024 16:34:44 +0400 Subject: [PATCH] added space product service --- src/space/dtos/add.space.dto.ts | 17 ++++ src/space/services/index.ts | 1 + src/space/services/space-products/index.ts | 1 + .../space-products/space-products.service.ts | 95 +++++++++++++++++++ src/space/services/space.service.ts | 11 ++- src/space/space.module.ts | 4 + 6 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 src/space/services/space-products/index.ts create mode 100644 src/space/services/space-products/space-products.service.ts diff --git a/src/space/dtos/add.space.dto.ts b/src/space/dtos/add.space.dto.ts index a33bb34..832287f 100644 --- a/src/space/dtos/add.space.dto.ts +++ b/src/space/dtos/add.space.dto.ts @@ -1,10 +1,13 @@ import { ApiProperty } from '@nestjs/swagger'; +import { Type } from 'class-transformer'; import { + IsArray, IsBoolean, IsNotEmpty, IsOptional, IsString, IsUUID, + ValidateNested, } from 'class-validator'; export class AddSpaceDto { @@ -32,6 +35,11 @@ export class AddSpaceDto { }) @IsBoolean() isPrivate: boolean; + + @IsArray() + @ValidateNested({ each: true }) + @Type(() => ProductAssignmentDto) + products: ProductAssignmentDto[]; } export class AddUserSpaceDto { @@ -69,7 +77,16 @@ export class AddUserSpaceUsingCodeDto { @IsString() @IsNotEmpty() public inviteCode: string; + constructor(dto: Partial) { Object.assign(this, dto); } } + +class ProductAssignmentDto { + @IsNotEmpty() + productId: string; + + @IsNotEmpty() + count: number; +} diff --git a/src/space/services/index.ts b/src/space/services/index.ts index c4e9405..89f8d9e 100644 --- a/src/space/services/index.ts +++ b/src/space/services/index.ts @@ -3,3 +3,4 @@ export * from './space-user.service'; export * from './space-device.service'; export * from './subspace'; export * from './space-scene.service'; +export * from './space-products'; diff --git a/src/space/services/space-products/index.ts b/src/space/services/space-products/index.ts new file mode 100644 index 0000000..d0b92d2 --- /dev/null +++ b/src/space/services/space-products/index.ts @@ -0,0 +1 @@ +export * from './space-products.service'; diff --git a/src/space/services/space-products/space-products.service.ts b/src/space/services/space-products/space-products.service.ts new file mode 100644 index 0000000..7c4d634 --- /dev/null +++ b/src/space/services/space-products/space-products.service.ts @@ -0,0 +1,95 @@ +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'; + +@Injectable() +export class SpaceProductService { + constructor( + private readonly productRepository: ProductRepository, + private readonly spaceProductRepository: SpaceProductRepository, + ) {} + + async assignProductsToSpace( + space: SpaceEntity, + products: { productId: string; count: number }[], + ): Promise { + try { + const uniqueProducts = this.validateUniqueProducts(products); + const productEntities = await this.getProductEntities(uniqueProducts); + + const spaceProductEntities = uniqueProducts.map( + ({ productId, count }) => { + const product = productEntities.get(productId); + if (!product) { + throw new HttpException( + `Product with ID ${productId} not found`, + HttpStatus.NOT_FOUND, + ); + } + + return this.spaceProductRepository.create({ + space, + product, + productCount: count, + }); + }, + ); + + return await this.spaceProductRepository.save(spaceProductEntities); + } 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', + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + + throw error; + } + } + + private validateUniqueProducts( + products: { productId: string; count: number }[], + ): { productId: string; count: number }[] { + const productIds = new Set(); + const uniqueProducts = []; + + for (const product of products) { + if (productIds.has(product.productId)) { + throw new HttpException( + `Duplicate product ID found: ${product.productId}`, + HttpStatus.BAD_REQUEST, + ); + } + productIds.add(product.productId); + uniqueProducts.push(product); + } + + return uniqueProducts; + } + + private async getProductEntities( + products: { productId: string; count: number }[], + ): Promise> { + try { + const productIds = products.map((p) => p.productId); + + const productEntities = await this.productRepository.find({ + where: { prodId: In(productIds) }, + }); + + return new Map(productEntities.map((p) => [p.prodId, p])); + } catch (error) { + console.error('Error fetching product entities:', error); + throw new HttpException( + 'Failed to fetch product entities', + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } +} diff --git a/src/space/services/space.service.ts b/src/space/services/space.service.ts index 78d45d7..7340c7c 100644 --- a/src/space/services/space.service.ts +++ b/src/space/services/space.service.ts @@ -11,12 +11,14 @@ import { BaseResponseDto } from '@app/common/dto/base.response.dto'; import { CommunityRepository } from '@app/common/modules/community/repositories'; import { SpaceEntity } from '@app/common/modules/space/entities'; import { generateRandomString } from '@app/common/helper/randomString'; +import { SpaceProductService } from './space-products'; @Injectable() export class SpaceService { constructor( private readonly spaceRepository: SpaceRepository, private readonly communityRepository: CommunityRepository, + private readonly spaceProductService: SpaceProductService, ) {} async createSpace( @@ -25,7 +27,7 @@ export class SpaceService { ): Promise { let parent: SpaceEntity | null = null; - const { parentUuid } = addSpaceDto; + const { parentUuid, products } = addSpaceDto; const community = await this.communityRepository.findOne({ where: { uuid: communityId }, }); @@ -60,6 +62,13 @@ export class SpaceService { await this.spaceRepository.save(newSpace); + if (products && products.length > 0) { + await this.spaceProductService.assignProductsToSpace( + newSpace, + products, + ); + } + return new SuccessResponseDto({ statusCode: HttpStatus.CREATED, data: newSpace, diff --git a/src/space/space.module.ts b/src/space/space.module.ts index c840bd9..030cb95 100644 --- a/src/space/space.module.ts +++ b/src/space/space.module.ts @@ -11,6 +11,7 @@ import { } from './controllers'; import { SpaceDeviceService, + SpaceProductService, SpaceSceneService, SpaceService, SpaceUserService, @@ -18,6 +19,7 @@ import { SubSpaceService, } from './services'; import { + SpaceProductRepository, SpaceRepository, SubspaceRepository, } from '@app/common/modules/space/repositories'; @@ -71,6 +73,8 @@ import { SceneDeviceRepository } from '@app/common/modules/scene-device/reposito DeviceStatusFirebaseService, DeviceStatusLogRepository, SceneDeviceRepository, + SpaceProductService, + SpaceProductRepository, ], exports: [SpaceService], })