mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-15 10:25:23 +00:00
removed unit,floor,building,room modules
This commit is contained in:
@ -3,14 +3,10 @@ import { ConfigModule } from '@nestjs/config';
|
|||||||
import config from './config';
|
import config from './config';
|
||||||
import { AuthenticationModule } from './auth/auth.module';
|
import { AuthenticationModule } from './auth/auth.module';
|
||||||
import { UserModule } from './users/user.module';
|
import { UserModule } from './users/user.module';
|
||||||
import { RoomModule } from './room/room.module';
|
|
||||||
import { GroupModule } from './group/group.module';
|
import { GroupModule } from './group/group.module';
|
||||||
import { DeviceModule } from './device/device.module';
|
import { DeviceModule } from './device/device.module';
|
||||||
import { UserDevicePermissionModule } from './user-device-permission/user-device-permission.module';
|
import { UserDevicePermissionModule } from './user-device-permission/user-device-permission.module';
|
||||||
import { CommunityModule } from './community/community.module';
|
import { CommunityModule } from './community/community.module';
|
||||||
import { BuildingModule } from './building/building.module';
|
|
||||||
import { FloorModule } from './floor/floor.module';
|
|
||||||
import { UnitModule } from './unit/unit.module';
|
|
||||||
import { RoleModule } from './role/role.module';
|
import { RoleModule } from './role/role.module';
|
||||||
import { SeederModule } from '@app/common/seed/seeder.module';
|
import { SeederModule } from '@app/common/seed/seeder.module';
|
||||||
import { UserNotificationModule } from './user-notification/user-notification.module';
|
import { UserNotificationModule } from './user-notification/user-notification.module';
|
||||||
@ -34,12 +30,9 @@ import { SpaceModule } from './space/space.module';
|
|||||||
UserModule,
|
UserModule,
|
||||||
RoleModule,
|
RoleModule,
|
||||||
CommunityModule,
|
CommunityModule,
|
||||||
BuildingModule,
|
|
||||||
FloorModule,
|
|
||||||
UnitModule,
|
|
||||||
SpaceModule,
|
SpaceModule,
|
||||||
RoomModule,
|
|
||||||
RoomModule,
|
|
||||||
GroupModule,
|
GroupModule,
|
||||||
DeviceModule,
|
DeviceModule,
|
||||||
DeviceMessagesSubscriptionModule,
|
DeviceMessagesSubscriptionModule,
|
||||||
|
@ -10,7 +10,6 @@ import {
|
|||||||
UpdateAutomationDto,
|
UpdateAutomationDto,
|
||||||
UpdateAutomationStatusDto,
|
UpdateAutomationStatusDto,
|
||||||
} from '../dtos';
|
} from '../dtos';
|
||||||
import { GetUnitByUuidInterface } from 'src/unit/interface/unit.interface';
|
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { TuyaContext } from '@tuya/tuya-connector-nodejs';
|
import { TuyaContext } from '@tuya/tuya-connector-nodejs';
|
||||||
import { convertKeysToSnakeCase } from '@app/common/helper/snakeCaseConverter';
|
import { convertKeysToSnakeCase } from '@app/common/helper/snakeCaseConverter';
|
||||||
@ -23,7 +22,6 @@ import {
|
|||||||
GetAutomationByUnitInterface,
|
GetAutomationByUnitInterface,
|
||||||
} from '../interface/automation.interface';
|
} from '../interface/automation.interface';
|
||||||
import { convertKeysToCamelCase } from '@app/common/helper/camelCaseConverter';
|
import { convertKeysToCamelCase } from '@app/common/helper/camelCaseConverter';
|
||||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
|
||||||
import {
|
import {
|
||||||
ActionExecutorEnum,
|
ActionExecutorEnum,
|
||||||
EntityTypeEnum,
|
EntityTypeEnum,
|
||||||
@ -126,18 +124,14 @@ export class AutomationService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async getUnitByUuid(unitUuid: string): Promise<GetUnitByUuidInterface> {
|
async getUnitByUuid(unitUuid: string) {
|
||||||
try {
|
try {
|
||||||
const unit = await this.spaceRepository.findOne({
|
const unit = await this.spaceRepository.findOne({
|
||||||
where: {
|
where: {
|
||||||
uuid: unitUuid,
|
uuid: unitUuid,
|
||||||
spaceType: {
|
|
||||||
type: SpaceType.UNIT,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
relations: ['spaceType'],
|
|
||||||
});
|
});
|
||||||
if (!unit || !unit.spaceType || unit.spaceType.type !== SpaceType.UNIT) {
|
if (!unit) {
|
||||||
throw new BadRequestException('Invalid unit UUID');
|
throw new BadRequestException('Invalid unit UUID');
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@ -145,7 +139,6 @@ export class AutomationService {
|
|||||||
createdAt: unit.createdAt,
|
createdAt: unit.createdAt,
|
||||||
updatedAt: unit.updatedAt,
|
updatedAt: unit.updatedAt,
|
||||||
name: unit.spaceName,
|
name: unit.spaceName,
|
||||||
type: unit.spaceType.type,
|
|
||||||
spaceTuyaUuid: unit.spaceTuyaUuid,
|
spaceTuyaUuid: unit.spaceTuyaUuid,
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
import { BuildingService } from './services/building.service';
|
|
||||||
import { BuildingController } from './controllers/building.controller';
|
|
||||||
import { ConfigModule } from '@nestjs/config';
|
|
||||||
import { SpaceRepositoryModule } from '@app/common/modules/space/space.repository.module';
|
|
||||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
|
||||||
import { SpaceTypeRepository } from '@app/common/modules/space/repositories';
|
|
||||||
import { UserSpaceRepository } from '@app/common/modules/user/repositories';
|
|
||||||
import { UserRepository } from '@app/common/modules/user/repositories';
|
|
||||||
import { UserRepositoryModule } from '@app/common/modules/user/user.repository.module';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [ConfigModule, SpaceRepositoryModule, UserRepositoryModule],
|
|
||||||
controllers: [BuildingController],
|
|
||||||
providers: [
|
|
||||||
BuildingService,
|
|
||||||
SpaceRepository,
|
|
||||||
SpaceTypeRepository,
|
|
||||||
UserSpaceRepository,
|
|
||||||
UserRepository,
|
|
||||||
],
|
|
||||||
exports: [BuildingService],
|
|
||||||
})
|
|
||||||
export class BuildingModule {}
|
|
@ -1,106 +0,0 @@
|
|||||||
import { BuildingService } from '../services/building.service';
|
|
||||||
import {
|
|
||||||
Body,
|
|
||||||
Controller,
|
|
||||||
Get,
|
|
||||||
HttpStatus,
|
|
||||||
Param,
|
|
||||||
Post,
|
|
||||||
Put,
|
|
||||||
Query,
|
|
||||||
UseGuards,
|
|
||||||
} from '@nestjs/common';
|
|
||||||
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
|
||||||
import { AddBuildingDto, AddUserBuildingDto } from '../dtos/add.building.dto';
|
|
||||||
import { GetBuildingChildDto } from '../dtos/get.building.dto';
|
|
||||||
import { UpdateBuildingNameDto } from '../dtos/update.building.dto';
|
|
||||||
import { CheckCommunityTypeGuard } from 'src/guards/community.type.guard';
|
|
||||||
import { CheckUserBuildingGuard } from 'src/guards/user.building.guard';
|
|
||||||
import { AdminRoleGuard } from 'src/guards/admin.role.guard';
|
|
||||||
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
|
||||||
import { BuildingPermissionGuard } from 'src/guards/building.permission.guard';
|
|
||||||
import { EnableDisableStatusEnum } from '@app/common/constants/days.enum';
|
|
||||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
|
||||||
|
|
||||||
@ApiTags('Building Module')
|
|
||||||
@Controller({
|
|
||||||
version: EnableDisableStatusEnum.ENABLED,
|
|
||||||
path: SpaceType.BUILDING,
|
|
||||||
})
|
|
||||||
export class BuildingController {
|
|
||||||
constructor(private readonly buildingService: BuildingService) {}
|
|
||||||
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, CheckCommunityTypeGuard)
|
|
||||||
@Post()
|
|
||||||
async addBuilding(@Body() addBuildingDto: AddBuildingDto) {
|
|
||||||
const building = await this.buildingService.addBuilding(addBuildingDto);
|
|
||||||
return {
|
|
||||||
statusCode: HttpStatus.CREATED,
|
|
||||||
success: true,
|
|
||||||
message: 'Building added successfully',
|
|
||||||
data: building,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, BuildingPermissionGuard)
|
|
||||||
@Get(':buildingUuid')
|
|
||||||
async getBuildingByUuid(@Param('buildingUuid') buildingUuid: string) {
|
|
||||||
const building = await this.buildingService.getBuildingByUuid(buildingUuid);
|
|
||||||
return building;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, BuildingPermissionGuard)
|
|
||||||
@Get('child/:buildingUuid')
|
|
||||||
async getBuildingChildByUuid(
|
|
||||||
@Param('buildingUuid') buildingUuid: string,
|
|
||||||
@Query() query: GetBuildingChildDto,
|
|
||||||
) {
|
|
||||||
const building = await this.buildingService.getBuildingChildByUuid(
|
|
||||||
buildingUuid,
|
|
||||||
query,
|
|
||||||
);
|
|
||||||
return building;
|
|
||||||
}
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, BuildingPermissionGuard)
|
|
||||||
@Get('parent/:buildingUuid')
|
|
||||||
async getBuildingParentByUuid(@Param('buildingUuid') buildingUuid: string) {
|
|
||||||
const building =
|
|
||||||
await this.buildingService.getBuildingParentByUuid(buildingUuid);
|
|
||||||
return building;
|
|
||||||
}
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(AdminRoleGuard, CheckUserBuildingGuard)
|
|
||||||
@Post('user')
|
|
||||||
async addUserBuilding(@Body() addUserBuildingDto: AddUserBuildingDto) {
|
|
||||||
await this.buildingService.addUserBuilding(addUserBuildingDto);
|
|
||||||
return {
|
|
||||||
statusCode: HttpStatus.CREATED,
|
|
||||||
success: true,
|
|
||||||
message: 'user building added successfully',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard)
|
|
||||||
@Get('user/:userUuid')
|
|
||||||
async getBuildingsByUserId(@Param('userUuid') userUuid: string) {
|
|
||||||
return await this.buildingService.getBuildingsByUserId(userUuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, BuildingPermissionGuard)
|
|
||||||
@Put(':buildingUuid')
|
|
||||||
async renameBuildingByUuid(
|
|
||||||
@Param('buildingUuid') buildingUuid: string,
|
|
||||||
@Body() updateBuildingDto: UpdateBuildingNameDto,
|
|
||||||
) {
|
|
||||||
const building = await this.buildingService.renameBuildingByUuid(
|
|
||||||
buildingUuid,
|
|
||||||
updateBuildingDto,
|
|
||||||
);
|
|
||||||
return building;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export * from './building.controller';
|
|
@ -1,42 +0,0 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
|
||||||
import { IsNotEmpty, IsString } from 'class-validator';
|
|
||||||
|
|
||||||
export class AddBuildingDto {
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'buildingName',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public buildingName: string;
|
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'communityUuid',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public communityUuid: string;
|
|
||||||
constructor(dto: Partial<AddBuildingDto>) {
|
|
||||||
Object.assign(this, dto);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export class AddUserBuildingDto {
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'buildingUuid',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public buildingUuid: string;
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'userUuid',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public userUuid: string;
|
|
||||||
constructor(dto: Partial<AddUserBuildingDto>) {
|
|
||||||
Object.assign(this, dto);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
import { BooleanValues } from '@app/common/constants/boolean-values.enum';
|
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
|
||||||
import { Transform } from 'class-transformer';
|
|
||||||
import {
|
|
||||||
IsBoolean,
|
|
||||||
IsInt,
|
|
||||||
IsNotEmpty,
|
|
||||||
IsOptional,
|
|
||||||
IsString,
|
|
||||||
Min,
|
|
||||||
} from 'class-validator';
|
|
||||||
|
|
||||||
export class GetBuildingDto {
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'buildingUuid',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public buildingUuid: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class GetBuildingChildDto {
|
|
||||||
@ApiProperty({ example: 1, description: 'Page number', required: true })
|
|
||||||
@IsInt({ message: 'Page must be a number' })
|
|
||||||
@Min(1, { message: 'Page must not be less than 1' })
|
|
||||||
@IsNotEmpty()
|
|
||||||
public page: number;
|
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
example: 10,
|
|
||||||
description: 'Number of items per page',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsInt({ message: 'Page size must be a number' })
|
|
||||||
@Min(1, { message: 'Page size must not be less than 1' })
|
|
||||||
@IsNotEmpty()
|
|
||||||
public pageSize: number;
|
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
example: true,
|
|
||||||
description: 'Flag to determine whether to fetch full hierarchy',
|
|
||||||
required: false,
|
|
||||||
default: false,
|
|
||||||
})
|
|
||||||
@IsOptional()
|
|
||||||
@IsBoolean()
|
|
||||||
@Transform((value) => {
|
|
||||||
return value.obj.includeSubSpaces === BooleanValues.TRUE;
|
|
||||||
})
|
|
||||||
public includeSubSpaces: boolean = false;
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export * from './add.building.dto';
|
|
@ -1,16 +0,0 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
|
||||||
import { IsNotEmpty, IsString } from 'class-validator';
|
|
||||||
|
|
||||||
export class UpdateBuildingNameDto {
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'buildingName',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public buildingName: string;
|
|
||||||
|
|
||||||
constructor(dto: Partial<UpdateBuildingNameDto>) {
|
|
||||||
Object.assign(this, dto);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
export interface GetBuildingByUuidInterface {
|
|
||||||
uuid: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BuildingChildInterface {
|
|
||||||
uuid: string;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
totalCount?: number;
|
|
||||||
children?: BuildingChildInterface[];
|
|
||||||
}
|
|
||||||
export interface BuildingParentInterface {
|
|
||||||
uuid: string;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
parent?: BuildingParentInterface;
|
|
||||||
}
|
|
||||||
export interface RenameBuildingByUuidInterface {
|
|
||||||
uuid: string;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
}
|
|
||||||
export interface GetBuildingByUserUuidInterface {
|
|
||||||
uuid: string;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
}
|
|
@ -1,317 +0,0 @@
|
|||||||
import { GetBuildingChildDto } from '../dtos/get.building.dto';
|
|
||||||
import { SpaceTypeRepository } from '../../../libs/common/src/modules/space/repositories/space.repository';
|
|
||||||
import {
|
|
||||||
Injectable,
|
|
||||||
HttpException,
|
|
||||||
HttpStatus,
|
|
||||||
BadRequestException,
|
|
||||||
} from '@nestjs/common';
|
|
||||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
|
||||||
import { AddBuildingDto, AddUserBuildingDto } from '../dtos';
|
|
||||||
import {
|
|
||||||
BuildingChildInterface,
|
|
||||||
BuildingParentInterface,
|
|
||||||
GetBuildingByUserUuidInterface,
|
|
||||||
GetBuildingByUuidInterface,
|
|
||||||
RenameBuildingByUuidInterface,
|
|
||||||
} from '../interface/building.interface';
|
|
||||||
import { SpaceEntity } from '@app/common/modules/space/entities';
|
|
||||||
import { UpdateBuildingNameDto } from '../dtos/update.building.dto';
|
|
||||||
import { UserSpaceRepository } from '@app/common/modules/user/repositories';
|
|
||||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
|
||||||
import { CommonErrorCodes } from '@app/common/constants/error-codes.enum';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class BuildingService {
|
|
||||||
constructor(
|
|
||||||
private readonly spaceRepository: SpaceRepository,
|
|
||||||
private readonly spaceTypeRepository: SpaceTypeRepository,
|
|
||||||
private readonly userSpaceRepository: UserSpaceRepository,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
async addBuilding(addBuildingDto: AddBuildingDto) {
|
|
||||||
try {
|
|
||||||
const spaceType = await this.spaceTypeRepository.findOne({
|
|
||||||
where: {
|
|
||||||
type: SpaceType.BUILDING,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!spaceType) {
|
|
||||||
throw new BadRequestException('Invalid building UUID');
|
|
||||||
}
|
|
||||||
const building = await this.spaceRepository.save({
|
|
||||||
spaceName: addBuildingDto.buildingName,
|
|
||||||
parent: { uuid: addBuildingDto.communityUuid },
|
|
||||||
spaceType: { uuid: spaceType.uuid },
|
|
||||||
});
|
|
||||||
return building;
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof BadRequestException) {
|
|
||||||
throw err; // Re-throw BadRequestException
|
|
||||||
} else {
|
|
||||||
throw new HttpException('Building not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getBuildingByUuid(
|
|
||||||
buildingUuid: string,
|
|
||||||
): Promise<GetBuildingByUuidInterface> {
|
|
||||||
try {
|
|
||||||
const building = await this.spaceRepository.findOne({
|
|
||||||
where: {
|
|
||||||
uuid: buildingUuid,
|
|
||||||
spaceType: {
|
|
||||||
type: SpaceType.BUILDING,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
relations: ['spaceType'],
|
|
||||||
});
|
|
||||||
if (
|
|
||||||
!building ||
|
|
||||||
!building.spaceType ||
|
|
||||||
building.spaceType.type !== SpaceType.BUILDING
|
|
||||||
) {
|
|
||||||
throw new BadRequestException('Invalid building UUID');
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
uuid: building.uuid,
|
|
||||||
createdAt: building.createdAt,
|
|
||||||
updatedAt: building.updatedAt,
|
|
||||||
name: building.spaceName,
|
|
||||||
type: building.spaceType.type,
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof BadRequestException) {
|
|
||||||
throw err; // Re-throw BadRequestException
|
|
||||||
} else {
|
|
||||||
throw new HttpException('Building not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async getBuildingChildByUuid(
|
|
||||||
buildingUuid: string,
|
|
||||||
getBuildingChildDto: GetBuildingChildDto,
|
|
||||||
): Promise<BuildingChildInterface> {
|
|
||||||
try {
|
|
||||||
const { includeSubSpaces, page, pageSize } = getBuildingChildDto;
|
|
||||||
|
|
||||||
const space = await this.spaceRepository.findOneOrFail({
|
|
||||||
where: { uuid: buildingUuid },
|
|
||||||
relations: ['children', 'spaceType'],
|
|
||||||
});
|
|
||||||
if (
|
|
||||||
!space ||
|
|
||||||
!space.spaceType ||
|
|
||||||
space.spaceType.type !== SpaceType.BUILDING
|
|
||||||
) {
|
|
||||||
throw new BadRequestException('Invalid building UUID');
|
|
||||||
}
|
|
||||||
|
|
||||||
const totalCount = await this.spaceRepository.count({
|
|
||||||
where: { parent: { uuid: space.uuid } },
|
|
||||||
});
|
|
||||||
|
|
||||||
const children = await this.buildHierarchy(
|
|
||||||
space,
|
|
||||||
includeSubSpaces,
|
|
||||||
page,
|
|
||||||
pageSize,
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
uuid: space.uuid,
|
|
||||||
name: space.spaceName,
|
|
||||||
type: space.spaceType.type,
|
|
||||||
totalCount,
|
|
||||||
children,
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof BadRequestException) {
|
|
||||||
throw err; // Re-throw BadRequestException
|
|
||||||
} else {
|
|
||||||
throw new HttpException('Building not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async buildHierarchy(
|
|
||||||
space: SpaceEntity,
|
|
||||||
includeSubSpaces: boolean,
|
|
||||||
page: number,
|
|
||||||
pageSize: number,
|
|
||||||
): Promise<BuildingChildInterface[]> {
|
|
||||||
const children = await this.spaceRepository.find({
|
|
||||||
where: { parent: { uuid: space.uuid } },
|
|
||||||
relations: ['spaceType'],
|
|
||||||
skip: (page - 1) * pageSize,
|
|
||||||
take: pageSize,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!children || children.length === 0 || !includeSubSpaces) {
|
|
||||||
return children
|
|
||||||
.filter(
|
|
||||||
(child) =>
|
|
||||||
child.spaceType.type !== SpaceType.BUILDING &&
|
|
||||||
child.spaceType.type !== SpaceType.COMMUNITY,
|
|
||||||
) // Filter remaining building and community types
|
|
||||||
.map((child) => ({
|
|
||||||
uuid: child.uuid,
|
|
||||||
name: child.spaceName,
|
|
||||||
type: child.spaceType.type,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
const childHierarchies = await Promise.all(
|
|
||||||
children
|
|
||||||
.filter(
|
|
||||||
(child) =>
|
|
||||||
child.spaceType.type !== SpaceType.BUILDING &&
|
|
||||||
child.spaceType.type !== SpaceType.COMMUNITY,
|
|
||||||
) // Filter remaining building and community types
|
|
||||||
.map(async (child) => ({
|
|
||||||
uuid: child.uuid,
|
|
||||||
name: child.spaceName,
|
|
||||||
type: child.spaceType.type,
|
|
||||||
children: await this.buildHierarchy(child, true, 1, pageSize),
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
|
|
||||||
return childHierarchies;
|
|
||||||
}
|
|
||||||
|
|
||||||
async getBuildingParentByUuid(
|
|
||||||
buildingUuid: string,
|
|
||||||
): Promise<BuildingParentInterface> {
|
|
||||||
try {
|
|
||||||
const building = await this.spaceRepository.findOne({
|
|
||||||
where: {
|
|
||||||
uuid: buildingUuid,
|
|
||||||
spaceType: {
|
|
||||||
type: SpaceType.BUILDING,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
relations: ['spaceType', 'parent', 'parent.spaceType'],
|
|
||||||
});
|
|
||||||
if (
|
|
||||||
!building ||
|
|
||||||
!building.spaceType ||
|
|
||||||
building.spaceType.type !== SpaceType.BUILDING
|
|
||||||
) {
|
|
||||||
throw new BadRequestException('Invalid building UUID');
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
uuid: building.uuid,
|
|
||||||
name: building.spaceName,
|
|
||||||
type: building.spaceType.type,
|
|
||||||
parent: {
|
|
||||||
uuid: building.parent.uuid,
|
|
||||||
name: building.parent.spaceName,
|
|
||||||
type: building.parent.spaceType.type,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof BadRequestException) {
|
|
||||||
throw err; // Re-throw BadRequestException
|
|
||||||
} else {
|
|
||||||
throw new HttpException('Building not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getBuildingsByUserId(
|
|
||||||
userUuid: string,
|
|
||||||
): Promise<GetBuildingByUserUuidInterface[]> {
|
|
||||||
try {
|
|
||||||
const buildings = await this.userSpaceRepository.find({
|
|
||||||
relations: ['space', 'space.spaceType'],
|
|
||||||
where: {
|
|
||||||
user: { uuid: userUuid },
|
|
||||||
space: { spaceType: { type: SpaceType.BUILDING } },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (buildings.length === 0) {
|
|
||||||
throw new HttpException(
|
|
||||||
'this user has no buildings',
|
|
||||||
HttpStatus.NOT_FOUND,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const spaces = buildings.map((building) => ({
|
|
||||||
uuid: building.space.uuid,
|
|
||||||
name: building.space.spaceName,
|
|
||||||
type: building.space.spaceType.type,
|
|
||||||
}));
|
|
||||||
|
|
||||||
return spaces;
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof HttpException) {
|
|
||||||
throw err;
|
|
||||||
} else {
|
|
||||||
throw new HttpException('user not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async addUserBuilding(addUserBuildingDto: AddUserBuildingDto) {
|
|
||||||
try {
|
|
||||||
await this.userSpaceRepository.save({
|
|
||||||
user: { uuid: addUserBuildingDto.userUuid },
|
|
||||||
space: { uuid: addUserBuildingDto.buildingUuid },
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
if (err.code === CommonErrorCodes.DUPLICATE_ENTITY) {
|
|
||||||
throw new HttpException(
|
|
||||||
'User already belongs to this building',
|
|
||||||
HttpStatus.BAD_REQUEST,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
throw new HttpException(
|
|
||||||
err.message || 'Internal Server Error',
|
|
||||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async renameBuildingByUuid(
|
|
||||||
buildingUuid: string,
|
|
||||||
updateBuildingNameDto: UpdateBuildingNameDto,
|
|
||||||
): Promise<RenameBuildingByUuidInterface> {
|
|
||||||
try {
|
|
||||||
const building = await this.spaceRepository.findOneOrFail({
|
|
||||||
where: { uuid: buildingUuid },
|
|
||||||
relations: ['spaceType'],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (
|
|
||||||
!building ||
|
|
||||||
!building.spaceType ||
|
|
||||||
building.spaceType.type !== SpaceType.BUILDING
|
|
||||||
) {
|
|
||||||
throw new BadRequestException('Invalid building UUID');
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.spaceRepository.update(
|
|
||||||
{ uuid: buildingUuid },
|
|
||||||
{ spaceName: updateBuildingNameDto.buildingName },
|
|
||||||
);
|
|
||||||
|
|
||||||
// Fetch the updated building
|
|
||||||
const updatedBuilding = await this.spaceRepository.findOneOrFail({
|
|
||||||
where: { uuid: buildingUuid },
|
|
||||||
relations: ['spaceType'],
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
uuid: updatedBuilding.uuid,
|
|
||||||
name: updatedBuilding.spaceName,
|
|
||||||
type: updatedBuilding.spaceType.type,
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof BadRequestException) {
|
|
||||||
throw err; // Re-throw BadRequestException
|
|
||||||
} else {
|
|
||||||
throw new HttpException('Building not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export * from './building.service';
|
|
@ -38,6 +38,7 @@ import { DeviceStatusFirebaseService } from '@app/common/firebase/devices-status
|
|||||||
import { DeviceStatuses } from '@app/common/constants/device-status.enum';
|
import { DeviceStatuses } from '@app/common/constants/device-status.enum';
|
||||||
import { CommonErrorCodes } from '@app/common/constants/error-codes.enum';
|
import { CommonErrorCodes } from '@app/common/constants/error-codes.enum';
|
||||||
import { BatteryStatus } from '@app/common/constants/battery-status.enum';
|
import { BatteryStatus } from '@app/common/constants/battery-status.enum';
|
||||||
|
import { SpaceEntity } from '@app/common/modules/space/entities';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DeviceService {
|
export class DeviceService {
|
||||||
@ -836,6 +837,7 @@ export class DeviceService {
|
|||||||
'permission.permissionType',
|
'permission.permissionType',
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const devicesData = await Promise.allSettled(
|
const devicesData = await Promise.allSettled(
|
||||||
devices.map(async (device) => {
|
devices.map(async (device) => {
|
||||||
let battery = null;
|
let battery = null;
|
||||||
@ -880,22 +882,26 @@ export class DeviceService {
|
|||||||
battery = batteryStatus.value;
|
battery = batteryStatus.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const spaceDevice = device?.spaceDevice;
|
|
||||||
return {
|
|
||||||
space: {
|
|
||||||
uuid: spaceDevice?.uuid,
|
|
||||||
name: spaceDevice?.spaceName,
|
|
||||||
},
|
|
||||||
|
|
||||||
|
const spaceHierarchy = await this.getFullSpaceHierarchy(
|
||||||
|
device?.spaceDevice,
|
||||||
|
);
|
||||||
|
const orderedHierarchy = spaceHierarchy.reverse();
|
||||||
|
|
||||||
|
return {
|
||||||
|
spaces: orderedHierarchy.map((space) => ({
|
||||||
|
uuid: space.uuid,
|
||||||
|
spaceName: space.spaceName,
|
||||||
|
})),
|
||||||
productUuid: device.productDevice.uuid,
|
productUuid: device.productDevice.uuid,
|
||||||
productType: device.productDevice.prodType,
|
productType: device.productDevice.prodType,
|
||||||
permissionType: device.permission[0].permissionType.type,
|
// permissionType: device.permission[0].permissionType.type,
|
||||||
...(await this.getDeviceDetailsByDeviceIdTuya(
|
/* ...(await this.getDeviceDetailsByDeviceIdTuya(
|
||||||
device.deviceTuyaUuid,
|
device.deviceTuyaUuid,
|
||||||
)),
|
)),*/
|
||||||
uuid: device.uuid,
|
uuid: device.uuid,
|
||||||
...(battery && { battery }),
|
...(battery && { battery }),
|
||||||
} as GetDeviceDetailsInterface;
|
};
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -969,4 +975,83 @@ export class DeviceService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getFullSpaceHierarchy(
|
||||||
|
space: SpaceEntity,
|
||||||
|
): Promise<{ uuid: string; spaceName: string }[]> {
|
||||||
|
try {
|
||||||
|
console.log('Fetching hierarchy for space:', space.uuid);
|
||||||
|
|
||||||
|
// Fetch only the relevant spaces, starting with the target space
|
||||||
|
const targetSpace = await this.spaceRepository.findOne({
|
||||||
|
where: { uuid: space.uuid },
|
||||||
|
relations: ['parent', 'children'],
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fetch only the ancestors of the target space
|
||||||
|
const ancestors = await this.fetchAncestors(targetSpace);
|
||||||
|
|
||||||
|
// Optionally, fetch descendants if required
|
||||||
|
const descendants = await this.fetchDescendants(targetSpace);
|
||||||
|
|
||||||
|
const fullHierarchy = [...ancestors, targetSpace, ...descendants].map(
|
||||||
|
(space) => ({
|
||||||
|
uuid: space.uuid,
|
||||||
|
spaceName: space.spaceName,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return fullHierarchy;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching space hierarchy:', error.message);
|
||||||
|
throw new HttpException(
|
||||||
|
'Error fetching space hierarchy',
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async fetchAncestors(space: SpaceEntity): Promise<SpaceEntity[]> {
|
||||||
|
const ancestors: SpaceEntity[] = [];
|
||||||
|
|
||||||
|
let currentSpace = space;
|
||||||
|
while (currentSpace && currentSpace.parent) {
|
||||||
|
// Fetch the parent space
|
||||||
|
const parent = await this.spaceRepository.findOne({
|
||||||
|
where: { uuid: currentSpace.parent.uuid },
|
||||||
|
relations: ['parent'], // To continue fetching upwards
|
||||||
|
});
|
||||||
|
|
||||||
|
if (parent) {
|
||||||
|
ancestors.push(parent);
|
||||||
|
currentSpace = parent;
|
||||||
|
} else {
|
||||||
|
currentSpace = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the ancestors in reverse order to have the root at the start
|
||||||
|
return ancestors.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async fetchDescendants(space: SpaceEntity): Promise<SpaceEntity[]> {
|
||||||
|
const descendants: SpaceEntity[] = [];
|
||||||
|
|
||||||
|
// Fetch the immediate children of the current space
|
||||||
|
const children = await this.spaceRepository.find({
|
||||||
|
where: { parent: { uuid: space.uuid } },
|
||||||
|
relations: ['children'], // To continue fetching downwards
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const child of children) {
|
||||||
|
// Add the child to the descendants list
|
||||||
|
descendants.push(child);
|
||||||
|
|
||||||
|
// Recursively fetch the child's descendants
|
||||||
|
const childDescendants = await this.fetchDescendants(child);
|
||||||
|
descendants.push(...childDescendants);
|
||||||
|
}
|
||||||
|
|
||||||
|
return descendants;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,104 +0,0 @@
|
|||||||
import { FloorService } from '../services/floor.service';
|
|
||||||
import {
|
|
||||||
Body,
|
|
||||||
Controller,
|
|
||||||
Get,
|
|
||||||
HttpStatus,
|
|
||||||
Param,
|
|
||||||
Post,
|
|
||||||
Put,
|
|
||||||
Query,
|
|
||||||
UseGuards,
|
|
||||||
} from '@nestjs/common';
|
|
||||||
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
|
||||||
import { AddFloorDto, AddUserFloorDto } from '../dtos/add.floor.dto';
|
|
||||||
import { GetFloorChildDto } from '../dtos/get.floor.dto';
|
|
||||||
import { UpdateFloorNameDto } from '../dtos/update.floor.dto';
|
|
||||||
import { CheckBuildingTypeGuard } from 'src/guards/building.type.guard';
|
|
||||||
import { CheckUserFloorGuard } from 'src/guards/user.floor.guard';
|
|
||||||
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
|
||||||
import { AdminRoleGuard } from 'src/guards/admin.role.guard';
|
|
||||||
import { FloorPermissionGuard } from 'src/guards/floor.permission.guard';
|
|
||||||
import { EnableDisableStatusEnum } from '@app/common/constants/days.enum';
|
|
||||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
|
||||||
|
|
||||||
@ApiTags('Floor Module')
|
|
||||||
@Controller({
|
|
||||||
version: EnableDisableStatusEnum.ENABLED,
|
|
||||||
path: SpaceType.FLOOR,
|
|
||||||
})
|
|
||||||
export class FloorController {
|
|
||||||
constructor(private readonly floorService: FloorService) {}
|
|
||||||
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, CheckBuildingTypeGuard)
|
|
||||||
@Post()
|
|
||||||
async addFloor(@Body() addFloorDto: AddFloorDto) {
|
|
||||||
const floor = await this.floorService.addFloor(addFloorDto);
|
|
||||||
return {
|
|
||||||
statusCode: HttpStatus.CREATED,
|
|
||||||
success: true,
|
|
||||||
message: 'Floor added successfully',
|
|
||||||
data: floor,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, FloorPermissionGuard)
|
|
||||||
@Get(':floorUuid')
|
|
||||||
async getFloorByUuid(@Param('floorUuid') floorUuid: string) {
|
|
||||||
const floor = await this.floorService.getFloorByUuid(floorUuid);
|
|
||||||
return floor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, FloorPermissionGuard)
|
|
||||||
@Get('child/:floorUuid')
|
|
||||||
async getFloorChildByUuid(
|
|
||||||
@Param('floorUuid') floorUuid: string,
|
|
||||||
@Query() query: GetFloorChildDto,
|
|
||||||
) {
|
|
||||||
const floor = await this.floorService.getFloorChildByUuid(floorUuid, query);
|
|
||||||
return floor;
|
|
||||||
}
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, FloorPermissionGuard)
|
|
||||||
@Get('parent/:floorUuid')
|
|
||||||
async getFloorParentByUuid(@Param('floorUuid') floorUuid: string) {
|
|
||||||
const floor = await this.floorService.getFloorParentByUuid(floorUuid);
|
|
||||||
return floor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(AdminRoleGuard, CheckUserFloorGuard)
|
|
||||||
@Post('user')
|
|
||||||
async addUserFloor(@Body() addUserFloorDto: AddUserFloorDto) {
|
|
||||||
await this.floorService.addUserFloor(addUserFloorDto);
|
|
||||||
return {
|
|
||||||
statusCode: HttpStatus.CREATED,
|
|
||||||
success: true,
|
|
||||||
message: 'user floor added successfully',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard)
|
|
||||||
@Get('user/:userUuid')
|
|
||||||
async getFloorsByUserId(@Param('userUuid') userUuid: string) {
|
|
||||||
return await this.floorService.getFloorsByUserId(userUuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, FloorPermissionGuard)
|
|
||||||
@Put(':floorUuid')
|
|
||||||
async renameFloorByUuid(
|
|
||||||
@Param('floorUuid') floorUuid: string,
|
|
||||||
@Body() updateFloorNameDto: UpdateFloorNameDto,
|
|
||||||
) {
|
|
||||||
const floor = await this.floorService.renameFloorByUuid(
|
|
||||||
floorUuid,
|
|
||||||
updateFloorNameDto,
|
|
||||||
);
|
|
||||||
return floor;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export * from './floor.controller';
|
|
@ -1,42 +0,0 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
|
||||||
import { IsNotEmpty, IsString } from 'class-validator';
|
|
||||||
|
|
||||||
export class AddFloorDto {
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'floorName',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public floorName: string;
|
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'buildingUuid',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public buildingUuid: string;
|
|
||||||
constructor(dto: Partial<AddFloorDto>) {
|
|
||||||
Object.assign(this, dto);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export class AddUserFloorDto {
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'floorUuid',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public floorUuid: string;
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'userUuid',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public userUuid: string;
|
|
||||||
constructor(dto: Partial<AddUserFloorDto>) {
|
|
||||||
Object.assign(this, dto);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
import { BooleanValues } from '@app/common/constants/boolean-values.enum';
|
|
||||||
import { ApiProperty } from '@nestjs/swagger';
|
|
||||||
import { Transform } from 'class-transformer';
|
|
||||||
import {
|
|
||||||
IsBoolean,
|
|
||||||
IsInt,
|
|
||||||
IsNotEmpty,
|
|
||||||
IsOptional,
|
|
||||||
IsString,
|
|
||||||
Min,
|
|
||||||
} from 'class-validator';
|
|
||||||
|
|
||||||
export class GetFloorDto {
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'floorUuid',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public floorUuid: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class GetFloorChildDto {
|
|
||||||
@ApiProperty({ example: 1, description: 'Page number', required: true })
|
|
||||||
@IsInt({ message: 'Page must be a number' })
|
|
||||||
@Min(1, { message: 'Page must not be less than 1' })
|
|
||||||
@IsNotEmpty()
|
|
||||||
public page: number;
|
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
example: 10,
|
|
||||||
description: 'Number of items per page',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsInt({ message: 'Page size must be a number' })
|
|
||||||
@Min(1, { message: 'Page size must not be less than 1' })
|
|
||||||
@IsNotEmpty()
|
|
||||||
public pageSize: number;
|
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
example: true,
|
|
||||||
description: 'Flag to determine whether to fetch full hierarchy',
|
|
||||||
required: false,
|
|
||||||
default: false,
|
|
||||||
})
|
|
||||||
@IsOptional()
|
|
||||||
@IsBoolean()
|
|
||||||
@Transform((value) => {
|
|
||||||
return value.obj.includeSubSpaces === BooleanValues.TRUE;
|
|
||||||
})
|
|
||||||
public includeSubSpaces: boolean = false;
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export * from './add.floor.dto';
|
|
@ -1,16 +0,0 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
|
||||||
import { IsNotEmpty, IsString } from 'class-validator';
|
|
||||||
|
|
||||||
export class UpdateFloorNameDto {
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'floorName',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public floorName: string;
|
|
||||||
|
|
||||||
constructor(dto: Partial<UpdateFloorNameDto>) {
|
|
||||||
Object.assign(this, dto);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
import { FloorService } from './services/floor.service';
|
|
||||||
import { FloorController } from './controllers/floor.controller';
|
|
||||||
import { ConfigModule } from '@nestjs/config';
|
|
||||||
import { SpaceRepositoryModule } from '@app/common/modules/space/space.repository.module';
|
|
||||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
|
||||||
import { SpaceTypeRepository } from '@app/common/modules/space/repositories';
|
|
||||||
import { UserSpaceRepository } from '@app/common/modules/user/repositories';
|
|
||||||
import { UserRepositoryModule } from '@app/common/modules/user/user.repository.module';
|
|
||||||
import { UserRepository } from '@app/common/modules/user/repositories';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [ConfigModule, SpaceRepositoryModule, UserRepositoryModule],
|
|
||||||
controllers: [FloorController],
|
|
||||||
providers: [
|
|
||||||
FloorService,
|
|
||||||
SpaceRepository,
|
|
||||||
SpaceTypeRepository,
|
|
||||||
UserSpaceRepository,
|
|
||||||
UserRepository,
|
|
||||||
],
|
|
||||||
exports: [FloorService],
|
|
||||||
})
|
|
||||||
export class FloorModule {}
|
|
@ -1,32 +0,0 @@
|
|||||||
export interface GetFloorByUuidInterface {
|
|
||||||
uuid: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FloorChildInterface {
|
|
||||||
uuid: string;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
totalCount?: number;
|
|
||||||
children?: FloorChildInterface[];
|
|
||||||
}
|
|
||||||
export interface FloorParentInterface {
|
|
||||||
uuid: string;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
parent?: FloorParentInterface;
|
|
||||||
}
|
|
||||||
export interface RenameFloorByUuidInterface {
|
|
||||||
uuid: string;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GetFloorByUserUuidInterface {
|
|
||||||
uuid: string;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
}
|
|
@ -1,310 +0,0 @@
|
|||||||
import { GetFloorChildDto } from '../dtos/get.floor.dto';
|
|
||||||
import { SpaceTypeRepository } from '../../../libs/common/src/modules/space/repositories/space.repository';
|
|
||||||
import {
|
|
||||||
Injectable,
|
|
||||||
HttpException,
|
|
||||||
HttpStatus,
|
|
||||||
BadRequestException,
|
|
||||||
} from '@nestjs/common';
|
|
||||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
|
||||||
import { AddFloorDto, AddUserFloorDto } from '../dtos';
|
|
||||||
import {
|
|
||||||
FloorChildInterface,
|
|
||||||
FloorParentInterface,
|
|
||||||
GetFloorByUserUuidInterface,
|
|
||||||
GetFloorByUuidInterface,
|
|
||||||
RenameFloorByUuidInterface,
|
|
||||||
} from '../interface/floor.interface';
|
|
||||||
import { SpaceEntity } from '@app/common/modules/space/entities';
|
|
||||||
import { UpdateFloorNameDto } from '../dtos/update.floor.dto';
|
|
||||||
import { UserSpaceRepository } from '@app/common/modules/user/repositories';
|
|
||||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
|
||||||
import { CommonErrorCodes } from '@app/common/constants/error-codes.enum';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class FloorService {
|
|
||||||
constructor(
|
|
||||||
private readonly spaceRepository: SpaceRepository,
|
|
||||||
private readonly spaceTypeRepository: SpaceTypeRepository,
|
|
||||||
private readonly userSpaceRepository: UserSpaceRepository,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
async addFloor(addFloorDto: AddFloorDto) {
|
|
||||||
try {
|
|
||||||
const spaceType = await this.spaceTypeRepository.findOne({
|
|
||||||
where: {
|
|
||||||
type: SpaceType.FLOOR,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const floor = await this.spaceRepository.save({
|
|
||||||
spaceName: addFloorDto.floorName,
|
|
||||||
parent: { uuid: addFloorDto.buildingUuid },
|
|
||||||
spaceType: { uuid: spaceType.uuid },
|
|
||||||
});
|
|
||||||
return floor;
|
|
||||||
} catch (err) {
|
|
||||||
throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getFloorByUuid(floorUuid: string): Promise<GetFloorByUuidInterface> {
|
|
||||||
try {
|
|
||||||
const floor = await this.spaceRepository.findOne({
|
|
||||||
where: {
|
|
||||||
uuid: floorUuid,
|
|
||||||
spaceType: {
|
|
||||||
type: SpaceType.FLOOR,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
relations: ['spaceType'],
|
|
||||||
});
|
|
||||||
if (
|
|
||||||
!floor ||
|
|
||||||
!floor.spaceType ||
|
|
||||||
floor.spaceType.type !== SpaceType.FLOOR
|
|
||||||
) {
|
|
||||||
throw new BadRequestException('Invalid floor UUID');
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
uuid: floor.uuid,
|
|
||||||
createdAt: floor.createdAt,
|
|
||||||
updatedAt: floor.updatedAt,
|
|
||||||
name: floor.spaceName,
|
|
||||||
type: floor.spaceType.type,
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof BadRequestException) {
|
|
||||||
throw err; // Re-throw BadRequestException
|
|
||||||
} else {
|
|
||||||
throw new HttpException('Floor not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async getFloorChildByUuid(
|
|
||||||
floorUuid: string,
|
|
||||||
getFloorChildDto: GetFloorChildDto,
|
|
||||||
): Promise<FloorChildInterface> {
|
|
||||||
try {
|
|
||||||
const { includeSubSpaces, page, pageSize } = getFloorChildDto;
|
|
||||||
|
|
||||||
const space = await this.spaceRepository.findOneOrFail({
|
|
||||||
where: { uuid: floorUuid },
|
|
||||||
relations: ['children', 'spaceType'],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (
|
|
||||||
!space ||
|
|
||||||
!space.spaceType ||
|
|
||||||
space.spaceType.type !== SpaceType.FLOOR
|
|
||||||
) {
|
|
||||||
throw new BadRequestException('Invalid floor UUID');
|
|
||||||
}
|
|
||||||
const totalCount = await this.spaceRepository.count({
|
|
||||||
where: { parent: { uuid: space.uuid } },
|
|
||||||
});
|
|
||||||
|
|
||||||
const children = await this.buildHierarchy(
|
|
||||||
space,
|
|
||||||
includeSubSpaces,
|
|
||||||
page,
|
|
||||||
pageSize,
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
uuid: space.uuid,
|
|
||||||
name: space.spaceName,
|
|
||||||
type: space.spaceType.type,
|
|
||||||
totalCount,
|
|
||||||
children,
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof BadRequestException) {
|
|
||||||
throw err; // Re-throw BadRequestException
|
|
||||||
} else {
|
|
||||||
throw new HttpException('Floor not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async buildHierarchy(
|
|
||||||
space: SpaceEntity,
|
|
||||||
includeSubSpaces: boolean,
|
|
||||||
page: number,
|
|
||||||
pageSize: number,
|
|
||||||
): Promise<FloorChildInterface[]> {
|
|
||||||
const children = await this.spaceRepository.find({
|
|
||||||
where: { parent: { uuid: space.uuid } },
|
|
||||||
relations: ['spaceType'],
|
|
||||||
skip: (page - 1) * pageSize,
|
|
||||||
take: pageSize,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!children || children.length === 0 || !includeSubSpaces) {
|
|
||||||
return children
|
|
||||||
.filter(
|
|
||||||
(child) =>
|
|
||||||
child.spaceType.type !== SpaceType.FLOOR &&
|
|
||||||
child.spaceType.type !== SpaceType.BUILDING &&
|
|
||||||
child.spaceType.type !== SpaceType.COMMUNITY,
|
|
||||||
) // Filter remaining floor and building and community types
|
|
||||||
.map((child) => ({
|
|
||||||
uuid: child.uuid,
|
|
||||||
name: child.spaceName,
|
|
||||||
type: child.spaceType.type,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
const childHierarchies = await Promise.all(
|
|
||||||
children
|
|
||||||
.filter(
|
|
||||||
(child) =>
|
|
||||||
child.spaceType.type !== SpaceType.FLOOR &&
|
|
||||||
child.spaceType.type !== SpaceType.BUILDING &&
|
|
||||||
child.spaceType.type !== SpaceType.COMMUNITY,
|
|
||||||
) // Filter remaining floor and building and community types
|
|
||||||
.map(async (child) => ({
|
|
||||||
uuid: child.uuid,
|
|
||||||
name: child.spaceName,
|
|
||||||
type: child.spaceType.type,
|
|
||||||
children: await this.buildHierarchy(child, true, 1, pageSize),
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
|
|
||||||
return childHierarchies;
|
|
||||||
}
|
|
||||||
|
|
||||||
async getFloorParentByUuid(floorUuid: string): Promise<FloorParentInterface> {
|
|
||||||
try {
|
|
||||||
const floor = await this.spaceRepository.findOne({
|
|
||||||
where: {
|
|
||||||
uuid: floorUuid,
|
|
||||||
spaceType: {
|
|
||||||
type: SpaceType.FLOOR,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
relations: ['spaceType', 'parent', 'parent.spaceType'],
|
|
||||||
});
|
|
||||||
if (
|
|
||||||
!floor ||
|
|
||||||
!floor.spaceType ||
|
|
||||||
floor.spaceType.type !== SpaceType.FLOOR
|
|
||||||
) {
|
|
||||||
throw new BadRequestException('Invalid floor UUID');
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
uuid: floor.uuid,
|
|
||||||
name: floor.spaceName,
|
|
||||||
type: floor.spaceType.type,
|
|
||||||
parent: {
|
|
||||||
uuid: floor.parent.uuid,
|
|
||||||
name: floor.parent.spaceName,
|
|
||||||
type: floor.parent.spaceType.type,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof BadRequestException) {
|
|
||||||
throw err; // Re-throw BadRequestException
|
|
||||||
} else {
|
|
||||||
throw new HttpException('Floor not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getFloorsByUserId(
|
|
||||||
userUuid: string,
|
|
||||||
): Promise<GetFloorByUserUuidInterface[]> {
|
|
||||||
try {
|
|
||||||
const floors = await this.userSpaceRepository.find({
|
|
||||||
relations: ['space', 'space.spaceType'],
|
|
||||||
where: {
|
|
||||||
user: { uuid: userUuid },
|
|
||||||
space: { spaceType: { type: SpaceType.FLOOR } },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (floors.length === 0) {
|
|
||||||
throw new HttpException(
|
|
||||||
'this user has no floors',
|
|
||||||
HttpStatus.NOT_FOUND,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const spaces = floors.map((floor) => ({
|
|
||||||
uuid: floor.space.uuid,
|
|
||||||
name: floor.space.spaceName,
|
|
||||||
type: floor.space.spaceType.type,
|
|
||||||
}));
|
|
||||||
|
|
||||||
return spaces;
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof HttpException) {
|
|
||||||
throw err;
|
|
||||||
} else {
|
|
||||||
throw new HttpException('user not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async addUserFloor(addUserFloorDto: AddUserFloorDto) {
|
|
||||||
try {
|
|
||||||
await this.userSpaceRepository.save({
|
|
||||||
user: { uuid: addUserFloorDto.userUuid },
|
|
||||||
space: { uuid: addUserFloorDto.floorUuid },
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
if (err.code === CommonErrorCodes.DUPLICATE_ENTITY) {
|
|
||||||
throw new HttpException(
|
|
||||||
'User already belongs to this floor',
|
|
||||||
HttpStatus.BAD_REQUEST,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
throw new HttpException(
|
|
||||||
err.message || 'Internal Server Error',
|
|
||||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async renameFloorByUuid(
|
|
||||||
floorUuid: string,
|
|
||||||
updateFloorDto: UpdateFloorNameDto,
|
|
||||||
): Promise<RenameFloorByUuidInterface> {
|
|
||||||
try {
|
|
||||||
const floor = await this.spaceRepository.findOneOrFail({
|
|
||||||
where: { uuid: floorUuid },
|
|
||||||
relations: ['spaceType'],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (
|
|
||||||
!floor ||
|
|
||||||
!floor.spaceType ||
|
|
||||||
floor.spaceType.type !== SpaceType.FLOOR
|
|
||||||
) {
|
|
||||||
throw new BadRequestException('Invalid floor UUID');
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.spaceRepository.update(
|
|
||||||
{ uuid: floorUuid },
|
|
||||||
{ spaceName: updateFloorDto.floorName },
|
|
||||||
);
|
|
||||||
|
|
||||||
// Fetch the updated floor
|
|
||||||
const updatedFloor = await this.spaceRepository.findOneOrFail({
|
|
||||||
where: { uuid: floorUuid },
|
|
||||||
relations: ['spaceType'],
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
uuid: updatedFloor.uuid,
|
|
||||||
name: updatedFloor.spaceName,
|
|
||||||
type: updatedFloor.spaceType.type,
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof BadRequestException) {
|
|
||||||
throw err; // Re-throw BadRequestException
|
|
||||||
} else {
|
|
||||||
throw new HttpException('Floor not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export * from './floor.service';
|
|
@ -1,4 +1,3 @@
|
|||||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
|
||||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
||||||
import {
|
import {
|
||||||
Injectable,
|
Injectable,
|
||||||
@ -40,11 +39,7 @@ export class CheckBuildingTypeGuard implements CanActivate {
|
|||||||
where: { uuid: buildingUuid },
|
where: { uuid: buildingUuid },
|
||||||
relations: ['spaceType'],
|
relations: ['spaceType'],
|
||||||
});
|
});
|
||||||
if (
|
if (!buildingData) {
|
||||||
!buildingData ||
|
|
||||||
!buildingData.spaceType ||
|
|
||||||
buildingData.spaceType.type !== SpaceType.BUILDING
|
|
||||||
) {
|
|
||||||
throw new BadRequestException('Invalid building UUID');
|
throw new BadRequestException('Invalid building UUID');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import {
|
|||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
||||||
import { BadRequestException } from '@nestjs/common';
|
import { BadRequestException } from '@nestjs/common';
|
||||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CheckCommunityTypeGuard implements CanActivate {
|
export class CheckCommunityTypeGuard implements CanActivate {
|
||||||
@ -41,11 +40,7 @@ export class CheckCommunityTypeGuard implements CanActivate {
|
|||||||
relations: ['spaceType'],
|
relations: ['spaceType'],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (
|
if (!communityData) {
|
||||||
!communityData ||
|
|
||||||
!communityData.spaceType ||
|
|
||||||
communityData.spaceType.type !== SpaceType.COMMUNITY
|
|
||||||
) {
|
|
||||||
throw new BadRequestException('Invalid community UUID');
|
throw new BadRequestException('Invalid community UUID');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
|
||||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
||||||
import {
|
import {
|
||||||
Injectable,
|
Injectable,
|
||||||
@ -37,14 +36,9 @@ export class CheckFloorTypeGuard implements CanActivate {
|
|||||||
async checkFloorIsFloorType(floorUuid: string) {
|
async checkFloorIsFloorType(floorUuid: string) {
|
||||||
const floorData = await this.spaceRepository.findOne({
|
const floorData = await this.spaceRepository.findOne({
|
||||||
where: { uuid: floorUuid },
|
where: { uuid: floorUuid },
|
||||||
relations: ['spaceType'],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (
|
if (!floorData) {
|
||||||
!floorData ||
|
|
||||||
!floorData.spaceType ||
|
|
||||||
floorData.spaceType.type !== SpaceType.FLOOR
|
|
||||||
) {
|
|
||||||
throw new BadRequestException('Invalid floor UUID');
|
throw new BadRequestException('Invalid floor UUID');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import {
|
|||||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
||||||
import { BadRequestException, NotFoundException } from '@nestjs/common';
|
import { BadRequestException, NotFoundException } from '@nestjs/common';
|
||||||
import { DeviceRepository } from '@app/common/modules/device/repositories';
|
import { DeviceRepository } from '@app/common/modules/device/repositories';
|
||||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CheckRoomGuard implements CanActivate {
|
export class CheckRoomGuard implements CanActivate {
|
||||||
@ -43,9 +42,6 @@ export class CheckRoomGuard implements CanActivate {
|
|||||||
const room = await this.spaceRepository.findOne({
|
const room = await this.spaceRepository.findOne({
|
||||||
where: {
|
where: {
|
||||||
uuid: roomUuid,
|
uuid: roomUuid,
|
||||||
spaceType: {
|
|
||||||
type: SpaceType.ROOM,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (!room) {
|
if (!room) {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
|
||||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
||||||
import {
|
import {
|
||||||
Injectable,
|
Injectable,
|
||||||
@ -37,14 +36,9 @@ export class CheckUnitTypeGuard implements CanActivate {
|
|||||||
async checkFloorIsFloorType(unitUuid: string) {
|
async checkFloorIsFloorType(unitUuid: string) {
|
||||||
const unitData = await this.spaceRepository.findOne({
|
const unitData = await this.spaceRepository.findOne({
|
||||||
where: { uuid: unitUuid },
|
where: { uuid: unitUuid },
|
||||||
relations: ['spaceType'],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (
|
if (!unitData) {
|
||||||
!unitData ||
|
|
||||||
!unitData.spaceType ||
|
|
||||||
unitData.spaceType.type !== SpaceType.UNIT
|
|
||||||
) {
|
|
||||||
throw new BadRequestException('Invalid unit UUID');
|
throw new BadRequestException('Invalid unit UUID');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ import {
|
|||||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
||||||
import { BadRequestException, NotFoundException } from '@nestjs/common';
|
import { BadRequestException, NotFoundException } from '@nestjs/common';
|
||||||
import { UserRepository } from '@app/common/modules/user/repositories';
|
import { UserRepository } from '@app/common/modules/user/repositories';
|
||||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CheckUserBuildingGuard implements CanActivate {
|
export class CheckUserBuildingGuard implements CanActivate {
|
||||||
@ -44,7 +43,7 @@ export class CheckUserBuildingGuard implements CanActivate {
|
|||||||
|
|
||||||
private async checkBuildingIsFound(spaceUuid: string) {
|
private async checkBuildingIsFound(spaceUuid: string) {
|
||||||
const spaceData = await this.spaceRepository.findOne({
|
const spaceData = await this.spaceRepository.findOne({
|
||||||
where: { uuid: spaceUuid, spaceType: { type: SpaceType.BUILDING } },
|
where: { uuid: spaceUuid },
|
||||||
relations: ['spaceType'],
|
relations: ['spaceType'],
|
||||||
});
|
});
|
||||||
if (!spaceData) {
|
if (!spaceData) {
|
||||||
|
@ -7,7 +7,6 @@ import {
|
|||||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
||||||
import { BadRequestException, NotFoundException } from '@nestjs/common';
|
import { BadRequestException, NotFoundException } from '@nestjs/common';
|
||||||
import { UserRepository } from '@app/common/modules/user/repositories';
|
import { UserRepository } from '@app/common/modules/user/repositories';
|
||||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CheckUserCommunityGuard implements CanActivate {
|
export class CheckUserCommunityGuard implements CanActivate {
|
||||||
@ -44,8 +43,7 @@ export class CheckUserCommunityGuard implements CanActivate {
|
|||||||
|
|
||||||
private async checkCommunityIsFound(spaceUuid: string) {
|
private async checkCommunityIsFound(spaceUuid: string) {
|
||||||
const spaceData = await this.spaceRepository.findOne({
|
const spaceData = await this.spaceRepository.findOne({
|
||||||
where: { uuid: spaceUuid, spaceType: { type: SpaceType.COMMUNITY } },
|
where: { uuid: spaceUuid },
|
||||||
relations: ['spaceType'],
|
|
||||||
});
|
});
|
||||||
if (!spaceData) {
|
if (!spaceData) {
|
||||||
throw new NotFoundException('Community not found');
|
throw new NotFoundException('Community not found');
|
||||||
|
@ -44,8 +44,7 @@ export class CheckUserFloorGuard implements CanActivate {
|
|||||||
|
|
||||||
private async checkFloorIsFound(spaceUuid: string) {
|
private async checkFloorIsFound(spaceUuid: string) {
|
||||||
const spaceData = await this.spaceRepository.findOne({
|
const spaceData = await this.spaceRepository.findOne({
|
||||||
where: { uuid: spaceUuid, spaceType: { type: SpaceType.FLOOR } },
|
where: { uuid: spaceUuid },
|
||||||
relations: ['spaceType'],
|
|
||||||
});
|
});
|
||||||
if (!spaceData) {
|
if (!spaceData) {
|
||||||
throw new NotFoundException('Floor not found');
|
throw new NotFoundException('Floor not found');
|
||||||
|
@ -7,7 +7,6 @@ import {
|
|||||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
||||||
import { BadRequestException, NotFoundException } from '@nestjs/common';
|
import { BadRequestException, NotFoundException } from '@nestjs/common';
|
||||||
import { UserRepository } from '@app/common/modules/user/repositories';
|
import { UserRepository } from '@app/common/modules/user/repositories';
|
||||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CheckUserRoomGuard implements CanActivate {
|
export class CheckUserRoomGuard implements CanActivate {
|
||||||
@ -44,7 +43,7 @@ export class CheckUserRoomGuard implements CanActivate {
|
|||||||
|
|
||||||
private async checkRoomIsFound(spaceUuid: string) {
|
private async checkRoomIsFound(spaceUuid: string) {
|
||||||
const spaceData = await this.spaceRepository.findOne({
|
const spaceData = await this.spaceRepository.findOne({
|
||||||
where: { uuid: spaceUuid, spaceType: { type: SpaceType.ROOM } },
|
where: { uuid: spaceUuid },
|
||||||
relations: ['spaceType'],
|
relations: ['spaceType'],
|
||||||
});
|
});
|
||||||
if (!spaceData) {
|
if (!spaceData) {
|
||||||
|
@ -7,7 +7,6 @@ import {
|
|||||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
||||||
import { BadRequestException, NotFoundException } from '@nestjs/common';
|
import { BadRequestException, NotFoundException } from '@nestjs/common';
|
||||||
import { UserRepository } from '@app/common/modules/user/repositories';
|
import { UserRepository } from '@app/common/modules/user/repositories';
|
||||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CheckUserUnitGuard implements CanActivate {
|
export class CheckUserUnitGuard implements CanActivate {
|
||||||
@ -44,7 +43,7 @@ export class CheckUserUnitGuard implements CanActivate {
|
|||||||
|
|
||||||
private async checkUnitIsFound(spaceUuid: string) {
|
private async checkUnitIsFound(spaceUuid: string) {
|
||||||
const spaceData = await this.spaceRepository.findOne({
|
const spaceData = await this.spaceRepository.findOne({
|
||||||
where: { uuid: spaceUuid, spaceType: { type: SpaceType.UNIT } },
|
where: { uuid: spaceUuid },
|
||||||
relations: ['spaceType'],
|
relations: ['spaceType'],
|
||||||
});
|
});
|
||||||
if (!spaceData) {
|
if (!spaceData) {
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export * from './room.controller';
|
|
@ -1,90 +0,0 @@
|
|||||||
import { RoomService } from '../services/room.service';
|
|
||||||
import {
|
|
||||||
Body,
|
|
||||||
Controller,
|
|
||||||
Get,
|
|
||||||
HttpStatus,
|
|
||||||
Param,
|
|
||||||
Post,
|
|
||||||
Put,
|
|
||||||
UseGuards,
|
|
||||||
} from '@nestjs/common';
|
|
||||||
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
|
||||||
import { AddRoomDto, AddUserRoomDto } from '../dtos/add.room.dto';
|
|
||||||
import { UpdateRoomNameDto } from '../dtos/update.room.dto';
|
|
||||||
import { CheckUnitTypeGuard } from 'src/guards/unit.type.guard';
|
|
||||||
import { CheckUserRoomGuard } from 'src/guards/user.room.guard';
|
|
||||||
import { AdminRoleGuard } from 'src/guards/admin.role.guard';
|
|
||||||
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
|
||||||
import { RoomPermissionGuard } from 'src/guards/room.permission.guard';
|
|
||||||
import { EnableDisableStatusEnum } from '@app/common/constants/days.enum';
|
|
||||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
|
||||||
|
|
||||||
@ApiTags('Room Module')
|
|
||||||
@Controller({
|
|
||||||
version: EnableDisableStatusEnum.ENABLED,
|
|
||||||
path: SpaceType.ROOM,
|
|
||||||
})
|
|
||||||
export class RoomController {
|
|
||||||
constructor(private readonly roomService: RoomService) {}
|
|
||||||
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, CheckUnitTypeGuard)
|
|
||||||
@Post()
|
|
||||||
async addRoom(@Body() addRoomDto: AddRoomDto) {
|
|
||||||
const room = await this.roomService.addRoom(addRoomDto);
|
|
||||||
return {
|
|
||||||
statusCode: HttpStatus.CREATED,
|
|
||||||
success: true,
|
|
||||||
message: 'Room added successfully',
|
|
||||||
data: room,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, RoomPermissionGuard)
|
|
||||||
@Get(':roomUuid')
|
|
||||||
async getRoomByUuid(@Param('roomUuid') roomUuid: string) {
|
|
||||||
const room = await this.roomService.getRoomByUuid(roomUuid);
|
|
||||||
return room;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, RoomPermissionGuard)
|
|
||||||
@Get('parent/:roomUuid')
|
|
||||||
async getRoomParentByUuid(@Param('roomUuid') roomUuid: string) {
|
|
||||||
const room = await this.roomService.getRoomParentByUuid(roomUuid);
|
|
||||||
return room;
|
|
||||||
}
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(AdminRoleGuard, CheckUserRoomGuard)
|
|
||||||
@Post('user')
|
|
||||||
async addUserRoom(@Body() addUserRoomDto: AddUserRoomDto) {
|
|
||||||
await this.roomService.addUserRoom(addUserRoomDto);
|
|
||||||
return {
|
|
||||||
statusCode: HttpStatus.CREATED,
|
|
||||||
success: true,
|
|
||||||
message: 'user room added successfully',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard)
|
|
||||||
@Get('user/:userUuid')
|
|
||||||
async getRoomsByUserId(@Param('userUuid') userUuid: string) {
|
|
||||||
return await this.roomService.getRoomsByUserId(userUuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, RoomPermissionGuard)
|
|
||||||
@Put(':roomUuid')
|
|
||||||
async renameRoomByUuid(
|
|
||||||
@Param('roomUuid') roomUuid: string,
|
|
||||||
@Body() updateRoomNameDto: UpdateRoomNameDto,
|
|
||||||
) {
|
|
||||||
const room = await this.roomService.renameRoomByUuid(
|
|
||||||
roomUuid,
|
|
||||||
updateRoomNameDto,
|
|
||||||
);
|
|
||||||
return room;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
|
||||||
import { IsNotEmpty, IsString } from 'class-validator';
|
|
||||||
|
|
||||||
export class AddRoomDto {
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'roomName',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public roomName: string;
|
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'unitUuid',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public unitUuid: string;
|
|
||||||
constructor(dto: Partial<AddRoomDto>) {
|
|
||||||
Object.assign(this, dto);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export class AddUserRoomDto {
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'roomUuid',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public roomUuid: string;
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'userUuid',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public userUuid: string;
|
|
||||||
constructor(dto: Partial<AddUserRoomDto>) {
|
|
||||||
Object.assign(this, dto);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export * from './add.room.dto';
|
|
@ -1,16 +0,0 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
|
||||||
import { IsNotEmpty, IsString } from 'class-validator';
|
|
||||||
|
|
||||||
export class UpdateRoomNameDto {
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'roomName',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public roomName: string;
|
|
||||||
|
|
||||||
constructor(dto: Partial<UpdateRoomNameDto>) {
|
|
||||||
Object.assign(this, dto);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
export interface GetRoomByUuidInterface {
|
|
||||||
uuid: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RoomParentInterface {
|
|
||||||
uuid: string;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
parent?: RoomParentInterface;
|
|
||||||
}
|
|
||||||
export interface RenameRoomByUuidInterface {
|
|
||||||
uuid: string;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
}
|
|
||||||
export interface GetRoomByUserUuidInterface {
|
|
||||||
uuid: string;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
import { RoomService } from './services/room.service';
|
|
||||||
import { RoomController } from './controllers/room.controller';
|
|
||||||
import { ConfigModule } from '@nestjs/config';
|
|
||||||
import { SpaceRepositoryModule } from '@app/common/modules/space/space.repository.module';
|
|
||||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
|
||||||
import { SpaceTypeRepository } from '@app/common/modules/space/repositories';
|
|
||||||
import { UserSpaceRepository } from '@app/common/modules/user/repositories';
|
|
||||||
import { UserRepositoryModule } from '@app/common/modules/user/user.repository.module';
|
|
||||||
import { UserRepository } from '@app/common/modules/user/repositories';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [ConfigModule, SpaceRepositoryModule, UserRepositoryModule],
|
|
||||||
controllers: [RoomController],
|
|
||||||
providers: [
|
|
||||||
RoomService,
|
|
||||||
SpaceRepository,
|
|
||||||
SpaceTypeRepository,
|
|
||||||
UserSpaceRepository,
|
|
||||||
UserRepository,
|
|
||||||
],
|
|
||||||
exports: [RoomService],
|
|
||||||
})
|
|
||||||
export class RoomModule {}
|
|
@ -1 +0,0 @@
|
|||||||
export * from './room.service';
|
|
@ -1,200 +0,0 @@
|
|||||||
import { SpaceTypeRepository } from '../../../libs/common/src/modules/space/repositories/space.repository';
|
|
||||||
import {
|
|
||||||
Injectable,
|
|
||||||
HttpException,
|
|
||||||
HttpStatus,
|
|
||||||
BadRequestException,
|
|
||||||
} from '@nestjs/common';
|
|
||||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
|
||||||
import { AddRoomDto, AddUserRoomDto } from '../dtos';
|
|
||||||
import {
|
|
||||||
RoomParentInterface,
|
|
||||||
GetRoomByUuidInterface,
|
|
||||||
RenameRoomByUuidInterface,
|
|
||||||
GetRoomByUserUuidInterface,
|
|
||||||
} from '../interface/room.interface';
|
|
||||||
import { UpdateRoomNameDto } from '../dtos/update.room.dto';
|
|
||||||
import { UserSpaceRepository } from '@app/common/modules/user/repositories';
|
|
||||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
|
||||||
import { CommonErrorCodes } from '@app/common/constants/error-codes.enum';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class RoomService {
|
|
||||||
constructor(
|
|
||||||
private readonly spaceRepository: SpaceRepository,
|
|
||||||
private readonly spaceTypeRepository: SpaceTypeRepository,
|
|
||||||
private readonly userSpaceRepository: UserSpaceRepository,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
async addRoom(addRoomDto: AddRoomDto) {
|
|
||||||
try {
|
|
||||||
const spaceType = await this.spaceTypeRepository.findOne({
|
|
||||||
where: {
|
|
||||||
type: SpaceType.ROOM,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const room = await this.spaceRepository.save({
|
|
||||||
spaceName: addRoomDto.roomName,
|
|
||||||
parent: { uuid: addRoomDto.unitUuid },
|
|
||||||
spaceType: { uuid: spaceType.uuid },
|
|
||||||
});
|
|
||||||
return room;
|
|
||||||
} catch (err) {
|
|
||||||
throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getRoomByUuid(roomUuid: string): Promise<GetRoomByUuidInterface> {
|
|
||||||
try {
|
|
||||||
const room = await this.spaceRepository.findOne({
|
|
||||||
where: {
|
|
||||||
uuid: roomUuid,
|
|
||||||
spaceType: {
|
|
||||||
type: SpaceType.ROOM,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
relations: ['spaceType'],
|
|
||||||
});
|
|
||||||
if (!room || !room.spaceType || room.spaceType.type !== SpaceType.ROOM) {
|
|
||||||
throw new BadRequestException('Invalid room UUID');
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
uuid: room.uuid,
|
|
||||||
createdAt: room.createdAt,
|
|
||||||
updatedAt: room.updatedAt,
|
|
||||||
name: room.spaceName,
|
|
||||||
type: room.spaceType.type,
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof BadRequestException) {
|
|
||||||
throw err; // Re-throw BadRequestException
|
|
||||||
} else {
|
|
||||||
throw new HttpException('Room not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getRoomParentByUuid(roomUuid: string): Promise<RoomParentInterface> {
|
|
||||||
try {
|
|
||||||
const room = await this.spaceRepository.findOne({
|
|
||||||
where: {
|
|
||||||
uuid: roomUuid,
|
|
||||||
spaceType: {
|
|
||||||
type: SpaceType.ROOM,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
relations: ['spaceType', 'parent', 'parent.spaceType'],
|
|
||||||
});
|
|
||||||
if (!room || !room.spaceType || room.spaceType.type !== SpaceType.ROOM) {
|
|
||||||
throw new BadRequestException('Invalid room UUID');
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
uuid: room.uuid,
|
|
||||||
name: room.spaceName,
|
|
||||||
type: room.spaceType.type,
|
|
||||||
parent: {
|
|
||||||
uuid: room.parent.uuid,
|
|
||||||
name: room.parent.spaceName,
|
|
||||||
type: room.parent.spaceType.type,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof BadRequestException) {
|
|
||||||
throw err; // Re-throw BadRequestException
|
|
||||||
} else {
|
|
||||||
throw new HttpException('Room not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getRoomsByUserId(
|
|
||||||
userUuid: string,
|
|
||||||
): Promise<GetRoomByUserUuidInterface[]> {
|
|
||||||
try {
|
|
||||||
const rooms = await this.userSpaceRepository.find({
|
|
||||||
relations: ['space', 'space.spaceType'],
|
|
||||||
where: {
|
|
||||||
user: { uuid: userUuid },
|
|
||||||
space: { spaceType: { type: SpaceType.ROOM } },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (rooms.length === 0) {
|
|
||||||
throw new HttpException('this user has no rooms', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
const spaces = rooms.map((room) => ({
|
|
||||||
uuid: room.space.uuid,
|
|
||||||
name: room.space.spaceName,
|
|
||||||
type: room.space.spaceType.type,
|
|
||||||
}));
|
|
||||||
|
|
||||||
return spaces;
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof HttpException) {
|
|
||||||
throw err;
|
|
||||||
} else {
|
|
||||||
throw new HttpException('user not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async addUserRoom(addUserRoomDto: AddUserRoomDto) {
|
|
||||||
try {
|
|
||||||
await this.userSpaceRepository.save({
|
|
||||||
user: { uuid: addUserRoomDto.userUuid },
|
|
||||||
space: { uuid: addUserRoomDto.roomUuid },
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
if (err.code === CommonErrorCodes.DUPLICATE_ENTITY) {
|
|
||||||
throw new HttpException(
|
|
||||||
'User already belongs to this room',
|
|
||||||
HttpStatus.BAD_REQUEST,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
throw new HttpException(
|
|
||||||
err.message || 'Internal Server Error',
|
|
||||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async renameRoomByUuid(
|
|
||||||
roomUuid: string,
|
|
||||||
updateRoomNameDto: UpdateRoomNameDto,
|
|
||||||
): Promise<RenameRoomByUuidInterface> {
|
|
||||||
try {
|
|
||||||
const room = await this.spaceRepository.findOneOrFail({
|
|
||||||
where: { uuid: roomUuid },
|
|
||||||
relations: ['spaceType'],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!room || !room.spaceType || room.spaceType.type !== SpaceType.ROOM) {
|
|
||||||
throw new BadRequestException('Invalid room UUID');
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.spaceRepository.update(
|
|
||||||
{ uuid: roomUuid },
|
|
||||||
{ spaceName: updateRoomNameDto.roomName },
|
|
||||||
);
|
|
||||||
|
|
||||||
// Fetch the updated room
|
|
||||||
const updateRoom = await this.spaceRepository.findOneOrFail({
|
|
||||||
where: { uuid: roomUuid },
|
|
||||||
relations: ['spaceType'],
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
uuid: updateRoom.uuid,
|
|
||||||
name: updateRoom.spaceName,
|
|
||||||
type: updateRoom.spaceType.type,
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof BadRequestException) {
|
|
||||||
throw err; // Re-throw BadRequestException
|
|
||||||
} else {
|
|
||||||
throw new HttpException('Room not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,7 +6,6 @@ import {
|
|||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
||||||
import { AddSceneTapToRunDto, UpdateSceneTapToRunDto } from '../dtos';
|
import { AddSceneTapToRunDto, UpdateSceneTapToRunDto } from '../dtos';
|
||||||
import { GetUnitByUuidInterface } from 'src/unit/interface/unit.interface';
|
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { TuyaContext } from '@tuya/tuya-connector-nodejs';
|
import { TuyaContext } from '@tuya/tuya-connector-nodejs';
|
||||||
import { convertKeysToSnakeCase } from '@app/common/helper/snakeCaseConverter';
|
import { convertKeysToSnakeCase } from '@app/common/helper/snakeCaseConverter';
|
||||||
@ -18,7 +17,6 @@ import {
|
|||||||
SceneDetailsResult,
|
SceneDetailsResult,
|
||||||
} from '../interface/scene.interface';
|
} from '../interface/scene.interface';
|
||||||
import { convertKeysToCamelCase } from '@app/common/helper/camelCaseConverter';
|
import { convertKeysToCamelCase } from '@app/common/helper/camelCaseConverter';
|
||||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
|
||||||
import { ActionExecutorEnum } from '@app/common/constants/automation.enum';
|
import { ActionExecutorEnum } from '@app/common/constants/automation.enum';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -104,18 +102,14 @@ export class SceneService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async getUnitByUuid(unitUuid: string): Promise<GetUnitByUuidInterface> {
|
async getUnitByUuid(unitUuid: string) {
|
||||||
try {
|
try {
|
||||||
const unit = await this.spaceRepository.findOne({
|
const unit = await this.spaceRepository.findOne({
|
||||||
where: {
|
where: {
|
||||||
uuid: unitUuid,
|
uuid: unitUuid,
|
||||||
spaceType: {
|
|
||||||
type: SpaceType.UNIT,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
relations: ['spaceType'],
|
|
||||||
});
|
});
|
||||||
if (!unit || !unit.spaceType || unit.spaceType.type !== SpaceType.UNIT) {
|
if (!unit) {
|
||||||
throw new BadRequestException('Invalid unit UUID');
|
throw new BadRequestException('Invalid unit UUID');
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@ -123,7 +117,6 @@ export class SceneService {
|
|||||||
createdAt: unit.createdAt,
|
createdAt: unit.createdAt,
|
||||||
updatedAt: unit.updatedAt,
|
updatedAt: unit.updatedAt,
|
||||||
name: unit.spaceName,
|
name: unit.spaceName,
|
||||||
type: unit.spaceType.type,
|
|
||||||
spaceTuyaUuid: unit.spaceTuyaUuid,
|
spaceTuyaUuid: unit.spaceTuyaUuid,
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export * from './unit.controller';
|
|
@ -1,126 +0,0 @@
|
|||||||
import { UnitService } from '../services/unit.service';
|
|
||||||
import {
|
|
||||||
Body,
|
|
||||||
Controller,
|
|
||||||
Get,
|
|
||||||
HttpStatus,
|
|
||||||
Param,
|
|
||||||
Post,
|
|
||||||
Put,
|
|
||||||
Query,
|
|
||||||
UseGuards,
|
|
||||||
} from '@nestjs/common';
|
|
||||||
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
|
|
||||||
import {
|
|
||||||
AddUnitDto,
|
|
||||||
AddUserUnitDto,
|
|
||||||
AddUserUnitUsingCodeDto,
|
|
||||||
} from '../dtos/add.unit.dto';
|
|
||||||
import { GetUnitChildDto } from '../dtos/get.unit.dto';
|
|
||||||
import { UpdateUnitNameDto } from '../dtos/update.unit.dto';
|
|
||||||
import { CheckFloorTypeGuard } from 'src/guards/floor.type.guard';
|
|
||||||
import { CheckUserUnitGuard } from 'src/guards/user.unit.guard';
|
|
||||||
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
|
||||||
import { UnitPermissionGuard } from 'src/guards/unit.permission.guard';
|
|
||||||
import { EnableDisableStatusEnum } from '@app/common/constants/days.enum';
|
|
||||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
|
||||||
|
|
||||||
@ApiTags('Unit Module')
|
|
||||||
@Controller({
|
|
||||||
version: EnableDisableStatusEnum.ENABLED,
|
|
||||||
path: SpaceType.UNIT,
|
|
||||||
})
|
|
||||||
export class UnitController {
|
|
||||||
constructor(private readonly unitService: UnitService) {}
|
|
||||||
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, CheckFloorTypeGuard)
|
|
||||||
@Post()
|
|
||||||
async addUnit(@Body() addUnitDto: AddUnitDto) {
|
|
||||||
const unit = await this.unitService.addUnit(addUnitDto);
|
|
||||||
return {
|
|
||||||
statusCode: HttpStatus.CREATED,
|
|
||||||
success: true,
|
|
||||||
message: 'Unit added successfully',
|
|
||||||
data: unit,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, UnitPermissionGuard)
|
|
||||||
@Get(':unitUuid')
|
|
||||||
async getUnitByUuid(@Param('unitUuid') unitUuid: string) {
|
|
||||||
const unit = await this.unitService.getUnitByUuid(unitUuid);
|
|
||||||
return unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, UnitPermissionGuard)
|
|
||||||
@Get('child/:unitUuid')
|
|
||||||
async getUnitChildByUuid(
|
|
||||||
@Param('unitUuid') unitUuid: string,
|
|
||||||
@Query() query: GetUnitChildDto,
|
|
||||||
) {
|
|
||||||
const unit = await this.unitService.getUnitChildByUuid(unitUuid, query);
|
|
||||||
return unit;
|
|
||||||
}
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, UnitPermissionGuard)
|
|
||||||
@Get('parent/:unitUuid')
|
|
||||||
async getUnitParentByUuid(@Param('unitUuid') unitUuid: string) {
|
|
||||||
const unit = await this.unitService.getUnitParentByUuid(unitUuid);
|
|
||||||
return unit;
|
|
||||||
}
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, CheckUserUnitGuard)
|
|
||||||
@Post('user')
|
|
||||||
async addUserUnit(@Body() addUserUnitDto: AddUserUnitDto) {
|
|
||||||
await this.unitService.addUserUnit(addUserUnitDto);
|
|
||||||
return {
|
|
||||||
statusCode: HttpStatus.CREATED,
|
|
||||||
success: true,
|
|
||||||
message: 'user unit added successfully',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard)
|
|
||||||
@Get('user/:userUuid')
|
|
||||||
async getUnitsByUserId(@Param('userUuid') userUuid: string) {
|
|
||||||
return await this.unitService.getUnitsByUserId(userUuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, UnitPermissionGuard)
|
|
||||||
@Put(':unitUuid')
|
|
||||||
async renameUnitByUuid(
|
|
||||||
@Param('unitUuid') unitUuid: string,
|
|
||||||
@Body() updateUnitNameDto: UpdateUnitNameDto,
|
|
||||||
) {
|
|
||||||
const unit = await this.unitService.renameUnitByUuid(
|
|
||||||
unitUuid,
|
|
||||||
updateUnitNameDto,
|
|
||||||
);
|
|
||||||
return unit;
|
|
||||||
}
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard, UnitPermissionGuard)
|
|
||||||
@Get(':unitUuid/invitation-code')
|
|
||||||
async getUnitInvitationCode(@Param('unitUuid') unitUuid: string) {
|
|
||||||
const unit = await this.unitService.getUnitInvitationCode(unitUuid);
|
|
||||||
return unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiBearerAuth()
|
|
||||||
@UseGuards(JwtAuthGuard)
|
|
||||||
@Post('user/verify-code')
|
|
||||||
async verifyCodeAndAddUserUnit(
|
|
||||||
@Body() addUserUnitUsingCodeDto: AddUserUnitUsingCodeDto,
|
|
||||||
) {
|
|
||||||
await this.unitService.verifyCodeAndAddUserUnit(addUserUnitUsingCodeDto);
|
|
||||||
return {
|
|
||||||
statusCode: HttpStatus.CREATED,
|
|
||||||
success: true,
|
|
||||||
message: 'user unit added successfully',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
|
||||||
import { IsNotEmpty, IsString } from 'class-validator';
|
|
||||||
|
|
||||||
export class AddUnitDto {
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'unitName',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public unitName: string;
|
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'floorUuid',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public floorUuid: string;
|
|
||||||
constructor(dto: Partial<AddUnitDto>) {
|
|
||||||
Object.assign(this, dto);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export class AddUserUnitDto {
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'unitUuid',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public unitUuid: string;
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'userUuid',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public userUuid: string;
|
|
||||||
constructor(dto: Partial<AddUserUnitDto>) {
|
|
||||||
Object.assign(this, dto);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export class AddUserUnitUsingCodeDto {
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'userUuid',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public userUuid: string;
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'inviteCode',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public inviteCode: string;
|
|
||||||
constructor(dto: Partial<AddUserUnitDto>) {
|
|
||||||
Object.assign(this, dto);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
|
||||||
import { IsInt, IsNotEmpty, IsString, Min } from 'class-validator';
|
|
||||||
|
|
||||||
export class GetUnitDto {
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'unitUuid',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public unitUuid: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class GetUnitChildDto {
|
|
||||||
@ApiProperty({ example: 1, description: 'Page number', required: true })
|
|
||||||
@IsInt({ message: 'Page must be a number' })
|
|
||||||
@Min(1, { message: 'Page must not be less than 1' })
|
|
||||||
@IsNotEmpty()
|
|
||||||
public page: number;
|
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
example: 10,
|
|
||||||
description: 'Number of items per page',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsInt({ message: 'Page size must be a number' })
|
|
||||||
@Min(1, { message: 'Page size must not be less than 1' })
|
|
||||||
@IsNotEmpty()
|
|
||||||
public pageSize: number;
|
|
||||||
}
|
|
||||||
export class GetUnitByUserIdDto {
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'userUuid',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public userUuid: string;
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export * from './add.unit.dto';
|
|
@ -1,16 +0,0 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
|
||||||
import { IsNotEmpty, IsString } from 'class-validator';
|
|
||||||
|
|
||||||
export class UpdateUnitNameDto {
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'unitName',
|
|
||||||
required: true,
|
|
||||||
})
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public unitName: string;
|
|
||||||
|
|
||||||
constructor(dto: Partial<UpdateUnitNameDto>) {
|
|
||||||
Object.assign(this, dto);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
export interface GetUnitByUuidInterface {
|
|
||||||
uuid: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
spaceTuyaUuid: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UnitChildInterface {
|
|
||||||
uuid: string;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
totalCount?: number;
|
|
||||||
children?: UnitChildInterface[];
|
|
||||||
}
|
|
||||||
export interface UnitParentInterface {
|
|
||||||
uuid: string;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
parent?: UnitParentInterface;
|
|
||||||
}
|
|
||||||
export interface RenameUnitByUuidInterface {
|
|
||||||
uuid: string;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
}
|
|
||||||
export interface GetUnitByUserUuidInterface {
|
|
||||||
uuid: string;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
}
|
|
||||||
export interface addTuyaSpaceInterface {
|
|
||||||
success: boolean;
|
|
||||||
result: string;
|
|
||||||
msg: string;
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export * from './unit.service';
|
|
@ -1,453 +0,0 @@
|
|||||||
import { GetUnitChildDto } from '../dtos/get.unit.dto';
|
|
||||||
import { SpaceTypeRepository } from '../../../libs/common/src/modules/space/repositories/space.repository';
|
|
||||||
import {
|
|
||||||
Injectable,
|
|
||||||
HttpException,
|
|
||||||
HttpStatus,
|
|
||||||
BadRequestException,
|
|
||||||
} from '@nestjs/common';
|
|
||||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
|
||||||
import { AddUnitDto, AddUserUnitDto, AddUserUnitUsingCodeDto } from '../dtos';
|
|
||||||
import {
|
|
||||||
UnitChildInterface,
|
|
||||||
UnitParentInterface,
|
|
||||||
GetUnitByUuidInterface,
|
|
||||||
RenameUnitByUuidInterface,
|
|
||||||
GetUnitByUserUuidInterface,
|
|
||||||
addTuyaSpaceInterface,
|
|
||||||
} from '../interface/unit.interface';
|
|
||||||
import { SpaceEntity } from '@app/common/modules/space/entities';
|
|
||||||
import { UpdateUnitNameDto } from '../dtos/update.unit.dto';
|
|
||||||
import { UserSpaceRepository } from '@app/common/modules/user/repositories';
|
|
||||||
import { generateRandomString } from '@app/common/helper/randomString';
|
|
||||||
import { UserDevicePermissionService } from 'src/user-device-permission/services';
|
|
||||||
import { PermissionType } from '@app/common/constants/permission-type.enum';
|
|
||||||
import { TuyaContext } from '@tuya/tuya-connector-nodejs';
|
|
||||||
import { ConfigService } from '@nestjs/config';
|
|
||||||
import { SpaceType } from '@app/common/constants/space-type.enum';
|
|
||||||
import { CommonErrorCodes } from '@app/common/constants/error-codes.enum';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class UnitService {
|
|
||||||
private tuya: TuyaContext;
|
|
||||||
constructor(
|
|
||||||
private readonly configService: ConfigService,
|
|
||||||
private readonly spaceRepository: SpaceRepository,
|
|
||||||
private readonly spaceTypeRepository: SpaceTypeRepository,
|
|
||||||
private readonly userSpaceRepository: UserSpaceRepository,
|
|
||||||
private readonly userDevicePermissionService: UserDevicePermissionService,
|
|
||||||
) {
|
|
||||||
const accessKey = this.configService.get<string>('auth-config.ACCESS_KEY');
|
|
||||||
const secretKey = this.configService.get<string>('auth-config.SECRET_KEY');
|
|
||||||
const tuyaEuUrl = this.configService.get<string>('tuya-config.TUYA_EU_URL');
|
|
||||||
|
|
||||||
this.tuya = new TuyaContext({
|
|
||||||
baseUrl: tuyaEuUrl,
|
|
||||||
accessKey,
|
|
||||||
secretKey,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async addUnit(addUnitDto: AddUnitDto) {
|
|
||||||
try {
|
|
||||||
const spaceType = await this.spaceTypeRepository.findOne({
|
|
||||||
where: {
|
|
||||||
type: SpaceType.UNIT,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const tuyaUnit = await this.addUnitTuya(addUnitDto.unitName);
|
|
||||||
if (!tuyaUnit.result) {
|
|
||||||
throw new HttpException('Error creating unit', HttpStatus.BAD_REQUEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
const unit = await this.spaceRepository.save({
|
|
||||||
spaceName: addUnitDto.unitName,
|
|
||||||
parent: { uuid: addUnitDto.floorUuid },
|
|
||||||
spaceType: { uuid: spaceType.uuid },
|
|
||||||
spaceTuyaUuid: tuyaUnit.result,
|
|
||||||
});
|
|
||||||
return unit;
|
|
||||||
} catch (err) {
|
|
||||||
throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async addUnitTuya(unitName: string): Promise<addTuyaSpaceInterface> {
|
|
||||||
try {
|
|
||||||
const path = `/v2.0/cloud/space/creation`;
|
|
||||||
const response = await this.tuya.request({
|
|
||||||
method: 'POST',
|
|
||||||
path,
|
|
||||||
body: {
|
|
||||||
name: unitName,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return response as addTuyaSpaceInterface;
|
|
||||||
} catch (error) {
|
|
||||||
throw new HttpException(
|
|
||||||
'Error creating unit from Tuya',
|
|
||||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getUnitByUuid(unitUuid: string): Promise<GetUnitByUuidInterface> {
|
|
||||||
try {
|
|
||||||
const unit = await this.spaceRepository.findOne({
|
|
||||||
where: {
|
|
||||||
uuid: unitUuid,
|
|
||||||
spaceType: {
|
|
||||||
type: SpaceType.UNIT,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
relations: ['spaceType'],
|
|
||||||
});
|
|
||||||
if (!unit || !unit.spaceType || unit.spaceType.type !== SpaceType.UNIT) {
|
|
||||||
throw new BadRequestException('Invalid unit UUID');
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
uuid: unit.uuid,
|
|
||||||
createdAt: unit.createdAt,
|
|
||||||
updatedAt: unit.updatedAt,
|
|
||||||
name: unit.spaceName,
|
|
||||||
type: unit.spaceType.type,
|
|
||||||
spaceTuyaUuid: unit.spaceTuyaUuid,
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof BadRequestException) {
|
|
||||||
throw err; // Re-throw BadRequestException
|
|
||||||
} else {
|
|
||||||
throw new HttpException('Unit not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async getUnitChildByUuid(
|
|
||||||
unitUuid: string,
|
|
||||||
getUnitChildDto: GetUnitChildDto,
|
|
||||||
): Promise<UnitChildInterface> {
|
|
||||||
try {
|
|
||||||
const { page, pageSize } = getUnitChildDto;
|
|
||||||
|
|
||||||
const space = await this.spaceRepository.findOneOrFail({
|
|
||||||
where: { uuid: unitUuid },
|
|
||||||
relations: ['children', 'spaceType'],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (
|
|
||||||
!space ||
|
|
||||||
!space.spaceType ||
|
|
||||||
space.spaceType.type !== SpaceType.UNIT
|
|
||||||
) {
|
|
||||||
throw new BadRequestException('Invalid unit UUID');
|
|
||||||
}
|
|
||||||
|
|
||||||
const totalCount = await this.spaceRepository.count({
|
|
||||||
where: { parent: { uuid: space.uuid } },
|
|
||||||
});
|
|
||||||
|
|
||||||
const children = await this.buildHierarchy(space, false, page, pageSize);
|
|
||||||
|
|
||||||
return {
|
|
||||||
uuid: space.uuid,
|
|
||||||
name: space.spaceName,
|
|
||||||
type: space.spaceType.type,
|
|
||||||
totalCount,
|
|
||||||
children,
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof BadRequestException) {
|
|
||||||
throw err; // Re-throw BadRequestException
|
|
||||||
} else {
|
|
||||||
throw new HttpException('Unit not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async buildHierarchy(
|
|
||||||
space: SpaceEntity,
|
|
||||||
includeSubSpaces: boolean,
|
|
||||||
page: number,
|
|
||||||
pageSize: number,
|
|
||||||
): Promise<UnitChildInterface[]> {
|
|
||||||
const children = await this.spaceRepository.find({
|
|
||||||
where: { parent: { uuid: space.uuid } },
|
|
||||||
relations: ['spaceType'],
|
|
||||||
skip: (page - 1) * pageSize,
|
|
||||||
take: pageSize,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!children || children.length === 0 || !includeSubSpaces) {
|
|
||||||
return children
|
|
||||||
.filter(
|
|
||||||
(child) =>
|
|
||||||
child.spaceType.type !== SpaceType.UNIT &&
|
|
||||||
child.spaceType.type !== SpaceType.FLOOR &&
|
|
||||||
child.spaceType.type !== SpaceType.COMMUNITY &&
|
|
||||||
child.spaceType.type !== SpaceType.UNIT,
|
|
||||||
) // Filter remaining unit and floor and community and unit types
|
|
||||||
.map((child) => ({
|
|
||||||
uuid: child.uuid,
|
|
||||||
name: child.spaceName,
|
|
||||||
type: child.spaceType.type,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
const childHierarchies = await Promise.all(
|
|
||||||
children
|
|
||||||
.filter(
|
|
||||||
(child) =>
|
|
||||||
child.spaceType.type !== SpaceType.UNIT &&
|
|
||||||
child.spaceType.type !== SpaceType.FLOOR &&
|
|
||||||
child.spaceType.type !== SpaceType.COMMUNITY &&
|
|
||||||
child.spaceType.type !== SpaceType.UNIT,
|
|
||||||
) // Filter remaining unit and floor and community and unit types
|
|
||||||
.map(async (child) => ({
|
|
||||||
uuid: child.uuid,
|
|
||||||
name: child.spaceName,
|
|
||||||
type: child.spaceType.type,
|
|
||||||
children: await this.buildHierarchy(child, true, 1, pageSize),
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
|
|
||||||
return childHierarchies;
|
|
||||||
}
|
|
||||||
|
|
||||||
async getUnitParentByUuid(unitUuid: string): Promise<UnitParentInterface> {
|
|
||||||
try {
|
|
||||||
const unit = await this.spaceRepository.findOne({
|
|
||||||
where: {
|
|
||||||
uuid: unitUuid,
|
|
||||||
spaceType: {
|
|
||||||
type: SpaceType.UNIT,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
relations: ['spaceType', 'parent', 'parent.spaceType'],
|
|
||||||
});
|
|
||||||
if (!unit || !unit.spaceType || unit.spaceType.type !== SpaceType.UNIT) {
|
|
||||||
throw new BadRequestException('Invalid unit UUID');
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
uuid: unit.uuid,
|
|
||||||
name: unit.spaceName,
|
|
||||||
type: unit.spaceType.type,
|
|
||||||
parent: {
|
|
||||||
uuid: unit.parent.uuid,
|
|
||||||
name: unit.parent.spaceName,
|
|
||||||
type: unit.parent.spaceType.type,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof BadRequestException) {
|
|
||||||
throw err; // Re-throw BadRequestException
|
|
||||||
} else {
|
|
||||||
throw new HttpException('Unit not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async getUnitsByUserId(
|
|
||||||
userUuid: string,
|
|
||||||
): Promise<GetUnitByUserUuidInterface[]> {
|
|
||||||
try {
|
|
||||||
const units = await this.userSpaceRepository.find({
|
|
||||||
relations: ['space', 'space.spaceType'],
|
|
||||||
where: {
|
|
||||||
user: { uuid: userUuid },
|
|
||||||
space: { spaceType: { type: SpaceType.UNIT } },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (units.length === 0) {
|
|
||||||
throw new HttpException('this user has no units', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
const spaces = units.map((unit) => ({
|
|
||||||
uuid: unit.space.uuid,
|
|
||||||
name: unit.space.spaceName,
|
|
||||||
type: unit.space.spaceType.type,
|
|
||||||
}));
|
|
||||||
|
|
||||||
return spaces;
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof HttpException) {
|
|
||||||
throw err;
|
|
||||||
} else {
|
|
||||||
throw new HttpException('user not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async addUserUnit(addUserUnitDto: AddUserUnitDto) {
|
|
||||||
try {
|
|
||||||
return await this.userSpaceRepository.save({
|
|
||||||
user: { uuid: addUserUnitDto.userUuid },
|
|
||||||
space: { uuid: addUserUnitDto.unitUuid },
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
if (err.code === CommonErrorCodes.DUPLICATE_ENTITY) {
|
|
||||||
throw new HttpException(
|
|
||||||
'User already belongs to this unit',
|
|
||||||
HttpStatus.BAD_REQUEST,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
throw new HttpException(
|
|
||||||
err.message || 'Internal Server Error',
|
|
||||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async renameUnitByUuid(
|
|
||||||
unitUuid: string,
|
|
||||||
updateUnitNameDto: UpdateUnitNameDto,
|
|
||||||
): Promise<RenameUnitByUuidInterface> {
|
|
||||||
try {
|
|
||||||
const unit = await this.spaceRepository.findOneOrFail({
|
|
||||||
where: { uuid: unitUuid },
|
|
||||||
relations: ['spaceType'],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!unit || !unit.spaceType || unit.spaceType.type !== SpaceType.UNIT) {
|
|
||||||
throw new BadRequestException('Invalid unit UUID');
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.spaceRepository.update(
|
|
||||||
{ uuid: unitUuid },
|
|
||||||
{ spaceName: updateUnitNameDto.unitName },
|
|
||||||
);
|
|
||||||
|
|
||||||
// Fetch the updated unit
|
|
||||||
const updatedUnit = await this.spaceRepository.findOneOrFail({
|
|
||||||
where: { uuid: unitUuid },
|
|
||||||
relations: ['spaceType'],
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
uuid: updatedUnit.uuid,
|
|
||||||
name: updatedUnit.spaceName,
|
|
||||||
type: updatedUnit.spaceType.type,
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof BadRequestException) {
|
|
||||||
throw err; // Re-throw BadRequestException
|
|
||||||
} else {
|
|
||||||
throw new HttpException('Unit not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async getUnitInvitationCode(unitUuid: string): Promise<any> {
|
|
||||||
try {
|
|
||||||
// Generate a 6-character random invitation code
|
|
||||||
const invitationCode = generateRandomString(6);
|
|
||||||
|
|
||||||
// Update the unit with the new invitation code
|
|
||||||
await this.spaceRepository.update({ uuid: unitUuid }, { invitationCode });
|
|
||||||
|
|
||||||
// Fetch the updated unit
|
|
||||||
const updatedUnit = await this.spaceRepository.findOneOrFail({
|
|
||||||
where: { uuid: unitUuid },
|
|
||||||
relations: ['spaceType'],
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
uuid: updatedUnit.uuid,
|
|
||||||
invitationCode: updatedUnit.invitationCode,
|
|
||||||
type: updatedUnit.spaceType.type,
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof BadRequestException) {
|
|
||||||
throw err;
|
|
||||||
} else {
|
|
||||||
throw new HttpException('Unit not found', HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async verifyCodeAndAddUserUnit(
|
|
||||||
addUserUnitUsingCodeDto: AddUserUnitUsingCodeDto,
|
|
||||||
) {
|
|
||||||
try {
|
|
||||||
const unit = await this.findUnitByInviteCode(
|
|
||||||
addUserUnitUsingCodeDto.inviteCode,
|
|
||||||
);
|
|
||||||
|
|
||||||
await this.addUserToUnit(addUserUnitUsingCodeDto.userUuid, unit.uuid);
|
|
||||||
|
|
||||||
await this.clearUnitInvitationCode(unit.uuid);
|
|
||||||
|
|
||||||
const deviceUUIDs = await this.getDeviceUUIDsForUnit(unit.uuid);
|
|
||||||
|
|
||||||
await this.addUserPermissionsToDevices(
|
|
||||||
addUserUnitUsingCodeDto.userUuid,
|
|
||||||
deviceUUIDs,
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
throw new HttpException(
|
|
||||||
'Invalid invitation code',
|
|
||||||
HttpStatus.BAD_REQUEST,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async findUnitByInviteCode(inviteCode: string): Promise<SpaceEntity> {
|
|
||||||
const unit = await this.spaceRepository.findOneOrFail({
|
|
||||||
where: {
|
|
||||||
invitationCode: inviteCode,
|
|
||||||
spaceType: { type: SpaceType.UNIT },
|
|
||||||
},
|
|
||||||
relations: ['spaceType'],
|
|
||||||
});
|
|
||||||
|
|
||||||
return unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async addUserToUnit(userUuid: string, unitUuid: string) {
|
|
||||||
const user = await this.addUserUnit({ userUuid, unitUuid });
|
|
||||||
|
|
||||||
if (user.uuid) {
|
|
||||||
return user;
|
|
||||||
} else {
|
|
||||||
throw new HttpException(
|
|
||||||
'Failed to add user to unit',
|
|
||||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async clearUnitInvitationCode(unitUuid: string) {
|
|
||||||
await this.spaceRepository.update(
|
|
||||||
{ uuid: unitUuid },
|
|
||||||
{ invitationCode: null },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async getDeviceUUIDsForUnit(
|
|
||||||
unitUuid: string,
|
|
||||||
): Promise<{ uuid: string }[]> {
|
|
||||||
const devices = await this.spaceRepository.find({
|
|
||||||
where: { parent: { uuid: unitUuid } },
|
|
||||||
relations: ['devicesSpaceEntity', 'devicesSpaceEntity.productDevice'],
|
|
||||||
});
|
|
||||||
|
|
||||||
const allDevices = devices.flatMap((space) => space.devicesSpaceEntity);
|
|
||||||
|
|
||||||
return allDevices.map((device) => ({ uuid: device.uuid }));
|
|
||||||
}
|
|
||||||
|
|
||||||
private async addUserPermissionsToDevices(
|
|
||||||
userUuid: string,
|
|
||||||
deviceUUIDs: { uuid: string }[],
|
|
||||||
): Promise<void> {
|
|
||||||
const permissionPromises = deviceUUIDs.map(async (device) => {
|
|
||||||
try {
|
|
||||||
await this.userDevicePermissionService.addUserPermission({
|
|
||||||
userUuid,
|
|
||||||
deviceUuid: device.uuid,
|
|
||||||
permissionType: PermissionType.CONTROLLABLE,
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error(
|
|
||||||
`Failed to add permission for device ${device.uuid}: ${error.message}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await Promise.all(permissionPromises);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
import { UnitService } from './services/unit.service';
|
|
||||||
import { UnitController } from './controllers/unit.controller';
|
|
||||||
import { ConfigModule } from '@nestjs/config';
|
|
||||||
import { SpaceRepositoryModule } from '@app/common/modules/space/space.repository.module';
|
|
||||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
|
||||||
import { SpaceTypeRepository } from '@app/common/modules/space/repositories';
|
|
||||||
import { UserSpaceRepository } from '@app/common/modules/user/repositories';
|
|
||||||
import { UserRepositoryModule } from '@app/common/modules/user/user.repository.module';
|
|
||||||
import { UserRepository } from '@app/common/modules/user/repositories';
|
|
||||||
import { UserDevicePermissionService } from 'src/user-device-permission/services';
|
|
||||||
import { DeviceUserPermissionRepository } from '@app/common/modules/device/repositories';
|
|
||||||
import { PermissionTypeRepository } from '@app/common/modules/permission/repositories';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [ConfigModule, SpaceRepositoryModule, UserRepositoryModule],
|
|
||||||
controllers: [UnitController],
|
|
||||||
providers: [
|
|
||||||
UnitService,
|
|
||||||
SpaceRepository,
|
|
||||||
SpaceTypeRepository,
|
|
||||||
UserSpaceRepository,
|
|
||||||
UserRepository,
|
|
||||||
UserDevicePermissionService,
|
|
||||||
DeviceUserPermissionRepository,
|
|
||||||
PermissionTypeRepository,
|
|
||||||
],
|
|
||||||
exports: [UnitService],
|
|
||||||
})
|
|
||||||
export class UnitModule {}
|
|
Reference in New Issue
Block a user