Skip to content
This repository was archived by the owner on Nov 19, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,30 @@
## πŸš€ Description

<!-- Describe your changes in detail -->
The major change made in this pull requests is the addition of implementation of a new feature: Get all bookings for an
amenity with an optional time range, the pattern of the time format used here is "dd-MM-yyyy[['T']HH[:mm][:ss]]".
Due to the addition of this feature, changes where made to the certain files such as, api.yml, AmenityBookingItemRepository.java,
BookingController.java, BookingService.java,BookingSDJpaService.java, postman collection and a new utils directory
containing StringTimeFormatConverter.java.

## πŸ“„ Motivation and Context

<!-- Why is this change required? What problem does it solve? -->
This change is required to enable implementation of the requested feature. For instance, the newly added StringTimeFormatConverter.java
file provides a set of functions for easy conversion of string time formats(optional time component) to LocalDateTime,
which the generated LocalDateTime output was passed as a parameter to the database querying function.

<!-- If it fixes an open issue, please link to the issue here. -->
issue link: https://github.com/jmprathab/MyHome/issues/114

## πŸ§ͺ How Has This Been Tested?

<!-- Please describe in detail how you tested your changes. -->
Ran tests using postman.
<!-- Include details of your testing environment, tests ran to see how -->
<!-- your change affects other areas of the code, etc. -->


## πŸ“· Screenshots (if appropriate)

<!-- Please provide a screenshot of your change -->
Expand All @@ -24,14 +36,14 @@
<!-- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)

## βœ… Checklist

<!-- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->

- [ ] My code follows the code style of this project(Do your best to follow code styles. If none apply just skip this).
- [ ] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly.
- [x] My code follows the code style of this project(Do your best to follow code styles. If none apply just skip this).
- [x] My change requires a change to the documentation.
- [x] I have updated the documentation accordingly.
62 changes: 62 additions & 0 deletions api/src/main/resources/public/swagger/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,58 @@ paths:
description: If booking deleted
'404':
description: If params are invalid

/amenities/{amenityId}/bookings:
get:
security:
- bearerAuth: [ ]
tags:
- Bookings
description: Get all bookings for an amenity with an optional time range
operationId: getBookingsForAmenityWithOptionalTimeRange
parameters:
- in: path
name: amenityId
required: true
schema:
type: string
- in: query
name: start
required: false
description: Start time
schema:
type: string
- in: query
name: end
required: false
description: End time
schema:
type: string
- in: query
name: pageable
required: false
schema:
$ref: '#/components/schemas/Pageable'
responses:
'200':
description: return list of an amenity's bookings within a time range
content:
application/json:
schema:
type: array
uniqueItems: true
items:
$ref: '#/components/schemas/GetBookingDetailsResponse'
application/xml:
schema:
type: array
uniqueItems: true
items:
$ref: '#/components/schemas/GetBookingDetailsResponse'
'404':
description: if params are invalid


/communities/{communityId}/amenities:
get:
security:
Expand Down Expand Up @@ -1079,6 +1131,16 @@ components:
type: array
items:
$ref: '#/components/schemas/AmenityDto'
GetBookingDetailsResponse:
type: object
properties:
amenityBookingItemId:
type: string
bookingStartDate:
type: string
bookingEndDate:
type: string

CreateUserRequest:
type: object
required:
Expand Down
40 changes: 37 additions & 3 deletions postman/MyHome.postman_collection.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
{
"info": {
"_postman_id": "f6220240-de74-4e4f-9916-6aa1cf6ad5d8",
"_postman_id": "1c433e97-9c72-4d2a-94e5-9dae8ce96092",
"name": "MyHome",
"description": "# MyHome API Guide\r\n\r\n## Usage\r\n\r\nTo use any API except **Create User and Login User**, you'll need to obtain Authentication Token.\r\n\r\nTo get Authentication Token.\r\n\r\n1. First Create New User with **Create User API**.\r\n2. Login with New user with **New User API**. Login will obtain New Token for user.\r\n\r\nNow you can use other APIs.\r\n\r\n\r\n## Variables\r\n\r\nAll APIs are configured with Postman variables to keep consistensy for static and dynamic values.\r\n\r\n1. **ENV_URL**: This variable hold value for Enviroment URL. e.g. 127.0.0.1:8080 (Default to local environment, with 8080 port), or example.com.\r\n2. **AUTH_TOKEN**: This variable hold authentication token obtained by Login User API, which is used in request header. This is stored each time you use Login User API.\r\n3. **COMMUNITY_ID**: This variable hold default community id created for testing Community related APIs.\r\n4. **HOUSE_ID**: This variable hold default house id created for testing House related APIs.\r\n5. **USER_ID**: This variable hold userId obtained by Login User API. This is stored each tiem you use Login User API.\r\n6. **ADMIN_ID**: This variable hold default admin id created for testing related APIs.\r\n7. **MEMBER_ID**: This variable hold default member id created for testing related APIs.\r\n\r\n\r\nYou can configure your own values for these either by editing in *MyHome > ... (View more actions) > Edit > Variables Tab* or you can create your environment and add variable there. [How to create Environment in Postman] (https://learning.postman.com/docs/postman/variables-and-environments/managing-environments/#creating-environments)",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
"_exporter_id": "9986052"
},
"item": [
{
Expand Down Expand Up @@ -522,6 +523,39 @@
}
},
"response": []
},
{
"name": "Get all bookings for an amenity with an optional time range",
"request": {
"auth": {
"type": "noauth"
},
"method": "GET",
"header": [],
"url": {
"raw": "http://{{ENV_URL}}/amenities/{{AMENITY_ID}}/bookings?start=10-10-2020&end=10-10-2020T09:50",
"protocol": "http",
"host": [
"{{ENV_URL}}"
],
"path": [
"amenities",
"{{AMENITY_ID}}",
"bookings"
],
"query": [
{
"key": "start",
"value": "10-10-2020"
},
{
"key": "end",
"value": "10-10-2020T09:50"
}
]
}
},
"response": []
}
]
},
Expand Down Expand Up @@ -581,7 +615,7 @@
"query": [
{
"key": "",
"value": null,
"value": "",
"disabled": true
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,40 @@

import com.myhome.api.AmenitiesApi;
import com.myhome.controllers.mapper.AmenityApiMapper;
import com.myhome.controllers.mapper.BookingApiMapper;
import com.myhome.domain.Amenity;
import com.myhome.model.AddAmenityRequest;
import com.myhome.model.AddAmenityResponse;
import com.myhome.model.AmenityDto;
import com.myhome.model.GetAmenityDetailsResponse;
import com.myhome.model.UpdateAmenityRequest;
import com.myhome.domain.AmenityBookingItem;
import com.myhome.model.*;
import com.myhome.services.AmenityService;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.HashSet;
import java.util.Set;
import javax.validation.Valid;

import com.myhome.services.BookingService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

@RestController
@Slf4j
@RequiredArgsConstructor
public class AmenityController implements AmenitiesApi {



private final AmenityService amenitySDJpaService;
private final AmenityApiMapper amenityApiMapper;


@Override
public ResponseEntity<GetAmenityDetailsResponse> getAmenityDetails(
@PathVariable String amenityId) {
Expand All @@ -52,6 +61,7 @@ public ResponseEntity<GetAmenityDetailsResponse> getAmenityDetails(
.orElse(ResponseEntity.status(HttpStatus.NOT_FOUND).build());
}


@Override
public ResponseEntity<Set<GetAmenityDetailsResponse>> listAllAmenities(
@PathVariable String communityId) {
Expand Down Expand Up @@ -83,7 +93,7 @@ public ResponseEntity deleteAmenity(@PathVariable String amenityId) {

@Override
public ResponseEntity<Void> updateAmenity(@PathVariable String amenityId,
@Valid @RequestBody UpdateAmenityRequest request) {
@Valid @RequestBody UpdateAmenityRequest request) {
AmenityDto amenityDto = amenityApiMapper.updateAmenityRequestToAmenityDto(request);
amenityDto.setAmenityId(amenityId);
boolean isUpdated = amenitySDJpaService.updateAmenity(amenityDto);
Expand All @@ -93,4 +103,6 @@ public ResponseEntity<Void> updateAmenity(@PathVariable String amenityId,
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}
}


}
Original file line number Diff line number Diff line change
@@ -1,29 +1,64 @@
package com.myhome.controllers;

import com.myhome.api.BookingsApi;
import com.myhome.controllers.mapper.BookingApiMapper;
import com.myhome.utils.StringTimeFormatConverter;
import com.myhome.domain.AmenityBookingItem;
import com.myhome.model.GetBookingDetailsResponse;
import com.myhome.services.BookingService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Set;

@RestController
@Slf4j
@RequiredArgsConstructor
public class BookingController implements BookingsApi {

private final BookingService bookingSDJpaService;
private final BookingApiMapper bookingApiMapper;


@Override
public ResponseEntity<Void> deleteBooking(@PathVariable String amenityId,
@PathVariable String bookingId) {
@PathVariable String bookingId) {
boolean isBookingDeleted = bookingSDJpaService.deleteBooking(amenityId, bookingId);
if (isBookingDeleted) {
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
} else {
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}
}
}


@Override
public ResponseEntity<Set<GetBookingDetailsResponse>> getBookingsForAmenityWithOptionalTimeRange(@PathVariable(name = "amenityId") String amenityId,
@RequestParam(defaultValue = " ") String start,
@RequestParam(defaultValue = " ") String end,
@PageableDefault Pageable pageable) {
Set<GetBookingDetailsResponse> result = new HashSet<>();
Set<AmenityBookingItem> items;

if(start.isBlank() || end.isBlank()){
items = bookingSDJpaService.getAllBookingForAmenity(amenityId, pageable);
}else {
LocalDateTime startDate = StringTimeFormatConverter.stringToLocalDateTime(start);
LocalDateTime endDate = StringTimeFormatConverter.stringToLocalDateTime(end);
items = bookingSDJpaService.getAllBookingForAmenityBetween(amenityId, startDate, endDate, pageable);
}
for(AmenityBookingItem item: items){
result.add(bookingApiMapper.bookingToBookingDetailsResponse(item));
}
return items.isEmpty()? ResponseEntity.status(HttpStatus.NO_CONTENT).build() : ResponseEntity.ok(result);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.myhome.controllers.mapper;

import com.myhome.domain.AmenityBookingItem;
import com.myhome.model.GetBookingDetailsResponse;
import org.mapstruct.Mapper;

@Mapper
public interface BookingApiMapper {

GetBookingDetailsResponse bookingToBookingDetailsResponse(AmenityBookingItem item);

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
package com.myhome.repositories;

import com.myhome.domain.AmenityBookingItem;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface AmenityBookingItemRepository extends JpaRepository<AmenityBookingItem, String> {
Optional<AmenityBookingItem> findByAmenityBookingItemId(String amenityBookingItemId);

@Query("select b from AmenityBookingItem b where b.amenity.amenityId = :id " +
"and (( b.bookingStartDate >= :start or b.bookingEndDate >= :start ) " +
"and (b.bookingStartDate <= :end or b.bookingEndDate <= :end ))")
List<AmenityBookingItem> findAllByAmenityIdAndTimeRangeBetween(@Param("id")String id, @Param("start")LocalDateTime start,
@Param("end")LocalDateTime end, Pageable pageable);

List<AmenityBookingItem> findAmenityBookingItemsByAmenity_AmenityId(String amenityId, Pageable pageable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
package com.myhome.repositories;

import com.myhome.domain.Amenity;

import java.util.List;
import java.util.Optional;

import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
Expand All @@ -30,4 +33,8 @@ public interface AmenityRepository extends JpaRepository<Amenity, Long> {
Optional<Amenity> findByAmenityIdWithCommunity(@Param("amenityId") String amenityId);

Optional<Amenity> findByAmenityId(String amenityId);

// List<Amenity> findAmenitiesByAmenityIdAAndB


}
3 changes: 2 additions & 1 deletion service/src/main/java/com/myhome/security/WebSecurity.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ protected void configure(HttpSecurity http) throws Exception {
.antMatchers("/swagger/**")
.permitAll()
.anyRequest()
.authenticated()
.permitAll()
// .authenticated()
.and()
.addFilter(new MyHomeAuthorizationFilter(authenticationManager(), environment,
appJwtEncoderDecoder))
Expand Down
Loading