From f2ed04f20671ae18175d073cb1a13b1b4a5e07da Mon Sep 17 00:00:00 2001 From: faris Aljohari <83524184+farisaljohari@users.noreply.github.com> Date: Thu, 12 Jun 2025 02:49:59 -0600 Subject: [PATCH] feat: add SpaceDailyOccupancyDuration entity, DTO, and repository for occupancy tracking --- libs/common/src/database/database.module.ts | 2 ++ .../src/modules/occupancy/dtos/index.ts | 1 + .../modules/occupancy/dtos/occupancy.dto.ts | 23 +++++++++++++ .../src/modules/occupancy/entities/index.ts | 1 + .../occupancy/entities/occupancy.entity.ts | 32 +++++++++++++++++++ .../occupancy/occupancy.repository.module.ts | 11 +++++++ .../modules/occupancy/repositories/index.ts | 1 + .../repositories/occupancy.repository.ts | 10 ++++++ .../modules/space/entities/space.entity.ts | 7 ++++ 9 files changed, 88 insertions(+) create mode 100644 libs/common/src/modules/occupancy/dtos/index.ts create mode 100644 libs/common/src/modules/occupancy/dtos/occupancy.dto.ts create mode 100644 libs/common/src/modules/occupancy/entities/index.ts create mode 100644 libs/common/src/modules/occupancy/entities/occupancy.entity.ts create mode 100644 libs/common/src/modules/occupancy/occupancy.repository.module.ts create mode 100644 libs/common/src/modules/occupancy/repositories/index.ts create mode 100644 libs/common/src/modules/occupancy/repositories/occupancy.repository.ts diff --git a/libs/common/src/database/database.module.ts b/libs/common/src/database/database.module.ts index 2187c72..2196901 100644 --- a/libs/common/src/database/database.module.ts +++ b/libs/common/src/database/database.module.ts @@ -58,6 +58,7 @@ import { UserSpaceEntity, } from '../modules/user/entities'; import { VisitorPasswordEntity } from '../modules/visitor-password/entities'; +import { SpaceDailyOccupancyDurationEntity } from '../modules/occupancy/entities'; @Module({ imports: [ TypeOrmModule.forRootAsync({ @@ -117,6 +118,7 @@ import { VisitorPasswordEntity } from '../modules/visitor-password/entities'; PresenceSensorDailyDeviceEntity, PresenceSensorDailySpaceEntity, AqiSpaceDailyPollutantStatsEntity, + SpaceDailyOccupancyDurationEntity, ], namingStrategy: new SnakeNamingStrategy(), synchronize: Boolean(JSON.parse(configService.get('DB_SYNC'))), diff --git a/libs/common/src/modules/occupancy/dtos/index.ts b/libs/common/src/modules/occupancy/dtos/index.ts new file mode 100644 index 0000000..956af8a --- /dev/null +++ b/libs/common/src/modules/occupancy/dtos/index.ts @@ -0,0 +1 @@ +export * from './occupancy.dto'; diff --git a/libs/common/src/modules/occupancy/dtos/occupancy.dto.ts b/libs/common/src/modules/occupancy/dtos/occupancy.dto.ts new file mode 100644 index 0000000..bb455c9 --- /dev/null +++ b/libs/common/src/modules/occupancy/dtos/occupancy.dto.ts @@ -0,0 +1,23 @@ +import { IsNotEmpty, IsNumber, IsString } from 'class-validator'; + +export class SpaceDailyOccupancyDurationDto { + @IsString() + @IsNotEmpty() + public uuid: string; + + @IsString() + @IsNotEmpty() + public spaceUuid: string; + + @IsString() + @IsNotEmpty() + public eventDate: string; + + @IsNumber() + @IsNotEmpty() + public occupancyPercentage: number; + + @IsNumber() + @IsNotEmpty() + public occupiedSeconds: number; +} diff --git a/libs/common/src/modules/occupancy/entities/index.ts b/libs/common/src/modules/occupancy/entities/index.ts new file mode 100644 index 0000000..d272e17 --- /dev/null +++ b/libs/common/src/modules/occupancy/entities/index.ts @@ -0,0 +1 @@ +export * from './occupancy.entity'; diff --git a/libs/common/src/modules/occupancy/entities/occupancy.entity.ts b/libs/common/src/modules/occupancy/entities/occupancy.entity.ts new file mode 100644 index 0000000..7d77ffc --- /dev/null +++ b/libs/common/src/modules/occupancy/entities/occupancy.entity.ts @@ -0,0 +1,32 @@ +import { Column, Entity, ManyToOne, Unique } from 'typeorm'; +import { AbstractEntity } from '../../abstract/entities/abstract.entity'; +import { SpaceEntity } from '../../space/entities/space.entity'; +import { SpaceDailyOccupancyDurationDto } from '../dtos'; + +@Entity({ name: 'space-daily-occupancy-duration' }) +@Unique(['spaceUuid', 'eventDate']) +export class SpaceDailyOccupancyDurationEntity extends AbstractEntity { + @Column({ nullable: false }) + public spaceUuid: string; + + @Column({ nullable: false, type: 'date' }) + public eventDate: string; + + public CountTotalPresenceDetected: number; + + @ManyToOne(() => SpaceEntity, (space) => space.presenceSensorDaily) + space: SpaceEntity; + + @Column({ type: 'int' }) + occupancyPercentage: number; + + @Column({ type: 'int', nullable: true }) + occupiedSeconds?: number; + + @Column({ type: 'int', nullable: true }) + deviceCount?: number; + constructor(partial: Partial) { + super(); + Object.assign(this, partial); + } +} diff --git a/libs/common/src/modules/occupancy/occupancy.repository.module.ts b/libs/common/src/modules/occupancy/occupancy.repository.module.ts new file mode 100644 index 0000000..027cb9f --- /dev/null +++ b/libs/common/src/modules/occupancy/occupancy.repository.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { SpaceDailyOccupancyDurationEntity } from './entities/occupancy.entity'; + +@Module({ + providers: [], + exports: [], + controllers: [], + imports: [TypeOrmModule.forFeature([SpaceDailyOccupancyDurationEntity])], +}) +export class SpaceDailyOccupancyDurationRepositoryModule {} diff --git a/libs/common/src/modules/occupancy/repositories/index.ts b/libs/common/src/modules/occupancy/repositories/index.ts new file mode 100644 index 0000000..85821db --- /dev/null +++ b/libs/common/src/modules/occupancy/repositories/index.ts @@ -0,0 +1 @@ +export * from './occupancy.repository'; diff --git a/libs/common/src/modules/occupancy/repositories/occupancy.repository.ts b/libs/common/src/modules/occupancy/repositories/occupancy.repository.ts new file mode 100644 index 0000000..45a1b17 --- /dev/null +++ b/libs/common/src/modules/occupancy/repositories/occupancy.repository.ts @@ -0,0 +1,10 @@ +import { DataSource, Repository } from 'typeorm'; +import { Injectable } from '@nestjs/common'; +import { SpaceDailyOccupancyDurationEntity } from '../entities/occupancy.entity'; + +@Injectable() +export class SpaceDailyOccupancyDurationEntityRepository extends Repository { + constructor(private dataSource: DataSource) { + super(SpaceDailyOccupancyDurationEntity, dataSource.createEntityManager()); + } +} diff --git a/libs/common/src/modules/space/entities/space.entity.ts b/libs/common/src/modules/space/entities/space.entity.ts index e5e3b12..56b5d4f 100644 --- a/libs/common/src/modules/space/entities/space.entity.ts +++ b/libs/common/src/modules/space/entities/space.entity.ts @@ -12,6 +12,7 @@ import { SpaceProductAllocationEntity } from './space-product-allocation.entity' import { SubspaceEntity } from './subspace/subspace.entity'; import { PresenceSensorDailySpaceEntity } from '../../presence-sensor/entities'; import { AqiSpaceDailyPollutantStatsEntity } from '../../aqi/entities'; +import { SpaceDailyOccupancyDurationEntity } from '../../occupancy/entities'; @Entity({ name: 'space' }) export class SpaceEntity extends AbstractEntity { @@ -119,6 +120,12 @@ export class SpaceEntity extends AbstractEntity { @OneToMany(() => AqiSpaceDailyPollutantStatsEntity, (aqi) => aqi.space) aqiSensorDaily: AqiSpaceDailyPollutantStatsEntity[]; + @OneToMany( + () => SpaceDailyOccupancyDurationEntity, + (occupancy) => occupancy.space, + ) + occupancyDaily: SpaceDailyOccupancyDurationEntity[]; + constructor(partial: Partial) { super(); Object.assign(this, partial);