mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-10 15:17:41 +00:00
feat: add occupancy duration data retrieval and update procedures
This commit is contained in:
@ -257,6 +257,9 @@ export class DeviceStatusFirebaseService {
|
|||||||
await this.occupancyService.updateOccupancySensorHistoricalData(
|
await this.occupancyService.updateOccupancySensorHistoricalData(
|
||||||
addDeviceStatusDto.deviceUuid,
|
addDeviceStatusDto.deviceUuid,
|
||||||
);
|
);
|
||||||
|
await this.occupancyService.updateOccupancySensorHistoricalDurationData(
|
||||||
|
addDeviceStatusDto.deviceUuid,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,27 @@ export class OccupancyService {
|
|||||||
private readonly dataSource: DataSource,
|
private readonly dataSource: DataSource,
|
||||||
private readonly deviceRepository: DeviceRepository,
|
private readonly deviceRepository: DeviceRepository,
|
||||||
) {}
|
) {}
|
||||||
|
async updateOccupancySensorHistoricalDurationData(
|
||||||
|
deviceUuid: string,
|
||||||
|
): Promise<void> {
|
||||||
|
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_occupancy_duration',
|
||||||
|
'procedure_update_daily_space_occupancy_duration',
|
||||||
|
[dateStr, device.spaceDevice?.uuid],
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to insert or update occupancy duration data:', err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
async updateOccupancySensorHistoricalData(deviceUuid: string): Promise<void> {
|
async updateOccupancySensorHistoricalData(deviceUuid: string): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
@ -21,10 +41,11 @@ export class OccupancyService {
|
|||||||
relations: ['spaceDevice'],
|
relations: ['spaceDevice'],
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.executeProcedure('procedure_update_fact_space_occupancy', [
|
await this.executeProcedure(
|
||||||
dateStr,
|
'fact_space_occupancy_count',
|
||||||
device.spaceDevice?.uuid,
|
'procedure_update_fact_space_occupancy',
|
||||||
]);
|
[dateStr, device.spaceDevice?.uuid],
|
||||||
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to insert or update occupancy data:', err);
|
console.error('Failed to insert or update occupancy data:', err);
|
||||||
throw err;
|
throw err;
|
||||||
@ -32,13 +53,11 @@ export class OccupancyService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async executeProcedure(
|
private async executeProcedure(
|
||||||
|
procedureFolderName: string,
|
||||||
procedureFileName: string,
|
procedureFileName: string,
|
||||||
params: (string | number | null)[],
|
params: (string | number | null)[],
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const query = this.loadQuery(
|
const query = this.loadQuery(procedureFolderName, procedureFileName);
|
||||||
'fact_space_occupancy_count',
|
|
||||||
procedureFileName,
|
|
||||||
);
|
|
||||||
await this.dataSource.query(query, params);
|
await this.dataSource.query(query, params);
|
||||||
console.log(`Procedure ${procedureFileName} executed successfully.`);
|
console.log(`Procedure ${procedureFileName} executed successfully.`);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,10 @@ import { EnableDisableStatusEnum } from '@app/common/constants/days.enum';
|
|||||||
import { ControllerRoute } from '@app/common/constants/controller-route';
|
import { ControllerRoute } from '@app/common/constants/controller-route';
|
||||||
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
||||||
import { OccupancyService } from '../services/occupancy.service';
|
import { OccupancyService } from '../services/occupancy.service';
|
||||||
import { GetOccupancyHeatMapBySpaceDto } from '../dto/get-occupancy.dto';
|
import {
|
||||||
|
GetOccupancyDurationBySpaceDto,
|
||||||
|
GetOccupancyHeatMapBySpaceDto,
|
||||||
|
} from '../dto/get-occupancy.dto';
|
||||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||||
import { SpaceParamsDto } from '../dto/occupancy-params.dto';
|
import { SpaceParamsDto } from '../dto/occupancy-params.dto';
|
||||||
|
|
||||||
@ -43,4 +46,26 @@ export class OccupancyController {
|
|||||||
query,
|
query,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ApiBearerAuth()
|
||||||
|
@UseGuards(JwtAuthGuard)
|
||||||
|
@Get('duration/space/:spaceUuid')
|
||||||
|
@ApiOperation({
|
||||||
|
summary: ControllerRoute.Occupancy.ACTIONS.GET_OCCUPANCY_HEAT_MAP_SUMMARY,
|
||||||
|
description:
|
||||||
|
ControllerRoute.Occupancy.ACTIONS.GET_OCCUPANCY_HEAT_MAP_DESCRIPTION,
|
||||||
|
})
|
||||||
|
@ApiParam({
|
||||||
|
name: 'spaceUuid',
|
||||||
|
description: 'UUID of the Space',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
async getOccupancyDurationDataBySpace(
|
||||||
|
@Param() params: SpaceParamsDto,
|
||||||
|
@Query() query: GetOccupancyDurationBySpaceDto,
|
||||||
|
): Promise<BaseResponseDto> {
|
||||||
|
return await this.occupancyService.getOccupancyDurationDataBySpace(
|
||||||
|
params,
|
||||||
|
query,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,3 +13,15 @@ export class GetOccupancyHeatMapBySpaceDto {
|
|||||||
})
|
})
|
||||||
year: string;
|
year: string;
|
||||||
}
|
}
|
||||||
|
export class GetOccupancyDurationBySpaceDto {
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||||
import { GetOccupancyHeatMapBySpaceDto } from '../dto/get-occupancy.dto';
|
import {
|
||||||
|
GetOccupancyDurationBySpaceDto,
|
||||||
|
GetOccupancyHeatMapBySpaceDto,
|
||||||
|
} from '../dto/get-occupancy.dto';
|
||||||
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
||||||
import { SpaceParamsDto } from '../dto/occupancy-params.dto';
|
import { SpaceParamsDto } from '../dto/occupancy-params.dto';
|
||||||
import { SqlLoaderService } from '@app/common/helper/services/sql-loader.service';
|
import { SqlLoaderService } from '@app/common/helper/services/sql-loader.service';
|
||||||
@ -14,6 +17,38 @@ export class OccupancyService {
|
|||||||
private readonly dataSource: DataSource,
|
private readonly dataSource: DataSource,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
async getOccupancyDurationDataBySpace(
|
||||||
|
params: SpaceParamsDto,
|
||||||
|
query: GetOccupancyDurationBySpaceDto,
|
||||||
|
): Promise<BaseResponseDto> {
|
||||||
|
const { monthDate } = query;
|
||||||
|
const { spaceUuid } = params;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = await this.executeProcedure(
|
||||||
|
'fact_daily_space_occupancy_duration',
|
||||||
|
'procedure_select_daily_space_occupancy_duration',
|
||||||
|
[spaceUuid, monthDate],
|
||||||
|
);
|
||||||
|
const formattedData = data.map((item) => ({
|
||||||
|
...item,
|
||||||
|
event_date: new Date(item.event_date).toLocaleDateString('en-CA'), // YYYY-MM-DD
|
||||||
|
}));
|
||||||
|
return this.buildResponse(
|
||||||
|
`Occupancy duration data fetched successfully for ${spaceUuid} space`,
|
||||||
|
formattedData,
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch occupancy duration data', {
|
||||||
|
error,
|
||||||
|
spaceUuid,
|
||||||
|
});
|
||||||
|
throw new HttpException(
|
||||||
|
error.response?.message || 'Failed to fetch occupancy duration data',
|
||||||
|
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
async getOccupancyHeatMapDataBySpace(
|
async getOccupancyHeatMapDataBySpace(
|
||||||
params: SpaceParamsDto,
|
params: SpaceParamsDto,
|
||||||
query: GetOccupancyHeatMapBySpaceDto,
|
query: GetOccupancyHeatMapBySpaceDto,
|
||||||
@ -23,6 +58,7 @@ export class OccupancyService {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await this.executeProcedure(
|
const data = await this.executeProcedure(
|
||||||
|
'fact_space_occupancy_count',
|
||||||
'proceduce_select_fact_space_occupancy',
|
'proceduce_select_fact_space_occupancy',
|
||||||
[spaceUuid, year],
|
[spaceUuid, year],
|
||||||
);
|
);
|
||||||
@ -31,7 +67,7 @@ export class OccupancyService {
|
|||||||
event_date: new Date(item.event_date).toLocaleDateString('en-CA'), // YYYY-MM-DD
|
event_date: new Date(item.event_date).toLocaleDateString('en-CA'), // YYYY-MM-DD
|
||||||
}));
|
}));
|
||||||
return this.buildResponse(
|
return this.buildResponse(
|
||||||
`Occupancy heat map data fetched successfully for ${spaceUuid ? 'space' : 'community'}`,
|
`Occupancy heat map data fetched successfully for ${spaceUuid} space`,
|
||||||
formattedData,
|
formattedData,
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -54,13 +90,11 @@ export class OccupancyService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
private async executeProcedure(
|
private async executeProcedure(
|
||||||
|
procedureFolderName: string,
|
||||||
procedureFileName: string,
|
procedureFileName: string,
|
||||||
params: (string | number | null)[],
|
params: (string | number | null)[],
|
||||||
): Promise<any[]> {
|
): Promise<any[]> {
|
||||||
const query = this.loadQuery(
|
const query = this.loadQuery(procedureFolderName, procedureFileName);
|
||||||
'fact_space_occupancy_count',
|
|
||||||
procedureFileName,
|
|
||||||
);
|
|
||||||
return await this.dataSource.query(query, params);
|
return await this.dataSource.query(query, params);
|
||||||
}
|
}
|
||||||
private loadQuery(folderName: string, fileName: string): string {
|
private loadQuery(folderName: string, fileName: string): string {
|
||||||
|
Reference in New Issue
Block a user