package com.ruoyi.cwgl.service.impl; import java.util.List; import com.ruoyi.common.utils.DateUtils; import javax.annotation.Resource; import lombok.NonNull; 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.FundFlowClaimDetailMapper; import com.ruoyi.cwgl.mapper.FundFlowMapper; import com.ruoyi.cwgl.domain.FundFlowClaimDetail; import com.ruoyi.cwgl.domain.FundFlow; import com.ruoyi.cwgl.domain.FundFlowLog; import com.ruoyi.cwgl.domain.ReceivableBillSettlementDetail; import com.ruoyi.cwgl.domain.PayableBillSettlementDetail; import com.ruoyi.cwgl.domain.ReceivableBillManagement; import com.ruoyi.cwgl.domain.PayableBillManagement; import com.ruoyi.cwgl.service.IFundFlowClaimDetailService; import com.ruoyi.cwgl.service.IFundFlowLogService; import com.ruoyi.cwgl.service.IReceivableBillSettlementDetailService; import com.ruoyi.cwgl.service.IPayableBillSettlementDetailService; import com.ruoyi.cwgl.service.IReceivableBillManagementService; import com.ruoyi.cwgl.service.IPayableBillManagementService; import com.ruoyi.common.core.text.Convert; import com.ruoyi.common.utils.SecurityUtils; import java.math.BigDecimal; /** * 账单认领明细Service业务层处理 * * @author ruoyi * @date 2026-01-12 */ @Service @Transactional(rollbackFor = Exception.class) public class FundFlowClaimDetailServiceImpl extends BaseService implements IFundFlowClaimDetailService { protected final Logger logger = LoggerFactory.getLogger(getClass()); @Resource private FundFlowClaimDetailMapper fundFlowClaimDetailMapper; @Resource private FundFlowMapper fundFlowMapper; @Resource private IReceivableBillSettlementDetailService receivableBillSettlementDetailService; @Resource private IPayableBillSettlementDetailService payableBillSettlementDetailService; @Resource private IReceivableBillManagementService receivableBillManagementService; @Resource private IPayableBillManagementService payableBillManagementService; @Resource private IFundFlowLogService fundFlowLogService; /** * 查询账单认领明细 * * @param id 账单认领明细ID * @return 账单认领明细 */ @DataSource(DataSourceType.SLAVE) @Override public FundFlowClaimDetail selectFundFlowClaimDetailById(Integer id) { return fundFlowClaimDetailMapper.selectFundFlowClaimDetailById(id); } /** * 查询账单认领明细 记录数 * * @param fundFlowClaimDetail 账单认领明细 * @return 账单认领明细集合 */ @DataSource(DataSourceType.SLAVE) @Override public int selectFundFlowClaimDetailCount(FundFlowClaimDetail fundFlowClaimDetail) { return fundFlowClaimDetailMapper.selectFundFlowClaimDetailCount(fundFlowClaimDetail); } /** * 查询账单认领明细列表 * * @param fundFlowClaimDetail 账单认领明细 * @return 账单认领明细 */ @DataSource(DataSourceType.SLAVE) @Override public List selectFundFlowClaimDetailList(FundFlowClaimDetail fundFlowClaimDetail) { return fundFlowClaimDetailMapper.selectFundFlowClaimDetailList(fundFlowClaimDetail); } /** * 查询账单认领明细列表 异步 导出 * * @param fundFlowClaimDetail 账单认领明细 * @param exportKey 导出功能的唯一标识 * @return 账单认领明细集合 */ @DataSource(DataSourceType.SLAVE) @Async @Override public void export(FundFlowClaimDetail fundFlowClaimDetail,String exportKey) { super.export(FundFlowClaimDetail.class,exportKey,"fundFlowClaimDetailData",(pageNum)->{ PageUtils.startPage(pageNum, Constants.EXPORT_PATE_SIZE); return selectFundFlowClaimDetailList(fundFlowClaimDetail); }); } /** * 新增账单认领明细 * * @param fundFlowClaimDetail 账单认领明细 * @return 结果 */ @Override public int insertFundFlowClaimDetail(FundFlowClaimDetail fundFlowClaimDetail) { fundFlowClaimDetail.setCreateTime(DateUtils.getNowDate()); return fundFlowClaimDetailMapper.insertFundFlowClaimDetail(fundFlowClaimDetail); } /** * 新增账单认领明细[批量] * * @param fundFlowClaimDetails 账单认领明细 * @return 结果 */ @Override public int insertFundFlowClaimDetailBatch(List fundFlowClaimDetails) { int rows = fundFlowClaimDetailMapper.insertFundFlowClaimDetailBatch(fundFlowClaimDetails); return rows; } /** * 修改账单认领明细 * * @param fundFlowClaimDetail 账单认领明细 * @return 结果 */ @Override public int updateFundFlowClaimDetail(FundFlowClaimDetail fundFlowClaimDetail) { fundFlowClaimDetail.setUpdateTime(DateUtils.getNowDate()); return fundFlowClaimDetailMapper.updateFundFlowClaimDetail(fundFlowClaimDetail); } /** * 修改账单认领明细[批量] * * @param fundFlowClaimDetails 账单认领明细 * @return 结果 */ @Override public int updateFundFlowClaimDetailBatch(List fundFlowClaimDetails){ return fundFlowClaimDetailMapper.updateFundFlowClaimDetailBatch(fundFlowClaimDetails); } /** * 删除账单认领明细对象 * * @param ids 需要删除的数据ID * @return 结果 */ @Override public int deleteFundFlowClaimDetailByIds(String ids) { return deleteFundFlowClaimDetailByIds(Convert.toIntArray(ids)); } /** * 删除账单认领明细对象 * * * @param ids 需要删除的数据ID * @return 结果 */ @Override public int deleteFundFlowClaimDetailByIds(Integer[] ids) { if (ids == null || ids.length == 0) { throw new RuntimeException("删除的认领明细ID不能为空"); } // 由于删除只会有一条记录,取第一条进行处理 Integer id = ids[0]; FundFlowClaimDetail claimDetail = fundFlowClaimDetailMapper.selectFundFlowClaimDetailById(id); if (claimDetail == null) { throw new RuntimeException("未找到要删除的认领明细记录,ID: " + id); } Integer fundFlowId = claimDetail.getFundFlowId(); BigDecimal deleteAmount = claimDetail.getClaimAmount(); // 查询资金流水信息 FundFlow fundFlow = fundFlowMapper.selectFundFlowById(fundFlowId); if (fundFlow == null) { throw new RuntimeException("资金流水不存在,ID: " + fundFlowId); } // 更新资金流水的已认领金额 BigDecimal newClaimedAmount = fundFlow.getClaimedAmount().subtract(deleteAmount); if (newClaimedAmount.compareTo(BigDecimal.ZERO) < 0) { newClaimedAmount = BigDecimal.ZERO; } // 根据新的认领金额设置状态 String newStatus =fundFlow.getStatus(); if (newClaimedAmount.compareTo(BigDecimal.ZERO) == 0) { // 已认领金额为0,状态改为1(未认领) newStatus = "1"; } else if (newClaimedAmount.compareTo(fundFlow.getTransactionAmount()) < 0) { // 已认领金额小于交易金额,状态改为2(部分认领) newStatus = "2"; } // 更新资金流水状态和已认领金额 fundFlow.setStatus(newStatus); fundFlow.setClaimedAmount(newClaimedAmount); fundFlow.setUpdateTime(DateUtils.getNowDate()); int updateResult = fundFlowMapper.updateFundFlow(fundFlow); if (updateResult <= 0) { throw new RuntimeException("更新资金流水状态失败,ID: " + fundFlowId); } // 删除结算明细并更新账单状态 deleteSettlementDetailsAndUpdateBillStatus(claimDetail,fundFlow); int result = fundFlowClaimDetailMapper.deleteFundFlowClaimDetailByIds(ids); // 记录操作日志 if (result > 0) { FundFlowLog log = new FundFlowLog(); log.setFlowId(fundFlowId); log.setOperation("删除账单认领明细,账单编号:" + claimDetail.getBillNo() + ",认领金额:" + deleteAmount + ",资金流水号:" + fundFlow.getBankFlowNo()); fundFlowLogService.insertFundFlowLog(log); } return result; } /** * 删除账单认领明细信息 * * @param id 账单认领明细ID * @return 结果 */ @Override public int deleteFundFlowClaimDetailById(Integer id) { return fundFlowClaimDetailMapper.deleteFundFlowClaimDetailById(id); } /** * 账单认领 * * @param fundFlowId 资金流水ID * @param claimDetails 账单认领明细列表 * @return 结果 */ @Override public int claimBill(Integer fundFlowId, FundFlowClaimDetail claimDetail) { if (fundFlowId == null) { throw new RuntimeException("资金流水ID不能为空"); } if (claimDetail == null ) { throw new RuntimeException("认领明细列表不能为空"); } //金额 BigDecimal claimAmount = claimDetail.getClaimAmount(); if (claimAmount == null || claimAmount.compareTo(BigDecimal.ZERO) <= 0) { throw new RuntimeException("认领金额必须大于0"); } // 查询资金流水信息 FundFlow fundFlow = fundFlowMapper.selectFundFlowById(fundFlowId); // 根据总认领金额与交易金额的比较设置状态 String newStatus = getString(fundFlowId, claimDetail, fundFlow); // 更新资金流水状态和已认领金额 fundFlow.setStatus(newStatus); fundFlow.setClaimedAmount(fundFlow.getClaimedAmount().add(claimAmount)); // 设置已认领金额 fundFlow.setUpdateTime(DateUtils.getNowDate()); int updateResult = fundFlowMapper.updateFundFlow(fundFlow); if (updateResult <= 0) { throw new RuntimeException("更新资金流水状态失败,ID: " + fundFlowId); } // 设置资金流水ID claimDetail.setFundFlowId(fundFlowId); // 设置认领日期 claimDetail.setClaimDate(DateUtils.getNowDate()); // 设置创建时间 claimDetail.setCreateTime(DateUtils.getNowDate()); int insertResult = fundFlowClaimDetailMapper.insertFundFlowClaimDetail(claimDetail); // 新增:创建结算明细并更新账单状态 if (insertResult > 0) { createSettlementDetailsAndUpdateBillStatus(claimDetail, fundFlow); // 记录操作日志 FundFlowLog log = new FundFlowLog(); log.setFlowId(fundFlowId); log.setOperation("新增账单认领明细,账单编号:" + claimDetail.getBillNo() + ",认领金额:" + claimAmount + ",资金流水号:" + fundFlow.getBankFlowNo()); fundFlowLogService.insertFundFlowLog(log); } return insertResult; } /** * 根据资金流水ID、认领详情列表和资金流水对象获取状态字符串 * @param fundFlowId 资金流水ID,用于标识特定的资金流水记录 * @param claimDetail 认领详情列表,包含所有认领金额信息 * @param fundFlow 资金流水对象,包含交易金额等关键信息 * @return 返回处理后的状态字符串 * @throws RuntimeException 当资金流水对象为null时抛出异常 */ private static @NonNull String getString(Integer fundFlowId, FundFlowClaimDetail claimDetail, FundFlow fundFlow) { // 检查资金流水对象是否为空,如果为空则抛出异常 if (fundFlow == null) { throw new RuntimeException("资金流水不存在,ID: " + fundFlowId); } // 计算总认领金额 BigDecimal totalClaimAmount = claimDetail.getClaimAmount(); // 验证总认领金额不能超过交易金额 return getString(fundFlow, totalClaimAmount); } private static @NonNull String getString(FundFlow fundFlow, BigDecimal totalClaimAmount) { BigDecimal transactionAmount = fundFlow.getTransactionAmount(); if (totalClaimAmount.compareTo(transactionAmount) > 0) { throw new RuntimeException("总认领金额不能超过交易金额。交易金额: " + transactionAmount + ", 总认领金额: " + totalClaimAmount); } // 根据总认领金额与交易金额的比较设置状态 String newStatus; if (totalClaimAmount.compareTo(transactionAmount) < 0) { // 总认领金额小于交易金额,状态改为2(部分认领) newStatus = "2"; } else { // 总认领金额等于交易金额,状态改为3(完全认领) newStatus = "3"; } return newStatus; } /** * 创建结算明细并更新账单状态 */ private void createSettlementDetailsAndUpdateBillStatus(FundFlowClaimDetail claimDetail, FundFlow fundFlow) { String billNo = claimDetail.getBillNo(); BigDecimal claimAmount = claimDetail.getClaimAmount(); Integer claimDetailId = claimDetail.getId(); // 根据收支标识借贷标志判断是应收账单还是应付账单 if (fundFlow.getIncomeExpenseFlag().equals(0)) { // 应收账单 createReceivableSettlementDetail(billNo, claimAmount, fundFlow, claimDetailId); } else { // 应付账单 createPayableSettlementDetail(billNo, claimAmount, fundFlow, claimDetailId); } } /** * 创建应收账单结算明细 */ private void createReceivableSettlementDetail(String billNo, BigDecimal claimAmount, FundFlow fundFlow, Integer claimDetailId) { try { // 根据账单编号查询应收账单 ReceivableBillManagement bill = receivableBillManagementService.selectReceivableBillManagementBySystemNo(billNo); if (bill != null) { // 创建结算明细 ReceivableBillSettlementDetail settlementDetail = new ReceivableBillSettlementDetail(); settlementDetail.setBillId(bill.getId()); settlementDetail.setClaimDetailId(claimDetailId); // 设置认领明细ID settlementDetail.setReceiptAmount(claimAmount); settlementDetail.setReceiptDate(fundFlow.getTransactionDate()); settlementDetail.setSettlementMethod("银行转账"); // 根据实际情况设置 settlementDetail.setCreateBy(SecurityUtils.getUsername()); settlementDetail.setCreateTime(DateUtils.getNowDate()); // 插入结算明细(会自动更新账单状态) receivableBillSettlementDetailService.insertReceivableBillSettlementDetail(settlementDetail); logger.info("成功创建应收账单结算明细,账单编号:{},金额:{},认领明细ID:{}", billNo, claimAmount, claimDetailId); } else { logger.warn("未找到对应的应收账单,账单编号:{}", billNo); } } catch (Exception e) { logger.error("创建应收账单结算明细失败,账单编号:{}", billNo, e); // 这里可以选择抛出异常或记录日志,但不中断整个认领流程 } } /** * 创建应付账单结算明细 */ private void createPayableSettlementDetail(String billNo, BigDecimal claimAmount, FundFlow fundFlow, Integer claimDetailId) { try { // 根据账单编号查询应付账单 PayableBillManagement bill = payableBillManagementService.selectPayableBillManagementBySystemNo(billNo); if (bill != null) { // 创建结算明细 PayableBillSettlementDetail settlementDetail = new PayableBillSettlementDetail(); settlementDetail.setBillId(bill.getId()); settlementDetail.setClaimDetailId(claimDetailId); // 设置认领明细ID settlementDetail.setPaymentAmount(claimAmount); settlementDetail.setPaymentDate(fundFlow.getTransactionDate()); settlementDetail.setSettlementMethod("银行转账"); // 根据实际情况设置 settlementDetail.setCreateBy(SecurityUtils.getUsername()); settlementDetail.setCreateTime(DateUtils.getNowDate()); // 插入结算明细(会自动更新账单状态) payableBillSettlementDetailService.insertPayableBillSettlementDetail(settlementDetail); logger.info("成功创建应付账单结算明细,账单编号:{},金额:{},认领明细ID:{}", billNo, claimAmount, claimDetailId); } else { logger.warn("未找到对应的应付账单,账单编号:{}", billNo); } } catch (Exception e) { logger.error("创建应付账单结算明细失败,账单编号:{}", billNo, e); // 这里可以选择抛出异常或记录日志,但不中断整个认领流程 } } /** * 删除结算明细并更新账单状态 */ private void deleteSettlementDetailsAndUpdateBillStatus(FundFlowClaimDetail claimDetail, FundFlow fundFlow) { String billNo = claimDetail.getBillNo(); Integer claimDetailId = claimDetail.getId(); try { // 根据收支标识借贷标志判断是应收账单还是应付账单 if (fundFlow.getIncomeExpenseFlag().equals(0)) { // 应收账单 deleteReceivableSettlementDetail(claimDetailId); } else { // 应付账单 deletePayableSettlementDetail(claimDetailId); } logger.info("成功删除结算明细,认领明细ID:{}", claimDetailId); } catch (Exception e) { logger.error("删除结算明细失败,认领明细ID:{}", claimDetailId, e); // 这里可以选择抛出异常或记录日志,但不中断整个删除流程 } } /** * 删除应收账单结算明细 */ private void deleteReceivableSettlementDetail(Integer claimDetailId) { try { // 根据认领明细ID查询应收账单结算明细 ReceivableBillSettlementDetail receivableQuery = new ReceivableBillSettlementDetail(); receivableQuery.setClaimDetailId(claimDetailId); List receivableDetails = receivableBillSettlementDetailService.selectReceivableBillSettlementDetailList(receivableQuery); if (!receivableDetails.isEmpty()) { Integer[] receivableIds = receivableDetails.stream() .map(ReceivableBillSettlementDetail::getId) .toArray(Integer[]::new); receivableBillSettlementDetailService.deleteReceivableBillSettlementDetailByIds(receivableIds); logger.info("成功删除应收账单结算明细,认领明细ID:{}", claimDetailId); } } catch (Exception e) { logger.error("删除应收账单结算明细失败,认领明细ID:{}", claimDetailId, e); throw e; } } /** * 删除应付账单结算明细 */ private void deletePayableSettlementDetail(Integer claimDetailId) { try { // 根据认领明细ID查询应付账单结算明细 PayableBillSettlementDetail payableQuery = new PayableBillSettlementDetail(); payableQuery.setClaimDetailId(claimDetailId); List payableDetails = payableBillSettlementDetailService.selectPayableBillSettlementDetailList(payableQuery); if (!payableDetails.isEmpty()) { Integer[] payableIds = payableDetails.stream() .map(PayableBillSettlementDetail::getId) .toArray(Integer[]::new); payableBillSettlementDetailService.deletePayableBillSettlementDetailByIds(payableIds); logger.info("成功删除应付账单结算明细,认领明细ID:{}", claimDetailId); } } catch (Exception e) { logger.error("删除应付账单结算明细失败,认领明细ID:{}", claimDetailId, e); throw e; } } }