diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/controller/ConsumptionGoalApi.java b/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/controller/ConsumptionGoalApi.java index c14c7262..97b0e9ce 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/controller/ConsumptionGoalApi.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/controller/ConsumptionGoalApi.java @@ -1,70 +1,86 @@ package com.bbteam.budgetbuddies.domain.consumptiongoal.controller; import java.time.LocalDate; +import java.util.List; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PathVariable; +import com.bbteam.budgetbuddies.apiPayload.ApiResponse; +import com.bbteam.budgetbuddies.domain.consumptiongoal.dto.AllConsumptionCategoryResponseDto; +import com.bbteam.budgetbuddies.domain.consumptiongoal.dto.ConsumptionAnalysisResponseDto; import com.bbteam.budgetbuddies.domain.consumptiongoal.dto.ConsumptionGoalListRequestDto; import com.bbteam.budgetbuddies.domain.consumptiongoal.dto.ConsumptionGoalResponseListDto; +import com.bbteam.budgetbuddies.domain.consumptiongoal.dto.PeerInfoResponseDto; +import com.bbteam.budgetbuddies.domain.consumptiongoal.dto.TopCategoryConsumptionDto; +import com.bbteam.budgetbuddies.domain.consumptiongoal.dto.TopGoalCategoryResponseDto; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; -import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; public interface ConsumptionGoalApi { @Operation(summary = "또래들이 가장 큰 계획을 세운 카테고리 조회 Top4 API", description = "특정 사용자의 소비 목표 카테고리별 소비 목표 금액을 조회하는 API 입니다.") - @ApiResponses(value = {@ApiResponse(responseCode = "COMMON200", description = "OK, 성공")}) + @ApiResponses(value = { + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공")}) @Parameters({@Parameter(name = "userId", description = "로그인 한 유저 아이디"), @Parameter(name = "peerAgeStart", description = "또래나이 시작 범위"), @Parameter(name = "peerAgeEnd", description = "또래나이 끝 범위"), @Parameter(name = "peerGender", description = "또래 성별")}) - ResponseEntity getTopConsumptionGoalCategories(Long userId, int peerAgeStart, int peerAgeEnd, String peerGender); + ApiResponse> getTopConsumptionGoalCategories( + Long userId, int peerAgeStart, int peerAgeEnd, String peerGender); @Operation(summary = "또래들이 가장 많이 계획한 카테고리와 평균 금액 및 내 목표금액 차이 조회 API", description = "특정 사용자의 또래 소비 카테고리별 평균 목표 금액을 조회하는 API 입니다.") - @ApiResponses(value = {@ApiResponse(responseCode = "COMMON200", description = "OK, 성공")}) + @ApiResponses(value = { + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공")}) @Parameters({@Parameter(name = "userId", description = "로그인 한 유저 아이디"), @Parameter(name = "peerAgeStart", description = "또래나이 시작 범위"), @Parameter(name = "peerAgeEnd", description = "또래나이 끝 범위"), @Parameter(name = "peerGender", description = "또래 성별")}) - ResponseEntity getAllConsumptionGoalCategories(Long userId, int peerAgeStart, int peerAgeEnd, String peerGender); + ApiResponse> getAllConsumptionGoalCategories(Long userId, int peerAgeStart, + int peerAgeEnd, String peerGender); @Operation(summary = "또래나이와 성별 조회 API", description = "또래나이와 성별을 조회하는 API 입니다.") - @ApiResponses(value = {@ApiResponse(responseCode = "COMMON200", description = "OK, 성공")}) + @ApiResponses(value = { + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공")}) @Parameters({@Parameter(name = "userId", description = "로그인 한 유저 아이디"), @Parameter(name = "peerAgeStart", description = "또래나이 시작 범위"), @Parameter(name = "peerAgeEnd", description = "또래나이 끝 범위"), @Parameter(name = "peerGender", description = "또래 성별")}) - ResponseEntity getPeerInfo(Long userId, int peerAgeStart, int peerAgeEnd, String peerGender); + ApiResponse getPeerInfo(Long userId, int peerAgeStart, int peerAgeEnd, String peerGender); @Operation(summary = "소비 목표 조회 API", description = "date={yyyy-MM-dd} 형식의 query string을 통해서 사용자의 목표 달을 조회하는 API 입니다.") @Parameters({@Parameter(name = "date", description = "yyyy-MM-dd 형식으로 목표 달의 소비를 조회")}) - ResponseEntity findUserConsumptionGoal(LocalDate date, Long userId); + ApiResponse findUserConsumptionGoal(LocalDate date, Long userId); @Operation(summary = "이번 달 소비 목표 수정 API", description = "다른 달의 소비 목표를 업데이트하는 것은 불가능하고 오직 이번 달의 소비 목표만 업데이트 하는 API 입니다.") ResponseEntity updateOrElseGenerateConsumptionGoal(Long userId, ConsumptionGoalListRequestDto consumptionGoalListRequestDto); @Operation(summary = "또래들이 가장 많이한 소비 카테고리 조회 Top3 API", description = "특정 사용자의 또래 소비 카테고리별 소비 건 수을 조회하는 API 입니다.") - @ApiResponses(value = {@ApiResponse(responseCode = "COMMON200", description = "OK, 성공")}) + @ApiResponses(value = { + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공")}) @Parameters({@Parameter(name = "userId", description = "로그인 한 유저 아이디"), @Parameter(name = "peerAgeStart", description = "또래나이 시작 범위"), @Parameter(name = "peerAgeEnd", description = "또래나이 끝 범위"), @Parameter(name = "peerGender", description = "또래 성별")}) - ResponseEntity getTopConsumptionCategories(Long userId, int peerAgeStart, int peerAgeEnd, String peerGender); + ApiResponse> getTopConsumptionCategories(Long userId, int peerAgeStart, + int peerAgeEnd, String peerGender); @Operation(summary = "또래들이 가장 많이한 소비 카테고리와 평균 금액 및 내 소비금액 차이 조회 API", description = "특정 사용자의 또래 소비 카테고리별 평균 소비 금액을 조회하는 API 입니다.") - @ApiResponses(value = {@ApiResponse(responseCode = "COMMON200", description = "OK, 성공")}) + @ApiResponses(value = { + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공")}) @Parameters({@Parameter(name = "userId", description = "로그인 한 유저 아이디"), @Parameter(name = "peerAgeStart", description = "또래나이 시작 범위"), @Parameter(name = "peerAgeEnd", description = "또래나이 끝 범위"), @Parameter(name = "peerGender", description = "또래 성별")}) - ResponseEntity getAllConsumptionCategories(Long userId, int peerAgeStart, int peerAgeEnd, String peerGender); + ApiResponse> getAllConsumptionCategories(Long userId, int peerAgeStart, + int peerAgeEnd, String peerGender); @Operation(summary = "또래들이 가장 큰 목표로 세운 카테고리와 그 카테고리에서 이번주 사용한 금액 조회 API", description = "특정 사용자의 또래 소비 카테고리별 이번주 소비 금액을 조회하는 API 입니다.") - @ApiResponses(value = {@ApiResponse(responseCode = "COMMON200", description = "OK, 성공")}) - ResponseEntity getTopCategoryAndConsumptionAmount(@PathVariable Long userId); + @ApiResponses(value = { + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공")}) + ApiResponse getTopCategoryAndConsumptionAmount(@PathVariable Long userId); } \ No newline at end of file diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/controller/ConsumptionGoalController.java b/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/controller/ConsumptionGoalController.java index 04add868..0233a4c6 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/controller/ConsumptionGoalController.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/controller/ConsumptionGoalController.java @@ -13,7 +13,9 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import com.bbteam.budgetbuddies.apiPayload.ApiResponse; import com.bbteam.budgetbuddies.domain.consumptiongoal.dto.AllConsumptionCategoryResponseDto; +import com.bbteam.budgetbuddies.domain.consumptiongoal.dto.ConsumptionAnalysisResponseDto; import com.bbteam.budgetbuddies.domain.consumptiongoal.dto.ConsumptionGoalListRequestDto; import com.bbteam.budgetbuddies.domain.consumptiongoal.dto.ConsumptionGoalResponseListDto; import com.bbteam.budgetbuddies.domain.consumptiongoal.dto.PeerInfoResponseDto; @@ -32,43 +34,45 @@ public class ConsumptionGoalController implements ConsumptionGoalApi { @Override @GetMapping("/top-categories/top-goal/4") - public ResponseEntity getTopConsumptionGoalCategories(@RequestParam(name = "userId") Long userId, + public ApiResponse> getTopConsumptionGoalCategories( + @RequestParam(name = "userId") Long userId, @RequestParam(name = "peerAgeStart", defaultValue = "0") int peerAgeStart, @RequestParam(name = "peerAgeEnd", defaultValue = "0") int peerAgeEnd, @RequestParam(name = "peerGender", defaultValue = "none") String peerGender) { - List topCategoriesList = consumptionGoalService.getTopConsumptionGoalCategories( + List response = consumptionGoalService.getTopConsumptionGoalCategories( userId, peerAgeStart, peerAgeEnd, peerGender); - return ResponseEntity.ok(topCategoriesList); + return ApiResponse.onSuccess(response); } @GetMapping("/top-categories/top-goal") - public ResponseEntity getAllConsumptionGoalCategories(@RequestParam(name = "userId") Long userId, + public ApiResponse> getAllConsumptionGoalCategories( + @RequestParam(name = "userId") Long userId, @RequestParam(name = "peerAgeStart", defaultValue = "0") int peerAgeStart, @RequestParam(name = "peerAgeEnd", defaultValue = "0") int peerAgeEnd, @RequestParam(name = "peerGender", defaultValue = "none") String peerGender) { List response = consumptionGoalService.getAllConsumptionGoalCategories( userId, peerAgeStart, peerAgeEnd, peerGender); - return ResponseEntity.ok(response); + return ApiResponse.onSuccess(response); } @Override @GetMapping("/peer-info") - public ResponseEntity getPeerInfo(@RequestParam(name = "userId") Long userId, + public ApiResponse getPeerInfo(@RequestParam(name = "userId") Long userId, @RequestParam(name = "peerAgeStart", defaultValue = "0") int peerAgeStart, @RequestParam(name = "peerAgeEnd", defaultValue = "0") int peerAgeEnd, @RequestParam(name = "peerGender", defaultValue = "none") String peerGender) { PeerInfoResponseDto response = consumptionGoalService.getPeerInfo(userId, peerAgeStart, peerAgeEnd, peerGender); - return ResponseEntity.ok(response); + return ApiResponse.onSuccess(response); } @GetMapping("/{userId}") - public ResponseEntity findUserConsumptionGoal( + public ApiResponse findUserConsumptionGoal( @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate date, @PathVariable Long userId) { ConsumptionGoalResponseListDto response = consumptionGoalService.findUserConsumptionGoalList(userId, date); - return ResponseEntity.ok(response); + return ApiResponse.onSuccess(response); } @Override @@ -81,28 +85,31 @@ public ResponseEntity updateOrElseGenerateConsum } @GetMapping("/top-categories/top-consumption/3") - public ResponseEntity getTopConsumptionCategories(@RequestParam(name = "userId") Long userId, + public ApiResponse> getTopConsumptionCategories( + @RequestParam(name = "userId") Long userId, @RequestParam(name = "peerAgeStart", defaultValue = "0") int peerAgeStart, @RequestParam(name = "peerAgeEnd", defaultValue = "0") int peerAgeEnd, @RequestParam(name = "peerGender", defaultValue = "none") String peerGender) { - List topCategoriesList = consumptionGoalService.getTopConsumptionCategories(userId, + List response = consumptionGoalService.getTopConsumptionCategories(userId, peerAgeStart, peerAgeEnd, peerGender); - return ResponseEntity.ok(topCategoriesList); + return ApiResponse.onSuccess(response); } @GetMapping("/top-categories/top-consumption") - public ResponseEntity getAllConsumptionCategories(@RequestParam(name = "userId") Long userId, + public ApiResponse> getAllConsumptionCategories( + @RequestParam(name = "userId") Long userId, @RequestParam(name = "peerAgeStart", defaultValue = "0") int peerAgeStart, @RequestParam(name = "peerAgeEnd", defaultValue = "0") int peerAgeEnd, @RequestParam(name = "peerGender", defaultValue = "none") String peerGender) { List response = consumptionGoalService.getAllConsumptionCategories(userId, peerAgeStart, peerAgeEnd, peerGender); - return ResponseEntity.ok(response); + return ApiResponse.onSuccess(response); } @GetMapping("/top-categories/top-consumption/{userId}") - public ResponseEntity getTopCategoryAndConsumptionAmount(@PathVariable Long userId) { - return ResponseEntity.ok(consumptionGoalService.getTopCategoryAndConsumptionAmount(userId)); + public ApiResponse getTopCategoryAndConsumptionAmount(@PathVariable Long userId) { + ConsumptionAnalysisResponseDto response = consumptionGoalService.getTopCategoryAndConsumptionAmount(userId); + return ApiResponse.onSuccess(response); } } \ No newline at end of file diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/converter/ConsumptionGoalConverter.java b/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/converter/ConsumptionGoalConverter.java index 26ef9c81..0ffd0cea 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/converter/ConsumptionGoalConverter.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/converter/ConsumptionGoalConverter.java @@ -36,13 +36,16 @@ public ConsumptionGoalResponseDto toConsumptionGoalResponseDto(ConsumptionGoal c public ConsumptionGoalResponseListDto toConsumptionGoalResponseListDto( List consumptionGoalList, LocalDate goalMonth) { + Long totalGoalAmount = sumTotalGoalAmount(consumptionGoalList); + Long totalConsumptionAmount = sumTotalConsumptionAmount(consumptionGoalList); + return ConsumptionGoalResponseListDto.builder() .goalMonth(goalMonth) - .totalGoalAmount(sumTotalGoalAmount(consumptionGoalList)) - .totalConsumptionAmount(sumTotalConsumptionAmount(consumptionGoalList)) + .totalGoalAmount(totalGoalAmount) + .totalConsumptionAmount(totalConsumptionAmount) + .totalRemainingBalance(totalGoalAmount - totalConsumptionAmount) .consumptionGoalList(consumptionGoalList) .build(); - } private Long sumTotalConsumptionAmount(List consumptionGoalList) { diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/dto/ConsumptionGoalResponseDto.java b/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/dto/ConsumptionGoalResponseDto.java index bd8aca1b..8c7ca3cf 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/dto/ConsumptionGoalResponseDto.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/dto/ConsumptionGoalResponseDto.java @@ -9,6 +9,7 @@ public class ConsumptionGoalResponseDto { private Long categoryId; private Long goalAmount; private Long consumeAmount; + private Long remainingBalance; @Builder public ConsumptionGoalResponseDto(String categoryName, Long categoryId, Long goalAmount, Long consumeAmount) { @@ -16,5 +17,6 @@ public ConsumptionGoalResponseDto(String categoryName, Long categoryId, Long goa this.categoryId = categoryId; this.goalAmount = goalAmount; this.consumeAmount = consumeAmount; + this.remainingBalance = goalAmount - consumeAmount; } } diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/dto/ConsumptionGoalResponseListDto.java b/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/dto/ConsumptionGoalResponseListDto.java index f09ffc90..e6bcb0fa 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/dto/ConsumptionGoalResponseListDto.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/dto/ConsumptionGoalResponseListDto.java @@ -17,5 +17,6 @@ public class ConsumptionGoalResponseListDto { private LocalDate goalMonth; private Long totalGoalAmount; private Long totalConsumptionAmount; + private Long totalRemainingBalance; private List consumptionGoalList; } diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/service/ConsumptionGoalServiceImpl.java b/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/service/ConsumptionGoalServiceImpl.java index 2f26f303..4e52e77d 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/service/ConsumptionGoalServiceImpl.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/consumptiongoal/service/ConsumptionGoalServiceImpl.java @@ -51,14 +51,12 @@ public class ConsumptionGoalServiceImpl implements ConsumptionGoalService { private final UserRepository userRepository; private final ConsumptionGoalConverter consumptionGoalConverter; - - private int peerAgeStart; - private int peerAgeEnd; - private Gender peerGender; - private final LocalDate currentMonth = LocalDate.now().withDayOfMonth(1); private final LocalDate startOfWeek = LocalDate.now().with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); private final LocalDate endOfWeek = LocalDate.now().with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)); + private int peerAgeStart; + private int peerAgeEnd; + private Gender peerGender; @Override @Transactional(readOnly = true) @@ -405,7 +403,10 @@ public ConsumptionGoalResponseListDto findUserConsumptionGoalList(Long userId, L updateGoalMapWithPreviousMonth(userId, goalMonth, goalMap); updateGoalMapWithCurrentMonth(userId, goalMonth, goalMap); - return consumptionGoalConverter.toConsumptionGoalResponseListDto(new ArrayList<>(goalMap.values()), goalMonth); + List consumptionGoalList = new ArrayList<>(goalMap.values()); + + return consumptionGoalConverter.toConsumptionGoalResponseListDto( + orderByRemainingBalanceDescending(consumptionGoalList), goalMonth); } private Map initializeGoalMap(Long userId) { @@ -431,6 +432,13 @@ private void updateGoalMap(Long userId, LocalDate month, Map goalMap.put(goal.getCategoryId(), goal)); } + private List orderByRemainingBalanceDescending( + List consumptionGoalList) { + return consumptionGoalList.stream() + .sorted(Comparator.comparingLong(ConsumptionGoalResponseDto::getRemainingBalance).reversed()) + .toList(); + } + @Override @Transactional public void recalculateConsumptionAmount(Expense expense, ExpenseUpdateRequestDto request, User user) { 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 1751b374..62fd75e9 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 @@ -48,6 +48,13 @@ ResponseEntity createExpense( @GetMapping("/{userId}/{expenseId}") ResponseEntity findExpense(@Param("userId") Long userId, @Param("expenseId") Long expenseId); + @Operation(summary = "단일 소비 업데이트하기", description = "소비 아이디와 카테고리 아이디, amount(소비 금액)을 body에 담아서 소비를 업데이트") + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200", description = "OK, 성공"), + @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)))}) + @GetMapping("/{userId}/{expenseId}") @PostMapping("/{userId}") ResponseEntity updateExpense(@PathVariable @Param("userId") Long userId, @RequestBody ExpenseUpdateRequestDto request); diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/CompactExpenseResponseDto.java b/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/CompactExpenseResponseDto.java index e2f26ee7..f40b7c24 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/CompactExpenseResponseDto.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/CompactExpenseResponseDto.java @@ -2,6 +2,8 @@ import java.time.LocalDateTime; +import com.fasterxml.jackson.annotation.JsonFormat; + import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; @@ -16,5 +18,7 @@ public class CompactExpenseResponseDto { private Long expenseId; private String description; private Long amount; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") private LocalDateTime expenseDate; } diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/ExpenseRequestDto.java b/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/ExpenseRequestDto.java index 680be344..b5ca5bdc 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/ExpenseRequestDto.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/ExpenseRequestDto.java @@ -1,20 +1,24 @@ package com.bbteam.budgetbuddies.domain.expense.dto; +import java.time.LocalDateTime; + +import com.fasterxml.jackson.annotation.JsonFormat; + import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import java.time.LocalDateTime; - @Getter @Builder @NoArgsConstructor @AllArgsConstructor public class ExpenseRequestDto { - private Long userId; - private Long categoryId; - private Long amount; - private String description; - private LocalDateTime expenseDate; + private Long userId; + private Long categoryId; + private Long amount; + private String description; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime expenseDate; } \ No newline at end of file diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/ExpenseResponseDto.java b/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/ExpenseResponseDto.java index 4ae1a934..f0996be0 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/ExpenseResponseDto.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/ExpenseResponseDto.java @@ -1,22 +1,26 @@ package com.bbteam.budgetbuddies.domain.expense.dto; +import java.time.LocalDateTime; + +import com.fasterxml.jackson.annotation.JsonFormat; + import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import java.time.LocalDateTime; - @Getter @Builder @NoArgsConstructor @AllArgsConstructor public class ExpenseResponseDto { - private Long expenseId; - private Long userId; - private Long categoryId; - private String categoryName; - private Long amount; - private String description; - private LocalDateTime expenseDate; + private Long expenseId; + private Long userId; + private Long categoryId; + private String categoryName; + private Long amount; + private String description; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") + private LocalDateTime expenseDate; } diff --git a/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/ExpenseUpdateRequestDto.java b/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/ExpenseUpdateRequestDto.java index 4311b9b9..14312ca2 100644 --- a/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/ExpenseUpdateRequestDto.java +++ b/src/main/java/com/bbteam/budgetbuddies/domain/expense/dto/ExpenseUpdateRequestDto.java @@ -2,6 +2,8 @@ import java.time.LocalDateTime; +import com.fasterxml.jackson.annotation.JsonFormat; + import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; @@ -15,6 +17,8 @@ public class ExpenseUpdateRequestDto { private Long expenseId; private Long categoryId; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime expenseDate; private Long amount; } diff --git a/src/test/java/com/bbteam/budgetbuddies/domain/consumptiongoal/service/ConsumptionGoalServiceTest.java b/src/test/java/com/bbteam/budgetbuddies/domain/consumptiongoal/service/ConsumptionGoalServiceTest.java index 3b22aa79..e7ede59f 100644 --- a/src/test/java/com/bbteam/budgetbuddies/domain/consumptiongoal/service/ConsumptionGoalServiceTest.java +++ b/src/test/java/com/bbteam/budgetbuddies/domain/consumptiongoal/service/ConsumptionGoalServiceTest.java @@ -49,9 +49,9 @@ @ExtendWith(MockitoExtension.class) class ConsumptionGoalServiceTest { private final LocalDate GOAL_MONTH = LocalDate.of(2024, 07, 01); + private final LocalDate currentMonth = LocalDate.now().withDayOfMonth(1); private User user; private LocalDate goalMonthRandomDay; - @InjectMocks private ConsumptionGoalServiceImpl consumptionGoalService; @Mock @@ -63,8 +63,6 @@ class ConsumptionGoalServiceTest { @Spy private ConsumptionGoalConverter consumptionGoalConverter; - private final LocalDate currentMonth = LocalDate.now().withDayOfMonth(1); - @BeforeEach void setUp() { Random random = new Random(); @@ -92,18 +90,19 @@ void findUserConsumptionGoal_onlyCategory() { List categoryList = List.of(defaultCategory, userCategory); - given(categoryRepository.findUserCategoryByUserId(user.getId())).willReturn(categoryList); - - List expected = categoryList.stream() - .map(category -> consumptionGoalConverter.toConsumptionGoalResponseDto(category)) - .toList(); + List expected = List.of( + new ConsumptionGoalResponseDto(defaultCategory.getName(), defaultCategory.getId(), 0L, 0L), + new ConsumptionGoalResponseDto(userCategory.getName(), userCategory.getId(), 0L, 0L)); // when + when(categoryRepository.findUserCategoryByUserId(user.getId())).thenReturn(categoryList); + ConsumptionGoalResponseListDto result = consumptionGoalService.findUserConsumptionGoalList(user.getId(), goalMonthRandomDay); // then assertThat(result.getConsumptionGoalList()).usingRecursiveComparison().isEqualTo(expected); + assertEquals(result.getTotalRemainingBalance(), 0L); } @Test @@ -121,11 +120,13 @@ void findUserConsumptionGoal_previousMonth() { ConsumptionGoal previousMonthDefaultCategoryGoal = ConsumptionGoal.builder() .goalAmount(1_000_000L) - .consumeAmount(20_000L) + .consumeAmount(200_000L) .user(user) .category(defaultCategory) .goalMonth(goalMonthRandomDay.minusMonths(1)) .build(); + Long previousMonthDefaultGoalRemainingBalance = + previousMonthDefaultCategoryGoal.getGoalAmount() - previousMonthDefaultCategoryGoal.getConsumeAmount(); ConsumptionGoal previousMonthUserCategoryGoal = ConsumptionGoal.builder() .goalAmount(1_000_000L) @@ -134,23 +135,27 @@ void findUserConsumptionGoal_previousMonth() { .category(userCategory) .goalMonth(goalMonthRandomDay.minusMonths(1)) .build(); + Long previousMonthUseGoalRemainingBalance = + previousMonthUserCategoryGoal.getGoalAmount() - previousMonthUserCategoryGoal.getConsumeAmount(); List previousGoalList = List.of(previousMonthDefaultCategoryGoal, previousMonthUserCategoryGoal); - given(consumptionGoalRepository.findConsumptionGoalByUserIdAndGoalMonth(user.getId(), - GOAL_MONTH.minusMonths(1))).willReturn(previousGoalList); - - List expected = previousGoalList.stream() - .map(consumptionGoalConverter::toConsumptionGoalResponseDto) - .toList(); + List expected = List.of( + consumptionGoalConverter.toConsumptionGoalResponseDto(previousMonthUserCategoryGoal), + consumptionGoalConverter.toConsumptionGoalResponseDto(previousMonthDefaultCategoryGoal)); // when + when(consumptionGoalRepository.findConsumptionGoalByUserIdAndGoalMonth(user.getId(), + GOAL_MONTH.minusMonths(1))).thenReturn(previousGoalList); + ConsumptionGoalResponseListDto result = consumptionGoalService.findUserConsumptionGoalList(user.getId(), goalMonthRandomDay); // then assertThat(result.getConsumptionGoalList()).usingRecursiveComparison().isEqualTo(expected); + assertEquals(result.getTotalRemainingBalance(), + previousMonthDefaultGoalRemainingBalance + previousMonthUseGoalRemainingBalance); } @Test @@ -176,13 +181,13 @@ void findUserConsumptionGoal_previousMonthAndGoalMonth() { .goalMonth(goalMonthRandomDay) .build(); - given(consumptionGoalRepository.findConsumptionGoalByUserIdAndGoalMonth(user.getId(), - GOAL_MONTH.minusMonths(1))).willReturn(List.of(previousMonthUserCategoryGoal)); + // when + when(consumptionGoalRepository.findConsumptionGoalByUserIdAndGoalMonth(user.getId(), + GOAL_MONTH.minusMonths(1))).thenReturn(List.of(previousMonthUserCategoryGoal)); - given(consumptionGoalRepository.findConsumptionGoalByUserIdAndGoalMonth(user.getId(), GOAL_MONTH)).willReturn( + when(consumptionGoalRepository.findConsumptionGoalByUserIdAndGoalMonth(user.getId(), GOAL_MONTH)).thenReturn( List.of(goalMonthUserCategoryGoal)); - // when ConsumptionGoalResponseListDto result = consumptionGoalService.findUserConsumptionGoalList(user.getId(), goalMonthRandomDay);