From ef2245eae1eec5725f49b64cbfe0ce9b9a714eb0 Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Tue, 3 Jun 2025 23:37:52 -0600 Subject: [PATCH] Add AQI space daily pollutant stats module and related entities, DTOs, and repositories --- libs/common/src/database/database.module.ts | 2 + .../src/modules/aqi/aqi.repository.module.ts | 11 +++ libs/common/src/modules/aqi/dtos/aqi.dto.ts | 82 +++++++++++++++++ libs/common/src/modules/aqi/dtos/index.ts | 1 + .../src/modules/aqi/entities/aqi.entity.ts | 88 +++++++++++++++++++ libs/common/src/modules/aqi/entities/index.ts | 1 + .../src/modules/aqi/repositories/index.ts | 1 + .../presence-sensor.repository.ts | 19 ++++ 8 files changed, 205 insertions(+) create mode 100644 libs/common/src/modules/aqi/aqi.repository.module.ts create mode 100644 libs/common/src/modules/aqi/dtos/aqi.dto.ts create mode 100644 libs/common/src/modules/aqi/dtos/index.ts create mode 100644 libs/common/src/modules/aqi/entities/aqi.entity.ts create mode 100644 libs/common/src/modules/aqi/entities/index.ts create mode 100644 libs/common/src/modules/aqi/repositories/index.ts create mode 100644 libs/common/src/modules/aqi/repositories/presence-sensor.repository.ts diff --git a/libs/common/src/database/database.module.ts b/libs/common/src/database/database.module.ts index 183fbcc..d25dbd8 100644 --- a/libs/common/src/database/database.module.ts +++ b/libs/common/src/database/database.module.ts @@ -55,6 +55,7 @@ import { PresenceSensorDailyDeviceEntity, PresenceSensorDailySpaceEntity, } from '../modules/presence-sensor/entities'; +import { AqiSpaceDailyPollutantStatsEntity } from '../modules/aqi/entities'; @Module({ imports: [ TypeOrmModule.forRootAsync({ @@ -115,6 +116,7 @@ import { PowerClampMonthlyEntity, PresenceSensorDailyDeviceEntity, PresenceSensorDailySpaceEntity, + AqiSpaceDailyPollutantStatsEntity, ], namingStrategy: new SnakeNamingStrategy(), synchronize: Boolean(JSON.parse(configService.get('DB_SYNC'))), diff --git a/libs/common/src/modules/aqi/aqi.repository.module.ts b/libs/common/src/modules/aqi/aqi.repository.module.ts new file mode 100644 index 0000000..1fc820d --- /dev/null +++ b/libs/common/src/modules/aqi/aqi.repository.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { AqiSpaceDailyPollutantStatsEntity } from './entities/aqi.entity'; + +@Module({ + providers: [], + exports: [], + controllers: [], + imports: [TypeOrmModule.forFeature([AqiSpaceDailyPollutantStatsEntity])], +}) +export class AqiRepositoryModule {} diff --git a/libs/common/src/modules/aqi/dtos/aqi.dto.ts b/libs/common/src/modules/aqi/dtos/aqi.dto.ts new file mode 100644 index 0000000..1745d60 --- /dev/null +++ b/libs/common/src/modules/aqi/dtos/aqi.dto.ts @@ -0,0 +1,82 @@ +import { IsNotEmpty, IsNumber, IsString } from 'class-validator'; + +export class AqiSpaceDailyPollutantStatsDto { + @IsString() + @IsNotEmpty() + public uuid: string; + + @IsNotEmpty() + @IsString() + spaceUuid: string; + + @IsNotEmpty() + @IsString() + eventDay: string; + + @IsNotEmpty() + @IsNumber() + eventHour: number; + + @IsNumber() + pm1Min: number; + + @IsNumber() + pm1Avg: number; + + @IsNumber() + pm1Max: number; + + @IsNumber() + pm10Min: number; + + @IsNumber() + pm10Avg: number; + + @IsNumber() + pm10Max: number; + + @IsNumber() + pm25Min: number; + + @IsNumber() + pm25Avg: number; + + @IsNumber() + pm25Max: number; + + @IsNumber() + ch2oMin: number; + + @IsNumber() + ch2oAvg: number; + + @IsNumber() + ch2oMax: number; + + @IsNumber() + vocMin: number; + + @IsNumber() + vocAvg: number; + + @IsNumber() + vocMax: number; + + @IsNumber() + co2Min: number; + + @IsNumber() + co2Avg: number; + + @IsNumber() + co2Max: number; + + @IsNumber() + aqiMin: number; + + @IsNumber() + aqiAvg: number; + + @IsNumber() + aqiMax: number; +} diff --git a/libs/common/src/modules/aqi/dtos/index.ts b/libs/common/src/modules/aqi/dtos/index.ts new file mode 100644 index 0000000..da89122 --- /dev/null +++ b/libs/common/src/modules/aqi/dtos/index.ts @@ -0,0 +1 @@ +export * from './aqi.dto'; diff --git a/libs/common/src/modules/aqi/entities/aqi.entity.ts b/libs/common/src/modules/aqi/entities/aqi.entity.ts new file mode 100644 index 0000000..701bcdd --- /dev/null +++ b/libs/common/src/modules/aqi/entities/aqi.entity.ts @@ -0,0 +1,88 @@ +import { Column, Entity, ManyToOne, Unique } from 'typeorm'; +import { AbstractEntity } from '../../abstract/entities/abstract.entity'; +import { SpaceEntity } from '../../space/entities/space.entity'; +import { AqiSpaceDailyPollutantStatsDto } from '../dtos'; + +@Entity({ name: 'space-daily-pollutant-stats' }) +@Unique(['spaceUuid', 'eventDay', 'eventHour']) +export class AqiSpaceDailyPollutantStatsEntity extends AbstractEntity { + @Column({ nullable: false }) + public spaceUuid: string; + + @ManyToOne(() => SpaceEntity, (space) => space.presenceSensorDaily) + space: SpaceEntity; + + @Column({ nullable: false }) + public eventDay: string; + + @Column({ nullable: false }) + public eventHour: number; + + @Column('float', { nullable: true }) + public pm1Min: number; + + @Column('float', { nullable: true }) + public pm1Avg: number; + + @Column('float', { nullable: true }) + public pm1Max: number; + + @Column('float', { nullable: true }) + public pm10Min: number; + + @Column('float', { nullable: true }) + public pm10Avg: number; + + @Column('float', { nullable: true }) + public pm10Max: number; + + @Column('float', { nullable: true }) + public pm25Min: number; + + @Column('float', { nullable: true }) + public pm25Avg: number; + + @Column('float', { nullable: true }) + public pm25Max: number; + + @Column('float', { nullable: true }) + public ch2oMin: number; + + @Column('float', { nullable: true }) + public ch2oAvg: number; + + @Column('float', { nullable: true }) + public ch2oMax: number; + + @Column('float', { nullable: true }) + public vocMin: number; + + @Column('float', { nullable: true }) + public vocAvg: number; + + @Column('float', { nullable: true }) + public vocMax: number; + + @Column('float', { nullable: true }) + public co2Min: number; + + @Column('float', { nullable: true }) + public co2Avg: number; + + @Column('float', { nullable: true }) + public co2Max: number; + + @Column('float', { nullable: true }) + public aqiMin: number; + + @Column('float', { nullable: true }) + public aqiAvg: number; + + @Column('float', { nullable: true }) + public aqiMax: number; + + constructor(partial: Partial) { + super(); + Object.assign(this, partial); + } +} diff --git a/libs/common/src/modules/aqi/entities/index.ts b/libs/common/src/modules/aqi/entities/index.ts new file mode 100644 index 0000000..655a0e7 --- /dev/null +++ b/libs/common/src/modules/aqi/entities/index.ts @@ -0,0 +1 @@ +export * from './aqi.entity'; diff --git a/libs/common/src/modules/aqi/repositories/index.ts b/libs/common/src/modules/aqi/repositories/index.ts new file mode 100644 index 0000000..8b64ee8 --- /dev/null +++ b/libs/common/src/modules/aqi/repositories/index.ts @@ -0,0 +1 @@ +export * from './presence-sensor.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 new file mode 100644 index 0000000..146eb59 --- /dev/null +++ b/libs/common/src/modules/aqi/repositories/presence-sensor.repository.ts @@ -0,0 +1,19 @@ +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()); + } +}