mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-10 15:17:41 +00:00
Compare commits
16 Commits
refactor/a
...
b2fb378e52
Author | SHA1 | Date | |
---|---|---|---|
b2fb378e52 | |||
c5f8f96977 | |||
0b9eef276e | |||
b3f8b92826 | |||
5d4e5ca87e | |||
f4e748d735 | |||
f4f7999ae0 | |||
82c82d521c | |||
d3d84da5e3 | |||
49cc762962 | |||
a94d4610ed | |||
274cdf741f | |||
df59e9a4a3 | |||
8c34c68ba6 | |||
332b2f5851 | |||
8d44b66dd3 |
@ -69,7 +69,16 @@ export class ControllerRoute {
|
||||
'Retrieve the list of all regions registered in Syncrow.';
|
||||
};
|
||||
};
|
||||
static BOOKABLE_SPACES = class {
|
||||
public static readonly ROUTE = 'bookable-spaces';
|
||||
static ACTIONS = class {
|
||||
public static readonly ADD_BOOKABLE_SPACES_SUMMARY =
|
||||
'Add new bookable spaces';
|
||||
|
||||
public static readonly ADD_BOOKABLE_SPACES_DESCRIPTION =
|
||||
'This endpoint allows you to add new bookable spaces by providing the required details.';
|
||||
};
|
||||
};
|
||||
static COMMUNITY = class {
|
||||
public static readonly ROUTE = '/projects/:projectUuid/communities';
|
||||
static ACTIONS = class {
|
||||
|
@ -58,6 +58,7 @@ import {
|
||||
UserSpaceEntity,
|
||||
} from '../modules/user/entities';
|
||||
import { VisitorPasswordEntity } from '../modules/visitor-password/entities';
|
||||
import { BookableSpaceEntity } from '../modules/booking/entities';
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forRootAsync({
|
||||
@ -117,6 +118,7 @@ import { VisitorPasswordEntity } from '../modules/visitor-password/entities';
|
||||
PresenceSensorDailySpaceEntity,
|
||||
AqiSpaceDailyPollutantStatsEntity,
|
||||
SpaceDailyOccupancyDurationEntity,
|
||||
BookableSpaceEntity,
|
||||
],
|
||||
namingStrategy: new SnakeNamingStrategy(),
|
||||
synchronize: Boolean(JSON.parse(configService.get('DB_SYNC'))),
|
||||
|
5
libs/common/src/helper/timeToMinutes.ts
Normal file
5
libs/common/src/helper/timeToMinutes.ts
Normal file
@ -0,0 +1,5 @@
|
||||
// Convert time string (HH:mm) to minutes
|
||||
export function timeToMinutes(time: string): number {
|
||||
const [hours, minutes] = time.split(':').map(Number);
|
||||
return hours * 60 + minutes;
|
||||
}
|
11
libs/common/src/modules/booking/booking.repository.module.ts
Normal file
11
libs/common/src/modules/booking/booking.repository.module.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { BookableSpaceEntity } from './entities/bookable-space.entity';
|
||||
|
||||
@Module({
|
||||
providers: [],
|
||||
exports: [],
|
||||
controllers: [],
|
||||
imports: [TypeOrmModule.forFeature([BookableSpaceEntity])],
|
||||
})
|
||||
export class BookableRepositoryModule {}
|
@ -0,0 +1,48 @@
|
||||
import {
|
||||
Entity,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
OneToOne,
|
||||
JoinColumn,
|
||||
} from 'typeorm';
|
||||
import { SpaceEntity } from '../../space/entities/space.entity';
|
||||
import { DaysEnum } from '@app/common/constants/days.enum';
|
||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||
|
||||
@Entity('bookable-space')
|
||||
export class BookableSpaceEntity extends AbstractEntity {
|
||||
@Column({
|
||||
type: 'uuid',
|
||||
default: () => 'gen_random_uuid()',
|
||||
nullable: false,
|
||||
})
|
||||
public uuid: string;
|
||||
|
||||
@OneToOne(() => SpaceEntity, (space) => space.bookableConfig)
|
||||
@JoinColumn({ name: 'space_uuid' })
|
||||
space: SpaceEntity;
|
||||
|
||||
@Column({
|
||||
type: 'enum',
|
||||
enum: DaysEnum,
|
||||
array: true,
|
||||
nullable: false,
|
||||
})
|
||||
daysAvailable: DaysEnum[];
|
||||
|
||||
@Column({ type: 'time' })
|
||||
startTime: string;
|
||||
|
||||
@Column({ type: 'time' })
|
||||
endTime: string;
|
||||
|
||||
@Column({ type: 'int' })
|
||||
points: number;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn()
|
||||
updatedAt: Date;
|
||||
}
|
1
libs/common/src/modules/booking/entities/index.ts
Normal file
1
libs/common/src/modules/booking/entities/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './bookable-space.entity';
|
@ -0,0 +1,10 @@
|
||||
import { DataSource, Repository } from 'typeorm';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { BookableSpaceEntity } from '../entities/bookable-space.entity';
|
||||
|
||||
@Injectable()
|
||||
export class BookableSpaceEntityRepository extends Repository<BookableSpaceEntity> {
|
||||
constructor(private dataSource: DataSource) {
|
||||
super(BookableSpaceEntity, dataSource.createEntityManager());
|
||||
}
|
||||
}
|
1
libs/common/src/modules/booking/repositories/index.ts
Normal file
1
libs/common/src/modules/booking/repositories/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './booking.repository';
|
@ -1,4 +1,12 @@
|
||||
import { Column, Entity, JoinColumn, ManyToOne, OneToMany } from 'typeorm';
|
||||
import {
|
||||
Column,
|
||||
Entity,
|
||||
JoinColumn,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
OneToOne,
|
||||
} from 'typeorm';
|
||||
import { SpaceDto } from '../dtos';
|
||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||
import { AqiSpaceDailyPollutantStatsEntity } from '../../aqi/entities';
|
||||
import { CommunityEntity } from '../../community/entities';
|
||||
@ -9,9 +17,9 @@ import { PresenceSensorDailySpaceEntity } from '../../presence-sensor/entities';
|
||||
import { SceneEntity } from '../../scene/entities';
|
||||
import { SpaceModelEntity } from '../../space-model';
|
||||
import { UserSpaceEntity } from '../../user/entities';
|
||||
import { SpaceDto } from '../dtos';
|
||||
import { SpaceProductAllocationEntity } from './space-product-allocation.entity';
|
||||
import { SubspaceEntity } from './subspace/subspace.entity';
|
||||
import { BookableSpaceEntity } from '../../booking/entities';
|
||||
|
||||
@Entity({ name: 'space' })
|
||||
export class SpaceEntity extends AbstractEntity<SpaceDto> {
|
||||
@ -115,6 +123,9 @@ export class SpaceEntity extends AbstractEntity<SpaceDto> {
|
||||
)
|
||||
occupancyDaily: SpaceDailyOccupancyDurationEntity[];
|
||||
|
||||
@OneToOne(() => BookableSpaceEntity, (bookable) => bookable.space)
|
||||
bookableConfig: BookableSpaceEntity;
|
||||
|
||||
constructor(partial: Partial<SpaceEntity>) {
|
||||
super();
|
||||
Object.assign(this, partial);
|
||||
|
@ -44,6 +44,7 @@ import { OccupancyModule } from './occupancy/occupancy.module';
|
||||
import { WeatherModule } from './weather/weather.module';
|
||||
import { ScheduleModule as NestScheduleModule } from '@nestjs/schedule';
|
||||
import { SchedulerModule } from './scheduler/scheduler.module';
|
||||
import { BookingModule } from './booking';
|
||||
@Module({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
@ -98,6 +99,7 @@ import { SchedulerModule } from './scheduler/scheduler.module';
|
||||
AqiModule,
|
||||
SchedulerModule,
|
||||
NestScheduleModule.forRoot(),
|
||||
BookingModule,
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
|
17
src/booking/booking.module.ts
Normal file
17
src/booking/booking.module.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { Global, Module } from '@nestjs/common';
|
||||
import { BookableSpaceController } from './controllers';
|
||||
import { BookableSpaceService } from './services';
|
||||
import { BookableSpaceEntityRepository } from '@app/common/modules/booking/repositories';
|
||||
import { SpaceRepository } from '@app/common/modules/space';
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
controllers: [BookableSpaceController],
|
||||
providers: [
|
||||
BookableSpaceService,
|
||||
BookableSpaceEntityRepository,
|
||||
SpaceRepository,
|
||||
],
|
||||
exports: [BookableSpaceService],
|
||||
})
|
||||
export class BookingModule {}
|
30
src/booking/controllers/bookable-space.controller.ts
Normal file
30
src/booking/controllers/bookable-space.controller.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { Body, Controller, Post, UseGuards } from '@nestjs/common';
|
||||
import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger';
|
||||
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
||||
import { EnableDisableStatusEnum } from '@app/common/constants/days.enum';
|
||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||
import { ControllerRoute } from '@app/common/constants/controller-route';
|
||||
|
||||
import { CreateBookableSpaceDto } from '../dtos';
|
||||
import { BookableSpaceService } from '../services';
|
||||
|
||||
@ApiTags('Booking Module')
|
||||
@Controller({
|
||||
version: EnableDisableStatusEnum.ENABLED,
|
||||
path: ControllerRoute.BOOKABLE_SPACES.ROUTE,
|
||||
})
|
||||
export class BookableSpaceController {
|
||||
constructor(private readonly bookableSpaceService: BookableSpaceService) {}
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post()
|
||||
@ApiOperation({
|
||||
summary:
|
||||
ControllerRoute.BOOKABLE_SPACES.ACTIONS.ADD_BOOKABLE_SPACES_SUMMARY,
|
||||
description:
|
||||
ControllerRoute.BOOKABLE_SPACES.ACTIONS.ADD_BOOKABLE_SPACES_DESCRIPTION,
|
||||
})
|
||||
async create(@Body() dto: CreateBookableSpaceDto): Promise<BaseResponseDto> {
|
||||
return this.bookableSpaceService.create(dto);
|
||||
}
|
||||
}
|
1
src/booking/controllers/index.ts
Normal file
1
src/booking/controllers/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './bookable-space.controller';
|
62
src/booking/dtos/create-bookable-space.dto.ts
Normal file
62
src/booking/dtos/create-bookable-space.dto.ts
Normal file
@ -0,0 +1,62 @@
|
||||
// dtos/bookable-space.dto.ts
|
||||
import { DaysEnum } from '@app/common/constants/days.enum';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import {
|
||||
IsArray,
|
||||
IsEnum,
|
||||
IsNotEmpty,
|
||||
IsString,
|
||||
IsUUID,
|
||||
IsInt,
|
||||
ArrayMinSize,
|
||||
Max,
|
||||
Min,
|
||||
Matches,
|
||||
} from 'class-validator';
|
||||
|
||||
export class CreateBookableSpaceDto {
|
||||
@ApiProperty({
|
||||
type: 'string',
|
||||
isArray: true,
|
||||
example: [
|
||||
'3fa85f64-5717-4562-b3fc-2c963f66afa6',
|
||||
'4fa85f64-5717-4562-b3fc-2c963f66afa7',
|
||||
],
|
||||
})
|
||||
@IsArray()
|
||||
@ArrayMinSize(1, { message: 'At least one space must be selected' })
|
||||
@IsUUID('all', { each: true, message: 'Invalid space UUID provided' })
|
||||
spaceUuids: string[];
|
||||
|
||||
@ApiProperty({
|
||||
enum: DaysEnum,
|
||||
isArray: true,
|
||||
example: [DaysEnum.MON, DaysEnum.WED, DaysEnum.FRI],
|
||||
})
|
||||
@IsArray()
|
||||
@ArrayMinSize(1, { message: 'At least one day must be selected' })
|
||||
@IsEnum(DaysEnum, { each: true, message: 'Invalid day provided' })
|
||||
daysAvailable: DaysEnum[];
|
||||
|
||||
@ApiProperty({ example: '09:00' })
|
||||
@IsString()
|
||||
@IsNotEmpty({ message: 'Start time cannot be empty' })
|
||||
@Matches(/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/, {
|
||||
message: 'Start time must be in HH:mm format (24-hour)',
|
||||
})
|
||||
startTime: string;
|
||||
|
||||
@ApiProperty({ example: '17:00' })
|
||||
@IsString()
|
||||
@IsNotEmpty({ message: 'End time cannot be empty' })
|
||||
@Matches(/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/, {
|
||||
message: 'End time must be in HH:mm format (24-hour)',
|
||||
})
|
||||
endTime: string;
|
||||
|
||||
@ApiProperty({ example: 10 })
|
||||
@IsInt()
|
||||
@Min(0, { message: 'Points cannot be negative' })
|
||||
@Max(1000, { message: 'Points cannot exceed 1000' })
|
||||
points: number;
|
||||
}
|
1
src/booking/dtos/index.ts
Normal file
1
src/booking/dtos/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './create-bookable-space.dto';
|
1
src/booking/index.ts
Normal file
1
src/booking/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './booking.module';
|
127
src/booking/services/bookable-space.service.ts
Normal file
127
src/booking/services/bookable-space.service.ts
Normal file
@ -0,0 +1,127 @@
|
||||
import {
|
||||
Injectable,
|
||||
NotFoundException,
|
||||
ConflictException,
|
||||
BadRequestException,
|
||||
} from '@nestjs/common';
|
||||
import { CreateBookableSpaceDto } from '../dtos';
|
||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
||||
import { SpaceEntity } from '@app/common/modules/space/entities/space.entity';
|
||||
import { BookableSpaceEntityRepository } from '@app/common/modules/booking/repositories';
|
||||
import { SpaceRepository } from '@app/common/modules/space/repositories/space.repository';
|
||||
import { In } from 'typeorm';
|
||||
import { timeToMinutes } from '@app/common/helper/timeToMinutes';
|
||||
|
||||
@Injectable()
|
||||
export class BookableSpaceService {
|
||||
constructor(
|
||||
private readonly bookableSpaceEntityRepository: BookableSpaceEntityRepository,
|
||||
private readonly spaceRepository: SpaceRepository,
|
||||
) {}
|
||||
|
||||
async create(dto: CreateBookableSpaceDto): Promise<BaseResponseDto> {
|
||||
// Validate time slots first
|
||||
this.validateTimeSlot(dto.startTime, dto.endTime);
|
||||
|
||||
// fetch spaces exist
|
||||
const spaces = await this.getSpacesOrFindMissing(dto.spaceUuids);
|
||||
|
||||
// Validate no duplicate bookable configurations
|
||||
await this.validateNoDuplicateBookableConfigs(dto.spaceUuids);
|
||||
|
||||
// Create and save bookable spaces
|
||||
return this.createBookableSpaces(spaces, dto);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch spaces by UUIDs and throw an error if any are missing
|
||||
*/
|
||||
private async getSpacesOrFindMissing(
|
||||
spaceUuids: string[],
|
||||
): Promise<SpaceEntity[]> {
|
||||
const spaces = await this.spaceRepository.find({
|
||||
where: { uuid: In(spaceUuids) },
|
||||
});
|
||||
|
||||
if (spaces.length !== spaceUuids.length) {
|
||||
const foundUuids = spaces.map((s) => s.uuid);
|
||||
const missingUuids = spaceUuids.filter(
|
||||
(uuid) => !foundUuids.includes(uuid),
|
||||
);
|
||||
throw new NotFoundException(
|
||||
`Spaces not found: ${missingUuids.join(', ')}`,
|
||||
);
|
||||
}
|
||||
|
||||
return spaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate there are no existing bookable configurations for these spaces
|
||||
*/
|
||||
private async validateNoDuplicateBookableConfigs(
|
||||
spaceUuids: string[],
|
||||
): Promise<void> {
|
||||
const existingBookables = await this.bookableSpaceEntityRepository.find({
|
||||
where: { space: { uuid: In(spaceUuids) } },
|
||||
relations: ['space'],
|
||||
});
|
||||
|
||||
if (existingBookables.length > 0) {
|
||||
const existingUuids = [
|
||||
...new Set(existingBookables.map((b) => b.space.uuid)),
|
||||
];
|
||||
throw new ConflictException(
|
||||
`Bookable configuration already exists for spaces: ${existingUuids.join(', ')}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the slot start time is before the end time
|
||||
*/
|
||||
private validateTimeSlot(startTime: string, endTime: string): void {
|
||||
const start = timeToMinutes(startTime);
|
||||
const end = timeToMinutes(endTime);
|
||||
|
||||
if (start >= end) {
|
||||
throw new BadRequestException(
|
||||
`End time must be after start time for slot: ${startTime}-${endTime}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create bookable space entries after all validations pass
|
||||
*/
|
||||
private async createBookableSpaces(
|
||||
spaces: SpaceEntity[],
|
||||
dto: CreateBookableSpaceDto,
|
||||
): Promise<BaseResponseDto> {
|
||||
try {
|
||||
const entries = spaces.map((space) =>
|
||||
this.bookableSpaceEntityRepository.create({
|
||||
space,
|
||||
daysAvailable: dto.daysAvailable,
|
||||
startTime: dto.startTime,
|
||||
endTime: dto.endTime,
|
||||
points: dto.points,
|
||||
}),
|
||||
);
|
||||
|
||||
const data = await this.bookableSpaceEntityRepository.save(entries);
|
||||
return new SuccessResponseDto({
|
||||
data,
|
||||
message: 'Successfully added new bookable spaces',
|
||||
});
|
||||
} catch (error) {
|
||||
if (error.code === '23505') {
|
||||
throw new ConflictException(
|
||||
'Duplicate bookable space configuration detected',
|
||||
);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
1
src/booking/services/index.ts
Normal file
1
src/booking/services/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './bookable-space.service';
|
@ -3,6 +3,7 @@ import * as fs from 'fs';
|
||||
|
||||
import { ProjectParam } from '@app/common/dto/project-param.dto';
|
||||
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
||||
import { DeviceStatusFirebaseService } from '@app/common/firebase/devices-status/services/devices-status.service';
|
||||
import { TuyaService } from '@app/common/integrations/tuya/services/tuya.service';
|
||||
import { CommunityRepository } from '@app/common/modules/community/repositories';
|
||||
import { DeviceRepository } from '@app/common/modules/device/repositories';
|
||||
@ -20,6 +21,7 @@ export class DeviceCommissionService {
|
||||
constructor(
|
||||
private readonly tuyaService: TuyaService,
|
||||
private readonly deviceService: DeviceService,
|
||||
private readonly deviceStatusFirebaseService: DeviceStatusFirebaseService,
|
||||
private readonly communityRepository: CommunityRepository,
|
||||
private readonly spaceRepository: SpaceRepository,
|
||||
private readonly subspaceRepository: SubspaceRepository,
|
||||
@ -209,6 +211,10 @@ export class DeviceCommissionService {
|
||||
rawDeviceId,
|
||||
tuyaSpaceId,
|
||||
);
|
||||
|
||||
await this.deviceStatusFirebaseService.addDeviceStatusByDeviceUuid(
|
||||
rawDeviceId,
|
||||
);
|
||||
successCount.value++;
|
||||
console.log(
|
||||
`Device ${rawDeviceId} successfully processed and transferred to Tuya space ${tuyaSpaceId}`,
|
||||
|
@ -111,6 +111,7 @@ export class InviteUserService {
|
||||
});
|
||||
|
||||
const invitedUser = await queryRunner.manager.save(inviteUser);
|
||||
const invitedRoleType = await this.getRoleTypeByUuid(roleUuid);
|
||||
|
||||
// Link user to spaces
|
||||
const spacePromises = validSpaces.map(async (space) => {
|
||||
@ -128,7 +129,7 @@ export class InviteUserService {
|
||||
await this.emailService.sendEmailWithInvitationTemplate(email, {
|
||||
name: firstName,
|
||||
invitationCode,
|
||||
role: roleType,
|
||||
role: invitedRoleType.replace(/_/g, ' '),
|
||||
spacesList: spaceNames,
|
||||
});
|
||||
|
||||
|
@ -96,6 +96,16 @@ export class ScheduleService {
|
||||
throw new HttpException('Device Not Found', HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
if (
|
||||
deviceDetails.productDevice.prodType == ProductType.CUR_2 &&
|
||||
addScheduleDto.category != 'Timer'
|
||||
) {
|
||||
throw new HttpException(
|
||||
'Invalid category for CUR_2 devices',
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
|
||||
this.ensureProductTypeSupportedForSchedule(
|
||||
deviceDetails.productDevice.prodType as ProductType,
|
||||
);
|
||||
@ -103,6 +113,7 @@ export class ScheduleService {
|
||||
await this.addScheduleDeviceInTuya(
|
||||
deviceDetails.deviceTuyaUuid,
|
||||
addScheduleDto,
|
||||
deviceDetails.productDevice.prodType as ProductType,
|
||||
);
|
||||
} catch (error) {
|
||||
throw new HttpException(
|
||||
@ -125,10 +136,14 @@ export class ScheduleService {
|
||||
const schedules = await this.getScheduleDeviceInTuya(
|
||||
deviceDetails.deviceTuyaUuid,
|
||||
category,
|
||||
deviceDetails.productDevice.prodType as ProductType,
|
||||
);
|
||||
const result = schedules.result.map((schedule: any) => {
|
||||
return {
|
||||
category: schedule.category.replace('category_', ''),
|
||||
category:
|
||||
deviceDetails.productDevice.prodType == ProductType.CUR_2
|
||||
? schedule.category
|
||||
: schedule.category.replace('category_', ''),
|
||||
enable: schedule.enable,
|
||||
function: {
|
||||
code: schedule.functions[0].code,
|
||||
@ -159,6 +174,16 @@ export class ScheduleService {
|
||||
throw new HttpException('Device Not Found', HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
if (
|
||||
deviceDetails.productDevice.prodType == ProductType.CUR_2 &&
|
||||
updateScheduleDto.category != 'Timer'
|
||||
) {
|
||||
throw new HttpException(
|
||||
'Invalid category for CUR_2 devices',
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
|
||||
// Corrected condition for supported device types
|
||||
this.ensureProductTypeSupportedForSchedule(
|
||||
deviceDetails.productDevice.prodType as ProductType,
|
||||
@ -167,6 +192,7 @@ export class ScheduleService {
|
||||
await this.updateScheduleDeviceInTuya(
|
||||
deviceDetails.deviceTuyaUuid,
|
||||
updateScheduleDto,
|
||||
deviceDetails.productDevice.prodType as ProductType,
|
||||
);
|
||||
} catch (error) {
|
||||
throw new HttpException(
|
||||
@ -192,6 +218,7 @@ export class ScheduleService {
|
||||
private async addScheduleDeviceInTuya(
|
||||
deviceId: string,
|
||||
addScheduleDto: AddScheduleDto,
|
||||
deviceType: ProductType,
|
||||
): Promise<addScheduleDeviceInterface> {
|
||||
try {
|
||||
const convertedTime = convertTimestampToDubaiTime(addScheduleDto.time);
|
||||
@ -210,7 +237,10 @@ export class ScheduleService {
|
||||
...addScheduleDto.function,
|
||||
},
|
||||
],
|
||||
category: `category_${addScheduleDto.category}`,
|
||||
category:
|
||||
deviceType == ProductType.CUR_2
|
||||
? addScheduleDto.category
|
||||
: `category_${addScheduleDto.category}`,
|
||||
},
|
||||
});
|
||||
|
||||
@ -226,9 +256,12 @@ export class ScheduleService {
|
||||
private async getScheduleDeviceInTuya(
|
||||
deviceId: string,
|
||||
category: string,
|
||||
deviceType: ProductType,
|
||||
): Promise<getDeviceScheduleInterface> {
|
||||
try {
|
||||
const path = `/v2.0/cloud/timer/device/${deviceId}?category=category_${category}`;
|
||||
const categoryToSent =
|
||||
deviceType == ProductType.CUR_2 ? category : `category_${category}`;
|
||||
const path = `/v2.0/cloud/timer/device/${deviceId}?category=${categoryToSent}`;
|
||||
const response = await this.tuya.request({
|
||||
method: 'GET',
|
||||
path,
|
||||
@ -248,6 +281,7 @@ export class ScheduleService {
|
||||
private async updateScheduleDeviceInTuya(
|
||||
deviceId: string,
|
||||
updateScheduleDto: UpdateScheduleDto,
|
||||
deviceType: ProductType,
|
||||
): Promise<addScheduleDeviceInterface> {
|
||||
try {
|
||||
const convertedTime = convertTimestampToDubaiTime(updateScheduleDto.time);
|
||||
@ -268,7 +302,10 @@ export class ScheduleService {
|
||||
value: updateScheduleDto.function.value,
|
||||
},
|
||||
],
|
||||
category: `category_${updateScheduleDto.category}`,
|
||||
category:
|
||||
deviceType == ProductType.CUR_2
|
||||
? updateScheduleDto.category
|
||||
: `category_${updateScheduleDto.category}`,
|
||||
},
|
||||
});
|
||||
|
||||
|
Reference in New Issue
Block a user