mirror of
https://github.com/SyncrowIOT/backend.git
synced 2026-10-25 18:27:55 +00:00
311 lines
8.9 KiB
TypeScript
311 lines
8.9 KiB
TypeScript
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
|
import {
|
|
BadRequestException,
|
|
HttpException,
|
|
HttpStatus,
|
|
Injectable,
|
|
} from '@nestjs/common';
|
|
import { AddSpaceDto } from '../dtos';
|
|
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
|
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
|
import { CommunityRepository } from '@app/common/modules/community/repositories';
|
|
import { SpaceEntity } from '@app/common/modules/space/entities';
|
|
import { generateRandomString } from '@app/common/helper/randomString';
|
|
import { SpaceLinkService } from './space-link';
|
|
import { SpaceProductService } from './space-products';
|
|
|
|
@Injectable()
|
|
export class SpaceService {
|
|
constructor(
|
|
private readonly spaceRepository: SpaceRepository,
|
|
private readonly communityRepository: CommunityRepository,
|
|
private readonly spaceLinkService: SpaceLinkService,
|
|
private readonly spaceProductService: SpaceProductService,
|
|
) {}
|
|
|
|
async createSpace(
|
|
addSpaceDto: AddSpaceDto,
|
|
communityId: string,
|
|
): Promise<BaseResponseDto> {
|
|
const { parentUuid, direction, products } = addSpaceDto;
|
|
|
|
const community = await this.validateCommunity(communityId);
|
|
|
|
const parent = parentUuid ? await this.validateSpace(parentUuid) : null;
|
|
try {
|
|
const newSpace = this.spaceRepository.create({
|
|
...addSpaceDto,
|
|
community,
|
|
parent: parentUuid ? parent : null,
|
|
});
|
|
|
|
await this.spaceRepository.save(newSpace);
|
|
|
|
if (direction && parent) {
|
|
await this.spaceLinkService.saveSpaceLink(
|
|
parent.uuid,
|
|
newSpace.uuid,
|
|
direction,
|
|
);
|
|
}
|
|
|
|
if (products && products.length > 0) {
|
|
await this.spaceProductService.assignProductsToSpace(
|
|
newSpace,
|
|
products,
|
|
);
|
|
}
|
|
|
|
return new SuccessResponseDto({
|
|
statusCode: HttpStatus.CREATED,
|
|
data: newSpace,
|
|
message: 'Space created successfully',
|
|
});
|
|
} catch (error) {
|
|
throw new HttpException(error.message, HttpStatus.INTERNAL_SERVER_ERROR);
|
|
}
|
|
}
|
|
|
|
async getSpacesHierarchyForCommunity(
|
|
communityUuid: string,
|
|
): Promise<BaseResponseDto> {
|
|
await this.validateCommunity(communityUuid);
|
|
try {
|
|
// Get all spaces related to the community, including the parent-child relations
|
|
const spaces = await this.spaceRepository.find({
|
|
where: { community: { uuid: communityUuid } },
|
|
relations: [
|
|
'parent',
|
|
'children',
|
|
'incomingConnections',
|
|
'spaceProducts',
|
|
'spaceProducts.product',
|
|
], // Include parent and children relations
|
|
});
|
|
|
|
// Organize spaces into a hierarchical structure
|
|
const spaceHierarchy = this.buildSpaceHierarchy(spaces);
|
|
|
|
return new SuccessResponseDto({
|
|
message: `Spaces in community ${communityUuid} successfully fetched in hierarchy`,
|
|
data: spaceHierarchy,
|
|
statusCode: HttpStatus.OK,
|
|
});
|
|
} catch (error) {
|
|
throw new HttpException(
|
|
'An error occurred while fetching the spaces',
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
}
|
|
}
|
|
|
|
async findOne(spaceUuid: string): Promise<BaseResponseDto> {
|
|
try {
|
|
const space = await this.validateSpace(spaceUuid);
|
|
|
|
return new SuccessResponseDto({
|
|
message: `Space with ID ${spaceUuid} successfully fetched`,
|
|
data: space,
|
|
});
|
|
} catch (error) {
|
|
if (error instanceof HttpException) {
|
|
throw error; // If it's an HttpException, rethrow it
|
|
} else {
|
|
throw new HttpException(
|
|
'An error occurred while deleting the community',
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
async delete(
|
|
spaceUuid: string,
|
|
communityUuid: string,
|
|
): Promise<BaseResponseDto> {
|
|
try {
|
|
// First, check if the community exists
|
|
const space = await this.validateCommunityAndSpace(
|
|
communityUuid,
|
|
spaceUuid,
|
|
);
|
|
|
|
// Delete the space
|
|
await this.spaceRepository.remove(space);
|
|
|
|
return new SuccessResponseDto({
|
|
message: `Space with ID ${spaceUuid} successfully deleted`,
|
|
statusCode: HttpStatus.OK,
|
|
});
|
|
} catch (error) {
|
|
if (error instanceof HttpException) {
|
|
throw error;
|
|
}
|
|
throw new HttpException(
|
|
'An error occurred while deleting the space',
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
}
|
|
}
|
|
|
|
async updateSpace(
|
|
spaceUuid: string,
|
|
communityId: string,
|
|
updateSpaceDto: AddSpaceDto,
|
|
): Promise<BaseResponseDto> {
|
|
try {
|
|
const space = await this.validateCommunityAndSpace(
|
|
communityId,
|
|
spaceUuid,
|
|
);
|
|
|
|
// If a parentId is provided, check if the parent exists
|
|
const { parentUuid, products } = updateSpaceDto;
|
|
const parent = parentUuid ? await this.validateSpace(parentUuid) : null;
|
|
|
|
// Update other space properties from updateSpaceDto
|
|
Object.assign(space, updateSpaceDto, { parent });
|
|
|
|
// Save the updated space
|
|
const updatedSpace = await this.spaceRepository.save(space);
|
|
|
|
if (products && products.length > 0) {
|
|
await this.spaceProductService.assignProductsToSpace(
|
|
updatedSpace,
|
|
products,
|
|
);
|
|
}
|
|
|
|
return new SuccessResponseDto({
|
|
message: `Space with ID ${spaceUuid} successfully updated`,
|
|
data: space,
|
|
statusCode: HttpStatus.OK,
|
|
});
|
|
} catch (error) {
|
|
if (error instanceof HttpException) {
|
|
throw error;
|
|
}
|
|
throw new HttpException(
|
|
'An error occurred while updating the space',
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
}
|
|
}
|
|
|
|
async getSpacesHierarchyForSpace(
|
|
spaceUuid: string,
|
|
): Promise<BaseResponseDto> {
|
|
await this.validateSpace(spaceUuid);
|
|
|
|
try {
|
|
// Get all spaces that are children of the provided space, including the parent-child relations
|
|
const spaces = await this.spaceRepository.find({
|
|
where: { parent: { uuid: spaceUuid } },
|
|
relations: ['parent', 'children'], // Include parent and children relations
|
|
});
|
|
|
|
// Organize spaces into a hierarchical structure
|
|
const spaceHierarchy = this.buildSpaceHierarchy(spaces);
|
|
|
|
return new SuccessResponseDto({
|
|
message: `Spaces under space ${spaceUuid} successfully fetched in hierarchy`,
|
|
data: spaceHierarchy,
|
|
statusCode: HttpStatus.OK,
|
|
});
|
|
} catch (error) {
|
|
throw new HttpException(
|
|
'An error occurred while fetching the spaces under the space',
|
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
);
|
|
}
|
|
}
|
|
|
|
async getSpaceInvitationCode(spaceUuid: string): Promise<any> {
|
|
try {
|
|
const invitationCode = generateRandomString(6);
|
|
|
|
const space = await this.validateSpace(spaceUuid);
|
|
|
|
space.invitationCode = invitationCode;
|
|
await this.spaceRepository.save(space);
|
|
|
|
return new SuccessResponseDto({
|
|
message: `Invitation code has been successfuly added to the space`,
|
|
data: space,
|
|
});
|
|
} catch (err) {
|
|
if (err instanceof BadRequestException) {
|
|
throw err;
|
|
} else {
|
|
throw new HttpException('Space not found', HttpStatus.NOT_FOUND);
|
|
}
|
|
}
|
|
}
|
|
|
|
private buildSpaceHierarchy(spaces: SpaceEntity[]): SpaceEntity[] {
|
|
const map = new Map<string, SpaceEntity>();
|
|
|
|
// Step 1: Create a map of spaces by UUID
|
|
spaces.forEach((space) => {
|
|
map.set(
|
|
space.uuid,
|
|
this.spaceRepository.create({
|
|
...space,
|
|
children: [], // Add children if needed
|
|
}),
|
|
);
|
|
});
|
|
|
|
// Step 2: Organize the hierarchy
|
|
const rootSpaces: SpaceEntity[] = [];
|
|
spaces.forEach((space) => {
|
|
if (space.parent && space.parent.uuid) {
|
|
const parent = map.get(space.parent.uuid);
|
|
parent?.children?.push(map.get(space.uuid));
|
|
} else {
|
|
rootSpaces.push(map.get(space.uuid));
|
|
}
|
|
});
|
|
|
|
return rootSpaces;
|
|
}
|
|
|
|
private async validateCommunity(communityId: string) {
|
|
const community = await this.communityRepository.findOne({
|
|
where: { uuid: communityId },
|
|
});
|
|
if (!community) {
|
|
throw new HttpException(
|
|
`Community with ID ${communityId} not found`,
|
|
HttpStatus.NOT_FOUND,
|
|
);
|
|
}
|
|
return community;
|
|
}
|
|
|
|
async validateCommunityAndSpace(communityUuid: string, spaceUuid: string) {
|
|
const community = await this.validateCommunity(communityUuid);
|
|
if (!community) {
|
|
this.throwNotFound('Community', communityUuid);
|
|
}
|
|
|
|
const space = await this.validateSpace(spaceUuid);
|
|
return space;
|
|
}
|
|
|
|
private async validateSpace(spaceUuid: string) {
|
|
const space = await this.spaceRepository.findOne({
|
|
where: { uuid: spaceUuid },
|
|
});
|
|
if (!space) this.throwNotFound('Space', spaceUuid);
|
|
return space;
|
|
}
|
|
|
|
private throwNotFound(entity: string, uuid: string) {
|
|
throw new HttpException(
|
|
`${entity} with ID ${uuid} not found`,
|
|
HttpStatus.NOT_FOUND,
|
|
);
|
|
}
|
|
}
|