Browse Source

!585 会员: 会员等级功能优化,修改Review的代码
Merge pull request !585 from 疯狂的世界/member_dev

芋道源码 1 year ago
parent
commit
0619989586
41 changed files with 575 additions and 544 deletions
  1. 90 0
      sql/mysql/member_level.sql
  2. 2 2
      yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApi.java
  3. 1 1
      yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java
  4. 12 2
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApiImpl.java
  5. 16 17
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberExperienceRecordController.java
  6. 5 7
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelController.java
  7. 16 17
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelRecordController.java
  8. 1 1
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceRecordBaseVO.java
  9. 1 1
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceRecordPageReqVO.java
  10. 1 1
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceRecordRespVO.java
  11. 1 4
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelListReqVO.java
  12. 1 1
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelRecordBaseVO.java
  13. 1 1
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelRecordPageReqVO.java
  14. 1 1
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelRecordRespVO.java
  15. 9 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/MemberUserController.java
  16. 31 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserUpdateLevelReqVO.java
  17. 0 3
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserUpdateReqVO.java
  18. 0 27
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberExperienceLogConvert.java
  19. 30 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberExperienceRecordConvert.java
  20. 0 3
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelConvert.java
  21. 0 27
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelLogConvert.java
  22. 37 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelRecordConvert.java
  23. 3 3
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/level/MemberExperienceRecordDO.java
  24. 3 4
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/level/MemberLevelRecordDO.java
  25. 0 28
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberExperienceLogMapper.java
  26. 28 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberExperienceRecordMapper.java
  27. 3 4
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelMapper.java
  28. 9 9
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelRecordMapper.java
  29. 0 15
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java
  30. 0 64
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceLogServiceImpl.java
  31. 8 18
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordService.java
  32. 56 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordServiceImpl.java
  33. 0 77
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelLogService.java
  34. 0 109
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelLogServiceImpl.java
  35. 47 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordService.java
  36. 55 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordServiceImpl.java
  37. 9 13
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelService.java
  38. 70 67
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImpl.java
  39. 8 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java
  40. 12 8
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java
  41. 8 9
      yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImplTest.java

+ 90 - 0
sql/mysql/member_level.sql

@@ -1,3 +1,71 @@
+-- 会员表增加字段
+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);
@@ -6,3 +74,25 @@ insert system_dict_data(dict_type, label, value, sort) values ('member_experienc
 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);

+ 2 - 2
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApi.java

@@ -14,8 +14,8 @@ public interface MemberLevelApi {
      *
      * @param userId     会员ID
      * @param experience 经验
-     * @param bizType    业务类型
+     * @param bizType    业务类型 {@link MemberExperienceBizTypeEnum}
      * @param bizId      业务编号
      */
-    void plusExperience(Long userId, Integer experience, MemberExperienceBizTypeEnum bizType, String bizId);
+    void plusExperience(Long userId, Integer experience, Integer bizType, String bizId);
 }

+ 1 - 1
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java

@@ -50,7 +50,7 @@ public interface ErrorCodeConstants {
 
     ErrorCode LEVEL_LOG_NOT_EXISTS = new ErrorCode(1004011100, "用户等级记录不存在");
     ErrorCode EXPERIENCE_LOG_NOT_EXISTS = new ErrorCode(1004011200, "用户经验记录不存在");
-    ErrorCode LEVEL_REASON_NOT_EXISTS = new ErrorCode(1004011300, "用户等级调整原因不能为空");
+    ErrorCode EXPERIENCE_BIZ_NOT_SUPPORT = new ErrorCode(1004011201, "用户经验业务类型不支持");
 
     //========== 用户分组 1004012000 ==========
     ErrorCode GROUP_NOT_EXISTS = new ErrorCode(1004012000, "用户分组不存在");

+ 12 - 2
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApiImpl.java

@@ -1,11 +1,16 @@
 package cn.iocoder.yudao.module.member.api.level;
 
+import cn.hutool.core.util.EnumUtil;
 import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum;
 import cn.iocoder.yudao.module.member.service.level.MemberLevelService;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
+import java.util.Objects;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.EXPERIENCE_BIZ_NOT_SUPPORT;
 
 /**
  * 会员等级 API 实现类
@@ -19,7 +24,12 @@ public class MemberLevelApiImpl implements MemberLevelApi {
     @Resource
     private MemberLevelService memberLevelService;
 
-    public void plusExperience(Long userId, Integer experience, MemberExperienceBizTypeEnum bizType, String bizId) {
-        memberLevelService.plusExperience(userId, experience, bizType, bizId);
+    public void plusExperience(Long userId, Integer experience, Integer bizType, String bizId) {
+        MemberExperienceBizTypeEnum bizTypeEnum = EnumUtil.getBy(MemberExperienceBizTypeEnum.class, e -> Objects.equals(bizType, e.getValue()));
+        if (bizTypeEnum == null) {
+            throw exception(EXPERIENCE_BIZ_NOT_SUPPORT);
+        }
+
+        memberLevelService.addExperience(userId, experience, bizTypeEnum, bizId);
     }
 }

+ 16 - 17
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberExperienceLogController.java → yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberExperienceRecordController.java

@@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.member.controller.admin.level;
 
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceLogPageReqVO;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceLogRespVO;
-import cn.iocoder.yudao.module.member.convert.level.MemberExperienceLogConvert;
-import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceLogDO;
-import cn.iocoder.yudao.module.member.service.level.MemberExperienceLogService;
+import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceRecordPageReqVO;
+import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceRecordRespVO;
+import cn.iocoder.yudao.module.member.convert.level.MemberExperienceRecordConvert;
+import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceRecordDO;
+import cn.iocoder.yudao.module.member.service.level.MemberExperienceRecordService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,31 +22,30 @@ import javax.validation.Valid;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
-// TODO @疯狂:要不 Log 改成 Record,和 PointRecord 保持一致
 @Tag(name = "管理后台 - 会员经验记录")
 @RestController
-@RequestMapping("/member/experience-log")
+@RequestMapping("/member/experience-record")
 @Validated
-public class MemberExperienceLogController {
+public class MemberExperienceRecordController {
 
     @Resource
-    private MemberExperienceLogService experienceLogService;
+    private MemberExperienceRecordService experienceLogService;
 
     @GetMapping("/get")
     @Operation(summary = "获得会员经验记录")
     @Parameter(name = "id", description = "编号", required = true, example = "1024")
-    @PreAuthorize("@ss.hasPermission('member:experience-log:query')")
-    public CommonResult<MemberExperienceLogRespVO> getExperienceLog(@RequestParam("id") Long id) {
-        MemberExperienceLogDO experienceLog = experienceLogService.getExperienceLog(id);
-        return success(MemberExperienceLogConvert.INSTANCE.convert(experienceLog));
+    @PreAuthorize("@ss.hasPermission('member:experience-record:query')")
+    public CommonResult<MemberExperienceRecordRespVO> getExperienceLog(@RequestParam("id") Long id) {
+        MemberExperienceRecordDO experienceLog = experienceLogService.getExperienceRecord(id);
+        return success(MemberExperienceRecordConvert.INSTANCE.convert(experienceLog));
     }
 
     @GetMapping("/page")
     @Operation(summary = "获得会员经验记录分页")
-    @PreAuthorize("@ss.hasPermission('member:experience-log:query')")
-    public CommonResult<PageResult<MemberExperienceLogRespVO>> getExperienceLogPage(@Valid MemberExperienceLogPageReqVO pageVO) {
-        PageResult<MemberExperienceLogDO> pageResult = experienceLogService.getExperienceLogPage(pageVO);
-        return success(MemberExperienceLogConvert.INSTANCE.convertPage(pageResult));
+    @PreAuthorize("@ss.hasPermission('member:experience-record:query')")
+    public CommonResult<PageResult<MemberExperienceRecordRespVO>> getExperienceLogPage(@Valid MemberExperienceRecordPageReqVO pageVO) {
+        PageResult<MemberExperienceRecordDO> pageResult = experienceLogService.getExperienceRecordPage(pageVO);
+        return success(MemberExperienceRecordConvert.INSTANCE.convertPage(pageResult));
     }
 
 }

+ 5 - 7
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelController.java

@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.member.controller.admin.level;
 
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.*;
 import cn.iocoder.yudao.module.member.convert.level.MemberLevelConvert;
 import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO;
@@ -70,13 +69,12 @@ public class MemberLevelController {
         return success(MemberLevelConvert.INSTANCE.convertSimpleList(list));
     }
 
-    // TODO @疯狂:是不是不做分页,直接 list 就好啦;返回的时候,按照经验排序下哈;
-    @GetMapping("/page")
-    @Operation(summary = "获得会员等级分页")
+    @GetMapping("/list")
+    @Operation(summary = "获得会员等级列表")
     @PreAuthorize("@ss.hasPermission('member:level:query')")
-    public CommonResult<PageResult<MemberLevelRespVO>> getLevelPage(@Valid MemberLevelPageReqVO pageVO) {
-        PageResult<MemberLevelDO> pageResult = levelService.getLevelPage(pageVO);
-        return success(MemberLevelConvert.INSTANCE.convertPage(pageResult));
+    public CommonResult<List<MemberLevelRespVO>> getLevelList(@Valid MemberLevelListReqVO pageVO) {
+        List<MemberLevelDO> result = levelService.getLevelList(pageVO);
+        return success(MemberLevelConvert.INSTANCE.convertList(result));
     }
 
 }

+ 16 - 17
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelLogController.java → yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelRecordController.java

@@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.member.controller.admin.level;
 
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelLogPageReqVO;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelLogRespVO;
-import cn.iocoder.yudao.module.member.convert.level.MemberLevelLogConvert;
-import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelLogDO;
-import cn.iocoder.yudao.module.member.service.level.MemberLevelLogService;
+import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelRecordPageReqVO;
+import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelRecordRespVO;
+import cn.iocoder.yudao.module.member.convert.level.MemberLevelRecordConvert;
+import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO;
+import cn.iocoder.yudao.module.member.service.level.MemberLevelRecordService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,30 +22,29 @@ import javax.validation.Valid;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
-// TODO @疯狂:是不是不用这个 controller;因为日志只是为了记录,db 可以查询、和审计即可,目前暂时不需要开放出来;
 @Tag(name = "管理后台 - 会员等级记录")
 @RestController
-@RequestMapping("/member/level-log")
+@RequestMapping("/member/level-record")
 @Validated
-public class MemberLevelLogController {
+public class MemberLevelRecordController {
 
     @Resource
-    private MemberLevelLogService levelLogService;
+    private MemberLevelRecordService levelLogService;
 
     @GetMapping("/get")
     @Operation(summary = "获得会员等级记录")
     @Parameter(name = "id", description = "编号", required = true, example = "1024")
-    @PreAuthorize("@ss.hasPermission('member:level-log:query')")
-    public CommonResult<MemberLevelLogRespVO> getLevelLog(@RequestParam("id") Long id) {
-        MemberLevelLogDO levelLog = levelLogService.getLevelLog(id);
-        return success(MemberLevelLogConvert.INSTANCE.convert(levelLog));
+    @PreAuthorize("@ss.hasPermission('member:level-record:query')")
+    public CommonResult<MemberLevelRecordRespVO> getLevelLog(@RequestParam("id") Long id) {
+        MemberLevelRecordDO levelLog = levelLogService.getLevelRecord(id);
+        return success(MemberLevelRecordConvert.INSTANCE.convert(levelLog));
     }
 
     @GetMapping("/page")
     @Operation(summary = "获得会员等级记录分页")
-    @PreAuthorize("@ss.hasPermission('member:level-log:query')")
-    public CommonResult<PageResult<MemberLevelLogRespVO>> getLevelLogPage(@Valid MemberLevelLogPageReqVO pageVO) {
-        PageResult<MemberLevelLogDO> pageResult = levelLogService.getLevelLogPage(pageVO);
-        return success(MemberLevelLogConvert.INSTANCE.convertPage(pageResult));
+    @PreAuthorize("@ss.hasPermission('member:level-record:query')")
+    public CommonResult<PageResult<MemberLevelRecordRespVO>> getLevelLogPage(@Valid MemberLevelRecordPageReqVO pageVO) {
+        PageResult<MemberLevelRecordDO> pageResult = levelLogService.getLevelRecordPage(pageVO);
+        return success(MemberLevelRecordConvert.INSTANCE.convertPage(pageResult));
     }
 }

+ 1 - 1
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceLogBaseVO.java → yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceRecordBaseVO.java

@@ -10,7 +10,7 @@ import javax.validation.constraints.NotNull;
  * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  */
 @Data
-public class MemberExperienceLogBaseVO {
+public class MemberExperienceRecordBaseVO {
 
     @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3638")
     @NotNull(message = "用户编号不能为空")

+ 1 - 1
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceLogPageReqVO.java → yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceRecordPageReqVO.java

@@ -15,7 +15,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class MemberExperienceLogPageReqVO extends PageParam {
+public class MemberExperienceRecordPageReqVO extends PageParam {
 
     @Schema(description = "用户编号", example = "3638")
     private Long userId;

+ 1 - 1
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceLogRespVO.java → yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/experience/MemberExperienceRecordRespVO.java

@@ -11,7 +11,7 @@ import java.time.LocalDateTime;
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class MemberExperienceLogRespVO extends MemberExperienceLogBaseVO {
+public class MemberExperienceRecordRespVO extends MemberExperienceRecordBaseVO {
 
     @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "19610")
     private Long id;

+ 1 - 4
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelPageReqVO.java → yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/level/MemberLevelListReqVO.java

@@ -1,16 +1,13 @@
 package cn.iocoder.yudao.module.member.controller.admin.level.vo.level;
 
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
-import lombok.EqualsAndHashCode;
 import lombok.ToString;
 
 @Schema(description = "管理后台 - 会员等级分页 Request VO")
 @Data
-@EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class MemberLevelPageReqVO extends PageParam {
+public class MemberLevelListReqVO {
 
     @Schema(description = "等级名称", example = "芋艿")
     private String name;

+ 1 - 1
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelLogBaseVO.java → yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelRecordBaseVO.java

@@ -10,7 +10,7 @@ import javax.validation.constraints.NotNull;
  * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  */
 @Data
-public class MemberLevelLogBaseVO {
+public class MemberLevelRecordBaseVO {
 
     @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25923")
     @NotNull(message = "用户编号不能为空")

+ 1 - 1
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelLogPageReqVO.java → yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelRecordPageReqVO.java

@@ -15,7 +15,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class MemberLevelLogPageReqVO extends PageParam {
+public class MemberLevelRecordPageReqVO extends PageParam {
 
     @Schema(description = "用户编号", example = "25923")
     private Long userId;

+ 1 - 1
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelLogRespVO.java → yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelRecordRespVO.java

@@ -11,7 +11,7 @@ import java.time.LocalDateTime;
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class MemberLevelLogRespVO extends MemberLevelLogBaseVO {
+public class MemberLevelRecordRespVO extends MemberLevelRecordBaseVO {
 
     @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8741")
     private Long id;

+ 9 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/MemberUserController.java

@@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserPageReqVO;
 import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserRespVO;
+import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateLevelReqVO;
 import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateReqVO;
 import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert;
 import cn.iocoder.yudao.module.member.dal.dataobject.group.MemberGroupDO;
@@ -52,6 +53,14 @@ public class MemberUserController {
         return success(true);
     }
 
+    @PutMapping("/update-level")
+    @Operation(summary = "更新会员用户等级")
+    @PreAuthorize("@ss.hasPermission('member:user:update-level')")
+    public CommonResult<Boolean> updateUserLevel(@Valid @RequestBody MemberUserUpdateLevelReqVO updateReqVO) {
+        memberLevelService.updateUserLevel(updateReqVO);
+        return success(true);
+    }
+
     @GetMapping("/get")
     @Operation(summary = "获得会员用户")
     @Parameter(name = "id", description = "编号", required = true, example = "1024")

+ 31 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserUpdateLevelReqVO.java

@@ -0,0 +1,31 @@
+package cn.iocoder.yudao.module.member.controller.admin.user.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+@Schema(description = "管理后台 - 会员用户 修改等级 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MemberUserUpdateLevelReqVO extends MemberUserBaseVO {
+
+    @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23788")
+    @NotNull(message = "用户编号不能为空")
+    private Long id;
+
+    /**
+     * 取消用户等级时,值为空
+     */
+    @Schema(description = "用户等级编号", example = "1")
+    private Long levelId;
+
+    @Schema(description = "修改原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "推广需要")
+    @NotBlank(message = "修改原因不能为空")
+    private String reason;
+
+}

+ 0 - 3
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserUpdateReqVO.java

@@ -17,7 +17,4 @@ public class MemberUserUpdateReqVO extends MemberUserBaseVO {
     @NotNull(message = "编号不能为空")
     private Long id;
 
-    @Schema(description = "会员级别修改原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "推广需要")
-    private String levelReason;
-
 }

+ 0 - 27
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberExperienceLogConvert.java

@@ -1,27 +0,0 @@
-package cn.iocoder.yudao.module.member.convert.level;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceLogRespVO;
-import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceLogDO;
-import org.mapstruct.Mapper;
-import org.mapstruct.factory.Mappers;
-
-import java.util.List;
-
-/**
- * 会员经验记录 Convert
- *
- * @author owen
- */
-@Mapper
-public interface MemberExperienceLogConvert {
-
-    MemberExperienceLogConvert INSTANCE = Mappers.getMapper(MemberExperienceLogConvert.class);
-
-    MemberExperienceLogRespVO convert(MemberExperienceLogDO bean);
-
-    List<MemberExperienceLogRespVO> convertList(List<MemberExperienceLogDO> list);
-
-    PageResult<MemberExperienceLogRespVO> convertPage(PageResult<MemberExperienceLogDO> page);
-
-}

+ 30 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberExperienceRecordConvert.java

@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.module.member.convert.level;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceRecordRespVO;
+import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceRecordDO;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+/**
+ * 会员经验记录 Convert
+ *
+ * @author owen
+ */
+@Mapper
+public interface MemberExperienceRecordConvert {
+
+    MemberExperienceRecordConvert INSTANCE = Mappers.getMapper(MemberExperienceRecordConvert.class);
+
+    MemberExperienceRecordRespVO convert(MemberExperienceRecordDO bean);
+
+    List<MemberExperienceRecordRespVO> convertList(List<MemberExperienceRecordDO> list);
+
+    PageResult<MemberExperienceRecordRespVO> convertPage(PageResult<MemberExperienceRecordDO> page);
+
+    MemberExperienceRecordDO convert(Long userId, Integer experience, Integer totalExperience,
+                                     String bizId, Integer bizType,
+                                     String title, String description);
+}

+ 0 - 3
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelConvert.java

@@ -1,6 +1,5 @@
 package cn.iocoder.yudao.module.member.convert.level;
 
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelCreateReqVO;
 import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelRespVO;
 import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelSimpleRespVO;
@@ -29,7 +28,5 @@ public interface MemberLevelConvert {
 
     List<MemberLevelRespVO> convertList(List<MemberLevelDO> list);
 
-    PageResult<MemberLevelRespVO> convertPage(PageResult<MemberLevelDO> page);
-
     List<MemberLevelSimpleRespVO> convertSimpleList(List<MemberLevelDO> list);
 }

+ 0 - 27
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelLogConvert.java

@@ -1,27 +0,0 @@
-package cn.iocoder.yudao.module.member.convert.level;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelLogRespVO;
-import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelLogDO;
-import org.mapstruct.Mapper;
-import org.mapstruct.factory.Mappers;
-
-import java.util.List;
-
-/**
- * 会员等级记录 Convert
- *
- * @author owen
- */
-@Mapper
-public interface MemberLevelLogConvert {
-
-    MemberLevelLogConvert INSTANCE = Mappers.getMapper(MemberLevelLogConvert.class);
-
-    MemberLevelLogRespVO convert(MemberLevelLogDO bean);
-
-    List<MemberLevelLogRespVO> convertList(List<MemberLevelLogDO> list);
-
-    PageResult<MemberLevelLogRespVO> convertPage(PageResult<MemberLevelLogDO> page);
-
-}

+ 37 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelRecordConvert.java

@@ -0,0 +1,37 @@
+package cn.iocoder.yudao.module.member.convert.level;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelRecordRespVO;
+import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO;
+import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+/**
+ * 会员等级记录 Convert
+ *
+ * @author owen
+ */
+@Mapper
+public interface MemberLevelRecordConvert {
+
+    MemberLevelRecordConvert INSTANCE = Mappers.getMapper(MemberLevelRecordConvert.class);
+
+    MemberLevelRecordRespVO convert(MemberLevelRecordDO bean);
+
+    List<MemberLevelRecordRespVO> convertList(List<MemberLevelRecordDO> list);
+
+    PageResult<MemberLevelRecordRespVO> convertPage(PageResult<MemberLevelRecordDO> page);
+
+    default MemberLevelRecordDO copyTo(MemberLevelDO from, MemberLevelRecordDO to) {
+        if (from != null) {
+            to.setLevelId(from.getId());
+            to.setLevel(from.getLevel());
+            to.setDiscountPercent(from.getDiscountPercent());
+            to.setExperience(from.getExperience());
+        }
+        return to;
+    }
+}

+ 3 - 3
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/level/MemberExperienceLogDO.java → yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/level/MemberExperienceRecordDO.java

@@ -13,15 +13,15 @@ import lombok.*;
  *
  * @author owen
  */
-@TableName("member_experience_log")
-@KeySequence("member_experience_log_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@TableName("member_experience_record")
+@KeySequence("member_experience_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
 @Builder
 @NoArgsConstructor
 @AllArgsConstructor
-public class MemberExperienceLogDO extends BaseDO {
+public class MemberExperienceRecordDO extends BaseDO {
 
     /**
      * 编号

+ 3 - 4
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/level/MemberLevelLogDO.java → yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/level/MemberLevelRecordDO.java

@@ -14,15 +14,15 @@ import lombok.*;
  *
  * @author owen
  */
-@TableName("member_level_log")
-@KeySequence("member_level_log_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@TableName("member_level_record")
+@KeySequence("member_level_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
 @Builder
 @NoArgsConstructor
 @AllArgsConstructor
-public class MemberLevelLogDO extends BaseDO {
+public class MemberLevelRecordDO extends BaseDO {
 
     /**
      * 编号
@@ -59,7 +59,6 @@ public class MemberLevelLogDO extends BaseDO {
      * 会员此时的经验
      */
     private Integer userExperience;
-    // TODO @疯狂:是不是 remark 和 description 可以合并成 description 就够了
     /**
      * 备注
      */

+ 0 - 28
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberExperienceLogMapper.java

@@ -1,28 +0,0 @@
-package cn.iocoder.yudao.module.member.dal.mysql.level;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
-import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceLogPageReqVO;
-import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceLogDO;
-import org.apache.ibatis.annotations.Mapper;
-
-/**
- * 会员经验记录 Mapper
- *
- * @author owen
- */
-@Mapper
-public interface MemberExperienceLogMapper extends BaseMapperX<MemberExperienceLogDO> {
-
-    default PageResult<MemberExperienceLogDO> selectPage(MemberExperienceLogPageReqVO reqVO) {
-        return selectPage(reqVO, new LambdaQueryWrapperX<MemberExperienceLogDO>()
-                .eqIfPresent(MemberExperienceLogDO::getUserId, reqVO.getUserId())
-                .eqIfPresent(MemberExperienceLogDO::getBizId, reqVO.getBizId())
-                .eqIfPresent(MemberExperienceLogDO::getBizType, reqVO.getBizType())
-                .eqIfPresent(MemberExperienceLogDO::getTitle, reqVO.getTitle())
-                .betweenIfPresent(MemberExperienceLogDO::getCreateTime, reqVO.getCreateTime())
-                .orderByDesc(MemberExperienceLogDO::getId));
-    }
-
-}

+ 28 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberExperienceRecordMapper.java

@@ -0,0 +1,28 @@
+package cn.iocoder.yudao.module.member.dal.mysql.level;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceRecordPageReqVO;
+import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceRecordDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 会员经验记录 Mapper
+ *
+ * @author owen
+ */
+@Mapper
+public interface MemberExperienceRecordMapper extends BaseMapperX<MemberExperienceRecordDO> {
+
+    default PageResult<MemberExperienceRecordDO> selectPage(MemberExperienceRecordPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<MemberExperienceRecordDO>()
+                .eqIfPresent(MemberExperienceRecordDO::getUserId, reqVO.getUserId())
+                .eqIfPresent(MemberExperienceRecordDO::getBizId, reqVO.getBizId())
+                .eqIfPresent(MemberExperienceRecordDO::getBizType, reqVO.getBizType())
+                .eqIfPresent(MemberExperienceRecordDO::getTitle, reqVO.getTitle())
+                .betweenIfPresent(MemberExperienceRecordDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(MemberExperienceRecordDO::getId));
+    }
+
+}

+ 3 - 4
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelMapper.java

@@ -1,9 +1,8 @@
 package cn.iocoder.yudao.module.member.dal.mysql.level;
 
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelPageReqVO;
+import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelListReqVO;
 import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO;
 import org.apache.ibatis.annotations.Mapper;
 
@@ -17,8 +16,8 @@ import java.util.List;
 @Mapper
 public interface MemberLevelMapper extends BaseMapperX<MemberLevelDO> {
 
-    default PageResult<MemberLevelDO> selectPage(MemberLevelPageReqVO reqVO) {
-        return selectPage(reqVO, new LambdaQueryWrapperX<MemberLevelDO>()
+    default List<MemberLevelDO> selectList(MemberLevelListReqVO reqVO) {
+        return selectList(new LambdaQueryWrapperX<MemberLevelDO>()
                 .likeIfPresent(MemberLevelDO::getName, reqVO.getName())
                 .eqIfPresent(MemberLevelDO::getStatus, reqVO.getStatus())
                 .orderByAsc(MemberLevelDO::getLevel));

+ 9 - 9
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelLogMapper.java → yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelRecordMapper.java

@@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.member.dal.mysql.level;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelLogPageReqVO;
-import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelLogDO;
+import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelRecordPageReqVO;
+import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO;
 import org.apache.ibatis.annotations.Mapper;
 
 /**
@@ -13,14 +13,14 @@ import org.apache.ibatis.annotations.Mapper;
  * @author owen
  */
 @Mapper
-public interface MemberLevelLogMapper extends BaseMapperX<MemberLevelLogDO> {
+public interface MemberLevelRecordMapper extends BaseMapperX<MemberLevelRecordDO> {
 
-    default PageResult<MemberLevelLogDO> selectPage(MemberLevelLogPageReqVO reqVO) {
-        return selectPage(reqVO, new LambdaQueryWrapperX<MemberLevelLogDO>()
-                .eqIfPresent(MemberLevelLogDO::getUserId, reqVO.getUserId())
-                .eqIfPresent(MemberLevelLogDO::getLevelId, reqVO.getLevelId())
-                .betweenIfPresent(MemberLevelLogDO::getCreateTime, reqVO.getCreateTime())
-                .orderByDesc(MemberLevelLogDO::getId));
+    default PageResult<MemberLevelRecordDO> selectPage(MemberLevelRecordPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<MemberLevelRecordDO>()
+                .eqIfPresent(MemberLevelRecordDO::getUserId, reqVO.getUserId())
+                .eqIfPresent(MemberLevelRecordDO::getLevelId, reqVO.getLevelId())
+                .betweenIfPresent(MemberLevelRecordDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(MemberLevelRecordDO::getId));
     }
 
 }

+ 0 - 15
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java

@@ -7,7 +7,6 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserPageReqVO;
 import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import org.apache.ibatis.annotations.Mapper;
 
 import java.util.List;
@@ -50,20 +49,6 @@ public interface MemberUserMapper extends BaseMapperX<MemberUserDO> {
                 .orderByDesc(MemberUserDO::getId));
     }
 
-    // TODO @疯狂:命名可以改成 updateUserLevelToNull;db 侧的操作,尽量无业务含义,更多是 select、update、insert 操作
-    /**
-     * 取消会员的等级
-     *
-     * @param userId 会员编号
-     * @return 受影响的行数
-     */
-    default int cancelUserLevel(Long userId) {
-        return update(null, new LambdaUpdateWrapper<MemberUserDO>()
-                .eq(MemberUserDO::getId, userId)
-                .set(MemberUserDO::getExperience, 0)
-                .set(MemberUserDO::getLevelId, null));
-    }
-
     default Long selectCountByGroupId(Long groupId) {
         return selectCount(MemberUserDO::getGroupId, groupId);
     }

+ 0 - 64
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceLogServiceImpl.java

@@ -1,64 +0,0 @@
-package cn.iocoder.yudao.module.member.service.level;
-
-import cn.hutool.core.util.StrUtil;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceLogPageReqVO;
-import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceLogDO;
-import cn.iocoder.yudao.module.member.dal.mysql.level.MemberExperienceLogMapper;
-import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum;
-import org.springframework.stereotype.Service;
-import org.springframework.validation.annotation.Validated;
-
-import javax.annotation.Resource;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * 会员经验记录 Service 实现类
- *
- * @author owen
- */
-@Service
-@Validated
-public class MemberExperienceLogServiceImpl implements MemberExperienceLogService {
-
-    @Resource
-    private MemberExperienceLogMapper experienceLogMapper;
-
-
-    @Override
-    public MemberExperienceLogDO getExperienceLog(Long id) {
-        return experienceLogMapper.selectById(id);
-    }
-
-    @Override
-    public List<MemberExperienceLogDO> getExperienceLogList(Collection<Long> ids) {
-        return experienceLogMapper.selectBatchIds(ids);
-    }
-
-    @Override
-    public PageResult<MemberExperienceLogDO> getExperienceLogPage(MemberExperienceLogPageReqVO pageReqVO) {
-        return experienceLogMapper.selectPage(pageReqVO);
-    }
-
-    @Override
-    public void createAdjustLog(Long userId, int experience, int totalExperience) {
-        // 管理员调整时, 没有业务编号, 记录对应的枚举值
-        String bizId = MemberExperienceBizTypeEnum.ADMIN.getValue() + "";
-        this.createBizLog(userId, experience, totalExperience, MemberExperienceBizTypeEnum.ADMIN, bizId);
-    }
-
-    @Override
-    public void createBizLog(Long userId, int experience, int totalExperience, MemberExperienceBizTypeEnum bizType, String bizId) {
-        MemberExperienceLogDO experienceLogDO = new MemberExperienceLogDO();
-        experienceLogDO.setUserId(userId);
-        experienceLogDO.setExperience(experience);
-        experienceLogDO.setTotalExperience(totalExperience);
-        experienceLogDO.setBizId(bizId);
-        experienceLogDO.setBizType(bizType.getValue());
-        experienceLogDO.setTitle(bizType.getTitle());
-        experienceLogDO.setDescription(StrUtil.format(bizType.getDesc(), experience));
-        experienceLogMapper.insert(experienceLogDO);
-    }
-
-}

+ 8 - 18
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceLogService.java → yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordService.java

@@ -1,8 +1,8 @@
 package cn.iocoder.yudao.module.member.service.level;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceLogPageReqVO;
-import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceLogDO;
+import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceRecordPageReqVO;
+import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceRecordDO;
 import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum;
 
 import java.util.Collection;
@@ -13,7 +13,7 @@ import java.util.List;
  *
  * @author owen
  */
-public interface MemberExperienceLogService {
+public interface MemberExperienceRecordService {
 
     /**
      * 获得会员经验记录
@@ -21,7 +21,7 @@ public interface MemberExperienceLogService {
      * @param id 编号
      * @return 会员经验记录
      */
-    MemberExperienceLogDO getExperienceLog(Long id);
+    MemberExperienceRecordDO getExperienceRecord(Long id);
 
     /**
      * 获得会员经验记录列表
@@ -29,7 +29,7 @@ public interface MemberExperienceLogService {
      * @param ids 编号
      * @return 会员经验记录列表
      */
-    List<MemberExperienceLogDO> getExperienceLogList(Collection<Long> ids);
+    List<MemberExperienceRecordDO> getExperienceRecordList(Collection<Long> ids);
 
     /**
      * 获得会员经验记录分页
@@ -37,18 +37,7 @@ public interface MemberExperienceLogService {
      * @param pageReqVO 分页查询
      * @return 会员经验记录分页
      */
-    PageResult<MemberExperienceLogDO> getExperienceLogPage(MemberExperienceLogPageReqVO pageReqVO);
-
-    // TODO @疯狂:类似 MemberLevelLogService 的方法,这里也需要提供一个通用的方法,用于创建经验变动记录
-
-    /**
-     * 创建 手动调整 经验变动记录
-     *
-     * @param userId          会员编号
-     * @param experience      变动经验值
-     * @param totalExperience 会员当前的经验
-     */
-    void createAdjustLog(Long userId, int experience, int totalExperience);
+    PageResult<MemberExperienceRecordDO> getExperienceRecordPage(MemberExperienceRecordPageReqVO pageReqVO);
 
     /**
      * 根据业务类型, 创建 经验变动记录
@@ -59,5 +48,6 @@ public interface MemberExperienceLogService {
      * @param bizType         业务类型
      * @param bizId           业务ID
      */
-    void createBizLog(Long userId, int experience, int totalExperience, MemberExperienceBizTypeEnum bizType, String bizId);
+    void createExperienceRecord(Long userId, Integer experience, Integer totalExperience,
+                                MemberExperienceBizTypeEnum bizType, String bizId);
 }

+ 56 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordServiceImpl.java

@@ -0,0 +1,56 @@
+package cn.iocoder.yudao.module.member.service.level;
+
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceRecordPageReqVO;
+import cn.iocoder.yudao.module.member.convert.level.MemberExperienceRecordConvert;
+import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceRecordDO;
+import cn.iocoder.yudao.module.member.dal.mysql.level.MemberExperienceRecordMapper;
+import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 会员经验记录 Service 实现类
+ *
+ * @author owen
+ */
+@Service
+@Validated
+public class MemberExperienceRecordServiceImpl implements MemberExperienceRecordService {
+
+    @Resource
+    private MemberExperienceRecordMapper experienceLogMapper;
+
+
+    @Override
+    public MemberExperienceRecordDO getExperienceRecord(Long id) {
+        return experienceLogMapper.selectById(id);
+    }
+
+    @Override
+    public List<MemberExperienceRecordDO> getExperienceRecordList(Collection<Long> ids) {
+        return experienceLogMapper.selectBatchIds(ids);
+    }
+
+    @Override
+    public PageResult<MemberExperienceRecordDO> getExperienceRecordPage(MemberExperienceRecordPageReqVO pageReqVO) {
+        return experienceLogMapper.selectPage(pageReqVO);
+    }
+
+    @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);
+    }
+
+}

+ 0 - 77
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelLogService.java

@@ -1,77 +0,0 @@
-package cn.iocoder.yudao.module.member.service.level;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelLogPageReqVO;
-import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO;
-import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelLogDO;
-import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * 会员等级记录 Service 接口
- *
- * @author owen
- */
-public interface MemberLevelLogService {
-
-    /**
-     * 删除会员等级记录
-     *
-     * @param id 编号
-     */
-    void deleteLevelLog(Long id);
-
-    /**
-     * 获得会员等级记录
-     *
-     * @param id 编号
-     * @return 会员等级记录
-     */
-    MemberLevelLogDO getLevelLog(Long id);
-
-    /**
-     * 获得会员等级记录列表
-     *
-     * @param ids 编号
-     * @return 会员等级记录列表
-     */
-    List<MemberLevelLogDO> getLevelLogList(Collection<Long> ids);
-
-    /**
-     * 获得会员等级记录分页
-     *
-     * @param pageReqVO 分页查询
-     * @return 会员等级记录分页
-     */
-    PageResult<MemberLevelLogDO> getLevelLogPage(MemberLevelLogPageReqVO pageReqVO);
-
-    // TODO @疯狂:把 createCancelLog、createAdjustLog、createAutoUpgradeLog 几个日志合并成一个通用的日志方法;整体的内容,交给 MemberLevelService 去做;以及对应的 level 变化的通知;
-
-    /**
-     * 创建记录: 取消等级
-     *
-     * @param userId 会员编号
-     * @param reason 调整原因
-     */
-    void createCancelLog(Long userId, String reason);
-
-    /**
-     * 创建记录: 手动调整
-     *
-     * @param user       会员
-     * @param level      等级
-     * @param experience 变动经验值
-     * @param reason     调整原因
-     */
-    void createAdjustLog(MemberUserDO user, MemberLevelDO level, int experience, String reason);
-
-    /**
-     * 创建记录: 自动升级
-     *
-     * @param user  会员
-     * @param level 等级
-     */
-    void createAutoUpgradeLog(MemberUserDO user, MemberLevelDO level);
-}

+ 0 - 109
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelLogServiceImpl.java

@@ -1,109 +0,0 @@
-package cn.iocoder.yudao.module.member.service.level;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelLogPageReqVO;
-import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO;
-import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelLogDO;
-import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
-import cn.iocoder.yudao.module.member.dal.mysql.level.MemberLevelLogMapper;
-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 实现类
- *
- * @author owen
- */
-@Service
-@Validated
-public class MemberLevelLogServiceImpl implements MemberLevelLogService {
-
-    @Resource
-    private MemberLevelLogMapper levelLogMapper;
-
-    @Override
-    public void deleteLevelLog(Long id) {
-        // 校验存在
-        validateLevelLogExists(id);
-        // 删除
-        levelLogMapper.deleteById(id);
-    }
-
-    private void validateLevelLogExists(Long id) {
-        if (levelLogMapper.selectById(id) == null) {
-            throw exception(LEVEL_LOG_NOT_EXISTS);
-        }
-    }
-
-    @Override
-    public MemberLevelLogDO getLevelLog(Long id) {
-        return levelLogMapper.selectById(id);
-    }
-
-    @Override
-    public List<MemberLevelLogDO> getLevelLogList(Collection<Long> ids) {
-        return levelLogMapper.selectBatchIds(ids);
-    }
-
-    @Override
-    public PageResult<MemberLevelLogDO> getLevelLogPage(MemberLevelLogPageReqVO pageReqVO) {
-        return levelLogMapper.selectPage(pageReqVO);
-    }
-
-    @Override
-    public void createCancelLog(Long userId, String reason) {
-        MemberLevelLogDO levelLogDO = new MemberLevelLogDO();
-        levelLogDO.setUserId(userId);
-        levelLogDO.setRemark(reason);
-        levelLogDO.setDescription("管理员取消");
-        levelLogMapper.insert(levelLogDO);
-
-        // 给会员发送等级变动消息
-        notifyMember(userId, levelLogDO);
-    }
-
-    @Override
-    public void createAdjustLog(MemberUserDO user, MemberLevelDO level, int experience, String reason) {
-        MemberLevelLogDO levelLogDO = new MemberLevelLogDO();
-        levelLogDO.setUserId(user.getId());
-        levelLogDO.setLevelId(level.getId());
-        levelLogDO.setLevel(level.getLevel());
-        levelLogDO.setDiscountPercent(level.getDiscountPercent());
-        levelLogDO.setUserExperience(level.getExperience());
-        levelLogDO.setExperience(experience);
-        levelLogDO.setRemark(reason);
-        levelLogDO.setDescription("管理员调整为:" + level.getName());
-        levelLogMapper.insert(levelLogDO);
-
-        // 给会员发送等级变动消息
-        notifyMember(user.getId(), levelLogDO);
-    }
-
-    @Override
-    public void createAutoUpgradeLog(MemberUserDO user, MemberLevelDO level) {
-        MemberLevelLogDO levelLogDO = new MemberLevelLogDO();
-        levelLogDO.setUserId(user.getId());
-        levelLogDO.setLevelId(level.getId());
-        levelLogDO.setLevel(level.getLevel());
-        levelLogDO.setDiscountPercent(level.getDiscountPercent());
-        levelLogDO.setExperience(level.getExperience());
-        levelLogDO.setUserExperience(user.getExperience());
-        levelLogDO.setDescription("成为:" + level.getName());
-        levelLogMapper.insert(levelLogDO);
-
-        // 给会员发送等级变动消息
-        notifyMember(user.getId(), levelLogDO);
-    }
-
-    private void notifyMember(Long userId, MemberLevelLogDO level) {
-        //todo: 给会员发消息
-    }
-
-}

+ 47 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordService.java

@@ -0,0 +1,47 @@
+package cn.iocoder.yudao.module.member.service.level;
+
+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 接口
+ *
+ * @author owen
+ */
+public interface MemberLevelRecordService {
+
+    /**
+     * 获得会员等级记录
+     *
+     * @param id 编号
+     * @return 会员等级记录
+     */
+    MemberLevelRecordDO getLevelRecord(Long id);
+
+    /**
+     * 获得会员等级记录列表
+     *
+     * @param ids 编号
+     * @return 会员等级记录列表
+     */
+    List<MemberLevelRecordDO> getLevelRecordList(Collection<Long> ids);
+
+    /**
+     * 获得会员等级记录分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 会员等级记录分页
+     */
+    PageResult<MemberLevelRecordDO> getLevelRecordPage(MemberLevelRecordPageReqVO pageReqVO);
+
+    /**
+     * 创建会员等级记录
+     *
+     * @param levelRecord 会员等级记录
+     */
+    void createLevelRecord(MemberLevelRecordDO levelRecord);
+}

+ 55 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordServiceImpl.java

@@ -0,0 +1,55 @@
+package cn.iocoder.yudao.module.member.service.level;
+
+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 cn.iocoder.yudao.module.member.dal.mysql.level.MemberLevelRecordMapper;
+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 实现类
+ *
+ * @author owen
+ */
+@Service
+@Validated
+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<MemberLevelRecordDO> getLevelRecordList(Collection<Long> ids) {
+        return levelLogMapper.selectBatchIds(ids);
+    }
+
+    @Override
+    public PageResult<MemberLevelRecordDO> getLevelRecordPage(MemberLevelRecordPageReqVO pageReqVO) {
+        return levelLogMapper.selectPage(pageReqVO);
+    }
+
+    @Override
+    public void createLevelRecord(MemberLevelRecordDO levelRecord) {
+        levelLogMapper.insert(levelRecord);
+    }
+
+}

+ 9 - 13
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelService.java

@@ -1,15 +1,13 @@
 package cn.iocoder.yudao.module.member.service.level;
 
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelCreateReqVO;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelPageReqVO;
+import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelListReqVO;
 import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelUpdateReqVO;
+import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateLevelReqVO;
 import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO;
-import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
 import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum;
 
-import javax.annotation.Nullable;
 import javax.validation.Valid;
 import java.util.Collection;
 import java.util.List;
@@ -60,12 +58,12 @@ public interface MemberLevelService {
     List<MemberLevelDO> getLevelList(Collection<Long> ids);
 
     /**
-     * 获得会员等级分页
+     * 获得会员等级列表
      *
-     * @param pageReqVO 分页查询
-     * @return 会员等级分页
+     * @param listReqVO 查询参数
+     * @return 会员等级列表
      */
-    PageResult<MemberLevelDO> getLevelPage(MemberLevelPageReqVO pageReqVO);
+    List<MemberLevelDO> getLevelList(MemberLevelListReqVO listReqVO);
 
 
     /**
@@ -89,11 +87,9 @@ public interface MemberLevelService {
     /**
      * 修改会员的等级
      *
-     * @param user        会员
-     * @param levelId     要修改的等级编号,编号为空时,代表取消会员的等级
-     * @param levelReason 修改原因
+     * @param updateReqVO 修改参数
      */
-    void updateUserLevel(MemberUserDO user, @Nullable Long levelId, String levelReason);
+    void updateUserLevel(MemberUserUpdateLevelReqVO updateReqVO);
 
     /**
      * 增加会员经验
@@ -103,5 +99,5 @@ public interface MemberLevelService {
      * @param bizType    业务类型
      * @param bizId      业务编号
      */
-    void plusExperience(Long userId, Integer experience, MemberExperienceBizTypeEnum bizType, String bizId);
+    void addExperience(Long userId, Integer experience, MemberExperienceBizTypeEnum bizType, String bizId);
 }

+ 70 - 67
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImpl.java

@@ -4,17 +4,19 @@ import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.NumberUtil;
 import cn.hutool.core.util.ObjUtil;
 import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelCreateReqVO;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelPageReqVO;
+import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelListReqVO;
 import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelUpdateReqVO;
+import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateLevelReqVO;
 import cn.iocoder.yudao.module.member.convert.level.MemberLevelConvert;
+import cn.iocoder.yudao.module.member.convert.level.MemberLevelRecordConvert;
 import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO;
+import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO;
 import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
 import cn.iocoder.yudao.module.member.dal.mysql.level.MemberLevelMapper;
 import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper;
 import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum;
+import cn.iocoder.yudao.module.member.service.user.MemberUserService;
 import com.google.common.annotations.VisibleForTesting;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
@@ -42,11 +44,13 @@ public class MemberLevelServiceImpl implements MemberLevelService {
     @Resource
     private MemberLevelMapper levelMapper;
     @Resource
-    private MemberLevelLogService memberLevelLogService;
+    private MemberLevelRecordService memberLevelRecordService;
     @Resource
-    private MemberExperienceLogService memberExperienceLogService;
+    private MemberExperienceRecordService memberExperienceRecordService;
     @Resource
     private MemberUserMapper memberUserMapper;
+    @Resource
+    private MemberUserService memberUserService;
 
     @Override
     public Long createLevel(MemberLevelCreateReqVO createReqVO) {
@@ -168,8 +172,8 @@ public class MemberLevelServiceImpl implements MemberLevelService {
     }
 
     @Override
-    public PageResult<MemberLevelDO> getLevelPage(MemberLevelPageReqVO pageReqVO) {
-        return levelMapper.selectPage(pageReqVO);
+    public List<MemberLevelDO> getLevelList(MemberLevelListReqVO listReqVO) {
+        return levelMapper.selectList(listReqVO);
     }
 
     @Override
@@ -179,83 +183,83 @@ public class MemberLevelServiceImpl implements MemberLevelService {
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public void updateUserLevel(MemberUserDO user, Long levelId, String reason) {
-        // TODO @疯狂:可以直接 ObjUtil.equal(user.getLevelId(), levelId),解决这 2 个场景
-        // 未调整的情况1
-        if (user.getLevelId() == null && levelId == null) {
-            return;
+    public void updateUserLevel(MemberUserUpdateLevelReqVO updateReqVO) {
+        MemberUserDO user = memberUserMapper.selectById(updateReqVO.getId());
+        if (user == null) {
+            throw exception(USER_NOT_EXISTS);
         }
-        // 未调整的情况2
-        if (ObjUtil.equal(user.getLevelId(), levelId)) {
+        // 等级未发生变化
+        if (ObjUtil.equal(user.getLevelId(), updateReqVO.getLevelId())) {
             return;
         }
 
-        // 需要后台用户填写为什么调整会员的等级
-        // TODO @疯狂:这个 reason 是不是可以放到 validator 里做哈;
-        if (StrUtil.isBlank(reason)) {
-            throw exception(LEVEL_REASON_NOT_EXISTS);
-        }
-
-        int experience;
-        int totalExperience = 0;
-        // 记录等级变动
-        if (levelId == null) {
-            experience = -user.getExperience();
-
-            // TODO @疯狂:这里的逻辑,应该和下面的 207 到 210 行的逻辑一致,都是先记录日志,再更新会员表;所以,是不是都可以类似 214 的写法哈。
-            // 取消了会员的等级
-            memberLevelLogService.createCancelLog(user.getId(), reason);
-            memberUserMapper.cancelUserLevel(user.getId());
+        MemberLevelRecordDO levelRecord = new MemberLevelRecordDO()
+                .setUserId(user.getId())
+                .setRemark(updateReqVO.getReason());
+        MemberLevelDO memberLevel = null;
+        if (updateReqVO.getLevelId() == null) {
+            // 取消用户等级时,为扣减经验
+            levelRecord.setExperience(-user.getExperience());
+            levelRecord.setDescription("管理员取消了等级");
         } else {
-            MemberLevelDO level = validateLevelExists(levelId);
+            memberLevel = validateLevelExists(updateReqVO.getLevelId());
+            // 复制等级配置
+            MemberLevelRecordConvert.INSTANCE.copyTo(memberLevel, levelRecord);
             // 变动经验值 = 等级的升级经验 - 会员当前的经验;正数为增加经验,负数为扣减经验
-            experience = level.getExperience() - user.getExperience();
+            levelRecord.setExperience(memberLevel.getExperience() - user.getExperience());
             // 会员当前的经验 = 等级的升级经验
-            totalExperience = level.getExperience();
-
-            memberLevelLogService.createAdjustLog(user, level, experience, reason);
-
-            // 更新会员表上的等级编号、经验值
-            updateUserLevelIdAndExperience(user.getId(), levelId, totalExperience);
+            levelRecord.setUserExperience(memberLevel.getExperience());
+            levelRecord.setDescription("管理员调整为:" + memberLevel.getName());
         }
 
+        // 记录等级变动
+        memberLevelRecordService.createLevelRecord(levelRecord);
+
         // 记录会员经验变动
-        memberExperienceLogService.createAdjustLog(user.getId(), experience, totalExperience);
+        memberExperienceRecordService.createExperienceRecord(user.getId(),
+                levelRecord.getExperience(), levelRecord.getUserExperience(),
+                MemberExperienceBizTypeEnum.ADMIN, MemberExperienceBizTypeEnum.ADMIN.getValue() + "");
+
+        // 更新会员表上的等级编号、经验值
+        memberUserService.updateLevelIdAndExperience(user.getId(), updateReqVO.getLevelId(), levelRecord.getUserExperience());
+
+        // 给会员发送等级变动消息
+        notifyMemberLevelChange(user.getId(), memberLevel);
     }
 
-    // TODO @疯狂:方法名,建议改成 increase 或者 add 经验,和项目更统一一些
-    // TODO @疯狂:bizType 改成具体数值,主要是枚举在 api 不好传递,rpc 情况下
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public void plusExperience(Long userId, Integer experience, MemberExperienceBizTypeEnum bizType, String bizId) {
+    public void addExperience(Long userId, Integer experience, MemberExperienceBizTypeEnum bizType, String bizId) {
         if (experience == 0) {
             return;
         }
 
         MemberUserDO user = memberUserMapper.selectById(userId);
-        // TODO @疯狂:默认给 Experience 搞个 0 哈。这里就不做兜底逻辑啦
-        if (user.getExperience() == null) {
-            user.setExperience(0);
-        }
 
-        // 防止扣出负数
-        // TODO @疯狂:如果经验出现负数,是不是抛出异常会更合理;按道理不应该出现的;
         int userExperience = NumberUtil.max(user.getExperience() + experience, 0);
+        MemberLevelRecordDO levelRecord = new MemberLevelRecordDO()
+                .setUserId(user.getId())
+                .setExperience(experience)
+                // 防止扣出负数
+                .setUserExperience(userExperience);
+
         // 创建经验记录
-        memberExperienceLogService.createBizLog(userId, experience, userExperience, bizType, bizId);
+        memberExperienceRecordService.createExperienceRecord(userId, experience, userExperience,
+                bizType, bizId);
 
         // 计算会员等级
-        Long levelId = calcLevel(user, userExperience);
-        // 更新会员表上的等级编号、经验值
-        updateUserLevelIdAndExperience(user.getId(), levelId, userExperience);
-    }
+        MemberLevelDO newLevel = calculateNewLevel(user, userExperience);
+        if (newLevel != null) {
+            // 复制等级配置
+            MemberLevelRecordConvert.INSTANCE.copyTo(newLevel, levelRecord);
+            // 保存等级变更记录
+            memberLevelRecordService.createLevelRecord(levelRecord);
+            // 给会员发送等级变动消息
+            notifyMemberLevelChange(userId, newLevel);
+        }
 
-    // TODO @疯狂:让 memberUserService 那开个方法;每个模块,不直接操作对方的 mapper;
-    private void updateUserLevelIdAndExperience(Long userId, Long levelId, Integer experience) {
-        memberUserMapper.updateById(new MemberUserDO()
-                .setId(userId)
-                .setLevelId(levelId).setExperience(experience)
-        );
+        // 更新会员表上的等级编号、经验值
+        memberUserService.updateLevelIdAndExperience(user.getId(), levelRecord.getLevelId(), userExperience);
     }
 
     /**
@@ -263,11 +267,9 @@ public class MemberLevelServiceImpl implements MemberLevelService {
      *
      * @param user           会员
      * @param userExperience 会员当前的经验值
-     * @return 会员等级编号,null表示无变化
+     * @return 会员新的等级,null表示无变化
      */
-    // calc
-    // TODO @疯狂:calc 改成完整的拼写哈。是不是改成 calculateNewLevel
-    private Long calcLevel(MemberUserDO user, int userExperience) {
+    private MemberLevelDO calculateNewLevel(MemberUserDO user, int userExperience) {
         List<MemberLevelDO> list = getEnableLevelList();
         if (CollUtil.isEmpty(list)) {
             log.warn("计算会员等级失败:会员等级配置不存在");
@@ -288,9 +290,10 @@ public class MemberLevelServiceImpl implements MemberLevelService {
             return null;
         }
 
-        // TODO @疯狂:这个方法,应该只做 level 的计算,不做登记的变更。
-        // 保存等级变更记录
-        memberLevelLogService.createAutoUpgradeLog(user, matchLevel);
-        return matchLevel.getId();
+        return matchLevel;
+    }
+
+    private void notifyMemberLevelChange(Long userId, MemberLevelDO level) {
+        //todo: 给会员发消息
     }
 }

+ 8 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java

@@ -126,4 +126,12 @@ public interface MemberUserService {
      */
     PageResult<MemberUserDO> getUserPage(MemberUserPageReqVO pageReqVO);
 
+    /**
+     * 更新用户的等级和经验
+     *
+     * @param id         用户编号
+     * @param levelId    用户等级
+     * @param experience 用户经验
+     */
+    void updateLevelIdAndExperience(Long id, Long levelId, Integer experience);
 }

+ 12 - 8
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java

@@ -15,7 +15,6 @@ import cn.iocoder.yudao.module.member.convert.auth.AuthConvert;
 import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert;
 import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
 import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper;
-import cn.iocoder.yudao.module.member.service.level.MemberLevelService;
 import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
 import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
 import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
@@ -56,9 +55,6 @@ public class MemberUserServiceImpl implements MemberUserService {
     @Resource
     private PasswordEncoder passwordEncoder;
 
-    @Resource
-    private MemberLevelService memberLevelService;
-
     @Override
     public MemberUserDO getUserByMobile(String mobile) {
         return memberUserMapper.selectByMobile(mobile);
@@ -195,10 +191,6 @@ public class MemberUserServiceImpl implements MemberUserService {
         // 更新
         MemberUserDO updateObj = MemberUserConvert.INSTANCE.convert(updateReqVO);
         memberUserMapper.updateById(updateObj);
-
-        // 会员级别修改
-        // TODO @疯狂:修改用户等级,要不要单独一个前端操作 + 接口;因为它是个相对严肃独立的动作
-        memberLevelService.updateUserLevel(user, updateReqVO.getLevelId(), updateReqVO.getLevelReason());
     }
 
     @VisibleForTesting
@@ -236,4 +228,16 @@ public class MemberUserServiceImpl implements MemberUserService {
         return memberUserMapper.selectPage(pageReqVO);
     }
 
+    @Override
+    public void updateLevelIdAndExperience(Long id, Long levelId, Integer experience) {
+        if (levelId == null) {
+            // 0 代表无等级:防止UpdateById时,会被过滤掉的问题
+            levelId = 0L;
+        }
+        memberUserMapper.updateById(new MemberUserDO()
+                .setId(id)
+                .setLevelId(levelId).setExperience(experience)
+        );
+    }
+
 }

+ 8 - 9
yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImplTest.java

@@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
 import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelCreateReqVO;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelPageReqVO;
+import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelListReqVO;
 import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelUpdateReqVO;
 import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO;
 import cn.iocoder.yudao.module.member.dal.mysql.level.MemberLevelMapper;
@@ -41,9 +41,9 @@ public class MemberLevelServiceImplTest extends BaseDbUnitTest {
     private MemberLevelMapper levelMapper;
 
     @MockBean
-    private MemberLevelLogService memberLevelLogService;
+    private MemberLevelRecordService memberLevelRecordService;
     @MockBean
-    private MemberExperienceLogService memberExperienceLogService;
+    private MemberExperienceRecordService memberExperienceRecordService;
 
     @Test
     public void testCreateLevel_success() {
@@ -121,7 +121,7 @@ public class MemberLevelServiceImplTest extends BaseDbUnitTest {
     }
 
     @Test
-    public void testGetLevelPage() {
+    public void testGetLevelList() {
         // mock 数据
         MemberLevelDO dbLevel = randomPojo(MemberLevelDO.class, o -> { // 等会查询到
             o.setName("黄金会员");
@@ -133,16 +133,15 @@ public class MemberLevelServiceImplTest extends BaseDbUnitTest {
         // 测试 status 不匹配
         levelMapper.insert(cloneIgnoreId(dbLevel, o -> o.setStatus(0)));
         // 准备参数
-        MemberLevelPageReqVO reqVO = new MemberLevelPageReqVO();
+        MemberLevelListReqVO reqVO = new MemberLevelListReqVO();
         reqVO.setName("黄金会员");
         reqVO.setStatus(1);
 
         // 调用
-        PageResult<MemberLevelDO> pageResult = levelService.getLevelPage(reqVO);
+        List<MemberLevelDO> list = levelService.getLevelList(reqVO);
         // 断言
-        assertEquals(1, pageResult.getTotal());
-        assertEquals(1, pageResult.getList().size());
-        assertPojoEquals(dbLevel, pageResult.getList().get(0));
+        assertEquals(1, list.size());
+        assertPojoEquals(dbLevel, list.get(0));
     }
 
     @Test