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() .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() .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() .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 getBills(Long userId, LocalDate startDate, LocalDate endDate) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper() .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 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; } }