Refactor Scene Module: Add Update Scene Tap To Run Endpoint

This commit is contained in:
faris Aljohari
2024-06-24 16:03:01 +03:00
parent d6f846086c
commit feaae7341a
4 changed files with 126 additions and 16 deletions

View File

@ -8,10 +8,11 @@ import {
HttpStatus,
Param,
Post,
Put,
UseGuards,
} from '@nestjs/common';
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
import { AddSceneTapToRunDto } from '../dtos/add.scene.dto';
import { AddSceneTapToRunDto, UpdateSceneTapToRunDto } from '../dtos/scene.dto';
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
@ApiTags('Scene Module')
@ -99,11 +100,37 @@ export class SceneController {
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Get('tap-to-run/details/:sceneId')
async triggerTapToRunSceneDetails(@Param('sceneId') sceneId: string) {
async getTapToRunSceneDetails(@Param('sceneId') sceneId: string) {
try {
const tapToRunScenes =
await this.sceneService.triggerTapToRunSceneDetails(sceneId);
await this.sceneService.getTapToRunSceneDetails(sceneId);
return tapToRunScenes;
} catch (error) {
throw new HttpException(
error.message || 'Internal server error',
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
);
``;
}
}
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Put('tap-to-run/:sceneId')
async updateTapToRunScene(
@Body() updateSceneTapToRunDto: UpdateSceneTapToRunDto,
@Param('sceneId') sceneId: string,
) {
try {
const tapToRunScene = await this.sceneService.updateTapToRunScene(
updateSceneTapToRunDto,
sceneId,
);
return {
statusCode: HttpStatus.CREATED,
success: true,
message: 'Scene updated successfully',
data: tapToRunScene,
};
} catch (error) {
throw new HttpException(
error.message || 'Internal server error',

View File

@ -1 +1 @@
export * from './add.scene.dto';
export * from './scene.dto';

View File

@ -101,3 +101,34 @@ export class AddSceneTapToRunDto {
Object.assign(this, dto);
}
}
export class UpdateSceneTapToRunDto {
@ApiProperty({
description: 'Scene name',
required: true,
})
@IsString()
@IsNotEmpty()
public sceneName: string;
@ApiProperty({
description: 'Decision expression',
required: true,
})
@IsString()
@IsNotEmpty()
public decisionExpr: string;
@ApiProperty({
description: 'Actions',
required: true,
type: [Action],
})
@IsArray()
@ValidateNested({ each: true })
@Type(() => Action)
public actions: Action[];
constructor(dto: Partial<AddSceneTapToRunDto>) {
Object.assign(this, dto);
}
}

View File

@ -5,7 +5,7 @@ import {
BadRequestException,
} from '@nestjs/common';
import { SpaceRepository } from '@app/common/modules/space/repositories';
import { AddSceneTapToRunDto } from '../dtos';
import { AddSceneTapToRunDto, UpdateSceneTapToRunDto } from '../dtos';
import { GetUnitByUuidInterface } from 'src/unit/interface/unit.interface';
import { ConfigService } from '@nestjs/config';
import { TuyaContext } from '@tuya/tuya-connector-nodejs';
@ -36,12 +36,24 @@ export class SceneService {
});
}
async addTapToRunScene(addSceneTapToRunDto: AddSceneTapToRunDto) {
async addTapToRunScene(
addSceneTapToRunDto: AddSceneTapToRunDto,
spaceTuyaId = null,
) {
try {
const unit = await this.getUnitByUuid(addSceneTapToRunDto.unitUuid);
if (!unit.spaceTuyaUuid) {
throw new BadRequestException('Invalid unit UUID');
let unitSpaceTuyaId;
if (!spaceTuyaId) {
const unitDetails = await this.getUnitByUuid(
addSceneTapToRunDto.unitUuid,
);
unitSpaceTuyaId = unitDetails.spaceTuyaUuid;
if (!unitDetails) {
throw new BadRequestException('Invalid unit UUID');
}
} else {
unitSpaceTuyaId = spaceTuyaId;
}
const actions = addSceneTapToRunDto.actions.map((action) => {
return {
...action,
@ -65,7 +77,7 @@ export class SceneService {
method: 'POST',
path,
body: {
space_id: unit.spaceTuyaUuid,
space_id: unitSpaceTuyaId,
name: addSceneTapToRunDto.sceneName,
type: 'scene',
decision_expr: addSceneTapToRunDto.decisionExpr,
@ -157,14 +169,24 @@ export class SceneService {
}
}
}
async deleteTapToRunScene(unitUuid: string, sceneId: string) {
async deleteTapToRunScene(
unitUuid: string,
sceneId: string,
spaceTuyaId = null,
) {
try {
const unit = await this.getUnitByUuid(unitUuid);
if (!unit.spaceTuyaUuid) {
throw new BadRequestException('Invalid unit UUID');
let unitSpaceTuyaId;
if (!spaceTuyaId) {
const unitDetails = await this.getUnitByUuid(unitUuid);
unitSpaceTuyaId = unitDetails.spaceTuyaUuid;
if (!unitSpaceTuyaId) {
throw new BadRequestException('Invalid unit UUID');
}
} else {
unitSpaceTuyaId = spaceTuyaId;
}
const path = `/v2.0/cloud/scene/rule?ids=${sceneId}&space_id=${unit.spaceTuyaUuid}`;
const path = `/v2.0/cloud/scene/rule?ids=${sceneId}&space_id=${unitSpaceTuyaId}`;
const response: DeleteTapToRunSceneInterface = await this.tuya.request({
method: 'DELETE',
path,
@ -208,7 +230,7 @@ export class SceneService {
}
}
}
async triggerTapToRunSceneDetails(sceneId: string) {
async getTapToRunSceneDetails(sceneId: string, withSpaceId = false) {
try {
const path = `/v2.0/cloud/scene/rule/${sceneId}`;
const response = await this.tuya.request({
@ -225,7 +247,37 @@ export class SceneService {
status: responseData.status,
type: 'tap_to_run',
actions: responseData.actions,
...(withSpaceId && { spaceId: responseData.spaceId }),
};
} catch (err) {
if (err instanceof BadRequestException) {
throw err; // Re-throw BadRequestException
} else {
throw new HttpException('Scene not found', HttpStatus.NOT_FOUND);
}
}
}
async updateTapToRunScene(
updateSceneTapToRunDto: UpdateSceneTapToRunDto,
sceneId: string,
) {
try {
const spaceTuyaId = await this.getTapToRunSceneDetails(sceneId, true);
if (!spaceTuyaId.spaceId) {
throw new HttpException("Scene doesn't exist", HttpStatus.NOT_FOUND);
}
const addSceneTapToRunDto: AddSceneTapToRunDto = {
...updateSceneTapToRunDto,
unitUuid: null,
};
const newTapToRunScene = await this.addTapToRunScene(
addSceneTapToRunDto,
spaceTuyaId.spaceId,
);
if (newTapToRunScene.id) {
await this.deleteTapToRunScene(null, sceneId, spaceTuyaId.spaceId);
return newTapToRunScene;
}
} catch (err) {
if (err instanceof BadRequestException) {
throw err; // Re-throw BadRequestException