AI-accounting-soft/src/main/java/com/accounting/service/BillService.java
ni ziyi 3df3aea533 feat(账户功能新增)
1、实现单个账户功能,支持账户余额自动计算(初始余额 + 收入 - 支出),创建单独的账户管理页面,账单自动关联到默认账户
2025-12-13 21:55:55 +08:00

170 lines
5.7 KiB
Java

package com.accounting.service;
import com.accounting.dto.BillRequest;
import com.accounting.dto.BillResponse;
import com.accounting.entity.Account;
import com.accounting.entity.Bill;
import com.accounting.entity.Category;
import com.accounting.mapper.BillMapper;
import com.accounting.mapper.CategoryMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class BillService {
@Autowired
private BillMapper billMapper;
@Autowired
private CategoryMapper categoryMapper;
@Autowired
private AccountService accountService;
@Transactional
public BillResponse createBill(BillRequest request, Long userId) {
// 验证分类是否存在
Category category = categoryMapper.selectById(request.getCategoryId());
if (category == null) {
throw new RuntimeException("分类不存在");
}
// 获取或创建账户
Account account = accountService.getOrCreateAccount(userId);
// 创建账单
Bill bill = new Bill();
bill.setUserId(userId);
bill.setAccountId(account.getId()); // 自动关联账户
bill.setCategoryId(request.getCategoryId());
bill.setAmount(request.getAmount());
bill.setDescription(request.getDescription());
bill.setBillDate(request.getBillDate() != null ? request.getBillDate() : LocalDate.now());
bill.setImageUrl(request.getImageUrl());
bill.setType(request.getType()); // 设置账单类型
billMapper.insert(bill);
return convertToResponse(bill, category);
}
@Transactional
public BillResponse updateBill(Long id, BillRequest request, Long userId) {
// 验证账单是否存在且属于当前用户
Bill bill = billMapper.selectOne(
new LambdaQueryWrapper<Bill>()
.eq(Bill::getId, id)
.eq(Bill::getUserId, userId)
);
if (bill == null) {
throw new RuntimeException("账单不存在或无权限");
}
// 验证分类是否存在
Category category = categoryMapper.selectById(request.getCategoryId());
if (category == null) {
throw new RuntimeException("分类不存在");
}
// 如果账单没有关联账户,则自动关联
if (bill.getAccountId() == null) {
Account account = accountService.getOrCreateAccount(userId);
bill.setAccountId(account.getId());
}
// 更新账单
bill.setCategoryId(request.getCategoryId());
bill.setAmount(request.getAmount());
bill.setDescription(request.getDescription());
if (request.getBillDate() != null) {
bill.setBillDate(request.getBillDate());
}
if (request.getImageUrl() != null) {
bill.setImageUrl(request.getImageUrl());
}
bill.setType(request.getType()); // 更新账单类型
billMapper.updateById(bill);
return convertToResponse(bill, category);
}
@Transactional
public void deleteBill(Long id, Long userId) {
Bill bill = billMapper.selectOne(
new LambdaQueryWrapper<Bill>()
.eq(Bill::getId, id)
.eq(Bill::getUserId, userId)
);
if (bill == null) {
throw new RuntimeException("账单不存在或无权限");
}
billMapper.deleteById(id);
}
public BillResponse getBill(Long id, Long userId) {
Bill bill = billMapper.selectOne(
new LambdaQueryWrapper<Bill>()
.eq(Bill::getId, id)
.eq(Bill::getUserId, userId)
);
if (bill == null) {
throw new RuntimeException("账单不存在或无权限");
}
Category category = categoryMapper.selectById(bill.getCategoryId());
return convertToResponse(bill, category);
}
public List<BillResponse> getBills(Long userId, LocalDate startDate, LocalDate endDate) {
LambdaQueryWrapper<Bill> wrapper = new LambdaQueryWrapper<Bill>()
.eq(Bill::getUserId, userId)
.orderByDesc(Bill::getBillDate)
.orderByDesc(Bill::getCreateTime);
if (startDate != null) {
wrapper.ge(Bill::getBillDate, startDate);
}
if (endDate != null) {
wrapper.le(Bill::getBillDate, endDate);
}
List<Bill> bills = billMapper.selectList(wrapper);
return bills.stream().map(bill -> {
Category category = categoryMapper.selectById(bill.getCategoryId());
return convertToResponse(bill, category);
}).collect(Collectors.toList());
}
private BillResponse convertToResponse(Bill bill, Category category) {
BillResponse response = new BillResponse();
BeanUtils.copyProperties(bill, response);
if (category != null) {
response.setCategoryName(category.getName());
response.setCategoryIcon(category.getIcon());
// 如果账单有自己的类型,则使用账单的类型,否则使用分类的类型
if (response.getType() == null) {
response.setType(category.getType());
}
}
return response;
}
}