From 4816f151d677929f2c2faf62cd1ad2e4371a7b15 Mon Sep 17 00:00:00 2001 From: dzc <2388224167@qq.com> Date: Thu, 13 Aug 2026 15:41:29 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E5=A2=9E=E5=8A=A0=E5=AD=A6?= =?UTF-8?q?=E7=94=9F=E5=AE=B6=E9=95=BF=E5=AF=BC=E5=85=A5=E3=80=82=20feat?= =?UTF-8?q?=EF=BC=9A=E9=92=B1=E5=8C=85=E6=B5=81=E6=B0=B4=E3=80=81=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E5=85=85=E5=80=BC=E5=A2=9E=E5=8A=A0tag=E3=80=82=20fea?= =?UTF-8?q?t=EF=BC=9A=E4=BC=98=E5=8C=96=E8=A1=A8=E6=A0=BC=E5=8C=BA?= =?UTF-8?q?=E5=9F=9F=E7=9A=84=E6=90=9C=E7=B4=A2=E9=80=BB=E8=BE=91=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/20260813_add_wallet_transaction_tags.sql | 6 ++ db/800pjcloudx_wallet.sql | 2 + .../common/excel/annotation/ExcelDict.java | 8 +++ .../excel/annotation/ExcelTemplate.java | 9 ++- .../common/excel/aop/ExcelTemplateAspect.java | 18 +++++- .../dict/ExcelDictDataValidationWriter.java | 33 ++++++++-- .../handler/DefaultAnalysisEventListener.java | 22 +++++-- .../pjcloud-thirdparty-biz/pom.xml | 7 ++ ...pPlusWechatServiceImplPayCallbackTest.java | 2 +- .../admin/api/vo/StudentUserExcelVO.java | 18 ++++-- .../admin/controller/SysFileController.java | 3 +- .../admin/controller/SysUserController.java | 4 +- .../impl/SysUserImportExportServiceImpl.java | 12 +++- .../resources/file/student_user_import.xlsx | Bin 13322 -> 13932 bytes .../main/resources/file/wallet_recharge.xlsx | Bin 9818 -> 9830 bytes .../main/resources/mapper/SysUserMapper.xml | 24 +++++++ .../api/constant/WalletTransactionTag.java | 34 ++++++++++ .../wallet/api/constant/WalletTypeEnum.java | 4 +- .../api/dto/WalletBalanceTransactionDto.java | 5 ++ .../wallet/api/dto/WalletTransactionDto.java | 5 ++ .../dto/recharge/WalletRechargeImportDto.java | 5 ++ .../excel/WalletRechargeExcelDto.java | 15 +++++ .../api/entity/WalletTransactionEntity.java | 8 ++- .../recharge/WalletRechargeImportEntity.java | 8 ++- .../wallet/config/ExcelDictConfiguration.java | 36 +++++++++++ .../WalletTransactionController.java | 2 +- .../mapper/WalletTransactionMapper.java | 24 ++++++- .../service/WalletTransactionService.java | 22 +++++++ .../impl/WalletTransactionServiceImpl.java | 36 ++++++++++- .../WalletRechargeApplyServiceImpl.java | 60 +++++++++++++++--- .../WalletRechargeImportServiceImpl.java | 4 +- .../mapper/WalletTransactionMapper.xml | 18 +++++- .../recharge/WalletRechargeImportMapper.xml | 11 +++- 33 files changed, 418 insertions(+), 47 deletions(-) create mode 100644 db/20260813_add_wallet_transaction_tags.sql create mode 100644 pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/constant/WalletTransactionTag.java create mode 100644 pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/config/ExcelDictConfiguration.java diff --git a/db/20260813_add_wallet_transaction_tags.sql b/db/20260813_add_wallet_transaction_tags.sql new file mode 100644 index 00000000..cbe85615 --- /dev/null +++ b/db/20260813_add_wallet_transaction_tags.sql @@ -0,0 +1,6 @@ +-- 为充值导入记录及最终钱包流水补充财务统计标签;历史数据保持为空。 +ALTER TABLE wallet_recharge_import + ADD COLUMN tags varchar(512) DEFAULT NULL COMMENT '财务统计标签,多个wallet_transaction_tag字典值使用英文逗号分隔' AFTER price; + +ALTER TABLE wallet_transaction + ADD COLUMN tags varchar(512) DEFAULT NULL COMMENT '财务统计标签,多个wallet_transaction_tag字典值使用英文逗号分隔' AFTER balance; diff --git a/db/800pjcloudx_wallet.sql b/db/800pjcloudx_wallet.sql index 42efd830..c4583ce2 100644 --- a/db/800pjcloudx_wallet.sql +++ b/db/800pjcloudx_wallet.sql @@ -455,6 +455,7 @@ CREATE TABLE wallet_transaction title varchar(128) NOT NULL COMMENT '流水标题', price int NOT NULL COMMENT '交易金额, 单位分', balance int NOT NULL COMMENT '余额, 单位分', + tags varchar(512) DEFAULT NULL COMMENT '财务统计标签,多个wallet_transaction_tag字典值使用英文逗号分隔', create_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人', create_time datetime DEFAULT NULL COMMENT '创建时间', update_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '修改人', @@ -536,6 +537,7 @@ CREATE TABLE wallet_recharge_import apply_id bigint NOT NULL COMMENT '申请id', before_price int DEFAULT NULL COMMENT '导入前的金额', price int NOT NULL COMMENT '交易金额, 单位分', + tags varchar(512) DEFAULT NULL COMMENT '财务统计标签,多个wallet_transaction_tag字典值使用英文逗号分隔', create_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人', create_time datetime DEFAULT NULL COMMENT '创建时间', update_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '修改人', diff --git a/pjcloud-common/pjcloud-common-excel/src/main/java/com/bsd/pjcloud/common/excel/annotation/ExcelDict.java b/pjcloud-common/pjcloud-common-excel/src/main/java/com/bsd/pjcloud/common/excel/annotation/ExcelDict.java index 2b88ff1f..828ceb59 100644 --- a/pjcloud-common/pjcloud-common-excel/src/main/java/com/bsd/pjcloud/common/excel/annotation/ExcelDict.java +++ b/pjcloud-common/pjcloud-common-excel/src/main/java/com/bsd/pjcloud/common/excel/annotation/ExcelDict.java @@ -9,6 +9,7 @@ import java.lang.annotation.Target; /** * Excel 字典字段。 *

导入时校验单元格内容是否为字典标签,导出模板时将同一字典标签写入下拉选项。

+ *

多选字段在普通 Excel 中使用英文逗号分隔多个标签;原生下拉仅负责提供选项,无法自动追加多次选择。

*/ @Documented @Target(ElementType.FIELD) @@ -20,4 +21,11 @@ public @interface ExcelDict { */ String value(); + /** + * 是否允许一个单元格填写多个字典标签。 + * + * @return {@code true} 时按英文逗号拆分并逐项校验,{@code false} 时整个单元格只能是一个字典标签 + */ + boolean multiple() default false; + } diff --git a/pjcloud-common/pjcloud-common-excel/src/main/java/com/bsd/pjcloud/common/excel/annotation/ExcelTemplate.java b/pjcloud-common/pjcloud-common-excel/src/main/java/com/bsd/pjcloud/common/excel/annotation/ExcelTemplate.java index b295cf39..1dc04717 100644 --- a/pjcloud-common/pjcloud-common-excel/src/main/java/com/bsd/pjcloud/common/excel/annotation/ExcelTemplate.java +++ b/pjcloud-common/pjcloud-common-excel/src/main/java/com/bsd/pjcloud/common/excel/annotation/ExcelTemplate.java @@ -8,11 +8,18 @@ import java.lang.annotation.Target; /** * Excel 模板增强。 - *

切面自动收集 {@link RequestExcel} 导入参数中的模型,下载接口无需感知文件名或具体业务模型。

+ *

切面默认自动收集当前服务 {@link RequestExcel} 导入参数中的模型;跨服务模型可通过注解参数显式补充。

*/ @Documented @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface ExcelTemplate { + /** + * 当前下载接口需要额外处理的 Excel 模型,用于补充当前服务无法自动扫描到的跨服务导入模型。 + * + * @return 需要参与模板字典下拉增强的模型类型;默认不额外补充模型 + */ + Class[] value() default {}; + } diff --git a/pjcloud-common/pjcloud-common-excel/src/main/java/com/bsd/pjcloud/common/excel/aop/ExcelTemplateAspect.java b/pjcloud-common/pjcloud-common-excel/src/main/java/com/bsd/pjcloud/common/excel/aop/ExcelTemplateAspect.java index 9ba53d64..6918a987 100644 --- a/pjcloud-common/pjcloud-common-excel/src/main/java/com/bsd/pjcloud/common/excel/aop/ExcelTemplateAspect.java +++ b/pjcloud-common/pjcloud-common-excel/src/main/java/com/bsd/pjcloud/common/excel/aop/ExcelTemplateAspect.java @@ -63,7 +63,7 @@ public class ExcelTemplateAspect { Object result = joinPoint.proceed(wrappedArgs); wrapper.flushBuffer(); byte[] content = wrapper.getContentAsByteArray(); - byte[] enhancedContent = enhance(content, getModelClasses()); + byte[] enhancedContent = enhance(content, resolveModelClasses(excelTemplate)); response.setContentLength(enhancedContent.length); response.getOutputStream().write(enhancedContent); response.getOutputStream().flush(); @@ -72,6 +72,18 @@ public class ExcelTemplateAspect { throw new IllegalStateException("@ExcelTemplate 方法必须包含 HttpServletResponse 参数"); } + /** + * 合并注解显式模型与当前服务自动扫描模型,保证跨服务模板可增强且保留原有自动发现能力。 + * + * @param excelTemplate 当前下载方法的模板增强注解 + * @return 去重后的模板模型集合 + */ + private Class[] resolveModelClasses(ExcelTemplate excelTemplate) { + return java.util.stream.Stream.concat(Arrays.stream(excelTemplate.value()), Arrays.stream(getModelClasses())) + .distinct() + .toArray(Class[]::new); + } + private boolean isExcelTemplateRequest(Object[] args) { for (Object arg : args) { if (arg instanceof String value) { @@ -85,7 +97,7 @@ public class ExcelTemplateAspect { } /** - * 导入接口的 {@code @RequestExcel List} 是模板模型的唯一来源,新增导入模型无需再修改下载接口或注册表。 + * 自动收集当前服务导入接口中的 {@code @RequestExcel List} 模型,供未显式注册的同服务模板继续使用。 */ private Class[] getModelClasses() { Class[] cachedModelClasses = modelClasses; @@ -162,7 +174,7 @@ public class ExcelTemplateAspect { HeaderCell headerCell = findHeaderCell(sheet, headerName); if (headerCell != null) { ExcelDictDataValidationWriter.write(sheet, headerCell.columnIndex(), headerCell.rowIndex() + 1, - excelDict.value()); + excelDict.value(), excelDict.multiple()); enhanced = true; } } diff --git a/pjcloud-common/pjcloud-common-excel/src/main/java/com/bsd/pjcloud/common/excel/dict/ExcelDictDataValidationWriter.java b/pjcloud-common/pjcloud-common-excel/src/main/java/com/bsd/pjcloud/common/excel/dict/ExcelDictDataValidationWriter.java index f0837dce..a9b73fb6 100644 --- a/pjcloud-common/pjcloud-common-excel/src/main/java/com/bsd/pjcloud/common/excel/dict/ExcelDictDataValidationWriter.java +++ b/pjcloud-common/pjcloud-common-excel/src/main/java/com/bsd/pjcloud/common/excel/dict/ExcelDictDataValidationWriter.java @@ -31,9 +31,15 @@ public final class ExcelDictDataValidationWriter { } /** - * 将字典标签写入隐藏页,并为目标列创建引用式下拉。 + * 将字典标签写入隐藏页,并为目标列创建引用式下拉;多选模式允许按英文逗号手工组合多个选项。 + * + * @param dataSheet 数据页 + * @param columnIndex 字典字段所在列下标 + * @param firstDataRowIndex 首行数据的下标 + * @param dictType 字典类型 + * @param multiple 是否允许一个单元格包含多个字典标签 */ - public static void write(Sheet dataSheet, int columnIndex, int firstDataRowIndex, String dictType) { + public static void write(Sheet dataSheet, int columnIndex, int firstDataRowIndex, String dictType, boolean multiple) { List labels = ExcelDictHelper.getLabels(dictType); if (labels.isEmpty()) { throw new IllegalStateException("Excel 字典未配置或没有可用项: " + dictType); @@ -41,7 +47,7 @@ public final class ExcelDictDataValidationWriter { Workbook workbook = dataSheet.getWorkbook(); String formulaName = writeDictColumn(workbook, dictType, labels); removeColumnValidations(dataSheet, columnIndex); - addValidation(dataSheet, columnIndex, firstDataRowIndex, formulaName); + addValidation(dataSheet, columnIndex, firstDataRowIndex, formulaName, multiple); } /** @@ -123,15 +129,30 @@ public final class ExcelDictDataValidationWriter { return false; } - private static void addValidation(Sheet sheet, int columnIndex, int firstDataRowIndex, String formulaName) { + /** + * 为目标列添加字典下拉。多选时关闭 Excel 原生错误拦截,否则逗号组合值会被单选列表拒绝。 + * + * @param sheet 数据页 + * @param columnIndex 字典字段所在列下标 + * @param firstDataRowIndex 首行数据的下标 + * @param formulaName 隐藏字典区域的名称 + * @param multiple 是否允许按英文逗号组合多个标签 + */ + private static void addValidation(Sheet sheet, int columnIndex, int firstDataRowIndex, String formulaName, boolean multiple) { DataValidationHelper helper = sheet.getDataValidationHelper(); DataValidationConstraint constraint = helper.createFormulaListConstraint(formulaName); CellRangeAddressList range = new CellRangeAddressList(firstDataRowIndex, sheet.getWorkbook().getSpreadsheetVersion().getLastRowIndex(), columnIndex, columnIndex); DataValidation validation = helper.createValidation(constraint, range); validation.setEmptyCellAllowed(true); - validation.setShowErrorBox(true); - validation.createErrorBox("填写错误", "请选择下拉中的有效字典项"); + validation.setShowErrorBox(!multiple); + if (multiple) { + validation.setShowPromptBox(true); + validation.createPromptBox("填写说明", "可填写多个选项,请使用英文逗号分隔"); + } + else { + validation.createErrorBox("填写错误", "请选择下拉中的有效字典项"); + } sheet.addValidationData(validation); } diff --git a/pjcloud-common/pjcloud-common-excel/src/main/java/com/bsd/pjcloud/common/excel/handler/DefaultAnalysisEventListener.java b/pjcloud-common/pjcloud-common-excel/src/main/java/com/bsd/pjcloud/common/excel/handler/DefaultAnalysisEventListener.java index ade9e13d..4bd9519b 100644 --- a/pjcloud-common/pjcloud-common-excel/src/main/java/com/bsd/pjcloud/common/excel/handler/DefaultAnalysisEventListener.java +++ b/pjcloud-common/pjcloud-common-excel/src/main/java/com/bsd/pjcloud/common/excel/handler/DefaultAnalysisEventListener.java @@ -12,6 +12,7 @@ import org.springframework.util.StringUtils; import jakarta.validation.ConstraintViolation; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; @@ -67,7 +68,10 @@ public class DefaultAnalysisEventListener extends ListAnalysisEventListener validateExcelDict(Object data) { Set messages = new LinkedHashSet<>(); @@ -82,14 +86,24 @@ public class DefaultAnalysisEventListener extends ListAnalysisEventListener labels = dictLabelCache.computeIfAbsent(excelDict.value(), ExcelDictHelper::getLabels); String fieldName = getExcelFieldName(field); if (labels.isEmpty()) { messages.add(fieldName + "字典未配置或没有可用项"); } - else if (!labels.contains(label)) { - messages.add(fieldName + ":" + label + ",不在可选项中"); + else { + List selectedLabels = excelDict.multiple() + ? Arrays.stream(fieldText.split(",", -1)).map(String::trim).toList() + : List.of(fieldText); + if (selectedLabels.stream().anyMatch(label -> !StringUtils.hasText(label))) { + messages.add(fieldName + "包含空选项,请使用英文逗号正确分隔"); + continue; + } + List invalidLabels = selectedLabels.stream().filter(label -> !labels.contains(label)).distinct().toList(); + if (!invalidLabels.isEmpty()) { + messages.add(fieldName + ":" + String.join(",", invalidLabels) + ",不在可选项中"); + } } } catch (IllegalAccessException exception) { diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-biz/pom.xml b/pjcloud-thirdparty/pjcloud-thirdparty-biz/pom.xml index 8778e507..11ab4640 100644 --- a/pjcloud-thirdparty/pjcloud-thirdparty-biz/pom.xml +++ b/pjcloud-thirdparty/pjcloud-thirdparty-biz/pom.xml @@ -146,6 +146,13 @@ spring-boot-starter-test test + + + org.mockito + mockito-core + 5.11.0 + test + com.bsd diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/test/java/com/bsd/pjcloud/thirdparty/service/impl/appplus/ThirdAppPlusWechatServiceImplPayCallbackTest.java b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/test/java/com/bsd/pjcloud/thirdparty/service/impl/appplus/ThirdAppPlusWechatServiceImplPayCallbackTest.java index 4692cfbc..a436cf11 100644 --- a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/test/java/com/bsd/pjcloud/thirdparty/service/impl/appplus/ThirdAppPlusWechatServiceImplPayCallbackTest.java +++ b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/test/java/com/bsd/pjcloud/thirdparty/service/impl/appplus/ThirdAppPlusWechatServiceImplPayCallbackTest.java @@ -19,7 +19,7 @@ import com.wechat.pay.java.core.notification.NotificationParser; import com.wechat.pay.java.core.notification.RequestParam; import com.wechat.pay.java.service.partnerpayments.app.AppServiceExtension; import com.wechat.pay.java.service.partnerpayments.app.model.Transaction; -import com.wechat.pay.java.service.partnerpayments.app.model.TransactionAmount; +import com.wechat.pay.java.service.partnerpayments.model.TransactionAmount; import com.wechat.pay.java.service.refund.RefundService; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; diff --git a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/vo/StudentUserExcelVO.java b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/vo/StudentUserExcelVO.java index f9c428ae..3fcd3fa3 100644 --- a/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/vo/StudentUserExcelVO.java +++ b/pjcloud-upms/pjcloud-upms-api/src/main/java/com/bsd/pjcloud/admin/api/vo/StudentUserExcelVO.java @@ -43,11 +43,6 @@ public class StudentUserExcelVO { */ private Long guardianUserId; - /** - * 监护人部门id - */ - private Long guardianDeptId; - /** * 学号 */ @@ -55,6 +50,19 @@ public class StudentUserExcelVO { @ExcelProperty("学号") private String studentNo; + /** + * 学生所属部门名称或路径,必须匹配当前租户已有部门。 + */ + @NotBlank(message = "学生部门") + @ExcelProperty("学生部门") + private String studentDeptName; + + /** + * 同步校验阶段解析出的学生部门 ID,仅供异步写入使用,不直接读取 Excel。 + */ + @ExcelIgnore + private Long studentDeptId; + /** * 学校名称 */ diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/SysFileController.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/SysFileController.java index 8279a215..79075bee 100644 --- a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/SysFileController.java +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/SysFileController.java @@ -31,6 +31,7 @@ import com.bsd.pjcloud.common.excel.annotation.ExcelTemplate; import com.bsd.pjcloud.common.log.annotation.SysLog; import com.bsd.pjcloud.common.security.annotation.HasPermission; import com.bsd.pjcloud.common.security.annotation.Inner; +import com.bsd.pjcloud.wallet.api.dto.recharge.excel.WalletRechargeExcelDto; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; @@ -152,7 +153,7 @@ public class SysFileController { * @param response 本地文件 */ @SneakyThrows - @ExcelTemplate + @ExcelTemplate(WalletRechargeExcelDto.class) @GetMapping("/local/file/{fileName}") public void localFile(@PathVariable String fileName, HttpServletResponse response) { ClassPathResource resource = new ClassPathResource("file/" + fileName); diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/SysUserController.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/SysUserController.java index fd105598..68070e18 100644 --- a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/SysUserController.java +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/controller/SysUserController.java @@ -421,7 +421,7 @@ public class SysUserController { * @return 校验失败时包含对应行号和错误原因;校验通过时包含异步任务 ID 和初始进度 */ @PostMapping("/import") - @HasPermission("sys_user_export") + @HasPermission("sys_user_import") public R importUser(@RequestExcel List excelVOList, BindingResult bindingResult) { return userImportExportService.importUser(excelVOList, bindingResult); } @@ -479,7 +479,7 @@ public class SysUserController { * @return 校验失败时包含校验或图片处理错误;校验通过时包含异步任务 ID 和初始进度 */ @PostMapping("/import-face") - @HasPermission("sys_user_export") + @HasPermission("sys_user_import") @Idempotent(expireTime = 5, key = "'/user/import-face:' + #file.getSize() + ':' + #excelList.hashCode() + ':' + T(com.bsd.pjcloud.common.security.util.SecurityUtils).getUser().getId()", info = "正在导入中,请勿重复操作") public R importUserFace(@RequestParam("file") MultipartFile file, @RequestExcel List excelList, BindingResult bindingResult) { return userImportExportService.importUserFace(file, excelList, bindingResult); diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/SysUserImportExportServiceImpl.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/SysUserImportExportServiceImpl.java index 02dafddd..0b3123d5 100644 --- a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/SysUserImportExportServiceImpl.java +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/SysUserImportExportServiceImpl.java @@ -254,10 +254,13 @@ public class SysUserImportExportServiceImpl implements SysUserImportExportServic excel.setUsername(StrUtil.trim(excel.getUsername())); excel.setGuardianPhone(StrUtil.trim(excel.getGuardianPhone())); excel.setStudentNo(StrUtil.trim(excel.getStudentNo())); + excel.setStudentDeptName(StrUtil.trim(excel.getStudentDeptName())); excel.setSchoolName(StrUtil.trim(excel.getSchoolName())); excel.setClassName(StrUtil.trim(excel.getClassName())); }); + DepartmentIndex departmentIndex = new DepartmentIndex(sysDeptService.list()); + List guardianPhones = studentUserExcelList.stream().map(StudentUserExcelVO::getGuardianPhone) .filter(StrUtil::isNotBlank).distinct().toList(); Map guardianUserMap = guardianPhones.isEmpty() ? Map.of() : sysUserService.list( @@ -324,9 +327,12 @@ public class SysUserImportExportServiceImpl implements SysUserImportExportServic errorMessages.add("监护人手机号:" + excel.getGuardianPhone() + ",对应的用户未添加或未审批通过"); } else { excel.setGuardianUserId(guardian.getUserId()); - excel.setGuardianDeptId(guardian.getDeptId()); } } + SysDept studentDepartment = resolveDepartment(excel.getStudentDeptName(), departmentIndex, errorMessages); + if (studentDepartment != null) { + excel.setStudentDeptId(studentDepartment.getDeptId()); + } if (CollUtil.isNotEmpty(errorMessages)) { errorMessageList.add(new ErrorMessage(excel.getLineNum(), errorMessages)); } @@ -740,7 +746,7 @@ public class SysUserImportExportServiceImpl implements SysUserImportExportServic } /** - * 创建学生用户及监护关系,学生扩展信息只属于 STUDENT 身份。 + * 创建学生用户及监护关系,学生扩展信息只属于 STUDENT 身份,用户部门使用模板中已校验的学生部门。 * * @param excel 当前校验通过的学生行 * @param guardianWardRelationTypeId 监护关系类型 ID @@ -757,7 +763,7 @@ public class SysUserImportExportServiceImpl implements SysUserImportExportServic relationUser.setStaffingType(UserStaffingTypeEnum.NONE_STAFFING.getType()); relationUser.setIdentityTypes(List.of(UserIdentityTypeEnum.STUDENT.getType())); relationUser.setRole(studentRoleIds); - relationUser.setDeptId(excel.getGuardianDeptId()); + relationUser.setDeptId(excel.getStudentDeptId()); SysUserStudentDto studentInfo = new SysUserStudentDto(); studentInfo.setStudentNo(excel.getStudentNo()); studentInfo.setSchoolName(excel.getSchoolName()); diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/resources/file/student_user_import.xlsx b/pjcloud-upms/pjcloud-upms-biz/src/main/resources/file/student_user_import.xlsx index 284f54b7451bea42d18a8c6d806e80d411119582..320b93893d0a78732b50103e2a1528afa69f69c9 100644 GIT binary patch delta 8727 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 diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/resources/file/wallet_recharge.xlsx b/pjcloud-upms/pjcloud-upms-biz/src/main/resources/file/wallet_recharge.xlsx index 3d4d1cd2eb8d1584abb28a9e39b66c18096c2a67..d9a72455912d719c7ffc2e124d805f2475d13bf9 100644 GIT binary patch delta 5053 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 delta 5033 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℞7mqu|uWENaNRdy4jVd5XF%)}olVs#*2}yBD2%@obKevfOU&h;RJp_|4@=|L-@o%Q7(=d2$4WtX#`B;IyFY{^N0KF48#j<~y`U7SlNi zjqHzgx=&KSE|;I7zf%(`f6M?T@G`Ga^v2&w|2_z)m0!#bJi3e|DSj3g$M7u9QTo>r zx?c?v!+mtasK(}fcU%|`QD~Y+s1=CHzJhAHcca*!P>jBpG$-Om5sWsD**3dN7n%ts_7F8+?u1Ol;?lxh3N zEzB8Y^ElWz`=rJiljnOI>>)vtEtkJ`vr)CA@})>NffZxmM@ekRm6VxGpS{9Nk@vfc zs&BO~@1na_fr4sm-BV|)24?1=p`2k|XOrw^=E@l+`?o)^ASCecPu(tS#i{!eGUJsKbd%}i#S_} zli#H?g8`YBL(3FI*;0X8qd={|gqwab-F^i0DYxrf{fx+lT+2j%5%eysCiwZQ`$n)% z4<=sZYP+n;2m_BCc}vG!WEw)_apn$XkE+YKll}(h9}<`d*GlAVCvtt^%x3S+WB(5} zU7V)#M~|J&V{mVjfGZ=&JUA`kJp>2*kVgFyuT+{LJ@yQMNrs0M5ik_HlECh{&4S*=iEvVGCKR1*fla-5& z9g>XM4P&xcvJE1R4M)*0$t4<9TNk-&Mor$+3!o6Mm-hpfa{N1Zay1Q;XNwyj;C@LETmQ!l-&} zW{TE=@!{f-_l`2k&mJxL-gt~%EcOGy8zgn@N~avyvl+bcy+#_FH2~dhrgC2yk4392<5yivgg(uz_6a>F9wt0?Aa z8W~puD?^7P^_P#4p^>VsN4_i10W%o(AeG9M@Nk^FFCM~j1o7xiRrww7u)+%EMa#|e z6Pg~|`6H8b42h`DH AND u.staffing_type = #{query.staffingType} + + + AND EXISTS ( + SELECT 1 + FROM sys_user_identity user_identity + WHERE user_identity.user_id = u.user_id + AND user_identity.identity_type IN + + #{identityType} + + ) + and urole.role_id IN @@ -307,6 +319,18 @@ AND u.dept_id = #{query.deptId} + + + AND EXISTS ( + SELECT 1 + FROM sys_user_identity user_identity + WHERE user_identity.user_id = u.user_id + AND user_identity.identity_type IN + + #{identityType} + + ) + and urole.role_id IN diff --git a/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/constant/WalletTransactionTag.java b/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/constant/WalletTransactionTag.java new file mode 100644 index 00000000..0eb4aeef --- /dev/null +++ b/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/constant/WalletTransactionTag.java @@ -0,0 +1,34 @@ +package com.bsd.pjcloud.wallet.api.constant; + +import cn.hutool.core.util.ObjectUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 充值流水tag + */ +@Getter +@AllArgsConstructor +public enum WalletTransactionTag { + + BJZ_CZ("1", "不记账充值"), + ; + + private final String code; + + private final String desc; + + public static WalletTransactionTag valueOfByCode(String code) { + if (ObjectUtil.isEmpty(code)) return null; + return Arrays.stream(values()).filter(v -> ObjectUtil.equals(code, v.getCode())).findFirst().orElse(null); + } + + public static WalletTransactionTag descOf(String description) { + return Arrays.stream(WalletTransactionTag.values()) + .filter(v -> ObjectUtil.equal(v.getDesc(), description)) + .findFirst().orElse(null); + } + +} diff --git a/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/constant/WalletTypeEnum.java b/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/constant/WalletTypeEnum.java index e71c525b..7630e505 100644 --- a/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/constant/WalletTypeEnum.java +++ b/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/constant/WalletTypeEnum.java @@ -23,12 +23,12 @@ public enum WalletTypeEnum { public static WalletTypeEnum valueOfByCode(String code) { if (ObjectUtil.isEmpty(code)) return null; - return Arrays.stream(values()).filter(v -> ObjectUtil.equals(code, v.getCode())).findFirst().get(); + return Arrays.stream(values()).filter(v -> ObjectUtil.equals(code, v.getCode())).findFirst().orElse(null); } public static WalletTypeEnum descOf(String description) { return Arrays.stream(WalletTypeEnum.values()) .filter(v -> ObjectUtil.equal(v.getDesc(), description)) - .findFirst().get(); + .findFirst().orElse(null); } } diff --git a/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/dto/WalletBalanceTransactionDto.java b/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/dto/WalletBalanceTransactionDto.java index 2e7d0e0f..5faf255e 100644 --- a/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/dto/WalletBalanceTransactionDto.java +++ b/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/dto/WalletBalanceTransactionDto.java @@ -32,4 +32,9 @@ public class WalletBalanceTransactionDto { @NotNull(message = "是否暴力消费") private Boolean force = false; + /** + * 财务统计标签字典值,多个值使用英文逗号分隔;未传时不为流水设置标签。 + */ + private String tags; + } diff --git a/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/dto/WalletTransactionDto.java b/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/dto/WalletTransactionDto.java index 3fdf245f..4a98183d 100644 --- a/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/dto/WalletTransactionDto.java +++ b/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/dto/WalletTransactionDto.java @@ -39,6 +39,11 @@ public class WalletTransactionDto extends WalletTransactionEntity implements Bas private List bizTypes; + /** + * 财务统计标签筛选值;传入多个字典值时匹配包含任一标签的流水。 + */ + private List tagList; + private LocalDate[] createTimeList; /** diff --git a/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/dto/recharge/WalletRechargeImportDto.java b/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/dto/recharge/WalletRechargeImportDto.java index 0220b420..32b451d6 100644 --- a/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/dto/recharge/WalletRechargeImportDto.java +++ b/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/dto/recharge/WalletRechargeImportDto.java @@ -18,6 +18,11 @@ public class WalletRechargeImportDto extends WalletRechargeImportEntity implemen private List userUniqueIds; + /** + * 财务统计标签筛选值;传入多个字典值时匹配包含任一标签的导入记录。 + */ + private List tagList; + private Long userDeptId; diff --git a/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/dto/recharge/excel/WalletRechargeExcelDto.java b/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/dto/recharge/excel/WalletRechargeExcelDto.java index 6697c9df..577256eb 100644 --- a/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/dto/recharge/excel/WalletRechargeExcelDto.java +++ b/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/dto/recharge/excel/WalletRechargeExcelDto.java @@ -6,6 +6,7 @@ import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ContentRowHeight; import com.alibaba.excel.annotation.write.style.HeadRowHeight; +import com.bsd.pjcloud.common.excel.annotation.ExcelDict; import com.bsd.pjcloud.common.excel.annotation.ExcelLine; import lombok.AllArgsConstructor; import lombok.Builder; @@ -42,6 +43,20 @@ public class WalletRechargeExcelDto { @ExcelProperty("操作金额") private String price; + /** + * Excel 中展示和填写的财务标签名称;支持使用英文逗号分隔多个 {@code wallet_transaction_tag} 字典标签。 + */ + @ColumnWidth(100) + @ExcelProperty("操作标签") + @ExcelDict(value = "wallet_transaction_tag", multiple = true) + private String tag; + + /** + * 导入校验后解析出的财务标签字典值,多个值使用英文逗号分隔,不直接读取 Excel。 + */ + @ExcelIgnore + private String tags; + // 操作余额 private Integer priceNumber; diff --git a/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/entity/WalletTransactionEntity.java b/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/entity/WalletTransactionEntity.java index 55d771e3..7e0529e8 100644 --- a/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/entity/WalletTransactionEntity.java +++ b/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/entity/WalletTransactionEntity.java @@ -78,6 +78,12 @@ public class WalletTransactionEntity extends Model { @Schema(description = "余额, 单位分") private Integer balance; + /** + * 财务统计标签,保存 {@code wallet_transaction_tag} 字典值;多个值使用英文逗号分隔,历史流水可为空。 + */ + @Schema(description = "财务统计标签,多个字典值使用英文逗号分隔") + private String tags; + /** * 创建人 */ @@ -119,4 +125,4 @@ public class WalletTransactionEntity extends Model { */ @Schema(description = "租户ID") private Long tenantId; -} \ No newline at end of file +} diff --git a/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/entity/recharge/WalletRechargeImportEntity.java b/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/entity/recharge/WalletRechargeImportEntity.java index fc35e52f..d006d8dd 100644 --- a/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/entity/recharge/WalletRechargeImportEntity.java +++ b/pjcloud-wallet/pjcloud-wallet-api/src/main/java/com/bsd/pjcloud/wallet/api/entity/recharge/WalletRechargeImportEntity.java @@ -67,6 +67,12 @@ public class WalletRechargeImportEntity extends Model { + R> result = remoteDictService.getDictByType(dictType); + if (result == null || !result.isOk() || result.getData() == null) { + return Collections.emptyList(); + } + return result.getData().stream().map(SysDictItem::getLabel).toList(); + }; + } + +} diff --git a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/controller/WalletTransactionController.java b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/controller/WalletTransactionController.java index d9498856..e69a7a85 100644 --- a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/controller/WalletTransactionController.java +++ b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/controller/WalletTransactionController.java @@ -56,7 +56,7 @@ public class WalletTransactionController { @Inner @PostMapping("/add-balance") public R addWalletBalance(@Valid @RequestBody WalletBalanceTransactionDto dto) { - WalletTransactionEntity walletTransaction = walletTransactionService.addWalletBalance(dto.getWalletId(), dto.getPrice(), dto.getBizId(), dto.getBizType()); + WalletTransactionEntity walletTransaction = walletTransactionService.addWalletBalance(dto.getWalletId(), dto.getPrice(), dto.getBizId(), dto.getBizType(), dto.getTags()); if (ObjectUtil.isEmpty(walletTransaction)) return R.failed("增加钱包余额错误"); return R.ok(walletTransaction); } diff --git a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/mapper/WalletTransactionMapper.java b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/mapper/WalletTransactionMapper.java index 24e1d0a8..225e311f 100644 --- a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/mapper/WalletTransactionMapper.java +++ b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/mapper/WalletTransactionMapper.java @@ -61,6 +61,20 @@ public interface WalletTransactionMapper extends PjcloudBaseMapper { + boolean first = true; + for (String tag : dto.getTagList()) { + if (first) { + nested.apply("FIND_IN_SET({0}, tags) > 0", tag); + first = false; + } + else { + nested.or().apply("FIND_IN_SET({0}, tags) > 0", tag); + } + } + }); + } return wrapper; } @@ -98,5 +112,11 @@ public interface WalletTransactionMapper extends PjcloudBaseMapper sumAndCount(@Param("dto") WalletTransactionSumAndCountDto dto); - List exportCzTotalPerson(); -} \ No newline at end of file + /** + * 查询固定金额范围内的个人充值统计明细,并按财务标签筛选。 + * + * @param dto 充值统计筛选条件;标签多选时匹配包含任一标签的流水 + * @return 个人充值统计导出明细 + */ + List exportCzTotalPerson(@Param("dto") WalletTransactionDto dto); +} diff --git a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/WalletTransactionService.java b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/WalletTransactionService.java index 3f654347..7d3eeb85 100644 --- a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/WalletTransactionService.java +++ b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/WalletTransactionService.java @@ -69,6 +69,18 @@ public interface WalletTransactionService extends IService list); /** diff --git a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/WalletTransactionServiceImpl.java b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/WalletTransactionServiceImpl.java index 6e1d0128..36cefd52 100644 --- a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/WalletTransactionServiceImpl.java +++ b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/WalletTransactionServiceImpl.java @@ -212,6 +212,22 @@ public class WalletTransactionServiceImpl extends ServiceImpl list = baseMapper.exportCzTotalPerson(); + List list = baseMapper.exportCzTotalPerson(dto); WriteSheet writeSheet = EasyExcel.writerSheet().build(); FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build(); diff --git a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/recharge/WalletRechargeApplyServiceImpl.java b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/recharge/WalletRechargeApplyServiceImpl.java index e4a2f74e..a755fa87 100644 --- a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/recharge/WalletRechargeApplyServiceImpl.java +++ b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/recharge/WalletRechargeApplyServiceImpl.java @@ -12,8 +12,10 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.bsd.pjcloud.admin.api.dto.UserInfo; import com.bsd.pjcloud.admin.api.entity.SysDept; +import com.bsd.pjcloud.admin.api.entity.SysDictItem; import com.bsd.pjcloud.admin.api.entity.SysUser; import com.bsd.pjcloud.admin.api.feign.RemoteDeptService; +import com.bsd.pjcloud.admin.api.feign.RemoteDictService; import com.bsd.pjcloud.admin.api.feign.RemoteUserService; import com.bsd.pjcloud.admin.api.utils.DataUtil; import com.bsd.pjcloud.admin.api.vo.UserVO; @@ -90,6 +92,11 @@ public class WalletRechargeApplyServiceImpl extends ServiceImpl batchSaveList = list.stream().map(v -> WalletRechargeImportEntity.builder().price(v.getPriceNumber()).userId(v.getUserId()).userDeptId(v.getUserDeptId()).build()).toList(); + List batchSaveList = list.stream().map(v -> WalletRechargeImportEntity.builder().price(v.getPriceNumber()).userId(v.getUserId()).userDeptId(v.getUserDeptId()).tags(v.getTags()).build()).toList(); batchSaveList.forEach(v -> v.setApplyId(insertObj.getId())); rechargeImportService.saveBatch(batchSaveList); return R.ok(null, "导入成功"); @@ -349,7 +357,7 @@ public class WalletRechargeApplyServiceImpl extends ServiceImpl batchSaveList = list.stream().map(v -> WalletRechargeImportEntity.builder().price(0).userId(v.getUserId()).userDeptId(v.getUserDeptId()).build()).toList(); + List batchSaveList = list.stream().map(v -> WalletRechargeImportEntity.builder().price(0).userId(v.getUserId()).userDeptId(v.getUserDeptId()).tags(v.getTags()).build()).toList(); batchSaveList.forEach(v -> v.setApplyId(insertObj.getId())); rechargeImportService.saveBatch(batchSaveList); return R.ok(null, "导入成功"); @@ -371,7 +379,7 @@ public class WalletRechargeApplyServiceImpl extends ServiceImpl batchSaveList = list.stream().map(v -> WalletRechargeImportEntity.builder().price(v.getPriceNumber()).userId(v.getUserId()).userDeptId(v.getUserDeptId()).invoiceId(invoice.getId()).build()).toList(); + List batchSaveList = list.stream().map(v -> WalletRechargeImportEntity.builder().price(v.getPriceNumber()).userId(v.getUserId()).userDeptId(v.getUserDeptId()).invoiceId(invoice.getId()).tags(v.getTags()).build()).toList(); rechargeImportService.saveBatch(batchSaveList); return R.ok(null, "导入成功"); } @@ -388,6 +396,7 @@ public class WalletRechargeApplyServiceImpl extends ServiceImpl errorMessageList = (List) bindingResult.getTarget(); + resolveTransactionTagValues(list, errorMessageList); List usernameList = list.stream().map(WalletRechargeExcelDto::getUsername).toList(); List userPoneList = list.stream().map(WalletRechargeExcelDto::getUserMobile).toList(); for (WalletRechargeExcelDto v : list) { @@ -442,6 +451,41 @@ public class WalletRechargeApplyServiceImpl extends ServiceImpl list, List errorMessageList) { + List taggedRows = list.stream().filter(item -> ObjectUtil.isNotEmpty(item.getTag())).toList(); + if (taggedRows.isEmpty()) { + return; + } + R> result = remoteDictService.getDictByType(TRANSACTION_TAG_DICT_TYPE); + if (result == null || !result.isOk() || ObjectUtil.isEmpty(result.getData())) { + taggedRows.forEach(item -> errorMessageList.add(new ErrorMessage(item.getLineNum(), Set.of("操作标签字典查询失败")))); + return; + } + Map valueByLabel = result.getData().stream() + .filter(item -> ObjectUtil.isNotEmpty(item.getLabel()) && ObjectUtil.isNotEmpty(item.getItemValue())) + .collect(java.util.stream.Collectors.toMap(SysDictItem::getLabel, SysDictItem::getItemValue, (first, ignored) -> first)); + for (WalletRechargeExcelDto item : taggedRows) { + List tagValues = Arrays.stream(item.getTag().split(",")) + .map(String::trim) + .distinct() + .map(valueByLabel::get) + .filter(Objects::nonNull) + .toList(); + long selectedTagCount = Arrays.stream(item.getTag().split(",")).map(String::trim).distinct().count(); + if (tagValues.size() != selectedTagCount) { + errorMessageList.add(new ErrorMessage(item.getLineNum(), Set.of("操作标签包含无法映射的字典项"))); + continue; + } + item.setTags(String.join(",", tagValues)); + } + } + /* ************************************* end excel end ************************************* */ @Override @@ -497,7 +541,7 @@ public class WalletRechargeApplyServiceImpl extends ServiceImpl userIds = importList.stream().map(WalletRechargeImportEntity::getUserId).distinct().toList(); @@ -548,7 +592,7 @@ public class WalletRechargeApplyServiceImpl extends ServiceImpl + @@ -22,6 +23,7 @@ a.title, a.price, a.balance, + a.tags, a.create_by, a.create_time, a.update_by, @@ -44,6 +46,13 @@ and a.biz_type = #{dto.bizType} + + and ( + + FIND_IN_SET(#{tag}, a.tags) > 0 + + ) + and a.dept_id = #{dto.deptId} @@ -286,6 +295,13 @@ and t.biz_type in ('1', '2', '3') and t.price in (80000, 160000, 240000) and t.dept_id not in (1875013738914156546, 1910218102049226753, 1910218128624336898, 1942046316044144642) + + and ( + + FIND_IN_SET(#{tag}, t.tags) > 0 + + ) + order by v.mchId, v.deptId @@ -303,4 +319,4 @@ ) - \ No newline at end of file + diff --git a/pjcloud-wallet/pjcloud-wallet-biz/src/main/resources/mapper/recharge/WalletRechargeImportMapper.xml b/pjcloud-wallet/pjcloud-wallet-biz/src/main/resources/mapper/recharge/WalletRechargeImportMapper.xml index 2d7394b3..086f0d75 100644 --- a/pjcloud-wallet/pjcloud-wallet-biz/src/main/resources/mapper/recharge/WalletRechargeImportMapper.xml +++ b/pjcloud-wallet/pjcloud-wallet-biz/src/main/resources/mapper/recharge/WalletRechargeImportMapper.xml @@ -9,6 +9,7 @@ + @@ -24,6 +25,7 @@ a.apply_id, a.before_price, a.price, + a.tags, a.create_by, a.create_time, a.update_by, @@ -71,6 +73,13 @@ and a.create_time between #{dto.createTimeList[0]} and #{dto.createTimeList[1]} + + and ( + + FIND_IN_SET(#{tag}, a.tags) > 0 + + ) + @@ -134,4 +143,4 @@ - \ No newline at end of file +