Skip to content

Commit

Permalink
Merge pull request #132 from BudgetBuddiesTeam/feat/#131
Browse files Browse the repository at this point in the history
  • Loading branch information
JunRain2 authored Aug 18, 2024
2 parents e3596b3 + 60490d6 commit 7b1b90a
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 142 deletions.
Original file line number Diff line number Diff line change
@@ -1,50 +1,55 @@
package com.bbteam.budgetbuddies.domain.expense.controller;

import java.time.LocalDate;
import org.springframework.data.domain.Pageable;

import org.springframework.data.repository.query.Param;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
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;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

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 io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import org.springframework.web.bind.annotation.DeleteMapping;

public interface ExpenseApi {
@Operation(summary = "소비 내역 추가", description = "사용자가 소비 내역을 추가합니다.")
@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)))})
@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)))})
ResponseEntity<ExpenseResponseDto> createExpense(
@Parameter(description = "user_id, category_id, amount, description, expenseDate") ExpenseRequestDto expenseRequestDto);
@Parameter(description = "user_id, category_id, amount, description, expenseDate") ExpenseRequestDto expenseRequestDto);

@Operation(summary = "월별 소비 조회", description = "무한 스크롤을 통한 조회로 예상하여 Slice를 통해서 조회")
@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)))})
ResponseEntity<MonthlyExpenseCompactResponseDto> findExpensesForMonth(Pageable pageable, Long userId, LocalDate date);
@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)))})
ResponseEntity<MonthlyExpenseCompactResponseDto> findExpensesForMonth(
@PathVariable @Param("userId") Long userId,
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate date);

@Operation(summary = "단일 소비 조회하기", description = "queryParameter를 통해 소비 Id를 전달 받아서 응답값을 조회")
@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)))})
@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}")
ResponseEntity<ExpenseResponseDto> findExpense(@Param("userId") Long userId, @Param("expenseId") Long expenseId);

Expand All @@ -56,14 +61,15 @@ ResponseEntity<ExpenseResponseDto> createExpense(
@ApiResponse(responseCode = "AUTH006", description = "access 토큰 모양이 이상함", content = @Content(schema = @Schema(implementation = ApiResponse.class)))})
@GetMapping("/{userId}/{expenseId}")
@PostMapping("/{userId}")
ResponseEntity<ExpenseResponseDto> updateExpense(@PathVariable @Param("userId") Long userId, @RequestBody ExpenseUpdateRequestDto request);
ResponseEntity<ExpenseResponseDto> updateExpense(@PathVariable @Param("userId") Long userId,
@RequestBody ExpenseUpdateRequestDto request);

@Operation(summary = "소비 내역 삭제", description = "사용자가 소비 내역을 삭제합니다.")
@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))),
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH004", description = "access 토큰 만료", content = @Content(schema = @Schema(implementation = ApiResponse.class))),
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH006", description = "access 토큰 모양이 이상함", content = @Content(schema = @Schema(implementation = ApiResponse.class)))
@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))),
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH004", description = "access 토큰 만료", content = @Content(schema = @Schema(implementation = ApiResponse.class))),
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH006", description = "access 토큰 모양이 이상함", content = @Content(schema = @Schema(implementation = ApiResponse.class)))
})
@DeleteMapping("/delete/{expenseId}")
ResponseEntity<String> deleteExpense(@Parameter(description = "expense_id") @PathVariable Long expenseId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,25 @@

import java.time.LocalDate;

import io.swagger.v3.oas.annotations.Parameter;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.query.Param;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
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;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

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.service.ExpenseService;

import io.swagger.v3.oas.annotations.Parameter;
import lombok.RequiredArgsConstructor;

@RestController
Expand All @@ -24,40 +32,40 @@ public class ExpenseController implements ExpenseApi {
@Override
@PostMapping("/add")
public ResponseEntity<ExpenseResponseDto> createExpense(
@Parameter(description = "user_id, category_id, amount, description, expenseDate")
@RequestBody ExpenseRequestDto expenseRequestDto) {
@Parameter(description = "user_id, category_id, amount, description, expenseDate")
@RequestBody ExpenseRequestDto expenseRequestDto) {
ExpenseResponseDto response = expenseService.createExpense(expenseRequestDto);
return ResponseEntity.ok(response);
}

@Override
@GetMapping("/{userId}")
public ResponseEntity<MonthlyExpenseCompactResponseDto> findExpensesForMonth(Pageable pageable,
@PathVariable @Param("userId") Long userId,
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate date) {
public ResponseEntity<MonthlyExpenseCompactResponseDto> findExpensesForMonth(
@PathVariable @Param("userId") Long userId,
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate date) {

return ResponseEntity.ok(expenseService.getMonthlyExpense(pageable, userId, date));
return ResponseEntity.ok(expenseService.getMonthlyExpense(userId, date));
}

@Override
@GetMapping("/{userId}/{expenseId}")
public ResponseEntity<ExpenseResponseDto> findExpense(@PathVariable @Param("userId") Long userId,
@PathVariable @Param("expenseId") Long expenseId) {
@PathVariable @Param("expenseId") Long expenseId) {
return ResponseEntity.ok(expenseService.findExpenseResponseFromUserIdAndExpenseId(userId, expenseId));
}

@Override
@PostMapping("/{userId}")
public ResponseEntity<ExpenseResponseDto> updateExpense(@PathVariable @Param("userId") Long userId,
@RequestBody ExpenseUpdateRequestDto request) {
@RequestBody ExpenseUpdateRequestDto request) {
ExpenseResponseDto response = expenseService.updateExpense(userId, request);
return ResponseEntity.ok(response);
}

@DeleteMapping("/delete/{expenseId}")
public ResponseEntity<String> deleteExpense(
@Parameter(description = "expense_id")
@PathVariable Long expenseId) {
@Parameter(description = "expense_id")
@PathVariable Long expenseId) {
expenseService.deleteExpense(expenseId);
return ResponseEntity.ok("Successfully deleted expense!");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
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;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.data.domain.Slice;
import org.springframework.stereotype.Component;

import com.bbteam.budgetbuddies.domain.category.entity.Category;
Expand Down Expand Up @@ -39,26 +43,31 @@ public ExpenseResponseDto toExpenseResponseDto(Expense expense) {
.build();
}

public MonthlyExpenseCompactResponseDto toMonthlyExpenseCompactResponseDto(Slice<Expense> expenseSlice,
public MonthlyExpenseCompactResponseDto toMonthlyExpenseCompactResponseDto(List<Expense> expenseList,
LocalDate startOfMonth) {
List<CompactExpenseResponseDto> compactResponseList = expenseSlice.getContent().stream()
.map(this::toExpenseCompactResponseDto).toList();
Long totalConsumptionAmount = expenseList.stream().mapToLong(Expense::getAmount).sum();

return MonthlyExpenseCompactResponseDto
.builder()
Map<String, List<CompactExpenseResponseDto>> expenses = expenseList.stream().collect(
Collectors.groupingBy(e -> this.convertDayToKorean(e.getExpenseDate()),
Collectors.mapping(this::toExpenseCompactResponseDto, Collectors.toList())));

return MonthlyExpenseCompactResponseDto.builder()
.expenseMonth(startOfMonth)
.currentPage(expenseSlice.getPageable().getPageNumber())
.hasNext(expenseSlice.hasNext())
.expenseList(compactResponseList)
.totalConsumptionAmount(totalConsumptionAmount)
.expenses(expenses)
.build();
}

private String convertDayToKorean(LocalDateTime localDateTime) {
return localDateTime.getDayOfMonth() + "일 " + localDateTime.getDayOfWeek()
.getDisplayName(TextStyle.FULL, Locale.KOREAN);
}

private CompactExpenseResponseDto toExpenseCompactResponseDto(Expense expense) {
return CompactExpenseResponseDto.builder()
.expenseId(expense.getId())
.description(expense.getDescription())
.amount(expense.getAmount())
.expenseDate(expense.getExpenseDate())
.categoryId(expense.getCategory().getId())
.build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package com.bbteam.budgetbuddies.domain.expense.dto;

import java.time.LocalDateTime;

import com.fasterxml.jackson.annotation.JsonFormat;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
Expand All @@ -19,7 +15,4 @@ public class CompactExpenseResponseDto {
private String description;
private Long amount;
private Long categoryId;

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
private LocalDateTime expenseDate;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.time.LocalDate;
import java.util.List;
import java.util.Map;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
Expand All @@ -15,7 +16,7 @@
@Builder
public class MonthlyExpenseCompactResponseDto {
private LocalDate expenseMonth;
private int currentPage;
private boolean hasNext;
private List<CompactExpenseResponseDto> expenseList;
private Long totalConsumptionAmount;

private Map<String, List<CompactExpenseResponseDto>> expenses;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import java.time.LocalDateTime;
import java.util.List;

import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
Expand All @@ -14,8 +12,8 @@

public interface ExpenseRepository extends JpaRepository<Expense, Long> {
@Query("SELECT e FROM Expense e WHERE e.user = :user AND e.expenseDate BETWEEN :startDate AND :endDate ORDER BY e.expenseDate DESC")
Slice<Expense> findAllByUserIdForPeriod(Pageable pageable, @Param("user") User user,
@Param("startDate") LocalDateTime startDate, @Param("endDate") LocalDateTime endDate);

List<Expense> findAllByUserIdForPeriod(@Param("user") User user, @Param("startDate") LocalDateTime startDate,
@Param("endDate") LocalDateTime endDate);
List<Expense> findByCategoryIdAndUserId(Long categoryId, Long userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

import java.time.LocalDate;

import org.springframework.data.domain.Pageable;

import com.bbteam.budgetbuddies.domain.expense.dto.ExpenseRequestDto;
import com.bbteam.budgetbuddies.domain.expense.dto.ExpenseResponseDto;
import com.bbteam.budgetbuddies.domain.expense.dto.ExpenseUpdateRequestDto;
Expand All @@ -12,7 +10,7 @@
public interface ExpenseService {
ExpenseResponseDto createExpense(ExpenseRequestDto expenseRequestDto);

MonthlyExpenseCompactResponseDto getMonthlyExpense(Pageable pageable, Long userId, LocalDate localDate);
MonthlyExpenseCompactResponseDto getMonthlyExpense(Long userId, LocalDate localDate);

ExpenseResponseDto findExpenseResponseFromUserIdAndExpenseId(Long userId, Long expenseId);

Expand Down
Loading

0 comments on commit 7b1b90a

Please sign in to comment.