From 8cbb2af12d59d33ce33e519b27318487ac3368bd Mon Sep 17 00:00:00 2001 From: KEEKE132 Date: Tue, 20 May 2025 14:58:02 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EC=B9=B4=EB=93=9C/=ED=98=84?= =?UTF-8?q?=EA=B8=88=20=EA=B5=AC=EB=B6=84=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/expense/service/ExpenseService.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/Backend/src/main/java/com/luckyseven/backend/domain/expense/service/ExpenseService.java b/Backend/src/main/java/com/luckyseven/backend/domain/expense/service/ExpenseService.java index 7c9543bb..551eefab 100644 --- a/Backend/src/main/java/com/luckyseven/backend/domain/expense/service/ExpenseService.java +++ b/Backend/src/main/java/com/luckyseven/backend/domain/expense/service/ExpenseService.java @@ -11,6 +11,7 @@ import com.luckyseven.backend.domain.expense.dto.ExpenseResponse; import com.luckyseven.backend.domain.expense.dto.ExpenseUpdateRequest; import com.luckyseven.backend.domain.expense.entity.Expense; +import com.luckyseven.backend.domain.expense.enums.PaymentMethod; import com.luckyseven.backend.domain.expense.mapper.ExpenseMapper; import com.luckyseven.backend.domain.expense.repository.ExpenseRepository; import com.luckyseven.backend.domain.member.entity.Member; @@ -21,6 +22,7 @@ import com.luckyseven.backend.sharedkernel.dto.PageResponse; import com.luckyseven.backend.sharedkernel.exception.CustomLogicException; import java.math.BigDecimal; +import java.math.RoundingMode; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; @@ -46,13 +48,25 @@ public CreateExpenseResponse saveExpense(Long teamId, ExpenseRequest request) { Member payer = findPayerOrThrow(request.payerId()); Budget budget = team.getBudget(); - validateSufficientBudget(request.amount(), budget.getBalance()); + + if (request.paymentMethod() == PaymentMethod.CASH) { + BigDecimal foreignAmount = request.amount(); + BigDecimal KRWAmount = foreignAmount.divide(budget.getAvgExchangeRate(), 2, + RoundingMode.HALF_UP); + validateSufficientBudget(KRWAmount, budget.getBalance()); + validateSufficientBudget(foreignAmount, budget.getForeignBalance()); + budget.updateBalance(budget.getBalance().subtract(KRWAmount)); + budget.setForeignBalance(budget.getForeignBalance().subtract(foreignAmount)); + + } else if (request.paymentMethod() == PaymentMethod.CARD) { + validateSufficientBudget(request.amount(), budget.getBalance()); + budget.updateBalance(budget.getBalance().subtract(request.amount())); + } Expense expense = ExpenseMapper.fromExpenseRequest(request, team, payer); Expense saved = expenseRepository.save(expense); // TODO: 낙관적 락(Lock) 적용 검토 - budget.updateBalance(budget.getBalance().subtract(request.amount())); createAllSettlements(request, payer, saved); From 7c54cdd51d9b4df22f0d7a32d11813b45ec8f01e Mon Sep 17 00:00:00 2001 From: KEEKE132 Date: Tue, 20 May 2025 16:11:59 +0900 Subject: [PATCH 2/2] =?UTF-8?q?refactor:=20=EC=98=88=EC=82=B0=20=EA=B3=84?= =?UTF-8?q?=EC=82=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/budget/entity/Budget.java | 25 +++++++++++++------ .../domain/budget/service/BudgetService.java | 1 + .../expense/service/ExpenseService.java | 4 +-- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/Backend/src/main/java/com/luckyseven/backend/domain/budget/entity/Budget.java b/Backend/src/main/java/com/luckyseven/backend/domain/budget/entity/Budget.java index ce643efa..3fa19447 100644 --- a/Backend/src/main/java/com/luckyseven/backend/domain/budget/entity/Budget.java +++ b/Backend/src/main/java/com/luckyseven/backend/domain/budget/entity/Budget.java @@ -1,5 +1,6 @@ package com.luckyseven.backend.domain.budget.entity; +import com.luckyseven.backend.domain.budget.dto.BudgetUpdateRequest; import com.luckyseven.backend.domain.team.entity.Team; import com.luckyseven.backend.sharedkernel.entity.BaseEntity; import jakarta.persistence.Column; @@ -66,7 +67,13 @@ public Budget(Team team, BigDecimal totalAmount, Long setBy, public void setTotalAmount(BigDecimal totalAmount) { this.totalAmount = totalAmount; - this.balance = totalAmount; + } + + public void addBalance(BudgetUpdateRequest request) { + if (request.additionalBudget() == null) { + return; + } + this.balance = this.balance.add(request.additionalBudget()); } public void setExchangeInfo(boolean isExchanged, BigDecimal amount, BigDecimal exchangeRate) { @@ -77,8 +84,6 @@ public void setExchangeInfo(boolean isExchanged, BigDecimal amount, BigDecimal e } updateForeignBalance(amount, exchangeRate); - this.avgExchangeRate = exchangeRate; - } public void updateExchangeInfo(boolean isExchanged, BigDecimal amount, BigDecimal exchangeRate) { @@ -86,20 +91,23 @@ public void updateExchangeInfo(boolean isExchanged, BigDecimal amount, BigDecima return; } - updateForeignBalance(amount, exchangeRate); updateAvgExchangeRate(amount, exchangeRate); + updateForeignBalance(amount, exchangeRate); } // 예산 추가 후 외화잔고 및 평균환율 수정 private void updateAvgExchangeRate(BigDecimal amount, BigDecimal exchangeRate) { - if (this.avgExchangeRate == null) { + if (this.avgExchangeRate == null || this.avgExchangeRate.compareTo(BigDecimal.ZERO) == 0) { avgExchangeRate = exchangeRate; return; } - this.avgExchangeRate = (this.balance.multiply(this.avgExchangeRate) - .add(amount.multiply(exchangeRate))) - .divide(this.balance.add(amount), 2, RoundingMode.HALF_UP); + BigDecimal foreignAmount = amount.divide(exchangeRate, 10, + RoundingMode.HALF_UP); // 외화 환산, 충분한 정밀도 확보 + BigDecimal totalCost = this.foreignBalance.multiply(this.avgExchangeRate).add(amount); + BigDecimal totalForeign = this.foreignBalance.add(foreignAmount); + this.avgExchangeRate = totalCost.divide(totalForeign, 2, RoundingMode.HALF_UP); + } private void updateForeignBalance(BigDecimal amount, BigDecimal exchangeRate) { @@ -131,6 +139,7 @@ public Budget setTeam(Team team) { return this; } + public void updateBalance(BigDecimal balance) { if (balance != null) { this.balance = balance; diff --git a/Backend/src/main/java/com/luckyseven/backend/domain/budget/service/BudgetService.java b/Backend/src/main/java/com/luckyseven/backend/domain/budget/service/BudgetService.java index 4713ee6c..980f8ca8 100644 --- a/Backend/src/main/java/com/luckyseven/backend/domain/budget/service/BudgetService.java +++ b/Backend/src/main/java/com/luckyseven/backend/domain/budget/service/BudgetService.java @@ -85,6 +85,7 @@ private static void addBudget(BudgetUpdateRequest request, Budget budget) { request.additionalBudget(), request.exchangeRate()); budget.setTotalAmount(budget.getTotalAmount().add(request.additionalBudget())); + budget.addBalance(request); } } diff --git a/Backend/src/main/java/com/luckyseven/backend/domain/expense/service/ExpenseService.java b/Backend/src/main/java/com/luckyseven/backend/domain/expense/service/ExpenseService.java index 551eefab..b03795b4 100644 --- a/Backend/src/main/java/com/luckyseven/backend/domain/expense/service/ExpenseService.java +++ b/Backend/src/main/java/com/luckyseven/backend/domain/expense/service/ExpenseService.java @@ -22,7 +22,6 @@ import com.luckyseven.backend.sharedkernel.dto.PageResponse; import com.luckyseven.backend.sharedkernel.exception.CustomLogicException; import java.math.BigDecimal; -import java.math.RoundingMode; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; @@ -51,8 +50,7 @@ public CreateExpenseResponse saveExpense(Long teamId, ExpenseRequest request) { if (request.paymentMethod() == PaymentMethod.CASH) { BigDecimal foreignAmount = request.amount(); - BigDecimal KRWAmount = foreignAmount.divide(budget.getAvgExchangeRate(), 2, - RoundingMode.HALF_UP); + BigDecimal KRWAmount = foreignAmount.multiply(budget.getAvgExchangeRate()); validateSufficientBudget(KRWAmount, budget.getBalance()); validateSufficientBudget(foreignAmount, budget.getForeignBalance()); budget.updateBalance(budget.getBalance().subtract(KRWAmount));