【代码评审】商城:客服功能

This commit is contained in:
YunaiV 2024-06-04 20:25:24 +08:00
parent 2347bffeb1
commit d89a19a92b
16 changed files with 60 additions and 34 deletions

View File

@ -7,7 +7,7 @@ import lombok.Getter;
import java.util.Arrays; import java.util.Arrays;
/** /**
* 消息类型枚举 * 客服消息类型枚举
* *
* @author HUIHUI * @author HUIHUI
*/ */
@ -19,7 +19,7 @@ public enum KeFuMessageContentTypeEnum implements IntArrayValuable {
IMAGE(2, "图片消息"), IMAGE(2, "图片消息"),
VOICE(3, "语音消息"), VOICE(3, "语音消息"),
VIDEO(4, "视频消息"), VIDEO(4, "视频消息"),
// 和正常消息隔离下 // ========== 商城特殊消息 ==========
PRODUCT(10, "商品消息"), PRODUCT(10, "商品消息"),
ORDER(11, "订单消息"); ORDER(11, "订单消息");

View File

@ -27,6 +27,7 @@ public class KeFuConversationController {
@Resource @Resource
private KeFuConversationService conversationService; private KeFuConversationService conversationService;
// TODO @puhui999updateConversationPinned
@PostMapping("/update-pinned") @PostMapping("/update-pinned")
@Operation(summary = "置顶客服会话") @Operation(summary = "置顶客服会话")
@PreAuthorize("@ss.hasPermission('promotion:kefu-conversation:update')") @PreAuthorize("@ss.hasPermission('promotion:kefu-conversation:update')")

View File

@ -1,26 +1,24 @@
package cn.iocoder.yudao.module.promotion.controller.admin.kefu; package cn.iocoder.yudao.module.promotion.controller.admin.kefu;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessagePageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessagePageReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageRespVO; import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageRespVO;
import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageSendReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMessageSendReqVO;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.validation.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO;
import cn.iocoder.yudao.module.promotion.service.kefu.KeFuMessageService; import cn.iocoder.yudao.module.promotion.service.kefu.KeFuMessageService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - 客服消息") @Tag(name = "管理后台 - 客服消息")
@RestController @RestController
@ -47,6 +45,7 @@ public class KeFuMessageController {
return success(true); return success(true);
} }
// TODO @puhui999这个应该是某个会话上翻下翻不是传统的分页哈
@GetMapping("/page") @GetMapping("/page")
@Operation(summary = "获得客服消息分页") @Operation(summary = "获得客服消息分页")
@PreAuthorize("@ss.hasPermission('promotion:kefu-message:query')") @PreAuthorize("@ss.hasPermission('promotion:kefu-message:query')")

View File

@ -15,9 +15,11 @@ public class KeFuConversationRespVO {
@Schema(description = "会话所属用户", requiredMode = Schema.RequiredMode.REQUIRED, example = "8300") @Schema(description = "会话所属用户", requiredMode = Schema.RequiredMode.REQUIRED, example = "8300")
private Long userId; private Long userId;
@Schema(description = "最后聊天时间", requiredMode = Schema.RequiredMode.REQUIRED,example = "2024-01-01 00:00:00") @Schema(description = "最后聊天时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime lastMessageTime; private LocalDateTime lastMessageTime;
// TODO @puhui999, 缺了空格哈
@Schema(description = "最后聊天内容", requiredMode = Schema.RequiredMode.REQUIRED,example = "嗨,您好啊") @Schema(description = "最后聊天内容", requiredMode = Schema.RequiredMode.REQUIRED,example = "嗨,您好啊")
private String lastMessageContent; private String lastMessageContent;
@ -36,7 +38,7 @@ public class KeFuConversationRespVO {
@Schema(description = "管理员未读消息数", requiredMode = Schema.RequiredMode.REQUIRED,example = "6") @Schema(description = "管理员未读消息数", requiredMode = Schema.RequiredMode.REQUIRED,example = "6")
private Integer adminUnreadMessageCount; private Integer adminUnreadMessageCount;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED,example = "2024-01-01 00:00:00") @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime; private LocalDateTime createTime;
} }

View File

@ -9,11 +9,11 @@ import lombok.Data;
public class KeFuConversationUpdatePinnedReqVO { public class KeFuConversationUpdatePinnedReqVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23202") @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23202")
@NotNull(message = "会话编号不能为空") @NotNull(message = "会话编号不能为空")
private Long id; private Long id;
@Schema(description = "管理端置顶", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") @Schema(description = "管理端置顶", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
@NotNull(message = "管理端置顶不能为空") @NotNull(message = "管理端置顶不能为空")
private Boolean adminPinned; private Boolean adminPinned;
} }

View File

@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
@Schema(description = "管理后台 - 客服消息分页 Request VO") @Schema(description = "管理后台 - 客服消息分页 Request VO")
@Data @Data
// TODO @puhui999不用 @EqualsAndHashCode
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)
public class KeFuMessagePageReqVO extends PageParam { public class KeFuMessagePageReqVO extends PageParam {

View File

@ -9,6 +9,8 @@ import lombok.Data;
@Data @Data
public class KeFuMessageSendReqVO { public class KeFuMessageSendReqVO {
// TODO @puhui999貌似字段多了1id 不用2senderIdsenderType 不用3receiverIdreceiverType 也不用原因可以想下哈
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23202") @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23202")
private Long id; private Long id;

View File

@ -25,10 +25,12 @@ public class AppKeFuConversationController {
@Resource @Resource
private KeFuConversationService conversationService; private KeFuConversationService conversationService;
// TODO @puhui999接口名不对噢
@GetMapping("/get") @GetMapping("/get")
@Operation(summary = "获得客服会话") @Operation(summary = "获得客服会话")
@PreAuthenticated @PreAuthenticated
public CommonResult<AppKeFuConversationRespVO> getDiyPage() { public CommonResult<AppKeFuConversationRespVO> getDiyPage() {
// TODO @puhui999建议获取和转换分成 2 个哈干净一些
return success(BeanUtils.toBean(conversationService.getOrCreateConversation(getLoginUserId()), AppKeFuConversationRespVO.class)); return success(BeanUtils.toBean(conversationService.getOrCreateConversation(getLoginUserId()), AppKeFuConversationRespVO.class));
} }

View File

@ -8,6 +8,7 @@ import lombok.ToString;
@Schema(description = "用户 App - 客服消息分页 Request VO") @Schema(description = "用户 App - 客服消息分页 Request VO")
@Data @Data
// TODO @puhui999不用 @EqualsAndHashCode
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)
public class AppKeFuMessagePageReqVO extends PageParam { public class AppKeFuMessagePageReqVO extends PageParam {

View File

@ -16,6 +16,7 @@ import java.util.List;
@Mapper @Mapper
public interface KeFuConversationMapper extends BaseMapperX<KeFuConversationDO> { public interface KeFuConversationMapper extends BaseMapperX<KeFuConversationDO> {
// TODO @puhui999排序可以交给前端或者 controller数据库的计算尽量少哈
default List<KeFuConversationDO> selectListWithSort() { default List<KeFuConversationDO> selectListWithSort() {
return selectList(new LambdaQueryWrapperX<KeFuConversationDO>() return selectList(new LambdaQueryWrapperX<KeFuConversationDO>()
.eq(KeFuConversationDO::getAdminDeleted, Boolean.FALSE) .eq(KeFuConversationDO::getAdminDeleted, Boolean.FALSE)
@ -23,6 +24,7 @@ public interface KeFuConversationMapper extends BaseMapperX<KeFuConversationDO>
.orderByDesc(KeFuConversationDO::getCreateTime)); .orderByDesc(KeFuConversationDO::getCreateTime));
} }
// TODO @puhui999是不是置零 update ok 然后单独搞个 +1 的方法
default void updateAdminUnreadMessageCountByConversationId(Long id, Integer count) { default void updateAdminUnreadMessageCountByConversationId(Long id, Integer count) {
LambdaUpdateWrapper<KeFuConversationDO> updateWrapper = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<KeFuConversationDO> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(KeFuConversationDO::getId, id); updateWrapper.eq(KeFuConversationDO::getId, id);
@ -31,7 +33,6 @@ public interface KeFuConversationMapper extends BaseMapperX<KeFuConversationDO>
} else { // 情况二管理员已读后重置 } else { // 情况二管理员已读后重置
updateWrapper.set(KeFuConversationDO::getAdminUnreadMessageCount, 0); updateWrapper.set(KeFuConversationDO::getAdminUnreadMessageCount, 0);
} }
update(updateWrapper); update(updateWrapper);
} }

View File

@ -26,13 +26,16 @@ public interface KeFuMessageMapper extends BaseMapperX<KeFuMessageDO> {
.orderByDesc(KeFuMessageDO::getId)); .orderByDesc(KeFuMessageDO::getId));
} }
default List<KeFuMessageDO> selectListByConversationIdAndReceiverIdAndReadStatus(Long conversationId, Long receiverId, Boolean readStatus) { default List<KeFuMessageDO> selectListByConversationIdAndReceiverIdAndReadStatus(Long conversationId,
Long receiverId,
Boolean readStatus) {
return selectList(new LambdaQueryWrapper<KeFuMessageDO>() return selectList(new LambdaQueryWrapper<KeFuMessageDO>()
.eq(KeFuMessageDO::getConversationId, conversationId) .eq(KeFuMessageDO::getConversationId, conversationId)
.eq(KeFuMessageDO::getReceiverId, receiverId) .eq(KeFuMessageDO::getReceiverId, receiverId)
.eq(KeFuMessageDO::getReadStatus, readStatus)); .eq(KeFuMessageDO::getReadStatus, readStatus));
} }
// TODO @puhui999status 拼写不对哈ps是不是搞个 ids + entity 的更新更通用点
default void updateReadStstusBatchByIds(Collection<Long> ids, Boolean readStatus) { default void updateReadStstusBatchByIds(Collection<Long> ids, Boolean readStatus) {
update(new LambdaUpdateWrapper<KeFuMessageDO>() update(new LambdaUpdateWrapper<KeFuMessageDO>()
.in(KeFuMessageDO::getId, ids) .in(KeFuMessageDO::getId, ids)

View File

@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuConversationDO;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
// TODO @puhui999可以在每个方法前面加个会员管理员区分下
/** /**
* 客服会话 Service 接口 * 客服会话 Service 接口
* *
@ -20,6 +21,7 @@ public interface KeFuConversationService {
*/ */
void deleteKefuConversation(Long id); void deleteKefuConversation(Long id);
// TODO @puhui999是不是方法名体现出更新的是管理员的置顶哈
/** /**
* 客服会话置顶 * 客服会话置顶
* *
@ -27,6 +29,7 @@ public interface KeFuConversationService {
*/ */
void updatePinned(KeFuConversationUpdatePinnedReqVO updateReqVO); void updatePinned(KeFuConversationUpdatePinnedReqVO updateReqVO);
// TODO @puhui999updateConversationLastMessage 会好点哈
/** /**
* 更新会话客服消息冗余信息 * 更新会话客服消息冗余信息
* *
@ -60,7 +63,9 @@ public interface KeFuConversationService {
List<KeFuConversationDO> getKefuConversationList(); List<KeFuConversationDO> getKefuConversationList();
/** /**
* 获得或创建会话 * 会员获得或创建会话
*
* 对于会员来说有且仅有一个对话
* *
* @param userId 用户编号 * @param userId 用户编号
* @return 客服会话 * @return 客服会话

View File

@ -37,7 +37,6 @@ public class KeFuConversationServiceImpl implements KeFuConversationService {
@Override @Override
public void updatePinned(KeFuConversationUpdatePinnedReqVO updateReqVO) { public void updatePinned(KeFuConversationUpdatePinnedReqVO updateReqVO) {
// 只有管理员端可以置顶会话
conversationMapper.updateById(new KeFuConversationDO().setId(updateReqVO.getId()).setAdminPinned(updateReqVO.getAdminPinned())); conversationMapper.updateById(new KeFuConversationDO().setId(updateReqVO.getId()).setAdminPinned(updateReqVO.getAdminPinned()));
} }
@ -62,10 +61,12 @@ public class KeFuConversationServiceImpl implements KeFuConversationService {
return conversationMapper.selectListWithSort(); return conversationMapper.selectListWithSort();
} }
// TODO @puhui999貌似这个对话得用户主动创建不然管理员会看到一个空的对话
@Override @Override
public KeFuConversationDO getOrCreateConversation(Long userId) { public KeFuConversationDO getOrCreateConversation(Long userId) {
KeFuConversationDO conversation = conversationMapper.selectOne(KeFuConversationDO::getUserId, userId); KeFuConversationDO conversation = conversationMapper.selectOne(KeFuConversationDO::getUserId, userId);
if (conversation == null) { // 没有历史会话则初始化一个新会话 // 没有历史会话则初始化一个新会话
if (conversation == null) {
conversation = new KeFuConversationDO().setUserId(userId).setLastMessageTime(LocalDateTime.now()) conversation = new KeFuConversationDO().setUserId(userId).setLastMessageTime(LocalDateTime.now())
.setLastMessageContent("").setLastMessageContentType(KeFuMessageContentTypeEnum.TEXT.getType()) .setLastMessageContent("").setLastMessageContentType(KeFuMessageContentTypeEnum.TEXT.getType())
.setAdminPinned(Boolean.FALSE).setUserDeleted(Boolean.FALSE).setAdminDeleted(Boolean.FALSE) .setAdminPinned(Boolean.FALSE).setUserDeleted(Boolean.FALSE).setAdminDeleted(Boolean.FALSE)
@ -77,12 +78,11 @@ public class KeFuConversationServiceImpl implements KeFuConversationService {
@Override @Override
public KeFuConversationDO validateKefuConversationExists(Long id) { public KeFuConversationDO validateKefuConversationExists(Long id) {
KeFuConversationDO conversationDO = conversationMapper.selectById(id); KeFuConversationDO conversation = conversationMapper.selectById(id);
if (conversationDO == null) { if (conversation == null) {
throw exception(KEFU_CONVERSATION_NOT_EXISTS); throw exception(KEFU_CONVERSATION_NOT_EXISTS);
} }
return conversation;
return conversationDO;
} }
} }

View File

@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.promotion.controller.admin.kefu.vo.message.KeFuMe
import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.kefu.KeFuMessageDO;
import jakarta.validation.Valid; import jakarta.validation.Valid;
// TODO @puhui999可以在每个方法前面加个会员管理员区分下
/** /**
* 客服消息 Service 接口 * 客服消息 Service 接口
* *

View File

@ -34,12 +34,16 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
@Validated @Validated
public class KeFuMessageServiceImpl implements KeFuMessageService { public class KeFuMessageServiceImpl implements KeFuMessageService {
// TODO @puhui999@芋艿捉摸要不要拿到一个地方枚举
private static final String KEFU_MESSAGE_TYPE = "kefu_message_type"; // 客服消息类型 private static final String KEFU_MESSAGE_TYPE = "kefu_message_type"; // 客服消息类型
// TODO @puhui999kefuMessageMapper因为 messageMapper 可能会重叠
@Resource @Resource
private KeFuMessageMapper messageMapper; private KeFuMessageMapper messageMapper;
@Resource @Resource
private KeFuConversationService conversationService; private KeFuConversationService conversationService;
@Resource @Resource
private AdminUserApi adminUserApi; private AdminUserApi adminUserApi;
@Resource @Resource
@ -58,6 +62,7 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
// 2.1 保存消息 // 2.1 保存消息
KeFuMessageDO kefuMessage = BeanUtils.toBean(sendReqVO, KeFuMessageDO.class); KeFuMessageDO kefuMessage = BeanUtils.toBean(sendReqVO, KeFuMessageDO.class);
messageMapper.insert(kefuMessage); messageMapper.insert(kefuMessage);
// TODO @puhui999是不是 updateConversationMessage里面统一处理未读恢复直接设置 KeFuMessageDO 作为参数好了
// 2.2 更新会话消息冗余 // 2.2 更新会话消息冗余
conversationService.updateConversationMessage(kefuMessage.getConversationId(), LocalDateTime.now(), conversationService.updateConversationMessage(kefuMessage.getConversationId(), LocalDateTime.now(),
kefuMessage.getContent(), kefuMessage.getContentType()); kefuMessage.getContent(), kefuMessage.getContentType());
@ -66,14 +71,13 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
conversationService.updateAdminUnreadMessageCountByConversationId(kefuMessage.getConversationId(), 1); conversationService.updateAdminUnreadMessageCountByConversationId(kefuMessage.getConversationId(), 1);
} }
// 2.4 会员用户发送消息时如果管理员删除过会话则进行恢复 // 2.4 会员用户发送消息时如果管理员删除过会话则进行恢复
// TODO @puhui999建议 && 换一行
if (UserTypeEnum.MEMBER.getValue().equals(kefuMessage.getSenderType()) && Boolean.TRUE.equals(conversation.getAdminDeleted())) { if (UserTypeEnum.MEMBER.getValue().equals(kefuMessage.getSenderType()) && Boolean.TRUE.equals(conversation.getAdminDeleted())) {
conversationService.updateConversationAdminDeleted(kefuMessage.getConversationId(), Boolean.FALSE); conversationService.updateConversationAdminDeleted(kefuMessage.getConversationId(), Boolean.FALSE);
} }
// 3. 发送消息 // 3. 发送消息
getSelf().sendAsyncMessage(sendReqVO.getReceiverType(), sendReqVO.getReceiverId(), kefuMessage); getSelf().sendAsyncMessage(sendReqVO.getReceiverType(), sendReqVO.getReceiverId(), kefuMessage);
// 返回
return kefuMessage.getId(); return kefuMessage.getId();
} }
@ -83,6 +87,7 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
// 1.1 校验会话是否存在 // 1.1 校验会话是否存在
conversationService.validateKefuConversationExists(conversationId); conversationService.validateKefuConversationExists(conversationId);
// 1.2 查询接收人所有的未读消息 // 1.2 查询接收人所有的未读消息
// TODO @puhui999应该不能 receiverId 过滤哈因为多个客服一个人点了就都点了
List<KeFuMessageDO> messageList = messageMapper.selectListByConversationIdAndReceiverIdAndReadStatus( List<KeFuMessageDO> messageList = messageMapper.selectListByConversationIdAndReceiverIdAndReadStatus(
conversationId, receiverId, Boolean.FALSE); conversationId, receiverId, Boolean.FALSE);
// 1.3 情况一没有未读消息 // 1.3 情况一没有未读消息
@ -98,7 +103,9 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
if (UserTypeEnum.ADMIN.getValue().equals(message.getReceiverType())) { if (UserTypeEnum.ADMIN.getValue().equals(message.getReceiverType())) {
conversationService.updateAdminUnreadMessageCountByConversationId(conversationId, 0); conversationService.updateAdminUnreadMessageCountByConversationId(conversationId, 0);
} }
// 2.3 发送消息通知发送者接收者已读 -> 发送者更新发送的消息状态 // 2.3 发送消息通知发送者接收者已读 -> 发送者更新发送的消息状态
// TODO @puhui999待定~
getSelf().sendAsyncMessage(message.getSenderType(), message.getSenderId(), "keFuMessageReadStatusChange"); getSelf().sendAsyncMessage(message.getSenderType(), message.getSenderId(), "keFuMessageReadStatusChange");
} }

View File

@ -131,8 +131,9 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
@Override @Override
public BrokerageUserDO getOrCreateBrokerageUser(Long id) { public BrokerageUserDO getOrCreateBrokerageUser(Long id) {
BrokerageUserDO brokerageUser = brokerageUserMapper.selectById(id); BrokerageUserDO brokerageUser = brokerageUserMapper.selectById(id);
// 特殊人人分销的情况下如果分销人为空则创建分销人
if (brokerageUser == null && ObjUtil.equal(BrokerageEnabledConditionEnum.ALL.getCondition(), if (brokerageUser == null && ObjUtil.equal(BrokerageEnabledConditionEnum.ALL.getCondition(),
tradeConfigService.getTradeConfig().getBrokerageEnabledCondition())) { // 人人分销的情况下如果分销人为空则创建分销人 tradeConfigService.getTradeConfig().getBrokerageEnabledCondition())) {
brokerageUser = new BrokerageUserDO().setId(id).setBrokerageEnabled(true).setBrokeragePrice(0) brokerageUser = new BrokerageUserDO().setId(id).setBrokerageEnabled(true).setBrokeragePrice(0)
.setBrokerageTime(LocalDateTime.now()).setFrozenPrice(0); .setBrokerageTime(LocalDateTime.now()).setFrozenPrice(0);
brokerageUserMapper.insert(brokerageUser); brokerageUserMapper.insert(brokerageUser);