updated create space model with query runner

This commit is contained in:
hannathkadher
2024-12-11 13:23:37 +04:00
parent 4f4fd7b734
commit 72c8445d24
4 changed files with 109 additions and 80 deletions

View File

@ -6,10 +6,12 @@ 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';
import { DataSource } from 'typeorm';
@Injectable()
export class SpaceModelService {
constructor(
private readonly dataSource: DataSource,
private readonly spaceModelRepository: SpaceModelRepository,
private readonly projectRepository: ProjectRepository,
private readonly subSpaceModelService: SubSpaceModelService,
@ -24,6 +26,11 @@ export class SpaceModelService {
createSpaceModelDto;
const project = await this.validateProject(params.projectUuid);
const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
const isModelExist = await this.validateName(
modelName,
@ -40,17 +47,24 @@ export class SpaceModelService {
modelName,
project,
});
const savedSpaceModel = await this.spaceModelRepository.save(spaceModel);
const savedSpaceModel = await queryRunner.manager.save(spaceModel);
await this.subSpaceModelService.createSubSpaceModels(
subspaceModels,
savedSpaceModel,
);
if (subspaceModels) {
await this.subSpaceModelService.createSubSpaceModels(
subspaceModels,
savedSpaceModel,
queryRunner,
);
}
await this.spaceProductModelService.createSpaceProductModels(
spaceProductModels,
savedSpaceModel,
);
if (spaceProductModels) {
await this.spaceProductModelService.createSpaceProductModels(
spaceProductModels,
savedSpaceModel,
queryRunner,
);
}
await queryRunner.commitTransaction();
return new SuccessResponseDto({
message: `Successfully created new space model with uuid ${savedSpaceModel.uuid}`,
@ -58,6 +72,8 @@ export class SpaceModelService {
statusCode: HttpStatus.CREATED,
});
} catch (error) {
await queryRunner.rollbackTransaction();
if (error instanceof HttpException) {
throw error;
}
@ -66,6 +82,8 @@ export class SpaceModelService {
error.message || `An unexpected error occurred`,
HttpStatus.INTERNAL_SERVER_ERROR,
);
} finally {
await queryRunner.release();
}
}

View File

@ -5,6 +5,7 @@ import {
} from '@app/common/modules/space-model';
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { CreateSpaceProductItemModelDto } from '../dtos';
import { QueryRunner } from 'typeorm';
@Injectable()
export class SpaceProductItemModelService {
@ -16,41 +17,37 @@ export class SpaceProductItemModelService {
itemModelDtos: CreateSpaceProductItemModelDto[],
spaceProductModel: SpaceProductModelEntity,
spaceModel: SpaceModelEntity,
queryRunner: QueryRunner,
) {
try {
await this.validateTags(itemModelDtos, spaceModel);
await this.validateTags(itemModelDtos, spaceModel, queryRunner);
for (const itemModelDto of itemModelDtos) {
await this.create(itemModelDto, spaceProductModel, spaceModel);
}
try {
const productItems = itemModelDtos.map((dto) =>
queryRunner.manager.create(this.spaceProductItemRepository.target, {
tag: dto.tag,
spaceProductModel,
spaceModel,
}),
);
await queryRunner.manager.save(productItems);
} catch (error) {
if (error instanceof HttpException) {
throw error;
}
throw new HttpException(
error.message || `An unexpected error occurred`,
error.message ||
'An unexpected error occurred while creating product items.',
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(
private async validateTags(
itemModelDtos: CreateSpaceProductItemModelDto[],
spaceModel: SpaceModelEntity,
queryRunner: QueryRunner,
) {
const incomingTags = itemModelDtos.map((item) => item.tag);
@ -59,15 +56,18 @@ export class SpaceProductItemModelService {
);
if (duplicateTags.length > 0) {
throw new HttpException(
`Duplicate tags found in request: ${duplicateTags.join(', ')}`,
HttpStatus.CONFLICT,
`Duplicate tags found in the request: ${[...new Set(duplicateTags)].join(', ')}`,
HttpStatus.BAD_REQUEST,
);
}
const existingTags = await this.spaceProductItemRepository.find({
where: { spaceModel },
select: ['tag'],
});
const existingTags = await queryRunner.manager.find(
this.spaceProductItemRepository.target,
{
where: { spaceModel },
select: ['tag'],
},
);
const existingTagSet = new Set(existingTags.map((item) => item.tag));
const conflictingTags = incomingTags.filter((tag) =>

View File

@ -6,6 +6,7 @@ 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';
import { QueryRunner } from 'typeorm';
@Injectable()
export class SpaceProductModelService {
@ -18,60 +19,66 @@ export class SpaceProductModelService {
async createSpaceProductModels(
spaceProductModelDtos: CreateSpaceProductModelDto[],
spaceModel: SpaceModelEntity,
queryRunner: QueryRunner,
) {
try {
for (const spaceProductModelDto of spaceProductModelDtos) {
await this.create(spaceProductModelDto, spaceModel);
}
const productModels = await Promise.all(
spaceProductModelDtos.map(async (dto) => {
this.validateProductCount(dto);
const product = await this.getProduct(dto.productId);
return queryRunner.manager.create(
this.spaceProductModelRepository.target,
{
product,
productCount: dto.productCount,
spaceModel,
},
);
}),
);
const savedProductModels = await queryRunner.manager.save(productModels);
await Promise.all(
spaceProductModelDtos.map((dto, index) =>
this.spaceProductItemModelService.createProdutItemModel(
dto.items,
savedProductModels[index],
spaceModel,
queryRunner,
),
),
);
} catch (error) {
if (error instanceof HttpException) {
throw error;
}
throw new HttpException(
error.message || `An unexpected error occurred`,
error.message ||
'An unexpected error occurred while creating product models.',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async create(
spaceProductModelDto: CreateSpaceProductModelDto,
spaceModel: SpaceModelEntity,
) {
this.validateCount(spaceProductModelDto);
const product = await this.productRepository.findOneBy({
uuid: spaceProductModelDto.productId,
});
if (!product) {
private validateProductCount(dto: CreateSpaceProductModelDto) {
const productItemCount = dto.items.length;
if (dto.productCount !== productItemCount) {
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,
);
}
private validateCount(spaceProductModelDto: CreateSpaceProductModelDto) {
const productItemCount = spaceProductModelDto.items.length;
if (spaceProductModelDto.productCount !== productItemCount) {
throw new HttpException(
`Product count (${spaceProductModelDto.productCount}) does not match the number of items (${productItemCount}) for product ID ${spaceProductModelDto.productId}.`,
`Product count (${dto.productCount}) does not match the number of items (${productItemCount}) for product ID ${dto.productId}.`,
HttpStatus.BAD_REQUEST,
);
}
}
private async getProduct(productId: string) {
const product = await this.productRepository.findOneBy({ uuid: productId });
if (!product) {
throw new HttpException(
`Product with ID ${productId} not found.`,
HttpStatus.NOT_FOUND,
);
}
return product;
}
}

View File

@ -4,6 +4,7 @@ import {
} from '@app/common/modules/space-model';
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { CreateSubspaceModelDto } from '../dtos';
import { QueryRunner } from 'typeorm';
@Injectable()
export class SubSpaceModelService {
@ -14,16 +15,19 @@ export class SubSpaceModelService {
async createSubSpaceModels(
subSpaceModelDtos: CreateSubspaceModelDto[],
spaceModel: SpaceModelEntity,
queryRunner: QueryRunner,
) {
this.validateInputDtos(subSpaceModelDtos);
try {
this.validateInputDtos(subSpaceModelDtos);
for (const subspaceDto of subSpaceModelDtos) {
const subspace = this.subspaceModelRepository.create({
const subspaces = subSpaceModelDtos.map((subspaceDto) =>
queryRunner.manager.create(this.subspaceModelRepository.target, {
subspaceName: subspaceDto.subspaceName,
spaceModel: spaceModel,
});
await this.subspaceModelRepository.save(subspace);
}
}),
);
await queryRunner.manager.save(subspaces);
} catch (error) {
if (error instanceof HttpException) {
throw error;