Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -77,29 +84,30 @@ public void setExchangeInfo(boolean isExchanged, BigDecimal amount, BigDecimal e
}

updateForeignBalance(amount, exchangeRate);
this.avgExchangeRate = exchangeRate;

}

public void updateExchangeInfo(boolean isExchanged, BigDecimal amount, BigDecimal exchangeRate) {
if (!isExchanged) {
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) {
Expand Down Expand Up @@ -131,6 +139,7 @@ public Budget setTeam(Team team) {

return this;
}

public void updateBalance(BigDecimal balance) {
if (balance != null) {
this.balance = balance;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -46,13 +47,24 @@ 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.multiply(budget.getAvgExchangeRate());
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);

Expand Down