diff --git a/sql/mysql/member_level.sql b/sql/mysql/member_level.sql deleted file mode 100644 index c7a02bbb0..000000000 --- a/sql/mysql/member_level.sql +++ /dev/null @@ -1,98 +0,0 @@ --- 会员表增加字段 -alter table member_user add column experience int not null default 0 comment '经验'; -alter table member_user add column level_id bigint comment '等级编号'; - --- 增加3张表 -create table member_level -( - id bigint auto_increment comment '编号' primary key, - name varchar(30) default '' not null comment '等级名称', - experience int default 0 not null comment '升级经验', - level int default 0 not null comment '等级', - discount_percent tinyint default 100 not null comment '享受折扣', - icon varchar(255) default '' not null comment '等级图标', - background_url varchar(255) default '' not null comment '等级背景图', - status tinyint default 0 not null comment '状态', - creator varchar(64) default '' null comment '创建者', - create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间', - updater varchar(64) default '' null comment '更新者', - update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', - deleted bit default b'0' not null comment '是否删除', - tenant_id bigint default 0 not null comment '租户编号' -) - comment '会员等级'; - -create table member_level_record -( - id bigint auto_increment comment '编号' primary key, - user_id bigint default 0 not null comment '用户编号', - level_id bigint default 0 not null comment '等级编号', - level int default 0 not null comment '会员等级', - discount_percent tinyint default 100 not null comment '享受折扣', - experience int default 0 not null comment '升级经验', - user_experience int default 0 not null comment '会员此时的经验', - remark varchar(255) default '' not null comment '备注', - description varchar(255) default '' not null comment '描述', - creator varchar(64) default '' null comment '创建者', - create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间', - updater varchar(64) default '' null comment '更新者', - update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', - deleted bit default b'0' not null comment '是否删除', - tenant_id bigint default 0 not null comment '租户编号' -) - comment '会员等级记录'; - -create index idx_user_id on member_level_record (user_id) comment '会员等级记录-用户编号'; - -create table member_experience_record -( - id bigint auto_increment comment '编号' primary key, - user_id bigint default 0 not null comment '用户编号', - biz_id varchar(64) default '' not null comment '业务编号', - biz_type tinyint default 0 not null comment '业务类型', - title varchar(30) default '' not null comment '标题', - experience int default 0 not null comment '经验', - total_experience int default 0 not null comment '变更后的经验', - description varchar(512) default '' not null comment '描述', - creator varchar(64) default '' null comment '创建者', - create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间', - updater varchar(64) default '' null comment '更新者', - update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', - deleted bit default b'0' not null comment '是否删除', - tenant_id bigint default 0 not null comment '租户编号' -) - comment '会员经验记录'; - -create index idx_user_id on member_experience_record (user_id) comment '会员经验记录-用户编号'; -create index idx_user_biz_type on member_experience_record (user_id, biz_type) comment '会员经验记录-用户业务类型'; - --- 增加字典 -insert system_dict_type(name, type) values ('会员经验业务类型', 'member_experience_biz_type'); -insert system_dict_data(dict_type, label, value, sort) values ('member_experience_biz_type', '管理员调整', '0', 0); -insert system_dict_data(dict_type, label, value, sort) values ('member_experience_biz_type', '邀新奖励', '1', 1); -insert system_dict_data(dict_type, label, value, sort) values ('member_experience_biz_type', '下单奖励', '2', 2); -insert system_dict_data(dict_type, label, value, sort) values ('member_experience_biz_type', '退单扣除', '3', 3); -insert system_dict_data(dict_type, label, value, sort) values ('member_experience_biz_type', '签到奖励', '4', 4); -insert system_dict_data(dict_type, label, value, sort) values ('member_experience_biz_type', '抽奖奖励', '5', 5); - --- 菜单 SQL -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status, component_name) -VALUES ('会员等级', '', 2, 3, 2262, 'level', '', 'member/level/index', 0, 'MemberLevel'); - --- 按钮父菜单ID --- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 -SELECT @parentId := LAST_INSERT_ID(); - --- 按钮 SQL -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) -VALUES ('会员等级查询', 'member:level:query', 3, 1, @parentId, '', '', '', 0); -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) -VALUES ('会员等级创建', 'member:level:create', 3, 2, @parentId, '', '', '', 0); -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) -VALUES ('会员等级更新', 'member:level:update', 3, 3, @parentId, '', '', '', 0); -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) -VALUES ('会员等级删除', 'member:level:delete', 3, 4, @parentId, '', '', '', 0); - --- 会员用户管理: 增加按钮权限 -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) -VALUES ('用户等级修改', 'member:user:update-level', 3, 5, 2309, '', '', '', 0); \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayBarPayClientTest.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayBarPayClientTest.java new file mode 100644 index 000000000..b6f24e136 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayBarPayClientTest.java @@ -0,0 +1,157 @@ +package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; + +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; +import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; +import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum; +import com.alipay.api.AlipayApiException; +import com.alipay.api.domain.AlipayTradePayModel; +import com.alipay.api.request.AlipayTradePayRequest; +import com.alipay.api.response.AlipayTradePayResponse; +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.Date; +import java.util.HashMap; +import java.util.Map; + +import static cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum.CLOSED; +import static cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum.WAITING; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.when; + +/** + * {@link AlipayBarPayClient} 单元测试 + * + * @author jason + */ +public class AlipayBarPayClientTest extends AbstractAlipayClientTest { + + @InjectMocks + private AlipayBarPayClient client = new AlipayBarPayClient(randomLongId(), config); + + @Override + @BeforeEach + public void setUp() { + setClient(client); + } + + @Test + @DisplayName("支付宝条码支付,非免密码支付下单成功") + public void test_unified_order_success() throws AlipayApiException { + String outTradeNo = randomString(); + String notifyUrl = randomURL(); + Integer price = randomInteger(); + String authCode = randomString(); + // 准备返回对象 + AlipayTradePayResponse response = randomPojo(AlipayTradePayResponse.class, o -> o.setSubCode("")); + + // mock + when(defaultAlipayClient.execute(argThat((ArgumentMatcher) request -> { + assertInstanceOf(AlipayTradePayModel.class, request.getBizModel()); + assertEquals(notifyUrl, request.getNotifyUrl()); + AlipayTradePayModel model = (AlipayTradePayModel) request.getBizModel(); + assertEquals(outTradeNo, model.getOutTradeNo()); + assertEquals(String.valueOf(price / 100.0), model.getTotalAmount()); + assertEquals(authCode, model.getAuthCode()); + return true; + }))).thenReturn(response); + // 准备请求参数 + PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(notifyUrl, outTradeNo, price); + // 设置条码 + Map extraParam = new HashMap<>(); + extraParam.put("auth_code", authCode); + reqDTO.setChannelExtras(extraParam); + // 下单请求 + PayOrderRespDTO resp = client.unifiedOrder(reqDTO); + // 断言 + assertEquals(WAITING.getStatus(), resp.getStatus()); + assertEquals(PayOrderDisplayModeEnum.BAR_CODE.getMode(), resp.getDisplayMode()); + assertEquals(outTradeNo, resp.getOutTradeNo()); + assertEquals("", resp.getDisplayContent()); + assertSame(response, resp.getRawData()); + } + + @Test + @DisplayName("支付宝条码支付,免密码支付下单成功") + public void test_unified_order_code_10000_success() throws AlipayApiException { + String outTradeNo = randomString(); + String channelNo = randomString(); + String channelUserId = randomString(); + Date payTime = randomDate(); + // 准备返回对象 + AlipayTradePayResponse response = randomPojo(AlipayTradePayResponse.class, o -> { + o.setSubCode(""); + o.setCode("10000"); + o.setOutTradeNo(outTradeNo); + o.setTradeNo(channelNo); + o.setBuyerUserId(channelUserId); + o.setGmtPayment(payTime); + }); + // mock + when(defaultAlipayClient.execute(argThat((ArgumentMatcher) request -> true))) + .thenReturn(response); + // 准备请求参数 + String authCode = randomString(); + PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(randomURL(), outTradeNo, randomInteger()); + // 设置条码 + Map extraParam = new HashMap<>(); + extraParam.put("auth_code", authCode); + reqDTO.setChannelExtras(extraParam); + // 下单请求 + PayOrderRespDTO resp = client.unifiedOrder(reqDTO); + // 断言 + assertEquals(PayOrderStatusRespEnum.SUCCESS.getStatus(), resp.getStatus()); + assertEquals(outTradeNo, resp.getOutTradeNo()); + assertEquals(channelNo, resp.getChannelOrderNo()); + assertEquals(channelUserId, resp.getChannelUserId()); + assertEquals(LocalDateTimeUtil.of(payTime), resp.getSuccessTime()); + assertSame(response, resp.getRawData()); + } + + @Test + @DisplayName("支付宝条码支付,没有传条码") + public void test_unified_order_empty_auth_code() { + PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(randomURL(), randomString(), randomInteger()); + // 断言 + assertThrows(ServiceException.class, () -> client.unifiedOrder(reqDTO)); + } + + @Test + @DisplayName("支付宝条码支付,渠道返回失败") + public void test_unified_order_channel_failed() throws AlipayApiException { + // 准备响应对象 + String subCode = randomString(); + String subMsg = randomString(); + AlipayTradePayResponse response = randomPojo(AlipayTradePayResponse.class, o -> { + o.setSubCode(subCode); + o.setSubMsg(subMsg); + }); + // mock + when(defaultAlipayClient.execute(argThat((ArgumentMatcher) request -> true))) + .thenReturn(response); + // 准备请求参数 + String authCode = randomString(); + String outTradeNo = randomString(); + PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(randomURL(), outTradeNo, randomInteger()); + // 设置条码 + Map extraParam = new HashMap<>(); + extraParam.put("auth_code", authCode); + reqDTO.setChannelExtras(extraParam); + // 下单请求 + PayOrderRespDTO resp = client.unifiedOrder(reqDTO); + // 断言 + assertEquals(CLOSED.getStatus(), resp.getStatus()); + assertEquals(subCode, resp.getChannelErrorCode()); + assertEquals(subMsg, resp.getChannelErrorMsg()); + assertSame(response, resp.getRawData()); + + } +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClientTest.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClientTest.java index 3d6b6f46e..9dfa6acc1 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClientTest.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClientTest.java @@ -23,6 +23,8 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; /** + * {@link AlipayPcPayClient} 单元测试 + * * @author jason */ public class AlipayPcPayClientTest extends AbstractAlipayClientTest { @@ -41,15 +43,13 @@ public class AlipayPcPayClientTest extends AbstractAlipayClientTest { public void test_unified_order_url_display_mode_success() throws AlipayApiException { // 准备返回对象 String notifyUrl = randomURL(); - Integer price = randomInteger(); - AlipayTradePagePayResponse response = randomPojo(AlipayTradePagePayResponse.class, o -> { - o.setSubCode(""); - }); + AlipayTradePagePayResponse response = randomPojo(AlipayTradePagePayResponse.class, o -> o.setSubCode("")); // mock when(defaultAlipayClient.pageExecute(argThat((ArgumentMatcher) request -> true), eq(Method.GET.name()))).thenReturn(response); // 准备请求参数 String outTradeNo = randomString(); + Integer price = randomInteger(); PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(notifyUrl, outTradeNo, price); // 设置 displayMode 为 null. reqDTO.setDisplayMode(null); @@ -67,15 +67,13 @@ public class AlipayPcPayClientTest extends AbstractAlipayClientTest { public void test_unified_order_form_display_mode_success() throws AlipayApiException { // 准备返回对象 String notifyUrl = randomURL(); - Integer price = randomInteger(); - AlipayTradePagePayResponse response = randomPojo(AlipayTradePagePayResponse.class, o -> { - o.setSubCode(""); - }); + AlipayTradePagePayResponse response = randomPojo(AlipayTradePagePayResponse.class, o -> o.setSubCode("")); // mock when(defaultAlipayClient.pageExecute(argThat((ArgumentMatcher) request -> true), eq(Method.POST.name()))).thenReturn(response); // 准备请求参数 String outTradeNo = randomString(); + Integer price = randomInteger(); PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(notifyUrl, outTradeNo, price); reqDTO.setDisplayMode(PayOrderDisplayModeEnum.FORM.getMode()); diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApi.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApi.java index b758633c8..2091189a2 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApi.java +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApi.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.member.api.level; import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; /** - * 会员等级 API接口 + * 会员等级 API 接口 * * @author owen */ @@ -17,5 +17,6 @@ public interface MemberLevelApi { * @param bizType 业务类型 {@link MemberExperienceBizTypeEnum} * @param bizId 业务编号 */ - void plusExperience(Long userId, Integer experience, Integer bizType, String bizId); + void addExperience(Long userId, Integer experience, Integer bizType, String bizId); + } diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java index b9df654f2..724ba0c5e 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java @@ -48,8 +48,6 @@ public interface ErrorCodeConstants { ErrorCode LEVEL_EXPERIENCE_MAX = new ErrorCode(1004011004, "升级经验必须小于下一个等级[{}]设置的升级经验[{}]"); ErrorCode LEVEL_HAS_USER = new ErrorCode(1004011005, "用户等级下存在用户,无法删除"); - ErrorCode LEVEL_LOG_NOT_EXISTS = new ErrorCode(1004011100, "用户等级记录不存在"); - ErrorCode EXPERIENCE_LOG_NOT_EXISTS = new ErrorCode(1004011200, "用户经验记录不存在"); ErrorCode EXPERIENCE_BIZ_NOT_SUPPORT = new ErrorCode(1004011201, "用户经验业务类型不支持"); //========== 用户分组 1004012000 ========== diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/MemberExperienceBizTypeEnum.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/MemberExperienceBizTypeEnum.java index 93cb886fb..d8cb54132 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/MemberExperienceBizTypeEnum.java +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/MemberExperienceBizTypeEnum.java @@ -11,18 +11,20 @@ import lombok.Getter; @Getter @AllArgsConstructor public enum MemberExperienceBizTypeEnum { + /** * 管理员调整、邀请新用户、下单、退单、签到、抽奖 */ - ADMIN(0, "管理员调整","管理员调整获得{}经验"), - INVITE_REGISTER(1, "邀新奖励","邀请好友获得{}经验"), - ORDER(2, "下单奖励", "下单获得{}经验"), - REFUND(3, "退单扣除","退单获得{}经验"), - SIGN_IN(4, "签到奖励","签到获得{}经验"), - LOTTERY(5, "抽奖奖励","抽奖获得{}经验"), + ADMIN(0, "管理员调整","管理员调整获得 {} 经验"), + INVITE_REGISTER(1, "邀新奖励","邀请好友获得 {} 经验"), + ORDER(2, "下单奖励", "下单获得 {} 经验"), + REFUND(3, "退单扣除","退单获得 {} 经验"), + SIGN_IN(4, "签到奖励","签到获得 {} 经验"), + LOTTERY(5, "抽奖奖励","抽奖获得 {} 经验"), ; - private final int value; + private final int type; private final String title; - private final String desc; + private final String description; + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApiImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApiImpl.java index c7c7f0d1e..3d89663e7 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApiImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApiImpl.java @@ -24,12 +24,15 @@ public class MemberLevelApiImpl implements MemberLevelApi { @Resource private MemberLevelService memberLevelService; - public void plusExperience(Long userId, Integer experience, Integer bizType, String bizId) { - MemberExperienceBizTypeEnum bizTypeEnum = EnumUtil.getBy(MemberExperienceBizTypeEnum.class, e -> Objects.equals(bizType, e.getValue())); + @Override + public void addExperience(Long userId, Integer experience, Integer bizType, String bizId) { + // TODO @疯狂:可以在 MemberExperienceBizTypeEnum 增加一个方法,获得哈。 + MemberExperienceBizTypeEnum bizTypeEnum = EnumUtil.getBy(MemberExperienceBizTypeEnum.class, + e -> Objects.equals(bizType, e.getType())); if (bizTypeEnum == null) { throw exception(EXPERIENCE_BIZ_NOT_SUPPORT); } - memberLevelService.addExperience(userId, experience, bizTypeEnum, bizId); } + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberExperienceRecordController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberExperienceRecordController.java index be3efc5ba..cdbd76046 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberExperienceRecordController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberExperienceRecordController.java @@ -35,7 +35,7 @@ public class MemberExperienceRecordController { @Operation(summary = "获得会员经验记录") @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('member:experience-record:query')") - public CommonResult getExperienceLog(@RequestParam("id") Long id) { + public CommonResult getExperienceRecord(@RequestParam("id") Long id) { MemberExperienceRecordDO experienceLog = experienceLogService.getExperienceRecord(id); return success(MemberExperienceRecordConvert.INSTANCE.convert(experienceLog)); } @@ -43,7 +43,8 @@ public class MemberExperienceRecordController { @GetMapping("/page") @Operation(summary = "获得会员经验记录分页") @PreAuthorize("@ss.hasPermission('member:experience-record:query')") - public CommonResult> getExperienceLogPage(@Valid MemberExperienceRecordPageReqVO pageVO) { + public CommonResult> getExperienceRecordPage( + @Valid MemberExperienceRecordPageReqVO pageVO) { PageResult pageResult = experienceLogService.getExperienceRecordPage(pageVO); return success(MemberExperienceRecordConvert.INSTANCE.convertPage(pageResult)); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelRecordController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelRecordController.java index 4ee2f1a08..05d133cbd 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelRecordController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelRecordController.java @@ -35,7 +35,7 @@ public class MemberLevelRecordController { @Operation(summary = "获得会员等级记录") @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('member:level-record:query')") - public CommonResult getLevelLog(@RequestParam("id") Long id) { + public CommonResult getLevelRecord(@RequestParam("id") Long id) { MemberLevelRecordDO levelLog = levelLogService.getLevelRecord(id); return success(MemberLevelRecordConvert.INSTANCE.convert(levelLog)); } @@ -43,8 +43,10 @@ public class MemberLevelRecordController { @GetMapping("/page") @Operation(summary = "获得会员等级记录分页") @PreAuthorize("@ss.hasPermission('member:level-record:query')") - public CommonResult> getLevelLogPage(@Valid MemberLevelRecordPageReqVO pageVO) { + public CommonResult> getLevelRecordPage( + @Valid MemberLevelRecordPageReqVO pageVO) { PageResult pageResult = levelLogService.getLevelRecordPage(pageVO); return success(MemberLevelRecordConvert.INSTANCE.convertPage(pageResult)); } + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelListReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelListReqVO.java index 87502b278..348e78e8e 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelListReqVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelListReqVO.java @@ -4,7 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.ToString; -@Schema(description = "管理后台 - 会员等级分页 Request VO") +@Schema(description = "管理后台 - 会员等级列表筛选 Request VO") @Data @ToString(callSuper = true) public class MemberLevelListReqVO { diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/MemberUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/MemberUserController.java index ccb9d5da5..e93aa0fde 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/MemberUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/MemberUserController.java @@ -25,10 +25,14 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Set; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @Tag(name = "管理后台 - 会员用户") @RestController @@ -79,26 +83,19 @@ public class MemberUserController { return success(PageResult.empty()); } - Set groupIds = new HashSet<>(pageResult.getList().size()); - // 处理用户标签返显 Set tagIds = pageResult.getList().stream() - .peek(m -> { - if (m.getGroupId() != null) { - groupIds.add(m.getGroupId()); - } - }) .map(MemberUserDO::getTagIds) .filter(Objects::nonNull) .flatMap(Collection::stream) .collect(Collectors.toSet()); List tags = memberTagService.getTagList(tagIds); - // 处理用户级别返显 - List levels = memberLevelService.getEnableLevelList(); + List levels = memberLevelService.getLevelList( + convertSet(pageResult.getList(), MemberUserDO::getLevelId)); // 处理用户分组返显 - List groups = memberGroupService.getGroupList(groupIds); - + List groups = memberGroupService.getGroupList( + convertSet(pageResult.getList(), MemberUserDO::getGroupId)); return success(MemberUserConvert.INSTANCE.convertPage(pageResult, tags, levels, groups)); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/MemberUserConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/MemberUserConvert.java index 73adc2dfd..21a67103d 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/MemberUserConvert.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/MemberUserConvert.java @@ -42,12 +42,10 @@ public interface MemberUserConvert { List levels, List groups) { PageResult result = convertPage(pageResult); - // 处理关联数据 Map tagMap = convertMap(tags, MemberTagDO::getId, MemberTagDO::getName); Map levelMap = convertMap(levels, MemberLevelDO::getId, MemberLevelDO::getName); Map groupMap = convertMap(groups, MemberGroupDO::getId, MemberGroupDO::getName); - // 填充关联数据 for (MemberUserRespVO vo : result.getList()) { vo.setTagNames(convertList(vo.getTagIds(), tagMap::get)); @@ -56,4 +54,5 @@ public interface MemberUserConvert { } return result; } + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/group/MemberGroupServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/group/MemberGroupServiceImpl.java index 93c241886..e0e24c776 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/group/MemberGroupServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/group/MemberGroupServiceImpl.java @@ -69,6 +69,7 @@ public class MemberGroupServiceImpl implements MemberGroupService { } } + // TODO @疯狂:不要直接调用 memberUserMapper,需要对方 service 提供方法 void validateGroupHasUser(Long id) { Long count = memberUserMapper.selectCountByGroupId(id); if (count > 0) { diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordServiceImpl.java index 9653928a4..8e75acfac 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordServiceImpl.java @@ -26,7 +26,6 @@ public class MemberExperienceRecordServiceImpl implements MemberExperienceRecord @Resource private MemberExperienceRecordMapper experienceLogMapper; - @Override public MemberExperienceRecordDO getExperienceRecord(Long id) { return experienceLogMapper.selectById(id); @@ -45,12 +44,11 @@ public class MemberExperienceRecordServiceImpl implements MemberExperienceRecord @Override public void createExperienceRecord(Long userId, Integer experience, Integer totalExperience, MemberExperienceBizTypeEnum bizType, String bizId) { - String description = StrUtil.format(bizType.getDesc(), experience); - MemberExperienceRecordDO recordDO = MemberExperienceRecordConvert.INSTANCE.convert(userId, - experience, totalExperience, - bizId, bizType.getValue(), bizType.getTitle(), - description); - experienceLogMapper.insert(recordDO); + String description = StrUtil.format(bizType.getDescription(), experience); + MemberExperienceRecordDO record = MemberExperienceRecordConvert.INSTANCE.convert( + userId, experience, totalExperience, + bizId, bizType.getType(), bizType.getTitle(), description); + experienceLogMapper.insert(record); } } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordService.java index cdee7ddc7..d89ad3505 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordService.java @@ -4,9 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelRecordPageReqVO; import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO; -import java.util.Collection; -import java.util.List; - /** * 会员等级记录 Service 接口 * @@ -22,14 +19,6 @@ public interface MemberLevelRecordService { */ MemberLevelRecordDO getLevelRecord(Long id); - /** - * 获得会员等级记录列表 - * - * @param ids 编号 - * @return 会员等级记录列表 - */ - List getLevelRecordList(Collection ids); - /** * 获得会员等级记录分页 * @@ -44,4 +33,5 @@ public interface MemberLevelRecordService { * @param levelRecord 会员等级记录 */ void createLevelRecord(MemberLevelRecordDO levelRecord); + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordServiceImpl.java index 83926cd98..2f7f542d4 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordServiceImpl.java @@ -8,11 +8,6 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.util.Collection; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.LEVEL_LOG_NOT_EXISTS; /** * 会员等级记录 Service 实现类 @@ -26,22 +21,11 @@ public class MemberLevelRecordServiceImpl implements MemberLevelRecordService { @Resource private MemberLevelRecordMapper levelLogMapper; - private void validateLevelLogExists(Long id) { - if (levelLogMapper.selectById(id) == null) { - throw exception(LEVEL_LOG_NOT_EXISTS); - } - } - @Override public MemberLevelRecordDO getLevelRecord(Long id) { return levelLogMapper.selectById(id); } - @Override - public List getLevelRecordList(Collection ids) { - return levelLogMapper.selectBatchIds(ids); - } - @Override public PageResult getLevelRecordPage(MemberLevelRecordPageReqVO pageReqVO) { return levelLogMapper.selectPage(pageReqVO); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelService.java index 11c75cd65..76d46e5c3 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelService.java @@ -65,7 +65,6 @@ public interface MemberLevelService { */ List getLevelList(MemberLevelListReqVO listReqVO); - /** * 获得指定状态的会员等级列表 * @@ -74,7 +73,6 @@ public interface MemberLevelService { */ List getLevelListByStatus(Integer status); - /** * 获得开启状态的会员等级列表 * @@ -100,4 +98,5 @@ public interface MemberLevelService { * @param bizId 业务编号 */ void addExperience(Long userId, Integer experience, MemberExperienceBizTypeEnum bizType, String bizId); + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImpl.java index 6120b711a..fb9d5c663 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImpl.java @@ -25,6 +25,7 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.Collection; +import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -153,11 +154,12 @@ public class MemberLevelServiceImpl implements MemberLevelService { validateExperienceOutRange(list, id, level, experience); } + // TODO 有 Service 提供接口哈,不直接调用对方的 memberUserMapper @VisibleForTesting void validateLevelHasUser(Long id) { Long count = memberUserMapper.selectCountByLevelId(id); if (count > 0) { - throw exception(GROUP_HAS_USER); + throw exception(LEVEL_HAS_USER); } } @@ -168,6 +170,9 @@ public class MemberLevelServiceImpl implements MemberLevelService { @Override public List getLevelList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } return levelMapper.selectBatchIds(ids); } @@ -184,7 +189,7 @@ public class MemberLevelServiceImpl implements MemberLevelService { @Override @Transactional(rollbackFor = Exception.class) public void updateUserLevel(MemberUserUpdateLevelReqVO updateReqVO) { - MemberUserDO user = memberUserMapper.selectById(updateReqVO.getId()); + MemberUserDO user = memberUserService.getUser(updateReqVO.getId()); if (user == null) { throw exception(USER_NOT_EXISTS); } @@ -193,6 +198,7 @@ public class MemberLevelServiceImpl implements MemberLevelService { return; } + // 记录等级变动 MemberLevelRecordDO levelRecord = new MemberLevelRecordDO() .setUserId(user.getId()) .setRemark(updateReqVO.getReason()); @@ -211,17 +217,16 @@ public class MemberLevelServiceImpl implements MemberLevelService { levelRecord.setUserExperience(memberLevel.getExperience()); levelRecord.setDescription("管理员调整为:" + memberLevel.getName()); } - - // 记录等级变动 memberLevelRecordService.createLevelRecord(levelRecord); // 记录会员经验变动 memberExperienceRecordService.createExperienceRecord(user.getId(), levelRecord.getExperience(), levelRecord.getUserExperience(), - MemberExperienceBizTypeEnum.ADMIN, MemberExperienceBizTypeEnum.ADMIN.getValue() + ""); + MemberExperienceBizTypeEnum.ADMIN, String.valueOf(MemberExperienceBizTypeEnum.ADMIN.getType())); // 更新会员表上的等级编号、经验值 - memberUserService.updateLevelIdAndExperience(user.getId(), updateReqVO.getLevelId(), levelRecord.getUserExperience()); + memberUserService.updateUserLevel(user.getId(), updateReqVO.getLevelId(), + levelRecord.getUserExperience()); // 给会员发送等级变动消息 notifyMemberLevelChange(user.getId(), memberLevel); @@ -259,7 +264,7 @@ public class MemberLevelServiceImpl implements MemberLevelService { } // 更新会员表上的等级编号、经验值 - memberUserService.updateLevelIdAndExperience(user.getId(), levelRecord.getLevelId(), userExperience); + memberUserService.updateUserLevel(user.getId(), levelRecord.getLevelId(), userExperience); } /** diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java index 8b7d7460a..2b8155184 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java @@ -133,5 +133,6 @@ public interface MemberUserService { * @param levelId 用户等级 * @param experience 用户经验 */ - void updateLevelIdAndExperience(Long id, Long levelId, Integer experience); + void updateUserLevel(Long id, Long levelId, Integer experience); + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java index c2918fd39..cfaaf22de 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.member.service.user; import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -229,11 +230,9 @@ public class MemberUserServiceImpl implements MemberUserService { } @Override - public void updateLevelIdAndExperience(Long id, Long levelId, Integer experience) { - if (levelId == null) { - // 0 代表无等级:防止UpdateById时,会被过滤掉的问题 - levelId = 0L; - } + public void updateUserLevel(Long id, Long levelId, Integer experience) { + // 0 代表无等级:防止UpdateById时,会被过滤掉的问题 + levelId = ObjectUtil.defaultIfNull(levelId, 0L); memberUserMapper.updateById(new MemberUserDO() .setId(id) .setLevelId(levelId).setExperience(experience)