diff --git a/src/main/java/com/umc/commonplant/domain/plant/controller/PlantController.java b/src/main/java/com/umc/commonplant/domain/plant/controller/PlantController.java new file mode 100644 index 0000000..1ff0dac --- /dev/null +++ b/src/main/java/com/umc/commonplant/domain/plant/controller/PlantController.java @@ -0,0 +1,88 @@ +package com.umc.commonplant.domain.plant.controller; + +import com.umc.commonplant.domain.Jwt.JwtService; +import com.umc.commonplant.domain.place.entity.Place; +import com.umc.commonplant.domain.place.service.PlaceService; +import com.umc.commonplant.domain.plant.dto.PlantDto; +import com.umc.commonplant.domain.plant.entity.Plant; +import com.umc.commonplant.domain.plant.service.PlantService; +import com.umc.commonplant.domain.user.entity.User; +import com.umc.commonplant.domain.user.service.UserService; +import com.umc.commonplant.global.dto.JsonResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +@Slf4j +@RequiredArgsConstructor +@RestController +public class PlantController { + + private final UserService userService; + private final JwtService jwtService; + private final PlaceService placeService; + private final PlantService plantService; + + /** + * [POST] 식물 추가 + * [POST] /plant/add + * @return 추가한 식물의 애칭 + */ + @PostMapping("/plant/add") + public ResponseEntity createPlant(@RequestPart("plant") PlantDto.createPlantReq createPlantReq, + @RequestPart("image") MultipartFile file) { + + log.info("=============CREATE PLANT==============="); + + String uuid = jwtService.resolveToken(); + User user = userService.getUser(uuid); + + String nickname = plantService.createPlant(user, createPlantReq, file); + + return ResponseEntity.ok(new JsonResponse(true, 200, "createPlant", nickname)); + } + + /** + * [GET] 같은 장소에 있는 식물 리스트 조회 + * @param placeCode: 장소 코드 + * @return 같은 장소에 있는 식물 리스트 + */ + @GetMapping("/plant/plantList/{placeCode}") + public ResponseEntity getPlantList(@PathVariable String placeCode) { + + log.info("=============GET PLANT LIST==============="); + + String uuid = jwtService.resolveToken(); + User user = userService.getUser(uuid); + + // Place place = placeService.getPlace(user, placeCode); + String place = placeService.getPlace(user, placeCode).getCode(); + + List plantList = plantService.getPlantList(place); + + return ResponseEntity.ok(new JsonResponse(true, 200, "getPlantList", plantList)); + } + + /** + * [PATCH] /plant/update + * @return 수정한 식물의 애칭 + */ + @PatchMapping("/plant/update/{plantIdx}") + public ResponseEntity updatePlant(@PathVariable Long plantIdx, + @RequestPart("nickname") String nickname, + @RequestPart("image") MultipartFile file){ + + log.info("=============UPDATE PLANT==============="); + + String uuid = jwtService.resolveToken(); + User user = userService.getUser(uuid); + + String updatedPlant = plantService.updatePlant(plantIdx, nickname, file); + + return ResponseEntity.ok(new JsonResponse(true, 200, "updatePlant", updatedPlant)); + } +} diff --git a/src/main/java/com/umc/commonplant/domain/plant/dto/PlantDto.java b/src/main/java/com/umc/commonplant/domain/plant/dto/PlantDto.java new file mode 100644 index 0000000..f7f4309 --- /dev/null +++ b/src/main/java/com/umc/commonplant/domain/plant/dto/PlantDto.java @@ -0,0 +1,56 @@ +package com.umc.commonplant.domain.plant.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.*; + +import java.time.LocalDateTime; + +public class PlantDto { + + @AllArgsConstructor + @NoArgsConstructor + @Data + public static class createPlantReq{ + // private String plantImage; + // TODO: 종 이름을 추가할 때 나중에 Information 에서 불러오기 때문에 추후 수정/삭제 + // private String scientificName; + private String nickname; + // TODO: 장소를 추가할 때 장소 리스트에서 선택하는 것이기 때문에 추후 수정/삭제 + private String place; + // TODO: (default)식물 도감에 있는 값(info.getWaterDay()), 사용자가 물주기 기간 설정 가능 + private int waterCycle; + private String strWateredDate; + // TODO: 물주는 날짜가 적게 남은 순서로 정렬 + } + + @AllArgsConstructor + @NoArgsConstructor + @Getter + // @Builder + public static class getPlantRes{ + private String name; + private String nickname; + + private String place; + + private String imgUrl; + + private Long countDate; + private Long remainderDate; + + // Info + private String scientificName; + private Long waterDay; + private String sunlight; + private Long tempMin; + private Long tempMax; + private String humidity; + + @JsonFormat(pattern = "yyyy.MM.dd") + private LocalDateTime createdAt; + + @JsonFormat(pattern = "yyyy.MM.dd") + private LocalDateTime wateredDate; + } + +} diff --git a/src/main/java/com/umc/commonplant/domain/plant/entity/Plant.java b/src/main/java/com/umc/commonplant/domain/plant/entity/Plant.java index 5d962dd..5eb71f4 100644 --- a/src/main/java/com/umc/commonplant/domain/plant/entity/Plant.java +++ b/src/main/java/com/umc/commonplant/domain/plant/entity/Plant.java @@ -1,8 +1,8 @@ package com.umc.commonplant.domain.plant.entity; import com.umc.commonplant.domain.BaseTime; -import com.umc.commonplant.domain2.info.entity.Info; import com.umc.commonplant.domain.place.entity.Place; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import org.hibernate.annotations.OnDelete; @@ -30,4 +30,21 @@ public class Plant extends BaseTime { private String imgUrl; private LocalDateTime wateredDate; + @Builder + public Plant(Place place, String name, String imgUrl, LocalDateTime wateredDate){ + this.place = place; + // this.info = info; + this.name = name; + this.imgUrl = imgUrl; + this.wateredDate = wateredDate; + } + + /** + * 식물 수정 API 관련 메소드 + */ + public void updatePlant(String imgUrl, String name) { + this.imgUrl = imgUrl; + this.name = name; + } + } diff --git a/src/main/java/com/umc/commonplant/domain/plant/entity/PlantRepository.java b/src/main/java/com/umc/commonplant/domain/plant/entity/PlantRepository.java new file mode 100644 index 0000000..a4b0863 --- /dev/null +++ b/src/main/java/com/umc/commonplant/domain/plant/entity/PlantRepository.java @@ -0,0 +1,20 @@ +package com.umc.commonplant.domain.plant.entity; + +import com.umc.commonplant.domain.place.entity.Place; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; + + +@Repository +public interface PlantRepository extends JpaRepository { + + @Query("select p from Plant p where p.plantIdx=?1") + Optional findByPlantIdx(Long plantIdx); + + @Query(value = "SELECT p FROM Plant p WHERE p.place= ?1 ") + List findAllByPlace(Place place); +} diff --git a/src/main/java/com/umc/commonplant/domain/plant/service/PlantService.java b/src/main/java/com/umc/commonplant/domain/plant/service/PlantService.java new file mode 100644 index 0000000..4c5e5b2 --- /dev/null +++ b/src/main/java/com/umc/commonplant/domain/plant/service/PlantService.java @@ -0,0 +1,133 @@ +package com.umc.commonplant.domain.plant.service; + +import com.umc.commonplant.domain.image.service.ImageService; +import com.umc.commonplant.domain.place.entity.Place; +import com.umc.commonplant.domain.place.entity.PlaceRepository; +import com.umc.commonplant.domain.place.service.PlaceService; +import com.umc.commonplant.domain.plant.dto.PlantDto; +import com.umc.commonplant.domain.plant.entity.Plant; +import com.umc.commonplant.domain.plant.entity.PlantRepository; +import com.umc.commonplant.domain.user.entity.User; +import com.umc.commonplant.global.exception.BadRequestException; +import com.umc.commonplant.global.exception.ErrorResponseStatus; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.time.Duration; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; + +@Slf4j +@RequiredArgsConstructor +@Service +public class PlantService { + + private final PlaceRepository placeRepository; + private final PlantRepository plantRepository; + + private final PlaceService placeService; + private final ImageService imageService; + + /** + * createPlant: 식물 추가 + * @param req + * @param plantImage + * @return + */ + @Transactional + public String createPlant(User user, PlantDto.createPlantReq req, MultipartFile plantImage) { + + // 식물 이미지 + String imgUrl = null; + + if (plantImage.getSize() > 0) { + imgUrl = imageService.saveImage(plantImage); + } else { + throw new BadRequestException(ErrorResponseStatus.NO_SELECTED_PLANT_IMAGE); + } + + // 식물 장소 + // TODO: 식물이 있는 장소 -> 장소의 코드로 검색(추후 장소의 이름으로 바뀔 수 있음) + Place plantPlace = placeRepository.getPlaceByCode(req.getPlace()) + .orElseThrow(() -> new BadRequestException(ErrorResponseStatus.NOT_FOUND_PLACE_NAME)); + + // 최근에 물 준 날짜 + // TODO: WateredDate -> String에서 LocalDateTime으로 변환 + String strWateredDate = req.getStrWateredDate(); + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy.MM.dd"); + + LocalDateTime parsedWateredDate = null; + parsedWateredDate = LocalDate.parse(strWateredDate, dateTimeFormatter).atStartOfDay(); + + // TODO: 식물 종 이름 -> 장소 처럼 검색(현재는 임시로 Info 객체 생성) + Plant plant = Plant.builder() + .place(plantPlace) + //.info(new Info()) + .name(req.getNickname()) + .imgUrl(imgUrl) + .wateredDate(parsedWateredDate) + .build(); + + plantRepository.save(plant); + + return req.getNickname(); + } + + /** + * getPlantList: 같은 장소에 있는 식물 리스트 조회 + * @param placeCode: 장소 코드 + * @return List + */ + @Transactional + public List getPlantList(String placeCode) { + + // TODO: 식물이 있는 장소 -> 장소의 코드로 검색(추후 장소의 이름으로 바뀔 수 있음) + Place plantPlace = placeRepository.getPlaceByCode(placeCode) + .orElseThrow(() -> new BadRequestException(ErrorResponseStatus.NOT_FOUND_PLACE_NAME)); + + return plantRepository.findAllByPlace(plantPlace); + } + + /** + * updatePlant: 식물 수정 + * @param plantIdx + * @param nickname + * @param plantImage + * @return + */ + @Transactional + public String updatePlant(Long plantIdx, String nickname, MultipartFile plantImage) { + + Plant plant = plantRepository.findByPlantIdx(plantIdx) + .orElseThrow(() -> new BadRequestException(ErrorResponseStatus.NOT_FOUND_PLANT)); + + // TODO: 식물의 애칭 + String plantNickname = null; + + if (nickname.isEmpty()) { + throw new BadRequestException(ErrorResponseStatus.NO_PLANT_NICKNAME); + } else if (nickname.length() <= 10) { + plantNickname = nickname; + } else { + throw new BadRequestException(ErrorResponseStatus.LONG_PLANT_NICKNAME); + } + + // TODO: imgUrl + String imgUrl = null; + + if (plantImage.getSize() > 0) { + imgUrl = plant.getImgUrl(); + } else { + throw new BadRequestException(ErrorResponseStatus.NO_SELECTED_PLANT_IMAGE); + } + + plant.updatePlant(imgUrl, plantNickname); + + return plantRepository.save(plant).getName(); + } +} diff --git a/src/main/java/com/umc/commonplant/global/exception/ErrorResponseStatus.java b/src/main/java/com/umc/commonplant/global/exception/ErrorResponseStatus.java index 2f135a4..77d9fea 100644 --- a/src/main/java/com/umc/commonplant/global/exception/ErrorResponseStatus.java +++ b/src/main/java/com/umc/commonplant/global/exception/ErrorResponseStatus.java @@ -17,6 +17,12 @@ public enum ErrorResponseStatus { EXPIRED_JWT(false, 4007, "만료된 토큰입니다."), NOT_FOUND_PLACE_CODE(false, 4100, "등록된 code가 없습니다."), + NOT_FOUND_PLACE_NAME(false, 4101, "등록된 장소 이름이 없습니다."), + + NOT_FOUND_PLANT(false, 4200, "등록된 식물이 없습니다."), + NO_PLANT_NICKNAME(false, 4201, "식물의 애칭을 입력해 주세요!"), + LONG_PLANT_NICKNAME(false, 4202, "식물의 애칭은 10자 이하로 설정해주세요!"), + NO_SELECTED_PLANT_IMAGE(false,4203, "식물의 이미지를 선택해주세요!"), //5000 : Server connection 오류 SERVER_ERROR(false, 5000, "서버와의 연결에 실패하였습니다."),