| | |
| | | package com.ruoyi.cwgl.service.impl; |
| | | |
| | | import java.io.File; |
| | | import java.io.OutputStream; |
| | | import java.lang.reflect.Field; |
| | | import java.nio.file.Files; |
| | | import java.nio.file.Paths; |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.util.*; |
| | | |
| | | import com.ruoyi.common.annotation.Excel; |
| | | 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.common.utils.file.DownloadExportUtil; |
| | | import com.ruoyi.common.utils.file.DownloadExportUtil.ExprotStatus; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.cwgl.domain.*; |
| | | 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 com.ruoyi.common.annotation.DataSource; |
| | | import com.ruoyi.common.enums.DataSourceType; |
| | | import com.ruoyi.common.core.service.BaseService; |
| | | import com.ruoyi.common.config.RuoYiConfig; |
| | | import com.ruoyi.common.exception.UtilException; |
| | | import com.ruoyi.common.core.redis.RedisCache; |
| | | |
| | | 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; |
| | | import org.apache.poi.ss.usermodel.*; |
| | | import org.apache.poi.xssf.streaming.SXSSFWorkbook; |
| | | |
| | | /** |
| | | * 应收费用管理Service业务层处理 |
| | |
| | | |
| | | @Autowired |
| | | private IReceivableFeeManagementLogService logService; |
| | | |
| | | @Autowired |
| | | private RedisCache redisCache; |
| | | |
| | | @Autowired |
| | | private ITmsCustomerInfoService tmsCustomerInfoService; |
| | | |
| | | /** |
| | | * 查询应收费用管理 |
| | |
| | | // 设置每个明细的应收费用管理ID |
| | | receivableFeeManagement.getReceivableFeeDetailList().forEach(detail -> { |
| | | detail.setReceivableFeeId(receivableFeeId); |
| | | detail.setUpdateTime(DateUtils.getNowDate()); // 设置更新时间 |
| | | detail.setCreateTime(DateUtils.getNowDate()); // 设置更新时间 |
| | | }); |
| | | |
| | | // 调用批量插入方法 |
| | |
| | | |
| | | return sb.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 导入应收费用管理数据(包含明细数据) |
| | | * |
| | | * @param receivableFeeList 应收费用管理数据列表(包含明细数据) |
| | | * @param operName 操作用户 |
| | | * @return 结果 |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public String importReceivableFee(List<ReceivableFeeManagement> receivableFeeList, String operName) { |
| | | if (receivableFeeList == null || receivableFeeList.isEmpty()) { |
| | | throw new ServiceException("导入应收费用数据不能为空!"); |
| | | } |
| | | int successNum = 0; |
| | | int failureNum = 0; |
| | | StringBuilder successMsg = new StringBuilder(); |
| | | StringBuilder failureMsg = new StringBuilder(); |
| | | |
| | | // 获取当前日期 |
| | | Date now = DateUtils.getNowDate(); |
| | | |
| | | for (ReceivableFeeManagement receivableFee : receivableFeeList) { |
| | | try { |
| | | // 自动生成系统编号(和新增功能一样) |
| | | String noByKey = systemDataNoService.getNoByKey(SystemDataNoEnum.YS); |
| | | receivableFee.setSystemNo(noByKey); |
| | | |
| | | // 设置创建时间和创建人 |
| | | receivableFee.setCreateTime(now); |
| | | receivableFee.setCreateBy(operName); |
| | | |
| | | // 根据客户名称查询客户ID |
| | | if (receivableFee.getCustomerName() != null && !receivableFee.getCustomerName().isEmpty()) { |
| | | TmsCustomerInfo customerQuery = new TmsCustomerInfo(); |
| | | customerQuery.setCustomerFullName(receivableFee.getCustomerName()); |
| | | List<TmsCustomerInfo> customerList = tmsCustomerInfoService.selectTmsCustomerInfoList(customerQuery); |
| | | if (customerList != null && !customerList.isEmpty()) { |
| | | // 取第一个匹配的客户 |
| | | TmsCustomerInfo customer = customerList.get(0); |
| | | receivableFee.setCustomerId(customer.getId()); |
| | | } else { |
| | | // 如果没有找到匹配的客户,可以记录日志或抛出异常 |
| | | logger.warn("未找到客户名称为 '{}' 的客户信息,customerId将设置为null", receivableFee.getCustomerName()); |
| | | } |
| | | } |
| | | |
| | | // 计算应收金额字符串描述 |
| | | if (receivableFee.getReceivableFeeDetailList() != null && !receivableFee.getReceivableFeeDetailList().isEmpty()) { |
| | | String receivableAmountStr = calculateReceivableAmountStr(receivableFee.getReceivableFeeDetailList()); |
| | | receivableFee.setReceivableAmountStr(receivableAmountStr); |
| | | } |
| | | |
| | | // 设置默认状态为待生成账单(0) |
| | | if (receivableFee.getStatus() == null || receivableFee.getStatus().isEmpty()) { |
| | | receivableFee.setStatus("0"); |
| | | } |
| | | |
| | | // 插入主表数据 |
| | | receivableFeeManagementMapper.insertReceivableFeeManagement(receivableFee); |
| | | |
| | | // 处理明细数据(如果有) |
| | | if (receivableFee.getReceivableFeeDetailList() != null && !receivableFee.getReceivableFeeDetailList().isEmpty()) { |
| | | for (ReceivableFeeDetail detail : receivableFee.getReceivableFeeDetailList()) { |
| | | detail.setReceivableFeeId(receivableFee.getId()); |
| | | detail.setCreateBy(operName); |
| | | detail.setCreateTime(now); |
| | | receivableFeeDetailService.insertReceivableFeeDetail(detail); |
| | | } |
| | | } |
| | | |
| | | successNum++; |
| | | successMsg.append("<br/>" + successNum + ".应收费用 " + receivableFee.getSystemNo() + " 导入成功"); |
| | | } catch (Exception e) { |
| | | failureNum++; |
| | | String msg = "<br/>" + failureNum + ".应收费用 " + receivableFee.getSystemNo() + " 导入失败:"; |
| | | failureMsg.append(msg + e.getMessage()); |
| | | logger.error(msg, e); |
| | | } |
| | | } |
| | | |
| | | if (failureNum > 0) { |
| | | failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); |
| | | throw new ServiceException(failureMsg.toString()); |
| | | } else { |
| | | successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); |
| | | } |
| | | return successMsg.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 下载导入模板(包含Sheet1主表和Sheet2明细表) |
| | | * |
| | | * @param exportKey 导出功能的唯一标识 |
| | | */ |
| | | @DataSource(DataSourceType.SLAVE) |
| | | @Async |
| | | @Override |
| | | public void importTemplate(String exportKey) { |
| | | String fileName = ExcelUtil.encodeFileName("应收费用导入模板"); |
| | | |
| | | // 设置当前任务为"下载中"状态 |
| | | DownloadExportUtil.deleteDownloadFile(redisCache, exportKey, ExprotStatus.XZZ.getStatus()); |
| | | |
| | | try { |
| | | // 创建空列表用于生成模板(只需要表头) |
| | | List<ReceivableFeeManagement> mainList = new ArrayList<>(); |
| | | List<ReceivableFeeDetail> detailList = new ArrayList<>(); |
| | | |
| | | // 使用我们新实现的exportMultiSheetData方法创建双sheet模板 |
| | | exportMultiSheetData( |
| | | ReceivableFeeManagement.class, |
| | | ReceivableFeeDetail.class, |
| | | fileName, |
| | | "应收费用主表", |
| | | "应收费用明细", |
| | | mainList, |
| | | detailList |
| | | ); |
| | | |
| | | // 设置下载完成状态 |
| | | DownloadExportUtil.setDownloadFile(redisCache, exportKey, fileName); |
| | | logger.info("导入模板导出完成: {}, file: {}", exportKey, fileName); |
| | | } catch (Exception e) { |
| | | logger.error("导入模板导出失败: {}, error: {}", exportKey, e.getMessage(), e); |
| | | DownloadExportUtil.deleteDownloadFile(redisCache, exportKey, ExprotStatus.XZYC.getStatus()); // 设置失败状态 |
| | | throw e; |
| | | } |
| | | } |
| | | |
| | | // 删除不再需要的方法 |
| | | /** |
| | | * 获取文件的绝对路径 |
| | | */ |
| | | private File getAbsoluteFile(String fileName) { |
| | | String downloadPath = RuoYiConfig.getDownloadPath(); |
| | | return new File(downloadPath + fileName); |
| | | } |
| | | } |