Merge remote-tracking branch 'refs/remotes/origin/feature/merged_all_req'
# Conflicts: # inside-notices/src/main/java/cn/axzo/msg/center/message/domain/dto/MessageTemplateDTO.java # msg-notices/msg-notices-integration/src/main/java/cn/axzo/msg/center/notices/integration/client/impl/AliYunSmsClientImpl.java
This commit is contained in:
commit
79f561dfe8
5
changelog/REQ-2324.md
Normal file
5
changelog/REQ-2324.md
Normal file
@ -0,0 +1,5 @@
|
||||
# DDL
|
||||
```mysql
|
||||
ALTER TABLE todo
|
||||
ADD support_batch_process VARCHAR(10) DEFAULT 'NO' NOT NULL COMMENT '是否支持批量处理. YES: 支持, NO: 不支持';
|
||||
```
|
||||
@ -42,18 +42,19 @@ import cn.hutool.core.date.StopWatch;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @description
|
||||
*
|
||||
* @author cold_blade
|
||||
* @date 2023/10/5
|
||||
* @version 1.0
|
||||
* @description
|
||||
* @date 2023/10/5
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@ -194,6 +195,12 @@ public class PendingMessageNewController implements PendingMessageClient {
|
||||
return CommonResponse.success(todoManager.completeBySubBizCode(param));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResponse<Boolean> rollbackTemplateCodeSubBizCode(@RequestBody @Valid CompletePendingBySubCodeRequest param) {
|
||||
log.info("rollbackByTemplateCodeSubBizCode, request={}", JSON.toJSONString(param));
|
||||
return CommonResponse.success(todoManager.rollbackBySubBizCode(param));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResponse<Boolean> revokeByTemplateCodeBizCode(CompletePendingMessageRequest param) {
|
||||
log.info("revokeByTemplateCodeBizCode, request={}", JSON.toJSONString(param));
|
||||
@ -230,6 +237,30 @@ public class PendingMessageNewController implements PendingMessageClient {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResponse<Boolean> batchSetProcessing(List<String> identityCodes) {
|
||||
log.info("setProcessing, request={}", JSON.toJSONString(identityCodes));
|
||||
Boolean result = null;
|
||||
try {
|
||||
result = todoManager.batchSetProcessing(identityCodes, null);
|
||||
return CommonResponse.success(result);
|
||||
} finally {
|
||||
log.info("setProcessing. request={}, response={}", identityCodes, result);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResponse<Boolean> batchSetProcessingByBizCodes(List<String> subBizCodes) {
|
||||
log.info("setProcessing, request={}", JSON.toJSONString(subBizCodes));
|
||||
Boolean result = null;
|
||||
try {
|
||||
result = todoManager.batchSetProcessing(null, subBizCodes);
|
||||
return CommonResponse.success(result);
|
||||
} finally {
|
||||
log.info("setProcessing. request={}, response={}", subBizCodes, result);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResponse<Boolean> firePresetButtonPressed(PresetButtonPressedRequest req) {
|
||||
log.info("firePresetButtonPressed, request={}", JSON.toJSONString(req));
|
||||
|
||||
@ -2,10 +2,12 @@ package cn.axzo.msg.center.message.domain.dto;
|
||||
|
||||
import cn.axzo.im.center.api.feign.SendPriority;
|
||||
import cn.axzo.msg.center.domain.entity.MessageBaseTemplate;
|
||||
import cn.axzo.msg.center.message.domain.dto.MessageTemplateRouterDTO.MessageRouteButtonDTO;
|
||||
import cn.axzo.msg.center.service.dto.MessageCardContentItemDTO;
|
||||
import cn.axzo.msg.center.service.enums.BizDetailJumpStrategyEnum;
|
||||
import cn.axzo.msg.center.service.enums.MessageCategoryEnum;
|
||||
import cn.axzo.msg.center.service.enums.PushTerminalEnum;
|
||||
import cn.axzo.msg.center.service.enums.RouterCategoryEnum;
|
||||
import cn.axzo.msg.center.utils.JSONObjectUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
@ -14,6 +16,7 @@ import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
@ -107,6 +110,16 @@ public class MessageTemplateDTO implements Serializable {
|
||||
return imSendPriority == null ? SendPriority.TEMPLATE_MESSAGE.getPriority() : imSendPriority;
|
||||
}
|
||||
|
||||
public boolean hasPresetButtons() {
|
||||
if (msgTemplateRouter == null)
|
||||
return false;
|
||||
List<MessageRouteButtonDTO> buttons = msgTemplateRouter.getRouteButtons();
|
||||
if (CollectionUtils.isEmpty(buttons))
|
||||
return false;
|
||||
return buttons.stream()
|
||||
.anyMatch(btn -> btn.getCategory() == RouterCategoryEnum.PRESET_BUTTON);
|
||||
}
|
||||
|
||||
public boolean isCardJumpToBiz() {
|
||||
if (msgTemplateRouter == null) {
|
||||
return false;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package cn.axzo.msg.center.message.domain.dto;
|
||||
|
||||
import cn.axzo.msg.center.api.custombutton.ProposedButtons;
|
||||
import cn.axzo.msg.center.domain.entity.PendingMessageRecord;
|
||||
import cn.axzo.msg.center.service.dto.IdentityDTO;
|
||||
import cn.axzo.msg.center.service.dto.MessageCardContentItemDTO;
|
||||
@ -17,6 +18,7 @@ import cn.axzo.msg.center.utils.DateFormatUtil;
|
||||
import cn.axzo.msg.center.utils.MessageRouterUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
@ -170,6 +172,10 @@ public class PendingMessageDTO implements Serializable {
|
||||
* 发起人工作台名称
|
||||
*/
|
||||
private String promoterWorkspaceName;
|
||||
/**
|
||||
* 发起人企业类型
|
||||
*/
|
||||
private OrganizationTypeEnum promoterWorkspaceType;
|
||||
/**
|
||||
* 发起人企业id
|
||||
*/
|
||||
@ -182,6 +188,10 @@ public class PendingMessageDTO implements Serializable {
|
||||
* 接收人工作台名称
|
||||
*/
|
||||
private String executorWorkspaceName;
|
||||
/**
|
||||
* 执行人企业类型
|
||||
*/
|
||||
private OrganizationTypeEnum executorWorkspaceType;
|
||||
/**
|
||||
* 接收人企业id
|
||||
*/
|
||||
@ -192,6 +202,13 @@ public class PendingMessageDTO implements Serializable {
|
||||
*/
|
||||
private MessageDetailStyle detailStyle;
|
||||
|
||||
/**
|
||||
* 自定义按钮
|
||||
*/
|
||||
private ProposedButtons proposedButtons;
|
||||
|
||||
private JSONObject bizExtParamObj;
|
||||
private JSONObject routerExtParamObj;
|
||||
|
||||
@Deprecated
|
||||
public static PendingMessageDTO from(PendingMessageRecord pendingMessageRecord) {
|
||||
@ -253,10 +270,15 @@ public class PendingMessageDTO implements Serializable {
|
||||
.promoterOuId(promoterOuId)
|
||||
.promoterWorkspaceId(promoterWorkspaceId)
|
||||
.promoterWorkspaceName(promoterWorkspaceName)
|
||||
.promoterWorkspaceType(promoterWorkspaceType)
|
||||
// 接收者单位、项目信息
|
||||
.executorOuId(executorOuId)
|
||||
.executorWorkspaceId(executorWorkspaceId)
|
||||
.executorWorkspaceName(executorWorkspaceName)
|
||||
.executorWorkspaceType(executorWorkspaceType)
|
||||
// 其它信息
|
||||
.bizExtParamObj(bizExtParamObj)
|
||||
.routerExtParamObj(routerExtParamObj)
|
||||
//页面展示
|
||||
.ouId(this.ouId)
|
||||
.workspaceId(workspaceId)
|
||||
@ -266,6 +288,7 @@ public class PendingMessageDTO implements Serializable {
|
||||
.isCreatedToday(isCreatedToday)
|
||||
.isRead(isRead)
|
||||
.todoType(todoType)
|
||||
.proposedButtons(proposedButtons)
|
||||
.templateCategory(templateCategory)
|
||||
.identityCode(this.identityCode)
|
||||
.templateCode(this.templateCode)
|
||||
|
||||
@ -12,6 +12,7 @@ import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description
|
||||
@ -48,6 +49,10 @@ public class MessageGroupNodeStatisticParam implements Serializable {
|
||||
* false: 否
|
||||
*/
|
||||
private Boolean withIdentify;
|
||||
/**
|
||||
* 项目部id列表
|
||||
*/
|
||||
private List<Long> workspaceIds;
|
||||
|
||||
public Long getPersonId() {
|
||||
return getOperator().getId();
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
package cn.axzo.msg.center.message.domain.param;
|
||||
|
||||
import cn.axzo.core.utils.converter.BeanConverter;
|
||||
import cn.axzo.msg.center.api.custombutton.ProposedButtons;
|
||||
import cn.axzo.msg.center.api.request.v3.PendingSendInfo;
|
||||
import cn.axzo.msg.center.service.dto.PersonDTO;
|
||||
import cn.axzo.msg.center.service.enums.OrganizationTypeEnum;
|
||||
import cn.axzo.msg.center.service.enums.YesOrNo;
|
||||
import cn.axzo.msg.center.service.pending.request.PendingMessagePushRequest;
|
||||
import cn.axzo.msg.center.service.util.JSONUtils;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
@ -78,6 +80,20 @@ public class PendingMessagePushParam extends PendingSendInfo implements Serializ
|
||||
*/
|
||||
private String routerParams;
|
||||
|
||||
/**
|
||||
* 是否支持批量处理
|
||||
*/
|
||||
private YesOrNo supportBatchProcess;
|
||||
|
||||
/**
|
||||
* 提前设定的按钮
|
||||
*/
|
||||
private ProposedButtons proposedButtons;
|
||||
|
||||
public ProposedButtons determineProposedButtons() {
|
||||
return proposedButtons == null ? new ProposedButtons() : proposedButtons;
|
||||
}
|
||||
|
||||
public static PendingMessagePushParam from(PendingMessagePushRequest request) {
|
||||
return BeanConverter.convert(request, PendingMessagePushParam.class);
|
||||
}
|
||||
|
||||
@ -763,10 +763,12 @@ public class PendingMessageNewServiceImpl implements PendingMessageNewService {
|
||||
pendingMessage.setPromoterOuId(adapter.getPromoterOuId());
|
||||
pendingMessage.setPromoterWorkspaceId(adapter.getPromoterOrgId());
|
||||
pendingMessage.setPromoterWorkspaceName(adapter.getPromoterOrgName());
|
||||
pendingMessage.setPromoterWorkspaceType(adapter.getPromoterOrgType());
|
||||
// 接收者单位、项目信息
|
||||
pendingMessage.setExecutorOuId(adapter.getOuId());
|
||||
pendingMessage.setExecutorWorkspaceId(adapter.getOrgId());
|
||||
pendingMessage.setExecutorWorkspaceName(adapter.getOrgName());
|
||||
pendingMessage.setExecutorWorkspaceType(adapter.getExecutorOrgType());
|
||||
// 兼容页面老逻辑
|
||||
pendingMessage.setOuId(adapter.getOuId());
|
||||
pendingMessage.setWorkspaceId(adapter.getPromoterOrgId());
|
||||
@ -778,6 +780,9 @@ public class PendingMessageNewServiceImpl implements PendingMessageNewService {
|
||||
// 其它信息
|
||||
pendingMessage.setTodoType(adapter.getTodoType());
|
||||
pendingMessage.setIsRead(adapter.isRead());
|
||||
pendingMessage.setProposedButtons(adapter.getCustomButtons());
|
||||
pendingMessage.setBizExtParamObj(adapter.getBizExtParamObj());
|
||||
pendingMessage.setRouterExtParamObj(adapter.getRouterParamObj());
|
||||
|
||||
Map<String, MessageTemplateDTO> templateCode2Template = messageTemplates.stream()
|
||||
.collect(toMap(MessageTemplateDTO::getCode, identity()));
|
||||
@ -838,7 +843,7 @@ public class PendingMessageNewServiceImpl implements PendingMessageNewService {
|
||||
res.setTerminalId(response.getWorkspaceId());
|
||||
res.setTerminalName(response.getWorkspaceName());
|
||||
res.setTerminalType(MsgRecordTerminalTypeEnum.valueOf(response.getOrganizationType().name()));
|
||||
res.setState(MsgStateEnum.getByCode(response.getState().getCode()));
|
||||
res.setState(MsgStateEnum.getByCode(response.getState().getDeprecatedCode()));
|
||||
res.setMsgTimestamp(DateFormatUtil.toTimestamp(response.getCreateTime()));
|
||||
res.setRouterParam(response.getRouterParam());
|
||||
buildRouter(res, response.getMsgTemplateRouter(), terminalType);
|
||||
|
||||
@ -81,8 +81,7 @@ public class TodoRangeQueryService {
|
||||
if (CollectionUtils.isEmpty(templateCodes))
|
||||
return AnalysisPage.emptyPage(request.getPage(), request.getPageSize());
|
||||
AnalysisPage<PendingRecordAdapter> pageResult;
|
||||
if (request.determineToDoType() == TodoType.EXECUTABLE
|
||||
&& request.getRoleCategory() == PendingMessageRoleCategoryEnum.PROMOTER)
|
||||
if (request.isQueryBusiness())
|
||||
// 我发起的
|
||||
pageResult = pageQueryBusiness(request, templateCodes);
|
||||
else
|
||||
@ -137,6 +136,8 @@ public class TodoRangeQueryService {
|
||||
// 查询的待办类型: COPIED_TO_ME, EXECUTABLE
|
||||
.eq(Todo::getType, request.determineToDoType())
|
||||
.eq(Todo::getExecutorPersonId, request.getPersonId())
|
||||
//判断是否支持批量过滤
|
||||
.eq(request.getSupportBatchProcess() != null, Todo::getSupportBatchProcess, request.getSupportBatchProcess())
|
||||
// like search
|
||||
.and(StringUtils.isNotBlank(request.getTitle()), nested -> nested
|
||||
.like(Todo::getTitle, request.getTitle())
|
||||
@ -300,6 +301,7 @@ public class TodoRangeQueryService {
|
||||
LambdaQueryWrapper<Todo> query = todoQuery(ouInfo)
|
||||
.in(Todo::getTemplateCode, templateCodes)
|
||||
.eq(Todo::getExecutorPersonId, request.getPersonId())
|
||||
.in(CollectionUtils.isNotEmpty(request.getWorkspaceIds()), Todo::getOrgId, request.getWorkspaceIds())
|
||||
.and(todoType == TodoType.EXECUTABLE, nested -> nested
|
||||
.eq(Todo::getType, TodoType.EXECUTABLE)
|
||||
.eq(Todo::getState, PendingMessageStateEnum.HAS_BEEN_SENT))
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package cn.axzo.msg.center.message.service.todo;
|
||||
|
||||
import cn.axzo.msg.center.api.custombutton.ProposedButtons;
|
||||
import cn.axzo.msg.center.common.utils.BizAssertions;
|
||||
import cn.axzo.msg.center.domain.entity.PendingRecordAdapter;
|
||||
import cn.axzo.msg.center.domain.entity.PendingRecordExt;
|
||||
@ -25,13 +26,12 @@ public class TodoRecordAdapter implements PendingRecordAdapter {
|
||||
|
||||
private final TodoBusiness business;
|
||||
private final Todo todo;
|
||||
// 查询我发起的待办的时候, 不返回subBizCode, 不然流程那边处理按钮会出现问题(当发起人同时也是执行人时)
|
||||
private final boolean useNullSubBizCode;
|
||||
private final boolean forBusiness;
|
||||
|
||||
private TodoRecordAdapter(TodoBusiness business, Todo todo, boolean useNullSubBizCode) {
|
||||
private TodoRecordAdapter(TodoBusiness business, Todo todo, boolean forBusiness) {
|
||||
this.business = business;
|
||||
this.todo = todo;
|
||||
this.useNullSubBizCode = useNullSubBizCode;
|
||||
this.forBusiness = forBusiness;
|
||||
}
|
||||
|
||||
public static TodoRecordAdapter adaptBusiness(TodoBusiness business, Todo todo) {
|
||||
@ -126,6 +126,11 @@ public class TodoRecordAdapter implements PendingRecordAdapter {
|
||||
return business.getOrgType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrganizationTypeEnum getExecutorOrgType() {
|
||||
return todo.getOrgType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPromoterOrgName() {
|
||||
return business.getOrgName();
|
||||
@ -168,7 +173,7 @@ public class TodoRecordAdapter implements PendingRecordAdapter {
|
||||
|
||||
@Override
|
||||
public String getSubBizCode() {
|
||||
return useNullSubBizCode ? "" : todo.getSubBizCode();
|
||||
return forBusiness ? "" : todo.getSubBizCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -247,4 +252,9 @@ public class TodoRecordAdapter implements PendingRecordAdapter {
|
||||
public TodoBusiness getTodoBusiness() {
|
||||
return business;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProposedButtons getCustomButtons() {
|
||||
return forBusiness ? business.getProposedButtons() : todo.getProposedButtons();
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,8 @@ import org.springframework.stereotype.Component;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
@ -95,10 +97,11 @@ public class NodeStatCache {
|
||||
|
||||
private static String buildCacheKey(MessageGroupNodeStatisticParam request) {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append("msg-center:node-stat:v2");
|
||||
buf.append("msg-center:node-stat:v3");
|
||||
Consumer<Object> appender = value -> {
|
||||
if (value != null)
|
||||
if (value != null) {
|
||||
buf.append(":").append(value);
|
||||
}
|
||||
};
|
||||
appender.accept(request.getPersonId());
|
||||
appender.accept(request.getOuId());
|
||||
@ -112,6 +115,14 @@ public class NodeStatCache {
|
||||
.sorted()
|
||||
.forEach(appender);
|
||||
}
|
||||
List<Long> workspaceIds = request.getWorkspaceIds();
|
||||
if (CollectionUtils.isNotEmpty(workspaceIds)) {
|
||||
workspaceIds.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.sorted()
|
||||
.forEach(appender);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,8 @@ import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapp
|
||||
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@ -41,6 +43,24 @@ class StateAdvanceBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
StateAdvanceBuilder in(SFunction<Todo, ?> column, Object... values) {
|
||||
query.in(column, values);
|
||||
update.in(column, values);
|
||||
boolean statePresent = Stream.of(values).anyMatch(v -> v instanceof PendingMessageStateEnum);
|
||||
if (!statePresent)
|
||||
noStateQuery.in(column, values);
|
||||
return this;
|
||||
}
|
||||
|
||||
StateAdvanceBuilder in(boolean condition, SFunction<Todo, ?> column, Object... values) {
|
||||
query.in(condition, column, values);
|
||||
update.in(condition, column, values);
|
||||
boolean statePresent = Stream.of(values).anyMatch(v -> v instanceof PendingMessageStateEnum);
|
||||
if (!statePresent)
|
||||
noStateQuery.in(condition, column, values);
|
||||
return this;
|
||||
}
|
||||
|
||||
StateAdvanceBuilder set(SFunction<Todo, ?> column, Object val) {
|
||||
update.set(column, val);
|
||||
return this;
|
||||
|
||||
@ -40,6 +40,16 @@ class TodoLogger {
|
||||
logTodosUpdated(ctx, todos);
|
||||
}
|
||||
|
||||
void logSetTodoProcessing(TodoRequestContext ctx, List<Todo> todos) {
|
||||
ctx.addLogContent("state", PendingMessageStateEnum.PROCESSING);
|
||||
logTodosUpdated(ctx, todos);
|
||||
}
|
||||
|
||||
void logTodoRollback(TodoRequestContext ctx, List<Todo> todos) {
|
||||
ctx.addLogContent("state", PendingMessageStateEnum.HAS_BEEN_SENT);
|
||||
logTodosUpdated(ctx, todos);
|
||||
}
|
||||
|
||||
void logTodoRevoked(TodoRequestContext ctx, List<Todo> todos) {
|
||||
ctx.addLogContent("state", PendingMessageStateEnum.RETRACT);
|
||||
logTodosUpdated(ctx, todos);
|
||||
|
||||
@ -17,8 +17,10 @@ import cn.axzo.msg.center.message.service.todo.manage.event.NewTodoEvent;
|
||||
import cn.axzo.msg.center.mq.MqMessageRecord;
|
||||
import cn.axzo.msg.center.mq.MqMessageType;
|
||||
import cn.axzo.msg.center.mq.MqProducer;
|
||||
import cn.axzo.msg.center.service.enums.MessageCategoryEnum;
|
||||
import cn.axzo.msg.center.service.enums.PendingMessageStateEnum;
|
||||
import cn.axzo.msg.center.service.enums.TodoType;
|
||||
import cn.axzo.msg.center.service.enums.YesOrNo;
|
||||
import cn.axzo.msg.center.service.pending.request.CompletePendingBySubCodeRequest;
|
||||
import cn.axzo.msg.center.service.pending.request.CompletePendingMessageByIdRequest;
|
||||
import cn.axzo.msg.center.service.pending.request.CompletePendingMessageRequest;
|
||||
@ -32,6 +34,7 @@ import cn.axzo.msg.center.service.util.JSONUtils;
|
||||
import cn.axzo.msg.center.utils.DateFormatUtil;
|
||||
import cn.axzo.msg.center.utils.QueryFormatter;
|
||||
import cn.axzo.msg.center.utils.UUIDUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.google.common.base.Supplier;
|
||||
@ -126,6 +129,13 @@ public class TodoManager {
|
||||
log.warn("Found duplicated business. Found business={}, request={}", business, request, e);
|
||||
}
|
||||
}
|
||||
//批量默认为false
|
||||
YesOrNo supportBatchProcess = request.getSupportBatchProcess() == null ? YesOrNo.NO : request.getSupportBatchProcess();
|
||||
//业务待办设置是否批量处理
|
||||
if (template.getMsgCategory() == MessageCategoryEnum.BIZ_PENDING_MESSAGE
|
||||
&& template.hasPresetButtons())
|
||||
supportBatchProcess = YesOrNo.YES;
|
||||
request.setSupportBatchProcess(supportBatchProcess);
|
||||
List<Todo> todos = todoRecordBuilder.buildTodos(
|
||||
request, ctx.getRequestNo(), ext, business);
|
||||
todoDao.saveBatch(todos);
|
||||
@ -262,6 +272,24 @@ public class TodoManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复待办
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean rollbackBySubBizCode(CompletePendingBySubCodeRequest request) {
|
||||
TodoRequestContext ctx = TodoRequestContext.create("rollbackBySubBizCode", request);
|
||||
StateAdvanceResult advanceResult = advanceState(ctx, execAdvanceBuilder()
|
||||
.eq(Todo::getTemplateCode, request.getTemplateCode())
|
||||
.eq(Todo::getBizCode, request.getBizCode())
|
||||
.eq(Todo::getSubBizCode, request.getSubBizCode())
|
||||
.set(Todo::getState, PendingMessageStateEnum.HAS_BEEN_SENT));
|
||||
if (!advanceResult.isAdvanced()) {
|
||||
return false;
|
||||
}
|
||||
todoLogger.logTodoRollback(ctx, advanceResult.getAdvancedTodos());
|
||||
return true;
|
||||
}
|
||||
|
||||
// !! revoke
|
||||
|
||||
/**
|
||||
@ -354,6 +382,22 @@ public class TodoManager {
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将待办设置为执行中
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean batchSetProcessing(List<String> identityCodes, List<String> subBizCodes) {
|
||||
log.info("batch set processing...,request:{}", JSONUtil.toJsonStr(identityCodes));
|
||||
BizAssertions.assertTrue(CollectionUtils.isNotEmpty(identityCodes), "identityCodes列表不能为空");
|
||||
Boolean updated = todoDao.batchSetExecutableProcessing(identityCodes, subBizCodes);
|
||||
if (updated) {
|
||||
List<Todo> updatedTodos = todoDao.getByIdentityCodes(identityCodes);
|
||||
TodoRequestContext ctx = TodoRequestContext.create("batchSetProcessing", identityCodes);
|
||||
todoLogger.logSetTodoProcessing(ctx, updatedTodos);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新待办的内容
|
||||
*/
|
||||
@ -531,7 +575,9 @@ public class TodoManager {
|
||||
return new StateAdvanceBuilder(todoDao)
|
||||
.set(Todo::getHideUntil, null)
|
||||
.eq(Todo::getType, TodoType.EXECUTABLE)
|
||||
.eq(Todo::getState, PendingMessageStateEnum.HAS_BEEN_SENT)
|
||||
.in(Todo::getState,
|
||||
PendingMessageStateEnum.HAS_BEEN_SENT,
|
||||
PendingMessageStateEnum.PROCESSING)
|
||||
.eq(Todo::getIsDelete, TableIsDeleteEnum.NORMAL.value);
|
||||
}
|
||||
|
||||
|
||||
@ -70,6 +70,9 @@ class TodoRecordBuilder {
|
||||
business.setRouterParams(ext.parseRouterExtParams());
|
||||
business.setDeadline(request.getDeadline());
|
||||
business.setBizFinalState(null);
|
||||
// 不能存成null, 因为老的流程数据没有传这个按钮, 需要做查询兼容
|
||||
// 是否为老的流程数据, 主要判断这个字段是否为null
|
||||
business.setProposedButtons(request.determineProposedButtons());
|
||||
return business;
|
||||
}
|
||||
|
||||
@ -105,11 +108,15 @@ class TodoRecordBuilder {
|
||||
todo.setBizDesc(request.getBizDesc());
|
||||
todo.setIsOuIdMigrated(YesOrNo.NO);
|
||||
todo.setHideUntil(null);
|
||||
todo.setSupportBatchProcess(request.getSupportBatchProcess());
|
||||
todo.setState(request.determineTodoType() == TodoType.COPIED_TO_ME
|
||||
? PendingMessageStateEnum.CREATED
|
||||
: PendingMessageStateEnum.HAS_BEEN_SENT);
|
||||
todo.setExecutorId(executor.identityIdOrDefault());
|
||||
todo.setExecutorType(executor.identityTypeOrDefault());
|
||||
// 不能存成null, 因为老的流程数据没有传这个按钮, 需要做查询兼容
|
||||
// 是否为老的流程数据, 主要判断这个字段是否为null
|
||||
todo.setProposedButtons(request.determineProposedButtons());
|
||||
}
|
||||
return todos;
|
||||
}
|
||||
|
||||
@ -29,11 +29,13 @@ public abstract class PageQuerySort<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SFunction<TodoBusiness, ?> getSortField(SortField field) {
|
||||
protected SFunction<TodoBusiness, ?> getCustomSortField(SortField field) {
|
||||
if (field == SortField.CREATE_AT)
|
||||
return TodoBusiness::getCreateAt;
|
||||
else if (field == SortField.UPDATE_AT)
|
||||
return TodoBusiness::getUpdateAt;
|
||||
else if (field == SortField.ID)
|
||||
return TodoBusiness::getId;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
@ -52,11 +54,13 @@ public abstract class PageQuerySort<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SFunction<Todo, ?> getSortField(SortField field) {
|
||||
protected SFunction<Todo, ?> getCustomSortField(SortField field) {
|
||||
if (field == SortField.CREATE_AT)
|
||||
return Todo::getCreateAt;
|
||||
else if (field == SortField.UPDATE_AT)
|
||||
return Todo::getUpdateAt;
|
||||
else if (field == SortField.ID)
|
||||
return Todo::getId;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
@ -65,11 +69,11 @@ public abstract class PageQuerySort<T> {
|
||||
|
||||
public final void appendSortExpr(
|
||||
PendingMessagePageRequest req, LambdaQueryWrapper<T> query) {
|
||||
if (!req.useCustomSort() || !appendRequestSortExpr(query, req.getOrderFields()))
|
||||
if (!req.useCustomSort() || !appendCustomSortExpr(query, req.getOrderFields()))
|
||||
appendDefaultSortExpr(req, query);
|
||||
}
|
||||
|
||||
private boolean appendRequestSortExpr(
|
||||
private boolean appendCustomSortExpr(
|
||||
LambdaQueryWrapper<T> query, Collection<QueryOrderByDTO> fields) {
|
||||
if (CollectionUtils.isEmpty(fields))
|
||||
return false;
|
||||
@ -77,14 +81,14 @@ public abstract class PageQuerySort<T> {
|
||||
for (QueryOrderByDTO reqField : fields) {
|
||||
SortField sortField = SortField.findByCode(reqField.getOrderField());
|
||||
if (sortField == null) continue;
|
||||
SFunction<T, ?> recordField = getSortField(sortField);
|
||||
if (recordField == null) continue;
|
||||
SFunction<T, ?> customRecordField = getCustomSortField(sortField);
|
||||
if (customRecordField == null) continue;
|
||||
customSortUsed = true;
|
||||
boolean isAsc = reqField.getIsAsc() != null && reqField.getIsAsc();
|
||||
if (isAsc)
|
||||
query.orderByAsc(recordField);
|
||||
query.orderByAsc(customRecordField);
|
||||
else
|
||||
query.orderByDesc(recordField);
|
||||
query.orderByDesc(customRecordField);
|
||||
}
|
||||
return customSortUsed;
|
||||
}
|
||||
@ -99,7 +103,7 @@ public abstract class PageQuerySort<T> {
|
||||
/**
|
||||
* 获取请求中传的排序字段
|
||||
*/
|
||||
abstract SFunction<T, ?> getSortField(SortField field);
|
||||
abstract SFunction<T, ?> getCustomSortField(SortField field);
|
||||
|
||||
/**
|
||||
* 排序字段
|
||||
@ -108,7 +112,8 @@ public abstract class PageQuerySort<T> {
|
||||
protected enum SortField {
|
||||
|
||||
CREATE_AT("createTimestamp"),
|
||||
UPDATE_AT("updateTimestamp");
|
||||
UPDATE_AT("updateTimestamp"),
|
||||
ID("id");
|
||||
|
||||
final String code;
|
||||
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
package cn.axzo.msg.center.api.custombutton;
|
||||
|
||||
import cn.axzo.msg.center.service.enums.RouterButtonSourceEnum;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 提前设定的按钮
|
||||
*
|
||||
* @author yanglin
|
||||
*/
|
||||
@Data
|
||||
public class ProposedButton {
|
||||
/**
|
||||
* 自定义按钮的key
|
||||
*/
|
||||
private String buttonKey;
|
||||
/**
|
||||
* 自定义按钮的名称
|
||||
*/
|
||||
private String buttonName;
|
||||
/**
|
||||
* 按钮类型
|
||||
*/
|
||||
private RouterButtonSourceEnum source;
|
||||
/**
|
||||
* 提前设定的按钮配置
|
||||
*/
|
||||
private List<ProposedButtonConfig> configs;
|
||||
|
||||
public List<ProposedButtonConfig> determineConfigs() {
|
||||
return configs == null ? Collections.emptyList() : configs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建按钮
|
||||
*/
|
||||
public static ProposedButton createButton(String buttonKey, ProposedButtonConfig... configs) {
|
||||
ProposedButton proposedButton = new ProposedButton();
|
||||
proposedButton.setButtonKey(buttonKey);
|
||||
proposedButton.setConfigs(configs == null ? Collections.emptyList() : Arrays.asList(configs));
|
||||
return proposedButton;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建按钮
|
||||
*/
|
||||
public static ProposedButton createButton(String buttonKey, List<ProposedButtonConfig> configs) {
|
||||
ProposedButton proposedButton = new ProposedButton();
|
||||
proposedButton.setButtonKey(buttonKey);
|
||||
proposedButton.setConfigs(configs);
|
||||
return proposedButton;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,135 @@
|
||||
package cn.axzo.msg.center.api.custombutton;
|
||||
|
||||
import cn.axzo.msg.center.api.enums.TodoActorType;
|
||||
import cn.axzo.msg.center.service.enums.BizFinalStateEnum;
|
||||
import cn.axzo.msg.center.service.enums.CodeDefinition;
|
||||
import cn.axzo.msg.center.service.enums.PendingMessageStateEnum;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
|
||||
/**
|
||||
* 提前设定的按钮配置
|
||||
*
|
||||
* @author yanglin
|
||||
*/
|
||||
@Data
|
||||
public class ProposedButtonConfig {
|
||||
|
||||
/**
|
||||
* 适用的按钮的角色
|
||||
*/
|
||||
private TodoActorType actorType;
|
||||
/**
|
||||
* 按钮可见的状态. 没有传则忽略状态, 都可见
|
||||
*/
|
||||
private Set<String> visibleStates;
|
||||
|
||||
/**
|
||||
* 创建对待办发起人总是可见的按钮, 忽略业务最终状态
|
||||
*/
|
||||
public static ProposedButtonConfig alwaysVisibleForPromoter() {
|
||||
return visibleForPromoterAndBizStates(Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建对待办发起人总是可见的按钮, 忽略待办状态
|
||||
*/
|
||||
public static ProposedButtonConfig alwaysVisibleForExecutor() {
|
||||
return visibleForExecutorAndTodoStates(Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建待办发起者按钮. 根据状态来控制可见性
|
||||
*
|
||||
* @param visibleBizFinalStates 按钮可见的状态. 为空则忽略状态, 都可见
|
||||
*/
|
||||
public static ProposedButtonConfig visibleForPromoterAndBizStates(BizFinalStateEnum... visibleBizFinalStates) {
|
||||
BizFinalStateEnum[] states = visibleBizFinalStates;
|
||||
if (states == null)
|
||||
states = new BizFinalStateEnum[0];
|
||||
return visibleForPromoterAndBizStates(Arrays.asList(states));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建待办执行者按钮. 根据状态来控制可见性
|
||||
*
|
||||
* @param visibleTodoStates 按钮可见的状态. 为空则忽略状态, 都可见
|
||||
*/
|
||||
public static ProposedButtonConfig visibleForExecutorAndTodoStates(PendingMessageStateEnum... visibleTodoStates) {
|
||||
PendingMessageStateEnum[] states = visibleTodoStates;
|
||||
if (states == null)
|
||||
states = new PendingMessageStateEnum[0];
|
||||
return visibleForExecutorAndTodoStates(Arrays.asList(states));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建待办发起者按钮. 根据状态来控制可见性
|
||||
*
|
||||
* @param visibleBizFinalStates 按钮可见的状态. 为空则忽略状态, 都可见
|
||||
*/
|
||||
public static ProposedButtonConfig visibleForPromoterAndBizStates(List<BizFinalStateEnum> visibleBizFinalStates) {
|
||||
ProposedButtonConfig proposedButtonConfig = new ProposedButtonConfig();
|
||||
proposedButtonConfig.setActorType(TodoActorType.TODO_PROMOTER);
|
||||
if (visibleBizFinalStates != null) {
|
||||
Set<String> visibleStates = visibleBizFinalStates.stream()
|
||||
.map(Enum::name)
|
||||
.collect(toSet());
|
||||
proposedButtonConfig.setVisibleStates(visibleStates);
|
||||
}
|
||||
return proposedButtonConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建待办执行者按钮. 根据状态来控制可见性
|
||||
*
|
||||
* @param visibleTodoStates 按钮可见的状态. 为空则忽略状态, 都可见
|
||||
*/
|
||||
public static ProposedButtonConfig visibleForExecutorAndTodoStates(List<PendingMessageStateEnum> visibleTodoStates) {
|
||||
ProposedButtonConfig proposedButtonConfig = new ProposedButtonConfig();
|
||||
proposedButtonConfig.setActorType(TodoActorType.TODO_EXECUTOR);
|
||||
if (visibleTodoStates != null) {
|
||||
Set<String> visibleStates = visibleTodoStates.stream()
|
||||
.map(Enum::name)
|
||||
.collect(toSet());
|
||||
proposedButtonConfig.setVisibleStates(visibleStates);
|
||||
}
|
||||
return proposedButtonConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断待办发起者按钮是否可见
|
||||
*/
|
||||
public boolean isVisible(BizFinalStateEnum state) {
|
||||
// 没有指定状态, 一直可见
|
||||
if (CollectionUtils.isEmpty(visibleStates))
|
||||
return true;
|
||||
return visibleStates.stream()
|
||||
.map(code -> CodeDefinition.findByCode(BizFinalStateEnum.class, code))
|
||||
.filter(Optional::isPresent)
|
||||
.map(Optional::get)
|
||||
.anyMatch(s -> s == state);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断待办执行者按钮是否可见
|
||||
*/
|
||||
public boolean isVisible(PendingMessageStateEnum state) {
|
||||
// 没有指定状态, 一直可见
|
||||
if (CollectionUtils.isEmpty(visibleStates))
|
||||
return true;
|
||||
return visibleStates.stream()
|
||||
.map(code -> CodeDefinition.findByCode(PendingMessageStateEnum.class, code))
|
||||
.filter(Optional::isPresent)
|
||||
.map(Optional::get)
|
||||
.anyMatch(s -> s == state);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package cn.axzo.msg.center.api.custombutton;
|
||||
|
||||
import cn.axzo.msg.center.service.dto.ButtonRouterDTO;
|
||||
import cn.axzo.msg.center.service.enums.RouterButtonSourceEnum;
|
||||
import cn.axzo.msg.center.service.pending.response.PendingMessageResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class ProposedButtonFilter {
|
||||
|
||||
public static void adjustProposedButtons(PendingMessageResponse response, boolean forPromoter) {
|
||||
response.setButtonRouters(filterProposedButtons(response, forPromoter));
|
||||
}
|
||||
|
||||
public static List<ButtonRouterDTO> filterProposedButtons(PendingMessageResponse response, boolean forPromoter) {
|
||||
ProposedButtons buttons = response.getProposedButtons();
|
||||
Function<String, Boolean> isConfiguredProposedBtnFun = btnKey -> {
|
||||
if (buttons == null || CollectionUtils.isEmpty(buttons.getConfiguredButtonKeys()))
|
||||
return false;
|
||||
return buttons.getConfiguredButtonKeys().contains(btnKey);
|
||||
};
|
||||
Function<String, ProposedButton> findProposedBtnFun = btnKey -> {
|
||||
if (buttons == null || CollectionUtils.isEmpty(buttons.getProposedButtons()))
|
||||
return null;
|
||||
return buttons.getProposedButtons().stream()
|
||||
.filter(i -> btnKey.equals(i.getButtonKey()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
};
|
||||
Function<ButtonRouterDTO, Boolean> syncBtnFun = btn -> {
|
||||
// 没有配置可见的自定义的按钮
|
||||
ProposedButton proposedBtn = findProposedBtnFun.apply(btn.getKey());
|
||||
if (proposedBtn == null || CollectionUtils.isEmpty(proposedBtn.getConfigs()))
|
||||
return false;
|
||||
return proposedBtn.getConfigs().stream()
|
||||
.anyMatch(c -> forPromoter
|
||||
? c.isVisible(response.getBizFinalState())
|
||||
: c.isVisible(response.getState()));
|
||||
};
|
||||
return response.getButtonRouters().stream()
|
||||
.filter(routerBtn -> {
|
||||
ProposedButton proposedBtn = findProposedBtnFun.apply(routerBtn.getKey());
|
||||
boolean isNormalCustomBtn = proposedBtn == null
|
||||
&& !isConfiguredProposedBtnFun.apply(routerBtn.getKey())
|
||||
&& routerBtn.getSource() == RouterButtonSourceEnum.CUSTOM;
|
||||
return isNormalCustomBtn || syncBtnFun.apply(routerBtn);
|
||||
})
|
||||
.collect(toList());
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package cn.axzo.msg.center.api.custombutton;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@Data
|
||||
public class ProposedButtons {
|
||||
/**
|
||||
* 所有配置的按钮key
|
||||
*/
|
||||
private Set<String> configuredButtonKeys;
|
||||
/**
|
||||
* 提前设定的按钮
|
||||
*/
|
||||
private List<ProposedButton> proposedButtons;
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package cn.axzo.msg.center.api.enums;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
public enum TodoActorType {
|
||||
/**
|
||||
* 待办发起者
|
||||
*/
|
||||
TODO_PROMOTER,
|
||||
/**
|
||||
* 待办执行者或抄送者
|
||||
*/
|
||||
TODO_EXECUTOR
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package cn.axzo.msg.center.api.response.v3;
|
||||
|
||||
import cn.axzo.msg.center.api.custombutton.ProposedButton;
|
||||
import cn.axzo.msg.center.service.enums.BizCategoryEnum;
|
||||
import cn.axzo.msg.center.service.enums.BizFinalStateEnum;
|
||||
import cn.axzo.msg.center.service.enums.IdentityTypeEnum;
|
||||
@ -12,6 +13,7 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
@ -162,4 +164,9 @@ public class SearchPendingMessageResp {
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateAt;
|
||||
|
||||
/**
|
||||
* 自定义按钮
|
||||
*/
|
||||
private List<ProposedButton> proposedButtons;
|
||||
}
|
||||
|
||||
@ -31,6 +31,10 @@ public enum AppTerminalTypeEnum {
|
||||
* OMS PC端
|
||||
*/
|
||||
OMS_WEB_PC("OMS PC端"),
|
||||
/**
|
||||
* 政府管理-政务
|
||||
*/
|
||||
PC_GA_GENERAL("政府管理-政务")
|
||||
;
|
||||
|
||||
private final String desc;
|
||||
|
||||
@ -14,7 +14,7 @@ import lombok.Getter;
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public enum BizFinalStateEnum {
|
||||
public enum BizFinalStateEnum implements CodeDefinition<String> {
|
||||
|
||||
/**
|
||||
* 已处理
|
||||
@ -38,4 +38,9 @@ public enum BizFinalStateEnum {
|
||||
ABORTED("https://axzo-public.oss-cn-chengdu.aliyuncs.com/%E5%8D%B0%E7%AB%A0-%E8%AF%A6%E6%83%85end.png");
|
||||
|
||||
private final String icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return name();
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,7 @@
|
||||
package cn.axzo.msg.center.service.enums;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@ -17,4 +19,15 @@ public interface CodeDefinition<T> {
|
||||
return code.equals(this.getCode());
|
||||
}
|
||||
|
||||
}
|
||||
static <T, E extends Enum<E> & CodeDefinition<T>>
|
||||
Optional<E> findByCode(Class<E> enumType, T code) {
|
||||
if (code == null)
|
||||
return Optional.empty();
|
||||
for (E e : enumType.getEnumConstants()) {
|
||||
if (e.getCode().equals(code))
|
||||
return Optional.of(e);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
||||
@ -4,8 +4,6 @@ import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 工作台类型
|
||||
* @description
|
||||
|
||||
@ -16,7 +16,7 @@ import java.util.Objects;
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public enum PendingMessageStateEnum {
|
||||
public enum PendingMessageStateEnum implements CodeDefinition<String> {
|
||||
|
||||
CREATED(0, "创建"),
|
||||
UNSENT(1, "未发送"),
|
||||
@ -25,15 +25,21 @@ public enum PendingMessageStateEnum {
|
||||
RETRACT(6, "已撤回"),
|
||||
DELETED(7, "已删除"),
|
||||
READ(8, "已读"),
|
||||
PROCESSING(9, "处理中")
|
||||
;
|
||||
|
||||
private final Integer code;
|
||||
private final Integer deprecatedCode;
|
||||
private final String message;
|
||||
|
||||
public static PendingMessageStateEnum codeOf(Integer code) {
|
||||
return Arrays.stream(values())
|
||||
.filter(e -> Objects.equals(e.code, code))
|
||||
.filter(e -> Objects.equals(e.deprecatedCode, code))
|
||||
.findFirst()
|
||||
.orElse(HAS_BEEN_SENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return name();
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ import lombok.Getter;
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public enum RouterButtonSourceEnum {
|
||||
public enum RouterButtonSourceEnum implements CodeDefinition<String> {
|
||||
|
||||
/**
|
||||
* 系统
|
||||
@ -21,4 +21,9 @@ public enum RouterButtonSourceEnum {
|
||||
* 自定义
|
||||
*/
|
||||
CUSTOM;
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return name();
|
||||
}
|
||||
}
|
||||
|
||||
@ -228,6 +228,15 @@ public interface PendingMessageClient {
|
||||
@PostMapping(value = "/pending-message/complete/by-sub-biz-code", produces = {MediaType.APPLICATION_JSON_VALUE})
|
||||
CommonResponse<Boolean> completeByTemplateCodeSubBizCode(@RequestBody @Valid CompletePendingBySubCodeRequest param);
|
||||
|
||||
/**
|
||||
* 通过模版编号和业务编号和子业务编号恢复代办
|
||||
*
|
||||
* @param param
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(value = "/pending-message/rollback/by-sub-biz-code", produces = {MediaType.APPLICATION_JSON_VALUE})
|
||||
CommonResponse<Boolean> rollbackTemplateCodeSubBizCode(@RequestBody @Valid CompletePendingBySubCodeRequest param);
|
||||
|
||||
/**
|
||||
* 通过模版编号和业务编号撤销代办
|
||||
*
|
||||
@ -261,6 +270,15 @@ public interface PendingMessageClient {
|
||||
@PostMapping(value = "/pending-message/update/setHide", produces = {MediaType.APPLICATION_JSON_VALUE})
|
||||
CommonResponse<Boolean> setHide(@RequestBody @Valid SetHideRequest req);
|
||||
|
||||
/**
|
||||
* 批量将待办设置为处理中
|
||||
*/
|
||||
@PostMapping(value = "/pending-message/update/batchSetProcessing", produces = {MediaType.APPLICATION_JSON_VALUE})
|
||||
CommonResponse<Boolean> batchSetProcessing(@RequestBody List<String> identityCodes);
|
||||
|
||||
@PostMapping(value = "/pending-message/update/batchSetProcessingByBizCodes", produces = {MediaType.APPLICATION_JSON_VALUE})
|
||||
CommonResponse<Boolean> batchSetProcessingByBizCodes(@RequestBody List<String> subBizCodes);
|
||||
|
||||
/**
|
||||
* 通过BizCode获取最新代办
|
||||
*
|
||||
|
||||
@ -10,6 +10,7 @@ import cn.axzo.msg.center.service.enums.PendingMessageStateEnum;
|
||||
import cn.axzo.msg.center.service.enums.TerminalTypeEnum;
|
||||
import cn.axzo.msg.center.service.enums.TodoQueryType;
|
||||
import cn.axzo.msg.center.service.enums.TodoType;
|
||||
import cn.axzo.msg.center.service.enums.YesOrNo;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
@ -136,6 +137,11 @@ public class PendingMessagePageRequest extends PageRequest implements Serializab
|
||||
*/
|
||||
private TodoQueryType queryType;
|
||||
|
||||
/**
|
||||
* 是否支持批量处理
|
||||
*/
|
||||
private YesOrNo supportBatchProcess;
|
||||
|
||||
// !! 用于排查问题
|
||||
private String analysisToken;
|
||||
private String todoCode;
|
||||
@ -178,6 +184,11 @@ public class PendingMessagePageRequest extends PageRequest implements Serializab
|
||||
return CollectionUtils.isNotEmpty(orderFields);
|
||||
}
|
||||
|
||||
public boolean isQueryBusiness() {
|
||||
return determineToDoType() == TodoType.EXECUTABLE
|
||||
&& getRoleCategory() == PendingMessageRoleCategoryEnum.PROMOTER;
|
||||
}
|
||||
|
||||
public TodoType determineToDoType() {
|
||||
return todoType == null ? TodoType.EXECUTABLE : todoType;
|
||||
}
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
package cn.axzo.msg.center.service.pending.request;
|
||||
|
||||
import cn.axzo.msg.center.api.custombutton.ProposedButtons;
|
||||
import cn.axzo.msg.center.service.dto.PersonDTO;
|
||||
import cn.axzo.msg.center.service.enums.BizCategoryEnum;
|
||||
import cn.axzo.msg.center.service.enums.BizFinalStateEnum;
|
||||
import cn.axzo.msg.center.service.enums.OrganizationTypeEnum;
|
||||
import cn.axzo.msg.center.service.enums.TodoType;
|
||||
import cn.axzo.msg.center.service.enums.YesOrNo;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
@ -125,6 +127,16 @@ public class PendingMessagePushRequest implements Serializable {
|
||||
*/
|
||||
private Long promoterWorkspaceId;
|
||||
|
||||
/**
|
||||
* 提前设定的按钮
|
||||
*/
|
||||
private ProposedButtons proposedButtons;
|
||||
|
||||
/**
|
||||
* 是否支持批量处理
|
||||
*/
|
||||
private YesOrNo supportBatchProcess;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JSON.toJSONString(this);
|
||||
|
||||
@ -9,13 +9,13 @@ import lombok.Setter;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description
|
||||
*
|
||||
* @author cold_blade
|
||||
* @date 2023/9/23
|
||||
* @version 1.0
|
||||
* @description
|
||||
* @date 2023/9/23
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@ -49,6 +49,11 @@ public class PendingMessageStatisticRequest implements Serializable {
|
||||
*/
|
||||
private AppTerminalTypeEnum terminalType;
|
||||
|
||||
/**
|
||||
* 项目部id列表
|
||||
*/
|
||||
private List<Long> workspaceIds;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JSON.toJSONString(this);
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
package cn.axzo.msg.center.service.pending.response;
|
||||
|
||||
import cn.axzo.basics.common.util.AssertUtil;
|
||||
import cn.azxo.framework.common.model.Page;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
@ -61,6 +63,16 @@ public class AnalysisPage<T> extends Page<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public void addAnalysis(String key, Object... fields) {
|
||||
if (!enableAnalysis) return;
|
||||
AssertUtil.notNull(fields, "Fields can't be null");
|
||||
AssertUtil.isTrue(fields.length % 2 == 0, "The length of fields must be an integer multiple of 2");
|
||||
Map<String, Object> fieldsObj = new HashMap<>();
|
||||
for (int i = 0; i < fields.length; i += 2)
|
||||
fieldsObj.put(String.valueOf(fields[i]), fields[i + 1]);
|
||||
addAnalysis(key, fieldsObj);
|
||||
}
|
||||
|
||||
public void setAnalysis(TreeMap<String, Object> analysis) {
|
||||
this.analysis = analysis;
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package cn.axzo.msg.center.service.pending.response;
|
||||
|
||||
import cn.axzo.msg.center.api.custombutton.ProposedButtonFilter;
|
||||
import cn.axzo.msg.center.api.custombutton.ProposedButtons;
|
||||
import cn.axzo.msg.center.service.dto.ButtonRouterDTO;
|
||||
import cn.axzo.msg.center.service.dto.DetailRouterDTO;
|
||||
import cn.axzo.msg.center.service.dto.IdentityDTO;
|
||||
@ -7,30 +9,35 @@ import cn.axzo.msg.center.service.dto.MessageCardContentItemDTO;
|
||||
import cn.axzo.msg.center.service.enums.BizCategoryEnum;
|
||||
import cn.axzo.msg.center.service.enums.BizFinalStateEnum;
|
||||
import cn.axzo.msg.center.service.enums.MessageCategoryEnum;
|
||||
import cn.axzo.msg.center.service.enums.OrganizationTypeEnum;
|
||||
import cn.axzo.msg.center.service.enums.PendingMessageStateEnum;
|
||||
import cn.axzo.msg.center.service.enums.TodoQueryType;
|
||||
import cn.axzo.msg.center.service.enums.TodoType;
|
||||
import cn.axzo.msg.center.service.template.response.MessageDetailStyle;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.*;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description
|
||||
* 代办消息记录页面展示数模型
|
||||
* @author cold_blade
|
||||
* @date 2023/9/23
|
||||
* @version 1.0
|
||||
* @description 代办消息记录页面展示数模型
|
||||
* @date 2023/9/23
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PendingMessageResponse implements Serializable {
|
||||
public class PendingMessageResponse implements Serializable, TodoButtonProvider {
|
||||
|
||||
private static final long serialVersionUID = -4133864010679470398L;
|
||||
|
||||
@ -120,6 +127,10 @@ public class PendingMessageResponse implements Serializable {
|
||||
* 发起人工作台名称
|
||||
*/
|
||||
private String promoterWorkspaceName;
|
||||
/**
|
||||
* 发起人企业类型
|
||||
*/
|
||||
private OrganizationTypeEnum promoterWorkspaceType;
|
||||
/**
|
||||
* 发起人企业id
|
||||
*/
|
||||
@ -132,6 +143,10 @@ public class PendingMessageResponse implements Serializable {
|
||||
* 接收人工作台名称
|
||||
*/
|
||||
private String executorWorkspaceName;
|
||||
/**
|
||||
* 执行人企业类型
|
||||
*/
|
||||
private OrganizationTypeEnum executorWorkspaceType;
|
||||
/**
|
||||
* 接收人企业id
|
||||
*/
|
||||
@ -203,15 +218,33 @@ public class PendingMessageResponse implements Serializable {
|
||||
|
||||
/**
|
||||
* 查询类型
|
||||
* HAS_BEEN_SENT: 待处理
|
||||
* COMPLETED: 已处理
|
||||
* SEND_BY_ME: 我发起
|
||||
* COPIED_TO_ME: 抄送我
|
||||
* HAS_BEEN_SENT: 待处理
|
||||
* COMPLETED: 已处理
|
||||
* SEND_BY_ME: 我发起
|
||||
* COPIED_TO_ME: 抄送我
|
||||
*/
|
||||
private TodoQueryType queryType;
|
||||
|
||||
/**
|
||||
* 业务类型
|
||||
*/
|
||||
private BizCategoryEnum bizCategoryEnum;
|
||||
|
||||
/**
|
||||
* 自定义按钮
|
||||
*/
|
||||
private ProposedButtons proposedButtons;
|
||||
|
||||
private JSONObject bizExtParamObj;
|
||||
private JSONObject routerExtParamObj;
|
||||
|
||||
public void adjustProposedButtons(boolean forPromoter) {
|
||||
ProposedButtonFilter.adjustProposedButtons(this, forPromoter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JSON.toJSONString(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
package cn.axzo.msg.center.service.pending.response;
|
||||
|
||||
import cn.axzo.msg.center.api.custombutton.ProposedButtons;
|
||||
import cn.axzo.msg.center.service.dto.ButtonRouterDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
public interface TodoButtonProvider {
|
||||
|
||||
List<ButtonRouterDTO> getButtonRouters();
|
||||
|
||||
ProposedButtons getProposedButtons();
|
||||
|
||||
}
|
||||
@ -49,6 +49,13 @@ public class TodoDao extends ServiceImpl<TodoMapper, Todo> {
|
||||
.list();
|
||||
}
|
||||
|
||||
public List<Todo> getByIdentityCodes(List<String> identityCodes) {
|
||||
return lambdaQuery()
|
||||
.eq(Todo::getIdentityCode, identityCodes)
|
||||
.eq(Todo::getIsDelete, TableIsDeleteEnum.NORMAL.value)
|
||||
.list();
|
||||
}
|
||||
|
||||
public Optional<Todo> getLatestByBiz(
|
||||
@Nullable String templateCode, String bizCode, String subBizCode, TodoType todoType) {
|
||||
if (StringUtils.isBlank(bizCode) && StringUtils.isBlank(subBizCode))
|
||||
@ -98,6 +105,19 @@ public class TodoDao extends ServiceImpl<TodoMapper, Todo> {
|
||||
return new SampleTodos(todos);
|
||||
}
|
||||
|
||||
public Boolean batchSetExecutableProcessing(List<String> identityCodes, List<String> subBizCodes) {
|
||||
if (CollectionUtils.isEmpty(identityCodes) && CollectionUtils.isEmpty(subBizCodes)) {
|
||||
throw new IllegalArgumentException("identityCodes and subBizCodes can't be empty");
|
||||
}
|
||||
return lambdaUpdate()
|
||||
.eq(Todo::getType, TodoType.EXECUTABLE)
|
||||
.in(CollectionUtils.isNotEmpty(identityCodes), Todo::getIdentityCode, identityCodes)
|
||||
.in(CollectionUtils.isNotEmpty(subBizCodes), Todo::getSubBizCode, subBizCodes)
|
||||
.in(Todo::getState, PendingMessageStateEnum.HAS_BEEN_SENT, PendingMessageStateEnum.PROCESSING)
|
||||
.set(Todo::getState, PendingMessageStateEnum.PROCESSING)
|
||||
.update();
|
||||
}
|
||||
|
||||
public boolean setExecutableHide(String subBizCode, Date expireTime) {
|
||||
return lambdaUpdate()
|
||||
.eq(Todo::getType, TodoType.EXECUTABLE)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package cn.axzo.msg.center.domain.entity;
|
||||
|
||||
import cn.axzo.msg.center.api.custombutton.ProposedButtons;
|
||||
import cn.axzo.msg.center.service.enums.BizCategoryEnum;
|
||||
import cn.axzo.msg.center.service.enums.BizFinalStateEnum;
|
||||
import cn.axzo.msg.center.service.enums.IdentityTypeEnum;
|
||||
@ -7,6 +8,9 @@ import cn.axzo.msg.center.service.enums.OrganizationTypeEnum;
|
||||
import cn.axzo.msg.center.service.enums.PendingMessageStateEnum;
|
||||
import cn.axzo.msg.center.service.enums.TodoType;
|
||||
import cn.axzo.msg.center.service.enums.YesOrNo;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ -99,6 +103,10 @@ public interface PendingRecordAdapter {
|
||||
return null;
|
||||
}
|
||||
|
||||
default OrganizationTypeEnum getExecutorOrgType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
default String getPromoterOrgName() {
|
||||
return "";
|
||||
}
|
||||
@ -114,4 +122,21 @@ public interface PendingRecordAdapter {
|
||||
default TodoBusiness getTodoBusiness() {
|
||||
return null;
|
||||
}
|
||||
|
||||
default ProposedButtons getCustomButtons() {
|
||||
return null;
|
||||
}
|
||||
|
||||
default JSONObject getBizExtParamObj() {
|
||||
return parseJsonObj(getBizExtParam());
|
||||
}
|
||||
|
||||
default JSONObject getRouterParamObj() {
|
||||
return parseJsonObj(getRouterParams());
|
||||
}
|
||||
|
||||
static JSONObject parseJsonObj(String json) {
|
||||
return StringUtils.isBlank(json) ? new JSONObject() : JSON.parseObject(json);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package cn.axzo.msg.center.domain.entity;
|
||||
|
||||
import cn.axzo.msg.center.api.custombutton.ProposedButtons;
|
||||
import cn.axzo.msg.center.domain.persistence.BaseEntityExt;
|
||||
import cn.axzo.msg.center.domain.utils.IgnorePropsJsonTypeHandler;
|
||||
import cn.axzo.msg.center.service.enums.IdentityTypeEnum;
|
||||
@ -146,12 +147,23 @@ public class Todo extends BaseEntityExt<Todo> {
|
||||
*/
|
||||
private YesOrNo isOuIdMigrated;
|
||||
|
||||
/**
|
||||
* 是否支持批量处理
|
||||
*/
|
||||
private YesOrNo supportBatchProcess;
|
||||
|
||||
/**
|
||||
* 保存额外的数据信息
|
||||
*/
|
||||
@TableField(typeHandler = IgnorePropsJsonTypeHandler.class)
|
||||
private PendingRecordExt recordExt = new PendingRecordExt();
|
||||
|
||||
/**
|
||||
* 自定义按钮
|
||||
*/
|
||||
@TableField(typeHandler = IgnorePropsJsonTypeHandler.class)
|
||||
private ProposedButtons proposedButtons;
|
||||
|
||||
// !! helper
|
||||
|
||||
@Override
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package cn.axzo.msg.center.domain.entity;
|
||||
|
||||
import cn.axzo.msg.center.api.custombutton.ProposedButtons;
|
||||
import cn.axzo.msg.center.domain.persistence.BaseEntityExt;
|
||||
import cn.axzo.msg.center.domain.utils.IgnorePropsJsonTypeHandler;
|
||||
import cn.axzo.msg.center.service.enums.BizCategoryEnum;
|
||||
@ -125,6 +126,12 @@ public class TodoBusiness extends BaseEntityExt<TodoBusiness> {
|
||||
@TableField(typeHandler = IgnorePropsJsonTypeHandler.class)
|
||||
private TodoBusinessExt recordExt = new TodoBusinessExt();
|
||||
|
||||
/**
|
||||
* 自定义按钮
|
||||
*/
|
||||
@TableField(typeHandler = IgnorePropsJsonTypeHandler.class)
|
||||
private ProposedButtons proposedButtons;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JSON.toJSONString(this);
|
||||
|
||||
@ -23,14 +23,12 @@ public class IgnorePropsJsonTypeHandler extends AbstractJsonTypeHandler<Object>
|
||||
@Override
|
||||
protected Object parse(String json) {
|
||||
if (StringUtils.isBlank(json))
|
||||
return JSON.parseObject("{}", type);
|
||||
return null;
|
||||
return JSON.parseObject(json, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String toJson(Object obj) {
|
||||
if (obj == null)
|
||||
return "{}";
|
||||
return JSON.toJSONString(obj);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package cn.axzo.msg.center.notices.integration.dto.request;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@ -31,4 +32,9 @@ public class SendSmsCommonRequest {
|
||||
/** 渠道请求号 */
|
||||
private String requestChannelNo;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JSON.toJSONString(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user