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:
yanglin 2024-06-05 18:25:49 +08:00
commit 79f561dfe8
40 changed files with 759 additions and 48 deletions

5
changelog/REQ-2324.md Normal file
View File

@ -0,0 +1,5 @@
# DDL
```mysql
ALTER TABLE todo
ADD support_batch_process VARCHAR(10) DEFAULT 'NO' NOT NULL COMMENT '是否支持批量处理. YES: 支持, NO: 不支持';
```

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,15 @@
package cn.axzo.msg.center.api.enums;
/**
* @author yanglin
*/
public enum TodoActorType {
/**
* 待办发起者
*/
TODO_PROMOTER,
/**
* 待办执行者或抄送者
*/
TODO_EXECUTOR
}

View File

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

View File

@ -31,6 +31,10 @@ public enum AppTerminalTypeEnum {
* OMS PC端
*/
OMS_WEB_PC("OMS PC端"),
/**
* 政府管理-政务
*/
PC_GA_GENERAL("政府管理-政务")
;
private final String desc;

View File

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

View File

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

View File

@ -4,8 +4,6 @@ import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 工作台类型
* @description

View File

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

View File

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

View File

@ -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获取最新代办
*

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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