disabling space

This commit is contained in:
hannathkadher
2024-12-25 16:23:09 +04:00
parent f9fe209076
commit f7b75a630a
12 changed files with 198 additions and 27 deletions

View File

@ -44,6 +44,12 @@ export class SceneDeviceEntity extends AbstractEntity<SceneDeviceDto> {
@JoinColumn({ name: 'scene_uuid' }) @JoinColumn({ name: 'scene_uuid' })
scene: SceneEntity; scene: SceneEntity;
@Column({
nullable: false,
default: false,
})
public disabled: boolean;
constructor(partial: Partial<SceneDeviceEntity>) { constructor(partial: Partial<SceneDeviceEntity>) {
super(); super();
Object.assign(this, partial); Object.assign(this, partial);

View File

@ -59,6 +59,12 @@ export class SceneEntity extends AbstractEntity<SceneDto> {
@JoinColumn({ name: 'space_uuid' }) @JoinColumn({ name: 'space_uuid' })
space: SpaceEntity; space: SpaceEntity;
@Column({
nullable: false,
default: false,
})
public disabled: boolean;
@ManyToOne(() => SceneIconEntity, (icon) => icon.scenesIconEntity, { @ManyToOne(() => SceneIconEntity, (icon) => icon.scenesIconEntity, {
nullable: false, nullable: false,
}) })

View File

@ -41,7 +41,7 @@ import {
import { convertKeysToCamelCase } from '@app/common/helper/camelCaseConverter'; import { convertKeysToCamelCase } from '@app/common/helper/camelCaseConverter';
import { DeviceRepository } from '@app/common/modules/device/repositories'; import { DeviceRepository } from '@app/common/modules/device/repositories';
import { PermissionType } from '@app/common/constants/permission-type.enum'; import { PermissionType } from '@app/common/constants/permission-type.enum';
import { In } from 'typeorm'; import { In, QueryRunner } from 'typeorm';
import { ProductType } from '@app/common/constants/product-type.enum'; import { ProductType } from '@app/common/constants/product-type.enum';
import { SpaceRepository } from '@app/common/modules/space/repositories'; import { SpaceRepository } from '@app/common/modules/space/repositories';
import { DeviceStatusFirebaseService } from '@app/common/firebase/devices-status/services/devices-status.service'; import { DeviceStatusFirebaseService } from '@app/common/firebase/devices-status/services/devices-status.service';
@ -59,6 +59,7 @@ import { DeviceSceneParamDto } from '../dtos/device.param.dto';
import { BaseResponseDto } from '@app/common/dto/base.response.dto'; import { BaseResponseDto } from '@app/common/dto/base.response.dto';
import { SuccessResponseDto } from '@app/common/dto/success.response.dto'; import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
import { DeleteSceneFromSceneDeviceDto } from '../dtos/delete.device.dto'; import { DeleteSceneFromSceneDeviceDto } from '../dtos/delete.device.dto';
import { DeviceEntity } from '@app/common/modules/device/entities';
@Injectable() @Injectable()
export class DeviceService { export class DeviceService {
@ -83,6 +84,7 @@ export class DeviceService {
secretKey, secretKey,
}); });
} }
async getDeviceByDeviceUuid( async getDeviceByDeviceUuid(
deviceUuid: string, deviceUuid: string,
withProductDevice: boolean = true, withProductDevice: boolean = true,
@ -98,6 +100,29 @@ export class DeviceService {
relations, relations,
}); });
} }
async deleteDevice(
devices: DeviceEntity[],
orphanSpace: SpaceEntity,
queryRunner: QueryRunner,
): Promise<void> {
try {
const deviceIds = devices.map((device) => device.uuid);
if (deviceIds.length > 0) {
await queryRunner.manager
.createQueryBuilder()
.update(DeviceEntity)
.set({ spaceDevice: orphanSpace })
.whereInIds(deviceIds)
.execute();
}
} catch (error) {
throw new HttpException(
`Failed to update devices to orphan space: ${error.message}`,
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async getDeviceByDeviceTuyaUuid(deviceTuyaUuid: string) { async getDeviceByDeviceTuyaUuid(deviceTuyaUuid: string) {
return await this.deviceRepository.findOne({ return await this.deviceRepository.findOne({

View File

@ -495,12 +495,16 @@ export class SceneService {
const space = await this.getSpaceByUuid(scene.space.uuid); const space = await this.getSpaceByUuid(scene.space.uuid);
await this.delete(scene.sceneTuyaUuid, space.spaceTuyaUuid); await this.delete(scene.sceneTuyaUuid, space.spaceTuyaUuid);
await this.sceneDeviceRepository.delete({ await this.sceneDeviceRepository.update(
scene: { uuid: sceneUuid }, { uuid: sceneUuid },
}); { disabled: true },
await this.sceneRepository.delete({ );
await this.sceneRepository.update(
{
uuid: sceneUuid, uuid: sceneUuid,
}); },
{ disabled: true },
);
return new SuccessResponseDto({ return new SuccessResponseDto({
message: `Scene with ID ${sceneUuid} deleted successfully`, message: `Scene with ID ${sceneUuid} deleted successfully`,
}); });

View File

@ -67,8 +67,8 @@ export class SpaceController {
description: ControllerRoute.SPACE.ACTIONS.DELETE_SPACE_DESCRIPTION, description: ControllerRoute.SPACE.ACTIONS.DELETE_SPACE_DESCRIPTION,
}) })
@Delete('/:spaceUuid') @Delete('/:spaceUuid')
async deleteSpace(@Param() params: GetSpaceParam): Promise<BaseResponseDto> { async deleteSpace(@Param() params: GetSpaceParam){
return this.spaceService.delete(params); return await this.spaceService.deleteSpace(params);
} }
@ApiBearerAuth() @ApiBearerAuth()

View File

@ -92,4 +92,35 @@ export class SpaceLinkService {
); );
} }
} }
async deleteSpaceLink(
space: SpaceEntity,
queryRunner: QueryRunner,
): Promise<void> {
try {
const spaceLinks = await queryRunner.manager.find(SpaceLinkEntity, {
where: [
{ startSpace: space, disabled: false },
{ endSpace: space, disabled: false },
],
});
if (spaceLinks.length === 0) {
return;
}
const linkIds = spaceLinks.map((link) => link.uuid);
await queryRunner.manager
.createQueryBuilder()
.update(SpaceLinkEntity)
.set({ disabled: true })
.whereInIds(linkIds)
.execute();
} catch (error) {
throw new HttpException(
`Failed to disable space links for the given space: ${error.message}`,
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
} }

View File

@ -5,6 +5,9 @@ import { SceneService } from '../../scene/services';
import { SuccessResponseDto } from '@app/common/dto/success.response.dto'; import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
import { GetSceneDto } from '../../scene/dtos'; import { GetSceneDto } from '../../scene/dtos';
import { ValidationService } from './space-validation.service'; import { ValidationService } from './space-validation.service';
import { SpaceEntity } from '@app/common/modules/space';
import { QueryRunner } from 'typeorm';
import { SceneEntity } from '@app/common/modules/scene/entities';
@Injectable() @Injectable()
export class SpaceSceneService { export class SpaceSceneService {
@ -48,4 +51,32 @@ export class SpaceSceneService {
} }
} }
} }
async deleteScenes(
space: SpaceEntity,
queryRunner: QueryRunner,
): Promise<void> {
try {
const scenes = await queryRunner.manager.find(SceneEntity, {
where: { space },
});
if (scenes.length === 0) {
return;
}
const sceneUuids = scenes.map((scene) => scene.uuid);
await Promise.all(
sceneUuids.map((uuid) =>
this.sceneSevice.deleteScene({ sceneUuid: uuid }),
),
);
} catch (error) {
throw new HttpException(
`Failed to delete scenes: ${error.message}`,
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
} }

View File

@ -1,4 +1,3 @@
import { CommunityEntity } from '@app/common/modules/community/entities';
import { SpaceEntity } from '@app/common/modules/space/entities'; import { SpaceEntity } from '@app/common/modules/space/entities';
import { SpaceRepository } from '@app/common/modules/space/repositories'; import { SpaceRepository } from '@app/common/modules/space/repositories';
import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
@ -21,16 +20,17 @@ export class ValidationService {
async validateCommunityAndProject( async validateCommunityAndProject(
communityUuid: string, communityUuid: string,
projectUuid: string, projectUuid: string,
): Promise<CommunityEntity> { ) {
await this.projectService.findOne(projectUuid); const project = await this.projectService.findOne(projectUuid);
const community = await this.communityService.getCommunityById({ const community = await this.communityService.getCommunityById({
communityUuid, communityUuid,
projectUuid, projectUuid,
}); });
return community.data; return { community: community.data, project: project };
} }
async validateSpaceWithinCommunityAndProject( async validateSpaceWithinCommunityAndProject(
communityUuid: string, communityUuid: string,
projectUuid: string, projectUuid: string,

View File

@ -24,6 +24,9 @@ import { ValidationService } from './space-validation.service';
import { ORPHAN_SPACE_NAME } from '@app/common/constants/orphan-constant'; import { ORPHAN_SPACE_NAME } from '@app/common/constants/orphan-constant';
import { TagService } from './tag'; import { TagService } from './tag';
import { SpaceModelService } from 'src/space-model/services'; import { SpaceModelService } from 'src/space-model/services';
import { UserSpaceService } from 'src/users/services';
import { DeviceService } from 'src/device/services';
import { SpaceSceneService } from './space-scene.service';
@Injectable() @Injectable()
export class SpaceService { export class SpaceService {
@ -35,6 +38,9 @@ export class SpaceService {
private readonly validationService: ValidationService, private readonly validationService: ValidationService,
private readonly tagService: TagService, private readonly tagService: TagService,
private readonly spaceModelService: SpaceModelService, private readonly spaceModelService: SpaceModelService,
private readonly userService: UserSpaceService,
private readonly deviceService: DeviceService,
private readonly sceneService: SpaceSceneService,
) {} ) {}
async createSpace( async createSpace(
@ -363,33 +369,70 @@ export class SpaceService {
} }
async deleteSpace(params: GetSpaceParam) { async deleteSpace(params: GetSpaceParam) {
const queryRunner = this.dataSource.createQueryRunner();
const { spaceUuid } = params;
try { try {
const { communityUuid, spaceUuid, projectUuid } = params; await queryRunner.connect();
const space = await queryRunner.startTransaction();
await this.validationService.validateSpaceWithinCommunityAndProject(
communityUuid,
projectUuid,
spaceUuid,
);
const spaces = await this.spaceRepository.find({ const spaces = await this.spaceRepository.find({
where: { parent: { uuid: spaceUuid }, disabled: false }, where: { parent: { uuid: spaceUuid }, disabled: false },
relations: ['parent', 'children'], // Include parent and children relations relations: [
'parent',
'children',
'subspaces',
'tags',
'subspaces.tags',
'devices',
], // Include parent and children relations
}); });
console.log(spaces); //this.disableSpace(space, orphanSpace);
// space.disabled = true; return spaces;
await this.spaceRepository.update({ uuid: space.uuid }, space);
} catch (error) { } catch (error) {
if (error instanceof HttpException) { if (error instanceof HttpException) {
throw error; throw error;
} }
throw new HttpException( throw new HttpException(
'An error occurred while deleting the space', `An error occurred while deleting the space ${error}`,
HttpStatus.INTERNAL_SERVER_ERROR, HttpStatus.INTERNAL_SERVER_ERROR,
); );
} }
} }
async disableSpace(space: SpaceEntity, orphanSpace: SpaceEntity) {
const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
const deleteSubspaceDtos = space.subspaces?.map((subspace) => ({
subspaceUuid: subspace.uuid,
}));
const deleteSpaceTagsDtos = space.tags?.map((tag) => tag.uuid);
await this.userService.deleteUserSpace(space.uuid);
await this.subSpaceService.deleteSubspaces(
deleteSubspaceDtos,
queryRunner,
);
await this.tagService.deleteTags(deleteSpaceTagsDtos, queryRunner);
await this.deviceService.deleteDevice(
space.devices,
orphanSpace,
queryRunner,
);
await this.spaceLinkService.deleteSpaceLink(space, queryRunner);
await this.sceneService.deleteScenes(space, queryRunner);
} catch (error) {
await queryRunner.rollbackTransaction();
} finally {
await queryRunner.release();
}
}
private updateSpaceProperties( private updateSpaceProperties(
space: SpaceEntity, space: SpaceEntity,
updateSpaceDto: UpdateSpaceDto, updateSpaceDto: UpdateSpaceDto,

View File

@ -19,7 +19,6 @@ import { In, QueryRunner } from 'typeorm';
import { import {
SpaceEntity, SpaceEntity,
SubspaceEntity, SubspaceEntity,
TagEntity,
} from '@app/common/modules/space/entities'; } from '@app/common/modules/space/entities';
import { SubspaceModelEntity } from '@app/common/modules/space-model'; import { SubspaceModelEntity } from '@app/common/modules/space-model';
import { ValidationService } from '../space-validation.service'; import { ValidationService } from '../space-validation.service';

View File

@ -28,7 +28,10 @@ import {
UserRepository, UserRepository,
UserSpaceRepository, UserSpaceRepository,
} from '@app/common/modules/user/repositories'; } from '@app/common/modules/user/repositories';
import { DeviceRepository } from '@app/common/modules/device/repositories'; import {
DeviceRepository,
DeviceUserPermissionRepository,
} from '@app/common/modules/device/repositories';
import { TuyaService } from '@app/common/integrations/tuya/services/tuya.service'; import { TuyaService } from '@app/common/integrations/tuya/services/tuya.service';
import { ProductRepository } from '@app/common/modules/product/repositories'; import { ProductRepository } from '@app/common/modules/product/repositories';
import { SceneService } from '../scene/services'; import { SceneService } from '../scene/services';
@ -55,6 +58,9 @@ import {
SubSpaceModelService, SubSpaceModelService,
TagModelService, TagModelService,
} from 'src/space-model/services'; } from 'src/space-model/services';
import { UserSpaceService } from 'src/users/services';
import { UserDevicePermissionService } from 'src/user-device-permission/services';
import { PermissionTypeRepository } from '@app/common/modules/permission/repositories';
@Module({ @Module({
imports: [ConfigModule, SpaceRepositoryModule, CommunityModule], imports: [ConfigModule, SpaceRepositoryModule, CommunityModule],
@ -100,6 +106,10 @@ import {
ProjectRepository, ProjectRepository,
SpaceModelRepository, SpaceModelRepository,
SubspaceModelRepository, SubspaceModelRepository,
UserSpaceService,
UserDevicePermissionService,
DeviceUserPermissionRepository,
PermissionTypeRepository,
], ],
exports: [SpaceService], exports: [SpaceService],
}) })

View File

@ -150,4 +150,20 @@ export class UserSpaceService {
await Promise.all(permissionPromises); await Promise.all(permissionPromises);
} }
async deleteUserSpace(spaceUuid: string) {
try {
await this.userSpaceRepository
.createQueryBuilder()
.delete()
.where('spaceUuid = :spaceUuid', { spaceUuid })
.execute();
} catch (error) {
console.error(`Error deleting user-space associations: ${error.message}`);
throw new HttpException(
`Failed to delete user-space associations: ${error.message}`,
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
} }