mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-16 02:36:19 +00:00
aadded product item to space
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
export * from './space.entity';
|
export * from './space.entity';
|
||||||
export * from './subspace.entity';
|
export * from './subspace';
|
||||||
export * from './space-product-item.entity';
|
|
||||||
export * from './space-product.entity';
|
export * from './space-product.entity';
|
||||||
|
export * from './space-product-item.entity';
|
||||||
export * from './space-link.entity';
|
export * from './space-link.entity';
|
||||||
|
@ -14,14 +14,13 @@ export class SpaceProductItemEntity extends AbstractEntity<SpaceProductItemDto>
|
|||||||
@ManyToOne(() => SpaceProductEntity, (spaceProduct) => spaceProduct.items, {
|
@ManyToOne(() => SpaceProductEntity, (spaceProduct) => spaceProduct.items, {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
})
|
})
|
||||||
public spaceProducts: SpaceProductEntity;
|
public spaceProduct: SpaceProductEntity;
|
||||||
|
|
||||||
@ManyToOne(
|
@ManyToOne(
|
||||||
() => SpaceProductItemModelEntity,
|
() => SpaceProductItemModelEntity,
|
||||||
(spaceProductItemModel) => spaceProductItemModel.items,
|
(spaceProductItemModel) => spaceProductItemModel.items,
|
||||||
{
|
{
|
||||||
nullable: true,
|
nullable: true,
|
||||||
onDelete: 'SET NULL',
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
public spaceProductItemModel?: SpaceProductItemModelEntity;
|
public spaceProductItemModel?: SpaceProductItemModelEntity;
|
||||||
|
@ -27,7 +27,7 @@ export class SpaceProductEntity extends AbstractEntity<SpaceProductEntity> {
|
|||||||
})
|
})
|
||||||
productCount: number;
|
productCount: number;
|
||||||
|
|
||||||
@OneToMany(() => SpaceProductItemEntity, (item) => item.spaceProducts, {
|
@OneToMany(() => SpaceProductItemEntity, (item) => item.spaceProduct, {
|
||||||
cascade: true,
|
cascade: true,
|
||||||
})
|
})
|
||||||
public items: SpaceProductItemEntity[];
|
public items: SpaceProductItemEntity[];
|
||||||
|
@ -11,7 +11,7 @@ import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
|||||||
import { UserSpaceEntity } from '../../user/entities';
|
import { UserSpaceEntity } from '../../user/entities';
|
||||||
import { DeviceEntity } from '../../device/entities';
|
import { DeviceEntity } from '../../device/entities';
|
||||||
import { CommunityEntity } from '../../community/entities';
|
import { CommunityEntity } from '../../community/entities';
|
||||||
import { SubspaceEntity } from './subspace.entity';
|
import { SubspaceEntity } from './subspace';
|
||||||
import { SpaceLinkEntity } from './space-link.entity';
|
import { SpaceLinkEntity } from './space-link.entity';
|
||||||
import { SpaceProductEntity } from './space-product.entity';
|
import { SpaceProductEntity } from './space-product.entity';
|
||||||
import { SceneEntity } from '../../scene/entities';
|
import { SceneEntity } from '../../scene/entities';
|
||||||
|
1
libs/common/src/modules/space/entities/subspace/index.ts
Normal file
1
libs/common/src/modules/space/entities/subspace/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './subspace.entity';
|
@ -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 { Column, Entity, JoinColumn, ManyToOne, OneToMany } from 'typeorm';
|
||||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
import { SubspaceDto } from '../../dtos';
|
||||||
import { DeviceEntity } from '../../device/entities';
|
import { SpaceEntity } from '../space.entity';
|
||||||
import { SpaceEntity } from './space.entity';
|
|
||||||
import { SubspaceDto } from '../dtos';
|
|
||||||
import { SubspaceModelEntity } from '../../space-model';
|
|
||||||
|
|
||||||
@Entity({ name: 'subspace' })
|
@Entity({ name: 'subspace' })
|
||||||
export class SubspaceEntity extends AbstractEntity<SubspaceDto> {
|
export class SubspaceEntity extends AbstractEntity<SubspaceDto> {
|
4
libs/common/src/modules/space/index.ts
Normal file
4
libs/common/src/modules/space/index.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export * from './dtos';
|
||||||
|
export * from './entities';
|
||||||
|
export * from './repositories';
|
||||||
|
export * from './space.repository.module';
|
@ -1,7 +1,12 @@
|
|||||||
import { DataSource, Repository } from 'typeorm';
|
import { DataSource, Repository } from 'typeorm';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { SpaceProductEntity } from '../entities/space-product.entity';
|
import { SpaceProductEntity } from '../entities/space-product.entity';
|
||||||
import { SpaceEntity, SpaceLinkEntity, SubspaceEntity } from '../entities';
|
import {
|
||||||
|
SpaceEntity,
|
||||||
|
SpaceLinkEntity,
|
||||||
|
SpaceProductItemEntity,
|
||||||
|
SubspaceEntity,
|
||||||
|
} from '../entities';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SpaceRepository extends Repository<SpaceEntity> {
|
export class SpaceRepository extends Repository<SpaceEntity> {
|
||||||
@ -28,3 +33,10 @@ export class SpaceProductRepository extends Repository<SpaceProductEntity> {
|
|||||||
super(SpaceProductEntity, dataSource.createEntityManager());
|
super(SpaceProductEntity, dataSource.createEntityManager());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SpaceProductItemRepository extends Repository<SpaceProductItemEntity> {
|
||||||
|
constructor(private dataSource: DataSource) {
|
||||||
|
super(SpaceProductItemEntity, dataSource.createEntityManager());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -20,13 +20,6 @@ export class SpaceProductItemModelService {
|
|||||||
queryRunner: QueryRunner,
|
queryRunner: QueryRunner,
|
||||||
) {
|
) {
|
||||||
await this.validateTags(itemModelDtos, queryRunner, spaceModel);
|
await this.validateTags(itemModelDtos, queryRunner, spaceModel);
|
||||||
|
|
||||||
if (!spaceProductModel) {
|
|
||||||
throw new HttpException(
|
|
||||||
'Space product model is required to create product items.',
|
|
||||||
HttpStatus.BAD_REQUEST,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
const productItems = itemModelDtos.map((dto) =>
|
const productItems = itemModelDtos.map((dto) =>
|
||||||
queryRunner.manager.create(this.spaceProductItemRepository.target, {
|
queryRunner.manager.create(this.spaceProductItemRepository.target, {
|
||||||
|
@ -5,3 +5,4 @@ export * from './subspace';
|
|||||||
export * from './space-link';
|
export * from './space-link';
|
||||||
export * from './space-scene.service';
|
export * from './space-scene.service';
|
||||||
export * from './space-products';
|
export * from './space-products';
|
||||||
|
export * from './space-product-items';
|
||||||
|
1
src/space/services/space-product-items/index.ts
Normal file
1
src/space/services/space-product-items/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './space-product-items.service';
|
@ -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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,96 +2,98 @@ import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
|
|||||||
import { ProductRepository } from '@app/common/modules/product/repositories';
|
import { ProductRepository } from '@app/common/modules/product/repositories';
|
||||||
import { SpaceEntity } from '@app/common/modules/space/entities';
|
import { SpaceEntity } from '@app/common/modules/space/entities';
|
||||||
import { SpaceProductEntity } from '@app/common/modules/space/entities/space-product.entity';
|
import { SpaceProductEntity } from '@app/common/modules/space/entities/space-product.entity';
|
||||||
import { SpaceProductRepository } from '@app/common/modules/space/repositories';
|
import { In, QueryRunner } from 'typeorm';
|
||||||
import { In } from 'typeorm';
|
import { ProductAssignmentDto } from '../../dtos';
|
||||||
|
import { SpaceProductItemService } from '../space-product-items';
|
||||||
|
import { SpaceModelEntity } from '@app/common/modules/space-model';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SpaceProductService {
|
export class SpaceProductService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly productRepository: ProductRepository,
|
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(
|
async assignProductsToSpace(
|
||||||
space: SpaceEntity,
|
space: SpaceEntity,
|
||||||
products: { productId: string; count: number }[],
|
products: ProductAssignmentDto[],
|
||||||
|
queryRunner: QueryRunner,
|
||||||
): Promise<SpaceProductEntity[]> {
|
): Promise<SpaceProductEntity[]> {
|
||||||
|
let updatedProducts: SpaceProductEntity[] = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const uniqueProducts = this.validateUniqueProducts(products);
|
const uniqueProducts = this.validateUniqueProducts(products);
|
||||||
const productEntities = await this.getProductEntities(uniqueProducts);
|
const productEntities = await this.getProductEntities(uniqueProducts);
|
||||||
|
const existingSpaceProducts = await this.getExistingSpaceProducts(
|
||||||
|
space,
|
||||||
|
queryRunner,
|
||||||
|
);
|
||||||
|
|
||||||
// Fetch existing space products
|
if (existingSpaceProducts) {
|
||||||
const existingSpaceProducts = await this.spaceProductRepository.find({
|
updatedProducts = await this.updateExistingProducts(
|
||||||
where: {
|
existingSpaceProducts,
|
||||||
space: {
|
uniqueProducts,
|
||||||
uuid: space.uuid,
|
productEntities,
|
||||||
},
|
queryRunner,
|
||||||
},
|
|
||||||
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 (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
|
const newProducts = await this.createNewProducts(
|
||||||
if (updatedProducts.length > 0) {
|
uniqueProducts,
|
||||||
await this.spaceProductRepository.save(updatedProducts);
|
productEntities,
|
||||||
}
|
space,
|
||||||
|
queryRunner,
|
||||||
if (newProducts.length > 0) {
|
);
|
||||||
await this.spaceProductRepository.save(newProducts);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [...updatedProducts, ...newProducts];
|
return [...updatedProducts, ...newProducts];
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error assigning products to space:', error);
|
|
||||||
|
|
||||||
if (!(error instanceof HttpException)) {
|
if (!(error instanceof HttpException)) {
|
||||||
throw new 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,
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private validateUniqueProducts(
|
private validateUniqueProducts(
|
||||||
products: { productId: string; count: number }[],
|
products: ProductAssignmentDto[],
|
||||||
): { productId: string; count: number }[] {
|
): ProductAssignmentDto[] {
|
||||||
const productIds = new Set();
|
const productIds = new Set();
|
||||||
const uniqueProducts = [];
|
const uniqueProducts = [];
|
||||||
|
|
||||||
@ -110,15 +112,13 @@ export class SpaceProductService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async getProductEntities(
|
private async getProductEntities(
|
||||||
products: { productId: string; count: number }[],
|
products: ProductAssignmentDto[],
|
||||||
): Promise<Map<string, any>> {
|
): Promise<Map<string, any>> {
|
||||||
try {
|
try {
|
||||||
const productIds = products.map((p) => p.productId);
|
const productIds = products.map((p) => p.productId);
|
||||||
|
|
||||||
const productEntities = await this.productRepository.find({
|
const productEntities = await this.productRepository.find({
|
||||||
where: { uuid: In(productIds) },
|
where: { uuid: In(productIds) },
|
||||||
});
|
});
|
||||||
|
|
||||||
return new Map(productEntities.map((p) => [p.uuid, p]));
|
return new Map(productEntities.map((p) => [p.uuid, p]));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching product entities:', error);
|
console.error('Error fetching product entities:', error);
|
||||||
@ -128,4 +128,90 @@ export class SpaceProductService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async getExistingSpaceProducts(
|
||||||
|
space: SpaceEntity,
|
||||||
|
queryRunner: QueryRunner,
|
||||||
|
): Promise<SpaceProductEntity[]> {
|
||||||
|
return queryRunner.manager.find(SpaceProductEntity, {
|
||||||
|
where: { space: { uuid: space.uuid } },
|
||||||
|
relations: ['product'],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async updateExistingProducts(
|
||||||
|
existingSpaceProducts: SpaceProductEntity[],
|
||||||
|
uniqueProducts: ProductAssignmentDto[],
|
||||||
|
productEntities: Map<string, any>,
|
||||||
|
queryRunner: QueryRunner,
|
||||||
|
): Promise<SpaceProductEntity[]> {
|
||||||
|
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<string, any>,
|
||||||
|
space: SpaceEntity,
|
||||||
|
queryRunner: QueryRunner,
|
||||||
|
): Promise<SpaceProductEntity[]> {
|
||||||
|
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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,12 @@ export class ValidationService {
|
|||||||
async validateSpaceModel(spaceModelUuid: string): Promise<SpaceModelEntity> {
|
async validateSpaceModel(spaceModelUuid: string): Promise<SpaceModelEntity> {
|
||||||
const spaceModel = await this.spaceModelRepository.findOne({
|
const spaceModel = await this.spaceModelRepository.findOne({
|
||||||
where: { uuid: spaceModelUuid },
|
where: { uuid: spaceModelUuid },
|
||||||
relations: ['subspaceModels'],
|
relations: [
|
||||||
|
'subspaceModels',
|
||||||
|
'spaceProductModels',
|
||||||
|
'spaceProductModels.product',
|
||||||
|
'spaceProductModels.items',
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!spaceModel) {
|
if (!spaceModel) {
|
||||||
|
@ -63,7 +63,7 @@ export class SpaceService {
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const newSpace = this.spaceRepository.create({
|
const newSpace = queryRunner.manager.create(SpaceEntity, {
|
||||||
...addSpaceDto,
|
...addSpaceDto,
|
||||||
spaceModel,
|
spaceModel,
|
||||||
parent: parentUuid ? parent : null,
|
parent: parentUuid ? parent : null,
|
||||||
@ -80,13 +80,13 @@ export class SpaceService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subspaces) {
|
if (subspaces?.length) {
|
||||||
await this.subSpaceService.createSubspacesFromNames(
|
await this.subSpaceService.createSubspacesFromNames(
|
||||||
subspaces,
|
subspaces,
|
||||||
newSpace,
|
newSpace,
|
||||||
queryRunner,
|
queryRunner,
|
||||||
);
|
);
|
||||||
} else {
|
} else if (spaceModel && spaceModel.subspaceModels.length) {
|
||||||
await this.subSpaceService.createSubSpaceFromModel(
|
await this.subSpaceService.createSubSpaceFromModel(
|
||||||
spaceModel,
|
spaceModel,
|
||||||
newSpace,
|
newSpace,
|
||||||
@ -98,6 +98,13 @@ export class SpaceService {
|
|||||||
await this.spaceProductService.assignProductsToSpace(
|
await this.spaceProductService.assignProductsToSpace(
|
||||||
newSpace,
|
newSpace,
|
||||||
products,
|
products,
|
||||||
|
queryRunner,
|
||||||
|
);
|
||||||
|
} else if (spaceModel && spaceModel.spaceProductModels.length) {
|
||||||
|
await this.spaceProductService.createProductItemFromModel(
|
||||||
|
spaceModel,
|
||||||
|
newSpace,
|
||||||
|
queryRunner,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
await queryRunner.commitTransaction();
|
await queryRunner.commitTransaction();
|
||||||
@ -216,7 +223,12 @@ export class SpaceService {
|
|||||||
updateSpaceDto: UpdateSpaceDto,
|
updateSpaceDto: UpdateSpaceDto,
|
||||||
): Promise<BaseResponseDto> {
|
): Promise<BaseResponseDto> {
|
||||||
const { communityUuid, spaceUuid, projectUuid } = params;
|
const { communityUuid, spaceUuid, projectUuid } = params;
|
||||||
|
const queryRunner = this.dataSource.createQueryRunner();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
await queryRunner.connect();
|
||||||
|
await queryRunner.startTransaction();
|
||||||
|
|
||||||
const space =
|
const space =
|
||||||
await this.validationService.validateSpaceWithinCommunityAndProject(
|
await this.validationService.validateSpaceWithinCommunityAndProject(
|
||||||
communityUuid,
|
communityUuid,
|
||||||
@ -234,14 +246,16 @@ export class SpaceService {
|
|||||||
Object.assign(space, updateSpaceDto, { parent });
|
Object.assign(space, updateSpaceDto, { parent });
|
||||||
|
|
||||||
// Save the updated space
|
// Save the updated space
|
||||||
const updatedSpace = await this.spaceRepository.save(space);
|
const updatedSpace = await queryRunner.manager.save(space);
|
||||||
|
|
||||||
if (products && products.length > 0) {
|
if (products && products.length > 0) {
|
||||||
await this.spaceProductService.assignProductsToSpace(
|
await this.spaceProductService.assignProductsToSpace(
|
||||||
updatedSpace,
|
updatedSpace,
|
||||||
products,
|
products,
|
||||||
|
queryRunner,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
await queryRunner.commitTransaction();
|
||||||
|
|
||||||
return new SuccessResponseDto({
|
return new SuccessResponseDto({
|
||||||
message: `Space with ID ${spaceUuid} successfully updated`,
|
message: `Space with ID ${spaceUuid} successfully updated`,
|
||||||
@ -249,6 +263,8 @@ export class SpaceService {
|
|||||||
statusCode: HttpStatus.OK,
|
statusCode: HttpStatus.OK,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
await queryRunner.rollbackTransaction();
|
||||||
|
|
||||||
if (error instanceof HttpException) {
|
if (error instanceof HttpException) {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
@ -256,6 +272,8 @@ export class SpaceService {
|
|||||||
'An error occurred while updating the space',
|
'An error occurred while updating the space',
|
||||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
);
|
);
|
||||||
|
} finally {
|
||||||
|
await queryRunner.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,13 +366,6 @@ export class SpaceService {
|
|||||||
return rootSpaces;
|
return rootSpaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
private throwNotFound(entity: string, uuid: string) {
|
|
||||||
throw new HttpException(
|
|
||||||
`${entity} with ID ${uuid} not found`,
|
|
||||||
HttpStatus.NOT_FOUND,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private validateSpaceCreation(
|
private validateSpaceCreation(
|
||||||
spaceModelUuid?: string,
|
spaceModelUuid?: string,
|
||||||
products?: ProductAssignmentDto[],
|
products?: ProductAssignmentDto[],
|
||||||
@ -362,7 +373,7 @@ export class SpaceService {
|
|||||||
) {
|
) {
|
||||||
if (spaceModelUuid && (products?.length || subSpaces?.length)) {
|
if (spaceModelUuid && (products?.length || subSpaces?.length)) {
|
||||||
throw new HttpException(
|
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,
|
HttpStatus.CONFLICT,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -49,9 +49,7 @@ export class SubSpaceService {
|
|||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const subSpaces = spaceModel.subspaceModels;
|
const subSpaces = spaceModel.subspaceModels;
|
||||||
|
|
||||||
if (!subSpaces || subSpaces.length === 0) {
|
if (!subSpaces?.length) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const subspaceData = subSpaces.map((subSpaceModel) => ({
|
const subspaceData = subSpaces.map((subSpaceModel) => ({
|
||||||
subspaceName: subSpaceModel.subspaceName,
|
subspaceName: subSpaceModel.subspaceName,
|
||||||
@ -79,12 +77,11 @@ export class SubSpaceService {
|
|||||||
addSubspaceDto: AddSubspaceDto,
|
addSubspaceDto: AddSubspaceDto,
|
||||||
params: GetSpaceParam,
|
params: GetSpaceParam,
|
||||||
): Promise<BaseResponseDto> {
|
): Promise<BaseResponseDto> {
|
||||||
const { communityUuid, spaceUuid, projectUuid } = params;
|
|
||||||
const space =
|
const space =
|
||||||
await this.validationService.validateSpaceWithinCommunityAndProject(
|
await this.validationService.validateSpaceWithinCommunityAndProject(
|
||||||
communityUuid,
|
params.projectUuid,
|
||||||
projectUuid,
|
params.projectUuid,
|
||||||
spaceUuid,
|
params.spaceUuid,
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
SpaceDeviceService,
|
SpaceDeviceService,
|
||||||
SpaceLinkService,
|
SpaceLinkService,
|
||||||
|
SpaceProductItemService,
|
||||||
SpaceProductService,
|
SpaceProductService,
|
||||||
SpaceSceneService,
|
SpaceSceneService,
|
||||||
SpaceService,
|
SpaceService,
|
||||||
@ -24,6 +25,7 @@ import {
|
|||||||
SpaceRepository,
|
SpaceRepository,
|
||||||
SubspaceRepository,
|
SubspaceRepository,
|
||||||
SpaceLinkRepository,
|
SpaceLinkRepository,
|
||||||
|
SpaceProductItemRepository,
|
||||||
} from '@app/common/modules/space/repositories';
|
} from '@app/common/modules/space/repositories';
|
||||||
import { CommunityRepository } from '@app/common/modules/community/repositories';
|
import { CommunityRepository } from '@app/common/modules/community/repositories';
|
||||||
import {
|
import {
|
||||||
@ -87,6 +89,8 @@ import { ValidationService } from './services/space-validation.service';
|
|||||||
ProjectRepository,
|
ProjectRepository,
|
||||||
SpaceModelRepository,
|
SpaceModelRepository,
|
||||||
SubspaceRepository,
|
SubspaceRepository,
|
||||||
|
SpaceProductItemService,
|
||||||
|
SpaceProductItemRepository,
|
||||||
],
|
],
|
||||||
exports: [SpaceService],
|
exports: [SpaceService],
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user