Skip to content

Commit

Permalink
Merge pull request #72 from VentionCapstone/feat/160_accommodation-re…
Browse files Browse the repository at this point in the history
…servations

Feat/160 accommodation reservations
  • Loading branch information
Zach13131 committed Feb 12, 2024
2 parents 51b5f2d + f6cf34c commit 5456755
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,10 @@ STRIPE_API_VERSION='2023-10-16'
FORGOT_PASSWORD_RESET_TOKEN_KEY=
FORGOT_PASSWORD_RESET_TOKEN_EXPIRY=
HASHING_LIMIT=72 # bcrypt has hashing limit of 72 characters

GOOGLE_CLIENT_ID=
GOOGLE_SECRET=

CACHE_TIMEOUT= # time after which the cache will be deleted, in milliseconds
CACHING_PAGES= # pages which will be cached on the cache warming
CACHING_PAGES_LIMIT= # number of accommodations per page, to chaching
40 changes: 40 additions & 0 deletions src/accommodation/accommodation.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import { AccommodationService } from './accommodation.service';
import { MediaAllDto } from './dto/accommodation-media.dto';
import AccommodationResponseDto, { AccommodationDto } from './dto/accommodation-response.dto';
import CreateAccommodationDto from './dto/create-accommodation.dto';
import AccommodationBookingsDto from './dto/get-accommodation-bookings.dto';
import { OrderAndFilterReviewDto } from './dto/get-review.dto';
import { GetUserAccommodationsDto } from './dto/get-user-accommodations.dto';
import ListOfAccommodationsResponseDto from './dto/list-of-accommodations.dto';
Expand Down Expand Up @@ -490,4 +491,43 @@ export class AccommodationController {

return { succes: true, data: media };
}

@ApiOperation({ summary: 'Get all reservations, for one accommodation' })
@ApiResponse({
status: 200,
description: 'All reservations',
type: AccommodationResponseDto,
})
@ApiUnauthorizedResponse({
status: 401,
description: 'Unauthorized',
})
@ApiResponse({
status: 404,
description: 'Not found',
})
@ApiResponse({
status: 500,
description: 'Internal Server Error',
})
@ApiParam({
name: 'id',
type: String,
description: 'Accommodation id',
required: true,
})
@ApiBearerAuth()
@UseGuards(UserGuard)
@Get('/:id/reservations')
async getAllReservations(
@Param('id') id: string,
@CurrentUser('id') userId: string,
@Query() options: AccommodationBookingsDto
) {
const data = await this.accommodationService.getAllReservations(id, userId, options);
return {
succes: true,
data,
};
}
}
89 changes: 89 additions & 0 deletions src/accommodation/accommodation.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { GlobalException } from 'src/exceptions/global.exception';
import { normalizeCityName } from 'src/helpers/normalizeCityName.helper';
import { normalizeCountryName } from 'src/helpers/normalizeCountryName.helper';
import { PrismaService } from 'src/prisma/prisma.service';
import AccommodationBookingsDto from './dto/get-accommodation-bookings.dto';
import { OrderAndFilterReviewDto, reviewOrderBy } from './dto/get-review.dto';
import { GetUserAccommodationsDto } from './dto/get-user-accommodations.dto';
import { OrderAndFilterDto, OrderBy } from './dto/orderAndFilter.dto';
Expand All @@ -34,6 +35,11 @@ interface UploadImageResponse {
};
}

type BookingWhereInput = {
accommodationId: string;
OR?: ({ startDate: { gte: string } } | { endDate: { gte: string } })[];
};

const {
ACCOMMODATION_MAX_PRICE,
ACCOMMODATION_MAX_PEOPLE,
Expand Down Expand Up @@ -818,6 +824,89 @@ export class AccommodationService {
}
}

async getAllReservations(
accommodationId: string,
userId: string,
options: AccommodationBookingsDto
) {
try {
const { currentMonth, nextMonth, orderByStartDate } = options;

const accommodation = await this.prisma.accommodation.findUnique({
include: { booking: true },
where: {
id: accommodationId,
ownerId: userId,
},
});

if (!accommodation) throw new NotFoundException(ErrorsTypes.NOT_FOUND_ACCOMMODATION);

const findBookingQuery = {
select: {
id: true,
userId: true,
startDate: true,
endDate: true,
status: true,
user: {
select: {
firstName: true,
lastName: true,
profile: {
select: {
imageUrl: true,
},
},
},
},
payment: {
select: {
totalAmount: true,
},
},
},

where: {
accommodationId: accommodation.id,
} as BookingWhereInput,
};

if (currentMonth && nextMonth) {
currentMonth.setDate(1);
currentMonth.setUTCHours(0, 0, 0, 0);

nextMonth.setDate(1);
nextMonth.setUTCHours(0, 0, 0, 0);

findBookingQuery.where = {
accommodationId: accommodation.id,
OR: [
{
startDate: {
gte: currentMonth.toISOString(),
},
},
{
endDate: {
gte: currentMonth.toISOString(),
},
},
],
};
}

const data = await this.prisma.booking.findMany({
...findBookingQuery,
orderBy: { startDate: orderByStartDate },
});
return data;
} catch (error) {
if (error instanceof HttpException) throw error;
throw new GlobalException(ErrorsTypes.ACCOMMODATION_FAILED_TO_GET, error.message);
}
}

private getCountByRating(ratingCounts: { rating: number; _count: number }[]) {
const countByRating: Record<number, number> = {};

Expand Down
19 changes: 19 additions & 0 deletions src/accommodation/dto/get-accommodation-bookings.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Transform } from 'class-transformer';
import { IsDate, IsEnum, IsOptional } from 'class-validator';
import { SortOrder } from 'src/enums/sortOrder.enum';

export default class AccommodationBookingsDto {
@IsOptional()
@Transform(({ value }) => new Date(value))
@IsDate()
currentMonth?: Date;

@IsOptional()
@Transform(({ value }) => new Date(value))
@IsDate()
nextMonth?: Date;

@IsEnum(SortOrder)
@IsOptional()
public orderByStartDate?: SortOrder;
}

0 comments on commit 5456755

Please sign in to comment.