added space link service

This commit is contained in:
hannathkadher
2024-11-20 16:01:51 +04:00
parent 4a98d94dda
commit c7404972a2
7 changed files with 145 additions and 159 deletions

View File

@ -0,0 +1,5 @@
export enum Direction {
LEFT = 'left',
RIGHT = 'right',
DOWN = 'down',
}

View File

@ -1,8 +1,9 @@
import { Column, Entity, JoinColumn, ManyToOne } from 'typeorm';
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
import { SpaceEntity } from './space.entity';
import { Direction } from '@app/common/constants/direction.enum';
@Entity({ name: 'space_link' })
@Entity({ name: 'space-link' })
export class SpaceLinkEntity extends AbstractEntity {
@ManyToOne(() => SpaceEntity, { nullable: false, onDelete: 'CASCADE' })
@JoinColumn({ name: 'start_space_id' })
@ -13,9 +14,8 @@ export class SpaceLinkEntity extends AbstractEntity {
public endSpace: SpaceEntity;
@Column({
type: 'varchar',
length: 10,
nullable: false,
enum: Object.values(Direction),
})
direction: string;

View File

@ -2,4 +2,5 @@ export * from './space.service';
export * from './space-user.service';
export * from './space-device.service';
export * from './subspace';
export * from './space-link';
export * from './space-scene.service';

View File

@ -0,0 +1 @@
export * from './space-link.service';

View File

@ -0,0 +1,88 @@
import {
SpaceLinkRepository,
SpaceRepository,
} from '@app/common/modules/space/repositories';
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
@Injectable()
export class SpaceLinkService {
constructor(
private readonly spaceRepository: SpaceRepository,
private readonly spaceLinkRepository: SpaceLinkRepository,
) {}
async saveSpaceLink(
startSpaceId: string,
endSpaceId: string,
direction: string,
): Promise<void> {
try {
// Check if a link between the startSpace and endSpace already exists
const existingLink = await this.spaceLinkRepository.findOne({
where: {
startSpace: { uuid: startSpaceId },
endSpace: { uuid: endSpaceId },
},
});
if (existingLink) {
// Update the direction if the link exists
existingLink.direction = direction;
await this.spaceLinkRepository.save(existingLink);
return;
}
const existingEndSpaceLink = await this.spaceLinkRepository.findOne({
where: { endSpace: { uuid: endSpaceId } },
});
if (
existingEndSpaceLink &&
existingEndSpaceLink.startSpace.uuid !== startSpaceId
) {
throw new Error(
`Space with ID ${endSpaceId} is already an endSpace in another link and cannot be reused.`,
);
}
// Find start space
const startSpace = await this.spaceRepository.findOne({
where: { uuid: startSpaceId },
});
if (!startSpace) {
throw new HttpException(
`Start space with ID ${startSpaceId} not found.`,
HttpStatus.NOT_FOUND,
);
}
// Find end space
const endSpace = await this.spaceRepository.findOne({
where: { uuid: endSpaceId },
});
if (!endSpace) {
throw new HttpException(
`End space with ID ${endSpaceId} not found.`,
HttpStatus.NOT_FOUND,
);
}
// Create and save the space link
const spaceLink = this.spaceLinkRepository.create({
startSpace,
endSpace,
direction,
});
await this.spaceLinkRepository.save(spaceLink);
} catch (error) {
throw new HttpException(
error.message ||
`Failed to save space link. Internal Server Error: ${error.message}`,
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
}

View File

@ -1,7 +1,4 @@
import {
SpaceLinkRepository,
SpaceRepository,
} from '@app/common/modules/space/repositories';
import { SpaceRepository } from '@app/common/modules/space/repositories';
import {
BadRequestException,
HttpException,
@ -14,47 +11,25 @@ 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';
@Injectable()
export class SpaceService {
constructor(
private readonly spaceRepository: SpaceRepository,
private readonly spaceLinkRepository: SpaceLinkRepository,
private readonly communityRepository: CommunityRepository,
private readonly spaceLinkService: SpaceLinkService,
) {}
async createSpace(
addSpaceDto: AddSpaceDto,
communityId: string,
): Promise<BaseResponseDto> {
let parent: SpaceEntity | null = null;
const { parentUuid, direction } = addSpaceDto;
const community = await this.communityRepository.findOne({
where: { uuid: communityId },
});
// If the community doesn't exist, throw a 404 error
if (!community) {
throw new HttpException(
`Community with ID ${communityId} not found`,
HttpStatus.NOT_FOUND,
);
}
const community = await this.validateCommunity(communityId);
if (parentUuid) {
parent = await this.spaceRepository.findOne({
where: { uuid: parentUuid },
});
// If the community doesn't exist, throw a 404 error
if (!parent) {
throw new HttpException(
`Parent with ID ${parentUuid} not found`,
HttpStatus.NOT_FOUND,
);
}
}
const parent = parentUuid ? await this.validateSpace(parentUuid) : null;
try {
const newSpace = this.spaceRepository.create({
...addSpaceDto,
@ -65,13 +40,11 @@ export class SpaceService {
await this.spaceRepository.save(newSpace);
if (direction && parent) {
const spaceLink = await this.spaceLinkRepository.create({
await this.spaceLinkService.saveSpaceLink(
parent.uuid,
newSpace.uuid,
direction,
endSpace: newSpace,
startSpace: parent,
});
await this.spaceLinkRepository.save(spaceLink);
);
}
return new SuccessResponseDto({
@ -87,17 +60,7 @@ export class SpaceService {
async getSpacesHierarchyForCommunity(
communityUuid: string,
): Promise<BaseResponseDto> {
const community = await this.communityRepository.findOne({
where: { uuid: communityUuid },
});
// If the community doesn't exist, throw a 404 error
if (!community) {
throw new HttpException(
`Community with ID ${communityUuid} not found`,
HttpStatus.NOT_FOUND,
);
}
await this.validateCommunity(communityUuid);
try {
// Get all spaces related to the community, including the parent-child relations
const spaces = await this.spaceRepository.find({
@ -123,19 +86,8 @@ export class SpaceService {
async findOne(spaceUuid: string): Promise<BaseResponseDto> {
try {
const space = await this.spaceRepository.findOne({
where: {
uuid: spaceUuid,
},
});
const space = await this.validateSpace(spaceUuid);
// If space is not found, throw a NotFoundException
if (!space) {
throw new HttpException(
`Space with UUID ${spaceUuid} not found`,
HttpStatus.NOT_FOUND,
);
}
return new SuccessResponseDto({
message: `Space with ID ${spaceUuid} successfully fetched`,
data: space,
@ -158,28 +110,10 @@ export class SpaceService {
): Promise<BaseResponseDto> {
try {
// First, check if the community exists
const community = await this.communityRepository.findOne({
where: { uuid: communityUuid },
});
if (!community) {
throw new HttpException(
`Community with ID ${communityUuid} not found`,
HttpStatus.NOT_FOUND,
const space = await this.validateCommunityAndSpace(
spaceUuid,
communityUuid,
);
}
// Check if the space exists
const space = await this.spaceRepository.findOne({
where: { uuid: spaceUuid, community: { uuid: communityUuid } },
});
if (!space) {
throw new HttpException(
`Space with ID ${spaceUuid} not found`,
HttpStatus.NOT_FOUND,
);
}
// Delete the space
await this.spaceRepository.remove(space);
@ -205,54 +139,17 @@ export class SpaceService {
updateSpaceDto: AddSpaceDto,
): Promise<BaseResponseDto> {
try {
// First, check if the community exists
const community = await this.communityRepository.findOne({
where: { uuid: communityId },
});
if (!community) {
throw new HttpException(
`Community with ID ${communityId} not found`,
HttpStatus.NOT_FOUND,
const space = await this.validateCommunityAndSpace(
communityId,
spaceUuid,
);
}
// Check if the space exists
const space = await this.spaceRepository.findOne({
where: { uuid: spaceUuid, community: { uuid: communityId } },
});
if (!space) {
throw new HttpException(
`Space with ID ${spaceUuid} not found`,
HttpStatus.NOT_FOUND,
);
}
// If a parentId is provided, check if the parent exists
const { parentUuid } = updateSpaceDto;
let parent: SpaceEntity | null = null;
if (parentUuid) {
parent = await this.spaceRepository.findOne({
where: { uuid: parentUuid, community: { uuid: communityId } },
});
// If the parent doesn't exist, throw a 404 error
if (!parent) {
throw new HttpException(
`Parent space with ID ${parentUuid} not found`,
HttpStatus.NOT_FOUND,
);
}
// Set the parent of the current space
space.parent = parent;
} else {
space.parent = null; // If no parent is provided, clear the parent
}
const parent = parentUuid ? await this.validateSpace(parentUuid) : null;
// Update other space properties from updateSpaceDto
Object.assign(space, updateSpaceDto);
Object.assign(space, updateSpaceDto, { parent });
// Save the updated space
await this.spaceRepository.save(space);
@ -276,17 +173,7 @@ export class SpaceService {
async getSpacesHierarchyForSpace(
spaceUuid: string,
): Promise<BaseResponseDto> {
const space = await this.spaceRepository.findOne({
where: { uuid: spaceUuid },
});
// If the space doesn't exist, throw a 404 error
if (!space) {
throw new HttpException(
`Space with ID ${spaceUuid} not found`,
HttpStatus.NOT_FOUND,
);
}
await this.validateSpace(spaceUuid);
try {
// Get all spaces that are children of the provided space, including the parent-child relations
@ -315,18 +202,7 @@ export class SpaceService {
try {
const invitationCode = generateRandomString(6);
const space = await this.spaceRepository.findOne({
where: {
uuid: spaceUuid,
},
});
if (!space) {
throw new HttpException(
`Space with ID ${spaceUuid} not found`,
HttpStatus.NOT_FOUND,
);
}
const space = await this.validateSpace(spaceUuid);
space.invitationCode = invitationCode;
await this.spaceRepository.save(space);
@ -369,24 +245,37 @@ export class SpaceService {
}
});
return rootSpaces; // Return the root spaces with children nested within them
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.communityRepository.findOne({
where: { uuid: communityUuid },
});
const community = await this.validateCommunity(communityUuid);
if (!community) {
this.throwNotFound('Community', communityUuid);
}
const space = await this.spaceRepository.findOne({
where: { uuid: spaceUuid, community: { uuid: communityUuid } },
relations: ['devices', 'devices.productDevice'],
});
if (!space) {
this.throwNotFound('Space', spaceUuid);
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;
}

View File

@ -11,6 +11,7 @@ import {
} from './controllers';
import {
SpaceDeviceService,
SpaceLinkService,
SpaceSceneService,
SpaceService,
SpaceUserService,
@ -55,6 +56,7 @@ import { DeviceStatusLogRepository } from '@app/common/modules/device-status-log
ProductRepository,
SubSpaceService,
SpaceDeviceService,
SpaceLinkService,
SubspaceDeviceService,
SpaceRepository,
DeviceRepository,