From df1f45530ecf45edc7d2c4230128df5cce0a7ee4 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 30 Aug 2026 19:42:20 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E5=90=8C=E6=AD=A5=E3=80=91BOOT=20?= =?UTF-8?q?=E5=92=8C=20CLOUD=20=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/query/LambdaQueryWrapperX.java | 2 +- .../framework/web/config/WebProperties.java | 5 +- ...actBpmTaskCandidateDeptLeaderStrategy.java | 17 ++ ...idateStartUserDeptLeaderMultiStrategy.java | 4 +- ...kCandidateStartUserDeptLeaderStrategy.java | 9 +- .../flowable/core/util/FlowableUtils.java | 12 ++ ...eStartUserDeptLeaderMultiStrategyTest.java | 19 +- ...didateStartUserDeptLeaderStrategyTest.java | 19 +- .../flowable/core/util/FlowableUtilsTest.java | 24 +++ .../config/FmsAccountUserServiceImpl.java | 2 +- .../config/FmsAccountUserServiceImplTest.java | 8 + .../config/HrmAttendanceGroupServiceImpl.java | 2 +- .../employee/info/HrmEmployeeServiceImpl.java | 6 +- ...suranceMonthEmployeeRecordServiceImpl.java | 2 +- ...rformanceAssessmentProcessServiceImpl.java | 4 +- .../plan/HrmPerformancePlanServiceImpl.java | 2 +- .../HrmRecruitInterviewServiceImpl.java | 2 +- .../post/HrmRecruitPostServiceImpl.java | 2 +- .../config/HrmSalaryGroupServiceImpl.java | 2 +- .../salary/slip/HrmSalarySlipServiceImpl.java | 2 +- .../HrmAttendanceGroupServiceImplTest.java | 22 +- .../info/HrmEmployeeServiceImplTest.java | 4 + ...nceMonthEmployeeRecordServiceImplTest.java | 8 + ...manceAssessmentProcessServiceImplTest.java | 8 + .../HrmRecruitInterviewServiceImplTest.java | 7 + .../post/HrmRecruitPostServiceImplTest.java | 8 + .../config/HrmSalaryGroupServiceImplTest.java | 10 +- .../slip/HrmSalarySlipServiceImplTest.java | 9 + .../client/impl/PayClientFactoryImpl.java | 1 + .../impl/alipay/AlipayLitePayClient.java | 86 ++++++++ .../impl/alipay/AlipayLitePayClientTest.java | 201 ++++++++++++++++++ .../mail/MailTemplateServiceImplTest.java | 14 ++ 32 files changed, 486 insertions(+), 37 deletions(-) create mode 100644 yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/client/impl/alipay/AlipayLitePayClient.java create mode 100644 yudao-module-pay/yudao-module-pay-server/src/test/java/cn/iocoder/yudao/module/pay/framework/pay/core/client/impl/alipay/AlipayLitePayClientTest.java diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/query/LambdaQueryWrapperX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/query/LambdaQueryWrapperX.java index 6fc5e756f..b1216ef51 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/query/LambdaQueryWrapperX.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/query/LambdaQueryWrapperX.java @@ -173,7 +173,7 @@ public class LambdaQueryWrapperX extends LambdaQueryWrapper { @Override public LambdaQueryWrapperX and(boolean condition, Consumer> consumer) { - super.and(condition,consumer); + super.and(condition, consumer); return this; } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/WebProperties.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/WebProperties.java index 8091e9afa..e16ec2175 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/WebProperties.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/WebProperties.java @@ -17,17 +17,19 @@ import jakarta.validation.constraints.NotNull; public class WebProperties { @NotNull(message = "APP API 不能为空") + @Valid private Api appApi = new Api("/app-api", "**.controller.app.**"); @NotNull(message = "Admin API 不能为空") + @Valid private Api adminApi = new Api("/admin-api", "**.controller.admin.**"); @NotNull(message = "Admin UI 不能为空") + @Valid private Ui adminUi; @Data @AllArgsConstructor @NoArgsConstructor - @Valid public static class Api { /** @@ -53,7 +55,6 @@ public class WebProperties { } @Data - @Valid public static class Ui { /** diff --git a/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/AbstractBpmTaskCandidateDeptLeaderStrategy.java b/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/AbstractBpmTaskCandidateDeptLeaderStrategy.java index 5cd249252..6b7eb5a7b 100644 --- a/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/AbstractBpmTaskCandidateDeptLeaderStrategy.java +++ b/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/AbstractBpmTaskCandidateDeptLeaderStrategy.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.d import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.BpmTaskCandidateStrategy; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; @@ -12,6 +13,7 @@ import jakarta.annotation.Resource; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Set; /** @@ -91,4 +93,19 @@ public abstract class AbstractBpmTaskCandidateDeptLeaderStrategy implements BpmT return deptApi.getDept(startUser.getDeptId()).getCheckedData(); } + /** + * 获取发起人的部门(优先使用流程变量中的发起人编号) + * + * @param startUserId 发起人 Id(流程变量不存在时使用) + * @param processVariables 流程变量 + * @return 发起人的部门 + */ + protected DeptRespDTO getStartUserDept(Long startUserId, Map processVariables) { + Long processStartUserId = FlowableUtils.getProcessInstanceStartUserId(processVariables); + if (processStartUserId != null && processStartUserId > 0) { + startUserId = processStartUserId; + } + return getStartUserDept(startUserId); + } + } diff --git a/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderMultiStrategy.java b/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderMultiStrategy.java index 00da98bd3..efd1675eb 100644 --- a/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderMultiStrategy.java +++ b/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderMultiStrategy.java @@ -49,7 +49,7 @@ public class BpmTaskCandidateStartUserDeptLeaderMultiStrategy extends AbstractBp ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getProcessInstanceId()); Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId()); // 获取发起人的 multi 部门负责人 - DeptRespDTO dept = super.getStartUserDept(startUserId); + DeptRespDTO dept = super.getStartUserDept(startUserId, processInstance.getProcessVariables()); if (dept == null) { return new HashSet<>(); } @@ -60,7 +60,7 @@ public class BpmTaskCandidateStartUserDeptLeaderMultiStrategy extends AbstractBp public Set calculateUsersByActivity(BpmnModel bpmnModel, String activityId, String param, Long startUserId, String processDefinitionId, Map processVariables) { int level = Integer.parseInt(param); // 参数是部门的层级 - DeptRespDTO dept = super.getStartUserDept(startUserId); + DeptRespDTO dept = super.getStartUserDept(startUserId, processVariables); if (dept == null) { return new HashSet<>(); } diff --git a/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderStrategy.java b/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderStrategy.java index 115bb3c39..86a01f975 100644 --- a/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderStrategy.java +++ b/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderStrategy.java @@ -48,19 +48,20 @@ public class BpmTaskCandidateStartUserDeptLeaderStrategy extends AbstractBpmTask ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getProcessInstanceId()); Long startUserId = NumberUtils.parseLong(processInstance.getStartUserId()); // 获取发起人的部门负责人 - return getStartUserDeptLeader(startUserId, param); + return getStartUserDeptLeader(startUserId, param, processInstance.getProcessVariables()); } @Override public Set calculateUsersByActivity(BpmnModel bpmnModel, String activityId, String param, Long startUserId, String processDefinitionId, Map processVariables) { // 获取发起人的部门负责人 - return getStartUserDeptLeader(startUserId, param); + return getStartUserDeptLeader(startUserId, param, processVariables); } - private Set getStartUserDeptLeader(Long startUserId, String param) { + private Set getStartUserDeptLeader(Long startUserId, String param, + Map processVariables) { int level = Integer.parseInt(param); // 参数是部门的层级 - DeptRespDTO dept = super.getStartUserDept(startUserId); + DeptRespDTO dept = super.getStartUserDept(startUserId, processVariables); if (dept == null) { return new HashSet<>(); } diff --git a/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java b/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java index fc21f7054..89b23289e 100644 --- a/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.util; +import cn.hutool.core.convert.Convert; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; @@ -133,6 +134,17 @@ public class FlowableUtils { return (Integer) processVariables.get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS); } + /** + * 获得流程实例的发起用户 ID + * + * @param processVariables 流程实例的 variables + * @return 发起用户 ID + */ + public static Long getProcessInstanceStartUserId(Map processVariables) { + return processVariables == null ? null : Convert.toLong( + processVariables.get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID)); + } + /** * 获得流程实例的审批原因 * diff --git a/yudao-module-bpm/yudao-module-bpm-server/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderMultiStrategyTest.java b/yudao-module-bpm/yudao-module-bpm-server/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderMultiStrategyTest.java index 39ccb9948..ea9a13a45 100644 --- a/yudao-module-bpm/yudao-module-bpm-server/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderMultiStrategyTest.java +++ b/yudao-module-bpm/yudao-module-bpm-server/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderMultiStrategyTest.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.dept; import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants; import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; @@ -13,6 +14,8 @@ import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; +import java.util.HashMap; +import java.util.Map; import java.util.Set; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -42,12 +45,16 @@ public class BpmTaskCandidateStartUserDeptLeaderMultiStrategyTest extends BaseMo String param = "2"; // mock 方法(获得流程发起人) Long startUserId = 1L; + Long processVariableStartUserId = 2L; ProcessInstance processInstance = mock(ProcessInstance.class); DelegateExecution execution = mock(DelegateExecution.class); when(processInstanceService.getProcessInstance(eq(execution.getProcessInstanceId()))).thenReturn(processInstance); when(processInstance.getStartUserId()).thenReturn(startUserId.toString()); + Map processVariables = new HashMap<>(); + processVariables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, processVariableStartUserId); + when(processInstance.getProcessVariables()).thenReturn(processVariables); // mock 方法(获取发起人的 multi 部门负责人) - mockGetStartUserDept(startUserId); + mockGetStartUserDept(processVariableStartUserId); // 调用 Set userIds = strategy.calculateUsersByTask(execution, param); @@ -61,12 +68,14 @@ public class BpmTaskCandidateStartUserDeptLeaderMultiStrategyTest extends BaseMo String param = "2"; // mock 方法 Long startUserId = 1L; - mockGetStartUserDept(startUserId); + Long processVariableStartUserId = 2L; + Map processVariables = new HashMap<>(); + processVariables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, processVariableStartUserId); + mockGetStartUserDept(processVariableStartUserId); - // 调用 Set userIds = strategy.calculateUsersByActivity(null, null, param, - startUserId, null, null); - // 断言 + startUserId, null, processVariables); + assertEquals(Sets.newLinkedHashSet(11L, 1001L), userIds); } diff --git a/yudao-module-bpm/yudao-module-bpm-server/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderStrategyTest.java b/yudao-module-bpm/yudao-module-bpm-server/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderStrategyTest.java index 1c4cad64b..77d79424d 100644 --- a/yudao-module-bpm/yudao-module-bpm-server/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderStrategyTest.java +++ b/yudao-module-bpm/yudao-module-bpm-server/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserDeptLeaderStrategyTest.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.candidate.strategy.dept; import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants; import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; @@ -13,6 +14,8 @@ import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; +import java.util.HashMap; +import java.util.Map; import java.util.Set; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -42,12 +45,16 @@ public class BpmTaskCandidateStartUserDeptLeaderStrategyTest extends BaseMockito String param = "2"; // mock 方法(获得流程发起人) Long startUserId = 1L; + Long processVariableStartUserId = 2L; ProcessInstance processInstance = mock(ProcessInstance.class); DelegateExecution execution = mock(DelegateExecution.class); when(processInstanceService.getProcessInstance(eq(execution.getProcessInstanceId()))).thenReturn(processInstance); when(processInstance.getStartUserId()).thenReturn(startUserId.toString()); + Map processVariables = new HashMap<>(); + processVariables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, processVariableStartUserId); + when(processInstance.getProcessVariables()).thenReturn(processVariables); // mock 方法(获取发起人的部门负责人) - mockGetStartUserDeptLeader(startUserId); + mockGetStartUserDeptLeader(processVariableStartUserId); // 调用 Set userIds = strategy.calculateUsersByTask(execution, param); @@ -61,12 +68,14 @@ public class BpmTaskCandidateStartUserDeptLeaderStrategyTest extends BaseMockito String param = "2"; // mock 方法 Long startUserId = 1L; - mockGetStartUserDeptLeader(startUserId); + Long processVariableStartUserId = 2L; + Map processVariables = new HashMap<>(); + processVariables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, processVariableStartUserId); + mockGetStartUserDeptLeader(processVariableStartUserId); - // 调用 Set userIds = strategy.calculateUsersByActivity(null, null, param, - startUserId, null, null); - // 断言 + startUserId, null, processVariables); + assertEquals(Sets.newLinkedHashSet(1001L), userIds); } diff --git a/yudao-module-bpm/yudao-module-bpm-server/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtilsTest.java b/yudao-module-bpm/yudao-module-bpm-server/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtilsTest.java index e1bebe1b4..67da990a0 100644 --- a/yudao-module-bpm/yudao-module-bpm-server/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtilsTest.java +++ b/yudao-module-bpm/yudao-module-bpm-server/src/test/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtilsTest.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.BpmModelMetaInfoVO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO; import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants; import org.junit.jupiter.api.Test; import java.util.Arrays; @@ -22,6 +23,29 @@ import static org.junit.jupiter.api.Assertions.assertNull; */ class FlowableUtilsTest { + @Test + public void testGetProcessInstanceStartUserId() { + // 准备参数 + Map processVariables = new HashMap<>(); + processVariables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, "1"); + + // 调用 + Long startUserId = FlowableUtils.getProcessInstanceStartUserId(processVariables); + + // 断言 + assertEquals(1L, startUserId); + } + + @Test + public void testGetProcessInstanceStartUserId_empty() { + // 准备参数 + Map processVariables = new HashMap<>(); + + // 调用 & 断言 + assertNull(FlowableUtils.getProcessInstanceStartUserId(processVariables)); + assertNull(FlowableUtils.getProcessInstanceStartUserId(null)); + } + @Test public void testGetSummary_customSummary_parseDbFormFields() { // 准备参数:模拟 DB 中 form_fields 字段,列表里每个元素都是一个 form-create 字段 JSON。 diff --git a/yudao-module-fms/yudao-module-fms-server/src/main/java/cn/iocoder/yudao/module/fms/service/config/FmsAccountUserServiceImpl.java b/yudao-module-fms/yudao-module-fms-server/src/main/java/cn/iocoder/yudao/module/fms/service/config/FmsAccountUserServiceImpl.java index ff242fcf7..0a3c92ac6 100644 --- a/yudao-module-fms/yudao-module-fms-server/src/main/java/cn/iocoder/yudao/module/fms/service/config/FmsAccountUserServiceImpl.java +++ b/yudao-module-fms/yudao-module-fms-server/src/main/java/cn/iocoder/yudao/module/fms/service/config/FmsAccountUserServiceImpl.java @@ -102,7 +102,7 @@ public class FmsAccountUserServiceImpl implements FmsAccountUserService { FmsAccountUserUpdateReqVO.Member::getUserId, FmsAccountUserUpdateReqVO.Member::getLevel); Set memberUserIds = new HashSet<>(memberLevelMap.keySet()); memberUserIds.removeAll(founderUserIds); - adminUserApi.validateUserList(memberUserIds); + adminUserApi.validateUserList(memberUserIds).checkError(); // 2.1 移出取消授权的成员 Set currentMemberUserIds = convertSet(accountUsers, FmsAccountUserDO::getUserId, diff --git a/yudao-module-fms/yudao-module-fms-server/src/test/java/cn/iocoder/yudao/module/fms/service/config/FmsAccountUserServiceImplTest.java b/yudao-module-fms/yudao-module-fms-server/src/test/java/cn/iocoder/yudao/module/fms/service/config/FmsAccountUserServiceImplTest.java index 66144365a..e909abc78 100644 --- a/yudao-module-fms/yudao-module-fms-server/src/test/java/cn/iocoder/yudao/module/fms/service/config/FmsAccountUserServiceImplTest.java +++ b/yudao-module-fms/yudao-module-fms-server/src/test/java/cn/iocoder/yudao/module/fms/service/config/FmsAccountUserServiceImplTest.java @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.fms.dal.mysql.config.FmsAccountUserMapper; import cn.iocoder.yudao.module.fms.enums.config.FmsAccountUserLevelEnum; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import jakarta.annotation.Resource; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; import org.springframework.test.context.bean.override.mockito.MockitoBean; @@ -22,6 +23,8 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static org.mockito.ArgumentMatchers.anyCollection; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -38,6 +41,11 @@ public class FmsAccountUserServiceImplTest extends BaseDbUnitTest { @MockitoBean private AdminUserApi adminUserApi; + @BeforeEach + public void setUp() { + when(adminUserApi.validateUserList(anyCollection())).thenReturn(success(true)); + } + @Test public void testCreateAccountOwner_firstAccountSet() { // 准备参数 diff --git a/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/config/HrmAttendanceGroupServiceImpl.java b/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/config/HrmAttendanceGroupServiceImpl.java index b0fccb6e1..8db70ee5f 100644 --- a/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/config/HrmAttendanceGroupServiceImpl.java +++ b/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/attendance/config/HrmAttendanceGroupServiceImpl.java @@ -312,7 +312,7 @@ public class HrmAttendanceGroupServiceImpl implements HrmAttendanceGroupService private void validateAttendanceGroup(HrmAttendanceGroupSaveReqVO reqVO) { // 1. 校验适用部门存在 - deptApi.validateDeptList(reqVO.getDeptIds()); + deptApi.validateDeptList(reqVO.getDeptIds()).checkError(); // 2. 校验适用员工存在 employeeService.validateEmployeeListExists(reqVO.getEmployeeIds()); } diff --git a/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/info/HrmEmployeeServiceImpl.java b/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/info/HrmEmployeeServiceImpl.java index c0caa68ab..7c2c47a77 100644 --- a/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/info/HrmEmployeeServiceImpl.java +++ b/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/info/HrmEmployeeServiceImpl.java @@ -628,7 +628,7 @@ public class HrmEmployeeServiceImpl implements HrmEmployeeService { throw exception(EMPLOYEE_CREATE_USER_LIST_DUPLICATE); } } - adminUserApi.validateUserList(userIds); + adminUserApi.validateUserList(userIds).checkError(); Map userMap = convertMap( adminUserApi.getUserList(userIds).getCheckedData(), AdminUserRespDTO::getId); // 1.2 构建并校验全部员工档案,避免部分数据校验失败时已经执行写库 @@ -1179,7 +1179,7 @@ public class HrmEmployeeServiceImpl implements HrmEmployeeService { private void validateDeptAndLeader(Long employeeId, Long deptId, Long leaderEmployeeId) { // 1. 校验部门是否存在 if (deptId != null) { - deptApi.validateDeptList(Collections.singleton(deptId)); + deptApi.validateDeptList(Collections.singleton(deptId)).checkError(); } // 2. 校验直属上级链路不存在自引用或环路 if (leaderEmployeeId == null) { @@ -1417,7 +1417,7 @@ public class HrmEmployeeServiceImpl implements HrmEmployeeService { try { notifyMessageSendApi.sendSingleMessageToAdmin(new NotifySendSingleToUserReqDTO() .setUserId(employee.getUserId()).setTemplateCode(templateCode) - .setTemplateParams(Collections.singletonMap("employeeName", employee.getName()))); + .setTemplateParams(Collections.singletonMap("employeeName", employee.getName()))).checkError(); return true; } catch (RuntimeException ex) { log.warn("[sendEmployeeMessage][employeeId({}) userId({}) templateCode({}) 发送失败]", diff --git a/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/insurance/monthrecord/HrmInsuranceMonthEmployeeRecordServiceImpl.java b/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/insurance/monthrecord/HrmInsuranceMonthEmployeeRecordServiceImpl.java index e00530fa6..5ca2a2f5b 100644 --- a/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/insurance/monthrecord/HrmInsuranceMonthEmployeeRecordServiceImpl.java +++ b/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/insurance/monthrecord/HrmInsuranceMonthEmployeeRecordServiceImpl.java @@ -536,7 +536,7 @@ public class HrmInsuranceMonthEmployeeRecordServiceImpl implements HrmInsuranceM notifyMessageSendApi.sendSingleMessageToAdmin(new NotifySendSingleToUserReqDTO() .setUserId(employee.getUserId()) .setTemplateCode(MessageTemplateConstants.INSURANCE_MONTH_RECORD_CREATED) - .setTemplateParams(templateParams)); + .setTemplateParams(templateParams)).checkError(); } } diff --git a/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/performance/assessment/HrmPerformanceAssessmentProcessServiceImpl.java b/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/performance/assessment/HrmPerformanceAssessmentProcessServiceImpl.java index f7c916625..df9c398ed 100644 --- a/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/performance/assessment/HrmPerformanceAssessmentProcessServiceImpl.java +++ b/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/performance/assessment/HrmPerformanceAssessmentProcessServiceImpl.java @@ -350,7 +350,7 @@ public class HrmPerformanceAssessmentProcessServiceImpl notifyMessageSendApi.sendSingleMessageToAdmin(new NotifySendSingleToUserReqDTO() .setUserId(handler.getUserId()) .setTemplateCode(MessageTemplateConstants.PERFORMANCE_TASK_PENDING) - .setTemplateParams(templateParams)); + .setTemplateParams(templateParams)).checkError(); } @Override @@ -386,7 +386,7 @@ public class HrmPerformanceAssessmentProcessServiceImpl notifyMessageSendApi.sendSingleMessageToAdmin(new NotifySendSingleToUserReqDTO() .setUserId(employee.getUserId()) .setTemplateCode(MessageTemplateConstants.PERFORMANCE_PROCESS_RESULT) - .setTemplateParams(templateParams)); + .setTemplateParams(templateParams)).checkError(); } } diff --git a/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/performance/plan/HrmPerformancePlanServiceImpl.java b/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/performance/plan/HrmPerformancePlanServiceImpl.java index 7bb36dd1c..38825e4a4 100644 --- a/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/performance/plan/HrmPerformancePlanServiceImpl.java +++ b/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/performance/plan/HrmPerformancePlanServiceImpl.java @@ -555,7 +555,7 @@ public class HrmPerformancePlanServiceImpl implements HrmPerformancePlanService employeeService.validateEmployeeListExists(employeeIds); } if (CollUtil.isNotEmpty(deptIds)) { - deptApi.validateDeptList(deptIds); + deptApi.validateDeptList(deptIds).checkError(); } } diff --git a/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/recruit/candidate/HrmRecruitInterviewServiceImpl.java b/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/recruit/candidate/HrmRecruitInterviewServiceImpl.java index 3112172a9..39b03195d 100644 --- a/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/recruit/candidate/HrmRecruitInterviewServiceImpl.java +++ b/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/recruit/candidate/HrmRecruitInterviewServiceImpl.java @@ -351,7 +351,7 @@ public class HrmRecruitInterviewServiceImpl implements HrmRecruitInterviewServic templateParams.put("interviewTime", INTERVIEW_TIME_FORMATTER.format(recruitInterview.getInterviewTime())); userIds.forEach(userId -> notifyMessageSendApi.sendSingleMessageToAdmin(new NotifySendSingleToUserReqDTO() .setUserId(userId).setTemplateCode(MessageTemplateConstants.RECRUIT_INTERVIEW_ARRANGED) - .setTemplateParams(templateParams))); + .setTemplateParams(templateParams)).checkError()); } } diff --git a/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/recruit/post/HrmRecruitPostServiceImpl.java b/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/recruit/post/HrmRecruitPostServiceImpl.java index 49723ae65..08b4a8a8a 100644 --- a/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/recruit/post/HrmRecruitPostServiceImpl.java +++ b/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/recruit/post/HrmRecruitPostServiceImpl.java @@ -146,7 +146,7 @@ public class HrmRecruitPostServiceImpl implements HrmRecruitPostService { // 1. 校验职位类型和用人部门存在 recruitPostTypeService.validateRecruitPostTypeExists(reqVO.getPostTypeId()); if (reqVO.getDeptId() != null) { - deptApi.validateDeptList(Collections.singleton(reqVO.getDeptId())); + deptApi.validateDeptList(Collections.singleton(reqVO.getDeptId())).checkError(); } // 2. 校验招聘负责人和面试官存在 diff --git a/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/config/HrmSalaryGroupServiceImpl.java b/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/config/HrmSalaryGroupServiceImpl.java index ed5c77f9f..293c856cc 100644 --- a/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/config/HrmSalaryGroupServiceImpl.java +++ b/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/config/HrmSalaryGroupServiceImpl.java @@ -221,7 +221,7 @@ public class HrmSalaryGroupServiceImpl implements HrmSalaryGroupService { // 1. 校验适用部门及其上下级部门未归属其他薪资组 Set selectedDeptIds = CollUtil.isEmpty(deptIds) ? Collections.emptySet() : new HashSet<>(deptIds); - deptApi.validateDeptList(selectedDeptIds); + deptApi.validateDeptList(selectedDeptIds).checkError(); List otherSalaryGroups = convertList(salaryGroupMapper.selectListByIdDesc(), salaryGroup -> salaryGroup, salaryGroup -> ObjUtil.notEqual(salaryGroup.getId(), id)); if (CollUtil.isNotEmpty(selectedDeptIds)) { diff --git a/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/slip/HrmSalarySlipServiceImpl.java b/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/slip/HrmSalarySlipServiceImpl.java index 3b4bcef18..7379c89ec 100644 --- a/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/slip/HrmSalarySlipServiceImpl.java +++ b/yudao-module-hrm/yudao-module-hrm-server/src/main/java/cn/iocoder/yudao/module/hrm/service/salary/slip/HrmSalarySlipServiceImpl.java @@ -256,7 +256,7 @@ public class HrmSalarySlipServiceImpl implements HrmSalarySlipService { templateParams.put("realSalary", employeeRecord.getRealPaySalary().toPlainString()); notifyMessageSendApi.sendSingleMessageToAdmin(new NotifySendSingleToUserReqDTO() .setUserId(employee.getUserId()).setTemplateCode(MessageTemplateConstants.SALARY_SLIP_SENT) - .setTemplateParams(templateParams)); + .setTemplateParams(templateParams)).checkError(); } } diff --git a/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/attendance/config/HrmAttendanceGroupServiceImplTest.java b/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/attendance/config/HrmAttendanceGroupServiceImplTest.java index ae5857d48..e85cdb165 100644 --- a/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/attendance/config/HrmAttendanceGroupServiceImplTest.java +++ b/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/attendance/config/HrmAttendanceGroupServiceImplTest.java @@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.hrm.enums.attendance.config.HrmAttendanceMisscard import cn.iocoder.yudao.module.hrm.service.employee.info.HrmEmployeeService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; @@ -22,13 +23,23 @@ import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; -import java.util.*; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyCollection; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; /** * {@link HrmAttendanceGroupServiceImpl} 的单元测试类 @@ -49,6 +60,11 @@ public class HrmAttendanceGroupServiceImplTest extends BaseMockitoUnitTest { @Mock private DeptApi deptApi; + @BeforeEach + public void setUp() { + lenient().when(deptApi.validateDeptList(anyCollection())).thenReturn(success(true)); + } + @Test public void testGetAttendanceGroupMap_employeeAndDeptAndDefaultGroup() { // mock 数据 diff --git a/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/employee/info/HrmEmployeeServiceImplTest.java b/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/employee/info/HrmEmployeeServiceImplTest.java index 1023baedc..8cfaa3119 100644 --- a/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/employee/info/HrmEmployeeServiceImplTest.java +++ b/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/employee/info/HrmEmployeeServiceImplTest.java @@ -68,6 +68,7 @@ import static java.util.Arrays.asList; import static java.util.Collections.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyCollection; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.*; @@ -128,6 +129,9 @@ public class HrmEmployeeServiceImplTest extends BaseDbUnitTest { HrmEmployeeChangeRecordCreateReqVO reqVO = invocation.getArgument(0); return BeanUtils.toBean(reqVO, HrmEmployeeChangeRecordDO.class).setId(randomLongId()); }); + lenient().when(deptApi.validateDeptList(anyCollection())).thenReturn(success(true)); + lenient().when(adminUserApi.validateUserList(anyCollection())).thenReturn(success(true)); + lenient().when(notifyMessageSendApi.sendSingleMessageToAdmin(any())).thenReturn(success(randomLongId())); } @Test diff --git a/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/insurance/monthrecord/HrmInsuranceMonthEmployeeRecordServiceImplTest.java b/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/insurance/monthrecord/HrmInsuranceMonthEmployeeRecordServiceImplTest.java index 566516bb2..0217add8c 100644 --- a/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/insurance/monthrecord/HrmInsuranceMonthEmployeeRecordServiceImplTest.java +++ b/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/insurance/monthrecord/HrmInsuranceMonthEmployeeRecordServiceImplTest.java @@ -25,6 +25,7 @@ import cn.iocoder.yudao.module.hrm.service.insurance.config.HrmInsuranceSchemeSe import cn.iocoder.yudao.module.hrm.service.insurance.employee.HrmInsuranceEmployeeInfoService; import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi; import jakarta.annotation.Resource; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; import org.springframework.test.context.bean.override.mockito.MockitoBean; @@ -37,6 +38,8 @@ import java.util.List; import java.util.Map; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.INSURANCE_EMPLOYEE_SCHEME_NOT_CONFIGURED; import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.INSURANCE_MONTH_EMPLOYEE_NOT_ELIGIBLE; @@ -73,6 +76,11 @@ public class HrmInsuranceMonthEmployeeRecordServiceImplTest extends BaseDbUnitTe @MockitoBean private NotifyMessageSendApi notifyMessageSendApi; + @BeforeEach + public void setUp() { + when(notifyMessageSendApi.sendSingleMessageToAdmin(any())).thenReturn(success(randomLongId())); + } + @Test public void testCreateMonthEmployeeRecordList_success() { // mock 数据 diff --git a/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/performance/assessment/HrmPerformanceAssessmentProcessServiceImplTest.java b/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/performance/assessment/HrmPerformanceAssessmentProcessServiceImplTest.java index 4c7be8590..757f04df1 100644 --- a/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/performance/assessment/HrmPerformanceAssessmentProcessServiceImplTest.java +++ b/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/performance/assessment/HrmPerformanceAssessmentProcessServiceImplTest.java @@ -43,6 +43,7 @@ import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi; import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO; import jakarta.annotation.Resource; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.springframework.context.annotation.Import; @@ -57,6 +58,7 @@ import java.util.List; import java.util.Map; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.PERFORMANCE_STAGE_NO_PERMISSION; @@ -70,6 +72,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -111,6 +114,11 @@ public class HrmPerformanceAssessmentProcessServiceImplTest extends BaseDbUnitTe @MockitoBean private HrmPerformanceAssessmentActionRecordService assessmentActionRecordService; + @BeforeEach + public void setUp() { + lenient().when(notifyMessageSendApi.sendSingleMessageToAdmin(any())).thenReturn(success(randomLongId())); + } + @Test public void testInitializeAssessmentStages_unboundEmployee_fail() { // mock 数据 diff --git a/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/recruit/candidate/HrmRecruitInterviewServiceImplTest.java b/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/recruit/candidate/HrmRecruitInterviewServiceImplTest.java index 4c6dde445..b01cb5d9d 100644 --- a/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/recruit/candidate/HrmRecruitInterviewServiceImplTest.java +++ b/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/recruit/candidate/HrmRecruitInterviewServiceImplTest.java @@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.hrm.service.employee.info.HrmEmployeeService; import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi; import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO; import jakarta.annotation.Resource; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.springframework.context.annotation.Import; @@ -27,6 +28,7 @@ import java.util.Map; import java.util.function.Consumer; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; @@ -68,6 +70,11 @@ public class HrmRecruitInterviewServiceImplTest extends BaseDbUnitTest { @MockitoBean private NotifyMessageSendApi notifyMessageSendApi; + @BeforeEach + public void setUp() { + when(notifyMessageSendApi.sendSingleMessageToAdmin(any())).thenReturn(success(randomLongId())); + } + @Test public void testCreateRecruitInterview_success() { // mock 数据 diff --git a/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/recruit/post/HrmRecruitPostServiceImplTest.java b/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/recruit/post/HrmRecruitPostServiceImplTest.java index 57fa81d7a..2e5434774 100644 --- a/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/recruit/post/HrmRecruitPostServiceImplTest.java +++ b/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/recruit/post/HrmRecruitPostServiceImplTest.java @@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.hrm.enums.recruit.post.HrmRecruitPostStatusEnum; import cn.iocoder.yudao.module.hrm.service.employee.info.HrmEmployeeService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import jakarta.annotation.Resource; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; import org.springframework.test.context.bean.override.mockito.MockitoBean; @@ -25,6 +26,7 @@ import java.util.Map; import java.util.function.Consumer; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.getDateTimeRange; @@ -44,6 +46,7 @@ import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.anyCollection; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.when; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; @@ -68,6 +71,11 @@ public class HrmRecruitPostServiceImplTest extends BaseDbUnitTest { @MockitoBean private DeptApi deptApi; + @BeforeEach + public void setUp() { + when(deptApi.validateDeptList(anyCollection())).thenReturn(success(true)); + } + @Test public void testCreateRecruitPost_success() { // 准备参数 diff --git a/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/salary/config/HrmSalaryGroupServiceImplTest.java b/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/salary/config/HrmSalaryGroupServiceImplTest.java index baee80420..a0c99e176 100644 --- a/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/salary/config/HrmSalaryGroupServiceImplTest.java +++ b/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/salary/config/HrmSalaryGroupServiceImplTest.java @@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.hrm.service.employee.info.HrmEmployeeService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import jakarta.annotation.Resource; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; import org.springframework.test.context.bean.override.mockito.MockitoBean; @@ -32,10 +33,10 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.*; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.when; import static org.mockito.ArgumentMatchers.anyCollection; import static org.mockito.ArgumentMatchers.argThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.when; /** * {@link HrmSalaryGroupServiceImpl} 的单元测试类 @@ -58,6 +59,11 @@ public class HrmSalaryGroupServiceImplTest extends BaseDbUnitTest { @MockitoBean private DeptApi deptApi; + @BeforeEach + public void setUp() { + when(deptApi.validateDeptList(anyCollection())).thenReturn(success(true)); + } + @Test public void testCreateSalaryGroup_success() { // 准备参数 diff --git a/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/salary/slip/HrmSalarySlipServiceImplTest.java b/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/salary/slip/HrmSalarySlipServiceImplTest.java index ef7c37ef6..7fe94e628 100644 --- a/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/salary/slip/HrmSalarySlipServiceImplTest.java +++ b/yudao-module-hrm/yudao-module-hrm-server/src/test/java/cn/iocoder/yudao/module/hrm/service/salary/slip/HrmSalarySlipServiceImplTest.java @@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi; import cn.iocoder.yudao.module.hrm.enums.salary.slip.HrmSalarySlipReadStatusEnum; import cn.iocoder.yudao.module.hrm.enums.salary.slip.HrmSalarySlipTemplateOptionTypeEnum; import jakarta.annotation.Resource; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; import org.springframework.test.context.bean.override.mockito.MockitoBean; @@ -27,6 +28,7 @@ import java.util.Map; import java.util.Set; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.SALARY_SLIP_ALREADY_SENT; import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.SALARY_SLIP_NOT_EXISTS; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -37,6 +39,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; /** * {@link HrmSalarySlipServiceImpl} 的单元测试类 @@ -56,6 +59,12 @@ public class HrmSalarySlipServiceImplTest extends BaseDbUnitTest { @MockitoBean private NotifyMessageSendApi notifyMessageSendApi; + @BeforeEach + public void setUp() { + when(notifyMessageSendApi.sendSingleMessageToAdmin(org.mockito.ArgumentMatchers.any())) + .thenReturn(success(randomLongId())); + } + @Test public void testCreateSalarySlipList_success() { // mock 数据 diff --git a/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/client/impl/PayClientFactoryImpl.java b/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/client/impl/PayClientFactoryImpl.java index 6b907cdeb..89b87ffe4 100644 --- a/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/client/impl/PayClientFactoryImpl.java +++ b/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/client/impl/PayClientFactoryImpl.java @@ -54,6 +54,7 @@ public class PayClientFactoryImpl implements PayClientFactory { clientClass.put(ALIPAY_APP, AlipayAppPayClient.class); clientClass.put(ALIPAY_PC, AlipayPcPayClient.class); clientClass.put(ALIPAY_BAR, AlipayBarPayClient.class); + clientClass.put(ALIPAY_LITE, AlipayLitePayClient.class); // 钱包支付客户端 clientClass.put(WALLET, WalletPayClient.class); // Mock 支付客户端 diff --git a/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/client/impl/alipay/AlipayLitePayClient.java b/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/client/impl/alipay/AlipayLitePayClient.java new file mode 100644 index 000000000..5a112f01c --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-server/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/client/impl/alipay/AlipayLitePayClient.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.pay.framework.pay.core.client.impl.alipay; + +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.pay.enums.PayChannelEnum; +import cn.iocoder.yudao.module.pay.framework.pay.core.client.dto.order.PayOrderRespDTO; +import cn.iocoder.yudao.module.pay.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; +import cn.iocoder.yudao.module.pay.framework.pay.core.enums.PayOrderDisplayModeEnum; +import com.alipay.api.AlipayApiException; +import com.alipay.api.domain.AlipayTradeCreateModel; +import com.alipay.api.request.AlipayTradeCreateRequest; +import com.alipay.api.response.AlipayTradeCreateResponse; + +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException; +import static cn.iocoder.yudao.module.pay.framework.pay.core.client.impl.alipay.AlipayPayClientConfig.MODE_CERTIFICATE; + +/** + * 支付宝【小程序】的 PayClient 实现类 + * + * 文档:统一收单交易创建 + * + * @author graypxl + */ +public class AlipayLitePayClient extends AbstractAlipayPayClient { + + public static final String BUYER_ID_KEY = "buyer_id"; + public static final String BUYER_OPEN_ID_KEY = "buyer_open_id"; + + public AlipayLitePayClient(Long channelId, AlipayPayClientConfig config) { + super(channelId, PayChannelEnum.ALIPAY_LITE.getCode(), config); + } + + @Override + public PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException { + AlipayTradeCreateModel model = new AlipayTradeCreateModel(); + model.setOutTradeNo(reqDTO.getOutTradeNo()); + model.setSubject(reqDTO.getSubject()); + model.setBody(reqDTO.getBody()); + model.setTotalAmount(formatAmount(reqDTO.getPrice())); + model.setTimeExpire(formatTime(reqDTO.getExpireTime())); + model.setProductCode("JSAPI_PAY"); + model.setOpAppId(config.getAppId()); + applyBuyerIdentity(model, reqDTO); + + AlipayTradeCreateRequest request = new AlipayTradeCreateRequest(); + request.setBizModel(model); + request.setNotifyUrl(reqDTO.getNotifyUrl()); + + AlipayTradeCreateResponse response; + if (Objects.equals(config.getMode(), MODE_CERTIFICATE)) { + response = client.certificateExecute(request); + } else { + response = client.execute(request); + } + if (!response.isSuccess()) { + return buildClosedPayOrderRespDTO(reqDTO, response); + } + return PayOrderRespDTO.waitingOf(PayOrderDisplayModeEnum.APP.getMode(), response.getTradeNo(), + reqDTO.getOutTradeNo(), response); + } + + static void applyBuyerIdentity(AlipayTradeCreateModel model, PayOrderUnifiedReqDTO reqDTO) { + String buyerId = MapUtil.getStr(reqDTO.getChannelExtras(), BUYER_ID_KEY); + String buyerOpenId = MapUtil.getStr(reqDTO.getChannelExtras(), BUYER_OPEN_ID_KEY); + if (StrUtil.isBlank(buyerOpenId)) { + buyerOpenId = MapUtil.getStr(reqDTO.getChannelExtras(), "openid"); + } + if (isAlipayUserId(buyerId)) { + model.setBuyerId(buyerId); + } else if (StrUtil.isNotBlank(buyerOpenId)) { + model.setBuyerOpenId(buyerOpenId); + } else if (StrUtil.isNotBlank(buyerId)) { + model.setBuyerOpenId(buyerId); + } else { + throw invalidParamException("支付请求的 buyer_open_id 不能为空!"); + } + } + + static boolean isAlipayUserId(String value) { + return StrUtil.isNotBlank(value) && value.startsWith("2088") && value.length() <= 28 + && StrUtil.isNumeric(value); + } + +} diff --git a/yudao-module-pay/yudao-module-pay-server/src/test/java/cn/iocoder/yudao/module/pay/framework/pay/core/client/impl/alipay/AlipayLitePayClientTest.java b/yudao-module-pay/yudao-module-pay-server/src/test/java/cn/iocoder/yudao/module/pay/framework/pay/core/client/impl/alipay/AlipayLitePayClientTest.java new file mode 100644 index 000000000..4150d6b0d --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-server/src/test/java/cn/iocoder/yudao/module/pay/framework/pay/core/client/impl/alipay/AlipayLitePayClientTest.java @@ -0,0 +1,201 @@ +package cn.iocoder.yudao.module.pay.framework.pay.core.client.impl.alipay; + +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; +import cn.iocoder.yudao.module.pay.framework.pay.core.client.dto.order.PayOrderRespDTO; +import cn.iocoder.yudao.module.pay.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; +import cn.iocoder.yudao.module.pay.framework.pay.core.enums.PayOrderDisplayModeEnum; +import cn.iocoder.yudao.module.pay.framework.pay.core.client.exception.PayClientException; +import com.alipay.api.AlipayApiException; +import com.alipay.api.domain.AlipayTradeCreateModel; +import com.alipay.api.request.AlipayTradeCreateRequest; +import com.alipay.api.response.AlipayTradeCreateResponse; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentMatcher; +import org.mockito.InjectMocks; + +import java.util.HashMap; +import java.util.Map; + +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum.CLOSED; +import static cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum.WAITING; +import static cn.iocoder.yudao.module.pay.framework.pay.core.client.impl.alipay.AlipayPayClientConfig.MODE_CERTIFICATE; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.when; + +/** + * {@link AlipayLitePayClient} 单元测试 + * + * @author graypxl + */ +public class AlipayLitePayClientTest extends AbstractAlipayClientTest { + + @InjectMocks + private AlipayLitePayClient client = new AlipayLitePayClient(randomLongId(), config); + + @Override + @BeforeEach + public void setUp() { + setClient(client); + } + + @Test + @DisplayName("支付宝小程序支付:buyer_open_id 下单成功") + public void testUnifiedOrder_buyerOpenId() throws AlipayApiException { + String buyerOpenId = "060d4dhFytu7VF5haNiDacG7b-n5toPeevhdLa07Kz9ass8"; + String tradeNo = randomString(); + AlipayTradeCreateResponse response = randomPojo(AlipayTradeCreateResponse.class, o -> { + o.setSubCode(""); + o.setTradeNo(tradeNo); + }); + when(defaultAlipayClient.execute(argThat(assertRequest(config.getAppId(), null, buyerOpenId)))) + .thenReturn(response); + PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(randomURL(), randomString(), randomInteger()); + reqDTO.setChannelExtras(Map.of(AlipayLitePayClient.BUYER_OPEN_ID_KEY, buyerOpenId)); + + PayOrderRespDTO resp = client.unifiedOrder(reqDTO); + + assertEquals(WAITING.getStatus(), resp.getStatus()); + assertEquals(reqDTO.getOutTradeNo(), resp.getOutTradeNo()); + assertNull(resp.getChannelOrderNo()); + assertNull(resp.getChannelUserId()); + assertNull(resp.getSuccessTime()); + assertEquals(PayOrderDisplayModeEnum.APP.getMode(), resp.getDisplayMode()); + assertEquals(tradeNo, resp.getDisplayContent()); + assertSame(response, resp.getRawData()); + assertNull(resp.getChannelErrorCode()); + assertNull(resp.getChannelErrorMsg()); + } + + @Test + @DisplayName("支付宝小程序支付:buyer_id 下单成功") + public void testUnifiedOrder_buyerId() throws AlipayApiException { + String buyerId = "2088123456789012"; + AlipayTradeCreateResponse response = randomPojo(AlipayTradeCreateResponse.class, o -> o.setSubCode("")); + when(defaultAlipayClient.execute(argThat(assertRequest(config.getAppId(), buyerId, null)))) + .thenReturn(response); + PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(randomURL(), randomString(), randomInteger()); + reqDTO.setChannelExtras(Map.of(AlipayLitePayClient.BUYER_ID_KEY, buyerId)); + + PayOrderRespDTO resp = client.unifiedOrder(reqDTO); + + assertEquals(WAITING.getStatus(), resp.getStatus()); + assertEquals(reqDTO.getOutTradeNo(), resp.getOutTradeNo()); + assertEquals(PayOrderDisplayModeEnum.APP.getMode(), resp.getDisplayMode()); + assertSame(response, resp.getRawData()); + } + + @Test + @DisplayName("支付宝小程序支付:兼容 openid 参数") + public void testUnifiedOrder_openidAlias() throws AlipayApiException { + String buyerOpenId = randomString(); + AlipayTradeCreateResponse response = randomPojo(AlipayTradeCreateResponse.class, o -> o.setSubCode("")); + when(defaultAlipayClient.execute(argThat(assertRequest(config.getAppId(), null, buyerOpenId)))) + .thenReturn(response); + PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(randomURL(), randomString(), randomInteger()); + reqDTO.setChannelExtras(Map.of("openid", buyerOpenId)); + + PayOrderRespDTO resp = client.unifiedOrder(reqDTO); + + assertEquals(WAITING.getStatus(), resp.getStatus()); + assertEquals(reqDTO.getOutTradeNo(), resp.getOutTradeNo()); + assertEquals(PayOrderDisplayModeEnum.APP.getMode(), resp.getDisplayMode()); + assertSame(response, resp.getRawData()); + } + + @Test + @DisplayName("支付宝小程序支付:证书模式下单成功") + public void testUnifiedOrder_certificateMode() throws AlipayApiException { + config.setMode(MODE_CERTIFICATE); + String buyerOpenId = randomString(); + AlipayTradeCreateResponse response = randomPojo(AlipayTradeCreateResponse.class, o -> o.setSubCode("")); + when(defaultAlipayClient.certificateExecute(argThat(assertRequest(config.getAppId(), null, buyerOpenId)))) + .thenReturn(response); + PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(randomURL(), randomString(), randomInteger()); + reqDTO.setChannelExtras(Map.of(AlipayLitePayClient.BUYER_OPEN_ID_KEY, buyerOpenId)); + + PayOrderRespDTO resp = client.unifiedOrder(reqDTO); + + assertEquals(WAITING.getStatus(), resp.getStatus()); + assertEquals(reqDTO.getOutTradeNo(), resp.getOutTradeNo()); + assertEquals(PayOrderDisplayModeEnum.APP.getMode(), resp.getDisplayMode()); + assertSame(response, resp.getRawData()); + } + + @Test + @DisplayName("支付宝小程序支付:渠道返回失败") + public void testUnifiedOrder_channelFailed() throws AlipayApiException { + String subCode = randomString(); + String subMsg = randomString(); + AlipayTradeCreateResponse response = randomPojo(AlipayTradeCreateResponse.class, o -> { + o.setSubCode(subCode); + o.setSubMsg(subMsg); + }); + when(defaultAlipayClient.execute(argThat((ArgumentMatcher) request -> true))) + .thenReturn(response); + PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(randomURL(), randomString(), randomInteger()); + reqDTO.setChannelExtras(Map.of(AlipayLitePayClient.BUYER_OPEN_ID_KEY, randomString())); + + PayOrderRespDTO resp = client.unifiedOrder(reqDTO); + + assertEquals(CLOSED.getStatus(), resp.getStatus()); + assertEquals(reqDTO.getOutTradeNo(), resp.getOutTradeNo()); + assertNull(resp.getChannelOrderNo()); + assertNull(resp.getChannelUserId()); + assertNull(resp.getSuccessTime()); + assertNull(resp.getDisplayMode()); + assertNull(resp.getDisplayContent()); + assertSame(response, resp.getRawData()); + assertEquals(subCode, resp.getChannelErrorCode()); + assertEquals(subMsg, resp.getChannelErrorMsg()); + } + + @Test + @DisplayName("支付宝小程序支付:买家标识为空") + public void testUnifiedOrder_buyerEmpty() { + PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(randomURL(), randomString(), randomInteger()); + reqDTO.setChannelExtras(new HashMap<>()); + + assertThrows(ServiceException.class, () -> client.unifiedOrder(reqDTO)); + } + + @Test + @DisplayName("支付宝小程序支付:抛出业务异常") + public void testUnifiedOrder_throwServiceException() throws AlipayApiException { + when(defaultAlipayClient.execute(argThat((ArgumentMatcher) request -> true))) + .thenThrow(ServiceExceptionUtil.exception(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR)); + PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(randomURL(), randomString(), randomInteger()); + reqDTO.setChannelExtras(Map.of(AlipayLitePayClient.BUYER_OPEN_ID_KEY, randomString())); + + assertThrows(ServiceException.class, () -> client.unifiedOrder(reqDTO)); + } + + @Test + @DisplayName("支付宝小程序支付:抛出系统异常") + public void testUnifiedOrder_throwPayException() throws AlipayApiException { + when(defaultAlipayClient.execute(argThat((ArgumentMatcher) request -> true))) + .thenThrow(new RuntimeException("系统异常")); + PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(randomURL(), randomString(), randomInteger()); + reqDTO.setChannelExtras(Map.of(AlipayLitePayClient.BUYER_OPEN_ID_KEY, randomString())); + + assertThrows(PayClientException.class, () -> client.unifiedOrder(reqDTO)); + } + + private static ArgumentMatcher assertRequest(String appId, String buyerId, + String buyerOpenId) { + return request -> { + AlipayTradeCreateModel model = (AlipayTradeCreateModel) request.getBizModel(); + assertEquals("JSAPI_PAY", model.getProductCode()); + assertEquals(appId, model.getOpAppId()); + assertEquals(buyerId, model.getBuyerId()); + assertEquals(buyerOpenId, model.getBuyerOpenId()); + return true; + }; + } + +} diff --git a/yudao-module-system/yudao-module-system-server/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImplTest.java b/yudao-module-system/yudao-module-system-server/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImplTest.java index af0211eda..046a2efea 100755 --- a/yudao-module-system/yudao-module-system-server/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-server/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImplTest.java @@ -398,4 +398,18 @@ public class MailTemplateServiceImplTest extends BaseDbUnitTest { assertFalse(formattedContent.contains("{activationLink}")); } + @Test + public void testFormatMailTemplateContent_dollarInCodeBlock() { + // 准备参数 + Map params = new HashMap<>(); + + // 测试代码块中包含 $ 与 \\(历史上 appendReplacement 会抛 IllegalArgumentException: Illegal group reference) + String content = "
echo $HOME && ls \\root
"; + + // 调用,并断言内容原样保留 + String result = mailTemplateService.formatMailTemplateContent(content, params); + assertTrue(result.contains("echo $HOME && ls \\root")); + assertTrue(result.contains("
")); + } + }