finished refactor vistitor password device

This commit is contained in:
faris Aljohari
2025-03-24 03:28:26 +03:00
parent 8efd8cfba2
commit 6785fb2b1e
6 changed files with 275 additions and 213 deletions
@@ -1,11 +1,11 @@
import { DeviceService } from '../services/device.service';
import { Controller, Get, Param, UseGuards } from '@nestjs/common';
import { Controller, Get, Param, Query, 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';
import { GetDoorLockDevices, ProjectParam } from '../dtos';
@ApiTags('Device Module')
@Controller({
@@ -23,7 +23,10 @@ export class DeviceProjectController {
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);
async getAllDevices(
@Param() param: ProjectParam,
@Query() query: GetDoorLockDevices,
) {
return await this.deviceService.getAllDevices(param, query);
}
}
+12 -1
View File
@@ -1,5 +1,6 @@
import { DeviceTypeEnum } from '@app/common/constants/device-type.enum';
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsOptional, IsString } from 'class-validator';
import { IsEnum, IsNotEmpty, IsOptional, IsString } from 'class-validator';
export class GetDeviceBySpaceUuidDto {
@ApiProperty({
@@ -33,3 +34,13 @@ export class GetDeviceLogsDto {
@IsOptional()
public endTime: string;
}
export class GetDoorLockDevices {
@ApiProperty({
description: 'Device Type',
enum: DeviceTypeEnum,
required: false,
})
@IsEnum(DeviceTypeEnum)
@IsOptional()
public deviceType: DeviceTypeEnum;
}
+184 -119
View File
@@ -31,6 +31,7 @@ import {
import {
GetDeviceBySpaceUuidDto,
GetDeviceLogsDto,
GetDoorLockDevices,
} from '../dtos/get.device.dto';
import {
BatchControlDevicesDto,
@@ -63,6 +64,7 @@ import { SpaceEntity } from '@app/common/modules/space/entities/space.entity';
import { ProjectRepository } from '@app/common/modules/project/repositiories';
import { ProjectParam } from '../dtos';
import { BatchDeviceTypeEnum } from '@app/common/constants/batch-device.enum';
import { DeviceTypeEnum } from '@app/common/constants/device-type.enum';
@Injectable()
export class DeviceService {
@@ -980,131 +982,138 @@ export class DeviceService {
}
}
async getAllDevices(param: ProjectParam): Promise<BaseResponseDto> {
async getAllDevices(
param: ProjectParam,
query: GetDoorLockDevices,
): Promise<BaseResponseDto> {
try {
await this.validateProject(param.projectUuid);
const devices = await this.deviceRepository.find({
where: {
isActive: true,
spaceDevice: {
community: { project: { uuid: param.projectUuid } },
spaceName: Not(ORPHAN_SPACE_NAME),
},
},
relations: [
'spaceDevice.parent',
'spaceDevice.community',
'productDevice',
'permission',
'permission.permissionType',
'subspace',
],
});
const devicesData = await Promise.allSettled(
devices.map(async (device) => {
let battery = null;
// Check if the device is a door lock (DL)
if (device.productDevice.prodType === ProductType.DL) {
const doorLockInstructionsStatus: BaseResponseDto =
await this.getDevicesInstructionStatus(
device.uuid,
param.projectUuid,
);
const batteryStatus: any =
doorLockInstructionsStatus.data.status.find(
(status: any) =>
status.code === BatteryStatus.RESIDUAL_ELECTRICITY,
);
if (batteryStatus) {
battery = batteryStatus.value;
}
}
// Check if the device is a door sensor (DS)
if (device.productDevice.prodType === ProductType.DS) {
const doorSensorInstructionsStatus: BaseResponseDto =
await this.getDevicesInstructionStatus(
device.uuid,
param.projectUuid,
);
const batteryStatus: any =
doorSensorInstructionsStatus.data.status.find(
(status: any) =>
status.code === BatteryStatus.BATTERY_PERCENTAGE,
);
if (batteryStatus) {
battery = batteryStatus.value;
}
}
// Check if the device is a water leak sensor (WL)
if (device.productDevice.prodType === ProductType.WL) {
const doorSensorInstructionsStatus: BaseResponseDto =
await this.getDevicesInstructionStatus(
device.uuid,
param.projectUuid,
);
const batteryStatus: any =
doorSensorInstructionsStatus.data.status.find(
(status: any) =>
status.code === BatteryStatus.BATTERY_PERCENTAGE,
);
if (batteryStatus) {
battery = batteryStatus.value;
}
}
const spaceHierarchy = await this.getParentHierarchy(
device?.spaceDevice,
);
const orderedHierarchy = [
device?.spaceDevice,
...spaceHierarchy.reverse(),
];
return {
spaces: orderedHierarchy.map((space) => ({
uuid: space.uuid,
spaceName: space.spaceName,
})),
productUuid: device.productDevice.uuid,
productType: device.productDevice.prodType,
community: {
uuid: device.spaceDevice.community.uuid,
name: device.spaceDevice.community.name,
if (query.deviceType === DeviceTypeEnum.DOOR_LOCK) {
return await this.getDoorLockDevices(param.projectUuid);
} else if (!query.deviceType) {
const devices = await this.deviceRepository.find({
where: {
isActive: true,
spaceDevice: {
community: { project: { uuid: param.projectUuid } },
spaceName: Not(ORPHAN_SPACE_NAME),
},
subspace: device.subspace,
// permissionType: device.permission[0].permissionType.type,
...(await this.getDeviceDetailsByDeviceIdTuya(
device.deviceTuyaUuid,
)),
uuid: device.uuid,
...(battery && { battery }),
} as GetDeviceDetailsInterface;
}),
);
},
relations: [
'spaceDevice.parent',
'spaceDevice.community',
'productDevice',
'permission',
'permission.permissionType',
'subspace',
],
});
// Filter out rejected promises and extract the fulfilled values
const fulfilledDevices = devicesData
.filter((result) => result.status === DeviceStatuses.FULLFILLED)
.map(
(result) =>
(result as PromiseFulfilledResult<GetDeviceDetailsInterface>).value,
const devicesData = await Promise.allSettled(
devices.map(async (device) => {
let battery = null;
// Check if the device is a door lock (DL)
if (device.productDevice.prodType === ProductType.DL) {
const doorLockInstructionsStatus: BaseResponseDto =
await this.getDevicesInstructionStatus(
device.uuid,
param.projectUuid,
);
const batteryStatus: any =
doorLockInstructionsStatus.data.status.find(
(status: any) =>
status.code === BatteryStatus.RESIDUAL_ELECTRICITY,
);
if (batteryStatus) {
battery = batteryStatus.value;
}
}
// Check if the device is a door sensor (DS)
if (device.productDevice.prodType === ProductType.DS) {
const doorSensorInstructionsStatus: BaseResponseDto =
await this.getDevicesInstructionStatus(
device.uuid,
param.projectUuid,
);
const batteryStatus: any =
doorSensorInstructionsStatus.data.status.find(
(status: any) =>
status.code === BatteryStatus.BATTERY_PERCENTAGE,
);
if (batteryStatus) {
battery = batteryStatus.value;
}
}
// Check if the device is a water leak sensor (WL)
if (device.productDevice.prodType === ProductType.WL) {
const doorSensorInstructionsStatus: BaseResponseDto =
await this.getDevicesInstructionStatus(
device.uuid,
param.projectUuid,
);
const batteryStatus: any =
doorSensorInstructionsStatus.data.status.find(
(status: any) =>
status.code === BatteryStatus.BATTERY_PERCENTAGE,
);
if (batteryStatus) {
battery = batteryStatus.value;
}
}
const spaceHierarchy = await this.getParentHierarchy(
device?.spaceDevice,
);
const orderedHierarchy = [
device?.spaceDevice,
...spaceHierarchy.reverse(),
];
return {
spaces: orderedHierarchy.map((space) => ({
uuid: space.uuid,
spaceName: space.spaceName,
})),
productUuid: device.productDevice.uuid,
productType: device.productDevice.prodType,
community: {
uuid: device.spaceDevice.community.uuid,
name: device.spaceDevice.community.name,
},
subspace: device.subspace,
// permissionType: device.permission[0].permissionType.type,
...(await this.getDeviceDetailsByDeviceIdTuya(
device.deviceTuyaUuid,
)),
uuid: device.uuid,
...(battery && { battery }),
} as GetDeviceDetailsInterface;
}),
);
return new SuccessResponseDto({
message: `Devices fetched successfully`,
data: fulfilledDevices,
statusCode: HttpStatus.OK,
});
// Filter out rejected promises and extract the fulfilled values
const fulfilledDevices = devicesData
.filter((result) => result.status === DeviceStatuses.FULLFILLED)
.map(
(result) =>
(result as PromiseFulfilledResult<GetDeviceDetailsInterface>)
.value,
);
return new SuccessResponseDto({
message: `Devices fetched successfully`,
data: fulfilledDevices,
statusCode: HttpStatus.OK,
});
}
} catch (error) {
throw new HttpException(
error.message || 'Internal server error',
@@ -1650,4 +1659,60 @@ export class DeviceService {
{ spaceDevice: targetSpace },
);
}
async getDoorLockDevices(projectUuid: string) {
await this.validateProject(projectUuid);
const devices = await this.deviceRepository.find({
where: {
productDevice: {
prodType: ProductType.DL,
},
spaceDevice: {
spaceName: Not(ORPHAN_SPACE_NAME),
community: {
project: {
uuid: projectUuid,
},
},
},
isActive: true,
},
relations: ['productDevice', 'spaceDevice'],
});
const devicesData = await Promise.all(
devices?.map(async (device) => {
try {
const deviceDetails = await this.getDeviceDetailsByDeviceIdTuya(
device.deviceTuyaUuid,
);
return {
productUuid: device.productDevice.uuid,
productType: device.productDevice.prodType,
...deviceDetails,
uuid: device.uuid,
spaceName: device.spaceDevice.spaceName,
} as GetDeviceDetailsInterface;
} catch (error) {
console.error(
`Error fetching details for device ${device.deviceTuyaUuid}:`,
error,
);
// Return null to indicate the error
return null;
}
}),
);
// Filter out null values to only include successful device data
const filteredDevicesData = devicesData.filter(
(deviceData) => deviceData !== null,
);
return new SuccessResponseDto({
message: 'Successfully retrieved all pass devices',
data: filteredDevicesData,
statusCode: HttpStatus.OK,
});
}
}