Merge branch 'feature/REQ-3282'
# Conflicts: # inside-notices/src/main/java/cn/axzo/msg/center/message/migrate/OuIdMigrateService.java
This commit is contained in:
commit
cf988d0e5e
@ -21,6 +21,11 @@
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.axzo.org</groupId>
|
||||
<artifactId>org-api</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.axzo.epic</groupId>
|
||||
<artifactId>epic-api</artifactId>
|
||||
@ -184,6 +189,10 @@
|
||||
<version>3.5.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.axzo.msgcenter</groupId>
|
||||
<artifactId>msg-center-api-v2</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@ -0,0 +1,36 @@
|
||||
package cn.axzo.msg.center.inside.notices.service.impl.v2;
|
||||
|
||||
import cn.axzo.foundation.result.ApiResult;
|
||||
import cn.axzo.msg.center.api.request.v3.MessageSendReqV3;
|
||||
import cn.axzo.msg.center.api.response.v3.MessageSendRespV3;
|
||||
import cn.axzo.msg.center.api.v2.message.feign.MessageApiV2;
|
||||
import cn.axzo.msg.center.api.v2.message.req.MessageSendV2Req;
|
||||
import cn.axzo.msg.center.api.v2.message.resp.MessageSendV2Resp;
|
||||
import cn.axzo.msg.center.inside.notices.service.MessageServiceV3;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author : zhanghonghao@axzo.cn
|
||||
* @since : 2024/12/13
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
public class MessageApiV2Controller implements MessageApiV2 {
|
||||
|
||||
private final MessageServiceV3 messageServiceV3;
|
||||
|
||||
@Override
|
||||
public ApiResult<MessageSendV2Resp> send(MessageSendV2Req req) {
|
||||
log.info("MessageAPIV3Controller.send req={}", req);
|
||||
MessageSendReqV3 sendReqV3 = new MessageSendReqV3();
|
||||
BeanUtils.copyProperties(req, sendReqV3);
|
||||
MessageSendRespV3 sendRespV3 = messageServiceV3.send(sendReqV3);
|
||||
MessageSendV2Resp sendV2Resp = new MessageSendV2Resp();
|
||||
BeanUtils.copyProperties(sendRespV3, sendV2Resp);
|
||||
return ApiResult.success(sendV2Resp);
|
||||
}
|
||||
}
|
||||
@ -1,244 +0,0 @@
|
||||
package cn.axzo.msg.center.message.migrate;
|
||||
|
||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
||||
import cn.axzo.maokai.api.client.OrganizationalTeamOuRelationApi;
|
||||
import cn.axzo.maokai.api.vo.response.OrganizationalTeamOuRelationResp;
|
||||
import cn.axzo.msg.center.common.utils.BizAssertions;
|
||||
import cn.axzo.msg.center.dal.PendingMessageRecordDao;
|
||||
import cn.axzo.msg.center.domain.entity.PendingMessageRecord;
|
||||
import cn.axzo.msg.center.domain.entity.PendingRecordExt;
|
||||
import cn.axzo.msg.center.domain.enums.YesNoEnum;
|
||||
import cn.axzo.msg.center.domain.persistence.BaseEntityExt;
|
||||
import cn.axzo.msg.center.service.enums.YesOrNo;
|
||||
import cn.axzo.pluto.api.TeamServiceApi;
|
||||
import cn.axzo.pluto.teams.common.enums.UserTerminalPerspective;
|
||||
import cn.azxo.framework.common.model.CommonResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.google.common.collect.Lists;
|
||||
import jodd.util.concurrent.ThreadFactoryBuilder;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class OuIdMigrateService {
|
||||
|
||||
private static final String MIGRATE_OU_CURSOR = "msg_center_migrate_ou_cursor";
|
||||
|
||||
private final RedisTemplate<Object, Object> redisTemplate;
|
||||
private final PendingMessageRecordDao pendingMessageRecordDao;
|
||||
private final OrganizationalTeamOuRelationApi organizationalTeamOuRelationApi;
|
||||
private final TeamServiceApi teamServiceApi;
|
||||
|
||||
@Value("${message.pending.ouMigrateBatchSize:100}")
|
||||
private final Long migrateBatchSize;
|
||||
|
||||
@Getter
|
||||
private volatile boolean isRunning;
|
||||
|
||||
|
||||
|
||||
private final ThreadFactory moduleStatisticTaskThreadFactory = ThreadFactoryBuilder.create()
|
||||
.setDaemon(true)
|
||||
.setNameFormat("MODULE_STATISTIC_TASK_%d")
|
||||
.get();
|
||||
private final ExecutorService taskThreadPool = new ThreadPoolExecutor(20, 100, 10, TimeUnit.SECONDS,
|
||||
new ArrayBlockingQueue<>(2000), moduleStatisticTaskThreadFactory);
|
||||
|
||||
public void migrate(List<PendingMessageRecord> records) {
|
||||
try {
|
||||
String ids = records.stream()
|
||||
.map(BaseEntityExt::getId)
|
||||
.map(String::valueOf)
|
||||
.collect(joining(","));
|
||||
log.info("start - migrate ou id: {}", ids);
|
||||
// 迁移ou_id=0的
|
||||
// 逻辑: 通过身份查询人默认的班组,获取到班组后,再获取班组对应的团队,取团队的id
|
||||
migrateZeroOuId(records);
|
||||
log.info("end - migrate ou id: {}", ids);
|
||||
} catch (Exception e) {
|
||||
log.warn("ouId fail", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void migrateZeroOuId(List<PendingMessageRecord> records) throws ExecutionException, InterruptedException {
|
||||
// 业务发送待办时未传ouId
|
||||
List<PendingMessageRecord> zeroOuIdRecords = records.stream()
|
||||
.filter(i -> i.getOuId().equals(0L))
|
||||
.collect(toList());
|
||||
if (zeroOuIdRecords.isEmpty()) {
|
||||
log.info("updateOuIdJob migrate is empty");
|
||||
return;
|
||||
}
|
||||
|
||||
List<List<PendingMessageRecord>> partitions = Lists
|
||||
.partition(zeroOuIdRecords, 20);
|
||||
List<CompletableFuture> futures = new ArrayList<>();
|
||||
for (int i = 0; i < partitions.size(); i++) {
|
||||
List<PendingMessageRecord> dataList = partitions.get(i);
|
||||
futures.add(CompletableFuture.runAsync(() ->
|
||||
updateZero(dataList), taskThreadPool));
|
||||
}
|
||||
CompletableFuture.allOf(futures.stream().toArray(CompletableFuture[]::new)).get();
|
||||
}
|
||||
|
||||
private void updateZero(List<PendingMessageRecord> records) {
|
||||
List<PendingMessageRecord> update = records.stream()
|
||||
.map(record -> {
|
||||
try {
|
||||
log.info("zeroOuId, record:{}", record.getId());
|
||||
Long identityId = record.getExecutorId();
|
||||
|
||||
DefaultTeamInfo defaultTeam = getDefaultTeamId(identityId);
|
||||
log.info("zeroOuId, record:{}, defaultTeam:{}", record.getId(), JSONObject.toJSONString(defaultTeam));
|
||||
if (defaultTeam == null) {
|
||||
PendingMessageRecord pendingMessageRecord = new PendingMessageRecord();
|
||||
pendingMessageRecord.setId(record.getId());
|
||||
pendingMessageRecord.setIsDelete(YesNoEnum.YES.getCode().longValue());
|
||||
return pendingMessageRecord;
|
||||
}
|
||||
|
||||
Map<Long, OrganizationalTeamOuRelationResp> teamId2OuInfo =
|
||||
getOuInfoByTeamId(Lists.newArrayList(defaultTeam.teamId));
|
||||
OrganizationalTeamOuRelationResp teamInfo = teamId2OuInfo.get(defaultTeam.teamId);
|
||||
log.info("zeroOuId, record:{}, teamInfo:{}", record.getId(), JSONObject.toJSONString(teamInfo));
|
||||
if (teamInfo == null) {
|
||||
PendingMessageRecord pendingMessageRecord = new PendingMessageRecord();
|
||||
pendingMessageRecord.setId(record.getId());
|
||||
pendingMessageRecord.setIsDelete(YesNoEnum.YES.getCode().longValue());
|
||||
return pendingMessageRecord;
|
||||
} else {
|
||||
return tryUpdate(record, teamInfo.getOuId(), String.format(
|
||||
"找到了默认团队, 并通过身份id找到默认团队, 再找到对应的单位. teamId=%d, ouId=%d, 视角=%s, 视角type=%s",
|
||||
defaultTeam.teamId, teamInfo.getOuId(), defaultTeam.perspectiveDesc, defaultTeam.perspective));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("ouId fail, recordId:{}; e:{}", record.getId(), e);
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(toList());
|
||||
List<Long> removeIds = update.stream()
|
||||
.filter(record -> Objects.equals(record.getIsDelete(), YesNoEnum.YES.getCode().longValue()))
|
||||
.map(PendingMessageRecord::getId)
|
||||
.collect(toList());
|
||||
if (!CollectionUtils.isEmpty(removeIds)) {
|
||||
pendingMessageRecordDao.removeByIds(removeIds);
|
||||
}
|
||||
|
||||
List<PendingMessageRecord> updates = update.stream()
|
||||
.filter(record -> !Objects.equals(record.getIsDelete(), YesNoEnum.YES.getCode().longValue()))
|
||||
.collect(toList());
|
||||
if (!CollectionUtils.isEmpty(updates)) {
|
||||
pendingMessageRecordDao.updateBatchById(updates);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private DefaultTeamInfo getDefaultTeamId(Long identityId) {
|
||||
Integer successCode = 200;
|
||||
CommonResponse<Long> resp1 = teamServiceApi.getDefaultTeam(
|
||||
identityId, UserTerminalPerspective.LEADER_PERSPECTIVE.code);
|
||||
if (successCode.equals(resp1.getCode())) {
|
||||
return new DefaultTeamInfo(resp1.getData(), UserTerminalPerspective.LEADER_PERSPECTIVE, "工人端-班组长视角");
|
||||
}
|
||||
CommonResponse<Long> resp2 = teamServiceApi.getDefaultTeam(
|
||||
identityId, UserTerminalPerspective.CMP_LEADER_PERSPECTIVE.code);
|
||||
if (successCode.equals(resp2.getCode())) {
|
||||
return new DefaultTeamInfo(resp2.getData(), UserTerminalPerspective.CMP_LEADER_PERSPECTIVE, "管理端-班b组长视角");
|
||||
}
|
||||
CommonResponse<Long> resp3 = teamServiceApi.getDefaultTeam(
|
||||
identityId, UserTerminalPerspective.WORKER_PERSPECTIVE.code);
|
||||
if (successCode.equals(resp3.getCode())) {
|
||||
return new DefaultTeamInfo(resp3.getData(), UserTerminalPerspective.WORKER_PERSPECTIVE, "工人端-工人视角");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Map<Long, OrganizationalTeamOuRelationResp> getOuInfoByTeamId(List<Long> maybeTeamIds) {
|
||||
ApiResult<List<OrganizationalTeamOuRelationResp>> maybeTeamIdsResp =
|
||||
organizationalTeamOuRelationApi.getByTeamOuIds(Lists.newArrayList(maybeTeamIds));
|
||||
return BizAssertions
|
||||
.assertResponse(maybeTeamIdsResp, "can't get plat team info").stream()
|
||||
.collect(Collectors.toMap(OrganizationalTeamOuRelationResp::getTeamOuId, Function.identity()));
|
||||
}
|
||||
|
||||
private PendingMessageRecord tryUpdate(PendingMessageRecord record, Long newOuId, String ouIdMigrateDesc) {
|
||||
PendingRecordExt ext = record.getRecordExt();
|
||||
if (ext == null)
|
||||
ext = new PendingRecordExt();
|
||||
if (record.getIsOuIdMigrated() == YesOrNo.YES)
|
||||
return null;
|
||||
// 找不到的newOuId不进行更新
|
||||
if (newOuId == null || newOuId == 0 ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 最原始的ouId不要被覆盖了
|
||||
if (ext.getMigrateOu().getOriginalOuId() != null)
|
||||
ext.getMigrateOu().setOriginalOuId(record.getOuId());
|
||||
ext.getMigrateOu().setOuIdMigrateTime(new Date());
|
||||
ext.getMigrateOu().setOuIdMigrateDesc(ouIdMigrateDesc);
|
||||
|
||||
PendingMessageRecord update = new PendingMessageRecord();
|
||||
update.setId(record.getId());
|
||||
update.setOuId(newOuId);
|
||||
update.setRecordExt(ext);
|
||||
update.setUpdateAt(new Date());
|
||||
update.setIsOuIdMigrated(YesOrNo.YES);
|
||||
log.warn("migrating pending record's ouId field. pending message id={}, originalOuId={}, newOuId={}",
|
||||
record.getId(), record.getOuId(), newOuId);
|
||||
return update;
|
||||
}
|
||||
|
||||
@Data
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Param {
|
||||
private List<Long> migrateRecordIds;
|
||||
private boolean scanMigrate;
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
private static class DefaultTeamInfo {
|
||||
private final Long teamId;
|
||||
private final UserTerminalPerspective perspective;
|
||||
private final String perspectiveDesc;
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,6 @@
|
||||
package cn.axzo.msg.center.message.service.impl;
|
||||
|
||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
||||
import cn.axzo.maokai.api.client.OrganizationalTeamOuRelationApi;
|
||||
import cn.axzo.maokai.api.vo.response.OrganizationalTeamOuRelationResp;
|
||||
import cn.axzo.foundation.result.ApiResult;
|
||||
import cn.axzo.msg.center.common.enums.TableIsDeleteEnum;
|
||||
import cn.axzo.msg.center.common.utils.BizAssertions;
|
||||
import cn.axzo.msg.center.dal.MessageGroupNodeDao;
|
||||
@ -10,6 +8,8 @@ import cn.axzo.msg.center.domain.entity.MessageGroupNode;
|
||||
import cn.axzo.msg.center.domain.persistence.BaseEntityExt;
|
||||
import cn.axzo.msg.center.inside.notices.config.PendingMessageBizConfig;
|
||||
import cn.axzo.msg.center.service.enums.AppTerminalTypeEnum;
|
||||
import cn.axzo.orggateway.api.orgteamourelation.OrgTeamOuRelationApi;
|
||||
import cn.axzo.orggateway.api.orgteamourelation.resp.OrgTeamOuRelationResp;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -39,7 +39,7 @@ import static java.util.stream.Collectors.toSet;
|
||||
@RequiredArgsConstructor
|
||||
public class PendingMessageNewServiceImpl {
|
||||
|
||||
private final OrganizationalTeamOuRelationApi organizationalTeamOuRelationApi;
|
||||
private final OrgTeamOuRelationApi orgTeamOuRelationApi;
|
||||
private final PendingMessageBizConfig pendingMessageBizConfig;
|
||||
private final MessageGroupNodeDao messageGroupNodeDao;
|
||||
|
||||
@ -82,12 +82,12 @@ public class PendingMessageNewServiceImpl {
|
||||
ouIds.add(ouId);
|
||||
// 2. 查询ouId下面所有的平台班组id当成ouId
|
||||
if (ouId != 0) {
|
||||
ApiResult<List<OrganizationalTeamOuRelationResp>> resp =
|
||||
organizationalTeamOuRelationApi.teamOuRelationList(ouId);
|
||||
List<OrganizationalTeamOuRelationResp> relations =
|
||||
ApiResult<List<OrgTeamOuRelationResp>> resp =
|
||||
orgTeamOuRelationApi.teamOuRelationList(ouId);
|
||||
List<OrgTeamOuRelationResp> relations =
|
||||
BizAssertions.assertResponse(resp, "获取平台班组id失败");
|
||||
relations.stream()
|
||||
.map(OrganizationalTeamOuRelationResp::getTeamOuId)
|
||||
.map(OrgTeamOuRelationResp::getTeamOuId)
|
||||
.distinct()
|
||||
.forEach(ouIds::add);
|
||||
}
|
||||
|
||||
47
msg-center-api-v2/pom.xml
Normal file
47
msg-center-api-v2/pom.xml
Normal file
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<artifactId>msg-center</artifactId>
|
||||
<groupId>cn.axzo.msgcenter</groupId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>msg-center-api-v2</artifactId>
|
||||
<version>${msg-center-api-v2-version}</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.axzo.foundation</groupId>
|
||||
<artifactId>common-lib</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@ -0,0 +1,14 @@
|
||||
package cn.axzo.msg.center.api.v2.config;
|
||||
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author : zhanghonghao@axzo.cn
|
||||
* @since : 2024/12/10
|
||||
*/
|
||||
@Configuration
|
||||
@EnableFeignClients(basePackages = "cn.axzo.msg.center.api.v2.**.feign")
|
||||
public class MsgCenterApiV2Config {
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package cn.axzo.msg.center.api.v2.message.feign;
|
||||
|
||||
import cn.axzo.foundation.result.ApiResult;
|
||||
import cn.axzo.msg.center.api.v2.message.req.MessageSendV2Req;
|
||||
import cn.axzo.msg.center.api.v2.message.resp.MessageSendV2Resp;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
@FeignClient(
|
||||
value = "msg-center",
|
||||
url = "${axzo.service.msg-center:http://msg-center:8080}")
|
||||
public interface MessageApiV2 {
|
||||
|
||||
@PostMapping(value = "api/message/v2/send")
|
||||
ApiResult<MessageSendV2Resp> send(@RequestBody @Valid MessageSendV2Req req);
|
||||
|
||||
}
|
||||
@ -0,0 +1,167 @@
|
||||
package cn.axzo.msg.center.api.v2.message.req;
|
||||
|
||||
import cn.axzo.basics.common.util.AssertUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@Slf4j
|
||||
public class MessageSendV2Req implements Serializable {
|
||||
|
||||
/**
|
||||
* 发送待办时, channelParams 的 key, 传值 {@link PendingSendInfo}
|
||||
*/
|
||||
public static final String CHANNEL_PENDING = "channel_pending";
|
||||
|
||||
/**
|
||||
* 发起者
|
||||
* <p>如果是平台,则发起人为空
|
||||
*/
|
||||
private PersonV2DTO sender;
|
||||
|
||||
/**
|
||||
* 接收者列表
|
||||
*/
|
||||
@NotNull(message = "接收者列表不能为空")
|
||||
private List<PersonV2DTO> receivers;
|
||||
|
||||
/**
|
||||
* 业务事件code
|
||||
* oms->消息模板 配置
|
||||
*/
|
||||
@NotBlank(message = "业务事件code不能为空")
|
||||
private String bizEventMappingCode;
|
||||
|
||||
/**
|
||||
* 关联业务唯一标识
|
||||
* 例如: 请假申请的编号
|
||||
*/
|
||||
private String bizCode;
|
||||
|
||||
/**
|
||||
* 业务扩展参数-JSON字符串格式
|
||||
*/
|
||||
private JSONObject bizExtParams;
|
||||
|
||||
/**
|
||||
* 路由参数-JSON字符串格式
|
||||
*/
|
||||
private JSONObject routerParams;
|
||||
|
||||
/**
|
||||
* 发送者项目部ID
|
||||
*/
|
||||
private Long senderWorkspaceId;
|
||||
|
||||
/**
|
||||
* 发送者企业ID
|
||||
*/
|
||||
private Long senderOuId;
|
||||
|
||||
/**
|
||||
* 接收者项目部ID
|
||||
*/
|
||||
private Long receiversWorkspaceId;
|
||||
|
||||
/**
|
||||
* 接收者企业ID
|
||||
* <p>如果是工人,则所在企业可以为空;其它均必传
|
||||
*/
|
||||
private Long receiversOuId;
|
||||
|
||||
/**
|
||||
* 接收者(消息)所属组织类型
|
||||
*/
|
||||
private Integer receiversOrgType;
|
||||
|
||||
/**
|
||||
* 副标题
|
||||
*/
|
||||
private String subtitle;
|
||||
|
||||
/**
|
||||
* 渠道参数
|
||||
*/
|
||||
private JSONObject channelParams;
|
||||
|
||||
public void addChannelParam(String key, Object object) {
|
||||
if (channelParams == null) {
|
||||
channelParams = new JSONObject();
|
||||
}
|
||||
channelParams.put(key, object);
|
||||
}
|
||||
|
||||
public <T> T getChannelParam(String key, Class<T> asType) {
|
||||
if (channelParams == null) {
|
||||
return null;
|
||||
}
|
||||
if (!channelParams.containsKey(key)) {
|
||||
return null;
|
||||
}
|
||||
return channelParams.getObject(key, asType);
|
||||
}
|
||||
|
||||
public Collection<PersonV2DTO> distinctReceivers() {
|
||||
if (receivers == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
HashMap<Long, PersonV2DTO> personId2Person = new HashMap<>();
|
||||
for (PersonV2DTO receiver : receivers) {
|
||||
if (!personId2Person.containsKey(receiver.getId())) {
|
||||
personId2Person.put(receiver.getId(), receiver);
|
||||
}
|
||||
}
|
||||
return personId2Person.values();
|
||||
}
|
||||
|
||||
public List<PersonV2DTO> receivers() {
|
||||
if (receivers == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return receivers;
|
||||
}
|
||||
|
||||
public Long determineReceiversOuId() {
|
||||
return receiversOuId == null ? 0L : receiversOuId;
|
||||
}
|
||||
|
||||
public Long determineReceiversWorkspaceId() {
|
||||
return receiversWorkspaceId == null ? 0L : receiversWorkspaceId;
|
||||
}
|
||||
|
||||
public String determineBizCode() {
|
||||
return bizCode == null ? "" : bizCode;
|
||||
}
|
||||
|
||||
public void validate() {
|
||||
AssertUtil.notNull(bizEventMappingCode, "bizEventCode不能为空");
|
||||
AssertUtil.notEmpty(receivers, "receivers不能为空");
|
||||
|
||||
for (PersonV2DTO receiver : receivers) {
|
||||
AssertUtil.notNull(receiver.getId(), "接收者ID不能为空");
|
||||
if (receiver.getId() <= 0)
|
||||
log.warn("接收者ID <= 0, request={}", this);
|
||||
// 去掉这个校验
|
||||
//AssertUtil.isFalse(receiver.getId() <= 0, "接收者ID必须>=0");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JSONObject.toJSONString(this);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package cn.axzo.msg.center.api.v2.message.req;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PersonV2DTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1231840051925115741L;
|
||||
|
||||
public PersonV2DTO(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public PersonV2DTO(Long id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自然人id
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 姓名
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* IM消息接收模型, 可以为空
|
||||
* <p>优先使用这里的ouId, 如果这里没有传, 就使用 {@link cn.axzo.msg.center.api.request.v3.MessageSendReqV3} 中的相应的信息
|
||||
*/
|
||||
private ReceiveModel imReceiveModel;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class ReceiveModel {
|
||||
|
||||
/**
|
||||
* 接收者单位id
|
||||
*/
|
||||
private Long ouId;
|
||||
|
||||
/**
|
||||
* 接收者项目部id
|
||||
*/
|
||||
private Long workspaceId;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package cn.axzo.msg.center.api.v2.message.resp;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MessageSendResultV2 implements Serializable {
|
||||
/**
|
||||
* 接收者id
|
||||
*/
|
||||
private Long receiverPersonId;
|
||||
|
||||
/**
|
||||
* 渠道结果id
|
||||
*/
|
||||
private Long resultId;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JSON.toJSONString(this);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package cn.axzo.msg.center.api.v2.message.resp;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MessageSendV2Resp implements Serializable {
|
||||
/**
|
||||
* 这次批量发送的批次号, 如果配置了多个模版,多个渠道, 可以用批次号串联起来
|
||||
*/
|
||||
private String batchNo;
|
||||
|
||||
/**
|
||||
* 模版code -> 模版发送结果
|
||||
*/
|
||||
private Map<String, TemplateSendV2Result> templateCode2SendResult;
|
||||
|
||||
public void addResult(TemplateSendV2Result result) {
|
||||
templateCode2SendResult.put(result.getTemplateCode(), result);
|
||||
}
|
||||
|
||||
public Optional<TemplateSendV2Result> findTemplateSendResult(String templateCode) {
|
||||
return Optional.ofNullable(templateCode2SendResult.get(templateCode));
|
||||
}
|
||||
|
||||
public Set<String> templateCodes() {
|
||||
return new HashSet<>(templateCode2SendResult.keySet());
|
||||
}
|
||||
|
||||
public Map<String, TemplateSendV2Result> templateSendResults() {
|
||||
return Collections.unmodifiableMap(templateCode2SendResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JSON.toJSONString(this);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
package cn.axzo.msg.center.api.v2.message.resp;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@Data
|
||||
public class TemplateSendV2Result implements Serializable {
|
||||
/**
|
||||
* 模版编码
|
||||
*/
|
||||
private String templateCode;
|
||||
|
||||
/**
|
||||
* 渠道
|
||||
* <p>NOTIFICATION: 通知, PENDING: 待办
|
||||
*/
|
||||
private String channel;
|
||||
|
||||
/**
|
||||
* 接收者personId -> 接收人发送结果
|
||||
* key: string, 兼容json的key必须为string类型
|
||||
*/
|
||||
private Map<String, MessageSendResultV2> receiverPersonId2SendResult;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public TemplateSendV2Result() {
|
||||
}
|
||||
|
||||
public TemplateSendV2Result(String templateCode, String channel) {
|
||||
this.templateCode = templateCode;
|
||||
this.channel = channel;
|
||||
this.receiverPersonId2SendResult = new HashMap<>();
|
||||
}
|
||||
|
||||
public void addResult(MessageSendResultV2 result) {
|
||||
if (receiverPersonId2SendResult == null)
|
||||
// 序列化问题
|
||||
throw new RuntimeException("需要通过构造函数初始化receiverPersonId2SendResult");
|
||||
String receiverPersonId = String.valueOf(result.getReceiverPersonId());
|
||||
receiverPersonId2SendResult.put(receiverPersonId, result);
|
||||
}
|
||||
|
||||
public Optional<MessageSendResultV2> findResultByReceiver(Long receiverPersonId) {
|
||||
if (receiverPersonId2SendResult == null)
|
||||
return Optional.empty();
|
||||
if (receiverPersonId == null)
|
||||
return Optional.empty();
|
||||
String strReceiverPersonId = String.valueOf(receiverPersonId);
|
||||
return Optional.ofNullable(receiverPersonId2SendResult.get(strReceiverPersonId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回的数量不一定和发送请求中的receivers数量一致, 发送的时候根据receiver的personId去了重
|
||||
* <p>推荐使用 {@link #findResultByReceiver}, 根据接收者获取发送结果
|
||||
*
|
||||
* @return 所有的发送结果
|
||||
*/
|
||||
public Collection<MessageSendResultV2> messageSendResults() {
|
||||
if (receiverPersonId2SendResult == null)
|
||||
return Collections.emptyList();
|
||||
return new ArrayList<>(receiverPersonId2SendResult.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JSON.toJSONString(receiverPersonId2SendResult);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
cn.axzo.msg.center.api.v2.config.MsgCenterApiV2Config
|
||||
@ -140,4 +140,20 @@ public class BizAssertions {
|
||||
return response.getData();
|
||||
}
|
||||
|
||||
public static <T> T assertResponse(cn.axzo.foundation.result.ApiResult<T> response) {
|
||||
return assertResponse(response, "error resp={}", JSON.toJSONString(response));
|
||||
}
|
||||
|
||||
public static <T> T assertResponse(cn.axzo.foundation.result.ApiResult<T> response, String message, Object... args) {
|
||||
if (!response.isSuccess()) {
|
||||
String finalMsg = MessageFormatter.arrayFormat(message, args).getMessage();
|
||||
if (StringUtils.isNotBlank(response.getMsg())) {
|
||||
finalMsg += ": " + response.getMsg();
|
||||
}
|
||||
ServiceException e = new ServiceException(finalMsg);
|
||||
log.warn("remote call response with error. response={}", JSON.toJSONString(response), e);
|
||||
throw e;
|
||||
}
|
||||
return response.getData();
|
||||
}
|
||||
}
|
||||
7
pom.xml
7
pom.xml
@ -15,6 +15,7 @@
|
||||
<packaging>pom</packaging>
|
||||
<version>${revision}</version>
|
||||
<modules>
|
||||
<module>msg-center-api-v2</module>
|
||||
<module>wx-notices</module>
|
||||
<module>inside-notices</module>
|
||||
<module>msg-center-api</module>
|
||||
@ -32,6 +33,7 @@
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<revision>1.0.0-SNAPSHOT</revision>
|
||||
<msg-center-api-version>1.0.1-SNAPSHOT</msg-center-api-version>
|
||||
<msg-center-api-v2-version>1.0.1-SNAPSHOT</msg-center-api-v2-version>
|
||||
<axzo-bom.version>2.0.0-SNAPSHOT</axzo-bom.version>
|
||||
<axzo-dependencies.version>2.0.0-SNAPSHOT</axzo-dependencies.version>
|
||||
<lombok.version>1.18.22</lombok.version>
|
||||
@ -99,6 +101,11 @@
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>${jetbrains.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.axzo.msgcenter</groupId>
|
||||
<artifactId>msg-center-api-v2</artifactId>
|
||||
<version>${msg-center-api-v2-version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
||||
@ -28,7 +28,8 @@ import org.springframework.core.env.Environment;
|
||||
"cn.axzo.msg.center.inside.notices.service.impl",
|
||||
"cn.axzo.meepo.api",
|
||||
"cn.axzo.riven.client.feign",
|
||||
"cn.axzo.epic.client.feign"
|
||||
"cn.axzo.epic.client.feign",
|
||||
"cn.axzo.orggateway.api.orgteamourelation"
|
||||
})
|
||||
/*@EnableAsync*/
|
||||
public class MsgCenterApplication {
|
||||
|
||||
@ -1,24 +0,0 @@
|
||||
package cn.axzo.msg.center.message.migrate;
|
||||
|
||||
import cn.axzo.msg.center.MsgCenterApplication;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@SpringBootTest(classes = MsgCenterApplication.class)
|
||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||
class OuIdMigrateServiceTest {
|
||||
|
||||
private final OuIdMigrateService ouIdMigrateService;
|
||||
|
||||
@Test
|
||||
void foo() {
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user