spring 如何从列表中的实体中取出双精度值并进行处理

8hhllhi2  于 2023-03-07  发布在  Spring
关注(0)|答案(1)|浏览(120)

我不知道如何创造一个更好的标题,所以这里是一个完整的解释。
我有wallet实体:

@Entity
@Table(name = "wallet")
public class Wallet {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "wallet_id")
private Long id;

@NotBlank(message = "Please, insert a wallet name")
private String walletName;

@NotNull(message = "Please, insert a amount")
private Double initialBalance;

@Transient
private double totalBalance;

@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "user_id", nullable = false, referencedColumnName = "user_id", insertable = false, updatable = false)
@OnDelete(action = OnDeleteAction.CASCADE)
@JsonIgnore
private User user;

@Column(name = "user_id", nullable = false)
private Long userId;

@OneToMany(mappedBy = "wallet", cascade = {
        CascadeType.ALL})
private Set<Transaction> transactions;

我还有一个transaction实体:

@Entity
@Table(name = "transaction")
public class Transaction {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "transaction_id")
private Long id;

@Column(name = "user_id", nullable = false)
private Long userId;

@Column(name = "wallet_name", nullable = false)
private String walletName;

@Column
@NotNull(message = "Please, insert a amount")
@Min(value = 0, message = "Please, insert a positive amount")
private Double amount;

@Column
private String note;

@DateTimeFormat(pattern = "yyyy-MM-dd")
@Column(name = "date")
private LocalDate date;

@ManyToOne
@OnDelete(action = OnDeleteAction.NO_ACTION)
@JoinColumn(name = "wallet_id", nullable = false)
private Wallet wallet;

@Enumerated(EnumType.STRING)
@Column(name = "transaction_type", columnDefinition = "ENUM('EXPENSE', 'INCOME')")
private TransactionType transactionType;

@Nullable
@Enumerated(EnumType.STRING)
@Column(name = "expense_categories", columnDefinition = "ENUM('FOOD_AND_DRINK', 'SHOPPING', 'TRANSPORT', 'HOME'," +
        " 'BILLS_AND_FEES', 'ENTERTAINMENT', 'CAR', 'TRAVEL', 'FAMILY_AND_PERSONAL', 'HEALTHCARE'," +
        " 'EDUCATION', 'GROCERIES', 'GIFTS', 'BEAUTY', 'WORK', 'SPORTS_AND_HOBBIES', 'OTHER')")
private ExpenseCategories expenseCategories;

@Nullable
@Enumerated(EnumType.STRING)
@Column(name = "income_categories", columnDefinition = "ENUM('SALARY', 'BUSINESS', 'GIFTS', 'EXTRA_INCOME', 'LOAN', 'PARENTAL_LEAVE', 'INSURANCE_PAYOUT', 'OTHER')")
private IncomeCategories incomeCategories;

现在,为了让你更好地了解我想要什么,我将按时间顺序介绍事情的运作方式:
这是允许用户创建income transaction:的控制器

@PostMapping("/saveIncome/{walletId}")
public String saveIncome(@PathVariable(value = "walletId") long walletId, @Valid Transaction transaction, BindingResult result, Model model) {

    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    UserDetailsImpl user = (UserDetailsImpl) authentication.getPrincipal();
    long userId = user.getId();

    Wallet wallet = walletService.getWalletById(walletId);

    boolean thereAreErrors = result.hasErrors();
    if (thereAreErrors) {
        model.addAttribute("incomeCategories", IncomeCategories.values());
        return "income_transaction";
    }

    transaction.setWallet(wallet);
    transaction.setUserId(userId);
    transaction.setWalletName(wallet.getWalletName());
    transactionService.saveIncome(transaction, walletId, userId);
    return "redirect:/api/wallet/userWallet/balance/" + userId;
}

没什么特别的,而且效果很好。
现在,当用户成功创建一个事务时,我有一个控制器,它返回一个页面,用户实际上可以在该页面中看到他所做的所有事务。

@GetMapping("/userTransactions/{user_id}")
public String getUserTransactions(@PathVariable("user_id") long user_id, TransactionGroup transactionGroup, Model model) {
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    UserDetailsImpl user = (UserDetailsImpl) authentication.getPrincipal();
    long userId = user.getId();
    model.addAttribute("userId", userId);

    List<Transaction> transactions = transactionRepository.getTransactionsByUserId(user_id);
    List<TransactionGroup> transactionByDate = new ArrayList<>();
    List<Transaction> transOnSingleDate = new ArrayList<>();
    boolean currDates = transactions.stream().findFirst().isPresent();

    if (currDates) {
        LocalDate currDate = transactions.get(0).getDate();

        TransactionGroup transGroup = new TransactionGroup();

        for (Transaction t : transactions) {
            if (!currDate.isEqual(t.getDate())) {
                transGroup.setDate(currDate);
                transGroup.setTransactions(transOnSingleDate);
                transactionByDate.add(transGroup);
                transGroup = new TransactionGroup();
                transOnSingleDate = new ArrayList<>();
            }

            transOnSingleDate.add(t);
            currDate = t.getDate();
        }
        transGroup.setDate(currDate);
        transGroup.setTransactions(transOnSingleDate);

        transactionByDate.add(transGroup);
    } else {
        System.out.println("Empty");
    }

    model.addAttribute("transactionGroup", transactionByDate);
    return "transactions";
}

你可以看到我有一些列表,因为我想按每个日期显示所有事务。这也工作得很好。更多的上下文,这是我的'helper'类,帮助我按日期显示用户事务:

public class TransactionGroup {
    private LocalDate date;
    private List<Transaction> transactions;

    public LocalDate getDate() {
        return date;
    }

    public void setDate(LocalDate date) {
        this.date = date;
    }

    public List<Transaction> getTransactions() {
        return transactions;
    }

    public void setTransactions(List<Transaction> transactions) {
        this.transactions = transactions;
    }

现在,我希望你们能全面了解它是如何运作的。现在,我想实现什么?
您可以在此处看到此字段:

@Column
@NotNull(message = "Please, insert a amount")
@Min(value = 0, message = "Please, insert a positive amount")
private Double amount;

我想计算每个日期的剩余金额。例如:
Date 03/03/2023 Transaction income: 100, Transaction income: 100 - Transaction expense: 50 == 150
我在getUserTransactionController中这样尝试:

for (int i = 0; i < transGroup.getTransactions().size(); i++) {
            double result = 0;

            if (transGroup.getTransactions().get(i).getTransactionType().getDisplayName().equalsIgnoreCase("income")) {
                System.out.println("Income amount for date " +
                        transGroup.getTransactions().get(i).getDate() + " is " + transGroup.getTransactions().get(i).getAmount());
                result = result + transGroup.getTransactions().get(i).getAmount();
                System.out.println("Result is " + result);
                System.out.println("------");

            }

但这是不好的,首先,它返回给我一个正确的值,但没有求和,如果我甚至使它这样的代码实际上求和,我不知道我应该如何从expense金额减去它。
有什么建议,忠告,我可以试试吗?

y53ybaqx

y53ybaqx1#

由于您已经按每个日期聚合了所有事务,因此它就像一个纯粹的计算问题。

LocalDate date = transGroup.getDate();
List<Transaction> transactions = transGroup.getTransactions();
// 1. sum all income
double income = transactions.stream()
        .filter(trans->trans.getTransactionType().getDisplayName().equalsIgnoreCase("income"))
        .mapToDouble(Transaction::getAmount)
        .sum();
// 2. sum all expense
double expense = transactions.stream()
        .filter(trans->trans.getTransactionType().getDisplayName().equalsIgnoreCase("expense"))
        .mapToDouble(Transaction::getAmount)
        .sum();
// 3. subtraction
double left = income - expense;
System.out.println("date:" + date + ",income:" + income + ",expense:"+ expense + ",left:" + left);

相关问题