diff --git a/src/common/contracts/error.ts b/src/common/contracts/error.ts index a5bdd41..d658cdb 100644 --- a/src/common/contracts/error.ts +++ b/src/common/contracts/error.ts @@ -111,4 +111,9 @@ export const Errors: Record = { message: 'Công việc được chọn không hợp lệ', httpStatus: HttpStatus.BAD_REQUEST }, + VISIT_SHOWROOM_BOOKING_NOT_FOUND: { + error: 'VISIT_SHOWROOM_BOOKING_NOT_FOUND', + message: 'Không tìm thấy lịch tham quan showroom. Vui lòng thử lại', + httpStatus: HttpStatus.BAD_REQUEST + } } diff --git a/src/visit-showroom-booking/booking.module.ts b/src/visit-showroom-booking/booking.module.ts index f0737e2..a32a122 100644 --- a/src/visit-showroom-booking/booking.module.ts +++ b/src/visit-showroom-booking/booking.module.ts @@ -7,6 +7,7 @@ import { VisitShowroomBookingCustomerController } from '@visit-showroom-booking/ import { VisitShowroomBookingService } from '@visit-showroom-booking/services/booking.service' import { VisitShowroomBookingRepository } from '@visit-showroom-booking/repositories/booking.repository' import { CustomerModule } from '@customer/customer.module' +import { VisitShowroomBookingProviderController } from './controllers/provider.controller' @Module({ imports: [ @@ -14,7 +15,7 @@ import { CustomerModule } from '@customer/customer.module' CategoryModule, CustomerModule ], - controllers: [VisitShowroomBookingCustomerController], + controllers: [VisitShowroomBookingCustomerController, VisitShowroomBookingProviderController], providers: [VisitShowroomBookingService, VisitShowroomBookingRepository], exports: [VisitShowroomBookingService] }) diff --git a/src/visit-showroom-booking/controllers/provider.controller.ts b/src/visit-showroom-booking/controllers/provider.controller.ts new file mode 100644 index 0000000..ed80a99 --- /dev/null +++ b/src/visit-showroom-booking/controllers/provider.controller.ts @@ -0,0 +1,45 @@ +import { Controller, Get, Param, Req, UseGuards } from '@nestjs/common' +import { ApiBadRequestResponse, ApiBearerAuth, ApiOkResponse, ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger' +import * as _ from 'lodash' + +import { ErrorResponse, PaginationQuery } from '@common/contracts/dto' +import { UserRole } from '@common/contracts/constant' +import { Roles } from '@auth/decorators/roles.decorator' +import { JwtAuthGuard } from '@auth/guards/jwt-auth.guard' +import { RolesGuard } from '@auth/guards/roles.guard' +import { Pagination, PaginationParams } from '@common/decorators/pagination.decorator' +import { ParseObjectIdPipe } from '@common/pipes/parse-object-id.pipe' +import { VisitShowroomBookingService } from '@visit-showroom-booking/services/booking.service' +import { VisitShowroomBookingPaginateResponseDto, VisitShowroomBookingResponseDto } from '@visit-showroom-booking/dto/booking.dto' + +@ApiTags('VisitShowroomBooking - Provider') +@ApiBearerAuth() +@UseGuards(JwtAuthGuard.ACCESS_TOKEN) +@Controller('provider') +export class VisitShowroomBookingProviderController { + constructor(private readonly visitShowroomBookingService: VisitShowroomBookingService) {} + + @Get() + @ApiOperation({ + summary: 'Get visit showroom bookings list' + }) + @Roles(UserRole.ADMIN, UserRole.STAFF) + @UseGuards(RolesGuard) + @ApiQuery({ type: PaginationQuery }) + @ApiOkResponse({ type: VisitShowroomBookingPaginateResponseDto }) + async paginate(@Pagination() paginationParams: PaginationParams) { + return await this.visitShowroomBookingService.paginate({}, paginationParams) + } + + @Get(':bookingId') + @ApiOperation({ + summary: 'Get visit showroom booking details' + }) + @Roles(UserRole.ADMIN, UserRole.STAFF) + @UseGuards(RolesGuard) + @ApiOkResponse({ type: VisitShowroomBookingResponseDto }) + @ApiBadRequestResponse({ type: ErrorResponse }) + async getOne(@Req() req, @Param('bookingId', ParseObjectIdPipe) bookingId: string) { + return await this.visitShowroomBookingService.getOne({ _id: bookingId }) + } +} diff --git a/src/visit-showroom-booking/dto/booking.dto.ts b/src/visit-showroom-booking/dto/booking.dto.ts index a1a6e75..d33e6f9 100644 --- a/src/visit-showroom-booking/dto/booking.dto.ts +++ b/src/visit-showroom-booking/dto/booking.dto.ts @@ -2,6 +2,9 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger' import { IsDateString, IsMongoId, IsNotEmpty, MaxLength, ValidateNested } from 'class-validator' import { Type } from 'class-transformer' import { BookingHistoryDto, CustomerDto } from '@visit-showroom-booking/schemas/booking.schema' +import { BookingStatus } from '@common/contracts/constant' +import { Category } from '@category/schemas/category.schema' +import { DataResponse, PaginateResponse } from '@common/contracts/openapi-builder' export class CreateVisitShowroomBookingDto { @ApiProperty({ type: () => CustomerDto }) @@ -25,3 +28,29 @@ export class CreateVisitShowroomBookingDto { bookingHistory?: BookingHistoryDto[] } + +export class VisitShowroomBookingDto { + @ApiProperty() + _id: string + + @ApiProperty({ type: CustomerDto }) + customer: CustomerDto + + @ApiProperty() + bookingDate: Date + + @ApiProperty() + bookingStatus: BookingStatus + + @ApiPropertyOptional({ isArray: true, type: Category }) + interestedCategories?: Category[] + + @ApiPropertyOptional() + notes?: string +} + +export class VisitShowroomBookingPaginateResponseDto extends DataResponse( + class VisitShowroomBookingPaginateResponse extends PaginateResponse(VisitShowroomBookingDto) {} +) {} + +export class VisitShowroomBookingResponseDto extends DataResponse(VisitShowroomBookingDto) {} \ No newline at end of file diff --git a/src/visit-showroom-booking/services/booking.service.ts b/src/visit-showroom-booking/services/booking.service.ts index eb18777..aa021ff 100644 --- a/src/visit-showroom-booking/services/booking.service.ts +++ b/src/visit-showroom-booking/services/booking.service.ts @@ -6,10 +6,12 @@ import { Errors } from '@src/common/contracts/error' import { CreateVisitShowroomBookingDto } from '@visit-showroom-booking/dto/booking.dto' import { CategoryRepository } from '@category/repositories/category.repository' import { VisitShowroomBookingRepository } from '@visit-showroom-booking/repositories/booking.repository' -import { BookingHistoryDto } from '@visit-showroom-booking/schemas/booking.schema' +import { BookingHistoryDto, VisitShowroomBooking } from '@visit-showroom-booking/schemas/booking.schema' import { CustomerRepository } from '@customer/repositories/customer.repository' import { MailerService } from '@nestjs-modules/mailer' import * as moment from 'moment' +import { FilterQuery } from 'mongoose' +import { PaginationParams } from '@common/decorators/pagination.decorator' @Injectable() export class VisitShowroomBookingService { @@ -71,4 +73,31 @@ export class VisitShowroomBookingService { return new IDResponse(booking._id) } + + public async paginate(filter: FilterQuery, paginationParams: PaginationParams) { + const result = await this.visitShowroomBookingRepository.paginate( + { + ...filter, + status: { + $ne: BookingStatus.DELETED + } + }, + { ...paginationParams } + ) + return result + } + + public async getOne(filter: FilterQuery) { + const booking = await this.visitShowroomBookingRepository.findOne({ + conditions: { + ...filter, + status: { + $ne: BookingStatus.DELETED + } + } + }) + if (!booking) throw new AppException(Errors.VISIT_SHOWROOM_BOOKING_NOT_FOUND) + + return booking + } }