mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-16 02:36:19 +00:00
add get All api for dashboard & mobile
This commit is contained in:
@ -103,6 +103,11 @@ export class ControllerRoute {
|
||||
|
||||
public static readonly GET_ALL_BOOKINGS_DESCRIPTION =
|
||||
'This endpoint retrieves all bookings.';
|
||||
|
||||
public static readonly GET_MY_BOOKINGS_SUMMARY = 'Get my bookings';
|
||||
|
||||
public static readonly GET_MY_BOOKINGS_DESCRIPTION =
|
||||
'This endpoint retrieves all bookings for the authenticated user.';
|
||||
};
|
||||
};
|
||||
static COMMUNITY = class {
|
||||
|
@ -2,11 +2,24 @@ import { ControllerRoute } from '@app/common/constants/controller-route';
|
||||
import { EnableDisableStatusEnum } from '@app/common/constants/days.enum';
|
||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
||||
import { Body, Controller, Post, Req, UseGuards } from '@nestjs/common';
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Query,
|
||||
Req,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
|
||||
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
||||
import { plainToInstance } from 'class-transformer';
|
||||
import { AdminRoleGuard } from 'src/guards/admin.role.guard';
|
||||
import { BookingRequestDto } from '../dtos/booking-request.dto';
|
||||
import { BookingResponseDto } from '../dtos/booking-response.dto';
|
||||
import { CreateBookingDto } from '../dtos/create-booking.dto';
|
||||
import { MyBookingRequestDto } from '../dtos/my-booking-request.dto';
|
||||
import { BookingService } from '../services/booking.service';
|
||||
|
||||
@ApiTags('Booking Module')
|
||||
@ -39,38 +52,56 @@ export class BookingController {
|
||||
});
|
||||
}
|
||||
|
||||
// @ApiBearerAuth()
|
||||
// @UseGuards(JwtAuthGuard)
|
||||
// @Get()
|
||||
// @ApiOperation({
|
||||
// summary:
|
||||
// ControllerRoute.BOOKABLE_SPACES.ACTIONS.GET_ALL_BOOKABLE_SPACES_SUMMARY,
|
||||
// description:
|
||||
// ControllerRoute.BOOKABLE_SPACES.ACTIONS
|
||||
// .GET_ALL_BOOKABLE_SPACES_DESCRIPTION,
|
||||
// })
|
||||
// async findAll(
|
||||
// @Query() query: BookableSpaceRequestDto,
|
||||
// @Req() req: Request,
|
||||
// ): Promise<PageResponse<BookableSpaceResponseDto>> {
|
||||
// const project = req['user']?.project?.uuid;
|
||||
// if (!project) {
|
||||
// throw new Error('Project UUID is required in the request');
|
||||
// }
|
||||
// const { data, pagination } = await this.bookableSpaceService.findAll(
|
||||
// query,
|
||||
// project,
|
||||
// );
|
||||
// return new PageResponse<BookableSpaceResponseDto>(
|
||||
// {
|
||||
// data: data.map((space) =>
|
||||
// plainToInstance(BookableSpaceResponseDto, space, {
|
||||
// excludeExtraneousValues: true,
|
||||
// }),
|
||||
// ),
|
||||
// message: 'Successfully fetched all bookable spaces',
|
||||
// },
|
||||
// pagination,
|
||||
// );
|
||||
// }
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(AdminRoleGuard)
|
||||
@Get()
|
||||
@ApiOperation({
|
||||
summary: ControllerRoute.BOOKING.ACTIONS.GET_ALL_BOOKINGS_SUMMARY,
|
||||
description: ControllerRoute.BOOKING.ACTIONS.GET_ALL_BOOKINGS_DESCRIPTION,
|
||||
})
|
||||
async findAll(
|
||||
@Query() query: BookingRequestDto,
|
||||
@Req() req: Request,
|
||||
): Promise<BaseResponseDto> {
|
||||
const project = req['user']?.project?.uuid;
|
||||
if (!project) {
|
||||
throw new Error('Project UUID is required in the request');
|
||||
}
|
||||
const result = await this.bookingService.findAll(query, project);
|
||||
return new SuccessResponseDto({
|
||||
data: plainToInstance(BookingResponseDto, result, {
|
||||
excludeExtraneousValues: true,
|
||||
}),
|
||||
message: 'Successfully fetched all bookings',
|
||||
});
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Get('my-bookings')
|
||||
@ApiOperation({
|
||||
summary: ControllerRoute.BOOKING.ACTIONS.GET_MY_BOOKINGS_SUMMARY,
|
||||
description: ControllerRoute.BOOKING.ACTIONS.GET_MY_BOOKINGS_DESCRIPTION,
|
||||
})
|
||||
async findMyBookings(
|
||||
@Query() query: MyBookingRequestDto,
|
||||
@Req() req: Request,
|
||||
): Promise<BaseResponseDto> {
|
||||
const userUuid = req['user']?.uuid;
|
||||
const project = req['user']?.project?.uuid;
|
||||
if (!project) {
|
||||
throw new Error('Project UUID is required in the request');
|
||||
}
|
||||
const result = await this.bookingService.findMyBookings(
|
||||
query,
|
||||
userUuid,
|
||||
project,
|
||||
);
|
||||
return new SuccessResponseDto({
|
||||
data: plainToInstance(BookingResponseDto, result, {
|
||||
excludeExtraneousValues: true,
|
||||
}),
|
||||
message: 'Successfully fetched all bookings',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
14
src/booking/dtos/booking-request.dto.ts
Normal file
14
src/booking/dtos/booking-request.dto.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNotEmpty, Matches } from 'class-validator';
|
||||
|
||||
export class BookingRequestDto {
|
||||
@ApiProperty({
|
||||
description: 'Month in MM/YYYY format',
|
||||
example: '07/2025',
|
||||
})
|
||||
@IsNotEmpty()
|
||||
@Matches(/^(0[1-9]|1[0-2])\/\d{4}$/, {
|
||||
message: 'Date must be in MM/YYYY format',
|
||||
})
|
||||
month: string;
|
||||
}
|
90
src/booking/dtos/booking-response.dto.ts
Normal file
90
src/booking/dtos/booking-response.dto.ts
Normal file
@ -0,0 +1,90 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { Expose, Transform, Type } from 'class-transformer';
|
||||
|
||||
export class BookingUserResponseDto {
|
||||
@ApiProperty()
|
||||
@Expose()
|
||||
uuid: string;
|
||||
|
||||
@ApiProperty()
|
||||
@Expose()
|
||||
firstName: string;
|
||||
|
||||
@ApiProperty()
|
||||
@Expose()
|
||||
lastName: string;
|
||||
|
||||
@ApiProperty({
|
||||
type: String,
|
||||
nullable: true,
|
||||
})
|
||||
@Expose()
|
||||
email: string;
|
||||
|
||||
@ApiProperty({
|
||||
type: String,
|
||||
nullable: true,
|
||||
})
|
||||
@Expose()
|
||||
@Transform(({ obj }) => {
|
||||
return {
|
||||
companyName: obj.inviteUser?.companyName || null,
|
||||
};
|
||||
})
|
||||
@ApiProperty({
|
||||
type: String,
|
||||
nullable: true,
|
||||
})
|
||||
@Expose()
|
||||
phoneNumber: string;
|
||||
}
|
||||
|
||||
export class BookingSpaceResponseDto {
|
||||
@ApiProperty()
|
||||
@Expose()
|
||||
uuid: string;
|
||||
|
||||
@ApiProperty()
|
||||
@Expose()
|
||||
spaceName: string;
|
||||
}
|
||||
|
||||
export class BookingResponseDto {
|
||||
@ApiProperty()
|
||||
@Expose()
|
||||
uuid: string;
|
||||
|
||||
@ApiProperty({
|
||||
type: Date,
|
||||
})
|
||||
@Expose()
|
||||
date: Date;
|
||||
|
||||
@ApiProperty()
|
||||
@Expose()
|
||||
startTime: string;
|
||||
|
||||
@ApiProperty()
|
||||
@Expose()
|
||||
endTime: string;
|
||||
|
||||
@ApiProperty({
|
||||
type: Number,
|
||||
})
|
||||
@Expose()
|
||||
cost: number;
|
||||
|
||||
@ApiProperty({
|
||||
type: BookingUserResponseDto,
|
||||
})
|
||||
@Type(() => BookingUserResponseDto)
|
||||
@Expose()
|
||||
user: BookingUserResponseDto;
|
||||
|
||||
@ApiProperty({
|
||||
type: BookingSpaceResponseDto,
|
||||
})
|
||||
@Type(() => BookingSpaceResponseDto)
|
||||
@Expose()
|
||||
space: BookingSpaceResponseDto;
|
||||
}
|
14
src/booking/dtos/my-booking-request.dto.ts
Normal file
14
src/booking/dtos/my-booking-request.dto.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsIn, IsOptional } from 'class-validator';
|
||||
|
||||
export class MyBookingRequestDto {
|
||||
@ApiProperty({
|
||||
description: 'Filter bookings by time period',
|
||||
example: 'past',
|
||||
enum: ['past', 'future'],
|
||||
required: false,
|
||||
})
|
||||
@IsOptional()
|
||||
@IsIn(['past', 'future'])
|
||||
when?: 'past' | 'future';
|
||||
}
|
@ -11,7 +11,10 @@ import {
|
||||
Injectable,
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { Between } from 'typeorm/find-options/operator/Between';
|
||||
import { BookingRequestDto } from '../dtos/booking-request.dto';
|
||||
import { CreateBookingDto } from '../dtos/create-booking.dto';
|
||||
import { MyBookingRequestDto } from '../dtos/my-booking-request.dto';
|
||||
|
||||
@Injectable()
|
||||
export class BookingService {
|
||||
@ -46,52 +49,39 @@ export class BookingService {
|
||||
return this.createBookings(space, userUuid, dto);
|
||||
}
|
||||
|
||||
// async findAll(
|
||||
// { active, page, size, configured, search }: BookingRequestDto,
|
||||
// project: string,
|
||||
// ): Promise<{
|
||||
// data: BaseResponseDto['data'];
|
||||
// pagination: PageResponseDto;
|
||||
// }> {
|
||||
// let qb = this.spaceRepository
|
||||
// .createQueryBuilder('space')
|
||||
// .leftJoinAndSelect('space.parent', 'parentSpace')
|
||||
// .leftJoinAndSelect('space.community', 'community')
|
||||
// .where('community.project = :project', { project });
|
||||
async findAll({ month }: BookingRequestDto, project: string) {
|
||||
const [monthNumber, year] = month.split('/').map(Number);
|
||||
const fromDate = new Date(year, monthNumber - 1, 1);
|
||||
const toDate = new Date(year, monthNumber, 0, 23, 59, 59);
|
||||
return this.bookingEntityRepository.find({
|
||||
where: {
|
||||
space: { community: { project: { uuid: project } } },
|
||||
date: Between(fromDate, toDate),
|
||||
},
|
||||
relations: ['space', 'user', 'user.inviteUser'],
|
||||
order: { date: 'DESC' },
|
||||
});
|
||||
}
|
||||
|
||||
// if (search) {
|
||||
// qb = qb.andWhere(
|
||||
// 'space.spaceName ILIKE :search OR community.name ILIKE :search OR parentSpace.spaceName ILIKE :search',
|
||||
// { search: `%${search}%` },
|
||||
// );
|
||||
// }
|
||||
// if (configured) {
|
||||
// qb = qb
|
||||
// .leftJoinAndSelect('space.bookableConfig', 'bookableConfig')
|
||||
// .andWhere('bookableConfig.uuid IS NOT NULL');
|
||||
// if (active !== undefined) {
|
||||
// qb = qb.andWhere('bookableConfig.active = :active', { active });
|
||||
// }
|
||||
// } else {
|
||||
// qb = qb
|
||||
// .leftJoinAndSelect('space.bookableConfig', 'bookableConfig')
|
||||
// .andWhere('bookableConfig.uuid IS NULL');
|
||||
// }
|
||||
|
||||
// const customModel = TypeORMCustomModel(this.spaceRepository);
|
||||
|
||||
// const { baseResponseDto, paginationResponseDto } =
|
||||
// await customModel.findAll({ page, size, modelName: 'space' }, qb);
|
||||
// return {
|
||||
// data: baseResponseDto.data.map((space) => {
|
||||
// return {
|
||||
// ...space,
|
||||
// virtualLocation: `${space.community?.name} - ${space.parent ? space.parent?.spaceName + ' - ' : ''}${space.spaceName}`,
|
||||
// };
|
||||
// }),
|
||||
// pagination: paginationResponseDto,
|
||||
// };
|
||||
// }
|
||||
async findMyBookings(
|
||||
{ when }: MyBookingRequestDto,
|
||||
userUuid: string,
|
||||
project: string,
|
||||
) {
|
||||
return this.bookingEntityRepository.find({
|
||||
where: {
|
||||
user: { uuid: userUuid },
|
||||
space: { community: { project: { uuid: project } } },
|
||||
// date: when
|
||||
// ? when === 'past'
|
||||
// ? LessThanOrEqual(new Date())
|
||||
// : MoreThanOrEqual(new Date())
|
||||
// : undefined,
|
||||
},
|
||||
relations: ['space', 'user'],
|
||||
order: { date: 'DESC' },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch space by UUID and throw an error if not found or if not configured for booking
|
||||
|
Reference in New Issue
Block a user