mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-11-26 19:44:55 +00:00
space product service
This commit is contained in:
@ -24,7 +24,7 @@ export class SubspaceEntity extends AbstractEntity<SubspaceDto> {
|
|||||||
nullable: false,
|
nullable: false,
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
})
|
})
|
||||||
@JoinColumn({ name: 'space_id' })
|
@JoinColumn({ name: 'space_uuid' })
|
||||||
space: SpaceEntity;
|
space: SpaceEntity;
|
||||||
|
|
||||||
@OneToMany(() => DeviceEntity, (device) => device.subspace, {
|
@OneToMany(() => DeviceEntity, (device) => device.subspace, {
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { Type } from 'class-transformer';
|
import { Type } from 'class-transformer';
|
||||||
import {
|
import {
|
||||||
ArrayNotEmpty,
|
|
||||||
IsArray,
|
IsArray,
|
||||||
IsBoolean,
|
IsBoolean,
|
||||||
IsNotEmpty,
|
IsNotEmpty,
|
||||||
@ -43,7 +42,6 @@ export class ProductAssignmentDto {
|
|||||||
example: [{ tag: 'Light 1' }, { tag: 'Light 2' }, { tag: 'Light 3' }],
|
example: [{ tag: 'Light 1' }, { tag: 'Light 2' }, { tag: 'Light 3' }],
|
||||||
})
|
})
|
||||||
@IsArray()
|
@IsArray()
|
||||||
@ArrayNotEmpty()
|
|
||||||
@ValidateNested({ each: true })
|
@ValidateNested({ each: true })
|
||||||
@Type(() => CreateSpaceProductItemDto)
|
@Type(() => CreateSpaceProductItemDto)
|
||||||
items: CreateSpaceProductItemDto[];
|
items: CreateSpaceProductItemDto[];
|
||||||
|
|||||||
@ -78,6 +78,27 @@ export class SpaceProductItemService {
|
|||||||
queryRunner: QueryRunner,
|
queryRunner: QueryRunner,
|
||||||
space: SpaceEntity,
|
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 incomingTags = itemModelDtos.map((item) => item.tag);
|
||||||
|
|
||||||
const duplicateTags = incomingTags.filter(
|
const duplicateTags = incomingTags.filter(
|
||||||
@ -90,13 +111,7 @@ export class SpaceProductItemService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const existingTags = await queryRunner.manager.find(
|
const existingTags = await queryRunner.manager.query(query, [space.uuid]);
|
||||||
this.spaceProductItemRepository.target,
|
|
||||||
{
|
|
||||||
where: { spaceProduct: { space } },
|
|
||||||
select: ['tag'],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
const existingTagSet = new Set(existingTags.map((item) => item.tag));
|
const existingTagSet = new Set(existingTags.map((item) => item.tag));
|
||||||
|
|
||||||
const conflictingTags = incomingTags.filter((tag) =>
|
const conflictingTags = incomingTags.filter((tag) =>
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export class SpaceProductService {
|
|||||||
private readonly spaceProductItemService: SpaceProductItemService,
|
private readonly spaceProductItemService: SpaceProductItemService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async createProductItemFromModel(
|
async createFromModel(
|
||||||
spaceModel: SpaceModelEntity,
|
spaceModel: SpaceModelEntity,
|
||||||
space: SpaceEntity,
|
space: SpaceEntity,
|
||||||
queryRunner: QueryRunner,
|
queryRunner: QueryRunner,
|
||||||
|
|||||||
@ -81,7 +81,7 @@ export class SpaceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (subspaces?.length) {
|
if (subspaces?.length) {
|
||||||
await this.subSpaceService.createSubspacesFromNames(
|
await this.subSpaceService.createSubspacesFromDto(
|
||||||
subspaces,
|
subspaces,
|
||||||
newSpace,
|
newSpace,
|
||||||
queryRunner,
|
queryRunner,
|
||||||
@ -101,7 +101,7 @@ export class SpaceService {
|
|||||||
queryRunner,
|
queryRunner,
|
||||||
);
|
);
|
||||||
} else if (spaceModel && spaceModel.spaceProductModels.length) {
|
} else if (spaceModel && spaceModel.spaceProductModels.length) {
|
||||||
await this.spaceProductService.createProductItemFromModel(
|
await this.spaceProductService.createFromModel(
|
||||||
spaceModel,
|
spaceModel,
|
||||||
newSpace,
|
newSpace,
|
||||||
queryRunner,
|
queryRunner,
|
||||||
|
|||||||
@ -1,9 +1,17 @@
|
|||||||
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
|
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
|
||||||
import { QueryRunner } from 'typeorm';
|
import { QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
import { SubspaceProductEntity } from '@app/common/modules/space';
|
import {
|
||||||
import { SubspaceProductModelEntity } from '@app/common/modules/space-model';
|
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 { SubspaceProductItemRepository } from '@app/common/modules/space/repositories/subspace.repository';
|
||||||
|
import { CreateSpaceProductItemDto } from 'src/space/dtos';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SubspaceProductItemService {
|
export class SubspaceProductItemService {
|
||||||
@ -39,12 +47,98 @@ export class SubspaceProductItemService {
|
|||||||
|
|
||||||
private createProductItem(
|
private createProductItem(
|
||||||
product: SubspaceProductEntity,
|
product: SubspaceProductEntity,
|
||||||
model: any,
|
model: SubspaceProductItemModelEntity,
|
||||||
queryRunner: QueryRunner,
|
queryRunner: QueryRunner,
|
||||||
): Partial<any> {
|
): Partial<any> {
|
||||||
return queryRunner.manager.create(this.productItemRepository.target, {
|
return queryRunner.manager.create(this.productItemRepository.target, {
|
||||||
tag: model.tag,
|
tag: model.tag,
|
||||||
product,
|
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 { QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
SpaceEntity,
|
||||||
SubspaceEntity,
|
SubspaceEntity,
|
||||||
SubspaceProductEntity,
|
SubspaceProductEntity,
|
||||||
} from '@app/common/modules/space';
|
} from '@app/common/modules/space';
|
||||||
@ -10,11 +11,15 @@ import {
|
|||||||
SubspaceProductModelEntity,
|
SubspaceProductModelEntity,
|
||||||
} from '@app/common/modules/space-model';
|
} from '@app/common/modules/space-model';
|
||||||
import { SubspaceProductItemService } from './subspace-product-item.service';
|
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()
|
@Injectable()
|
||||||
export class SubspaceProductService {
|
export class SubspaceProductService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly subspaceProductItemService: SubspaceProductItemService,
|
private readonly subspaceProductItemService: SubspaceProductItemService,
|
||||||
|
private readonly productService: ProductService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async createFromModel(
|
async createFromModel(
|
||||||
@ -63,4 +68,61 @@ export class SubspaceProductService {
|
|||||||
model: productModel,
|
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[],
|
addSubspaceDtos: AddSubspaceDto[],
|
||||||
space: SpaceEntity,
|
space: SpaceEntity,
|
||||||
queryRunner: QueryRunner,
|
queryRunner: QueryRunner,
|
||||||
): Promise<SubspaceEntity[]> {
|
): Promise<SubspaceEntity[]> {
|
||||||
const subspaceData = addSubspaceDtos.map((dto) => ({
|
try {
|
||||||
subspaceName: dto.subspaceName,
|
const subspaceData = addSubspaceDtos.map((dto) => ({
|
||||||
space,
|
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(
|
async createSubspace(
|
||||||
|
|||||||
@ -50,6 +50,7 @@ import { CommunityModule } from 'src/community/community.module';
|
|||||||
import { ValidationService } from './services';
|
import { ValidationService } from './services';
|
||||||
import {
|
import {
|
||||||
SubspaceProductItemRepository,
|
SubspaceProductItemRepository,
|
||||||
|
SubspaceProductRepository,
|
||||||
SubspaceRepository,
|
SubspaceRepository,
|
||||||
} from '@app/common/modules/space/repositories/subspace.repository';
|
} from '@app/common/modules/space/repositories/subspace.repository';
|
||||||
import { SubspaceProductService } from './services';
|
import { SubspaceProductService } from './services';
|
||||||
@ -99,6 +100,7 @@ import { SubspaceProductService } from './services';
|
|||||||
SpaceProductItemRepository,
|
SpaceProductItemRepository,
|
||||||
SubspaceProductService,
|
SubspaceProductService,
|
||||||
SubspaceProductItemService,
|
SubspaceProductItemService,
|
||||||
|
SubspaceProductRepository,
|
||||||
],
|
],
|
||||||
exports: [SpaceService],
|
exports: [SpaceService],
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user