From 53e302d590bdb2f6524dda601d7a1ecd738c9f85 Mon Sep 17 00:00:00 2001 From: kkang_h00n Date: Mon, 7 Jul 2025 17:03:44 +0900 Subject: [PATCH 1/2] =?UTF-8?q?Feat:=20=ED=8A=B9=EC=A0=95=20=EC=95=A0?= =?UTF-8?q?=EC=99=84=20=EC=8B=9D=EB=AC=BC=20=E2=80=98=EC=98=A4=EB=8A=98?= =?UTF-8?q?=EC=9D=98=20=EA=B8=B0=EB=A1=9D=E2=80=99=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/DailyRecordController.java | 13 +++++++ .../petPlant/domain/entity/DailyRecord.java | 4 ++ .../repository/DailyRecordRepository.java | 4 ++ .../request/UpdateDailyRecordRequestDto.java | 16 ++++++++ .../service/DailyRecordCommandService.java | 39 +++++++++++++++++++ 5 files changed, 76 insertions(+) create mode 100644 src/main/java/swyp/team5/greening/petPlant/dto/request/UpdateDailyRecordRequestDto.java diff --git a/src/main/java/swyp/team5/greening/petPlant/controller/DailyRecordController.java b/src/main/java/swyp/team5/greening/petPlant/controller/DailyRecordController.java index 79028d7..1df31ef 100644 --- a/src/main/java/swyp/team5/greening/petPlant/controller/DailyRecordController.java +++ b/src/main/java/swyp/team5/greening/petPlant/controller/DailyRecordController.java @@ -8,6 +8,7 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseStatus; @@ -15,6 +16,7 @@ import swyp.team5.greening.common.dto.response.ApiResponseDto; import swyp.team5.greening.common.resolver.LogIn; import swyp.team5.greening.petPlant.dto.request.CreateDailyRecordRequestDto; +import swyp.team5.greening.petPlant.dto.request.UpdateDailyRecordRequestDto; import swyp.team5.greening.petPlant.dto.response.CreateDailyRecordResponseDto; import swyp.team5.greening.petPlant.dto.response.FindDailyRecordResponseDto; import swyp.team5.greening.petPlant.service.DailyRecordCommandService; @@ -58,4 +60,15 @@ public ApiResponseDto getDailyRecord( )); } + @Operation(summary = "특정 애완 식물 오늘의 기록 수정 API") + @PutMapping("/daily-record/{dailyRecordId}") + @ResponseStatus(HttpStatus.OK) + public void updateDailyRecord ( + @LogIn Long userId, + @PathVariable Long dailyRecordId, + @Validated @RequestBody UpdateDailyRecordRequestDto requestDto + ) { + dailyRecordCommandService.updateDailyRecord(userId, dailyRecordId, requestDto); + } + } diff --git a/src/main/java/swyp/team5/greening/petPlant/domain/entity/DailyRecord.java b/src/main/java/swyp/team5/greening/petPlant/domain/entity/DailyRecord.java index d194449..b223c8b 100644 --- a/src/main/java/swyp/team5/greening/petPlant/domain/entity/DailyRecord.java +++ b/src/main/java/swyp/team5/greening/petPlant/domain/entity/DailyRecord.java @@ -58,6 +58,10 @@ public DailyRecord( this.petPlantId = petPlantId; } + public void updateTitle(String newTitle) { + this.title = newTitle; + } + public void updateContent(List contents) { dailyRecordContents.clear(); diff --git a/src/main/java/swyp/team5/greening/petPlant/domain/repository/DailyRecordRepository.java b/src/main/java/swyp/team5/greening/petPlant/domain/repository/DailyRecordRepository.java index d2a3506..5f95503 100644 --- a/src/main/java/swyp/team5/greening/petPlant/domain/repository/DailyRecordRepository.java +++ b/src/main/java/swyp/team5/greening/petPlant/domain/repository/DailyRecordRepository.java @@ -1,10 +1,14 @@ package swyp.team5.greening.petPlant.domain.repository; +import java.util.Optional; import swyp.team5.greening.petPlant.domain.entity.DailyRecord; +import swyp.team5.greening.petPlant.domain.entity.DailyRecordState; public interface DailyRecordRepository { DailyRecord save(DailyRecord dailyRecord); + Optional findByIdAndState(Long dailyRecordId, DailyRecordState state); + void deleteAll(); } diff --git a/src/main/java/swyp/team5/greening/petPlant/dto/request/UpdateDailyRecordRequestDto.java b/src/main/java/swyp/team5/greening/petPlant/dto/request/UpdateDailyRecordRequestDto.java new file mode 100644 index 0000000..2744825 --- /dev/null +++ b/src/main/java/swyp/team5/greening/petPlant/dto/request/UpdateDailyRecordRequestDto.java @@ -0,0 +1,16 @@ +package swyp.team5.greening.petPlant.dto.request; + +import jakarta.validation.constraints.NotEmpty; +import java.util.List; +import swyp.team5.greening.petPlant.dto.DailyRecordContentDto; + +public record UpdateDailyRecordRequestDto( + + @NotEmpty + String title, + + @NotEmpty + List content +) { + +} diff --git a/src/main/java/swyp/team5/greening/petPlant/service/DailyRecordCommandService.java b/src/main/java/swyp/team5/greening/petPlant/service/DailyRecordCommandService.java index 3e5503a..61e522d 100644 --- a/src/main/java/swyp/team5/greening/petPlant/service/DailyRecordCommandService.java +++ b/src/main/java/swyp/team5/greening/petPlant/service/DailyRecordCommandService.java @@ -17,6 +17,7 @@ import swyp.team5.greening.petPlant.domain.repository.DailyRecordRepository; import swyp.team5.greening.petPlant.domain.repository.PetPlantRepository; import swyp.team5.greening.petPlant.dto.request.CreateDailyRecordRequestDto; +import swyp.team5.greening.petPlant.dto.request.UpdateDailyRecordRequestDto; import swyp.team5.greening.petPlant.dto.response.CreateDailyRecordResponseDto; import swyp.team5.greening.petPlant.exception.PetPlantExceptionMessage; @@ -78,4 +79,42 @@ public CreateDailyRecordResponseDto createDailyRecord( return new CreateDailyRecordResponseDto(saved.getId()); } + //게시글 수정 + //1. 오늘의 기록 조회 + //2. 권한 확인 + //3. 제목 수정 + //4. 새로운 본문 저장 + @Transactional + public void updateDailyRecord( + Long userId, + Long dailyRecordId, + UpdateDailyRecordRequestDto requestDto + + ) { + DailyRecord dailyRecord = dailyRecordRepository.findByIdAndState(dailyRecordId, + DailyRecordState.IN_PROGRESS) + .orElseThrow(() -> new GreeningGlobalException( + PetPlantExceptionMessage.NOT_FOUND_PET_PLANT)); + + PetPlant petPlant = petPlantRepository.findByIdAndState(dailyRecord.getPetPlantId(), + PetPlantState.IN_PROGRESS) + .orElseThrow(() -> new GreeningGlobalException( + PetPlantExceptionMessage.NOT_FOUND_PET_PLANT)); + + if (!Objects.equals(petPlant.getUserId(), userId)) { + throw new GreeningGlobalException(PetPlantExceptionMessage.BAD_REQUEST_PET_PLANT_WRITER); + } + + dailyRecord.updateTitle(requestDto.title()); + + List contents = requestDto.content().stream() + .map(dto -> DailyRecordContent.builder() + .content(dto.value()) + .type(DailyRecordContentType.valueOf(dto.type().toUpperCase())) + .build()) + .toList(); + + dailyRecord.updateContent(contents); + } + } From 13004febac77b97b2ffc27d15bf230e8cc7f5682 Mon Sep 17 00:00:00 2001 From: kkang_h00n Date: Mon, 7 Jul 2025 20:53:25 +0900 Subject: [PATCH 2/2] =?UTF-8?q?Feat:=20=ED=8A=B9=EC=A0=95=20=EC=95=A0?= =?UTF-8?q?=EC=99=84=20=EC=8B=9D=EB=AC=BC=20=E2=80=98=EC=98=A4=EB=8A=98?= =?UTF-8?q?=EC=9D=98=20=EA=B8=B0=EB=A1=9D=E2=80=99=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/DailyRecordController.java | 13 +++++- .../petPlant/domain/entity/DailyRecord.java | 4 ++ .../repository/DailyRecordRepository.java | 3 ++ .../exception/PetPlantExceptionMessage.java | 1 + .../service/DailyRecordCommandService.java | 41 +++++++++++++++++-- 5 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/main/java/swyp/team5/greening/petPlant/controller/DailyRecordController.java b/src/main/java/swyp/team5/greening/petPlant/controller/DailyRecordController.java index 1df31ef..b50e043 100644 --- a/src/main/java/swyp/team5/greening/petPlant/controller/DailyRecordController.java +++ b/src/main/java/swyp/team5/greening/petPlant/controller/DailyRecordController.java @@ -5,6 +5,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -63,7 +64,7 @@ public ApiResponseDto getDailyRecord( @Operation(summary = "특정 애완 식물 오늘의 기록 수정 API") @PutMapping("/daily-record/{dailyRecordId}") @ResponseStatus(HttpStatus.OK) - public void updateDailyRecord ( + public void updateDailyRecord( @LogIn Long userId, @PathVariable Long dailyRecordId, @Validated @RequestBody UpdateDailyRecordRequestDto requestDto @@ -71,4 +72,14 @@ public void updateDailyRecord ( dailyRecordCommandService.updateDailyRecord(userId, dailyRecordId, requestDto); } + @Operation(summary = "특정 애완 식물 오늘의 기록 삭제 API") + @DeleteMapping("/daily-record/{dailyRecordId}") + @ResponseStatus(HttpStatus.OK) + public void deleteDailyRecord( + @LogIn Long userId, + @PathVariable Long dailyRecordId + ) { + dailyRecordCommandService.deleteDailyRecord(userId, dailyRecordId); + } + } diff --git a/src/main/java/swyp/team5/greening/petPlant/domain/entity/DailyRecord.java b/src/main/java/swyp/team5/greening/petPlant/domain/entity/DailyRecord.java index b223c8b..b3f74b3 100644 --- a/src/main/java/swyp/team5/greening/petPlant/domain/entity/DailyRecord.java +++ b/src/main/java/swyp/team5/greening/petPlant/domain/entity/DailyRecord.java @@ -72,4 +72,8 @@ public void updateContent(List contents) { content.setSequence(index); } } + + public void delete() { + this.state = DailyRecordState.DELETED; + } } diff --git a/src/main/java/swyp/team5/greening/petPlant/domain/repository/DailyRecordRepository.java b/src/main/java/swyp/team5/greening/petPlant/domain/repository/DailyRecordRepository.java index 5f95503..06579f1 100644 --- a/src/main/java/swyp/team5/greening/petPlant/domain/repository/DailyRecordRepository.java +++ b/src/main/java/swyp/team5/greening/petPlant/domain/repository/DailyRecordRepository.java @@ -1,5 +1,6 @@ package swyp.team5.greening.petPlant.domain.repository; +import java.time.LocalDate; import java.util.Optional; import swyp.team5.greening.petPlant.domain.entity.DailyRecord; import swyp.team5.greening.petPlant.domain.entity.DailyRecordState; @@ -8,6 +9,8 @@ public interface DailyRecordRepository { DailyRecord save(DailyRecord dailyRecord); + boolean existsByPetPlantIdAndWriteDateAndState(Long petPlantId, LocalDate writeDate, DailyRecordState state); + Optional findByIdAndState(Long dailyRecordId, DailyRecordState state); void deleteAll(); diff --git a/src/main/java/swyp/team5/greening/petPlant/exception/PetPlantExceptionMessage.java b/src/main/java/swyp/team5/greening/petPlant/exception/PetPlantExceptionMessage.java index 20c3d6f..dfa0d6c 100644 --- a/src/main/java/swyp/team5/greening/petPlant/exception/PetPlantExceptionMessage.java +++ b/src/main/java/swyp/team5/greening/petPlant/exception/PetPlantExceptionMessage.java @@ -12,6 +12,7 @@ public enum PetPlantExceptionMessage implements ExceptionMessage { BAD_REQUEST_PET_PLANT_WRITER("내가 등록한 애완 식물이 아닙니다.", "400"), NOT_FOUND_DAILY_RECORD("해당 날짜의 기록이 존재하지 않습니다.", "404"), + ALREADY_EXISTS_DAILY_RECORD("이미 작성한 오늘의 기록이 존재합니다", "409"), INVALID_DATE_ACCESS("해당 날짜에만 접근 가능합니다.", "400"); diff --git a/src/main/java/swyp/team5/greening/petPlant/service/DailyRecordCommandService.java b/src/main/java/swyp/team5/greening/petPlant/service/DailyRecordCommandService.java index 61e522d..c638cfb 100644 --- a/src/main/java/swyp/team5/greening/petPlant/service/DailyRecordCommandService.java +++ b/src/main/java/swyp/team5/greening/petPlant/service/DailyRecordCommandService.java @@ -34,7 +34,8 @@ public class DailyRecordCommandService { //1. 애완 식물 조회 //2. 사용자 유효성 검증 //3. 오늘 날짜 여부 확인 - //4. 오늘의 기록 저장 + //4. 이미 오늘 작성한 오늘의 기록이 존재하는지 확인 + //5. 오늘의 기록 작성 @Transactional public CreateDailyRecordResponseDto createDailyRecord( Long userId, @@ -58,6 +59,12 @@ public CreateDailyRecordResponseDto createDailyRecord( } //4 + if (dailyRecordRepository.existsByPetPlantIdAndWriteDateAndState(petPlantId, + nowDate.get(), DailyRecordState.IN_PROGRESS)) { + throw new GreeningGlobalException(PetPlantExceptionMessage.ALREADY_EXISTS_DAILY_RECORD); + } + + //5 DailyRecord dailyRecord = DailyRecord.builder() .title(requestDto.title()) .writeDate(requestDto.today()) @@ -79,7 +86,7 @@ public CreateDailyRecordResponseDto createDailyRecord( return new CreateDailyRecordResponseDto(saved.getId()); } - //게시글 수정 + //오늘의 기록 수정 //1. 오늘의 기록 조회 //2. 권한 확인 //3. 제목 수정 @@ -102,7 +109,8 @@ public void updateDailyRecord( PetPlantExceptionMessage.NOT_FOUND_PET_PLANT)); if (!Objects.equals(petPlant.getUserId(), userId)) { - throw new GreeningGlobalException(PetPlantExceptionMessage.BAD_REQUEST_PET_PLANT_WRITER); + throw new GreeningGlobalException( + PetPlantExceptionMessage.BAD_REQUEST_PET_PLANT_WRITER); } dailyRecord.updateTitle(requestDto.title()); @@ -117,4 +125,31 @@ public void updateDailyRecord( dailyRecord.updateContent(contents); } + //오늘의 기록 삭제 + //1. 오늘의 기록 조회 + //2. 권한 확인 + //3. 삭제 + @Transactional + public void deleteDailyRecord( + Long userId, + Long dailyRecordId + ) { + DailyRecord dailyRecord = dailyRecordRepository.findByIdAndState(dailyRecordId, + DailyRecordState.IN_PROGRESS) + .orElseThrow(() -> new GreeningGlobalException( + PetPlantExceptionMessage.NOT_FOUND_PET_PLANT)); + + PetPlant petPlant = petPlantRepository.findByIdAndState(dailyRecord.getPetPlantId(), + PetPlantState.IN_PROGRESS) + .orElseThrow(() -> new GreeningGlobalException( + PetPlantExceptionMessage.NOT_FOUND_PET_PLANT)); + + if (!Objects.equals(petPlant.getUserId(), userId)) { + throw new GreeningGlobalException( + PetPlantExceptionMessage.BAD_REQUEST_PET_PLANT_WRITER); + } + + dailyRecord.delete(); + } + }