Merge remote-tracking branch 'origin/feature/mall_product' into member_dev

This commit is contained in:
owen 2023-08-25 21:03:19 +08:00
commit 2895ae3ddb
20 changed files with 226 additions and 189 deletions

View File

@ -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如果你是 OraclePostgreSQLSQLServer 的话需要手动修改 @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);

View File

@ -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<AlipayTradePayRequest>) 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<String, String> 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<AlipayTradePayRequest>) request -> true)))
.thenReturn(response);
// 准备请求参数
String authCode = randomString();
PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(randomURL(), outTradeNo, randomInteger());
// 设置条码
Map<String, String> 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<AlipayTradePayRequest>) request -> true)))
.thenReturn(response);
// 准备请求参数
String authCode = randomString();
String outTradeNo = randomString();
PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(randomURL(), outTradeNo, randomInteger());
// 设置条码
Map<String, String> 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());
}
}

View File

@ -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<AlipayTradePagePayRequest>) 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<AlipayTradePagePayRequest>) 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());

View File

@ -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);
}

View File

@ -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 ==========

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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<MemberExperienceRecordRespVO> getExperienceLog(@RequestParam("id") Long id) {
public CommonResult<MemberExperienceRecordRespVO> 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<PageResult<MemberExperienceRecordRespVO>> getExperienceLogPage(@Valid MemberExperienceRecordPageReqVO pageVO) {
public CommonResult<PageResult<MemberExperienceRecordRespVO>> getExperienceRecordPage(
@Valid MemberExperienceRecordPageReqVO pageVO) {
PageResult<MemberExperienceRecordDO> pageResult = experienceLogService.getExperienceRecordPage(pageVO);
return success(MemberExperienceRecordConvert.INSTANCE.convertPage(pageResult));
}

View File

@ -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<MemberLevelRecordRespVO> getLevelLog(@RequestParam("id") Long id) {
public CommonResult<MemberLevelRecordRespVO> 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<PageResult<MemberLevelRecordRespVO>> getLevelLogPage(@Valid MemberLevelRecordPageReqVO pageVO) {
public CommonResult<PageResult<MemberLevelRecordRespVO>> getLevelRecordPage(
@Valid MemberLevelRecordPageReqVO pageVO) {
PageResult<MemberLevelRecordDO> pageResult = levelLogService.getLevelRecordPage(pageVO);
return success(MemberLevelRecordConvert.INSTANCE.convertPage(pageResult));
}
}

View File

@ -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 {

View File

@ -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<Long> groupIds = new HashSet<>(pageResult.getList().size());
// 处理用户标签返显
Set<Long> 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<MemberTagDO> tags = memberTagService.getTagList(tagIds);
// 处理用户级别返显
List<MemberLevelDO> levels = memberLevelService.getEnableLevelList();
List<MemberLevelDO> levels = memberLevelService.getLevelList(
convertSet(pageResult.getList(), MemberUserDO::getLevelId));
// 处理用户分组返显
List<MemberGroupDO> groups = memberGroupService.getGroupList(groupIds);
List<MemberGroupDO> groups = memberGroupService.getGroupList(
convertSet(pageResult.getList(), MemberUserDO::getGroupId));
return success(MemberUserConvert.INSTANCE.convertPage(pageResult, tags, levels, groups));
}

View File

@ -42,12 +42,10 @@ public interface MemberUserConvert {
List<MemberLevelDO> levels,
List<MemberGroupDO> groups) {
PageResult<MemberUserRespVO> result = convertPage(pageResult);
// 处理关联数据
Map<Long, String> tagMap = convertMap(tags, MemberTagDO::getId, MemberTagDO::getName);
Map<Long, String> levelMap = convertMap(levels, MemberLevelDO::getId, MemberLevelDO::getName);
Map<Long, String> 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;
}
}

View File

@ -69,6 +69,7 @@ public class MemberGroupServiceImpl implements MemberGroupService {
}
}
// TODO @疯狂不要直接调用 memberUserMapper需要对方 service 提供方法
void validateGroupHasUser(Long id) {
Long count = memberUserMapper.selectCountByGroupId(id);
if (count > 0) {

View File

@ -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);
}
}

View File

@ -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<MemberLevelRecordDO> getLevelRecordList(Collection<Long> ids);
/**
* 获得会员等级记录分页
*
@ -44,4 +33,5 @@ public interface MemberLevelRecordService {
* @param levelRecord 会员等级记录
*/
void createLevelRecord(MemberLevelRecordDO levelRecord);
}

View File

@ -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<MemberLevelRecordDO> getLevelRecordList(Collection<Long> ids) {
return levelLogMapper.selectBatchIds(ids);
}
@Override
public PageResult<MemberLevelRecordDO> getLevelRecordPage(MemberLevelRecordPageReqVO pageReqVO) {
return levelLogMapper.selectPage(pageReqVO);

View File

@ -65,7 +65,6 @@ public interface MemberLevelService {
*/
List<MemberLevelDO> getLevelList(MemberLevelListReqVO listReqVO);
/**
* 获得指定状态的会员等级列表
*
@ -74,7 +73,6 @@ public interface MemberLevelService {
*/
List<MemberLevelDO> getLevelListByStatus(Integer status);
/**
* 获得开启状态的会员等级列表
*
@ -100,4 +98,5 @@ public interface MemberLevelService {
* @param bizId 业务编号
*/
void addExperience(Long userId, Integer experience, MemberExperienceBizTypeEnum bizType, String bizId);
}

View File

@ -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<MemberLevelDO> getLevelList(Collection<Long> 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);
}
/**

View File

@ -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);
}

View File

@ -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)