mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-15 02:15:21 +00:00
Add endpoints and logic for fetching power clamp data by community or space
- Introduced new API endpoints to retrieve power clamp historical data based on community or space UUID. - Updated PowerClampController to handle requests with optional parameters for community and space. - Enhanced PowerClampService to validate input and fetch devices accordingly. - Created ResourceParamsDto to manage request parameters. - Updated ControllerRoute with new action summaries and descriptions.
This commit is contained in:
@ -498,6 +498,10 @@ export class ControllerRoute {
|
|||||||
'Get power clamp historical data';
|
'Get power clamp historical data';
|
||||||
public static readonly GET_ENERGY_DESCRIPTION =
|
public static readonly GET_ENERGY_DESCRIPTION =
|
||||||
'This endpoint retrieves the historical data of a power clamp device based on the provided parameters.';
|
'This endpoint retrieves the historical data of a power clamp device based on the provided parameters.';
|
||||||
|
public static readonly GET_ENERGY_BY_COMMUNITY_OR_SPACE_SUMMARY =
|
||||||
|
'Get power clamp historical data by community or space';
|
||||||
|
public static readonly GET_ENERGY_BY_COMMUNITY_OR_SPACE_DESCRIPTION =
|
||||||
|
'This endpoint retrieves the historical data of power clamp devices based on the provided community or space UUID.';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
static DEVICE = class {
|
static DEVICE = class {
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
|
import {
|
||||||
|
Injectable,
|
||||||
|
HttpException,
|
||||||
|
HttpStatus,
|
||||||
|
NotFoundException,
|
||||||
|
} from '@nestjs/common';
|
||||||
import { AddCommunityDto, GetCommunityParams, ProjectParam } from '../dtos';
|
import { AddCommunityDto, GetCommunityParams, ProjectParam } from '../dtos';
|
||||||
import { UpdateCommunityNameDto } from '../dtos/update.community.dto';
|
import { UpdateCommunityNameDto } from '../dtos/update.community.dto';
|
||||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||||
@ -16,6 +21,8 @@ import { ORPHAN_COMMUNITY_NAME } from '@app/common/constants/orphan-constant';
|
|||||||
import { ILike, In, Not } from 'typeorm';
|
import { ILike, In, Not } from 'typeorm';
|
||||||
import { SpaceService } from 'src/space/services';
|
import { SpaceService } from 'src/space/services';
|
||||||
import { SpaceRepository } from '@app/common/modules/space';
|
import { SpaceRepository } from '@app/common/modules/space';
|
||||||
|
import { DeviceEntity } from '@app/common/modules/device/entities';
|
||||||
|
import { SpaceEntity } from '@app/common/modules/space/entities/space.entity';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CommunityService {
|
export class CommunityService {
|
||||||
@ -303,4 +310,58 @@ export class CommunityService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
async getAllDevicesByCommunity(
|
||||||
|
communityUuid: string,
|
||||||
|
): Promise<DeviceEntity[]> {
|
||||||
|
// Fetch the community and its top-level spaces
|
||||||
|
const community = await this.communityRepository.findOne({
|
||||||
|
where: { uuid: communityUuid },
|
||||||
|
relations: [
|
||||||
|
'spaces',
|
||||||
|
'spaces.children',
|
||||||
|
'spaces.devices',
|
||||||
|
'spaces.devices.productDevice',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!community) {
|
||||||
|
throw new NotFoundException('Community not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const allDevices: DeviceEntity[] = [];
|
||||||
|
|
||||||
|
// Recursive fetch function for spaces
|
||||||
|
const fetchSpaceDevices = async (space: SpaceEntity) => {
|
||||||
|
if (space.devices && space.devices.length > 0) {
|
||||||
|
allDevices.push(...space.devices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (space.children && space.children.length > 0) {
|
||||||
|
for (const childSpace of space.children) {
|
||||||
|
const fullChildSpace = await this.spaceRepository.findOne({
|
||||||
|
where: { uuid: childSpace.uuid },
|
||||||
|
relations: ['children', 'devices', 'devices.productDevice'],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (fullChildSpace) {
|
||||||
|
await fetchSpaceDevices(fullChildSpace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Start recursive fetch for all top-level spaces
|
||||||
|
for (const space of community.spaces) {
|
||||||
|
const fullSpace = await this.spaceRepository.findOne({
|
||||||
|
where: { uuid: space.uuid },
|
||||||
|
relations: ['children', 'devices', 'devices.productDevice'],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (fullSpace) {
|
||||||
|
await fetchSpaceDevices(fullSpace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return allDevices;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
ApiBearerAuth,
|
ApiBearerAuth,
|
||||||
ApiOperation,
|
ApiOperation,
|
||||||
ApiParam,
|
ApiParam,
|
||||||
|
ApiQuery,
|
||||||
} from '@nestjs/swagger';
|
} from '@nestjs/swagger';
|
||||||
import { EnableDisableStatusEnum } from '@app/common/constants/days.enum';
|
import { EnableDisableStatusEnum } from '@app/common/constants/days.enum';
|
||||||
import { ControllerRoute } from '@app/common/constants/controller-route';
|
import { ControllerRoute } from '@app/common/constants/controller-route';
|
||||||
@ -16,7 +17,7 @@ import {
|
|||||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||||
import {
|
import {
|
||||||
PowerClampParamsDto,
|
PowerClampParamsDto,
|
||||||
SpaceParamsDto,
|
ResourceParamsDto,
|
||||||
} from '../dto/power-clamp-params.dto';
|
} from '../dto/power-clamp-params.dto';
|
||||||
|
|
||||||
@ApiTags('Power Clamp Module')
|
@ApiTags('Power Clamp Module')
|
||||||
@ -47,20 +48,32 @@ export class PowerClampController {
|
|||||||
}
|
}
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@Get('historical/space/:spaceUuid')
|
@Get('historical')
|
||||||
@ApiOperation({
|
@ApiOperation({
|
||||||
summary: ControllerRoute.PowerClamp.ACTIONS.GET_ENERGY_SUMMARY,
|
summary:
|
||||||
description: ControllerRoute.PowerClamp.ACTIONS.GET_ENERGY_DESCRIPTION,
|
ControllerRoute.PowerClamp.ACTIONS
|
||||||
|
.GET_ENERGY_BY_COMMUNITY_OR_SPACE_SUMMARY,
|
||||||
|
description:
|
||||||
|
ControllerRoute.PowerClamp.ACTIONS
|
||||||
|
.GET_ENERGY_BY_COMMUNITY_OR_SPACE_DESCRIPTION,
|
||||||
})
|
})
|
||||||
@ApiParam({
|
@ApiQuery({
|
||||||
name: 'spaceUuid',
|
name: 'spaceUuid',
|
||||||
description: 'UUID of the Space',
|
description: 'UUID of the Space',
|
||||||
required: true,
|
required: false,
|
||||||
})
|
})
|
||||||
async getPowerClampBySpaceData(
|
@ApiQuery({
|
||||||
@Param() params: SpaceParamsDto,
|
name: 'communityUuid',
|
||||||
|
description: 'UUID of the Community',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
async getPowerClampDataBySpaceOrCommunity(
|
||||||
|
@Query() params: ResourceParamsDto,
|
||||||
@Query() query: GetPowerClampBySpaceDto,
|
@Query() query: GetPowerClampBySpaceDto,
|
||||||
): Promise<BaseResponseDto> {
|
): Promise<BaseResponseDto> {
|
||||||
return await this.powerClampService.getPowerClampBySpaceData(params, query);
|
return await this.powerClampService.getPowerClampDataBySpaceOrCommunity(
|
||||||
|
params,
|
||||||
|
query,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { IsUUID } from 'class-validator';
|
import { IsNotEmpty, IsOptional, IsUUID, ValidateIf } from 'class-validator';
|
||||||
|
|
||||||
export class PowerClampParamsDto {
|
export class PowerClampParamsDto {
|
||||||
@IsUUID('4', { message: 'Invalid UUID format' })
|
@IsUUID('4', { message: 'Invalid UUID format' })
|
||||||
@ -8,3 +8,16 @@ export class SpaceParamsDto {
|
|||||||
@IsUUID('4', { message: 'Invalid UUID format' })
|
@IsUUID('4', { message: 'Invalid UUID format' })
|
||||||
spaceUuid: string;
|
spaceUuid: string;
|
||||||
}
|
}
|
||||||
|
export class ResourceParamsDto {
|
||||||
|
@IsUUID('4', { message: 'Invalid UUID format' })
|
||||||
|
@IsOptional()
|
||||||
|
spaceUuid?: string;
|
||||||
|
|
||||||
|
@IsUUID('4', { message: 'Invalid UUID format' })
|
||||||
|
@IsOptional()
|
||||||
|
communityUuid?: string;
|
||||||
|
|
||||||
|
@ValidateIf((o) => !o.spaceUuid && !o.communityUuid)
|
||||||
|
@IsNotEmpty({ message: 'Either spaceUuid or communityUuid must be provided' })
|
||||||
|
requireEither?: never; // This ensures at least one of them is provided
|
||||||
|
}
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
import {
|
||||||
|
BadRequestException,
|
||||||
|
HttpException,
|
||||||
|
HttpStatus,
|
||||||
|
Injectable,
|
||||||
|
} from '@nestjs/common';
|
||||||
import {
|
import {
|
||||||
GetPowerClampBySpaceDto,
|
GetPowerClampBySpaceDto,
|
||||||
GetPowerClampDto,
|
GetPowerClampDto,
|
||||||
@ -11,7 +16,7 @@ import {
|
|||||||
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
||||||
import {
|
import {
|
||||||
PowerClampParamsDto,
|
PowerClampParamsDto,
|
||||||
SpaceParamsDto,
|
ResourceParamsDto,
|
||||||
} from '../dto/power-clamp-params.dto';
|
} from '../dto/power-clamp-params.dto';
|
||||||
import { DeviceRepository } from '@app/common/modules/device/repositories';
|
import { DeviceRepository } from '@app/common/modules/device/repositories';
|
||||||
import { SpaceDeviceService } from 'src/space/services';
|
import { SpaceDeviceService } from 'src/space/services';
|
||||||
@ -20,6 +25,8 @@ import { DataSource } from 'typeorm';
|
|||||||
import { SQL_PROCEDURES_PATH } from '@app/common/constants/sql-query-path';
|
import { SQL_PROCEDURES_PATH } from '@app/common/constants/sql-query-path';
|
||||||
import { filterByMonth, toMMYYYY } from '@app/common/helper/date-format';
|
import { filterByMonth, toMMYYYY } from '@app/common/helper/date-format';
|
||||||
import { ProductType } from '@app/common/constants/product-type.enum';
|
import { ProductType } from '@app/common/constants/product-type.enum';
|
||||||
|
import { CommunityService } from 'src/community/services';
|
||||||
|
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PowerClampService {
|
export class PowerClampService {
|
||||||
@ -31,50 +38,77 @@ export class PowerClampService {
|
|||||||
private readonly spaceDeviceService: SpaceDeviceService,
|
private readonly spaceDeviceService: SpaceDeviceService,
|
||||||
private readonly sqlLoader: SqlLoaderService,
|
private readonly sqlLoader: SqlLoaderService,
|
||||||
private readonly dataSource: DataSource,
|
private readonly dataSource: DataSource,
|
||||||
|
private readonly communityService: CommunityService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async getPowerClampBySpaceData(
|
async getPowerClampDataBySpaceOrCommunity(
|
||||||
params: SpaceParamsDto,
|
params: ResourceParamsDto,
|
||||||
query: GetPowerClampBySpaceDto,
|
query: GetPowerClampBySpaceDto,
|
||||||
) {
|
): Promise<BaseResponseDto> {
|
||||||
const { monthDate } = query;
|
const { monthDate } = query;
|
||||||
const { spaceUuid } = params;
|
const { spaceUuid, communityUuid } = params;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const devices =
|
// Validate we have at least one identifier
|
||||||
await this.spaceDeviceService.getAllDevicesBySpace(spaceUuid);
|
if (!spaceUuid && !communityUuid) {
|
||||||
console.log('devices', devices);
|
throw new BadRequestException(
|
||||||
|
'Either spaceUuid or communityUuid must be provided',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get devices based on space or community
|
||||||
|
const devices = spaceUuid
|
||||||
|
? await this.spaceDeviceService.getAllDevicesBySpace(spaceUuid)
|
||||||
|
: await this.communityService.getAllDevicesByCommunity(communityUuid);
|
||||||
|
|
||||||
|
if (!devices?.length) {
|
||||||
|
return this.buildResponse(
|
||||||
|
'No power clamp devices found for the specified criteria',
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter and prepare device UUIDs
|
||||||
const deviceUuids = devices
|
const deviceUuids = devices
|
||||||
.filter((device) => device.productDevice.prodType === ProductType.PC)
|
.filter((device) => device.productDevice?.prodType === ProductType.PC)
|
||||||
.map((device) => device.uuid)
|
.map((device) => device.uuid);
|
||||||
.join(',');
|
|
||||||
console.log('deviceUuids', deviceUuids);
|
|
||||||
|
|
||||||
|
if (deviceUuids.length === 0) {
|
||||||
|
return this.buildResponse(
|
||||||
|
'No power clamp devices (PC type) found for the specified criteria',
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute procedure
|
||||||
const formattedMonthDate = toMMYYYY(monthDate);
|
const formattedMonthDate = toMMYYYY(monthDate);
|
||||||
|
|
||||||
const data = await this.executeProcedure(
|
const data = await this.executeProcedure(
|
||||||
'fact_daily_space_energy_consumed_procedure',
|
'fact_daily_space_energy_consumed_procedure',
|
||||||
[formattedMonthDate, deviceUuids],
|
[formattedMonthDate, deviceUuids.join(',')],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Format date to YYYY-MM-DD
|
// Format and filter data
|
||||||
const formattedData = data.map((item) => ({
|
const formattedData = data.map((item) => ({
|
||||||
...item,
|
...item,
|
||||||
date: new Date(item.date).toLocaleDateString('en-CA'), // YYYY-MM-DD
|
date: new Date(item.date).toLocaleDateString('en-CA'), // YYYY-MM-DD
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const filteredData = monthDate
|
const resultData = monthDate
|
||||||
? filterByMonth(formattedData, monthDate)
|
? filterByMonth(formattedData, monthDate)
|
||||||
: formattedData;
|
: formattedData;
|
||||||
|
|
||||||
return this.buildResponse(
|
return this.buildResponse(
|
||||||
`Power clamp data for space ${spaceUuid} fetched successfully`,
|
`Power clamp data fetched successfully for ${spaceUuid ? 'space' : 'community'}`,
|
||||||
filteredData,
|
resultData,
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.error('Error fetching power clamp data', {
|
||||||
|
error,
|
||||||
|
spaceUuid,
|
||||||
|
communityUuid,
|
||||||
|
});
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
error.message || 'Error fetching power clamp data by space',
|
error.response?.message || 'Failed to fetch power clamp data',
|
||||||
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
|
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user