package com.ruoyi.cwgl.service.impl; import java.util.List; import com.ruoyi.common.utils.DateUtils; import javax.annotation.Resource; import org.springframework.transaction.annotation.Transactional; import org.springframework.stereotype.Service; import org.springframework.scheduling.annotation.Async; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ruoyi.common.utils.PageUtils; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.annotation.DataSource; import com.ruoyi.common.enums.DataSourceType; import com.ruoyi.common.core.service.BaseService; import com.ruoyi.cwgl.mapper.ReceivableBillSettlementDetailMapper; import com.ruoyi.cwgl.domain.ReceivableBillSettlementDetail; import com.ruoyi.cwgl.service.IReceivableBillSettlementDetailService; import com.ruoyi.cwgl.service.IReceivableBillManagementService; import com.ruoyi.cwgl.service.IReceivableBillManagementLogService; import com.ruoyi.cwgl.domain.ReceivableBillManagement; import com.ruoyi.cwgl.domain.ReceivableBillManagementLog; import com.ruoyi.common.core.text.Convert; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.SecurityUtils; import java.math.BigDecimal; import java.util.Set; import java.util.Objects; import java.util.stream.Collectors; import java.util.HashSet; /** * 应收账单结算明细Service业务层处理 * * @author ruoyi * @date 2025-12-17 */ @Service @Transactional(rollbackFor = Exception.class) public class ReceivableBillSettlementDetailServiceImpl extends BaseService implements IReceivableBillSettlementDetailService { protected final Logger logger = LoggerFactory.getLogger(getClass()); @Resource private ReceivableBillSettlementDetailMapper receivableBillSettlementDetailMapper; @Resource private IReceivableBillManagementService receivableBillManagementService; @Resource private IReceivableBillManagementLogService receivableBillManagementLogService; /** * 查询应收账单结算明细 * * @param id 应收账单结算明细ID * @return 应收账单结算明细 */ @DataSource(DataSourceType.SLAVE) @Override public ReceivableBillSettlementDetail selectReceivableBillSettlementDetailById(Integer id) { return receivableBillSettlementDetailMapper.selectReceivableBillSettlementDetailById(id); } /** * 查询应收账单结算明细 记录数 * * @param receivableBillSettlementDetail 应收账单结算明细 * @return 应收账单结算明细集合 */ @DataSource(DataSourceType.SLAVE) @Override public int selectReceivableBillSettlementDetailCount(ReceivableBillSettlementDetail receivableBillSettlementDetail) { return receivableBillSettlementDetailMapper.selectReceivableBillSettlementDetailCount(receivableBillSettlementDetail); } /** * 查询应收账单结算明细列表 * * @param receivableBillSettlementDetail 应收账单结算明细 * @return 应收账单结算明细 */ @DataSource(DataSourceType.SLAVE) @Override public List selectReceivableBillSettlementDetailList(ReceivableBillSettlementDetail receivableBillSettlementDetail) { return receivableBillSettlementDetailMapper.selectReceivableBillSettlementDetailList(receivableBillSettlementDetail); } /** * 查询应收账单结算明细列表 异步 导出 * * @param receivableBillSettlementDetail 应收账单结算明细 * @param exportKey 导出功能的唯一标识 * @return 应收账单结算明细集合 */ @DataSource(DataSourceType.SLAVE) @Async @Override public void export(ReceivableBillSettlementDetail receivableBillSettlementDetail,String exportKey) { super.export(ReceivableBillSettlementDetail.class,exportKey,"receivableBillSettlementDetailData",(pageNum)->{ PageUtils.startPage(pageNum, Constants.EXPORT_PATE_SIZE); return selectReceivableBillSettlementDetailList(receivableBillSettlementDetail); }); } /** * 新增应收账单结算明细 * * @param receivableBillSettlementDetail 应收账单结算明细 * @return 结果 */ @Override public int insertReceivableBillSettlementDetail(ReceivableBillSettlementDetail receivableBillSettlementDetail) { // 1. 设置创建时间 receivableBillSettlementDetail.setCreateTime(DateUtils.getNowDate()); // 2. 插入结算明细记录 int result = receivableBillSettlementDetailMapper.insertReceivableBillSettlementDetail(receivableBillSettlementDetail); // 3. 如果插入成功且billId不为空,则更新主表金额和状态 if (result > 0 && receivableBillSettlementDetail.getBillId() != null) { updateReceivableBillAmountAndStatus(receivableBillSettlementDetail.getBillId()); // 记录添加结算明细操作日志 ReceivableBillManagement billManagement = receivableBillManagementService.selectReceivableBillManagementById(receivableBillSettlementDetail.getBillId()); if (billManagement != null) { ReceivableBillManagementLog log = new ReceivableBillManagementLog(); log.setBillId(receivableBillSettlementDetail.getBillId()); log.setCreateBy(SecurityUtils.getUsername()); log.setCreateTime(DateUtils.getNowDate()); log.setOperation("添加结算明细,账单编号:" + billManagement.getSystemNo()); receivableBillManagementLogService.insertReceivableBillManagementLog(log); } } return result; } /** * 更新应收账单主表的金额和状态 * * @param billId 应收账单ID */ private void updateReceivableBillAmountAndStatus(Integer billId) { // 1. 查询应收账单主表记录 ReceivableBillManagement billManagement = receivableBillManagementService.selectReceivableBillManagementById(billId); if (billManagement == null) { throw new ServiceException("应收账单主表记录不存在,ID:" + billId); } // 2. 查询该账单的所有结算明细记录 ReceivableBillSettlementDetail queryDetail = new ReceivableBillSettlementDetail(); queryDetail.setBillId(billId); List settlementDetails = receivableBillSettlementDetailMapper.selectReceivableBillSettlementDetailList(queryDetail); // 3. 计算总收款金额 BigDecimal totalReceiptAmount = settlementDetails.stream() .map(ReceivableBillSettlementDetail::getReceiptAmount) .filter(amount -> amount != null) .reduce(BigDecimal.ZERO, BigDecimal::add); // 4. 验证金额不能为负数 if (totalReceiptAmount.compareTo(BigDecimal.ZERO) < 0) { throw new ServiceException("收款金额不能为负数"); } // 5. 计算待收金额(应结算金额 - 已收金额 - 减免金额) BigDecimal totalAmount = billManagement.getTotalAmount() != null ? billManagement.getTotalAmount() : BigDecimal.ZERO; BigDecimal discountAmount = billManagement.getDiscountAmount() != null ? billManagement.getDiscountAmount() : BigDecimal.ZERO; BigDecimal pendingAmount = totalAmount.subtract(totalReceiptAmount).subtract(discountAmount); // 6. 验证待收金额不能为负数 if (pendingAmount.compareTo(BigDecimal.ZERO) < 0) { throw new ServiceException("待收金额不能为负数,当前计算值:" + pendingAmount); } // 7. 更新主表金额 billManagement.setReceivedAmount(totalReceiptAmount); billManagement.setPendingAmount(pendingAmount); // 8. 根据待收金额更新状态 if (pendingAmount.compareTo(BigDecimal.ZERO) == 0) { // 待收金额为0,状态改为3(已结算) billManagement.setStatus("3"); } else { // 待收金额大于0,状态改为1(结算中) billManagement.setStatus("1"); } // 9. 更新主表记录 billManagement.setUpdateTime(DateUtils.getNowDate()); receivableBillManagementService.updateReceivableBillManagement(billManagement); } /** * 新增应收账单结算明细[批量] * * @param receivableBillSettlementDetails 应收账单结算明细 * @return 结果 */ @Override public int insertReceivableBillSettlementDetailBatch(List receivableBillSettlementDetails) { // 1. 设置创建时间 for (ReceivableBillSettlementDetail detail : receivableBillSettlementDetails) { detail.setCreateTime(DateUtils.getNowDate()); } // 2. 批量插入结算明细记录 int rows = receivableBillSettlementDetailMapper.insertReceivableBillSettlementDetailBatch(receivableBillSettlementDetails); // 3. 如果插入成功,则更新相关主表金额和状态 if (rows > 0) { // 获取所有不重复的billId Set billIds = receivableBillSettlementDetails.stream() .map(ReceivableBillSettlementDetail::getBillId) .filter(Objects::nonNull) .collect(Collectors.toSet()); // 更新每个账单主表的金额和状态 for (Integer billId : billIds) { updateReceivableBillAmountAndStatus(billId); } // 记录添加结算明细操作日志 if (!billIds.isEmpty()) { for (Integer billId : billIds) { ReceivableBillManagement billManagement = receivableBillManagementService.selectReceivableBillManagementById(billId); if (billManagement != null) { ReceivableBillManagementLog log = new ReceivableBillManagementLog(); log.setBillId(billId); log.setCreateBy(SecurityUtils.getUsername()); log.setCreateTime(DateUtils.getNowDate()); // 计算本次添加的明细数量 long detailCount = receivableBillSettlementDetails.stream() .filter(detail -> billId.equals(detail.getBillId())) .count(); log.setOperation("添加" + detailCount + "条结算明细,账单编号:" + billManagement.getSystemNo()); receivableBillManagementLogService.insertReceivableBillManagementLog(log); } } } } return rows; } /** * 修改应收账单结算明细 * * @param receivableBillSettlementDetail 应收账单结算明细 * @return 结果 */ @Override public int updateReceivableBillSettlementDetail(ReceivableBillSettlementDetail receivableBillSettlementDetail) { // 1. 获取修改前的记录,用于后续更新主表 ReceivableBillSettlementDetail oldDetail = null; if (receivableBillSettlementDetail.getId() != null) { oldDetail = receivableBillSettlementDetailMapper.selectReceivableBillSettlementDetailById(receivableBillSettlementDetail.getId()); } // 2. 设置更新时间 receivableBillSettlementDetail.setUpdateTime(DateUtils.getNowDate()); // 3. 更新结算明细记录 int result = receivableBillSettlementDetailMapper.updateReceivableBillSettlementDetail(receivableBillSettlementDetail); // 4. 如果更新成功,则更新相关主表金额和状态 if (result > 0) { // 获取需要更新的billId(优先使用新记录的billId,如果没有则使用旧记录的billId) Integer billId = receivableBillSettlementDetail.getBillId(); if (billId == null && oldDetail != null) { billId = oldDetail.getBillId(); } if (billId != null) { updateReceivableBillAmountAndStatus(billId); } } return result; } /** * 修改应收账单结算明细[批量] * * @param receivableBillSettlementDetails 应收账单结算明细 * @return 结果 */ @Override public int updateReceivableBillSettlementDetailBatch(List receivableBillSettlementDetails){ // 1. 设置更新时间 for (ReceivableBillSettlementDetail detail : receivableBillSettlementDetails) { detail.setUpdateTime(DateUtils.getNowDate()); } // 2. 批量更新结算明细记录 int result = receivableBillSettlementDetailMapper.updateReceivableBillSettlementDetailBatch(receivableBillSettlementDetails); // 3. 如果更新成功,则更新相关主表金额和状态 if (result > 0) { // 获取所有不重复的billId Set billIds = receivableBillSettlementDetails.stream() .map(ReceivableBillSettlementDetail::getBillId) .filter(Objects::nonNull) .collect(Collectors.toSet()); // 更新每个账单主表的金额和状态 for (Integer billId : billIds) { updateReceivableBillAmountAndStatus(billId); } } return result; } /** * 删除应收账单结算明细对象 * * @param ids 需要删除的数据ID * @return 结果 */ @Override public int deleteReceivableBillSettlementDetailByIds(String ids) { return deleteReceivableBillSettlementDetailByIds(Convert.toIntArray(ids)); } /** * 删除应收账单结算明细对象 * * * @param ids 需要删除的数据ID * @return 结果 */ @Override public int deleteReceivableBillSettlementDetailByIds(Integer[] ids) { // 1. 获取删除前的记录,用于后续更新主表 Set billIds = new HashSet<>(); for (Integer id : ids) { ReceivableBillSettlementDetail detail = receivableBillSettlementDetailMapper.selectReceivableBillSettlementDetailById(id); if (detail != null && detail.getBillId() != null) { billIds.add(detail.getBillId()); } } // 2. 删除结算明细记录 int result = receivableBillSettlementDetailMapper.deleteReceivableBillSettlementDetailByIds(ids); // 3. 如果删除成功,则更新相关主表金额和状态 if (result > 0) { for (Integer billId : billIds) { updateReceivableBillAmountAndStatus(billId); } } return result; } /** * 删除应收账单结算明细信息 * * @param id 应收账单结算明细ID * @return 结果 */ @Override public int deleteReceivableBillSettlementDetailById(Integer id) { // 1. 获取删除前的记录,用于后续更新主表 Integer billId = null; ReceivableBillSettlementDetail detail = receivableBillSettlementDetailMapper.selectReceivableBillSettlementDetailById(id); if (detail != null && detail.getBillId() != null) { billId = detail.getBillId(); } // 2. 删除结算明细记录 int result = receivableBillSettlementDetailMapper.deleteReceivableBillSettlementDetailById(id); // 3. 如果删除成功,则更新相关主表金额和状态 if (result > 0 && billId != null) { updateReceivableBillAmountAndStatus(billId); } return result; } }