package com.ruoyi.cwgl.service.impl; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; import com.ruoyi.common.enums.SystemDataNoEnum; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.cwgl.domain.ReceivableFeeDetail; import com.ruoyi.cwgl.domain.ReceivableFeeManagementLog; import com.ruoyi.cwgl.domain.vo.ReceivableFeeStatisticsVo; import com.ruoyi.cwgl.service.*; import com.ruoyi.system.domain.SysConfig; import com.ruoyi.system.mapper.SysConfigMapper; import com.ruoyi.system.service.ISystemDataNoService; import org.springframework.beans.factory.annotation.Autowired; 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.ReceivableFeeManagementMapper; import com.ruoyi.cwgl.domain.ReceivableFeeManagement; import com.ruoyi.cwgl.domain.ReceivableBillManagement; import com.ruoyi.cwgl.domain.ReceivableBillSettlementDetail; import com.ruoyi.cwgl.domain.vo.ReceivableBillCreateVo; import com.ruoyi.common.core.text.Convert; import javax.annotation.Resource; /** * 应收费用管理Service业务层处理 * * @author ruoyi * @date 2025-12-17 */ @Service @Transactional(rollbackFor = Exception.class) public class ReceivableFeeManagementServiceImpl extends BaseService implements IReceivableFeeManagementService { protected final Logger logger = LoggerFactory.getLogger(getClass()); @Resource private ReceivableFeeManagementMapper receivableFeeManagementMapper; @Autowired private IReceivableFeeDetailService receivableFeeDetailService; @Resource private SysConfigMapper sysConfigMapper; @Autowired private IReceivableBillManagementService receivableBillManagementService; @Autowired ISystemDataNoService systemDataNoService; @Autowired private IReceivableFeeManagementLogService logService; /** * 查询应收费用管理 * * @param id 应收费用管理ID * @return 应收费用管理 */ @DataSource(DataSourceType.SLAVE) @Override public ReceivableFeeManagement selectReceivableFeeManagementById(Integer id) { ReceivableFeeManagement receivableFeeManagement = receivableFeeManagementMapper.selectReceivableFeeManagementById(id); if (receivableFeeManagement != null) { // 查询对应的费用明细 ReceivableFeeDetail detail = new ReceivableFeeDetail(); detail.setReceivableFeeId(id); List detailList = receivableFeeDetailService.selectReceivableFeeDetailList(detail); receivableFeeManagement.setReceivableFeeDetailList(detailList); } return receivableFeeManagement; } /** * 查询应收费用管理 记录数 * * @param receivableFeeManagement 应收费用管理 * @return 应收费用管理集合 */ @DataSource(DataSourceType.SLAVE) @Override public int selectReceivableFeeManagementCount(ReceivableFeeManagement receivableFeeManagement) { return receivableFeeManagementMapper.selectReceivableFeeManagementCount(receivableFeeManagement); } /** * 查询应收费用管理列表 * * @param receivableFeeManagement 应收费用管理 * @return 应收费用管理 */ @DataSource(DataSourceType.SLAVE) @Override public List selectReceivableFeeManagementList(ReceivableFeeManagement receivableFeeManagement) { return receivableFeeManagementMapper.selectReceivableFeeManagementList(receivableFeeManagement); } /** * 查询应收费用管理列表 异步 导出 * * @param receivableFeeManagement 应收费用管理 * @param exportKey 导出功能的唯一标识 * @return 应收费用管理集合 */ @DataSource(DataSourceType.SLAVE) @Async @Override public void export(ReceivableFeeManagement receivableFeeManagement,String exportKey) { super.export(ReceivableFeeManagement.class,exportKey,"receivableFeeManagementData",(pageNum)->{ PageUtils.startPage(pageNum, Constants.EXPORT_PATE_SIZE); return selectReceivableFeeManagementList(receivableFeeManagement); }); } /** * 新增应收费用管理 * * @param receivableFeeManagement 应收费用管理 * @return 结果 */ @Override public int insertReceivableFeeManagement(ReceivableFeeManagement receivableFeeManagement) { receivableFeeManagement.setCreateTime(DateUtils.getNowDate()); String noByKey = systemDataNoService.getNoByKey(SystemDataNoEnum.YS); receivableFeeManagement.setSystemNo(noByKey); // 计算应收金额字符串描述 if (receivableFeeManagement.getReceivableFeeDetailList() != null && !receivableFeeManagement.getReceivableFeeDetailList().isEmpty()) { String receivableAmountStr = calculateReceivableAmountStr(receivableFeeManagement.getReceivableFeeDetailList()); receivableFeeManagement.setReceivableAmountStr(receivableAmountStr); } // 保存主表信息 int result = receivableFeeManagementMapper.insertReceivableFeeManagement(receivableFeeManagement); // 获取主表ID Integer receivableFeeId = receivableFeeManagement.getId(); // 批量保存明细列表 if (receivableFeeManagement.getReceivableFeeDetailList() != null && !receivableFeeManagement.getReceivableFeeDetailList().isEmpty()) { // 设置每个明细的应收费用管理ID receivableFeeManagement.getReceivableFeeDetailList().forEach(detail -> { detail.setReceivableFeeId(receivableFeeId); detail.setCreateTime(DateUtils.getNowDate()); // 设置创建时间 }); // 调用批量插入方法 receivableFeeDetailService.insertReceivableFeeDetailBatch(receivableFeeManagement.getReceivableFeeDetailList()); } // 记录操作日志 if (result > 0) { ReceivableFeeManagementLog log = new ReceivableFeeManagementLog(); log.setReceivableFeeId(receivableFeeId); log.setOperator(SecurityUtils.getUsername()); log.setOperationTime(DateUtils.getNowDate()); log.setOperationDesc("新增应收费用管理记录,系统编号:" + receivableFeeManagement.getSystemNo()); log.setCreateTime(DateUtils.getNowDate()); logService.insertReceivableFeeManagementLog(log); } return result; } /** * 修改应收费用管理 * * @param receivableFeeManagement 应收费用管理 * @return 结果 */ @Override public int updateReceivableFeeManagement(ReceivableFeeManagement receivableFeeManagement) { receivableFeeManagement.setUpdateTime(DateUtils.getNowDate()); // 计算应收金额字符串描述 if (receivableFeeManagement.getReceivableFeeDetailList() != null && !receivableFeeManagement.getReceivableFeeDetailList().isEmpty()) { String receivableAmountStr = calculateReceivableAmountStr(receivableFeeManagement.getReceivableFeeDetailList()); receivableFeeManagement.setReceivableAmountStr(receivableAmountStr); } // 1. 更新主表信息 int result = receivableFeeManagementMapper.updateReceivableFeeManagement(receivableFeeManagement); // 2. 获取主表ID Integer receivableFeeId = receivableFeeManagement.getId(); // 3. 删除该应收费用下的所有现有明细 receivableFeeDetailService.deleteReceivableFeeDetailByReceivableFeeId(receivableFeeId); // 4. 批量保存新的明细列表 if (receivableFeeManagement.getReceivableFeeDetailList() != null && !receivableFeeManagement.getReceivableFeeDetailList().isEmpty()) { // 设置每个明细的应收费用管理ID receivableFeeManagement.getReceivableFeeDetailList().forEach(detail -> { detail.setReceivableFeeId(receivableFeeId); detail.setUpdateTime(DateUtils.getNowDate()); // 设置更新时间 }); // 调用批量插入方法 receivableFeeDetailService.insertReceivableFeeDetailBatch(receivableFeeManagement.getReceivableFeeDetailList()); } // 记录操作日志 if (result > 0) { ReceivableFeeManagementLog log = new ReceivableFeeManagementLog(); log.setReceivableFeeId(receivableFeeId); log.setOperator(SecurityUtils.getUsername()); log.setOperationTime(DateUtils.getNowDate()); log.setOperationDesc("修改应收费用管理记录,系统编号:" + receivableFeeManagement.getSystemNo()); log.setCreateTime(DateUtils.getNowDate()); logService.insertReceivableFeeManagementLog(log); } return result; } /** * 作废应收费用管理记录 * * @param id 应收费用管理ID * @return 结果 */ @Override public int voidReceivableFeeManagement(Integer id) { // 查询费用管理记录 ReceivableFeeManagement feeManagement = receivableFeeManagementMapper.selectReceivableFeeManagementById(id); if (feeManagement == null) { throw new ServiceException("费用管理记录不存在"); } // 判断状态是否为0(待生成账单),只有状态为0才能作废 if (!"0".equals(feeManagement.getStatus())) { throw new ServiceException("只有状态为待生成账单的记录才能作废"); } // 设置状态为作废(假设用"2"表示作废状态) feeManagement.setStatus("2"); feeManagement.setUpdateTime(DateUtils.getNowDate()); // 更新记录 int result = receivableFeeManagementMapper.updateReceivableFeeManagement(feeManagement); // 记录操作日志 if (result > 0) { ReceivableFeeManagementLog log = new ReceivableFeeManagementLog(); log.setReceivableFeeId(id); log.setOperator(SecurityUtils.getUsername()); log.setOperationTime(DateUtils.getNowDate()); log.setOperationDesc("作废应收费用管理记录,系统编号:" + feeManagement.getSystemNo()); log.setCreateTime(DateUtils.getNowDate()); logService.insertReceivableFeeManagementLog(log); } return result; } /** * 新增应收费用管理[批量] * * @param receivableFeeManagements 应收费用管理 * @return 结果 */ @Override public int insertReceivableFeeManagementBatch(List receivableFeeManagements) { int rows = receivableFeeManagementMapper.insertReceivableFeeManagementBatch(receivableFeeManagements); return rows; } /** * 修改应收费用管理[批量] * * @param receivableFeeManagements 应收费用管理 * @return 结果 */ @Override public int updateReceivableFeeManagementBatch(List receivableFeeManagements){ return receivableFeeManagementMapper.updateReceivableFeeManagementBatch(receivableFeeManagements); } /** * 删除应收费用管理对象 * * @param ids 需要删除的数据ID * @return 结果 */ @Override public int deleteReceivableFeeManagementByIds(String ids) { return deleteReceivableFeeManagementByIds(Convert.toIntArray(ids)); } /** * 删除应收费用管理对象 * * * @param ids 需要删除的数据ID * @return 结果 */ @Override public int deleteReceivableFeeManagementByIds(Integer[] ids) { return receivableFeeManagementMapper.deleteReceivableFeeManagementByIds(ids); } /** * 删除应收费用管理信息 * * @param id 应收费用管理ID * @return 结果 */ @Override public int deleteReceivableFeeManagementById(Integer id) { return receivableFeeManagementMapper.deleteReceivableFeeManagementById(id); } /** * 根据应收费用ID数组查询统计信息和明细 * * @param ids 应收费用ID数组 * @return 包含统计信息和明细的结果 */ @DataSource(DataSourceType.SLAVE) @Override public ReceivableFeeStatisticsVo getReceivableFeeStatistics(Integer[] ids) { // 查询应收费用主表记录 List receivableFeeList = receivableFeeManagementMapper.selectReceivableFeeManagementByIds(ids); // 检查所有记录是否属于同一个客户 if (!receivableFeeList.isEmpty()) { Integer firstCustomerId = receivableFeeList.get(0).getCustomerId(); boolean allSameCustomer = receivableFeeList.stream() .allMatch(item -> Objects.equals(item.getCustomerId(), firstCustomerId)); if (!allSameCustomer) { throw new ServiceException("所选记录包含不同客户的数据,无法进行统计"); } } // 计算单据数量 int documentCount = receivableFeeList.size(); SysConfig sysConfig = sysConfigMapper.selectConfig(new SysConfig() {{ setConfigKey("sys.hk.rmb.rate"); }}); // 计算总应收金额(按币种分别计算) BigDecimal totalAmountRmb = BigDecimal.ZERO; BigDecimal totalAmountHkd = BigDecimal.ZERO; // 获取所有应收费用明细,按币种汇总 if (!receivableFeeList.isEmpty()) { // 获取所有应收费用ID Integer[] feeIds = receivableFeeList.stream() .map(ReceivableFeeManagement::getId) .toArray(Integer[]::new); // 查询所有明细记录 List allDetails = receivableFeeDetailService.selectReceivableFeeDetailByReceivableFeeIds(feeIds); // 按币种汇总金额 for (ReceivableFeeDetail detail : allDetails) { if (detail.getBillingAmount() != null && detail.getCurrency() != null) { if ("RMB".equals(detail.getCurrency())) { totalAmountRmb = totalAmountRmb.add(detail.getBillingAmount()); } else if ("HKD".equals(detail.getCurrency())) { totalAmountHkd = totalAmountHkd.add(detail.getBillingAmount()); } } } } BigDecimal exchangeRate = new BigDecimal(sysConfig.getConfigValue()); // 计算人民币总金额(人民币金额 + 港币换算成人民币) BigDecimal totalAmountRmbWithConversion = totalAmountRmb.add( totalAmountHkd.multiply(exchangeRate).setScale(2, RoundingMode.HALF_UP) ); // 计算港币总金额(港币金额 + 人民币换算成港币) BigDecimal totalAmountHkdWithConversion = totalAmountHkd.add( totalAmountRmb.divide(exchangeRate, 2, RoundingMode.HALF_UP) ); // 组装返回结果 ReceivableFeeStatisticsVo result = new ReceivableFeeStatisticsVo(); result.setDocumentCount(documentCount); result.setRate(exchangeRate); result.setTotalReceivableAmount(totalAmountRmbWithConversion); // 默认使用人民币总金额 result.setTotalAmountRmb(totalAmountRmbWithConversion); result.setTotalAmountHkd(totalAmountHkdWithConversion); result.setIds(ids); return result; } /** * 根据统计数据创建应收账单 * * @param billCreateVo 包含统计数据和账单类型的请求对象 * @return 创建的应收账单ID */ @Override public Integer createReceivableBill(ReceivableBillCreateVo billCreateVo) { // 1. 准备数据 ReceivableFeeStatisticsVo statisticsVo = billCreateVo.getStatisticsData(); // 检查费用管理表的状态,只有状态为0才能创建账单 Integer[] feeIds = statisticsVo.getIds(); if (feeIds != null && feeIds.length > 0) { for (Integer feeId : feeIds) { ReceivableFeeManagement feeManagement = receivableFeeManagementMapper.selectReceivableFeeManagementById(feeId); if (feeManagement != null && !"0".equals(feeManagement.getStatus())) { throw new ServiceException("费用记录ID为" + feeId + "的状态不是待生成账单,无法创建账单"); } } } Integer billType = billCreateVo.getBillType(); // 2. 创建应收账单主记录 ReceivableBillManagement billManagement = new ReceivableBillManagement(); billManagement.setDocumentCount(statisticsVo.getDocumentCount()); billManagement.setExchangeRate(statisticsVo.getRate()); billManagement.setStatus("0"); // 默认草稿状态 billManagement.setCreateTime(DateUtils.getNowDate()); billManagement.setBillName(billCreateVo.getBillName()); billManagement.setCustomerName(billCreateVo.getCustomerName()); billManagement.setIsInternalSettlement(billCreateVo.getIsInternalSettlement()); billManagement.setInternalSettlementUnit(billCreateVo.getInternalSettlementUnit()); // 3. 根据账单类型设置币种和总金额 if (billType == 0) { // 人民币账单 billManagement.setCurrency("RMB"); billManagement.setTotalAmount(statisticsVo.getTotalAmountRmb()); } else if (billType == 1) { // 港币账单 billManagement.setCurrency("HKD"); billManagement.setTotalAmount(statisticsVo.getTotalAmountHkd()); } else { throw new IllegalArgumentException("无效的账单类型:" + billType); } String noByKey = systemDataNoService.getNoByKey(SystemDataNoEnum.YSZD); billManagement.setSystemNo(noByKey); // 4. 保存主账单记录 int i = receivableBillManagementService.insertReceivableBillManagement(billManagement); // 5. 更新应收费用主表的关联账单编号 if (statisticsVo.getIds() != null && statisticsVo.getIds().length > 0) { // 获取生成的账单系统编号 String billSystemNo = billManagement.getSystemNo(); // 批量更新应收费用主表的关联账单编号 for (Integer feeId : statisticsVo.getIds()) { ReceivableFeeManagement feeManagement = new ReceivableFeeManagement(); feeManagement.setId(feeId); feeManagement.setRelatedBillNo(billSystemNo); feeManagement.setStatus("1"); receivableFeeManagementMapper.updateReceivableFeeManagement(feeManagement); // 记录操作日志 ReceivableFeeManagementLog log = new ReceivableFeeManagementLog(); log.setReceivableFeeId(feeId); log.setOperator(SecurityUtils.getUsername()); log.setOperationTime(DateUtils.getNowDate()); log.setOperationDesc("生成应收账单,账单编号:" + billSystemNo); log.setCreateTime(DateUtils.getNowDate()); logService.insertReceivableFeeManagementLog(log); } // 调用批量更新方法 } return i; } /** * 根据关联账单编号批量更新应收费用管理记录 * 清除关联账单编号并将状态改为0(待生成账单) * * @param relatedBillNo 关联账单编号 * @return 结果 */ @Override public int updateReceivableFeeManagementByRelatedBillNo(String relatedBillNo) { return receivableFeeManagementMapper.updateReceivableFeeManagementByRelatedBillNo(relatedBillNo); } /** * 计算应收金额字符串描述 * 根据明细列表按币种汇总金额,格式如:"200港币100人民币" * * @param detailList 应收费用明细列表 * @return 应收金额字符串描述 */ private String calculateReceivableAmountStr(List detailList) { if (detailList == null || detailList.isEmpty()) { return ""; } // 按币种汇总金额 Map currencyAmountMap = new HashMap<>(); for (ReceivableFeeDetail detail : detailList) { String currency = detail.getCurrency(); BigDecimal billingAmount = detail.getBillingAmount(); if (currency != null && billingAmount != null) { currencyAmountMap.merge(currency, billingAmount, BigDecimal::add); } } // 构建字符串描述 StringBuilder sb = new StringBuilder(); for (Map.Entry entry : currencyAmountMap.entrySet()) { if (sb.length() > 0) { sb.append(" "); } sb.append(entry.getValue().stripTrailingZeros().toPlainString()); // 根据币种显示对应的货币名称 String currency = entry.getKey(); if ("RMB".equals(currency)) { sb.append("人民币"); } else if ("HKD".equals(currency)) { sb.append("港币"); } else if ("USD".equals(currency)) { sb.append("美元"); } else { sb.append(currency); } } return sb.toString(); } }