mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-15 10:25:23 +00:00
Added tuya space to community
This commit is contained in:
@ -7,10 +7,12 @@ import { ConfigModule } from '@nestjs/config';
|
|||||||
import config from './config';
|
import config from './config';
|
||||||
import { EmailService } from './util/email.service';
|
import { EmailService } from './util/email.service';
|
||||||
import { ErrorMessageService } from 'src/error-message/error-message.service';
|
import { ErrorMessageService } from 'src/error-message/error-message.service';
|
||||||
|
import { TuyaService } from './integrations/tuya/tuya.service';
|
||||||
@Module({
|
@Module({
|
||||||
providers: [CommonService, EmailService, ErrorMessageService],
|
providers: [CommonService, EmailService, ErrorMessageService, TuyaService],
|
||||||
exports: [
|
exports: [
|
||||||
CommonService,
|
CommonService,
|
||||||
|
TuyaService,
|
||||||
HelperModule,
|
HelperModule,
|
||||||
AuthModule,
|
AuthModule,
|
||||||
EmailService,
|
EmailService,
|
||||||
|
@ -13,10 +13,10 @@ export class ControllerRoute {
|
|||||||
public static readonly ROUTE = 'community';
|
public static readonly ROUTE = 'community';
|
||||||
static ACTIONS = class {
|
static ACTIONS = class {
|
||||||
public static readonly GET_COMMUNITY_BY_ID_SUMMARY =
|
public static readonly GET_COMMUNITY_BY_ID_SUMMARY =
|
||||||
'Get community by community id';
|
'Get community by community community uuid';
|
||||||
|
|
||||||
public static readonly GET_COMMUNITY_BY_ID_DESCRIPTION =
|
public static readonly GET_COMMUNITY_BY_ID_DESCRIPTION =
|
||||||
'Get community by community id - ( [a-zA-Z0-9]{10} )';
|
'Get community by community community uuid - ( [a-zA-Z0-9]{10} )';
|
||||||
|
|
||||||
public static readonly LIST_COMMUNITY_SUMMARY = 'Get list of community';
|
public static readonly LIST_COMMUNITY_SUMMARY = 'Get list of community';
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ export class ControllerRoute {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static COMMUNITY_SPACE = class {
|
static COMMUNITY_SPACE = class {
|
||||||
public static readonly ROUTE = 'community/:id/spaces';
|
public static readonly ROUTE = 'community/:communityUuid/space';
|
||||||
static ACTIONS = class {
|
static ACTIONS = class {
|
||||||
public static readonly GET_COMMUNITY_SPACES_HIERARCHY_SUMMARY =
|
public static readonly GET_COMMUNITY_SPACES_HIERARCHY_SUMMARY =
|
||||||
'Fetch hierarchical structure of spaces within a community.';
|
'Fetch hierarchical structure of spaces within a community.';
|
||||||
|
38
libs/common/src/integrations/tuya/tuya.service.ts
Normal file
38
libs/common/src/integrations/tuya/tuya.service.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
import { TuyaContext } from '@tuya/tuya-connector-nodejs';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TuyaService {
|
||||||
|
private tuya: TuyaContext;
|
||||||
|
|
||||||
|
constructor(private readonly configService: ConfigService) {
|
||||||
|
const accessKey = this.configService.get<string>('auth-config.ACCESS_KEY');
|
||||||
|
const secretKey = this.configService.get<string>('auth-config.SECRET_KEY');
|
||||||
|
const tuyaEuUrl = this.configService.get<string>('tuya-config.TUYA_EU_URL');
|
||||||
|
this.tuya = new TuyaContext({
|
||||||
|
baseUrl: tuyaEuUrl,
|
||||||
|
accessKey,
|
||||||
|
secretKey,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async createSpace({ name }: { name: string }) {
|
||||||
|
const path = '/v2.0/cloud/space/creation';
|
||||||
|
const body = { name };
|
||||||
|
|
||||||
|
const response = await this.tuya.request({
|
||||||
|
method: 'POST',
|
||||||
|
path,
|
||||||
|
body,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
return response.result as string;
|
||||||
|
} else {
|
||||||
|
throw new HttpException(
|
||||||
|
'Error creating space in Tuya',
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
import { Column, Entity, ManyToOne, OneToMany, Unique } from 'typeorm';
|
import { Column, Entity, OneToMany, Unique } from 'typeorm';
|
||||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||||
import { CommunityDto } from '../dtos';
|
import { CommunityDto } from '../dtos';
|
||||||
import { RegionEntity } from '../../region/entities';
|
|
||||||
import { SpaceEntity } from '../../space/entities';
|
import { SpaceEntity } from '../../space/entities';
|
||||||
|
|
||||||
@Entity({ name: 'community' })
|
@Entity({ name: 'community' })
|
||||||
@ -23,12 +22,6 @@ export class CommunityEntity extends AbstractEntity<CommunityDto> {
|
|||||||
@Column({ length: 255, nullable: true })
|
@Column({ length: 255, nullable: true })
|
||||||
description: string;
|
description: string;
|
||||||
|
|
||||||
@ManyToOne(() => RegionEntity, (region) => region.communities, {
|
|
||||||
nullable: false,
|
|
||||||
onDelete: 'CASCADE',
|
|
||||||
})
|
|
||||||
region: RegionEntity;
|
|
||||||
|
|
||||||
@OneToMany(() => SpaceEntity, (space) => space.community)
|
@OneToMany(() => SpaceEntity, (space) => space.community)
|
||||||
spaces: SpaceEntity[];
|
spaces: SpaceEntity[];
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ import { Column, Entity, OneToMany } from 'typeorm';
|
|||||||
import { RegionDto } from '../dtos';
|
import { RegionDto } from '../dtos';
|
||||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||||
import { UserEntity } from '../../user/entities';
|
import { UserEntity } from '../../user/entities';
|
||||||
import { CommunityEntity } from '../../community/entities';
|
|
||||||
|
|
||||||
@Entity({ name: 'region' })
|
@Entity({ name: 'region' })
|
||||||
export class RegionEntity extends AbstractEntity<RegionDto> {
|
export class RegionEntity extends AbstractEntity<RegionDto> {
|
||||||
@ -14,9 +13,6 @@ export class RegionEntity extends AbstractEntity<RegionDto> {
|
|||||||
@OneToMany(() => UserEntity, (user) => user.region)
|
@OneToMany(() => UserEntity, (user) => user.region)
|
||||||
users: UserEntity[];
|
users: UserEntity[];
|
||||||
|
|
||||||
@OneToMany(() => CommunityEntity, (community) => community.region)
|
|
||||||
communities: CommunityEntity[];
|
|
||||||
|
|
||||||
constructor(partial: Partial<RegionEntity>) {
|
constructor(partial: Partial<RegionEntity>) {
|
||||||
super();
|
super();
|
||||||
Object.assign(this, partial);
|
Object.assign(this, partial);
|
||||||
|
@ -11,7 +11,7 @@ import { SpacePermissionService } from '@app/common/helper/services';
|
|||||||
import { CommunitySpaceService } from './services';
|
import { CommunitySpaceService } from './services';
|
||||||
import { CommunitySpaceController } from './controllers';
|
import { CommunitySpaceController } from './controllers';
|
||||||
import { CommunityRepository } from '@app/common/modules/community/repositories';
|
import { CommunityRepository } from '@app/common/modules/community/repositories';
|
||||||
import { RegionRepository } from '@app/common/modules/region/repositories';
|
import { TuyaService } from '@app/common/integrations/tuya/tuya.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [ConfigModule, SpaceRepositoryModule, UserRepositoryModule],
|
imports: [ConfigModule, SpaceRepositoryModule, UserRepositoryModule],
|
||||||
@ -22,7 +22,7 @@ import { RegionRepository } from '@app/common/modules/region/repositories';
|
|||||||
SpaceRepository,
|
SpaceRepository,
|
||||||
SpaceTypeRepository,
|
SpaceTypeRepository,
|
||||||
UserSpaceRepository,
|
UserSpaceRepository,
|
||||||
RegionRepository,
|
TuyaService,
|
||||||
CommunityRepository,
|
CommunityRepository,
|
||||||
SpacePermissionService,
|
SpacePermissionService,
|
||||||
],
|
],
|
||||||
|
@ -20,14 +20,6 @@ export class AddCommunityDto {
|
|||||||
@IsOptional()
|
@IsOptional()
|
||||||
public description?: string;
|
public description?: string;
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
description: 'The UUID of the region this community belongs to',
|
|
||||||
example: 'b6fa62c5-4fcf-4872-89a0-571cf431a6c7',
|
|
||||||
})
|
|
||||||
@IsUUID()
|
|
||||||
@IsNotEmpty()
|
|
||||||
public regionId: string;
|
|
||||||
|
|
||||||
constructor(dto: Partial<AddCommunityDto>) {
|
constructor(dto: Partial<AddCommunityDto>) {
|
||||||
Object.assign(this, dto);
|
Object.assign(this, dto);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
|
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
|
||||||
import { AddCommunityDto } from '../dtos';
|
import { AddCommunityDto } from '../dtos';
|
||||||
import { UpdateCommunityNameDto } from '../dtos/update.community.dto';
|
import { UpdateCommunityNameDto } from '../dtos/update.community.dto';
|
||||||
import { RegionRepository } from '@app/common/modules/region/repositories';
|
|
||||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||||
import {
|
import {
|
||||||
TypeORMCustomModel,
|
TypeORMCustomModel,
|
||||||
@ -11,23 +10,25 @@ import { PageResponse } from '@app/common/dto/pagination.response.dto';
|
|||||||
import { CommunityRepository } from '@app/common/modules/community/repositories';
|
import { CommunityRepository } from '@app/common/modules/community/repositories';
|
||||||
import { CommunityDto } from '@app/common/modules/community/dtos';
|
import { CommunityDto } from '@app/common/modules/community/dtos';
|
||||||
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
||||||
|
import { TuyaService } from '@app/common/integrations/tuya/tuya.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CommunityService {
|
export class CommunityService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly communityRepository: CommunityRepository,
|
private readonly communityRepository: CommunityRepository,
|
||||||
private readonly regionRepository: RegionRepository,
|
private readonly tuyaService: TuyaService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async createCommunity(dto: AddCommunityDto): Promise<BaseResponseDto> {
|
async createCommunity(dto: AddCommunityDto): Promise<BaseResponseDto> {
|
||||||
const { regionId, name, description } = dto;
|
const { name, description } = dto;
|
||||||
// Find the region by the provided regionId
|
|
||||||
const region = await this.regionRepository.findOneBy({ uuid: regionId });
|
|
||||||
|
|
||||||
if (!region) {
|
const existingCommunity = await this.communityRepository.findOneBy({
|
||||||
|
name,
|
||||||
|
});
|
||||||
|
if (existingCommunity) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
`Region with ID ${dto.regionId} not found.`,
|
`A community with the name '${name}' already exists.`,
|
||||||
HttpStatus.NOT_FOUND,
|
HttpStatus.BAD_REQUEST,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,11 +36,12 @@ export class CommunityService {
|
|||||||
const community = this.communityRepository.create({
|
const community = this.communityRepository.create({
|
||||||
name: name,
|
name: name,
|
||||||
description: description,
|
description: description,
|
||||||
region: region, // Associate with the found region
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Save the community to the database
|
// Save the community to the database
|
||||||
try {
|
try {
|
||||||
|
const externalId = await this.createTuyaSpace(name);
|
||||||
|
community.externalId = externalId;
|
||||||
await this.communityRepository.save(community);
|
await this.communityRepository.save(community);
|
||||||
return new SuccessResponseDto({
|
return new SuccessResponseDto({
|
||||||
statusCode: HttpStatus.CREATED,
|
statusCode: HttpStatus.CREATED,
|
||||||
@ -52,13 +54,15 @@ export class CommunityService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getCommunityById(id: string): Promise<BaseResponseDto> {
|
async getCommunityById(communityUuid: string): Promise<BaseResponseDto> {
|
||||||
const community = await this.communityRepository.findOneBy({ uuid: id });
|
const community = await this.communityRepository.findOneBy({
|
||||||
|
uuid: communityUuid,
|
||||||
|
});
|
||||||
|
|
||||||
// If the community is not found, throw a 404 NotFoundException
|
// If the community is not found, throw a 404 NotFoundException
|
||||||
if (!community) {
|
if (!community) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
`Community with ID ${id} not found.`,
|
`Community with ID ${communityUuid} not found.`,
|
||||||
HttpStatus.NOT_FOUND,
|
HttpStatus.NOT_FOUND,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -87,17 +91,17 @@ export class CommunityService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async updateCommunity(
|
async updateCommunity(
|
||||||
id: string,
|
communityUuid: string,
|
||||||
updateCommunityDto: UpdateCommunityNameDto,
|
updateCommunityDto: UpdateCommunityNameDto,
|
||||||
): Promise<BaseResponseDto> {
|
): Promise<BaseResponseDto> {
|
||||||
const community = await this.communityRepository.findOne({
|
const community = await this.communityRepository.findOne({
|
||||||
where: { uuid: id },
|
where: { uuid: communityUuid },
|
||||||
});
|
});
|
||||||
|
|
||||||
// If the community doesn't exist, throw a 404 error
|
// If the community doesn't exist, throw a 404 error
|
||||||
if (!community) {
|
if (!community) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
`Community with ID ${id} not found`,
|
`Community with ID ${communityUuid} not found`,
|
||||||
HttpStatus.NOT_FOUND,
|
HttpStatus.NOT_FOUND,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -129,15 +133,15 @@ export class CommunityService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteCommunity(id: string): Promise<BaseResponseDto> {
|
async deleteCommunity(communityUuid: string): Promise<BaseResponseDto> {
|
||||||
const community = await this.communityRepository.findOne({
|
const community = await this.communityRepository.findOne({
|
||||||
where: { uuid: id },
|
where: { uuid: communityUuid },
|
||||||
});
|
});
|
||||||
|
|
||||||
// If the community is not found, throw an error
|
// If the community is not found, throw an error
|
||||||
if (!community) {
|
if (!community) {
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
`Community with ID ${id} not found`,
|
`Community with ID ${communityUuid} not found`,
|
||||||
HttpStatus.NOT_FOUND,
|
HttpStatus.NOT_FOUND,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -145,11 +149,10 @@ export class CommunityService {
|
|||||||
// Find the community by its uuid
|
// Find the community by its uuid
|
||||||
|
|
||||||
// Remove the community from the database
|
// Remove the community from the database
|
||||||
await this.communityRepository.remove(community);
|
|
||||||
|
|
||||||
// Return success response
|
// Return success response
|
||||||
return new SuccessResponseDto({
|
return new SuccessResponseDto({
|
||||||
message: `Community with ID ${id} successfully deleted`,
|
message: `Community with ID ${communityUuid} successfully deleted`,
|
||||||
data: null,
|
data: null,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -164,4 +167,16 @@ export class CommunityService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async createTuyaSpace(name: string): Promise<string> {
|
||||||
|
try {
|
||||||
|
const response = await this.tuyaService.createSpace({ name });
|
||||||
|
return response;
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException(
|
||||||
|
'Failed to create a Tuya space',
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user