add update booking settings API

This commit is contained in:
Mhd Zayd Skaff
2025-07-27 10:22:09 +03:00
parent 331c8dffdc
commit 368e80408d
5 changed files with 109 additions and 2 deletions

View File

@ -448,6 +448,11 @@ export class ControllerRoute {
public static readonly UPDATE_NAME_DESCRIPTION =
'This endpoint updates the name for a user identified by their UUID.';
public static readonly UPDATE_BOOKING_SETTINGS_SUMMARY =
'Update booking settings by user UUID';
public static readonly UPDATE_BOOKING_SETTINGS_DESCRIPTION =
'This endpoint updates the booking settings for a user identified by their UUID.';
public static readonly DELETE_USER_SUMMARY = 'Delete user by UUID';
public static readonly DELETE_USER_DESCRIPTION =
'This endpoint deletes a user identified by their UUID. Accessible only by users with the Super Admin role.';

View File

@ -11,6 +11,7 @@ import {
} from 'typeorm';
import { OtpType } from '../../../../src/constants/otp-type.enum';
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
import { BookingEntity } from '../../booking/entities/booking.entity';
import { ClientEntity } from '../../client/entities';
import {
DeviceNotificationEntity,
@ -29,7 +30,6 @@ import {
UserOtpDto,
UserSpaceDto,
} from '../dtos';
import { BookingEntity } from '../../booking/entities/booking.entity';
@Entity({ name: 'user' })
export class UserEntity extends AbstractEntity<UserDto> {
@ -101,6 +101,9 @@ export class UserEntity extends AbstractEntity<UserDto> {
@Column({ type: 'timestamp', nullable: true })
appAgreementAcceptedAt: Date;
@Column({ type: Boolean, default: false })
bookingEnabled: boolean;
@OneToMany(() => UserSpaceEntity, (userSpace) => userSpace.user, {
onDelete: 'CASCADE',
})

View File

@ -25,6 +25,7 @@ import {
UpdateTimezoneDataDto,
} from '../dtos';
import { UserService } from '../services/user.service';
import { UpdateBookingSettingsDto } from '../dtos/update-user-booking-settings.dto';
@ApiTags('User Module')
@Controller({
@ -138,6 +139,30 @@ export class UserController {
};
}
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Put('/booking-settings/:userUuid')
@ApiOperation({
summary: ControllerRoute.USER.ACTIONS.UPDATE_BOOKING_SETTINGS_SUMMARY,
description:
ControllerRoute.USER.ACTIONS.UPDATE_BOOKING_SETTINGS_DESCRIPTION,
})
async updateBookingSettingsByUserUuid(
@Param('userUuid') userUuid: string,
@Body() dto: UpdateBookingSettingsDto,
) {
const userData = await this.userService.updateBookingSettingsByUserUuid(
userUuid,
dto,
);
return {
statusCode: HttpStatus.CREATED,
success: true,
message: 'Booking settings updated successfully',
data: userData,
};
}
@ApiBearerAuth()
@UseGuards(SuperAdminRoleGuard)
@Delete('/:userUuid')

View File

@ -0,0 +1,29 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsBoolean, IsInt, IsOptional, IsPositive, Min } from 'class-validator';
export class UpdateBookingSettingsDto {
@ApiProperty({
description: 'bookingEnable',
required: false,
})
@IsBoolean()
@IsOptional()
bookingEnable?: boolean;
@ApiProperty({
description: 'increase user booking balance by top up amount',
required: false,
})
@IsPositive()
@IsOptional()
topUp?: number;
@ApiProperty({
description: 'replace user booking balance by required amount',
required: false,
})
@IsInt()
@Min(0)
@IsOptional()
balance?: number;
}

View File

@ -10,6 +10,7 @@ import {
HttpStatus,
Injectable,
} from '@nestjs/common';
import { UpdateBookingSettingsDto } from '../dtos/update-user-booking-settings.dto';
import {
UpdateNameDto,
UpdateProfilePictureDataDto,
@ -33,7 +34,7 @@ export class UserService {
relations: ['region', 'timezone', 'roleType', 'project'],
});
if (!user) {
throw new BadRequestException('Invalid room UUID');
throw new BadRequestException('Invalid user UUID');
}
// Use the utility function to remove the base64 prefix
@ -53,6 +54,8 @@ export class UserService {
appAgreementAcceptedAt: user?.appAgreementAcceptedAt,
role: user?.roleType,
project: user?.project,
bookingPoints: user?.bookingPoints ?? 0,
bookingEnabled: user?.bookingEnabled ?? false,
};
} catch (err) {
if (err instanceof BadRequestException) {
@ -245,6 +248,48 @@ export class UserService {
);
}
}
async updateBookingSettingsByUserUuid(
userUuid: string,
{ balance, bookingEnable, topUp }: UpdateBookingSettingsDto,
) {
try {
let user = await this.getUserDetailsByUserUuid(userUuid);
if (!user) {
throw new HttpException('User not found', HttpStatus.NOT_FOUND);
}
if (balance && topUp) {
throw new BadRequestException(
'Please provide either balance or topUp, not both',
);
}
if (topUp) {
user.bookingPoints += topUp;
}
if (balance) {
user.bookingPoints = balance;
}
if (bookingEnable !== undefined) {
user.bookingEnabled = bookingEnable;
}
user = await this.userRepository.save(user);
return {
uuid: user.uuid,
bookingEnabled: user.bookingEnabled,
bookingPoints: user.bookingPoints,
};
} catch (err) {
throw new HttpException(
err.message || 'User not found',
HttpStatus.NOT_FOUND,
);
}
}
async acceptWebAgreement(userUuid: string) {
await this.userRepository.update(
{ uuid: userUuid },