Skip to content
Merged
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
1 change: 1 addition & 0 deletions server/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ tasks.register('copyDocument', Copy){
openapi3 {
servers = [
{ url = "http://localhost:8080" },
{ url = "http://127.0.0.1:8080" },
{ url = "https://greenroom-server.site" }
]
title = '그린룸 API DOCUMENT'
Expand Down
23 changes: 23 additions & 0 deletions server/src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1034,3 +1034,26 @@ include::{snippets}/api/greenroom/activity/patch/1/response-fields.adoc[]
실패 1.
include::{snippets}/api/greenroom/activity/patch/2/http-response.adoc[]


=== **13. 식물 상세 정보를 조회**

특정 식물의 상세 정보를 조회함.

==== Request
include::{snippets}/api/plants/info/1/http-request.adoc[]

==== Request Headers
include::{snippets}/api/plants/info/1/request-headers.adoc[]

==== Request Path Parameter Fields
include::{snippets}/api/plants/info/1/path-parameters.adoc[]

==== 성공 Response
include::{snippets}/api/plants/info/1/http-response.adoc[]

==== Response Body Fields
include::{snippets}/api/plants/info/1/response-fields.adoc[]

==== 실패 Response
실패 1.
include::{snippets}/api/plants/info/2/http-response.adoc[]
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,8 @@ public ResponseEntity<ApiResponse> getWateringInfo(@PathVariable(value = "plant_
return ResponseEntity.ok(ApiResponse.success(plantService.getWateringInfo(plantId)));
}

@GetMapping("{plant_id}")
public ResponseEntity<ApiResponse> getPlantDetailInfo(@PathVariable(value = "plant_id")Long plantId){
return ResponseEntity.ok(ApiResponse.success(plantService.getPlantDetailInfo(plantId)));
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package com.greenroom.server.api.domain.greenroom.dto.out;

import com.greenroom.server.api.domain.greenroom.entity.GreenRoom;
import com.greenroom.server.api.domain.greenroom.entity.Plant;
import com.greenroom.server.api.domain.greenroom.entity.Todo;
import lombok.*;
import com.greenroom.server.api.global.config.PropertiesHolder;

import java.time.LocalDate;
import java.util.List;
Expand All @@ -29,8 +28,8 @@ public static GreenroomDetailResponseDto of(
}

public record GreenroomBasicInfoDto (Long greenroomId, String nickName, String plantName, Integer duration, String memo, String imageUrl){
public static GreenroomBasicInfoDto from(GreenRoom greenRoom,String cdnPath){
String completeImageUrl = greenRoom.getPictureUrl()==null? null: cdnPath+"/"+greenRoom.getPictureUrl();
public static GreenroomBasicInfoDto from(GreenRoom greenRoom){
String completeImageUrl = greenRoom.getPictureUrl()==null? null: PropertiesHolder.CDN_PATH+"/"+greenRoom.getPictureUrl();
return new GreenroomBasicInfoDto(greenRoom.getGreenroomId(),greenRoom.getName(), greenRoom.getPlant()==null?null:greenRoom.getPlant().getCommonName(),LocalDate.now().getDayOfYear()- greenRoom.getCreateDate().getDayOfYear()+1,greenRoom.getMemo(), completeImageUrl);
}
}
Expand All @@ -40,16 +39,4 @@ public static GreenroomManagementInfoDto from(Todo todo){
return new GreenroomManagementInfoDto(todo.getActivity().getActivityId(),todo.getActivity().getActivityName(),todo.getTerm(),todo.getNextTodoDate().getDayOfYear()-LocalDate.now().getDayOfYear());}
}

public record PlantInfoDto (Long plantId,String name,String scientificName,String description){
public static PlantInfoDto from(Plant plant){
return new PlantInfoDto(plant.getPlantId(),plant.getCommonName(),plant.getScientificName(),plant.getOtherInformation());
}
}

public record PlantManagementInfoDto (String managementLevel,String temperature,String sunlight,String watering,String humidity,String fertilizer){
public static PlantManagementInfoDto from(Plant plant){
return new PlantManagementInfoDto(plant.getManageLevel(),plant.getGrowthTemperature(), plant.getLightDemand(), plant.getWaterCycle(), plant.getHumidity(),plant.getFertilizer());
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.greenroom.server.api.domain.greenroom.entity.Activity;
import com.greenroom.server.api.domain.greenroom.entity.GreenRoom;
import com.greenroom.server.api.domain.greenroom.entity.Item;
import com.greenroom.server.api.global.config.PropertiesHolder;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -21,8 +22,8 @@ public static GreenroomInfoResponseDto of(GreenroomBasicInfoDto basicInfo, Green
return new GreenroomInfoResponseDto(basicInfo,todo,customItems);
}
public record GreenroomBasicInfoDto(Long greenroomId,String plantNickname,String plantName, String imageUrl,String memo){
public static GreenroomBasicInfoDto from(GreenRoom greenRoom,String cdnPath){
return new GreenroomBasicInfoDto(greenRoom.getGreenroomId(), greenRoom.getName(), greenRoom.getPlant()==null?null:greenRoom.getPlant().getCommonName() , greenRoom.getPictureUrl()==null?null:cdnPath+"/"+greenRoom.getPictureUrl() ,greenRoom.getMemo());
public static GreenroomBasicInfoDto from(GreenRoom greenRoom){
return new GreenroomBasicInfoDto(greenRoom.getGreenroomId(), greenRoom.getName(), greenRoom.getPlant()==null?null:greenRoom.getPlant().getCommonName() , greenRoom.getPictureUrl()==null?null: PropertiesHolder.CDN_PATH+"/"+greenRoom.getPictureUrl() ,greenRoom.getMemo());
}
}
public record GreenroomTodoInfoDto(List<TodoSimpleDto> todoList, Integer numberOfTodo){
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.greenroom.server.api.domain.greenroom.dto.out;


import com.greenroom.server.api.domain.greenroom.entity.Plant;

public record PlantDetailInfoResponseDto(PlantInfoDto plantInfo, PlantManagementInfoDto plantManagementInfo) {
public static PlantDetailInfoResponseDto from(Plant plant){
return new PlantDetailInfoResponseDto(PlantInfoDto.from(plant),PlantManagementInfoDto.from(plant));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.greenroom.server.api.domain.greenroom.dto.out;

import com.greenroom.server.api.domain.greenroom.entity.Plant;
import com.greenroom.server.api.global.config.PropertiesHolder;
import org.springframework.beans.factory.annotation.Value;

public record PlantInfoDto (Long plantId, String name, String scientificName, String description, String imageUrl){

public static PlantInfoDto from(Plant plant){
return new PlantInfoDto(plant.getPlantId(),plant.getCommonName(),plant.getScientificName(),plant.getOtherInformation(), PropertiesHolder.CDN_PATH +"/"+ plant.getPlantPictureUrlS3());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.greenroom.server.api.domain.greenroom.dto.out;

import com.greenroom.server.api.domain.greenroom.entity.Plant;


public record PlantManagementInfoDto (String managementLevel,String temperature,String sunlight,String watering,String humidity,String fertilizer){
public static PlantManagementInfoDto from(Plant plant){
return new PlantManagementInfoDto(plant.getManageLevel(),plant.getGrowthTemperature(), plant.getLightDemand(), plant.getWaterCycle(), plant.getHumidity(),plant.getFertilizer());
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.greenroom.server.api.domain.greenroom.service;

import com.greenroom.server.api.domain.greenroom.dto.out.GreenroomDetailResponseDto;
import com.greenroom.server.api.domain.greenroom.dto.out.GreenroomInfoResponseDto;
import com.greenroom.server.api.domain.greenroom.dto.out.ItemSimpleDto;
import com.greenroom.server.api.domain.greenroom.dto.out.*;
import com.greenroom.server.api.domain.greenroom.entity.GreenRoom;
import com.greenroom.server.api.domain.greenroom.entity.Plant;
import org.springframework.beans.factory.annotation.Value;
Expand All @@ -13,10 +11,6 @@

@Component
public class GreenroomResponseAssembler {

@Value("${cloud.cdn.path.root}")
private String cdnPath;

private final AdornmentService adornmentService;
private final TodoService todoService;

Expand All @@ -27,25 +21,25 @@ public GreenroomResponseAssembler(AdornmentService adornmentService, TodoService

public GreenroomDetailResponseDto toDetailResponse(GreenRoom greenRoom) {

GreenroomDetailResponseDto.GreenroomBasicInfoDto greenroomBasicInfoDto = GreenroomDetailResponseDto.GreenroomBasicInfoDto.from(greenRoom,cdnPath);
GreenroomDetailResponseDto.GreenroomBasicInfoDto greenroomBasicInfoDto = GreenroomDetailResponseDto.GreenroomBasicInfoDto.from(greenRoom);

Map<String, ItemSimpleDto> decoration = adornmentService.getGreenroomSimpleAdornmentInfo(greenRoom);

List<GreenroomDetailResponseDto.GreenroomManagementInfoDto> managementInfo = todoService.getGreenroomManagementInfo(greenRoom);

Plant plant = greenRoom.getPlant();

GreenroomDetailResponseDto.PlantInfoDto plantInfo = plant==null? null: GreenroomDetailResponseDto.PlantInfoDto.from(plant);
PlantInfoDto plantInfo = plant==null? null: PlantInfoDto.from(plant);

GreenroomDetailResponseDto.PlantManagementInfoDto plantManagementInfo = plant==null? null: GreenroomDetailResponseDto.PlantManagementInfoDto.from(plant);
PlantManagementInfoDto plantManagementInfo = plant==null? null: PlantManagementInfoDto.from(plant);

return GreenroomDetailResponseDto.of(greenroomBasicInfoDto,decoration,managementInfo,plantInfo,plantManagementInfo);
}

public GreenroomInfoResponseDto toGreenroomInfo(GreenRoom greenRoom){

//user의 greenroom 기본 정보 조회
GreenroomInfoResponseDto.GreenroomBasicInfoDto greenroomBasicInfo= GreenroomInfoResponseDto.GreenroomBasicInfoDto.from(greenRoom,cdnPath);
GreenroomInfoResponseDto.GreenroomBasicInfoDto greenroomBasicInfo= GreenroomInfoResponseDto.GreenroomBasicInfoDto.from(greenRoom);

//user의 greenroom todo 조회
GreenroomInfoResponseDto.GreenroomTodoInfoDto greenroomTodoInfo = todoService.getGreenroomTodoInfo(greenRoom);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.greenroom.server.api.domain.greenroom.document.PlantDocument;
import com.greenroom.server.api.domain.greenroom.dto.out.PlantDetailInfoResponseDto;
import com.greenroom.server.api.domain.greenroom.dto.out.PlantResponseDto;
import com.greenroom.server.api.domain.greenroom.dto.out.PlantWateringInfoResponseDto;
import com.greenroom.server.api.domain.greenroom.entity.Plant;
Expand Down Expand Up @@ -123,5 +124,11 @@ public PlantWateringInfoResponseDto getWateringInfo(Long plantId){
return PlantWateringInfoResponseDto.of(plantId,plant.getCommonName(),plant.getWaterCycle());
}

public PlantDetailInfoResponseDto getPlantDetailInfo(Long plantId){
Plant plant = findPlantById(plantId); // 없으면 not found
return PlantDetailInfoResponseDto.from(plant);
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.greenroom.server.api.global.config;

import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class PropertiesHolder {

@Value("${cloud.cdn.path.root}")
private String cdnPathValue;

public static String CDN_PATH;

@PostConstruct
public void init() {
CDN_PATH = cdnPathValue;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ private MockMultipartFile getInvalidTestMultiPartFile (){
fieldWithPath("data.plantInfo.name").type(JsonFieldType.STRING).description("식물 이름").optional(),
fieldWithPath("data.plantInfo.scientificName").type(JsonFieldType.STRING).description("식물 학명").optional(),
fieldWithPath("data.plantInfo.description").type(JsonFieldType.STRING).description("식물에 대한 설명").optional(),
fieldWithPath("data.plantInfo.imageUrl").type(JsonFieldType.STRING).description("식물 사진").optional(),
fieldWithPath("data.plantManagementInfo").type(JsonFieldType.OBJECT).description("식물 키우는 법").optional().attributes(new Attributes.Attribute("constraint","등록된 식물이 없으면 null")),
fieldWithPath("data.plantManagementInfo.managementLevel").type(JsonFieldType.STRING).description("관리 레벨 정보").optional(),
fieldWithPath("data.plantManagementInfo.temperature").type(JsonFieldType.STRING).description("온도 정보").optional(),
Expand Down Expand Up @@ -1429,4 +1430,5 @@ private RestDocumentationResultHandler getDocumentForUpdateActivityInfo(Integer
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.greenroom.server.api.config.TestExecutionListener;
import com.greenroom.server.api.domain.greenroom.document.PlantDocument;
import com.greenroom.server.api.domain.greenroom.dto.in.ActivityInfoUpdateRequestDto;
import com.greenroom.server.api.domain.greenroom.dto.in.GreenroomPlantRequestDto;
import com.greenroom.server.api.domain.greenroom.entity.GreenRoom;
import com.greenroom.server.api.domain.greenroom.repository.*;
import com.greenroom.server.api.domain.greenroom.service.PlantService;
import com.greenroom.server.api.domain.user.entity.User;
Expand All @@ -29,9 +32,11 @@
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.restdocs.RestDocumentationContextProvider;
import org.springframework.restdocs.RestDocumentationExtension;
import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders;
import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler;
import org.springframework.restdocs.operation.preprocess.HeadersModifyingOperationPreprocessor;
import org.springframework.restdocs.payload.FieldDescriptor;
import org.springframework.restdocs.payload.JsonFieldType;
Expand All @@ -48,6 +53,7 @@
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
Expand Down Expand Up @@ -189,6 +195,25 @@ private HeadersModifyingOperationPreprocessor getModifiedHeader() {
fieldWithPath("data.wateringInfo").type(JsonFieldType.STRING).description("식물 물주기 정보")
);

List<FieldDescriptor> resultDescriptorsForPlantDetails= List.of(
fieldWithPath("status").type(JsonFieldType.STRING).description("응답 상태"),
fieldWithPath("code").type(JsonFieldType.STRING).description("상태 코드"),
fieldWithPath("data").type(JsonFieldType.OBJECT).optional().description("data").optional(),
fieldWithPath("data.plantInfo").type(JsonFieldType.OBJECT).description("식물 기본 정보"),
fieldWithPath("data.plantInfo.plantId").type(JsonFieldType.NUMBER).description("식물 id").optional(),
fieldWithPath("data.plantInfo.name").type(JsonFieldType.STRING).description("식물 이름").optional(),
fieldWithPath("data.plantInfo.scientificName").type(JsonFieldType.STRING).description("식물 학명").optional(),
fieldWithPath("data.plantInfo.description").type(JsonFieldType.STRING).description("식물에 대한 설명").optional(),
fieldWithPath("data.plantInfo.imageUrl").type(JsonFieldType.STRING).description("식물 사진").optional(),
fieldWithPath("data.plantManagementInfo").type(JsonFieldType.OBJECT).description("식물 키우는 법"),
fieldWithPath("data.plantManagementInfo.managementLevel").type(JsonFieldType.STRING).description("관리 레벨 정보").optional(),
fieldWithPath("data.plantManagementInfo.temperature").type(JsonFieldType.STRING).description("온도 정보").optional(),
fieldWithPath("data.plantManagementInfo.sunlight").type(JsonFieldType.STRING).description("햇빛 정보").optional(),
fieldWithPath("data.plantManagementInfo.watering").type(JsonFieldType.STRING).description("물주기 정보").optional(),
fieldWithPath("data.plantManagementInfo.humidity").type(JsonFieldType.STRING).description("습도 정보").optional(),
fieldWithPath("data.plantManagementInfo.fertilizer").type(JsonFieldType.STRING).description("비료 정보").optional()
);


@Test
void 인기_식물_조회_성공() throws Exception {
Expand Down Expand Up @@ -356,4 +381,57 @@ private HeadersModifyingOperationPreprocessor getModifiedHeader() {
.build()))
);
}

private ResultActions getResultActionsForPlantInfo(Long plantId) throws Exception {

String token = getTokenForTest((long) (10*1000));
return mockMvc.perform( // api 실행
RestDocumentationRequestBuilders
.get("/api/plants/{plantId}",plantId)
.header(HttpHeaders.AUTHORIZATION, "Bearer "+token));
}

private RestDocumentationResultHandler getDocumentForPlantInfo(Integer identifier){
return document("api/plants/info/"+identifier,
preprocessRequest(prettyPrint(),modifyUris().scheme("https").host("greenroom-server.site").removePort()),
preprocessResponse(prettyPrint(), getModifiedHeader()),
pathParameters(pathParametersForPlantId),
responseFields(resultDescriptorsForPlantDetails), // responseBody 설명
requestHeaders(headerWithName("Authorization").description("Bearer : 사용자 access Token")),
resource(ResourceSnippetParameters.builder()
.tag("그린룸") // 문서에서 api들이 태그로 분류됨
.summary("식물 상세 정보 조회 api") // api 이름
.description("식물 사전에서 식물 상세 정보를 조회함.") // api 설명
.build()));
}

@Test
@Transactional
public void 식물정보_조회_성공() throws Exception {
//given

//when
ResultActions resultActions = getResultActionsForPlantInfo(10L);

//then
resultActions.andExpect(status().isOk());

//문서화
resultActions.andDo(getDocumentForPlantInfo(1));
}

@Test
@Transactional
public void 식물정보_조회_실패() throws Exception {
//given

//when
ResultActions resultActions = getResultActionsForPlantInfo(10000L);

//then
resultActions.andExpect(status().is(ResponseCodeEnum.PLANT_NOT_FOUND.getStatus().value())).andExpect(jsonPath("code").value(ResponseCodeEnum.PLANT_NOT_FOUND.getCode()));

//문서화
resultActions.andDo(getDocumentForPlantInfo(2));
}
}
Loading