Merge pull request #314 from SyncrowIOT/feat/move-automation-by-space-to-space-module

Feat/move-automation-by-space-to-space-module
This commit is contained in:
hannathkadher
2025-03-14 11:47:57 +04:00
committed by GitHub
7 changed files with 162 additions and 54 deletions

View File

@ -624,18 +624,13 @@ export class ControllerRoute {
}; };
static AUTOMATION = class { static AUTOMATION = class {
public static readonly ROUTE = '/projects/:projectUuid/automation'; public static readonly ROUTE = '/projects/:projectUuid/automations';
static ACTIONS = class { static ACTIONS = class {
public static readonly ADD_AUTOMATION_SUMMARY = 'Add automation'; public static readonly ADD_AUTOMATION_SUMMARY = 'Add automation';
public static readonly ADD_AUTOMATION_DESCRIPTION = public static readonly ADD_AUTOMATION_DESCRIPTION =
'This endpoint creates a new automation based on the provided details.'; 'This endpoint creates a new automation based on the provided details.';
public static readonly GET_AUTOMATION_BY_SPACE_SUMMARY =
'Get automation by space';
public static readonly GET_AUTOMATION_BY_SPACE_DESCRIPTION =
'This endpoint retrieves the automations associated with a particular space.';
public static readonly GET_AUTOMATION_DETAILS_SUMMARY = public static readonly GET_AUTOMATION_DETAILS_SUMMARY =
'Get automation details'; 'Get automation details';
public static readonly GET_AUTOMATION_DETAILS_DESCRIPTION = public static readonly GET_AUTOMATION_DETAILS_DESCRIPTION =
@ -656,6 +651,17 @@ export class ControllerRoute {
}; };
}; };
static AUTOMATION_SPACE = class {
public static readonly ROUTE =
'/projects/:projectUuid/communities/:communityUuid/spaces/:spaceUuid/automation';
static ACTIONS = class {
public static readonly GET_AUTOMATION_BY_SPACE_SUMMARY =
'Get automation by space';
public static readonly GET_AUTOMATION_BY_SPACE_DESCRIPTION =
'This endpoint retrieves the automations associated with a particular space.';
};
};
static DOOR_LOCK = class { static DOOR_LOCK = class {
public static readonly ROUTE = 'door-lock'; public static readonly ROUTE = 'door-lock';

View File

@ -0,0 +1,12 @@
import { ApiProperty } from '@nestjs/swagger';
import { ProjectParam } from './project-param.dto';
import { IsUUID } from 'class-validator';
export class CommunityParam extends ProjectParam {
@ApiProperty({
description: 'UUID of the community this space belongs to',
example: 'd290f1ee-6c54-4b01-90e6-d701748f0851',
})
@IsUUID()
communityUuid: string;
}

View File

@ -0,0 +1,12 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsUUID } from 'class-validator';
import { CommunityParam } from './community-space.param';
export class GetSpaceParam extends CommunityParam {
@ApiProperty({
description: 'UUID of the Space',
example: 'd290f1ee-6c54-4b01-90e6-d701748f0851',
})
@IsUUID()
spaceUuid: string;
}

View File

@ -17,10 +17,11 @@ import {
import { SceneDeviceRepository } from '@app/common/modules/scene-device/repositories'; import { SceneDeviceRepository } from '@app/common/modules/scene-device/repositories';
import { AutomationRepository } from '@app/common/modules/automation/repositories'; import { AutomationRepository } from '@app/common/modules/automation/repositories';
import { ProjectRepository } from '@app/common/modules/project/repositiories/project.repository'; import { ProjectRepository } from '@app/common/modules/project/repositiories/project.repository';
import { AutomationSpaceController } from './controllers/automation-space.controller';
@Module({ @Module({
imports: [ConfigModule, SpaceRepositoryModule, DeviceStatusFirebaseModule], imports: [ConfigModule, SpaceRepositoryModule, DeviceStatusFirebaseModule],
controllers: [AutomationController], controllers: [AutomationController, AutomationSpaceController],
providers: [ providers: [
AutomationService, AutomationService,
TuyaService, TuyaService,

View File

@ -0,0 +1,33 @@
import { ControllerRoute } from '@app/common/constants/controller-route';
import { EnableDisableStatusEnum } from '@app/common/constants/days.enum';
import { Controller, Get, Param, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { AutomationService } from '../services';
import { Permissions } from 'src/decorators/permissions.decorator';
import { PermissionsGuard } from 'src/guards/permissions.guard';
import { GetSpaceParam } from '@app/common/dto/get.space.param';
@ApiTags('Automation Module')
@Controller({
version: EnableDisableStatusEnum.ENABLED,
path: ControllerRoute.AUTOMATION_SPACE.ROUTE,
})
export class AutomationSpaceController {
constructor(private readonly automationService: AutomationService) {}
@ApiBearerAuth()
@UseGuards(PermissionsGuard)
@Permissions('AUTOMATION_VIEW')
@Get()
@ApiOperation({
summary:
ControllerRoute.AUTOMATION_SPACE.ACTIONS.GET_AUTOMATION_BY_SPACE_SUMMARY,
description:
ControllerRoute.AUTOMATION_SPACE.ACTIONS
.GET_AUTOMATION_BY_SPACE_DESCRIPTION,
})
async getAutomationBySpace(@Param() param: GetSpaceParam) {
const automation = await this.automationService.getAutomationBySpace(param);
return automation;
}
}

View File

@ -17,7 +17,7 @@ import {
UpdateAutomationStatusDto, UpdateAutomationStatusDto,
} from '../dtos/automation.dto'; } from '../dtos/automation.dto';
import { EnableDisableStatusEnum } from '@app/common/constants/days.enum'; import { EnableDisableStatusEnum } from '@app/common/constants/days.enum';
import { AutomationParamDto, SpaceParamDto } from '../dtos'; import { AutomationParamDto } from '../dtos';
import { ControllerRoute } from '@app/common/constants/controller-route'; import { ControllerRoute } from '@app/common/constants/controller-route';
import { PermissionsGuard } from 'src/guards/permissions.guard'; import { PermissionsGuard } from 'src/guards/permissions.guard';
import { Permissions } from 'src/decorators/permissions.decorator'; import { Permissions } from 'src/decorators/permissions.decorator';
@ -55,20 +55,6 @@ export class AutomationController {
}; };
} }
@ApiBearerAuth()
@UseGuards(PermissionsGuard)
@Permissions('AUTOMATION_VIEW')
@Get(':spaceUuid')
@ApiOperation({
summary: ControllerRoute.AUTOMATION.ACTIONS.GET_AUTOMATION_BY_SPACE_SUMMARY,
description:
ControllerRoute.AUTOMATION.ACTIONS.GET_AUTOMATION_BY_SPACE_DESCRIPTION,
})
async getAutomationBySpace(@Param() param: SpaceParamDto) {
const automation = await this.automationService.getAutomationBySpace(param);
return automation;
}
@ApiBearerAuth() @ApiBearerAuth()
@UseGuards(PermissionsGuard) @UseGuards(PermissionsGuard)
@Permissions('AUTOMATION_VIEW') @Permissions('AUTOMATION_VIEW')

View File

@ -8,7 +8,6 @@ import { SpaceRepository } from '@app/common/modules/space/repositories';
import { import {
AddAutomationDto, AddAutomationDto,
AutomationParamDto, AutomationParamDto,
SpaceParamDto,
UpdateAutomationDto, UpdateAutomationDto,
UpdateAutomationStatusDto, UpdateAutomationStatusDto,
} from '../dtos'; } from '../dtos';
@ -42,6 +41,7 @@ import { AutomationEntity } from '@app/common/modules/automation/entities';
import { DeleteTapToRunSceneInterface } from 'src/scene/interface/scene.interface'; import { DeleteTapToRunSceneInterface } from 'src/scene/interface/scene.interface';
import { ProjectParam } from '@app/common/dto/project-param.dto'; import { ProjectParam } from '@app/common/dto/project-param.dto';
import { ProjectRepository } from '@app/common/modules/project/repositiories'; import { ProjectRepository } from '@app/common/modules/project/repositiories';
import { GetSpaceParam } from '@app/common/dto/get.space.param';
@Injectable() @Injectable()
export class AutomationService { export class AutomationService {
@ -81,8 +81,9 @@ export class AutomationService {
conditions, conditions,
spaceUuid, spaceUuid,
} = addAutomationDto; } = addAutomationDto;
const space = await this.getSpaceByUuid(spaceUuid); const space = await this.getSpaceByUuid(spaceUuid, param.projectUuid);
const automation = await this.add({ const automation = await this.add(
{
automationName, automationName,
effectiveTime, effectiveTime,
decisionExpr, decisionExpr,
@ -90,7 +91,9 @@ export class AutomationService {
conditions, conditions,
spaceTuyaId: space.spaceTuyaUuid, spaceTuyaId: space.spaceTuyaUuid,
spaceUuid, spaceUuid,
}); },
param.projectUuid,
);
return new SuccessResponseDto({ return new SuccessResponseDto({
message: `Successfully created new automation with uuid ${automation.uuid}`, message: `Successfully created new automation with uuid ${automation.uuid}`,
data: automation, data: automation,
@ -109,9 +112,15 @@ export class AutomationService {
); );
} }
} }
async createAutomationExternalService(params: AddAutomationParams) { async createAutomationExternalService(
params: AddAutomationParams,
projectUuid: string,
) {
try { try {
const formattedActions = await this.prepareActions(params.actions); const formattedActions = await this.prepareActions(
params.actions,
projectUuid,
);
const formattedCondition = await this.prepareConditions( const formattedCondition = await this.prepareConditions(
params.conditions, params.conditions,
); );
@ -149,9 +158,12 @@ export class AutomationService {
} }
} }
} }
async add(params: AddAutomationParams) { async add(params: AddAutomationParams, projectUuid: string) {
try { try {
const response = await this.createAutomationExternalService(params); const response = await this.createAutomationExternalService(
params,
projectUuid,
);
const automation = await this.automationRepository.save({ const automation = await this.automationRepository.save({
automationTuyaUuid: response.result.id, automationTuyaUuid: response.result.id,
@ -176,11 +188,16 @@ export class AutomationService {
} }
} }
async getSpaceByUuid(spaceUuid: string) { async getSpaceByUuid(spaceUuid: string, projectUuid: string) {
try { try {
const space = await this.spaceRepository.findOne({ const space = await this.spaceRepository.findOne({
where: { where: {
uuid: spaceUuid, uuid: spaceUuid,
community: {
project: {
uuid: projectUuid,
},
},
}, },
relations: ['community'], relations: ['community'],
}); });
@ -203,14 +220,22 @@ export class AutomationService {
} }
} }
async getAutomationBySpace(param: SpaceParamDto) { async getAutomationBySpace(param: GetSpaceParam) {
try { try {
await this.validateProject(param.projectUuid); await this.validateProject(param.projectUuid);
// Fetch automation data from the repository // Fetch automation data from the repository
const automationData = await this.automationRepository.find({ const automationData = await this.automationRepository.find({
where: { where: {
space: { uuid: param.spaceUuid }, space: {
uuid: param.spaceUuid,
community: {
uuid: param.communityUuid,
project: {
uuid: param.projectUuid,
},
},
},
disabled: false, disabled: false,
}, },
relations: ['space'], relations: ['space'],
@ -259,9 +284,10 @@ export class AutomationService {
); );
} }
} }
async findAutomationBySpace(spaceUuid: string) {
async findAutomationBySpace(spaceUuid: string, projectUuid: string) {
try { try {
await this.getSpaceByUuid(spaceUuid); await this.getSpaceByUuid(spaceUuid, projectUuid);
const automationData = await this.automationRepository.find({ const automationData = await this.automationRepository.find({
where: { where: {
@ -334,7 +360,10 @@ export class AutomationService {
await this.validateProject(param.projectUuid); await this.validateProject(param.projectUuid);
try { try {
const automation = await this.findAutomation(param.automationUuid); const automation = await this.findAutomation(
param.automationUuid,
param.projectUuid,
);
const automationDetails = await this.getAutomation(automation); const automationDetails = await this.getAutomation(automation);
@ -460,9 +489,15 @@ export class AutomationService {
} }
} }
} }
async findAutomation(sceneUuid: string): Promise<AutomationEntity> { async findAutomation(
sceneUuid: string,
projectUuid: string,
): Promise<AutomationEntity> {
const automation = await this.automationRepository.findOne({ const automation = await this.automationRepository.findOne({
where: { uuid: sceneUuid }, where: {
uuid: sceneUuid,
space: { community: { project: { uuid: projectUuid } } },
},
relations: ['space'], relations: ['space'],
}); });
@ -480,8 +515,14 @@ export class AutomationService {
await this.validateProject(param.projectUuid); await this.validateProject(param.projectUuid);
try { try {
const automationData = await this.findAutomation(automationUuid); const automationData = await this.findAutomation(
const space = await this.getSpaceByUuid(automationData.space.uuid); automationUuid,
param.projectUuid,
);
const space = await this.getSpaceByUuid(
automationData.space.uuid,
param.projectUuid,
);
await this.delete(automationData.automationTuyaUuid, space.spaceTuyaUuid); await this.delete(automationData.automationTuyaUuid, space.spaceTuyaUuid);
const existingSceneDevice = await this.sceneDeviceRepository.findOne({ const existingSceneDevice = await this.sceneDeviceRepository.findOne({
where: { automationTuyaUuid: automationData.automationTuyaUuid }, where: { automationTuyaUuid: automationData.automationTuyaUuid },
@ -534,11 +575,12 @@ export class AutomationService {
spaceTuyaUuid: string, spaceTuyaUuid: string,
automationUuid: string, automationUuid: string,
updateAutomationDto: UpdateAutomationDto, updateAutomationDto: UpdateAutomationDto,
projectUuid: string,
) { ) {
const { automationName, decisionExpr, actions, conditions, effectiveTime } = const { automationName, decisionExpr, actions, conditions, effectiveTime } =
updateAutomationDto; updateAutomationDto;
try { try {
const formattedActions = await this.prepareActions(actions); const formattedActions = await this.prepareActions(actions, projectUuid);
const formattedCondition = await this.prepareConditions(conditions); const formattedCondition = await this.prepareConditions(conditions);
const response = await this.tuyaService.updateAutomation( const response = await this.tuyaService.updateAutomation(
automationUuid, automationUuid,
@ -581,14 +623,21 @@ export class AutomationService {
await this.validateProject(param.projectUuid); await this.validateProject(param.projectUuid);
try { try {
const automation = await this.findAutomation(param.automationUuid); const automation = await this.findAutomation(
const space = await this.getSpaceByUuid(automation.space.uuid); param.automationUuid,
param.projectUuid,
);
const space = await this.getSpaceByUuid(
automation.space.uuid,
param.projectUuid,
);
const updateTuyaAutomationResponse = const updateTuyaAutomationResponse =
await this.updateAutomationExternalService( await this.updateAutomationExternalService(
space.spaceTuyaUuid, space.spaceTuyaUuid,
automation.automationTuyaUuid, automation.automationTuyaUuid,
updateAutomationDto, updateAutomationDto,
param.projectUuid,
); );
if (!updateTuyaAutomationResponse.success) { if (!updateTuyaAutomationResponse.success) {
@ -626,8 +675,11 @@ export class AutomationService {
await this.validateProject(param.projectUuid); await this.validateProject(param.projectUuid);
try { try {
const automation = await this.findAutomation(param.automationUuid); const automation = await this.findAutomation(
const space = await this.getSpaceByUuid(spaceUuid); param.automationUuid,
param.projectUuid,
);
const space = await this.getSpaceByUuid(spaceUuid, param.projectUuid);
if (!space.spaceTuyaUuid) { if (!space.spaceTuyaUuid) {
throw new HttpException( throw new HttpException(
`Invalid space UUID ${spaceUuid}`, `Invalid space UUID ${spaceUuid}`,
@ -654,7 +706,10 @@ export class AutomationService {
} }
} }
private async prepareActions(actions: Action[]): Promise<ConvertedAction[]> { private async prepareActions(
actions: Action[],
projectUuid: string,
): Promise<ConvertedAction[]> {
const convertedData = convertKeysToSnakeCase(actions) as ConvertedAction[]; const convertedData = convertKeysToSnakeCase(actions) as ConvertedAction[];
await Promise.all( await Promise.all(
@ -687,7 +742,10 @@ export class AutomationService {
action.action_executor === ActionExecutorEnum.RULE_ENABLE action.action_executor === ActionExecutorEnum.RULE_ENABLE
) { ) {
if (action.action_type === ActionTypeEnum.AUTOMATION) { if (action.action_type === ActionTypeEnum.AUTOMATION) {
const automation = await this.findAutomation(action.entity_id); const automation = await this.findAutomation(
action.entity_id,
projectUuid,
);
action.entity_id = automation.automationTuyaUuid; action.entity_id = automation.automationTuyaUuid;
} }
} }