diff --git a/server/src/main/java/server/haengdong/application/BillActionService.java b/server/src/main/java/server/haengdong/application/BillActionService.java index fa00fabd6..68abb466e 100644 --- a/server/src/main/java/server/haengdong/application/BillActionService.java +++ b/server/src/main/java/server/haengdong/application/BillActionService.java @@ -64,4 +64,12 @@ private Event getEvent(String eventToken) { return eventRepository.findByToken(eventToken) .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); } + + @Transactional + public void deleteBillAction(String token, Long actionId) { + Event event = eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); + + billActionRepository.deleteByAction_EventAndActionId(event, actionId); + } } diff --git a/server/src/main/java/server/haengdong/domain/action/BillAction.java b/server/src/main/java/server/haengdong/domain/action/BillAction.java index 273965755..738b04d39 100644 --- a/server/src/main/java/server/haengdong/domain/action/BillAction.java +++ b/server/src/main/java/server/haengdong/domain/action/BillAction.java @@ -54,15 +54,14 @@ private void validateTitle(String title) { int titleLength = title.trim().length(); if (titleLength < MIN_TITLE_LENGTH || titleLength > MAX_TITLE_LENGTH) { throw new HaengdongException(HaengdongErrorCode.BAD_REQUEST, - String.format("앞뒤 공백을 제거한 지출 내역 제목은 %d ~ %d자여야 합니다.", MIN_TITLE_LENGTH, - MAX_TITLE_LENGTH)); + String.format("앞뒤 공백을 제거한 지출 내역 제목은 %d ~ %d자여야 합니다.", MIN_TITLE_LENGTH, MAX_TITLE_LENGTH)); } } private void validatePrice(Long price) { if (price < MIN_PRICE || price > MAX_PRICE) { throw new HaengdongException(HaengdongErrorCode.BAD_REQUEST, - String.format("지출 금액은 %,d 이하의 자연수여야 합니다.", MAX_PRICE)); + String.format("지출 금액은 %,d 이하의 자연수여야 합니다.", MAX_PRICE)); } } diff --git a/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java b/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java index 389b498db..a0e6a1bf1 100644 --- a/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java +++ b/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java @@ -13,5 +13,7 @@ public interface BillActionRepository extends JpaRepository { @EntityGraph(attributePaths = {"action"}) List findByAction_Event(Event event); + void deleteByAction_EventAndActionId(Event event, Long actionId); + Optional findByAction_Id(Long actionId); } diff --git a/server/src/main/java/server/haengdong/domain/event/EventRepository.java b/server/src/main/java/server/haengdong/domain/event/EventRepository.java index 6038c368b..09526125e 100644 --- a/server/src/main/java/server/haengdong/domain/event/EventRepository.java +++ b/server/src/main/java/server/haengdong/domain/event/EventRepository.java @@ -6,6 +6,6 @@ @Repository public interface EventRepository extends JpaRepository { - + Optional findByToken(String token); } diff --git a/server/src/main/java/server/haengdong/presentation/BillActionController.java b/server/src/main/java/server/haengdong/presentation/BillActionController.java index 7fe0a5ec0..251f69831 100644 --- a/server/src/main/java/server/haengdong/presentation/BillActionController.java +++ b/server/src/main/java/server/haengdong/presentation/BillActionController.java @@ -3,14 +3,15 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; 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.RestController; import server.haengdong.application.BillActionService; -import server.haengdong.presentation.request.BillActionsSaveRequest; import server.haengdong.presentation.request.BillActionUpdateRequest; +import server.haengdong.presentation.request.BillActionsSaveRequest; @RequiredArgsConstructor @RestController @@ -40,4 +41,15 @@ public ResponseEntity updateBillAction( return ResponseEntity.ok() .build(); } + + @DeleteMapping("/api/events/{eventId}/actions/{actionId}/bills") + public ResponseEntity deleteBillAction( + @PathVariable("eventId") String token, + @PathVariable("actionId") Long actionId + ) { + billActionService.deleteBillAction(token, actionId); + + return ResponseEntity.ok() + .build(); + } } diff --git a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java index 82ac51a4a..98e0b13b1 100644 --- a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java +++ b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java @@ -123,4 +123,26 @@ void updateBillAction1() { assertThatThrownBy(() -> billActionService.updateBillAction(token2, actionId, request)) .isInstanceOf(HaengdongException.class); } + + @DisplayName("지출 내역을 삭제한다.") + @Test + void deleteBillAction() { + String token = "토다리 토큰"; + Event event = new Event("감자", token); + eventRepository.save(event); + BillAction billAction = new BillAction(new Action(event, 1L), "커피", 50_900L); + billActionRepository.save(billAction); + Long actionId = billAction.getAction().getId(); + + billActionService.deleteBillAction(token, actionId); + + assertThat(billActionRepository.findById(billAction.getId())).isEmpty(); + } + + @DisplayName("지출 내역 삭제 시 행사가 존재하지 않으면 예외가 발생한다.") + @Test + void deleteBillAction1() { + assertThatThrownBy(() -> billActionService.deleteBillAction("소하망쵸", 1L)) + .isInstanceOf(HaengdongException.class); + } } diff --git a/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java index bfd844b8e..3170707d6 100644 --- a/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java +++ b/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java @@ -1,5 +1,8 @@ package server.haengdong.presentation; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doThrow; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; @@ -15,6 +18,8 @@ import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import server.haengdong.application.BillActionService; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; import server.haengdong.presentation.request.BillActionSaveRequest; import server.haengdong.presentation.request.BillActionsSaveRequest; import server.haengdong.presentation.request.BillActionUpdateRequest; @@ -83,4 +88,26 @@ void updateBillAction() throws Exception { .andDo(print()) .andExpect(status().isOk()); } + + @DisplayName("지출 내역을 삭제한다.") + @Test + void deleteBillAction() throws Exception { + String token = "토다리토큰"; + + mockMvc.perform(delete("/api/events/{token}/actions/{actionId}/bills", token, 1)) + .andDo(print()) + .andExpect(status().isOk()); + } + + @DisplayName("존재하지 않는 행사에 대한 지출 내역을 삭제할 수 없다.") + @Test + void deleteBillAction1() throws Exception { + String token = "TOKEN19348"; + doThrow(new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)) + .when(billActionService).deleteBillAction(any(String.class), any(Long.class)); + + mockMvc.perform(delete("/api/events/{token}/actions/{actionId}/bills", token, 1)) + .andDo(print()) + .andExpect(status().isBadRequest()); + } }