created space model create service

This commit is contained in:
hannathkadher
2024-12-11 10:51:17 +04:00
parent b945740fb8
commit b2a422f71b
11 changed files with 374 additions and 0 deletions
@@ -0,0 +1,33 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsString, IsArray, ValidateNested } from 'class-validator';
import { Type } from 'class-transformer';
import { CreateSubspaceModelDto } from './create-subspace-model.dto';
import { CreateSpaceProductModelDto } from './create-space-product-model.dto';
export class CreateSpaceModelDto {
@ApiProperty({
description: 'Name of the space model',
example: 'Apartment Model',
})
@IsNotEmpty()
@IsString()
modelName: string;
@ApiProperty({
description: 'List of subspaces included in the model',
type: [CreateSubspaceModelDto],
})
@IsArray()
@ValidateNested({ each: true })
@Type(() => CreateSubspaceModelDto)
subspaceModels?: CreateSubspaceModelDto[];
@ApiProperty({
description: 'List of products included in the model',
type: [CreateSpaceProductModelDto],
})
@IsArray()
@ValidateNested({ each: true })
@Type(() => CreateSpaceProductModelDto)
spaceProductModels?: CreateSpaceProductModelDto[];
}
@@ -0,0 +1,12 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsString } from 'class-validator';
export class CreateSpaceProductItemModelDto {
@ApiProperty({
description: 'Specific name for the product item',
example: 'Light 1',
})
@IsNotEmpty()
@IsString()
tag: string;
}
@@ -0,0 +1,30 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsString, IsArray, ValidateNested } from 'class-validator';
import { Type } from 'class-transformer';
import { CreateSpaceProductItemModelDto } from './create-space-product-item-model.dto';
export class CreateSpaceProductModelDto {
@ApiProperty({
description: 'ID of the product associated with the model',
example: 'product-uuid',
})
@IsNotEmpty()
@IsString()
productId: string;
@ApiProperty({
description: 'Number of products in the model',
example: 3,
})
@IsNotEmpty()
productCount: number;
@ApiProperty({
description: 'Specific names for each product item',
type: [CreateSpaceProductItemModelDto],
})
@IsArray()
@ValidateNested({ each: true })
@Type(() => CreateSpaceProductItemModelDto)
items: CreateSpaceProductItemModelDto[];
}
@@ -0,0 +1,12 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsString } from 'class-validator';
export class CreateSubspaceModelDto {
@ApiProperty({
description: 'Name of the subspace',
example: 'Living Room',
})
@IsNotEmpty()
@IsString()
subspaceName: string;
}
+5
View File
@@ -0,0 +1,5 @@
export * from './create-space-model.dto';
export * from './create-space-product-item-model.dto';
export * from './create-space-product-model.dto';
export * from './create-subspace-model.dto';
export * from './project-param.dto';
+11
View File
@@ -0,0 +1,11 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsUUID } from 'class-validator';
export class projectParam {
@ApiProperty({
description: 'UUID of the Project',
example: 'd290f1ee-6c54-4b01-90e6-d701748f0851',
})
@IsUUID()
projectUuid: string;
}
+4
View File
@@ -0,0 +1,4 @@
export * from './space-model.service';
export * from './space-product-item-model.service';
export * from './space-product-model.service';
export * from './subspace-model.service';
@@ -0,0 +1,94 @@
import { SpaceModelRepository } from '@app/common/modules/space-model';
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { CreateSpaceModelDto } from '../dtos';
import { ProjectRepository } from '@app/common/modules/project/repositiories';
import { ProjectParam } from 'src/community/dtos';
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
import { SubSpaceModelService } from './subspace-model.service';
import { SpaceProductModelService } from './space-product-model.service';
@Injectable()
export class SpaceModelService {
constructor(
private readonly spaceModelRepository: SpaceModelRepository,
private readonly projectRepository: ProjectRepository,
private readonly subSpaceModelService: SubSpaceModelService,
private readonly spaceProductModelService: SpaceProductModelService,
) {}
async createSpaceModel(
createSpaceModelDto: CreateSpaceModelDto,
params: ProjectParam,
) {
const { modelName, subspaceModels, spaceProductModels } =
createSpaceModelDto;
const project = await this.validateProject(params.projectUuid);
try {
const isModelExist = await this.validateName(
modelName,
params.projectUuid,
);
if (isModelExist) {
throw new HttpException(
`Model name "${modelName}" already exists in this project ${project.name}.`,
HttpStatus.CONFLICT,
);
}
const spaceModel = await this.spaceModelRepository.create({
modelName,
project,
});
const savedSpaceModel = await this.spaceModelRepository.save(spaceModel);
await this.subSpaceModelService.createSubSpaceModels(
subspaceModels,
savedSpaceModel,
);
await this.spaceProductModelService.createSpaceProductModels(
spaceProductModels,
savedSpaceModel,
);
return new SuccessResponseDto({
message: `Successfully created new space model with uuid ${savedSpaceModel.uuid}`,
data: savedSpaceModel,
statusCode: HttpStatus.CREATED,
});
} catch (error) {
if (error instanceof HttpException) {
throw error;
}
throw new HttpException(
error.message || `An unexpected error occurred`,
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async validateProject(projectUuid: string) {
const project = await this.projectRepository.findOne({
where: {
uuid: projectUuid,
},
});
if (!project) {
throw new HttpException(
`Project with uuid ${projectUuid} not found`,
HttpStatus.NOT_FOUND,
);
}
return project;
}
async validateName(modelName: string, projectUuid: string): Promise<boolean> {
const isModelExist = await this.spaceModelRepository.exists({
where: { modelName, project: { uuid: projectUuid } },
});
return isModelExist;
}
}
@@ -0,0 +1,79 @@
import {
SpaceModelEntity,
SpaceProductItemModelRepository,
SpaceProductModelEntity,
} from '@app/common/modules/space-model';
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { CreateSpaceProductItemModelDto } from '../dtos';
@Injectable()
export class SpaceProductItemModelService {
constructor(
private readonly spaceProductItemRepository: SpaceProductItemModelRepository,
) {}
async createProdutItemModel(
itemModelDtos: CreateSpaceProductItemModelDto[],
spaceProductModel: SpaceProductModelEntity,
spaceModel: SpaceModelEntity,
) {
try {
await this.validateTags(itemModelDtos, spaceModel);
for (const itemModelDto of itemModelDtos) {
await this.create(itemModelDto, spaceProductModel, spaceModel);
}
} catch (error) {
throw new HttpException(
error.message || `An unexpected error occurred`,
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async create(
itemModelDto: CreateSpaceProductItemModelDto,
spaceProductModel: SpaceProductModelEntity,
spaceModel: SpaceModelEntity,
) {
const productItem = this.spaceProductItemRepository.create({
tag: itemModelDto.tag,
spaceProductModel,
spaceModel,
});
await this.spaceProductItemRepository.save(productItem);
}
async validateTags(
itemModelDtos: CreateSpaceProductItemModelDto[],
spaceModel: SpaceModelEntity,
) {
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 request: ${duplicateTags.join(', ')}`,
HttpStatus.CONFLICT,
);
}
const existingTags = await this.spaceProductItemRepository.find({
where: { spaceModel },
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,
);
}
}
}
@@ -0,0 +1,61 @@
import {
SpaceModelEntity,
SpaceProductModelRepository,
} from '@app/common/modules/space-model';
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { CreateSpaceProductModelDto } from '../dtos';
import { ProductRepository } from '@app/common/modules/product/repositories';
import { SpaceProductItemModelService } from './space-product-item-model.service';
@Injectable()
export class SpaceProductModelService {
constructor(
private readonly spaceProductModelRepository: SpaceProductModelRepository,
private readonly productRepository: ProductRepository,
private readonly spaceProductItemModelService: SpaceProductItemModelService,
) {}
async createSpaceProductModels(
spaceProductModelDtos: CreateSpaceProductModelDto[],
spaceModel: SpaceModelEntity,
) {
try {
for (const spaceProductModelDto of spaceProductModelDtos) {
await this.create(spaceProductModelDto, spaceModel);
}
} catch (error) {
throw new HttpException(
error.message || `An unexpected error occurred`,
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async create(
spaceProductModelDto: CreateSpaceProductModelDto,
spaceModel: SpaceModelEntity,
) {
const product = await this.productRepository.findOneBy({
uuid: spaceProductModelDto.productId,
});
if (!product) {
throw new HttpException(
`Product with ID ${spaceProductModelDto.productId} not found`,
HttpStatus.NOT_FOUND,
);
}
const spaceProductModel = this.spaceProductModelRepository.create({
product,
productCount: spaceProductModelDto.productCount,
spaceModel: spaceModel,
});
const newProductModel =
await this.spaceProductModelRepository.save(spaceProductModel);
await this.spaceProductItemModelService.createProdutItemModel(
spaceProductModelDto.items,
newProductModel,
spaceModel,
);
}
}
@@ -0,0 +1,33 @@
import {
SpaceModelEntity,
SubspaceModelRepository,
} from '@app/common/modules/space-model';
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { CreateSubspaceModelDto } from '../dtos';
@Injectable()
export class SubSpaceModelService {
constructor(
private readonly subspaceModelRepository: SubspaceModelRepository,
) {}
async createSubSpaceModels(
subSpaceModelDtos: CreateSubspaceModelDto[],
spaceModel: SpaceModelEntity,
) {
try {
for (const subspaceDto of subSpaceModelDtos) {
const subspace = this.subspaceModelRepository.create({
subspaceName: subspaceDto.subspaceName,
spaceModel: spaceModel,
});
await this.subspaceModelRepository.save(subspace);
}
} catch (error) {
throw new HttpException(
error.message || `An unexpected error occurred`,
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
}