From c86be27576e6f4ea9c0fd4c32cc8ccf78a474998 Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Tue, 10 Jun 2025 18:19:34 -0600 Subject: [PATCH] Add AQI module and related services, controllers, and DTOs - Introduced AqiModule with AqiService and AqiController for handling AQI data. - Added DTOs for AQI requests: GetAqiDailyBySpaceDto and GetAqiPollutantBySpaceDto. - Implemented AqiDataService for managing AQI sensor historical data. - Updated existing modules to include AqiDataService where necessary. - Defined new routes for AQI data retrieval in ControllerRoute. --- libs/common/src/constants/controller-route.ts | 14 ++ .../common/src/constants/product-type.enum.ts | 1 + .../devices-status/devices-status.module.ts | 2 + .../services/devices-status.service.ts | 8 +- .../src/helper/services/aqi.data.service.ts | 47 ++++++ .../aqi/repositories/aqi.repository.ts | 10 ++ .../src/modules/aqi/repositories/index.ts | 2 +- .../presence-sensor.repository.ts | 19 --- src/app.module.ts | 2 + src/aqi/aqi.module.ts | 11 ++ src/aqi/controllers/aqi.controller.ts | 64 ++++++++ src/aqi/controllers/index.ts | 1 + src/aqi/dto/aqi-params.dto.ts | 7 + src/aqi/dto/get-aqi.dto.ts | 36 +++++ src/aqi/services/aqi.service.ts | 146 ++++++++++++++++++ src/aqi/services/index.ts | 1 + .../commission-device.module.ts | 2 + src/community/community.module.ts | 2 + src/door-lock/door.lock.module.ts | 2 + src/group/group.module.ts | 2 + src/invite-user/invite-user.module.ts | 2 + src/power-clamp/power-clamp.module.ts | 2 + src/project/project.module.ts | 2 + src/space-model/space-model.module.ts | 2 + src/space/space.module.ts | 2 + .../visitor-password.module.ts | 2 + 26 files changed, 370 insertions(+), 21 deletions(-) create mode 100644 libs/common/src/helper/services/aqi.data.service.ts create mode 100644 libs/common/src/modules/aqi/repositories/aqi.repository.ts delete mode 100644 libs/common/src/modules/aqi/repositories/presence-sensor.repository.ts create mode 100644 src/aqi/aqi.module.ts create mode 100644 src/aqi/controllers/aqi.controller.ts create mode 100644 src/aqi/controllers/index.ts create mode 100644 src/aqi/dto/aqi-params.dto.ts create mode 100644 src/aqi/dto/get-aqi.dto.ts create mode 100644 src/aqi/services/aqi.service.ts create mode 100644 src/aqi/services/index.ts diff --git a/libs/common/src/constants/controller-route.ts b/libs/common/src/constants/controller-route.ts index 064deba..cc37eee 100644 --- a/libs/common/src/constants/controller-route.ts +++ b/libs/common/src/constants/controller-route.ts @@ -524,6 +524,20 @@ export class ControllerRoute { 'This endpoint retrieves the occupancy heat map data based on the provided parameters.'; }; }; + static AQI = class { + public static readonly ROUTE = 'aqi'; + + static ACTIONS = class { + public static readonly GET_AQI_RANGE_DATA_SUMMARY = 'Get AQI range data'; + public static readonly GET_AQI_RANGE_DATA_DESCRIPTION = + 'This endpoint retrieves the AQI (Air Quality Index) range data based on the provided parameters.'; + + public static readonly GET_AQI_DISTRIBUTION_DATA_SUMMARY = + 'Get AQI distribution data'; + public static readonly GET_AQI_DISTRIBUTION_DATA_DESCRIPTION = + 'This endpoint retrieves the AQI (Air Quality Index) distribution data based on the provided parameters.'; + }; + }; static DEVICE = class { public static readonly ROUTE = 'devices'; diff --git a/libs/common/src/constants/product-type.enum.ts b/libs/common/src/constants/product-type.enum.ts index fd0cc6f..1bb1394 100644 --- a/libs/common/src/constants/product-type.enum.ts +++ b/libs/common/src/constants/product-type.enum.ts @@ -19,4 +19,5 @@ export enum ProductType { FOUR_S = '4S', SIX_S = '6S', SOS = 'SOS', + AQI = 'AQI', } diff --git a/libs/common/src/firebase/devices-status/devices-status.module.ts b/libs/common/src/firebase/devices-status/devices-status.module.ts index 784b801..52f6123 100644 --- a/libs/common/src/firebase/devices-status/devices-status.module.ts +++ b/libs/common/src/firebase/devices-status/devices-status.module.ts @@ -11,6 +11,7 @@ import { } from '@app/common/modules/power-clamp/repositories'; import { SqlLoaderService } from '@app/common/helper/services/sql-loader.service'; import { OccupancyService } from '@app/common/helper/services/occupancy.service'; +import { AqiDataService } from '@app/common/helper/services/aqi.data.service'; @Module({ providers: [ @@ -23,6 +24,7 @@ import { OccupancyService } from '@app/common/helper/services/occupancy.service' PowerClampMonthlyRepository, SqlLoaderService, OccupancyService, + AqiDataService, ], controllers: [DeviceStatusFirebaseController], exports: [DeviceStatusFirebaseService, DeviceStatusLogRepository], diff --git a/libs/common/src/firebase/devices-status/services/devices-status.service.ts b/libs/common/src/firebase/devices-status/services/devices-status.service.ts index 18c752c..4b0b0f7 100644 --- a/libs/common/src/firebase/devices-status/services/devices-status.service.ts +++ b/libs/common/src/firebase/devices-status/services/devices-status.service.ts @@ -23,6 +23,7 @@ import { PowerClampService } from '@app/common/helper/services/power.clamp.servi import { PowerClampEnergyEnum } from '@app/common/constants/power.clamp.enargy.enum'; import { PresenceSensorEnum } from '@app/common/constants/presence.sensor.enum'; import { OccupancyService } from '@app/common/helper/services/occupancy.service'; +import { AqiDataService } from '@app/common/helper/services/aqi.data.service'; @Injectable() export class DeviceStatusFirebaseService { private tuya: TuyaContext; @@ -32,6 +33,7 @@ export class DeviceStatusFirebaseService { private readonly deviceRepository: DeviceRepository, private readonly powerClampService: PowerClampService, private readonly occupancyService: OccupancyService, + private readonly aqiDataService: AqiDataService, private deviceStatusLogRepository: DeviceStatusLogRepository, ) { const accessKey = this.configService.get('auth-config.ACCESS_KEY'); @@ -262,7 +264,11 @@ export class DeviceStatusFirebaseService { ); } } - + if (addDeviceStatusDto.productType === ProductType.AQI) { + await this.aqiDataService.updateAQISensorHistoricalData( + addDeviceStatusDto.deviceUuid, + ); + } // Return the updated data const snapshot: DataSnapshot = await get(dataRef); return snapshot.val(); diff --git a/libs/common/src/helper/services/aqi.data.service.ts b/libs/common/src/helper/services/aqi.data.service.ts new file mode 100644 index 0000000..3e19b6c --- /dev/null +++ b/libs/common/src/helper/services/aqi.data.service.ts @@ -0,0 +1,47 @@ +import { DeviceRepository } from '@app/common/modules/device/repositories'; +import { Injectable } from '@nestjs/common'; +import { SqlLoaderService } from './sql-loader.service'; +import { DataSource } from 'typeorm'; +import { SQL_PROCEDURES_PATH } from '@app/common/constants/sql-query-path'; + +@Injectable() +export class AqiDataService { + constructor( + private readonly sqlLoader: SqlLoaderService, + private readonly dataSource: DataSource, + private readonly deviceRepository: DeviceRepository, + ) {} + async updateAQISensorHistoricalData(deviceUuid: string): Promise { + try { + const now = new Date(); + const dateStr = now.toLocaleDateString('en-CA'); // YYYY-MM-DD + const device = await this.deviceRepository.findOne({ + where: { uuid: deviceUuid }, + relations: ['spaceDevice'], + }); + + await this.executeProcedure( + 'fact_daily_space_aqi', + 'proceduce_update_daily_space_aqi', + [dateStr, device.spaceDevice?.uuid], + ); + } catch (err) { + console.error('Failed to insert or update aqi data:', err); + throw err; + } + } + + private async executeProcedure( + procedureFolderName: string, + procedureFileName: string, + params: (string | number | null)[], + ): Promise { + const query = this.loadQuery(procedureFolderName, procedureFileName); + await this.dataSource.query(query, params); + console.log(`Procedure ${procedureFileName} executed successfully.`); + } + + private loadQuery(folderName: string, fileName: string): string { + return this.sqlLoader.loadQuery(folderName, fileName, SQL_PROCEDURES_PATH); + } +} diff --git a/libs/common/src/modules/aqi/repositories/aqi.repository.ts b/libs/common/src/modules/aqi/repositories/aqi.repository.ts new file mode 100644 index 0000000..4f02490 --- /dev/null +++ b/libs/common/src/modules/aqi/repositories/aqi.repository.ts @@ -0,0 +1,10 @@ +import { DataSource, Repository } from 'typeorm'; +import { Injectable } from '@nestjs/common'; +import { AqiSpaceDailyPollutantStatsEntity } from '../entities'; + +@Injectable() +export class AqiSpaceDailyPollutantStatsRepository extends Repository { + constructor(private dataSource: DataSource) { + super(AqiSpaceDailyPollutantStatsEntity, dataSource.createEntityManager()); + } +} diff --git a/libs/common/src/modules/aqi/repositories/index.ts b/libs/common/src/modules/aqi/repositories/index.ts index 8b64ee8..d1c0488 100644 --- a/libs/common/src/modules/aqi/repositories/index.ts +++ b/libs/common/src/modules/aqi/repositories/index.ts @@ -1 +1 @@ -export * from './presence-sensor.repository'; +export * from './aqi.repository'; diff --git a/libs/common/src/modules/aqi/repositories/presence-sensor.repository.ts b/libs/common/src/modules/aqi/repositories/presence-sensor.repository.ts deleted file mode 100644 index 146eb59..0000000 --- a/libs/common/src/modules/aqi/repositories/presence-sensor.repository.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { DataSource, Repository } from 'typeorm'; -import { Injectable } from '@nestjs/common'; -import { - PresenceSensorDailyDeviceEntity, - PresenceSensorDailySpaceEntity, -} from '../entities'; - -@Injectable() -export class PresenceSensorDailyDeviceRepository extends Repository { - constructor(private dataSource: DataSource) { - super(PresenceSensorDailyDeviceEntity, dataSource.createEntityManager()); - } -} -@Injectable() -export class PresenceSensorDailySpaceRepository extends Repository { - constructor(private dataSource: DataSource) { - super(PresenceSensorDailySpaceEntity, dataSource.createEntityManager()); - } -} diff --git a/src/app.module.ts b/src/app.module.ts index bde273d..8d4b6e0 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -39,6 +39,7 @@ import { HealthModule } from './health/health.module'; import { winstonLoggerOptions } from '../libs/common/src/logger/services/winston.logger'; import { OccupancyModule } from './occupancy/occupancy.module'; import { WeatherModule } from './weather/weather.module'; +import { AqiModule } from './aqi/aqi.module'; @Module({ imports: [ ConfigModule.forRoot({ @@ -81,6 +82,7 @@ import { WeatherModule } from './weather/weather.module'; HealthModule, OccupancyModule, WeatherModule, + AqiModule, ], providers: [ { diff --git a/src/aqi/aqi.module.ts b/src/aqi/aqi.module.ts new file mode 100644 index 0000000..fdf3a5f --- /dev/null +++ b/src/aqi/aqi.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { ConfigModule } from '@nestjs/config'; +import { SqlLoaderService } from '@app/common/helper/services/sql-loader.service'; +import { AqiService } from './services'; +import { AqiController } from './controllers'; +@Module({ + imports: [ConfigModule], + controllers: [AqiController], + providers: [AqiService, SqlLoaderService], +}) +export class AqiModule {} diff --git a/src/aqi/controllers/aqi.controller.ts b/src/aqi/controllers/aqi.controller.ts new file mode 100644 index 0000000..32d1d6c --- /dev/null +++ b/src/aqi/controllers/aqi.controller.ts @@ -0,0 +1,64 @@ +import { Controller, Get, Param, Query, UseGuards } from '@nestjs/common'; +import { + ApiTags, + ApiBearerAuth, + ApiOperation, + ApiParam, +} from '@nestjs/swagger'; +import { EnableDisableStatusEnum } from '@app/common/constants/days.enum'; +import { ControllerRoute } from '@app/common/constants/controller-route'; +import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard'; +import { AqiService } from '../services/aqi.service'; +import { + GetAqiDailyBySpaceDto, + GetAqiPollutantBySpaceDto, +} from '../dto/get-aqi.dto'; +import { BaseResponseDto } from '@app/common/dto/base.response.dto'; +import { SpaceParamsDto } from '../dto/aqi-params.dto'; + +@ApiTags('AQI Module') +@Controller({ + version: EnableDisableStatusEnum.ENABLED, + path: ControllerRoute.AQI.ROUTE, +}) +export class AqiController { + constructor(private readonly aqiService: AqiService) {} + + @ApiBearerAuth() + @UseGuards(JwtAuthGuard) + @Get('range/space/:spaceUuid') + @ApiOperation({ + summary: ControllerRoute.AQI.ACTIONS.GET_AQI_RANGE_DATA_SUMMARY, + description: ControllerRoute.AQI.ACTIONS.GET_AQI_RANGE_DATA_DESCRIPTION, + }) + @ApiParam({ + name: 'spaceUuid', + description: 'UUID of the Space', + required: true, + }) + async getAQIRangeDataBySpace( + @Param() params: SpaceParamsDto, + @Query() query: GetAqiDailyBySpaceDto, + ): Promise { + return await this.aqiService.getAQIRangeDataBySpace(params, query); + } + @ApiBearerAuth() + @UseGuards(JwtAuthGuard) + @Get('distribution/space/:spaceUuid') + @ApiOperation({ + summary: ControllerRoute.AQI.ACTIONS.GET_AQI_DISTRIBUTION_DATA_SUMMARY, + description: + ControllerRoute.AQI.ACTIONS.GET_AQI_DISTRIBUTION_DATA_DESCRIPTION, + }) + @ApiParam({ + name: 'spaceUuid', + description: 'UUID of the Space', + required: true, + }) + async getAQIDistributionDataBySpace( + @Param() params: SpaceParamsDto, + @Query() query: GetAqiPollutantBySpaceDto, + ): Promise { + return await this.aqiService.getAQIDistributionDataBySpace(params, query); + } +} diff --git a/src/aqi/controllers/index.ts b/src/aqi/controllers/index.ts new file mode 100644 index 0000000..ffd182e --- /dev/null +++ b/src/aqi/controllers/index.ts @@ -0,0 +1 @@ +export * from './aqi.controller'; diff --git a/src/aqi/dto/aqi-params.dto.ts b/src/aqi/dto/aqi-params.dto.ts new file mode 100644 index 0000000..6e26d4f --- /dev/null +++ b/src/aqi/dto/aqi-params.dto.ts @@ -0,0 +1,7 @@ +import { IsNotEmpty, IsUUID } from 'class-validator'; + +export class SpaceParamsDto { + @IsUUID('4', { message: 'Invalid UUID format' }) + @IsNotEmpty() + spaceUuid: string; +} diff --git a/src/aqi/dto/get-aqi.dto.ts b/src/aqi/dto/get-aqi.dto.ts new file mode 100644 index 0000000..53d49ec --- /dev/null +++ b/src/aqi/dto/get-aqi.dto.ts @@ -0,0 +1,36 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { Matches, IsNotEmpty, IsString } from 'class-validator'; + +export class GetAqiDailyBySpaceDto { + @ApiProperty({ + description: 'Month and year in format YYYY-MM', + example: '2025-03', + required: true, + }) + @Matches(/^\d{4}-(0[1-9]|1[0-2])$/, { + message: 'monthDate must be in YYYY-MM format', + }) + @IsNotEmpty() + monthDate: string; +} +export class GetAqiPollutantBySpaceDto { + @ApiProperty({ + description: 'Pollutant Type', + enum: ['aqi', 'pm25', 'pm10', 'voc', 'co2', 'ch2o'], + example: 'aqi', + required: true, + }) + @IsString() + @IsNotEmpty() + public pollutantType: string; + @ApiProperty({ + description: 'Month and year in format YYYY-MM', + example: '2025-03', + required: true, + }) + @Matches(/^\d{4}-(0[1-9]|1[0-2])$/, { + message: 'monthDate must be in YYYY-MM format', + }) + @IsNotEmpty() + monthDate: string; +} diff --git a/src/aqi/services/aqi.service.ts b/src/aqi/services/aqi.service.ts new file mode 100644 index 0000000..a8435ed --- /dev/null +++ b/src/aqi/services/aqi.service.ts @@ -0,0 +1,146 @@ +import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; +import { + GetAqiDailyBySpaceDto, + GetAqiPollutantBySpaceDto, +} from '../dto/get-aqi.dto'; +import { SuccessResponseDto } from '@app/common/dto/success.response.dto'; +import { SpaceParamsDto } from '../dto/aqi-params.dto'; +import { SqlLoaderService } from '@app/common/helper/services/sql-loader.service'; +import { DataSource } from 'typeorm'; +import { SQL_PROCEDURES_PATH } from '@app/common/constants/sql-query-path'; +import { BaseResponseDto } from '@app/common/dto/base.response.dto'; +import { convertKeysToCamelCase } from '@app/common/helper/camelCaseConverter'; + +@Injectable() +export class AqiService { + constructor( + private readonly sqlLoader: SqlLoaderService, + private readonly dataSource: DataSource, + ) {} + async getAQIDistributionDataBySpace( + params: SpaceParamsDto, + query: GetAqiPollutantBySpaceDto, + ): Promise { + const { monthDate, pollutantType } = query; + const { spaceUuid } = params; + + // Validate pollutantType against the allowed values + const allowedPollutants = ['aqi', 'pm25', 'pm10', 'voc', 'co2', 'ch2o']; + if (!allowedPollutants.includes(pollutantType.toLowerCase())) { + throw new HttpException( + `Invalid pollutant type. Allowed values: ${allowedPollutants.join(', ')}`, + HttpStatus.BAD_REQUEST, + ); + } + + try { + const data = await this.executeProcedure( + 'fact_daily_space_aqi', + 'proceduce_select_daily_space_aqi', + [spaceUuid, monthDate], + ); + + const categories = [ + 'good', + 'moderate', + 'unhealthy_sensitive', + 'unhealthy', + 'very_unhealthy', + 'hazardous', + ]; + + const transformedData = data.map((item) => { + const date = new Date(item.event_date).toLocaleDateString('en-CA'); // YYYY-MM-DD + + const categoryData = categories.map((category) => { + const key = `${category}_${pollutantType.toLowerCase()}_percentage`; + return { + type: category, + percentage: item[key] ?? 0, + }; + }); + + return { date, data: categoryData }; + }); + + const response = this.buildResponse( + `AQI distribution data fetched successfully for ${spaceUuid} space and pollutant ${pollutantType}`, + transformedData, + ); + return response; + } catch (error) { + console.error('Failed to fetch AQI distribution data', { + error, + spaceUuid, + }); + throw new HttpException( + error.response?.message || 'Failed to fetch AQI distribution data', + error.status || HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + + async getAQIRangeDataBySpace( + params: SpaceParamsDto, + query: GetAqiDailyBySpaceDto, + ): Promise { + const { monthDate } = query; + const { spaceUuid } = params; + + try { + const data = await this.executeProcedure( + 'fact_daily_space_aqi', + 'proceduce_select_daily_space_aqi', + [spaceUuid, monthDate], + ); + + // Define pollutants dynamically + const pollutants = ['aqi', 'pm25', 'pm10', 'voc', 'co2', 'ch2o']; + + const transformedData = data.map((item) => { + const date = new Date(item.event_date).toLocaleDateString('en-CA'); // YYYY-MM-DD + const dailyData = pollutants.map((type) => ({ + type, + min: item[`daily_min_${type}`], + max: item[`daily_max_${type}`], + average: item[`daily_avg_${type}`], + })); + return { date, data: dailyData }; + }); + + const response = this.buildResponse( + `AQI data fetched successfully for ${spaceUuid} space`, + transformedData, + ); + return convertKeysToCamelCase(response); + } catch (error) { + console.error('Failed to fetch AQI data', { + error, + spaceUuid, + }); + throw new HttpException( + error.response?.message || 'Failed to fetch AQI data', + error.status || HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + + private buildResponse(message: string, data: any[]) { + return new SuccessResponseDto({ + message, + data, + statusCode: HttpStatus.OK, + }); + } + private async executeProcedure( + procedureFolderName: string, + procedureFileName: string, + params: (string | number | null)[], + ): Promise { + const query = this.loadQuery(procedureFolderName, procedureFileName); + return await this.dataSource.query(query, params); + } + private loadQuery(folderName: string, fileName: string): string { + return this.sqlLoader.loadQuery(folderName, fileName, SQL_PROCEDURES_PATH); + } +} diff --git a/src/aqi/services/index.ts b/src/aqi/services/index.ts new file mode 100644 index 0000000..f0ba82c --- /dev/null +++ b/src/aqi/services/index.ts @@ -0,0 +1 @@ +export * from './aqi.service'; diff --git a/src/commission-device/commission-device.module.ts b/src/commission-device/commission-device.module.ts index 8821410..3306705 100644 --- a/src/commission-device/commission-device.module.ts +++ b/src/commission-device/commission-device.module.ts @@ -29,6 +29,7 @@ import { import { PowerClampService } from '@app/common/helper/services/power.clamp.service'; import { SqlLoaderService } from '@app/common/helper/services/sql-loader.service'; import { OccupancyService } from '@app/common/helper/services/occupancy.service'; +import { AqiDataService } from '@app/common/helper/services/aqi.data.service'; @Module({ imports: [ConfigModule, SpaceRepositoryModule], @@ -57,6 +58,7 @@ import { OccupancyService } from '@app/common/helper/services/occupancy.service' PowerClampMonthlyRepository, SqlLoaderService, OccupancyService, + AqiDataService, ], exports: [], }) diff --git a/src/community/community.module.ts b/src/community/community.module.ts index a6f64df..edaddbb 100644 --- a/src/community/community.module.ts +++ b/src/community/community.module.ts @@ -64,6 +64,7 @@ import { } from '@app/common/modules/power-clamp/repositories'; import { SqlLoaderService } from '@app/common/helper/services/sql-loader.service'; import { OccupancyService } from '@app/common/helper/services/occupancy.service'; +import { AqiDataService } from '@app/common/helper/services/aqi.data.service'; @Module({ imports: [ConfigModule, SpaceRepositoryModule, UserRepositoryModule], @@ -116,6 +117,7 @@ import { OccupancyService } from '@app/common/helper/services/occupancy.service' PowerClampMonthlyRepository, SqlLoaderService, OccupancyService, + AqiDataService, ], exports: [CommunityService, SpacePermissionService], }) diff --git a/src/door-lock/door.lock.module.ts b/src/door-lock/door.lock.module.ts index 3f2cee7..c2eaad1 100644 --- a/src/door-lock/door.lock.module.ts +++ b/src/door-lock/door.lock.module.ts @@ -29,6 +29,7 @@ import { import { SqlLoaderService } from '@app/common/helper/services/sql-loader.service'; import { OccupancyService } from '@app/common/helper/services/occupancy.service'; import { CommunityRepository } from '@app/common/modules/community/repositories'; +import { AqiDataService } from '@app/common/helper/services/aqi.data.service'; @Module({ imports: [ConfigModule, DeviceRepositoryModule], controllers: [DoorLockController], @@ -56,6 +57,7 @@ import { CommunityRepository } from '@app/common/modules/community/repositories' SqlLoaderService, OccupancyService, CommunityRepository, + AqiDataService, ], exports: [DoorLockService], }) diff --git a/src/group/group.module.ts b/src/group/group.module.ts index b50bac9..443ac31 100644 --- a/src/group/group.module.ts +++ b/src/group/group.module.ts @@ -27,6 +27,7 @@ import { import { SqlLoaderService } from '@app/common/helper/services/sql-loader.service'; import { OccupancyService } from '@app/common/helper/services/occupancy.service'; import { CommunityRepository } from '@app/common/modules/community/repositories'; +import { AqiDataService } from '@app/common/helper/services/aqi.data.service'; @Module({ imports: [ConfigModule, DeviceRepositoryModule], controllers: [GroupController], @@ -53,6 +54,7 @@ import { CommunityRepository } from '@app/common/modules/community/repositories' SqlLoaderService, OccupancyService, CommunityRepository, + AqiDataService, ], exports: [GroupService], }) diff --git a/src/invite-user/invite-user.module.ts b/src/invite-user/invite-user.module.ts index fb1ba8d..a42922c 100644 --- a/src/invite-user/invite-user.module.ts +++ b/src/invite-user/invite-user.module.ts @@ -84,6 +84,7 @@ import { import { PowerClampService } from '@app/common/helper/services/power.clamp.service'; import { SqlLoaderService } from '@app/common/helper/services/sql-loader.service'; import { OccupancyService } from '@app/common/helper/services/occupancy.service'; +import { AqiDataService } from '@app/common/helper/services/aqi.data.service'; @Module({ imports: [ConfigModule, InviteUserRepositoryModule, CommunityModule], @@ -154,6 +155,7 @@ import { OccupancyService } from '@app/common/helper/services/occupancy.service' PowerClampMonthlyRepository, SqlLoaderService, OccupancyService, + AqiDataService, ], exports: [InviteUserService], }) diff --git a/src/power-clamp/power-clamp.module.ts b/src/power-clamp/power-clamp.module.ts index e85ea1b..9910dd9 100644 --- a/src/power-clamp/power-clamp.module.ts +++ b/src/power-clamp/power-clamp.module.ts @@ -61,6 +61,7 @@ import { NewTagRepository } from '@app/common/modules/tag/repositories/tag-repos import { SpaceModelProductAllocationService } from 'src/space-model/services/space-model-product-allocation.service'; import { SubspaceModelProductAllocationService } from 'src/space-model/services/subspace/subspace-model-product-allocation.service'; import { OccupancyService } from '@app/common/helper/services/occupancy.service'; +import { AqiDataService } from '@app/common/helper/services/aqi.data.service'; @Module({ imports: [ConfigModule], controllers: [PowerClampController], @@ -111,6 +112,7 @@ import { OccupancyService } from '@app/common/helper/services/occupancy.service' SpaceModelProductAllocationRepoitory, SubspaceModelProductAllocationRepoitory, OccupancyService, + AqiDataService, ], exports: [PowerClamp], }) diff --git a/src/project/project.module.ts b/src/project/project.module.ts index fd9acb3..306a6c2 100644 --- a/src/project/project.module.ts +++ b/src/project/project.module.ts @@ -68,6 +68,7 @@ import { } from '@app/common/modules/power-clamp/repositories'; import { SqlLoaderService } from '@app/common/helper/services/sql-loader.service'; import { OccupancyService } from '@app/common/helper/services/occupancy.service'; +import { AqiDataService } from '@app/common/helper/services/aqi.data.service'; const CommandHandlers = [CreateOrphanSpaceHandler]; @@ -126,6 +127,7 @@ const CommandHandlers = [CreateOrphanSpaceHandler]; PowerClampMonthlyRepository, SqlLoaderService, OccupancyService, + AqiDataService, ], exports: [ProjectService, CqrsModule], }) diff --git a/src/space-model/space-model.module.ts b/src/space-model/space-model.module.ts index be57bb3..cdb713c 100644 --- a/src/space-model/space-model.module.ts +++ b/src/space-model/space-model.module.ts @@ -66,6 +66,7 @@ import { } from '@app/common/modules/power-clamp/repositories'; import { SqlLoaderService } from '@app/common/helper/services/sql-loader.service'; import { OccupancyService } from '@app/common/helper/services/occupancy.service'; +import { AqiDataService } from '@app/common/helper/services/aqi.data.service'; const CommandHandlers = [ PropogateUpdateSpaceModelHandler, @@ -126,6 +127,7 @@ const CommandHandlers = [ PowerClampMonthlyRepository, SqlLoaderService, OccupancyService, + AqiDataService, ], exports: [CqrsModule, SpaceModelService], }) diff --git a/src/space/space.module.ts b/src/space/space.module.ts index f74d993..0b33696 100644 --- a/src/space/space.module.ts +++ b/src/space/space.module.ts @@ -91,6 +91,7 @@ import { } from '@app/common/modules/power-clamp/repositories'; import { SqlLoaderService } from '@app/common/helper/services/sql-loader.service'; import { OccupancyService } from '@app/common/helper/services/occupancy.service'; +import { AqiDataService } from '@app/common/helper/services/aqi.data.service'; export const CommandHandlers = [DisableSpaceHandler]; @@ -168,6 +169,7 @@ export const CommandHandlers = [DisableSpaceHandler]; PowerClampService, SqlLoaderService, OccupancyService, + AqiDataService, ], exports: [SpaceService], }) diff --git a/src/vistor-password/visitor-password.module.ts b/src/vistor-password/visitor-password.module.ts index 6924713..c66ba39 100644 --- a/src/vistor-password/visitor-password.module.ts +++ b/src/vistor-password/visitor-password.module.ts @@ -31,6 +31,7 @@ import { import { SqlLoaderService } from '@app/common/helper/services/sql-loader.service'; import { OccupancyService } from '@app/common/helper/services/occupancy.service'; import { CommunityRepository } from '@app/common/modules/community/repositories'; +import { AqiDataService } from '@app/common/helper/services/aqi.data.service'; @Module({ imports: [ConfigModule, DeviceRepositoryModule, DoorLockModule], controllers: [VisitorPasswordController], @@ -59,6 +60,7 @@ import { CommunityRepository } from '@app/common/modules/community/repositories' SqlLoaderService, OccupancyService, CommunityRepository, + AqiDataService, ], exports: [VisitorPasswordService], })