From 2a596d3b33b464e047f77cc6e2b58227baecee42 Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Tue, 27 Aug 2024 22:09:33 +0300 Subject: [PATCH] Add Comprehensive Door Lock Module Enhancements --- src/door-lock/door.lock.module.ts | 16 +- src/door-lock/services/door.lock.service.ts | 236 ++++++++++++++------ 2 files changed, 182 insertions(+), 70 deletions(-) diff --git a/src/door-lock/door.lock.module.ts b/src/door-lock/door.lock.module.ts index 3b1920e..b72fad9 100644 --- a/src/door-lock/door.lock.module.ts +++ b/src/door-lock/door.lock.module.ts @@ -5,10 +5,24 @@ import { ConfigModule } from '@nestjs/config'; import { DeviceRepositoryModule } from '@app/common/modules/device'; import { DeviceRepository } from '@app/common/modules/device/repositories'; import { PasswordEncryptionService } from './services/encryption.services'; +import { VisitorPasswordRepository } from '@app/common/modules/visitor-password/repositories'; +import { DeviceService } from 'src/device/services'; +import { ProductRepository } from '@app/common/modules/product/repositories'; +import { DeviceStatusFirebaseService } from '@app/common/firebase/devices-status/services/devices-status.service'; +import { SpaceRepository } from '@app/common/modules/space/repositories'; @Module({ imports: [ConfigModule, DeviceRepositoryModule], controllers: [DoorLockController], - providers: [DoorLockService, PasswordEncryptionService, DeviceRepository], + providers: [ + DoorLockService, + PasswordEncryptionService, + DeviceRepository, + VisitorPasswordRepository, + DeviceService, + ProductRepository, + DeviceStatusFirebaseService, + SpaceRepository, + ], exports: [DoorLockService], }) export class DoorLockModule {} diff --git a/src/door-lock/services/door.lock.service.ts b/src/door-lock/services/door.lock.service.ts index e875f67..8f81c16 100644 --- a/src/door-lock/services/door.lock.service.ts +++ b/src/door-lock/services/door.lock.service.ts @@ -22,6 +22,8 @@ import { AddDoorLockOfflineTempMultipleTimeDto } from '../dtos/add.offline-temp. import { convertKeysToCamelCase } from '@app/common/helper/camelCaseConverter'; import { UpdateDoorLockOfflineTempDto } from '../dtos/update.offline-temp.dto'; import { defaultDoorLockPass } from '@app/common/constants/default.door-lock-pass'; +import { VisitorPasswordRepository } from '@app/common/modules/visitor-password/repositories'; +import { DeviceService } from 'src/device/services'; @Injectable() export class DoorLockService { @@ -29,7 +31,9 @@ export class DoorLockService { constructor( private readonly configService: ConfigService, private readonly deviceRepository: DeviceRepository, + private readonly deviceService: DeviceService, private readonly passwordEncryptionService: PasswordEncryptionService, + private readonly visitorPasswordRepository: VisitorPasswordRepository, ) { const accessKey = this.configService.get('auth-config.ACCESS_KEY'); const secretKey = this.configService.get('auth-config.SECRET_KEY'); @@ -105,6 +109,10 @@ export class DoorLockService { HttpStatus.BAD_REQUEST, ); } + const deviceTuyaDetails = + await this.deviceService.getDeviceDetailsByDeviceIdTuya( + deviceDetails.deviceTuyaUuid, + ); const passwords = await this.getTemporaryOfflinePasswordsTuya( deviceDetails.deviceTuyaUuid, 'multiple', @@ -115,23 +123,37 @@ export class DoorLockService { } if (passwords.result.records.length > 0) { return fromVisitor - ? convertKeysToCamelCase(passwords.result.records).map((password) => { - const timestampInSeconds = Math.floor(Date.now() / 1000); - return { - passwordId: `${password.pwdId}`, - invalidTime: `${password.gmtExpired}`, - effectiveTime: `${password.gmtStart}`, - passwordCreated: `${password.gmtCreate}`, - createdTime: password.pwdName, - passwordType: 'OFFLINE_MULTIPLE', - deviceUuid: doorLockUuid, - passwordStatus: isExpired - ? 'EXPIRED' - : timestampInSeconds > password.effectiveTime - ? 'EFFECTIVE' - : 'TO_BE_EFFECTIVE', - }; - }) + ? Promise.all( + convertKeysToCamelCase(passwords.result.records).map( + async (password) => { + const passwordFromDB = await this.getVisitorPasswordFromDB( + password.pwdId, + ); + const timestampInSeconds = Math.floor(Date.now() / 1000); + return { + passwordId: `${password.pwdId}`, + invalidTime: `${password.gmtExpired}`, + effectiveTime: `${password.gmtStart}`, + passwordCreated: `${password.gmtCreate}`, + createdTime: password.pwdName, + passwordType: 'OFFLINE_MULTIPLE', + deviceUuid: doorLockUuid, + deviceName: deviceTuyaDetails.name, + passwordStatus: isExpired + ? 'EXPIRED' + : timestampInSeconds > password.effectiveTime + ? 'EFFECTIVE' + : 'TO_BE_EFFECTIVE', + authorizerEmail: passwordFromDB + ? passwordFromDB.user.email + : 'OTHER', + authorizerDate: passwordFromDB + ? `${Math.floor(new Date(passwordFromDB.createdAt).getTime() / 1000)}` + : '', + }; + }, + ), + ) : convertKeysToCamelCase(passwords.result.records); } return passwords; @@ -158,6 +180,10 @@ export class DoorLockService { HttpStatus.BAD_REQUEST, ); } + const deviceTuyaDetails = + await this.deviceService.getDeviceDetailsByDeviceIdTuya( + deviceDetails.deviceTuyaUuid, + ); const passwords = await this.getTemporaryOfflinePasswordsTuya( deviceDetails.deviceTuyaUuid, 'once', @@ -168,23 +194,38 @@ export class DoorLockService { } if (passwords.result.records.length > 0) { return fromVisitor - ? convertKeysToCamelCase(passwords.result.records).map((password) => { - const timestampInSeconds = Math.floor(Date.now() / 1000); - return { - passwordId: `${password.pwdId}`, - invalidTime: `${password.gmtExpired}`, - effectiveTime: `${password.gmtStart}`, - createdTime: `${password.gmtCreate}`, - passwordName: password.pwdName, - passwordType: 'OFFLINE_ONETIME', - deviceUuid: doorLockUuid, - passwordStatus: isExpired - ? 'EXPIRED' - : timestampInSeconds > password.gmtStart - ? 'EFFECTIVE' - : 'TO_BE_EFFECTIVE', - }; - }) + ? Promise.all( + convertKeysToCamelCase(passwords.result.records).map( + async (password) => { + const passwordFromDB = await this.getVisitorPasswordFromDB( + password.pwdId, + ); + + const timestampInSeconds = Math.floor(Date.now() / 1000); + return { + passwordId: `${password.pwdId}`, + invalidTime: `${password.gmtExpired}`, + effectiveTime: `${password.gmtStart}`, + createdTime: `${password.gmtCreate}`, + passwordName: password.pwdName, + passwordType: 'OFFLINE_ONETIME', + deviceUuid: doorLockUuid, + deviceName: deviceTuyaDetails.name, + passwordStatus: isExpired + ? 'EXPIRED' + : timestampInSeconds > password.gmtStart + ? 'EFFECTIVE' + : 'TO_BE_EFFECTIVE', + authorizerEmail: passwordFromDB + ? passwordFromDB.user.email + : 'OTHER', + authorizerDate: passwordFromDB + ? `${Math.floor(new Date(passwordFromDB.createdAt).getTime() / 1000)}` + : '', + }; + }, + ), + ) : convertKeysToCamelCase(passwords.result.records); } @@ -212,6 +253,10 @@ export class DoorLockService { HttpStatus.BAD_REQUEST, ); } + const deviceTuyaDetails = + await this.deviceService.getDeviceDetailsByDeviceIdTuya( + deviceDetails.deviceTuyaUuid, + ); const passwords = await this.getOnlineTemporaryPasswordsMultipleTuya( deviceDetails.deviceTuyaUuid, isExpired, @@ -240,24 +285,36 @@ export class DoorLockService { }); return fromVisitor - ? convertKeysToCamelCase(passwordFiltered).map((password) => { - const timestampInSeconds = Math.floor(Date.now() / 1000); - return { - passwordId: `${password.id}`, - invalidTime: `${password.invalidTime}`, - effectiveTime: `${password.effectiveTime}`, - createdTime: '', - scheduleList: password?.scheduleList, - passwordName: password.name, - passwordType: 'ONLINE_MULTIPLE', - deviceUuid: doorLockUuid, - passwordStatus: isExpired - ? 'EXPIRED' - : timestampInSeconds > password.effectiveTime - ? 'EFFECTIVE' - : 'TO_BE_EFFECTIVE', - }; - }) + ? Promise.all( + convertKeysToCamelCase(passwordFiltered).map(async (password) => { + const passwordFromDB = await this.getVisitorPasswordFromDB( + password.id, + ); + const timestampInSeconds = Math.floor(Date.now() / 1000); + return { + passwordId: `${password.id}`, + invalidTime: `${password.invalidTime}`, + effectiveTime: `${password.effectiveTime}`, + createdTime: '', + scheduleList: password?.scheduleList, + passwordName: password.name, + passwordType: 'ONLINE_MULTIPLE', + deviceUuid: doorLockUuid, + deviceName: deviceTuyaDetails.name, + passwordStatus: isExpired + ? 'EXPIRED' + : timestampInSeconds > password.effectiveTime + ? 'EFFECTIVE' + : 'TO_BE_EFFECTIVE', + authorizerEmail: passwordFromDB + ? passwordFromDB.user.email + : 'OTHER', + authorizerDate: passwordFromDB + ? `${Math.floor(new Date(passwordFromDB.createdAt).getTime() / 1000)}` + : '', + }; + }), + ) : convertKeysToCamelCase(passwordFiltered); } if (fromVisitor) { @@ -271,12 +328,34 @@ export class DoorLockService { ); } } + async getVisitorPasswordFromDB(passwordId: string) { + try { + return await this.visitorPasswordRepository.findOne({ + where: { + passwordTuyaUuid: passwordId, + }, + relations: ['user'], + select: { + user: { + email: true, + }, + }, + }); + } catch (error) { + throw new HttpException( + error.message || 'Error retrieving visitor password from database', + error.status || HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + async getOnlineTemporaryPasswordsOneTime( doorLockUuid: string, fromVisitor?: boolean, isExpired?: boolean, ) { try { + // Retrieve device details const deviceDetails = await this.getDeviceByDeviceUuid(doorLockUuid); if (!deviceDetails || !deviceDetails.deviceTuyaUuid) { @@ -287,11 +366,17 @@ export class DoorLockService { HttpStatus.BAD_REQUEST, ); } + const deviceTuyaDetails = + await this.deviceService.getDeviceDetailsByDeviceIdTuya( + deviceDetails.deviceTuyaUuid, + ); + // Get online temporary passwords const passwords = await this.getOnlineTemporaryPasswordsMultipleTuya( deviceDetails.deviceTuyaUuid, isExpired, ); if (passwords.result?.length > 0) { + // Filter and map the passwords const passwordFiltered = passwords.result .filter((item) => item.type === 1) .map((password: any) => { @@ -314,24 +399,37 @@ export class DoorLockService { return password; }); + // Process passwords with optimized query handling return fromVisitor - ? convertKeysToCamelCase(passwordFiltered).map((password) => { - const timestampInSeconds = Math.floor(Date.now() / 1000); - return { - passwordId: `${password.id}`, - invalidTime: `${password.invalidTime}`, - effectiveTime: `${password.effectiveTime}`, - createdTime: '', - passwordName: password.name, - passwordType: 'ONLINE_ONETIME', - deviceUuid: doorLockUuid, - passwordStatus: isExpired - ? 'EXPIRED' - : timestampInSeconds > password.effectiveTime - ? 'EFFECTIVE' - : 'TO_BE_EFFECTIVE', - }; - }) + ? Promise.all( + convertKeysToCamelCase(passwordFiltered).map(async (password) => { + const passwordFromDB = await this.getVisitorPasswordFromDB( + password.id, + ); + const timestampInSeconds = Math.floor(Date.now() / 1000); + return { + passwordId: `${password.id}`, + invalidTime: `${password.invalidTime}`, + effectiveTime: `${password.effectiveTime}`, + createdTime: '', + passwordName: password.name, + passwordType: 'ONLINE_ONETIME', + deviceUuid: doorLockUuid, + deviceName: deviceTuyaDetails.name, + passwordStatus: isExpired + ? 'EXPIRED' + : timestampInSeconds > password.effectiveTime + ? 'EFFECTIVE' + : 'TO_BE_EFFECTIVE', + authorizerEmail: passwordFromDB + ? passwordFromDB.user.email + : 'OTHER', + authorizerDate: passwordFromDB + ? `${Math.floor(new Date(passwordFromDB.createdAt).getTime() / 1000)}` + : '', + }; + }), + ) : convertKeysToCamelCase(passwordFiltered); } if (fromVisitor) {