diff --git a/mooney/src/main/java/tamtam/mooney/domain/transaction/controller/TransactionController.java b/mooney/src/main/java/tamtam/mooney/domain/transaction/controller/TransactionController.java index cad3e5d..1391695 100644 --- a/mooney/src/main/java/tamtam/mooney/domain/transaction/controller/TransactionController.java +++ b/mooney/src/main/java/tamtam/mooney/domain/transaction/controller/TransactionController.java @@ -9,10 +9,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import tamtam.mooney.domain.transaction.dto.MonthlyTransactionDayUnitDto; -import tamtam.mooney.domain.transaction.dto.ExpenseAddRequestDto; -import tamtam.mooney.domain.transaction.dto.IncomeAddRequestDto; -import tamtam.mooney.domain.transaction.dto.MonthlyTransactionResponseDto; +import tamtam.mooney.domain.transaction.dto.*; import tamtam.mooney.domain.transaction.service.ExpenseDataLoader; import tamtam.mooney.domain.transaction.service.ExpenseService; import tamtam.mooney.domain.transaction.service.IncomeService; @@ -30,7 +27,6 @@ public class TransactionController { private final TransactionService transactionService; private final ExpenseService expenseService; private final IncomeService incomeService; - private final ExpenseDataLoader expenseDataLoader; @Operation(summary = "지출 내역 추가") @PostMapping("/expenses") @@ -39,6 +35,13 @@ public ResponseEntity createExpense(@RequestBody @Valid ExpenseAddReques return ResponseEntity.ok(category); } + @Operation(summary = "지출 내역 추가 w.카테고리") + @PostMapping("/expenses/category") + public ResponseEntity createExpenseWithCategory(@RequestBody @Valid ExpenseWithCategoryAddRequestDto request) { + String category = expenseService.createExpenseWithCategory(request); + return ResponseEntity.ok(category); + } + @Operation(summary = "지출 내역 여러 건 추가") @PostMapping("/expenses-multiple") public ResponseEntity createMultipleExpenses( diff --git a/mooney/src/main/java/tamtam/mooney/domain/transaction/dto/BaseExpenseRequest.java b/mooney/src/main/java/tamtam/mooney/domain/transaction/dto/BaseExpenseRequest.java new file mode 100644 index 0000000..31e3b9b --- /dev/null +++ b/mooney/src/main/java/tamtam/mooney/domain/transaction/dto/BaseExpenseRequest.java @@ -0,0 +1,11 @@ +package tamtam.mooney.domain.transaction.dto; + +import java.time.LocalDateTime; + +public interface BaseExpenseRequest { + String payee(); + long amount(); + LocalDateTime transactionTime(); + String transactionSource(); + String sourceApp(); +} diff --git a/mooney/src/main/java/tamtam/mooney/domain/transaction/dto/ExpenseAddRequestDto.java b/mooney/src/main/java/tamtam/mooney/domain/transaction/dto/ExpenseAddRequestDto.java index ff99c75..4abc024 100644 --- a/mooney/src/main/java/tamtam/mooney/domain/transaction/dto/ExpenseAddRequestDto.java +++ b/mooney/src/main/java/tamtam/mooney/domain/transaction/dto/ExpenseAddRequestDto.java @@ -1,24 +1,16 @@ package tamtam.mooney.domain.transaction.dto; import jakarta.validation.constraints.NotNull; -import tamtam.mooney.global.exception.CustomException; -import tamtam.mooney.global.exception.ErrorCode; import java.time.LocalDateTime; public record ExpenseAddRequestDto( - @NotNull(message = "Amount is required") - Long amount, + long amount, @NotNull(message = "Transaction time is required") LocalDateTime transactionTime, String transactionSource, String sourceApp, + @NotNull(message = "Payee is required") String payee -) { - public ExpenseAddRequestDto { - // 금액 검증 (0 이상이어야 함) - if (amount != null && amount < 0) { - throw new CustomException(ErrorCode.INVALID_INPUT_VALUE); - } - } -} +) implements BaseExpenseRequest { } + diff --git a/mooney/src/main/java/tamtam/mooney/domain/transaction/dto/ExpenseWithCategoryAddRequestDto.java b/mooney/src/main/java/tamtam/mooney/domain/transaction/dto/ExpenseWithCategoryAddRequestDto.java new file mode 100644 index 0000000..d4df3db --- /dev/null +++ b/mooney/src/main/java/tamtam/mooney/domain/transaction/dto/ExpenseWithCategoryAddRequestDto.java @@ -0,0 +1,18 @@ +package tamtam.mooney.domain.transaction.dto; + +import jakarta.validation.constraints.NotNull; +import tamtam.mooney.domain.enums.ExpenseCategory; + +import java.time.LocalDateTime; + +public record ExpenseWithCategoryAddRequestDto( + long amount, + @NotNull(message = "Transaction time is required") + LocalDateTime transactionTime, + String transactionSource, + String sourceApp, + @NotNull(message = "Payee is required") + String payee, + ExpenseCategory expenseCategory +) implements BaseExpenseRequest { +} \ No newline at end of file diff --git a/mooney/src/main/java/tamtam/mooney/domain/transaction/service/ExpenseService.java b/mooney/src/main/java/tamtam/mooney/domain/transaction/service/ExpenseService.java index 2accc2a..b2e9f70 100644 --- a/mooney/src/main/java/tamtam/mooney/domain/transaction/service/ExpenseService.java +++ b/mooney/src/main/java/tamtam/mooney/domain/transaction/service/ExpenseService.java @@ -4,9 +4,10 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import tamtam.mooney.domain.mission.repository.MissionRepository; import tamtam.mooney.domain.mission.service.MissionService; +import tamtam.mooney.domain.transaction.dto.BaseExpenseRequest; import tamtam.mooney.domain.transaction.dto.ExpenseAddRequestDto; +import tamtam.mooney.domain.transaction.dto.ExpenseWithCategoryAddRequestDto; import tamtam.mooney.domain.transaction.entity.Expense; import tamtam.mooney.domain.enums.ExpenseCategory; import tamtam.mooney.domain.transaction.repository.ExpenseRepository; @@ -30,20 +31,31 @@ public class ExpenseService { private final ExpenseRepository expenseRepository; private final UserService userService; // private final LlmCategoryClassifier llmCategoryClassifier; - private final MissionRepository missionRepository; private final MissionService missionService; - // 지출 추가 + // 지출 추가 (카테고리 예측) public String createExpense(ExpenseAddRequestDto request) { User user = userService.getCurrentUser(); + String predicted = "FOOD"; //llmCategoryClassifier.classifyCategory(request.payee(), true); + ExpenseCategory category = ExpenseCategory.valueOf(predicted); + return saveAndReturnCategory(request, user, category); + } - // String predictedCategory = llmCategoryClassifier.classifyCategory(request.payee(), true); - String predictedCategory = ExpenseCategory.FOOD.name(); - ExpenseCategory expenseCategory = ExpenseCategory.valueOf(predictedCategory); + // 지출 추가 (카테고리 직접 지정) + public String createExpenseWithCategory(ExpenseWithCategoryAddRequestDto request) { + User user = userService.getCurrentUser(); + return saveAndReturnCategory(request, user, request.expenseCategory()); + } + // ——— private 헬퍼 메서드 ——— + private String saveAndReturnCategory( + T request, + User user, + ExpenseCategory category + ) { Expense expense = Expense.builder() .payee(request.payee()) - .expenseCategory(expenseCategory) + .expenseCategory(category) .amount(request.amount()) .transactionTime(request.transactionTime()) .transactionSource(request.transactionSource()) @@ -52,11 +64,8 @@ public String createExpense(ExpenseAddRequestDto request) { .build(); transactionRepository.save(expense); - - //들어온 지출의 payee가 현재 진행중인 미션 place에 해당된다면 missionRepo에 save - missionService.updateMission(user, request.payee(),request.amount()); - - return expense.getExpenseCategory().name(); + missionService.updateMission(user, request.payee(), request.amount()); + return category.name(); } @Transactional(readOnly = true)