diff --git a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/controller/WalletManageController.java b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/controller/WalletManageController.java index 7f9e550c8..43a92a41b 100644 --- a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/controller/WalletManageController.java +++ b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/controller/WalletManageController.java @@ -7,6 +7,7 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.bsd.pjcloud.common.asynctask.vo.AsyncTaskProgressVO; import com.bsd.pjcloud.common.core.util.R; import com.bsd.pjcloud.common.data.datascope.DataScope; import com.bsd.pjcloud.common.log.annotation.SysLog; @@ -24,8 +25,8 @@ import com.bsd.pjcloud.wallet.api.vo.WalletQbTotalVo; import com.bsd.pjcloud.wallet.mapper.WalletManageMapper; import com.bsd.pjcloud.wallet.mapper.mch.view.MchDeptViewMapper; import com.bsd.pjcloud.wallet.service.WalletCodeUseService; +import com.bsd.pjcloud.wallet.service.WalletManageExportService; import com.bsd.pjcloud.wallet.service.WalletManageService; -import jakarta.servlet.http.HttpServletResponse; import org.springframework.security.access.prepost.PreAuthorize; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import org.springdoc.core.annotations.ParameterObject; @@ -50,6 +51,9 @@ public class WalletManageController { private final WalletManageService walletManageService; private final WalletCodeUseService walletCodeUseService; + /** 钱包管理异步导出服务,负责提交任务并生成可轮询的文件结果。 */ + private final WalletManageExportService walletManageExportService; + private final WalletManageMapper walletManageMapper; private final MchDeptViewMapper mchDeptViewMapper; @@ -358,15 +362,27 @@ public class WalletManageController { return R.ok(walletManageService.removeBatchByIds(CollUtil.toList(ids))); } + /** + * 按当前筛选条件提交账户余额异步导出任务。 + * + * @param dto 账户余额筛选条件 + * @return 供前端轮询的初始进度,成功终态包含文件下载地址 + */ @PostMapping("/export") @PreAuthorize("@pms.hasPermission('wallet_walletManage_export')") - public void export(HttpServletResponse response, @ParameterObject Page page, @RequestBody WalletManageDto dto) { - walletManageService.export(response, page, dto); + public R export(@RequestBody WalletManageDto dto) { + return R.ok(walletManageExportService.submitExport(dto), "账户余额导出任务已提交"); } + /** + * 按当前筛选条件提交月度钱包记录异步导出任务。 + * + * @param dto 月度钱包记录筛选条件 + * @return 供前端轮询的初始进度,成功终态包含文件下载地址 + */ @PostMapping("/export-qb") // @PreAuthorize("@pms.hasPermission('wallet_walletManage_export')") - public void exportQb(HttpServletResponse response, @ParameterObject Page page, @RequestBody WalletManageBalanceDto dto) { - walletManageService.exportQb(response, page, dto); + public R exportQb(@RequestBody WalletManageBalanceDto dto) { + return R.ok(walletManageExportService.submitQbExport(dto), "钱包记录导出任务已提交"); } } diff --git a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/WalletManageExportService.java b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/WalletManageExportService.java new file mode 100644 index 000000000..fc78384b9 --- /dev/null +++ b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/WalletManageExportService.java @@ -0,0 +1,28 @@ +package com.bsd.pjcloud.wallet.service; + +import com.bsd.pjcloud.common.asynctask.vo.AsyncTaskProgressVO; +import com.bsd.pjcloud.wallet.api.dto.WalletManageBalanceDto; +import com.bsd.pjcloud.wallet.api.dto.WalletManageDto; + +/** + * 钱包管理导出服务。 + *

导出任务统一异步执行,提交接口只返回任务进度,文件生成后由通用进度接口提供下载地址。

+ */ +public interface WalletManageExportService { + + /** + * 提交账户余额异步导出任务。 + * + * @param dto 账户余额筛选条件;任务提交后会复制一份条件供后台线程独占使用 + * @return 已创建的异步任务初始进度 + */ + AsyncTaskProgressVO submitExport(WalletManageDto dto); + + /** + * 提交月度钱包记录异步导出任务。 + * + * @param dto 月度钱包记录筛选条件;任务提交后会复制一份条件供后台线程独占使用 + * @return 已创建的异步任务初始进度 + */ + AsyncTaskProgressVO submitQbExport(WalletManageBalanceDto dto); +} diff --git a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/WalletManageService.java b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/WalletManageService.java index fa4830bba..4f4d42af2 100644 --- a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/WalletManageService.java +++ b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/WalletManageService.java @@ -12,7 +12,6 @@ import com.bsd.pjcloud.wallet.api.entity.WalletManageEntity; import com.bsd.pjcloud.wallet.api.entity.mch.MchTakeOutSettingEntity; import com.bsd.pjcloud.wallet.api.vo.WalletManageVo; import com.bsd.pjcloud.wallet.api.vo.WalletQbTotalVo; -import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.constraints.NotNull; import java.util.List; @@ -105,16 +104,6 @@ public interface WalletManageService extends IService { */ String getQrCode(Long walletId); - /** - * 导出 - */ - void export(HttpServletResponse response, Page page, WalletManageDto dto); - - /** - * 钱包记录导出 - */ - void exportQb(HttpServletResponse response, Page page, WalletManageBalanceDto dto); - /** * 修改用户 */ diff --git a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/WalletManageExportServiceImpl.java b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/WalletManageExportServiceImpl.java new file mode 100644 index 000000000..19f5b3cba --- /dev/null +++ b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/WalletManageExportServiceImpl.java @@ -0,0 +1,381 @@ +package com.bsd.pjcloud.wallet.service.impl; + +import cn.hutool.core.io.resource.ResourceUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.alibaba.excel.write.metadata.fill.FillConfig; +import com.bsd.pjcloud.admin.api.feign.RemoteFileService; +import com.bsd.pjcloud.common.asynctask.service.AsyncTaskExecutorService; +import com.bsd.pjcloud.common.asynctask.service.AsyncTaskProgressReporter; +import com.bsd.pjcloud.common.asynctask.service.AsyncTaskResult; +import com.bsd.pjcloud.common.asynctask.vo.AsyncTaskProgressVO; +import com.bsd.pjcloud.common.core.util.R; +import com.bsd.pjcloud.common.data.datascope.DataScope; +import com.bsd.pjcloud.common.data.datascope.DataScopeFuncEnum; +import com.bsd.pjcloud.wallet.api.dto.WalletManageBalanceDto; +import com.bsd.pjcloud.wallet.api.dto.WalletManageDto; +import com.bsd.pjcloud.wallet.api.vo.WalletManageVo; +import com.bsd.pjcloud.wallet.mapper.WalletManageMapper; +import com.bsd.pjcloud.wallet.service.WalletManageExportService; +import com.bsd.pjcloud.wallet.service.WalletManageService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 钱包管理导出服务实现。 + *

导出过程沿用系统用户导出的异步任务、进度上报和文件中心上传协议,避免 HTTP 请求长时间占用连接。

+ */ +@Slf4j +@Service +public class WalletManageExportServiceImpl implements WalletManageExportService { + + /** 账户余额导出任务的 Redis Key 命名空间。 */ + private static final String BALANCE_EXPORT_REDIS_KEY = "wallet:manage:export:balance"; + + /** 钱包记录导出任务的 Redis Key 命名空间。 */ + private static final String RECORD_EXPORT_REDIS_KEY = "wallet:manage:export:record"; + + /** 账户余额导出任务展示名称。 */ + private static final String BALANCE_EXPORT_TASK_NAME = "账户余额导出"; + + /** 钱包记录导出任务展示名称。 */ + private static final String RECORD_EXPORT_TASK_NAME = "钱包记录导出"; + + /** 查询真实数据量前创建任务使用的占位总数。 */ + private static final int INITIAL_TOTAL = 1; + + /** 账户余额导出的最大记录数,与原同步导出限制保持一致。 */ + private static final int MAX_BALANCE_EXPORT_SIZE = 5000; + + /** 账户余额导出模板路径。 */ + private static final String BALANCE_TEMPLATE_PATH = "file/账户余额.xlsx"; + + /** 月度钱包记录导出模板路径。 */ + private static final String RECORD_TEMPLATE_PATH = "file/个人钱包记录明细.xlsx"; + + /** 文件中心保存导出文件的业务目录。 */ + private static final String EXPORT_FILE_DIR = "wallet-export"; + + /** 文件中心标记账户余额导出的类型编码。 */ + private static final String BALANCE_EXPORT_FILE_TYPE = "WALLET_BALANCE_EXPORT"; + + /** 文件中心标记钱包记录导出的类型编码。 */ + private static final String RECORD_EXPORT_FILE_TYPE = "WALLET_RECORD_EXPORT"; + + /** Excel 文件上传时使用的 MIME 类型。 */ + private static final String EXCEL_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + + /** 异步生成文件名使用的时间格式,避免连续导出文件名难以区分。 */ + private static final DateTimeFormatter EXPORT_FILE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + + /** 钱包查询服务,负责执行数据权限过滤、用户部门补充和钱包类型转换。 */ + private final WalletManageService walletManageService; + + /** 钱包 Mapper,用于在账户余额导出前按数据权限统计记录数。 */ + private final WalletManageMapper walletManageMapper; + + /** 通用异步任务执行器,负责恢复租户、安全和 Feign 上下文并持久化进度。 */ + private final AsyncTaskExecutorService asyncTaskExecutorService; + + /** 文件中心远程服务,用于保存异步生成的 Excel 文件。 */ + private final RemoteFileService remoteFileService; + + /** + * 创建钱包管理导出服务。 + * + * @param walletManageService 钱包查询服务 + * @param walletManageMapper 钱包数据 Mapper + * @param asyncTaskExecutorService 通用异步任务执行器 + * @param remoteFileService 文件中心远程服务 + */ + public WalletManageExportServiceImpl(WalletManageService walletManageService, WalletManageMapper walletManageMapper, + AsyncTaskExecutorService asyncTaskExecutorService, RemoteFileService remoteFileService) { + this.walletManageService = walletManageService; + this.walletManageMapper = walletManageMapper; + this.asyncTaskExecutorService = asyncTaskExecutorService; + this.remoteFileService = remoteFileService; + } + + /** + * 提交账户余额异步导出任务。 + * + * @param dto 账户余额筛选条件 + * @return 已创建的异步任务初始进度 + */ + @Override + public AsyncTaskProgressVO submitExport(WalletManageDto dto) { + WalletManageDto querySnapshot = copyWalletManageDto(dto); + return asyncTaskExecutorService.submitWithResult(BALANCE_EXPORT_REDIS_KEY, BALANCE_EXPORT_TASK_NAME, + INITIAL_TOTAL, reporter -> exportBalance(querySnapshot, reporter)); + } + + /** + * 提交月度钱包记录异步导出任务。 + * + * @param dto 月度钱包记录筛选条件 + * @return 已创建的异步任务初始进度 + */ + @Override + public AsyncTaskProgressVO submitQbExport(WalletManageBalanceDto dto) { + WalletManageBalanceDto querySnapshot = copyBalanceDto(dto); + return asyncTaskExecutorService.submitWithResult(RECORD_EXPORT_REDIS_KEY, RECORD_EXPORT_TASK_NAME, + INITIAL_TOTAL, reporter -> exportWalletRecords(querySnapshot, reporter)); + } + + /** + * 查询、整理并上传账户余额导出文件。 + * + * @param dto 后台线程独占的账户余额筛选条件 + * @param reporter 当前异步任务进度报告器 + * @return 文件中心下载地址和文件名 + */ + private AsyncTaskResult exportBalance(WalletManageDto dto, AsyncTaskProgressReporter reporter) { + Long count = walletManageMapper.count(dto, DataScope.of().func(DataScopeFuncEnum.COUNT)); + if (count == null || count == 0) { + throw new IllegalStateException("没有符合当前条件的账户余额"); + } + if (count > MAX_BALANCE_EXPORT_SIZE) { + throw new IllegalStateException("导出数据超出5000条,请缩小查询范围"); + } + + List list = walletManageService.scopeList(dto, DataScope.of()); + if (ObjectUtil.isEmpty(list)) { + throw new IllegalStateException("没有符合当前条件的账户余额"); + } + if (list.size() > MAX_BALANCE_EXPORT_SIZE) { + throw new IllegalStateException("导出数据超出5000条,请缩小查询范围"); + } + reporter.updateTotal(list.size(), "已查询 " + list.size() + " 条账户余额"); + Map summary = prepareBalanceRows(dto, list, reporter); + String fileName = "电子钱包_" + LocalDateTime.now().format(EXPORT_FILE_TIME_FORMATTER) + ".xlsx"; + String fileUrl = writeAndUpload(BALANCE_TEMPLATE_PATH, summary, list, fileName, BALANCE_EXPORT_FILE_TYPE); + reporter.advance("账户余额导出文件已生成,共 " + list.size() + " 条"); + return AsyncTaskResult.file(fileUrl, fileName); + } + + /** + * 查询、整理并上传钱包记录导出文件。 + * + * @param dto 后台线程独占的月度钱包记录筛选条件 + * @param reporter 当前异步任务进度报告器 + * @return 文件中心下载地址和文件名 + */ + private AsyncTaskResult exportWalletRecords(WalletManageBalanceDto dto, AsyncTaskProgressReporter reporter) { + List list = walletManageService.scopeQbList(dto, DataScope.of()); + if (ObjectUtil.isEmpty(list)) { + throw new IllegalStateException("没有符合当前条件的钱包记录"); + } + reporter.updateTotal(list.size(), "已查询 " + list.size() + " 条钱包记录"); + Map summary = prepareRecordRows(list, reporter, dto.getWalletRecordMonth()); + String fileName = "钱包记录_" + LocalDateTime.now().format(EXPORT_FILE_TIME_FORMATTER) + ".xlsx"; + String fileUrl = writeAndUpload(RECORD_TEMPLATE_PATH, summary, list, fileName, RECORD_EXPORT_FILE_TYPE); + reporter.advance("钱包记录导出文件已生成,共 " + list.size() + " 条"); + return AsyncTaskResult.file(fileUrl, fileName); + } + + /** + * 为账户余额行补充序号、金额展示值并累计汇总金额。 + * + * @param dto 账户余额筛选条件,用于填充模板中的查询时间范围 + * @param list 待导出的账户余额列表 + * @param reporter 当前异步任务进度报告器 + * @return Excel 模板头部需要填充的汇总字段 + */ + private Map prepareBalanceRows(WalletManageDto dto, List list, + AsyncTaskProgressReporter reporter) { + Map summary = new HashMap<>(); + if (ObjectUtil.isNotEmpty(dto.getCreateTimeList())) { + summary.put("timeSpan", " 到 "); + summary.put("startTime", LocalDateTimeUtil.format(dto.getCreateTimeList()[0], DatePattern.NORM_DATETIME_PATTERN)); + summary.put("endTime", LocalDateTimeUtil.format(dto.getCreateTimeList()[1], DatePattern.NORM_DATETIME_PATTERN)); + } + long balanceSum = 0; + long totalExpenseSum = 0; + long totalRechargeSum = 0; + for (int index = 0; index < list.size(); index++) { + WalletManageVo item = list.get(index); + item.setLineNumber((long) index + 1); + if (item.getBalance() != null) { + balanceSum += item.getBalance(); + item.setBalanceStr(formatPrice(item.getBalance())); + } + if (item.getTotalExpense() != null) { + totalExpenseSum += item.getTotalExpense(); + item.setTotalExpenseStr(formatPrice(item.getTotalExpense())); + } + if (item.getTotalRecharge() != null) { + totalRechargeSum += item.getTotalRecharge(); + item.setTotalRechargeStr(formatPrice(item.getTotalRecharge())); + } + advanceExceptLast(reporter, index, list.size(), "正在整理第 " + (index + 1) + " / " + list.size() + " 条账户余额"); + } + summary.put("balanceSum", formatPrice(balanceSum)); + summary.put("totalExpenseSum", formatPrice(totalExpenseSum)); + summary.put("totalRechargeSum", formatPrice(totalRechargeSum)); + return summary; + } + + /** + * 为钱包记录行补充序号、金额展示值并累计余额。 + * + * @param list 待导出的钱包记录列表 + * @param reporter 当前异步任务进度报告器 + * @param walletRecordMonth 查询月份,写入模板头部 + * @return Excel 模板头部需要填充的汇总字段 + */ + private Map prepareRecordRows(List list, AsyncTaskProgressReporter reporter, + String walletRecordMonth) { + Map summary = new HashMap<>(); + long balanceSum = 0; + summary.put("walletRecordMonth", walletRecordMonth); + for (int index = 0; index < list.size(); index++) { + WalletManageVo item = list.get(index); + item.setLineNumber((long) index + 1); + if (item.getBalance() != null) { + balanceSum += item.getBalance(); + item.setBalanceStr(formatPrice(item.getBalance())); + } + advanceExceptLast(reporter, index, list.size(), "正在整理第 " + (index + 1) + " / " + list.size() + " 条钱包记录"); + } + summary.put("balanceSum", formatPrice(balanceSum)); + return summary; + } + + /** + * 在文件生成前报告除最后一条以外的行处理进度,最后一条在上传成功后报告,避免提前显示 100%。 + * + * @param reporter 当前异步任务进度报告器 + * @param index 当前行下标 + * @param total 总行数 + * @param message 当前处理说明 + */ + private void advanceExceptLast(AsyncTaskProgressReporter reporter, int index, int total, String message) { + if (index < total - 1) { + reporter.advance(message); + } + } + + /** + * 将分单位金额转换为模板展示使用的元字符串。 + * + * @param amount 金额,单位分 + * @return 两位小数的元金额字符串 + */ + private String formatPrice(long amount) { + return BigDecimal.valueOf(amount).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP).toPlainString(); + } + + /** + * 使用既有模板填充 Excel,并上传到文件中心。 + * + * @param templatePath 类路径模板 + * @param summary 模板头部汇总字段 + * @param rows 模板明细行 + * @param fileName 下载文件名 + * @param fileType 文件中心分类编码 + * @return 文件中心下载地址 + */ + private String writeAndUpload(String templatePath, Map summary, List rows, + String fileName, String fileType) { + try (InputStream template = ResourceUtil.getStream(templatePath); ByteArrayOutputStream output = new ByteArrayOutputStream()) { + try (ExcelWriter excelWriter = EasyExcel.write(output).withTemplate(template).build()) { + WriteSheet writeSheet = EasyExcel.writerSheet().build(); + FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build(); + excelWriter.fill(summary, writeSheet); + excelWriter.fill(rows, fillConfig, writeSheet); + } + MultipartFile exportFile = new MockMultipartFile("file", encodeUploadOriginalFilename(fileName), + EXCEL_CONTENT_TYPE, output.toByteArray()); + R uploadResult = remoteFileService.innerUpload(exportFile, EXPORT_FILE_DIR, null, fileType); + if (uploadResult == null || !uploadResult.isOk() || !(uploadResult.getData() instanceof Map resultData)) { + throw new IllegalStateException("文件中心未返回有效的钱包导出结果"); + } + Object resultUrl = resultData.get("url"); + if (resultUrl == null || StrUtil.isBlank(resultUrl.toString())) { + throw new IllegalStateException("文件中心未返回钱包导出下载地址"); + } + return resultUrl.toString(); + } catch (Exception exception) { + log.error("|钱包管理导出|生成或保存文件失败,fileName:{}", fileName, exception); + throw new IllegalStateException("生成钱包导出文件失败", exception); + } + } + + /** + * 复制账户余额筛选条件,避免异步线程读取请求对象中的可变集合。 + * + * @param source 控制器接收的筛选条件,可为空 + * @return 后台线程独占的筛选条件副本 + */ + private WalletManageDto copyWalletManageDto(WalletManageDto source) { + WalletManageDto target = new WalletManageDto(); + if (source == null) { + return target; + } + BeanUtils.copyProperties(source, target); + target.setUserIds(copyList(source.getUserIds())); + target.setWalletIds(copyList(source.getWalletIds())); + target.setDeptIds(copyList(source.getDeptIds())); + target.setCreateTimeList(source.getCreateTimeList() == null ? null : source.getCreateTimeList().clone()); + return target; + } + + /** + * 复制钱包记录筛选条件,避免异步线程读取请求对象中的可变集合。 + * + * @param source 控制器接收的筛选条件,可为空 + * @return 后台线程独占的筛选条件副本 + */ + private WalletManageBalanceDto copyBalanceDto(WalletManageBalanceDto source) { + WalletManageBalanceDto target = new WalletManageBalanceDto(); + if (source == null) { + return target; + } + BeanUtils.copyProperties(source, target); + target.setUserIds(copyList(source.getUserIds())); + target.setDeptIds(copyList(source.getDeptIds())); + target.setScopeDeptIds(copyList(source.getScopeDeptIds())); + return target; + } + + /** + * 复制可变筛选集合,空值保持空值语义。 + * + * @param source 请求中的筛选集合 + * @param 集合元素类型 + * @return 非空时返回新的列表 + */ + private List copyList(List source) { + return source == null ? null : new ArrayList<>(source); + } + + /** + * 按文件服务约定编码中文原始文件名,避免文件中心的 ISO-8859-1 转 UTF-8 过程产生乱码。 + * + * @param fileName 用户下载时看到的 UTF-8 文件名 + * @return 交给文件中心上传接口的原始文件名 + */ + private String encodeUploadOriginalFilename(String fileName) { + return new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1); + } +} diff --git a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/WalletManageServiceImpl.java b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/WalletManageServiceImpl.java index 482e9a9c8..51fc6a9a3 100644 --- a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/WalletManageServiceImpl.java +++ b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/WalletManageServiceImpl.java @@ -3,14 +3,8 @@ package com.bsd.pjcloud.wallet.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.LocalDateTimeUtil; -import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.extra.spring.SpringUtil; -import com.alibaba.excel.EasyExcel; -import com.alibaba.excel.ExcelWriter; -import com.alibaba.excel.write.metadata.WriteSheet; -import com.alibaba.excel.write.metadata.fill.FillConfig; -import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -52,7 +46,6 @@ import com.bsd.pjcloud.wallet.mapper.WalletTransactionMapper; import com.bsd.pjcloud.wallet.mapper.WalletTypeMapper; import com.bsd.pjcloud.wallet.mapper.mch.MchTakeOutSettingMapper; import com.bsd.pjcloud.wallet.service.*; -import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.constraints.NotNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -62,12 +55,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import java.io.IOException; -import java.math.BigDecimal; -import java.math.RoundingMode; import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CopyOnWriteArrayList; /** * 钱包管理 @@ -466,85 +454,6 @@ public class WalletManageServiceImpl extends ServiceImpl 5000) throw new RuntimeException("导出数据超出5000条,请缩小查询范围"); - List list = scopeList(dto, dataScope); - try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(ResourceUtil.getStream(fileName)).build()) { - WriteSheet writeSheet = EasyExcel.writerSheet().build(); - FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build(); - Map map = new HashMap(); - if (ObjectUtil.isNotEmpty(dto.getCreateTimeList())) { - map.put("timeSpan", " 到 "); - map.put("startTime", LocalDateTimeUtil.format(dto.getCreateTimeList()[0], DatePattern.NORM_DATETIME_PATTERN)); - map.put("endTime", LocalDateTimeUtil.format(dto.getCreateTimeList()[1], DatePattern.NORM_DATETIME_PATTERN)); - } - if (ObjectUtil.isNotEmpty(list)) { - BigDecimal balanceSum = BigDecimal.ZERO; - BigDecimal totalExpenseSum = BigDecimal.ZERO; - BigDecimal totalRechargeSum = BigDecimal.ZERO; - Long lineNumber = 1L; - for (WalletManageVo v : list) { - v.setLineNumber(lineNumber); - lineNumber++; - if (ObjectUtil.isNotEmpty(v.getBalance())) { - balanceSum = balanceSum.add(BigDecimal.valueOf(v.getBalance())); - v.setBalanceStr(BigDecimal.valueOf(v.getBalance()).divide(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP).toString()); - } - if (ObjectUtil.isNotEmpty(v.getTotalExpense())) { - totalExpenseSum = totalExpenseSum.add(BigDecimal.valueOf(v.getTotalExpense())); - v.setTotalExpenseStr(BigDecimal.valueOf(v.getTotalExpense()).divide(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP).toString()); - } - if (ObjectUtil.isNotEmpty(v.getTotalRecharge())) { - totalRechargeSum = totalRechargeSum.add(BigDecimal.valueOf(v.getTotalRecharge())); - v.setTotalRechargeStr(BigDecimal.valueOf(v.getTotalRecharge()).divide(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP).toString()); - } - } - map.put("balanceSum", balanceSum.divide(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP).toString()); - map.put("totalExpenseSum", totalExpenseSum.divide(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP).toString()); - map.put("totalRechargeSum", totalRechargeSum.divide(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP).toString()); - } - excelWriter.fill(map, writeSheet); - excelWriter.fill(list, fillConfig, writeSheet); - } catch (IOException e) { - e.printStackTrace(); - log.error("|{}|导入错误,dto:|{}|,fileName:|{}|,error:|{}|", TAG, JSON.toJSONString(dto), fileName, e.getMessage()); - } - } - - @Override - public void exportQb(HttpServletResponse response, Page page, WalletManageBalanceDto dto) { - String fileName = "file/个人钱包记录明细.xlsx"; - List list = scopeQbList(dto, DataScope.of()); - try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(ResourceUtil.getStream(fileName)).build()) { - WriteSheet writeSheet = EasyExcel.writerSheet().build(); - FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build(); - Map map = new HashMap(); - map.put("walletRecordMonth", dto.getWalletRecordMonth()); - if (ObjectUtil.isNotEmpty(list)) { - Long lineNumber = 1L; - BigDecimal balanceSum = BigDecimal.ZERO; - for (WalletManageVo v : list) { - v.setLineNumber(lineNumber); - lineNumber++; - if (ObjectUtil.isNotEmpty(v.getBalance())) { - balanceSum = balanceSum.add(BigDecimal.valueOf(v.getBalance())); - v.setBalanceStr(BigDecimal.valueOf(v.getBalance()).divide(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP).toString()); - } - } - map.put("balanceSum", balanceSum.divide(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP).toString()); - } - excelWriter.fill(map, writeSheet); - excelWriter.fill(list, fillConfig, writeSheet); - } catch (IOException e) { - e.printStackTrace(); - log.error("|{}|导入错误,dto:|{}|,fileName:|{}|,error:|{}|", TAG, JSON.toJSONString(dto), fileName, e.getMessage()); - } - } - @Override @Transactional(rollbackFor = Exception.class) public void userChange(Long userId, Boolean isDel) {