REQ-3581: 备份

This commit is contained in:
yanglin 2025-02-18 15:21:41 +08:00
parent 83ea8da3c5
commit 880d65bb4d
11 changed files with 101 additions and 36 deletions

View File

@ -0,0 +1,27 @@
package cn.axzo.nanopart.ess.api.domain;
import cn.axzo.nanopart.ess.api.enums.ApproverAssignType;
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.NotNull;
/**
* @author yanglin
*/
@Setter @Getter
public class DynamicApproverProps {
public static DynamicApproverProps defaultProps() {
DynamicApproverProps props = new DynamicApproverProps();
props.setAssignType(ApproverAssignType.NONE);
return props;
}
/**
* 动态签署人的限制信息
*/
@NotNull(message = "assignType不能为空")
private ApproverAssignType assignType = ApproverAssignType.NONE;
}

View File

@ -21,6 +21,9 @@ public class EssApproveDetail {
*/
private Long personId;
/**
* 签署编号
*/
private String recipientId;
/**

View File

@ -4,5 +4,10 @@ package cn.axzo.nanopart.ess.api.enums;
* @author yanglin
*/
public enum ApproverAssignType {
ORG_WEIXIN_APP
// 一个子客一个用户盖章
ONE_PERSON_PER_ORG,
// 不做限制
NONE
}

View File

@ -1,5 +1,6 @@
package cn.axzo.nanopart.ess.api.request;
import cn.axzo.nanopart.ess.api.domain.DynamicApproverProps;
import cn.axzo.nanopart.ess.api.domain.contract.Approver;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
@ -32,6 +33,12 @@ public class CreateContractInfo {
*/
private boolean dynamicApprover;
/**
* 动态签署人属性
*/
@Valid
private DynamicApproverProps dynamicApproverProps;
/**
* 合同签署方
*/

View File

@ -15,6 +15,7 @@ import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
import lombok.Getter;
import lombok.Setter;
import javax.swing.table.DefaultTableCellRenderer;
import java.util.List;
/**
@ -100,6 +101,17 @@ public class EssContract extends BaseEntity<EssContract> {
@TableField(typeHandler = FastjsonTypeHandler.class)
private RecordExt recordExt;
public boolean isDynamicApprover() {
return isDynamicApprover.isYes();
}
public boolean isOrgSigned(Long ouId) {
if (approveDetails == null)
return false;
return approveDetails.stream()
.anyMatch(detail -> detail.getOuId().equals(ouId));
}
public int preciseApproverSize() {
return approvers.size();
}

View File

@ -13,6 +13,6 @@ public class AssignedApprovers {
private ApproverAssignType assignType;
private SignByOrg signByOrg;
private SignByOrg signByOrg = new SignByOrg();
}

View File

@ -4,6 +4,7 @@ import cn.axzo.basics.common.exception.ServiceException;
import cn.axzo.nanopart.ess.api.domain.OrgPerson;
import cn.axzo.nanopart.ess.api.domain.contract.Approver;
import cn.axzo.nanopart.ess.api.domain.contract.EssApproveDetail;
import cn.axzo.nanopart.ess.api.enums.ApproverAssignType;
import cn.axzo.nanopart.ess.api.enums.EssContractState;
import cn.axzo.nanopart.ess.api.enums.EssSealType;
import cn.axzo.nanopart.ess.api.request.AssignWeixinAppUrlByOrgRequest;
@ -21,7 +22,6 @@ import cn.axzo.nanopart.ess.server.entity.EssOrg;
import cn.axzo.nanopart.ess.server.entity.EssPerson;
import cn.axzo.nanopart.ess.server.entity.EssSeal;
import cn.axzo.nanopart.ess.server.entity.EssSealPerson;
import cn.axzo.nanopart.ess.api.enums.ApproverAssignType;
import cn.axzo.nanopart.ess.server.ess.domain.JsonObjectAsString;
import cn.axzo.nanopart.ess.server.ess.domain.SealPersons;
import cn.axzo.nanopart.ess.server.ess.support.EssSupport;
@ -164,8 +164,7 @@ public class ContractManager {
EssContract contract = essContractDao.find(request.getEssContractId(), true).orElse(null);
BizAssertions.assertNotNull(contract, "找不到合同信息, essContractId={}", request.getEssContractId());
//noinspection DataFlowIssue
BizAssertions.assertTrue(contract.getIsDynamicApprover().isYes(), "合同不支持动态签署");
BizAssertions.assertEquals(ApproverAssignType.ORG_WEIXIN_APP, contract.getAssignType(), "签署方式不正确");
BizAssertions.assertEquals(ApproverAssignType.ONE_PERSON_PER_ORG, contract.getAssignType(), "签署方式不正确");
String recipientId = contract.getAssignedApprovers()
.getSignByOrg()
.assign(contract.getApprovers(), request.getOuId(), request.getRecipientId());
@ -196,7 +195,8 @@ public class ContractManager {
}
public EssPerson getContractCreatorOrThrow(EssContract contract) {
EssPerson creator = essPersonDao.findOrNull(contract.getCreatorOuId(), contract.getCreatorPersonId());
EssPerson creator = essPersonDao.findOrNull(
contract.getCreatorOuId(), contract.getCreatorPersonId());
BizAssertions.assertNotNull(creator, "找不到合同发起人信息");
return creator;
}

View File

@ -16,7 +16,7 @@ import cn.axzo.nanopart.ess.server.entity.EssPerson;
import cn.axzo.nanopart.ess.server.entity.EssSeal;
import cn.axzo.nanopart.ess.server.entity.EssSealPerson;
import cn.axzo.nanopart.ess.server.ess.EssClient.Func.FuncBuilder;
import cn.axzo.nanopart.ess.server.ess.domain.OuOpenId;
import cn.axzo.nanopart.ess.server.ess.domain.OrgOpenId;
import cn.axzo.nanopart.ess.server.ess.domain.PersonOpenId;
import cn.axzo.nanopart.ess.server.ess.support.EssProps;
import cn.axzo.nanopart.ess.server.ess.support.EssSupport;
@ -62,7 +62,6 @@ import com.tencentcloudapi.essbasic.v20210526.models.UserInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@ -240,7 +239,7 @@ public class EssClient implements InitializingBean {
approverInfo.setMobile(personProfile.getPhone());
approverInfo.setOpenId(PersonOpenId.create(approver).toOpenId());
approverInfo.setOrganizationName(orgProfile.getName());
approverInfo.setOrganizationOpenId(OuOpenId.ofPerson(approver).toOpenId());
approverInfo.setOrganizationOpenId(OrgOpenId.ofPerson(approver).toOpenId());
}
approverInfo.setApproverType(approver.getApproverType().name());
approverInfo.setNotifyType("NONE");
@ -286,7 +285,7 @@ public class EssClient implements InitializingBean {
approverInfo.setApproverMobile(personProfile.getPhone());
approverInfo.setOpenId(PersonOpenId.create(approver).toOpenId());
approverInfo.setOrganizationName(orgProfile.getName());
approverInfo.setOrganizationOpenId(OuOpenId.ofPerson(approver).toOpenId());
approverInfo.setOrganizationOpenId(OrgOpenId.ofPerson(approver).toOpenId());
ChannelCreateFlowApproversRequest request = new ChannelCreateFlowApproversRequest();
request.setAgent(agent(contractCreator));
request.setFlowId(essContractId);
@ -336,18 +335,18 @@ public class EssClient implements InitializingBean {
return response.getSignUrl();
}
public CreateSignUrlsResponse getContractSignUrlWeixinApp(
String essContractId, EssPerson signPerson, String recipientId) {
public CreateSignUrlsResponse assignWeixinAppUrlByOrg(
String essContractId, EssPerson creator,
OrgPerson signPerson, String recipientId) {
CreateSignUrlsRequest request = new CreateSignUrlsRequest();
request.setAgent(agent(signPerson));
request.setAgent(agent(creator));
request.setFlowIds(new String[]{essContractId});
request.setOpenId(PersonOpenId.create(signPerson).toOpenId());
if (StringUtils.isNotBlank(recipientId)) {
request.setOrganizationOpenId(OrgOpenId.ofPerson(signPerson).toOpenId());
request.setRecipientIds(new String[]{recipientId});
request.setGenerateType("RECIPIENT");
}
return exec(func()
.context("CreateSignUrls")
.context("CreateSignUrls:assignWeixinAppUrlByOrg")
.subject(essContractId)
.request(request)
.command(() -> manage.CreateSignUrls(request)));
@ -393,7 +392,7 @@ public class EssClient implements InitializingBean {
UserInfo userInfo = new UserInfo();
agent.setAppId(props.getAppId());
agent.setProxyAppId("");
agent.setProxyOrganizationOpenId(OuOpenId.ofPerson(person).toOpenId());
agent.setProxyOrganizationOpenId(OrgOpenId.ofPerson(person).toOpenId());
userInfo.setOpenId(PersonOpenId.create(person).toOpenId());
agent.setProxyOperator(userInfo);
return agent;

View File

@ -1,5 +1,7 @@
package cn.axzo.nanopart.ess.server.ess;
import cn.axzo.basics.common.exception.ServiceException;
import cn.axzo.nanopart.ess.api.enums.ApproverAssignType;
import cn.axzo.nanopart.ess.api.enums.EssEmbedType.EssContext;
import cn.axzo.nanopart.ess.api.enums.SignUrlType;
import cn.axzo.nanopart.ess.api.request.AddSealAuthorizationRequest;
@ -26,7 +28,6 @@ import com.tencentcloudapi.essbasic.v20210526.models.SignUrlInfo;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
/**
* @author yanglin
@ -44,7 +45,6 @@ public class EssService {
private final EssPersonDao essPersonDao;
private final EssProps essProps;
private final OssService ossService;
private final TransactionTemplate transactionTemplate;
public String createConsoleLoginUrl(CreateConsoleLoginUrlRequest request) {
OrgAndPerson orgAndPerson = orgManager.createConsoleLoginUrl(request);
@ -105,11 +105,18 @@ public class EssService {
public String assignWeixinAppUrlByOrg(AssignWeixinAppUrlByOrgRequest request) {
EssPerson signPerson = essPersonDao.findOrNull(request);
BizAssertions.assertNotNull(signPerson, "当前签署人员未加入单位, 无法签署");
String recipientId = contractManager.assignRecipientIdByOrg(request);
EssContract contract = essContractDao.getOrThrow(request.getEssContractId());
BizAssertions.assertTrue(contract.isDynamicApprover(), "合同不支持动态签署");
String recipientId;
if (contract.getAssignedApprovers().getAssignType() == ApproverAssignType.ONE_PERSON_PER_ORG) {
BizAssertions.assertFalse(contract.isOrgSigned(request.getOuId()), "该单位已签署, 无法再次签署");
recipientId = contractManager.assignRecipientIdByOrg(request);
} else {
throw new ServiceException(String.format("暂不支持的动态签署类型: %s", contract.getAssignedApprovers().getAssignType()));
}
EssPerson creator = contractManager.getContractCreatorOrThrow(contract);
CreateSignUrlsResponse essResponse = essClient
.getContractSignUrlWeixinApp(request.getEssContractId(), creator, recipientId);
CreateSignUrlsResponse essResponse = essClient.assignWeixinAppUrlByOrg(
request.getEssContractId(), creator, request, recipientId);
SignUrlInfo signUrlInfo = essResponse.getSignUrlInfos()[0];
return request.getUrlType() == SignUrlType.PC
? signUrlInfo.getSignQrcodeUrl()

View File

@ -47,8 +47,8 @@ public class PersonResignListener extends BaseListener
}
@Override
public void onEvent(Event messageEvent, EventConsumer.Context context) {
OrgUserStatusChangedEvent userEvent = messageEvent.normalizedData(OrgUserStatusChangedEvent.class);
public void onEvent(Event event, EventConsumer.Context context) {
OrgUserStatusChangedEvent userEvent = event.normalizedData(OrgUserStatusChangedEvent.class);
log.info("receive user event: {}", JSON.toJSONString(userEvent));
if (userEvent.getStatusCode() == 6)
trySetPersonResigned(userEvent);
@ -56,10 +56,15 @@ public class PersonResignListener extends BaseListener
log.info("ignore user event: {}", JSON.toJSONString(userEvent));
}
private void trySetPersonResigned(OrgUserStatusChangedEvent userEvent) {
EssPerson person = essPersonDao.findOrNull(userEvent.getOuId(), userEvent.getPersonId());
if (person == null) return;
EssPerson superAdmin = orgManager.getSuperAdminOrThrow(userEvent.getOuId());
private void trySetPersonResigned(OrgUserStatusChangedEvent event) {
EssPerson person = essPersonDao.findOrNull(event.getOuId(), event.getPersonId());
if (person == null)
return;
EssPerson superAdmin = orgManager.getSuperAdminOrThrow(event.getOuId());
if (superAdmin.getPersonId().equals(event.getPersonId())) {
log.info("ignore super admin resigned: {}", JSON.toJSONString(person));
return;
}
essClient.setEmployeeResigned(superAdmin, Collections.singletonList(person));
orgManager.setOrgPersonResign(person);
log.info("set person resigned: {}", JSON.toJSONString(person));

View File

@ -10,20 +10,20 @@ import lombok.RequiredArgsConstructor;
*/
@Getter
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class OuOpenId {
public class OrgOpenId {
private final Long ouId;
public static OuOpenId ofPerson(OrgPerson person) {
public static OrgOpenId ofPerson(OrgPerson person) {
return create(person.getOuId());
}
public static OuOpenId create(Long ouId) {
return new OuOpenId(ouId);
public static OrgOpenId create(Long ouId) {
return new OrgOpenId(ouId);
}
public static OuOpenId parse(String openId) {
return new OuOpenId(Long.parseLong(openId));
public static OrgOpenId parse(String openId) {
return new OrgOpenId(Long.parseLong(openId));
}
public String toOpenId() {