mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-15 10:25:23 +00:00
space product service
This commit is contained in:
@ -24,7 +24,7 @@ export class SubspaceEntity extends AbstractEntity<SubspaceDto> {
|
||||
nullable: false,
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn({ name: 'space_id' })
|
||||
@JoinColumn({ name: 'space_uuid' })
|
||||
space: SpaceEntity;
|
||||
|
||||
@OneToMany(() => DeviceEntity, (device) => device.subspace, {
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { Type } from 'class-transformer';
|
||||
import {
|
||||
ArrayNotEmpty,
|
||||
IsArray,
|
||||
IsBoolean,
|
||||
IsNotEmpty,
|
||||
@ -43,7 +42,6 @@ export class ProductAssignmentDto {
|
||||
example: [{ tag: 'Light 1' }, { tag: 'Light 2' }, { tag: 'Light 3' }],
|
||||
})
|
||||
@IsArray()
|
||||
@ArrayNotEmpty()
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => CreateSpaceProductItemDto)
|
||||
items: CreateSpaceProductItemDto[];
|
||||
|
@ -78,6 +78,27 @@ export class SpaceProductItemService {
|
||||
queryRunner: QueryRunner,
|
||||
space: SpaceEntity,
|
||||
) {
|
||||
const query = `
|
||||
SELECT spi.tag
|
||||
FROM "space-product-item" spi
|
||||
INNER JOIN "space-product" spm
|
||||
ON spi.space_product_uuid = spm.uuid
|
||||
WHERE spm.space_uuid = $1
|
||||
|
||||
UNION
|
||||
|
||||
SELECT spi.tag
|
||||
FROM "subspace-product-item" spi
|
||||
INNER JOIN "subspace-product" spm
|
||||
ON spi.subspace_product_uuid = spm.uuid
|
||||
INNER JOIN "subspace" sm
|
||||
ON spm.subspace_uuid = sm.uuid
|
||||
WHERE sm.space_uuid = $1;
|
||||
`;
|
||||
|
||||
const result = await queryRunner.manager.query(query, [space.uuid]);
|
||||
console.log(result);
|
||||
|
||||
const incomingTags = itemModelDtos.map((item) => item.tag);
|
||||
|
||||
const duplicateTags = incomingTags.filter(
|
||||
@ -90,13 +111,7 @@ export class SpaceProductItemService {
|
||||
);
|
||||
}
|
||||
|
||||
const existingTags = await queryRunner.manager.find(
|
||||
this.spaceProductItemRepository.target,
|
||||
{
|
||||
where: { spaceProduct: { space } },
|
||||
select: ['tag'],
|
||||
},
|
||||
);
|
||||
const existingTags = await queryRunner.manager.query(query, [space.uuid]);
|
||||
const existingTagSet = new Set(existingTags.map((item) => item.tag));
|
||||
|
||||
const conflictingTags = incomingTags.filter((tag) =>
|
||||
|
@ -14,7 +14,7 @@ export class SpaceProductService {
|
||||
private readonly spaceProductItemService: SpaceProductItemService,
|
||||
) {}
|
||||
|
||||
async createProductItemFromModel(
|
||||
async createFromModel(
|
||||
spaceModel: SpaceModelEntity,
|
||||
space: SpaceEntity,
|
||||
queryRunner: QueryRunner,
|
||||
|
@ -81,7 +81,7 @@ export class SpaceService {
|
||||
}
|
||||
|
||||
if (subspaces?.length) {
|
||||
await this.subSpaceService.createSubspacesFromNames(
|
||||
await this.subSpaceService.createSubspacesFromDto(
|
||||
subspaces,
|
||||
newSpace,
|
||||
queryRunner,
|
||||
@ -101,7 +101,7 @@ export class SpaceService {
|
||||
queryRunner,
|
||||
);
|
||||
} else if (spaceModel && spaceModel.spaceProductModels.length) {
|
||||
await this.spaceProductService.createProductItemFromModel(
|
||||
await this.spaceProductService.createFromModel(
|
||||
spaceModel,
|
||||
newSpace,
|
||||
queryRunner,
|
||||
|
@ -1,9 +1,17 @@
|
||||
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
|
||||
import { QueryRunner } from 'typeorm';
|
||||
|
||||
import { SubspaceProductEntity } from '@app/common/modules/space';
|
||||
import { SubspaceProductModelEntity } from '@app/common/modules/space-model';
|
||||
import {
|
||||
SpaceEntity,
|
||||
SubspaceProductEntity,
|
||||
SubspaceProductItemEntity,
|
||||
} from '@app/common/modules/space';
|
||||
import {
|
||||
SubspaceProductItemModelEntity,
|
||||
SubspaceProductModelEntity,
|
||||
} from '@app/common/modules/space-model';
|
||||
import { SubspaceProductItemRepository } from '@app/common/modules/space/repositories/subspace.repository';
|
||||
import { CreateSpaceProductItemDto } from 'src/space/dtos';
|
||||
|
||||
@Injectable()
|
||||
export class SubspaceProductItemService {
|
||||
@ -39,12 +47,98 @@ export class SubspaceProductItemService {
|
||||
|
||||
private createProductItem(
|
||||
product: SubspaceProductEntity,
|
||||
model: any,
|
||||
model: SubspaceProductItemModelEntity,
|
||||
queryRunner: QueryRunner,
|
||||
): Partial<any> {
|
||||
return queryRunner.manager.create(this.productItemRepository.target, {
|
||||
tag: model.tag,
|
||||
product,
|
||||
model,
|
||||
});
|
||||
}
|
||||
|
||||
async createItemFromDtos(
|
||||
product: SubspaceProductEntity,
|
||||
itemDto: CreateSpaceProductItemDto[],
|
||||
queryRunner: QueryRunner,
|
||||
space: SpaceEntity,
|
||||
) {
|
||||
if (!itemDto?.length) return;
|
||||
|
||||
try {
|
||||
await this.validateTags(itemDto, queryRunner, space);
|
||||
|
||||
const productItems = itemDto.map((dto) =>
|
||||
queryRunner.manager.create(SubspaceProductItemEntity, {
|
||||
tag: dto.tag,
|
||||
subspaceProduct: product,
|
||||
}),
|
||||
);
|
||||
|
||||
await queryRunner.manager.save(
|
||||
this.productItemRepository.target,
|
||||
productItems,
|
||||
);
|
||||
} catch (error) {
|
||||
throw new HttpException(
|
||||
error.message || 'An error occurred while creating product items.',
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async validateTags(
|
||||
subspaceItemModelDtos: CreateSpaceProductItemDto[],
|
||||
queryRunner: QueryRunner,
|
||||
space: SpaceEntity,
|
||||
) {
|
||||
const incomingTags = subspaceItemModelDtos.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 existingTagsQuery = `
|
||||
SELECT spi.tag
|
||||
FROM "space-product-item" spi
|
||||
INNER JOIN "space-product" spm
|
||||
ON spi.space_product_uuid = spm.uuid
|
||||
WHERE spm.space_uuid = $1
|
||||
|
||||
UNION
|
||||
|
||||
SELECT spi.tag
|
||||
FROM "subspace-product-item" spi
|
||||
INNER JOIN "subspace-product" spm
|
||||
ON spi.subspace_product_uuid = spm.uuid
|
||||
INNER JOIN "subspace" sm
|
||||
ON spm.subspace_uuid = sm.uuid
|
||||
WHERE sm.space_uuid = $1;
|
||||
`;
|
||||
|
||||
const existingTags = await queryRunner.manager.query(existingTagsQuery, [
|
||||
space.uuid,
|
||||
]);
|
||||
|
||||
console.log(existingTags);
|
||||
|
||||
const existingTagsSet = new Set(
|
||||
existingTags.map((row: { tag: string }) => row.tag),
|
||||
);
|
||||
const conflictingTags = [...incomingTags].filter((tag) =>
|
||||
existingTagsSet.has(tag),
|
||||
);
|
||||
if (conflictingTags.length > 0) {
|
||||
throw new HttpException(
|
||||
`Tags already exist in the model: ${conflictingTags.join(', ')}`,
|
||||
HttpStatus.CONFLICT,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import { QueryRunner } from 'typeorm';
|
||||
|
||||
import {
|
||||
SpaceEntity,
|
||||
SubspaceEntity,
|
||||
SubspaceProductEntity,
|
||||
} from '@app/common/modules/space';
|
||||
@ -10,11 +11,15 @@ import {
|
||||
SubspaceProductModelEntity,
|
||||
} from '@app/common/modules/space-model';
|
||||
import { SubspaceProductItemService } from './subspace-product-item.service';
|
||||
import { ProductAssignmentDto } from 'src/space/dtos';
|
||||
import { ProductService } from 'src/product/services';
|
||||
import { ProductEntity } from '@app/common/modules/product/entities';
|
||||
|
||||
@Injectable()
|
||||
export class SubspaceProductService {
|
||||
constructor(
|
||||
private readonly subspaceProductItemService: SubspaceProductItemService,
|
||||
private readonly productService: ProductService,
|
||||
) {}
|
||||
|
||||
async createFromModel(
|
||||
@ -63,4 +68,61 @@ export class SubspaceProductService {
|
||||
model: productModel,
|
||||
};
|
||||
}
|
||||
|
||||
async createFromDto(
|
||||
productDtos: ProductAssignmentDto[],
|
||||
subspace: SubspaceEntity,
|
||||
queryRunner: QueryRunner,
|
||||
space: SpaceEntity,
|
||||
): Promise<void> {
|
||||
try {
|
||||
const newSpaceProducts = await Promise.all(
|
||||
productDtos.map(async (dto) => {
|
||||
this.validateProductCount(dto);
|
||||
|
||||
const product = await this.getProduct(dto.productId);
|
||||
return queryRunner.manager.create(SubspaceProductEntity, {
|
||||
subspace,
|
||||
product,
|
||||
productCount: dto.count,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
const subspaceProducts = await queryRunner.manager.save(
|
||||
SubspaceProductEntity,
|
||||
newSpaceProducts,
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
productDtos.map((dto, index) =>
|
||||
this.subspaceProductItemService.createItemFromDtos(
|
||||
subspaceProducts[index],
|
||||
dto.items,
|
||||
queryRunner,
|
||||
space,
|
||||
),
|
||||
),
|
||||
);
|
||||
} catch (error) {
|
||||
throw new HttpException(
|
||||
`Failed to create subspace products from DTOs. Error: ${error.message}`,
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async getProduct(productId: string): Promise<ProductEntity> {
|
||||
const product = await this.productService.findOne(productId);
|
||||
return product.data;
|
||||
}
|
||||
|
||||
async validateProductCount(dto: ProductAssignmentDto) {
|
||||
if (dto.count !== dto.items.length) {
|
||||
throw new HttpException(
|
||||
'Producy item and count doesnot match',
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,17 +79,36 @@ export class SubSpaceService {
|
||||
);
|
||||
}
|
||||
|
||||
async createSubspacesFromNames(
|
||||
async createSubspacesFromDto(
|
||||
addSubspaceDtos: AddSubspaceDto[],
|
||||
space: SpaceEntity,
|
||||
queryRunner: QueryRunner,
|
||||
): Promise<SubspaceEntity[]> {
|
||||
const subspaceData = addSubspaceDtos.map((dto) => ({
|
||||
subspaceName: dto.subspaceName,
|
||||
space,
|
||||
}));
|
||||
try {
|
||||
const subspaceData = addSubspaceDtos.map((dto) => ({
|
||||
subspaceName: dto.subspaceName,
|
||||
space,
|
||||
}));
|
||||
|
||||
return await this.createSubspaces(subspaceData, queryRunner);
|
||||
const subspaces = await this.createSubspaces(subspaceData, queryRunner);
|
||||
|
||||
await Promise.all(
|
||||
addSubspaceDtos.map((dto, index) =>
|
||||
this.productService.createFromDto(
|
||||
dto.products,
|
||||
subspaces[index],
|
||||
queryRunner,
|
||||
space,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return subspaces;
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Transaction failed: Unable to create subspaces and products. ${error.message}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async createSubspace(
|
||||
|
@ -50,6 +50,7 @@ import { CommunityModule } from 'src/community/community.module';
|
||||
import { ValidationService } from './services';
|
||||
import {
|
||||
SubspaceProductItemRepository,
|
||||
SubspaceProductRepository,
|
||||
SubspaceRepository,
|
||||
} from '@app/common/modules/space/repositories/subspace.repository';
|
||||
import { SubspaceProductService } from './services';
|
||||
@ -99,6 +100,7 @@ import { SubspaceProductService } from './services';
|
||||
SpaceProductItemRepository,
|
||||
SubspaceProductService,
|
||||
SubspaceProductItemService,
|
||||
SubspaceProductRepository,
|
||||
],
|
||||
exports: [SpaceService],
|
||||
})
|
||||
|
Reference in New Issue
Block a user