diff --git a/src/main/java/com/bbteam/budgetbuddies/apiPayload/code/status/ErrorStatus.java b/src/main/java/com/bbteam/budgetbuddies/apiPayload/code/status/ErrorStatus.java index 62b158b0..b8dc8c81 100644 --- a/src/main/java/com/bbteam/budgetbuddies/apiPayload/code/status/ErrorStatus.java +++ b/src/main/java/com/bbteam/budgetbuddies/apiPayload/code/status/ErrorStatus.java @@ -12,6 +12,7 @@ public enum ErrorStatus implements BaseErrorCode { _INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMMON500", "서버에러"), + _BAD_REQUEST(HttpStatus.BAD_REQUEST, "COMMON400", "잘못된 요청"), USER_NOT_FOUND(HttpStatus.BAD_REQUEST, "USER4001", "사용자가 없습니다."), COMMENT_NOT_FOUND(HttpStatus.BAD_REQUEST, "COMMENT4001", "해당 댓글이 없습니다.") , PAGE_LOWER_ZERO(HttpStatus.BAD_REQUEST, "PAGE4001", "요청된 페이지가 0보다 작습니다."); diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/comment/controller/CommentController.java b/src/main/java/com/bbteam/budgetbuddies/domain/comment/controller/CommentController.java index d071fec8..3d96a560 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/comment/controller/CommentController.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/comment/controller/CommentController.java @@ -6,6 +6,7 @@ import com.bbteam.budgetbuddies.domain.comment.service.CommentService; import com.bbteam.budgetbuddies.domain.comment.validation.ExistComment; import com.bbteam.budgetbuddies.domain.user.validation.ExistUser; +import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -75,27 +76,27 @@ public ApiResponse deleteComment(@PathVariable("commentId") @ExistCommen } @GetMapping("/supports/comments/getOne/{commentId}") - public ApiResponse findSupportOne(@PathVariable("commentId")Long commentId) { + public ApiResponse findSupportOne(@PathVariable("commentId") @ExistComment Long commentId) { CommentResponseDto.SupportInfoCommentResponseDto result = supportCommentService.findCommentOne(commentId); return ApiResponse.onSuccess(result); } @PutMapping("/supports/comments/modify") public ApiResponse modifySupportOne( - @RequestBody CommentRequestDto.CommentModifyRequestDto dto) { + @RequestBody @Valid CommentRequestDto.CommentModifyRequestDto dto) { CommentResponseDto.SupportInfoCommentResponseDto result = supportCommentService.modifyComment(dto); return ApiResponse.onSuccess(result); } @GetMapping("/discounts/comments/getOne/{commentId}") - public ApiResponse findDiscountOne(@PathVariable("commentId")Long commentId) { + public ApiResponse findDiscountOne(@PathVariable("commentId") @ExistComment Long commentId) { CommentResponseDto.DiscountInfoCommentResponseDto result = discountCommentService.findCommentOne(commentId); return ApiResponse.onSuccess(result); } @PutMapping("/discounts/comments/modify") public ApiResponse modifyDiscountOne( - @RequestBody CommentRequestDto.CommentModifyRequestDto dto) { + @RequestBody @Valid CommentRequestDto.CommentModifyRequestDto dto) { CommentResponseDto.DiscountInfoCommentResponseDto result = discountCommentService.modifyComment(dto); return ApiResponse.onSuccess(result); } diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/comment/controller/CommentControllerApi.java b/src/main/java/com/bbteam/budgetbuddies/domain/comment/controller/CommentControllerApi.java index 87c0b0a7..b8279e41 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/comment/controller/CommentControllerApi.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/comment/controller/CommentControllerApi.java @@ -10,11 +10,11 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.responses.ApiResponses; +import jakarta.validation.Valid; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @@ -90,7 +90,7 @@ ApiResponse> findAllBySup @Parameters({ @Parameter(name = "commentId", description = "조회할 댓글 id 입니다. pathVariable") }) - ApiResponse findSupportOne(@RequestParam("commentId")Long commentId); + ApiResponse findSupportOne(@PathVariable("commentId") @ExistComment Long commentId); @Operation(summary = "[User] SupportInfo의 댓글 변경 API", description = "특정 댓글을 변경하는 API입니다.") @ApiResponses({ @@ -102,7 +102,7 @@ ApiResponse> findAllBySup }) ApiResponse modifySupportOne( - @RequestBody CommentRequestDto.CommentModifyRequestDto dto); + @RequestBody @Valid CommentRequestDto.CommentModifyRequestDto dto); @Operation(summary = "[User] DiscountInfo의 특정 댓글 요청 API", description = "특정 댓글을 요청하는 API입니다.") @@ -112,7 +112,7 @@ ApiResponse modifySupportOne( @Parameters({ @Parameter(name = "commentId", description = "조회할 댓글 id 입니다. pathVariable") }) - ApiResponse findDiscountOne(@RequestParam("commentId")Long commentId); + ApiResponse findDiscountOne(@PathVariable("commentId") @ExistComment Long commentId); @Operation(summary = "[User] DiscountInfo의 댓글 변경 API", description = "특정 댓글을 변경하는 API입니다.") @ApiResponses({ @@ -124,6 +124,6 @@ ApiResponse modifySupportOne( }) ApiResponse modifyDiscountOne( - @RequestBody CommentRequestDto.CommentModifyRequestDto dto); + @RequestBody @Valid CommentRequestDto.CommentModifyRequestDto dto); } diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/comment/dto/CommentRequestDto.java b/src/main/java/com/bbteam/budgetbuddies/domain/comment/dto/CommentRequestDto.java index ae354563..3d4ce6c6 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/comment/dto/CommentRequestDto.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/comment/dto/CommentRequestDto.java @@ -1,5 +1,6 @@ package com.bbteam.budgetbuddies.domain.comment.dto; +import com.bbteam.budgetbuddies.domain.comment.validation.ExistComment; import lombok.Builder; import lombok.Getter; @@ -23,6 +24,8 @@ public static class SupportInfoCommentRequestDto { @Builder public static class CommentModifyRequestDto { private String content; + + @ExistComment private Long commentId; } } diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/expense/controller/ExpenseApi.java b/src/main/java/com/bbteam/budgetbuddies/domain/expense/controller/ExpenseApi.java index 70ddae63..aedb93d6 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/expense/controller/ExpenseApi.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/expense/controller/ExpenseApi.java @@ -15,7 +15,7 @@ import com.bbteam.budgetbuddies.domain.expense.dto.ExpenseRequestDto; import com.bbteam.budgetbuddies.domain.expense.dto.ExpenseResponseDto; import com.bbteam.budgetbuddies.domain.expense.dto.ExpenseUpdateRequestDto; -import com.bbteam.budgetbuddies.domain.expense.dto.MonthlyExpenseCompactResponseDto; +import com.bbteam.budgetbuddies.domain.expense.dto.MonthlyExpenseResponseDto; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -42,7 +42,7 @@ ResponseEntity createExpense( @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH003", description = "access 토큰을 주세요!", content = @Content(schema = @Schema(implementation = ApiResponse.class))), @ApiResponse(responseCode = "AUTH004", description = "access 토큰 만료", content = @Content(schema = @Schema(implementation = ApiResponse.class))), @ApiResponse(responseCode = "AUTH006", description = "access 토큰 모양이 이상함", content = @Content(schema = @Schema(implementation = ApiResponse.class)))}) - ResponseEntity findExpensesForMonth( + ResponseEntity findExpensesForMonth( @PathVariable @Param("userId") Long userId, @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate date); diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/expense/controller/ExpenseController.java b/src/main/java/com/bbteam/budgetbuddies/domain/expense/controller/ExpenseController.java index d2762713..c6499330 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/expense/controller/ExpenseController.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/expense/controller/ExpenseController.java @@ -17,7 +17,7 @@ import com.bbteam.budgetbuddies.domain.expense.dto.ExpenseRequestDto; import com.bbteam.budgetbuddies.domain.expense.dto.ExpenseResponseDto; import com.bbteam.budgetbuddies.domain.expense.dto.ExpenseUpdateRequestDto; -import com.bbteam.budgetbuddies.domain.expense.dto.MonthlyExpenseCompactResponseDto; +import com.bbteam.budgetbuddies.domain.expense.dto.MonthlyExpenseResponseDto; import com.bbteam.budgetbuddies.domain.expense.service.ExpenseService; import io.swagger.v3.oas.annotations.Parameter; @@ -40,7 +40,7 @@ public ResponseEntity createExpense( @Override @GetMapping("/{userId}") - public ResponseEntity findExpensesForMonth( + public ResponseEntity findExpensesForMonth( @PathVariable @Param("userId") Long userId, @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate date) { diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/expense/converter/ExpenseConverter.java b/src/main/java/com/bbteam/budgetbuddies/domain/expense/converter/ExpenseConverter.java index f54098eb..665849d1 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/expense/converter/ExpenseConverter.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/expense/converter/ExpenseConverter.java @@ -1,7 +1,6 @@ package com.bbteam.budgetbuddies.domain.expense.converter; import java.time.LocalDate; -import java.time.LocalDateTime; import java.time.format.TextStyle; import java.util.List; import java.util.Locale; @@ -12,9 +11,10 @@ import com.bbteam.budgetbuddies.domain.category.entity.Category; import com.bbteam.budgetbuddies.domain.expense.dto.CompactExpenseResponseDto; +import com.bbteam.budgetbuddies.domain.expense.dto.DailyExpenseResponseDto; import com.bbteam.budgetbuddies.domain.expense.dto.ExpenseRequestDto; import com.bbteam.budgetbuddies.domain.expense.dto.ExpenseResponseDto; -import com.bbteam.budgetbuddies.domain.expense.dto.MonthlyExpenseCompactResponseDto; +import com.bbteam.budgetbuddies.domain.expense.dto.MonthlyExpenseResponseDto; import com.bbteam.budgetbuddies.domain.expense.entity.Expense; import com.bbteam.budgetbuddies.domain.user.entity.User; @@ -43,24 +43,33 @@ public ExpenseResponseDto toExpenseResponseDto(Expense expense) { .build(); } - public MonthlyExpenseCompactResponseDto toMonthlyExpenseCompactResponseDto(List expenseList, - LocalDate startOfMonth) { + public MonthlyExpenseResponseDto toMonthlyExpenseResponseDto(List expenseList, LocalDate startOfMonth) { Long totalConsumptionAmount = expenseList.stream().mapToLong(Expense::getAmount).sum(); - Map> expenses = expenseList.stream().collect( - Collectors.groupingBy(e -> this.convertDayToKorean(e.getExpenseDate()), - Collectors.mapping(this::toExpenseCompactResponseDto, Collectors.toList()))); + List dailyExpenses = toDailyExpenseResponseDto(expenseList); - return MonthlyExpenseCompactResponseDto.builder() + return MonthlyExpenseResponseDto.builder() .expenseMonth(startOfMonth) .totalConsumptionAmount(totalConsumptionAmount) - .expenses(expenses) + .dailyExpenses(dailyExpenses) .build(); } - private String convertDayToKorean(LocalDateTime localDateTime) { - return localDateTime.getDayOfMonth() + "일 " + localDateTime.getDayOfWeek() - .getDisplayName(TextStyle.FULL, Locale.KOREAN); + private List toDailyExpenseResponseDto(List expenseList) { + Map> expenses = expenseList.stream() + .collect(Collectors.groupingBy(e -> e.getExpenseDate().toLocalDate(), + Collectors.mapping(this::toExpenseCompactResponseDto, Collectors.toList()))); + + return expenses.keySet().stream().map(k -> this.generateDailyExpenseResponseDto(k, expenses.get(k))).toList(); + } + + private DailyExpenseResponseDto generateDailyExpenseResponseDto(LocalDate date, + List expenses) { + return DailyExpenseResponseDto.builder() + .daysOfMonth(date.getDayOfMonth()) + .daysOfTheWeek(date.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.KOREAN)) + .expenses(expenses) + .build(); } private CompactExpenseResponseDto toExpenseCompactResponseDto(Expense expense) { diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/DailyExpenseResponseDto.java b/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/DailyExpenseResponseDto.java new file mode 100644 index 00000000..14dc44ae --- /dev/null +++ b/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/DailyExpenseResponseDto.java @@ -0,0 +1,19 @@ +package com.bbteam.budgetbuddies.domain.expense.dto; + +import java.util.List; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@AllArgsConstructor +@Builder +@Getter +public class DailyExpenseResponseDto { + private Integer daysOfMonth; + private String daysOfTheWeek; + private List expenses; +} diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/MonthlyExpenseCompactResponseDto.java b/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/MonthlyExpenseResponseDto.java similarity index 75% rename from src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/MonthlyExpenseCompactResponseDto.java rename to src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/MonthlyExpenseResponseDto.java index c23523e6..efed1582 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/MonthlyExpenseCompactResponseDto.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/MonthlyExpenseResponseDto.java @@ -2,7 +2,6 @@ import java.time.LocalDate; import java.util.List; -import java.util.Map; import lombok.AccessLevel; import lombok.AllArgsConstructor; @@ -14,9 +13,9 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) @AllArgsConstructor @Builder -public class MonthlyExpenseCompactResponseDto { +public class MonthlyExpenseResponseDto { private LocalDate expenseMonth; private Long totalConsumptionAmount; - private Map> expenses; + private List dailyExpenses; } diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/expense/service/ExpenseService.java b/src/main/java/com/bbteam/budgetbuddies/domain/expense/service/ExpenseService.java index 4374284e..67df0f7e 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/expense/service/ExpenseService.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/expense/service/ExpenseService.java @@ -5,12 +5,12 @@ import com.bbteam.budgetbuddies.domain.expense.dto.ExpenseRequestDto; import com.bbteam.budgetbuddies.domain.expense.dto.ExpenseResponseDto; import com.bbteam.budgetbuddies.domain.expense.dto.ExpenseUpdateRequestDto; -import com.bbteam.budgetbuddies.domain.expense.dto.MonthlyExpenseCompactResponseDto; +import com.bbteam.budgetbuddies.domain.expense.dto.MonthlyExpenseResponseDto; public interface ExpenseService { ExpenseResponseDto createExpense(Long userId, ExpenseRequestDto expenseRequestDto); - MonthlyExpenseCompactResponseDto getMonthlyExpense(Long userId, LocalDate localDate); + MonthlyExpenseResponseDto getMonthlyExpense(Long userId, LocalDate localDate); ExpenseResponseDto findExpenseResponseFromUserIdAndExpenseId(Long userId, Long expenseId); diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/expense/service/ExpenseServiceImpl.java b/src/main/java/com/bbteam/budgetbuddies/domain/expense/service/ExpenseServiceImpl.java index 40390a76..be4ba45c 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/expense/service/ExpenseServiceImpl.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/expense/service/ExpenseServiceImpl.java @@ -14,7 +14,7 @@ import com.bbteam.budgetbuddies.domain.expense.dto.ExpenseRequestDto; import com.bbteam.budgetbuddies.domain.expense.dto.ExpenseResponseDto; import com.bbteam.budgetbuddies.domain.expense.dto.ExpenseUpdateRequestDto; -import com.bbteam.budgetbuddies.domain.expense.dto.MonthlyExpenseCompactResponseDto; +import com.bbteam.budgetbuddies.domain.expense.dto.MonthlyExpenseResponseDto; import com.bbteam.budgetbuddies.domain.expense.entity.Expense; import com.bbteam.budgetbuddies.domain.expense.repository.ExpenseRepository; import com.bbteam.budgetbuddies.domain.user.entity.User; @@ -92,7 +92,7 @@ public void deleteExpense(Long expenseId) { @Override @Transactional(readOnly = true) - public MonthlyExpenseCompactResponseDto getMonthlyExpense(Long userId, LocalDate localDate) { + public MonthlyExpenseResponseDto getMonthlyExpense(Long userId, LocalDate localDate) { LocalDate startOfMonth = localDate.withDayOfMonth(1); LocalDate endOfMonth = localDate.withDayOfMonth(startOfMonth.lengthOfMonth()); @@ -101,7 +101,7 @@ public MonthlyExpenseCompactResponseDto getMonthlyExpense(Long userId, LocalDate List expenseSlice = expenseRepository.findAllByUserIdForPeriod(user, startOfMonth.atStartOfDay(), endOfMonth.atStartOfDay()); - return expenseConverter.toMonthlyExpenseCompactResponseDto(expenseSlice, startOfMonth); + return expenseConverter.toMonthlyExpenseResponseDto(expenseSlice, startOfMonth); } @Override diff --git a/src/test/java/com/bbteam/budgetbuddies/domain/expense/service/ExpenseServiceImplTest.java b/src/test/java/com/bbteam/budgetbuddies/domain/expense/service/ExpenseServiceImplTest.java index a82e77d1..2c7a8484 100644 --- a/src/test/java/com/bbteam/budgetbuddies/domain/expense/service/ExpenseServiceImplTest.java +++ b/src/test/java/com/bbteam/budgetbuddies/domain/expense/service/ExpenseServiceImplTest.java @@ -7,7 +7,6 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; -import java.util.Map; import java.util.Optional; import org.junit.jupiter.api.BeforeEach; @@ -24,8 +23,9 @@ import com.bbteam.budgetbuddies.domain.category.repository.CategoryRepository; import com.bbteam.budgetbuddies.domain.expense.converter.ExpenseConverter; import com.bbteam.budgetbuddies.domain.expense.dto.CompactExpenseResponseDto; +import com.bbteam.budgetbuddies.domain.expense.dto.DailyExpenseResponseDto; import com.bbteam.budgetbuddies.domain.expense.dto.ExpenseResponseDto; -import com.bbteam.budgetbuddies.domain.expense.dto.MonthlyExpenseCompactResponseDto; +import com.bbteam.budgetbuddies.domain.expense.dto.MonthlyExpenseResponseDto; import com.bbteam.budgetbuddies.domain.expense.entity.Expense; import com.bbteam.budgetbuddies.domain.expense.repository.ExpenseRepository; import com.bbteam.budgetbuddies.domain.user.entity.User; @@ -54,7 +54,7 @@ void setUp() { } @Test - @DisplayName("월별 소비 조회 소비를 d일 N요일로 묶어서 반환") + @DisplayName("월별 소비 조회 소비를 DailyExpenseResponseDto로 반환") void getMonthlyExpense_Success() { // given given(userRepository.findById(user.getId())).willReturn(Optional.of(user)); @@ -69,27 +69,32 @@ void getMonthlyExpense_Success() { given(expenseRepository.findAllByUserIdForPeriod(any(User.class), any(LocalDateTime.class), any(LocalDateTime.class))).willReturn(expenses); - MonthlyExpenseCompactResponseDto expected = - MonthlyExpenseCompactResponseDto.builder() - .expenseMonth(LocalDate.of(2024, 07, 01)) - .totalConsumptionAmount(300_000L) - .expenses(Map.of( - "2일 화요일", List.of(CompactExpenseResponseDto.builder() - .amount(200_000L) - .description("User 소비") - .expenseId(-2L) - .categoryId(userCategory.getId()) - .build()), - "1일 월요일", List.of(CompactExpenseResponseDto.builder() - .amount(100_000L) - .description("User 소비") - .expenseId(-1L) - .categoryId(userCategory.getId()) - .build()))) - .build(); + MonthlyExpenseResponseDto expected = MonthlyExpenseResponseDto.builder() + .expenseMonth(LocalDate.of(2024, 07, 01)) + .totalConsumptionAmount(300_000L) + .dailyExpenses(List.of(DailyExpenseResponseDto.builder() + .daysOfMonth(2) + .daysOfTheWeek("화요일") + .expenses(List.of(CompactExpenseResponseDto.builder() + .amount(200_000L) + .description("User 소비") + .expenseId(-2L) + .categoryId(userCategory.getId()) + .build())) + .build(), DailyExpenseResponseDto.builder() + .daysOfMonth(1) + .daysOfTheWeek("월요일") + .expenses(List.of(CompactExpenseResponseDto.builder() + .amount(100_000L) + .description("User 소비") + .expenseId(-1L) + .categoryId(userCategory.getId()) + .build())) + .build())) + .build(); // when - MonthlyExpenseCompactResponseDto result = expenseService.getMonthlyExpense(user.getId(), requestMonth); + MonthlyExpenseResponseDto result = expenseService.getMonthlyExpense(user.getId(), requestMonth); // then assertThat(result).usingRecursiveComparison().isEqualTo(expected);