Merge branch 'dev' into feat/project-tag

This commit is contained in:
hannathkadher
2025-03-02 00:22:28 +04:00
26 changed files with 320 additions and 88 deletions

View File

@ -0,0 +1,29 @@
import { DeviceService } from '../services/device.service';
import { Controller, Get, Param, UseGuards } from '@nestjs/common';
import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger';
import { EnableDisableStatusEnum } from '@app/common/constants/days.enum';
import { ControllerRoute } from '@app/common/constants/controller-route';
import { PermissionsGuard } from 'src/guards/permissions.guard';
import { Permissions } from 'src/decorators/permissions.decorator';
import { ProjectParam } from '../dtos';
@ApiTags('Device Module')
@Controller({
version: EnableDisableStatusEnum.ENABLED,
path: ControllerRoute.DEVICE_PROJECT.ROUTE,
})
export class DeviceProjectController {
constructor(private readonly deviceService: DeviceService) {}
@ApiBearerAuth()
@UseGuards(PermissionsGuard)
@Permissions('DEVICE_VIEW')
@Get()
@ApiOperation({
summary: ControllerRoute.DEVICE.ACTIONS.GET_ALL_DEVICES_SUMMARY,
description: ControllerRoute.DEVICE.ACTIONS.GET_ALL_DEVICES_DESCRIPTION,
})
async getAllDevices(@Param() param: ProjectParam) {
return await this.deviceService.getAllDevices(param);
}
}

View File

@ -224,17 +224,6 @@ export class DeviceController {
async getDevicesInGateway(@Param('gatewayUuid') gatewayUuid: string) {
return await this.deviceService.getDevicesInGateway(gatewayUuid);
}
@ApiBearerAuth()
@UseGuards(PermissionsGuard)
@Permissions('DEVICE_VIEW')
@Get()
@ApiOperation({
summary: ControllerRoute.DEVICE.ACTIONS.GET_ALL_DEVICES_SUMMARY,
description: ControllerRoute.DEVICE.ACTIONS.GET_ALL_DEVICES_DESCRIPTION,
})
async getAllDevices() {
return await this.deviceService.getAllDevices();
}
@ApiBearerAuth()
@UseGuards(PermissionsGuard)

View File

@ -20,6 +20,8 @@ import {
} from '@app/common/modules/scene/repositories';
import { SceneDeviceRepository } from '@app/common/modules/scene-device/repositories';
import { AutomationRepository } from '@app/common/modules/automation/repositories';
import { ProjectRepository } from '@app/common/modules/project/repositiories';
import { DeviceProjectController } from './controllers/device-project.controller';
@Module({
imports: [
ConfigModule,
@ -28,13 +30,14 @@ import { AutomationRepository } from '@app/common/modules/automation/repositorie
DeviceRepositoryModule,
DeviceStatusFirebaseModule,
],
controllers: [DeviceController],
controllers: [DeviceController, DeviceProjectController],
providers: [
DeviceService,
ProductRepository,
DeviceUserPermissionRepository,
PermissionTypeRepository,
SpaceRepository,
ProjectRepository,
DeviceRepository,
UserRepository,
TuyaService,

View File

@ -1,3 +1,4 @@
export * from './add.device.dto';
export * from './control.device.dto';
export * from './get.device.dto';
export * from './project.param.dto';

View File

@ -0,0 +1,11 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsUUID } from 'class-validator';
export class ProjectParam {
@ApiProperty({
description: 'UUID of the project this community belongs to',
example: 'd290f1ee-6c54-4b01-90e6-d701748f0851',
})
@IsUUID()
projectUuid: string;
}

View File

@ -60,6 +60,8 @@ import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
import { DeleteSceneFromSceneDeviceDto } from '../dtos/delete.device.dto';
import { DeviceEntity } from '@app/common/modules/device/entities';
import { SpaceEntity } from '@app/common/modules/space/entities/space.entity';
import { ProjectRepository } from '@app/common/modules/project/repositiories';
import { ProjectParam } from '../dtos';
@Injectable()
export class DeviceService {
@ -74,6 +76,7 @@ export class DeviceService {
@Inject(forwardRef(() => SceneService))
private readonly sceneService: SceneService,
private readonly tuyaService: TuyaService,
private readonly projectRepository: ProjectRepository,
) {
const accessKey = this.configService.get<string>('auth-config.ACCESS_KEY');
const secretKey = this.configService.get<string>('auth-config.SECRET_KEY');
@ -950,10 +953,19 @@ export class DeviceService {
);
}
}
async getAllDevices(): Promise<GetDeviceDetailsInterface[]> {
async getAllDevices(
param: ProjectParam,
): Promise<GetDeviceDetailsInterface[]> {
try {
await this.validateProject(param.projectUuid);
const devices = await this.deviceRepository.find({
where: { isActive: true },
where: {
isActive: true,
spaceDevice: {
community: { project: { uuid: param.projectUuid } },
},
},
relations: [
'spaceDevice.parent',
'spaceDevice.community',
@ -1009,10 +1021,13 @@ export class DeviceService {
}
}
const spaceHierarchy = await this.getFullSpaceHierarchy(
const spaceHierarchy = await this.getParentHierarchy(
device?.spaceDevice,
);
const orderedHierarchy = spaceHierarchy.reverse();
const orderedHierarchy = [
device?.spaceDevice,
...spaceHierarchy.reverse(),
];
return {
spaces: orderedHierarchy.map((space) => ({
@ -1490,4 +1505,45 @@ export class DeviceService {
);
}
}
private async validateProject(uuid: string) {
const project = await this.projectRepository.findOne({
where: { uuid },
});
if (!project) {
throw new HttpException(
`A project with the uuid '${uuid}' doesn't exists.`,
HttpStatus.BAD_REQUEST,
);
}
return project;
}
async getParentHierarchy(
space: SpaceEntity,
): Promise<{ uuid: string; spaceName: string }[]> {
try {
const targetSpace = await this.spaceRepository.findOne({
where: { uuid: space.uuid },
relations: ['parent'],
});
if (!targetSpace) {
throw new HttpException('Space not found', HttpStatus.NOT_FOUND);
}
const ancestors = await this.fetchAncestors(targetSpace);
return ancestors.map((parentSpace) => ({
uuid: parentSpace.uuid,
spaceName: parentSpace.spaceName,
}));
} catch (error) {
console.error('Error fetching parent hierarchy:', error.message);
throw new HttpException(
'Error fetching parent hierarchy',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
}