REQ-3581: 备份
This commit is contained in:
parent
880d65bb4d
commit
2939ec73ab
@ -4,28 +4,26 @@ import cn.axzo.framework.domain.web.result.ApiResult;
|
|||||||
import cn.axzo.nanopart.ess.api.domain.EssOrgAndSealInfo;
|
import cn.axzo.nanopart.ess.api.domain.EssOrgAndSealInfo;
|
||||||
import cn.axzo.nanopart.ess.api.request.AddSealAuthorizationRequest;
|
import cn.axzo.nanopart.ess.api.request.AddSealAuthorizationRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.AddSealPersonsRequest;
|
import cn.axzo.nanopart.ess.api.request.AddSealPersonsRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.AssignWeixinAppUrlByOrgRequest;
|
|
||||||
import cn.axzo.nanopart.ess.api.request.CreateConsoleLoginUrlRequest;
|
import cn.axzo.nanopart.ess.api.request.CreateConsoleLoginUrlRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.CreateContractRequest;
|
import cn.axzo.nanopart.ess.api.request.CreateContractByFileRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.DownloadSingedContractPdfRequest;
|
import cn.axzo.nanopart.ess.api.request.DownloadSingedContractPdfRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.GetContractDetailByBizCodeRequest;
|
|
||||||
import cn.axzo.nanopart.ess.api.request.GetContractDetailByContractIdRequest;
|
import cn.axzo.nanopart.ess.api.request.GetContractDetailByContractIdRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.GetEmbedWebUrlRequest;
|
import cn.axzo.nanopart.ess.api.request.GetEmbedWebUrlRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.GetOrgAuthStatesRequest;
|
import cn.axzo.nanopart.ess.api.request.GetOrgAuthStatesRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.GetPersonAuthStateRequest;
|
import cn.axzo.nanopart.ess.api.request.GetPersonAuthStateRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.GetSealsRequest;
|
import cn.axzo.nanopart.ess.api.request.GetSealsRequest;
|
||||||
|
import cn.axzo.nanopart.ess.api.request.GetSignUrlRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.RemoveSealAuthorizationRequest;
|
import cn.axzo.nanopart.ess.api.request.RemoveSealAuthorizationRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.RemoveSealPersonRequest;
|
import cn.axzo.nanopart.ess.api.request.RemoveSealPersonRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.RevokeContractRequest;
|
import cn.axzo.nanopart.ess.api.request.RevokeContractRequest;
|
||||||
import cn.axzo.nanopart.ess.api.response.AssignWeixinAppUrlByOrgResponse;
|
|
||||||
import cn.axzo.nanopart.ess.api.response.CreateConsoleLoginUrlResponse;
|
import cn.axzo.nanopart.ess.api.response.CreateConsoleLoginUrlResponse;
|
||||||
import cn.axzo.nanopart.ess.api.response.CreateContractResponse;
|
import cn.axzo.nanopart.ess.api.response.CreateContractByFileResponse;
|
||||||
import cn.axzo.nanopart.ess.api.response.DownloadSingedContractPdfResponse;
|
import cn.axzo.nanopart.ess.api.response.DownloadSingedContractPdfResponse;
|
||||||
import cn.axzo.nanopart.ess.api.response.GetContractDetailByBizCodeResponse;
|
|
||||||
import cn.axzo.nanopart.ess.api.response.GetContractDetailByContractIdResponse;
|
import cn.axzo.nanopart.ess.api.response.GetContractDetailByContractIdResponse;
|
||||||
import cn.axzo.nanopart.ess.api.response.GetEmbedWebUrlResponse;
|
import cn.axzo.nanopart.ess.api.response.GetEmbedWebUrlResponse;
|
||||||
import cn.axzo.nanopart.ess.api.response.GetOrgAuthStatesResponse;
|
import cn.axzo.nanopart.ess.api.response.GetOrgAuthStatesResponse;
|
||||||
import cn.axzo.nanopart.ess.api.response.GetPersonAuthStateResponse;
|
import cn.axzo.nanopart.ess.api.response.GetPersonAuthStateResponse;
|
||||||
|
import cn.axzo.nanopart.ess.api.response.GetSignUrlResponse;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
@ -68,7 +66,7 @@ public interface EssApi {
|
|||||||
@RequestBody @Valid GetEmbedWebUrlRequest request);
|
@RequestBody @Valid GetEmbedWebUrlRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询单位已启用的印章以及授权人员列表
|
* 查询单位已启用的印章以及授权人员列表等等
|
||||||
*/
|
*/
|
||||||
@PostMapping("api/ess/getOrgEnabledSeals")
|
@PostMapping("api/ess/getOrgEnabledSeals")
|
||||||
ApiResult<List<EssOrgAndSealInfo>> getOrgEnabledSeals(
|
ApiResult<List<EssOrgAndSealInfo>> getOrgEnabledSeals(
|
||||||
@ -103,21 +101,21 @@ public interface EssApi {
|
|||||||
@RequestBody @Valid RemoveSealAuthorizationRequest request);
|
@RequestBody @Valid RemoveSealAuthorizationRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建合同
|
* 通过文件创建合同
|
||||||
*/
|
*/
|
||||||
@PostMapping("api/ess/createContract")
|
@PostMapping("api/ess/createContractByFile")
|
||||||
ApiResult<CreateContractResponse> createContract(
|
ApiResult<CreateContractByFileResponse> createContractByFile(
|
||||||
@RequestBody @Valid CreateContractRequest request);
|
@RequestBody @Valid CreateContractByFileRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据单位分配微信小程序签署链接, 有效期为5分钟
|
* 获取签署链接, 有效期为5分钟
|
||||||
*/
|
*/
|
||||||
@PostMapping("api/ess/assignWeixinAppUrlByOrg")
|
@PostMapping("api/ess/getContractSignUrl")
|
||||||
ApiResult<AssignWeixinAppUrlByOrgResponse> assignWeixinAppUrlByOrg(
|
ApiResult<GetSignUrlResponse> getContractSignUrl(
|
||||||
@RequestBody @Valid AssignWeixinAppUrlByOrgRequest request);
|
@RequestBody @Valid GetSignUrlRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载已签署的合同PDF. 下载链接有效期为5分钟
|
* 下载合同PDF. 下载链接有效期为5分钟
|
||||||
*/
|
*/
|
||||||
@PostMapping("api/ess/getContractPDFUrl")
|
@PostMapping("api/ess/getContractPDFUrl")
|
||||||
ApiResult<DownloadSingedContractPdfResponse> getContractPDFUrl(
|
ApiResult<DownloadSingedContractPdfResponse> getContractPDFUrl(
|
||||||
@ -133,15 +131,8 @@ public interface EssApi {
|
|||||||
/**
|
/**
|
||||||
* 获取合同详情, 通过合同id
|
* 获取合同详情, 通过合同id
|
||||||
*/
|
*/
|
||||||
@PostMapping("api/ess/getContractDetailByContractId")
|
@PostMapping("api/ess/getContractByContractId")
|
||||||
ApiResult<GetContractDetailByContractIdResponse> getContractDetailByContractId(
|
ApiResult<GetContractDetailByContractIdResponse> getContractByContractId(
|
||||||
@RequestBody @Valid GetContractDetailByContractIdRequest request);
|
@RequestBody @Valid GetContractDetailByContractIdRequest request);
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取合同详情, 通过业务id
|
|
||||||
*/
|
|
||||||
@PostMapping("api/ess/getContractDetailByBizCode")
|
|
||||||
ApiResult<GetContractDetailByBizCodeResponse> getContractDetailByBizCode(
|
|
||||||
@RequestBody @Valid GetContractDetailByBizCodeRequest request);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package cn.axzo.nanopart.ess.api.request;
|
package cn.axzo.nanopart.ess.api.domain;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@ -1,14 +1,17 @@
|
|||||||
package cn.axzo.nanopart.ess.api.request;
|
package cn.axzo.nanopart.ess.api.domain;
|
||||||
|
|
||||||
import cn.axzo.nanopart.ess.api.domain.DynamicApproverProps;
|
|
||||||
import cn.axzo.nanopart.ess.api.domain.contract.Approver;
|
import cn.axzo.nanopart.ess.api.domain.contract.Approver;
|
||||||
|
import cn.axzo.nanopart.ess.api.enums.Constraint;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import org.hibernate.validator.constraints.Range;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import javax.validation.constraints.NotBlank;
|
import javax.validation.constraints.NotBlank;
|
||||||
import javax.validation.constraints.NotEmpty;
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -18,7 +21,7 @@ import static java.util.stream.Collectors.toSet;
|
|||||||
* @author yanglin
|
* @author yanglin
|
||||||
*/
|
*/
|
||||||
@Setter @Getter
|
@Setter @Getter
|
||||||
public class CreateContractInfo {
|
public abstract class CreateContractInfo {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 合同名称
|
* 合同名称
|
||||||
@ -26,31 +29,25 @@ public class CreateContractInfo {
|
|||||||
@NotBlank(message = "contractName不能为空")
|
@NotBlank(message = "contractName不能为空")
|
||||||
private String contractName;
|
private String contractName;
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否为动态签署人, 即在创建合同的时候不指定签署人, 而是在获取签署链接时指定签署人
|
|
||||||
* dynamicApprover=true时,不需要指定Approver#signPerson
|
|
||||||
* dynamicApprover=false时, 需要指定Approver#signPerson
|
|
||||||
*/
|
|
||||||
private boolean dynamicApprover;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 动态签署人属性
|
|
||||||
*/
|
|
||||||
@Valid
|
|
||||||
private DynamicApproverProps dynamicApproverProps;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 合同签署方
|
* 合同签署方
|
||||||
*/
|
*/
|
||||||
@Valid
|
@Valid
|
||||||
@NotEmpty
|
@NotEmpty(message = "approvers不能为空")
|
||||||
private List<Approver> approvers;
|
private List<Approver> approvers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 合同签署方的签署约束种类
|
||||||
|
*/
|
||||||
|
@NotNull(message = "approverConstraint不能为空")
|
||||||
|
private Constraint constraint = Constraint.ONE_PERSON_PER_ORG;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 签署方签署控件(印章/签名等)的生成方式.
|
* 签署方签署控件(印章/签名等)的生成方式.
|
||||||
* 0: 在合同流程发起时,由发起人指定签署方的签署控件的位置和数量
|
* 0: 在合同流程发起时,由发起人指定签署方的签署控件的位置和数量
|
||||||
* 1: 签署方在签署时自行添加签署控件,可以拖动位置和控制数量
|
* 1: 签署方在签署时自行添加签署控件,可以拖动位置和控制数量
|
||||||
*/
|
*/
|
||||||
|
@Range(min = 0, max = 1, message = "signBeanTag必须是0或1")
|
||||||
private Long signBeanTag = 1L;
|
private Long signBeanTag = 1L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,7 +56,7 @@ public class CreateContractInfo {
|
|||||||
private boolean signOrdered = false;
|
private boolean signOrdered = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 合同流程的签署截止时间,格式为Unix标准时间戳
|
* 合同流程的签署截止时间,格式为Unix标准时间戳, 透传给腾讯电子签
|
||||||
* 如果未设置签署截止时间,则默认为合同流程创建后的365天时截止
|
* 如果未设置签署截止时间,则默认为合同流程创建后的365天时截止
|
||||||
* 如果在签署截止时间前未完成签署,则合同状态会变为已过期,导致合同作废。
|
* 如果在签署截止时间前未完成签署,则合同状态会变为已过期,导致合同作废。
|
||||||
*/
|
*/
|
||||||
@ -67,6 +64,8 @@ public class CreateContractInfo {
|
|||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
public Set<Long> getApproverOuIds() {
|
public Set<Long> getApproverOuIds() {
|
||||||
|
if (approvers == null)
|
||||||
|
return Collections.emptySet();
|
||||||
return approvers.stream()
|
return approvers.stream()
|
||||||
.map(Approver::getOuId)
|
.map(Approver::getOuId)
|
||||||
.collect(toSet());
|
.collect(toSet());
|
||||||
@ -1,27 +0,0 @@
|
|||||||
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;
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -34,6 +34,11 @@ public class EssSealPersonInfo {
|
|||||||
*/
|
*/
|
||||||
private boolean isPersonAuthorized;
|
private boolean isPersonAuthorized;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权时间, unix时间戳
|
||||||
|
*/
|
||||||
|
private Long authorizeTimeMs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否已经认证(印章授权)
|
* 是否已经认证(印章授权)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -0,0 +1,27 @@
|
|||||||
|
package cn.axzo.nanopart.ess.api.domain;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yanglin
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class OperatorInfo implements OrgPerson {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发起方单位id
|
||||||
|
*/
|
||||||
|
@NotNull(message = "ouId不能为空")
|
||||||
|
private Long ouId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发起方人员id
|
||||||
|
*/
|
||||||
|
@NotNull(message = "personId不能为空")
|
||||||
|
private Long personId;
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,5 +1,7 @@
|
|||||||
package cn.axzo.nanopart.ess.api.domain;
|
package cn.axzo.nanopart.ess.api.domain;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yanglin
|
* @author yanglin
|
||||||
*/
|
*/
|
||||||
@ -9,4 +11,8 @@ public interface OrgPerson {
|
|||||||
|
|
||||||
Long getPersonId();
|
Long getPersonId();
|
||||||
|
|
||||||
|
static boolean equals(OrgPerson a, OrgPerson b) {
|
||||||
|
return Objects.equals(a.getOuId(), b.getOuId())
|
||||||
|
&& Objects.equals(a.getPersonId(), b.getPersonId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -8,8 +8,11 @@ import com.alibaba.fastjson.annotation.JSONField;
|
|||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import org.hibernate.validator.constraints.Range;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
import javax.validation.constraints.Max;
|
||||||
|
import javax.validation.constraints.Min;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -18,10 +21,10 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
public class Approver implements OrgPerson {
|
public class Approver implements OrgPerson {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 签署方人员信息, 如果是动态签署人, 则不需要传入. 在获取签署链接时再指定签署人
|
* 签署方人员信息, 如果是动态签署人, 则传null, 在获取签署链接时再指定签署人
|
||||||
*/
|
*/
|
||||||
@Valid
|
@Valid
|
||||||
private OrgPersonInfo signPerson;
|
private OrgPersonInfo signPerson;
|
||||||
@ -35,6 +38,7 @@ public class Approver implements OrgPerson {
|
|||||||
/**
|
/**
|
||||||
* 签署方在签署合同之前,需要强制阅读合同的时长,可指定为3秒至300秒之间的任意值
|
* 签署方在签署合同之前,需要强制阅读合同的时长,可指定为3秒至300秒之间的任意值
|
||||||
*/
|
*/
|
||||||
|
@Range(min = 3, max = 300, message = "preReadTime必须在3-300之间")
|
||||||
@NotNull(message = "preReadTime不能为空")
|
@NotNull(message = "preReadTime不能为空")
|
||||||
private Long preReadTimeSeconds = 10L;
|
private Long preReadTimeSeconds = 10L;
|
||||||
|
|
||||||
@ -46,7 +50,7 @@ public class Approver implements OrgPerson {
|
|||||||
/**
|
/**
|
||||||
* 扩展信息, 内部使用
|
* 扩展信息, 内部使用
|
||||||
*/
|
*/
|
||||||
private JSONObject extension;
|
private JSONObject internal;
|
||||||
|
|
||||||
public void setEssRecipientId(String essRecipientId) {
|
public void setEssRecipientId(String essRecipientId) {
|
||||||
getOrCreateExtension().put("essRecipientId", essRecipientId);
|
getOrCreateExtension().put("essRecipientId", essRecipientId);
|
||||||
@ -54,15 +58,20 @@ public class Approver implements OrgPerson {
|
|||||||
|
|
||||||
@JsonIgnore @JSONField(serialize = false)
|
@JsonIgnore @JSONField(serialize = false)
|
||||||
public String getEssRecipientId() {
|
public String getEssRecipientId() {
|
||||||
if (extension == null) return null;
|
if (internal == null)
|
||||||
return extension.getString("essRecipientId");
|
return null;
|
||||||
|
return internal.getString("essRecipientId");
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonIgnore @JSONField(serialize = false)
|
@JsonIgnore @JSONField(serialize = false)
|
||||||
public JSONObject getOrCreateExtension() {
|
public JSONObject getOrCreateExtension() {
|
||||||
if (extension == null)
|
if (internal == null)
|
||||||
extension = new JSONObject();
|
internal = new JSONObject();
|
||||||
return extension;
|
return internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSignPersonPresent() {
|
||||||
|
return signPerson != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonIgnore @JSONField(serialize = false)
|
@JsonIgnore @JSONField(serialize = false)
|
||||||
@ -74,4 +83,5 @@ public class Approver implements OrgPerson {
|
|||||||
public Long getPersonId() {
|
public Long getPersonId() {
|
||||||
return signPerson == null ? 0L : signPerson.getPersonId();
|
return signPerson == null ? 0L : signPerson.getPersonId();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -12,12 +12,12 @@ import lombok.Setter;
|
|||||||
public class EssApproveDetail {
|
public class EssApproveDetail {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 签署人单位
|
* 签署人单位, 动态签署人在没有签署的时候可能为空
|
||||||
*/
|
*/
|
||||||
private Long ouId;
|
private Long ouId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 签署人
|
* 签署人, 动态签署人在没有签署的时候可能为空
|
||||||
*/
|
*/
|
||||||
private Long personId;
|
private Long personId;
|
||||||
|
|
||||||
@ -52,12 +52,12 @@ public class EssApproveDetail {
|
|||||||
private long approverDeadlineMs;
|
private long approverDeadlineMs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单位名称
|
* 单位名称, 动态签署人在没有签署的时候可能为空
|
||||||
*/
|
*/
|
||||||
private String ouName;
|
private String ouName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对应签署人的手机号
|
* 对应签署人的手机号, 动态签署人在没有签署的时候可能为空
|
||||||
*/
|
*/
|
||||||
private String phoneNumber;
|
private String phoneNumber;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
package cn.axzo.nanopart.ess.api.domain.contract;
|
package cn.axzo.nanopart.ess.api.domain.contract;
|
||||||
|
|
||||||
import cn.axzo.nanopart.ess.api.enums.EssContractState;
|
import cn.axzo.nanopart.ess.api.enums.EssContractState;
|
||||||
import cn.axzo.nanopart.ess.api.utils.YesOrNo;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
@ -50,22 +49,12 @@ public class EssContractInfo {
|
|||||||
private EssContractState state;
|
private EssContractState state;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否为动态签署人
|
* 合并签署方信息, 如果是动态签署, 里面的签署人信息可能为nul
|
||||||
*/
|
|
||||||
private YesOrNo isDynamicApprover;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 合并签署方信息(非动态签署人)
|
|
||||||
*/
|
*/
|
||||||
private List<Approver> approvers;
|
private List<Approver> approvers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 动态签署人信息
|
* 合同的签署方的签署情况
|
||||||
*/
|
|
||||||
private List<Approver> dynamicApprovers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 签署方的签署情况
|
|
||||||
*/
|
*/
|
||||||
private List<EssApproveDetail> approveDetails;
|
private List<EssApproveDetail> approveDetails;
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package cn.axzo.nanopart.ess.api.domain.contract;
|
package cn.axzo.nanopart.ess.api.domain.contract;
|
||||||
|
|
||||||
|
import cn.axzo.nanopart.ess.api.domain.OrgPerson;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
@ -9,7 +10,7 @@ import javax.validation.constraints.NotNull;
|
|||||||
* @author yanglin
|
* @author yanglin
|
||||||
*/
|
*/
|
||||||
@Setter @Getter
|
@Setter @Getter
|
||||||
public class OrgPersonInfo {
|
public class OrgPersonInfo implements OrgPerson {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单位id
|
* 单位id
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
package cn.axzo.nanopart.ess.api.enums;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author yanglin
|
|
||||||
*/
|
|
||||||
public enum ApproverAssignType {
|
|
||||||
|
|
||||||
// 一个子客一个用户盖章
|
|
||||||
ONE_PERSON_PER_ORG,
|
|
||||||
// 不做限制
|
|
||||||
NONE
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
package cn.axzo.nanopart.ess.api.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yanglin
|
||||||
|
*/
|
||||||
|
public enum Constraint {
|
||||||
|
|
||||||
|
// 一个子客只允许一个用户盖章
|
||||||
|
ONE_PERSON_PER_ORG
|
||||||
|
|
||||||
|
}
|
||||||
@ -4,6 +4,12 @@ import lombok.AccessLevel;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static java.util.stream.Collectors.toList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yanglin
|
* @author yanglin
|
||||||
*/
|
*/
|
||||||
@ -35,4 +41,10 @@ public enum EssContractState {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<EssContractState> collectFinalStates() {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(EssContractState::isFinalState)
|
||||||
|
.collect(toList());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -3,6 +3,6 @@ package cn.axzo.nanopart.ess.api.enums;
|
|||||||
/**
|
/**
|
||||||
* @author yanglin
|
* @author yanglin
|
||||||
*/
|
*/
|
||||||
public enum SignUrlType {
|
public enum SignUrlEndpoint {
|
||||||
PC, WEIXIN_APP
|
PC, WEIXIN_APP
|
||||||
}
|
}
|
||||||
@ -12,7 +12,7 @@ import lombok.Setter;
|
|||||||
public class EssContractStateChangeMessage extends MqMessage {
|
public class EssContractStateChangeMessage extends MqMessage {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 合同信息
|
* 合同信息, 处理签署详情时需要做幂等
|
||||||
*/
|
*/
|
||||||
private EssContractInfo contract;
|
private EssContractInfo contract;
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package cn.axzo.nanopart.ess.api.request;
|
package cn.axzo.nanopart.ess.api.request;
|
||||||
|
|
||||||
|
import cn.axzo.nanopart.ess.api.domain.OrgPerson;
|
||||||
import cn.axzo.nanopart.ess.api.enums.EssConsoleUrlEndpoint;
|
import cn.axzo.nanopart.ess.api.enums.EssConsoleUrlEndpoint;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@ -11,7 +12,7 @@ import javax.validation.constraints.NotNull;
|
|||||||
*/
|
*/
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
public class CreateConsoleLoginUrlRequest {
|
public class CreateConsoleLoginUrlRequest implements OrgPerson {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单位id
|
* 单位id
|
||||||
@ -41,6 +42,6 @@ public class CreateConsoleLoginUrlRequest {
|
|||||||
/**
|
/**
|
||||||
* 调试参数, 不填
|
* 调试参数, 不填
|
||||||
*/
|
*/
|
||||||
private transient boolean checkOperator = true;
|
private transient boolean essCheckLoginPerson = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,32 @@
|
|||||||
|
package cn.axzo.nanopart.ess.api.request;
|
||||||
|
|
||||||
|
import cn.axzo.nanopart.ess.api.domain.CreateContractByFile;
|
||||||
|
import cn.axzo.nanopart.ess.api.domain.CreateContractInfo;
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yanglin
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class CreateContractByFileRequest extends CreateContractRequest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过上传PDF发起合同
|
||||||
|
*/
|
||||||
|
@Valid
|
||||||
|
@NotNull(message = "byFile不能为空")
|
||||||
|
private CreateContractByFile byFile;
|
||||||
|
|
||||||
|
@JsonIgnore @JSONField(serialize = false)
|
||||||
|
public CreateContractInfo getContract() {
|
||||||
|
return byFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,5 +1,9 @@
|
|||||||
package cn.axzo.nanopart.ess.api.request;
|
package cn.axzo.nanopart.ess.api.request;
|
||||||
|
|
||||||
|
import cn.axzo.nanopart.ess.api.domain.CreateContractInfo;
|
||||||
|
import cn.axzo.nanopart.ess.api.domain.OperatorInfo;
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
@ -10,8 +14,9 @@ import javax.validation.constraints.NotNull;
|
|||||||
/**
|
/**
|
||||||
* @author yanglin
|
* @author yanglin
|
||||||
*/
|
*/
|
||||||
@Setter @Getter
|
@Setter
|
||||||
public class CreateContractRequest {
|
@Getter
|
||||||
|
public abstract class CreateContractRequest {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发起合同的应用或业务场景
|
* 发起合同的应用或业务场景
|
||||||
@ -20,40 +25,21 @@ public class CreateContractRequest {
|
|||||||
private String appCode;
|
private String appCode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 业务编码
|
* 业务编码, 最大长度200. 使用appCode和bizCode的合同不能重复
|
||||||
|
* <p/>
|
||||||
|
* 如果需要重复发起合同, 需要使用不同的bizCode, 建议: String.format("%s:%s", '真实业务编码', '序号或UUID')
|
||||||
*/
|
*/
|
||||||
@NotBlank(message = "bizCode不能为空")
|
@NotBlank(message = "bizCode不能为空")
|
||||||
private String bizCode;
|
private String bizCode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发起方信息
|
* 合同发起方信息
|
||||||
*/
|
*/
|
||||||
@Valid
|
@Valid
|
||||||
@NotNull(message = "operator不能为空")
|
@NotNull(message = "creator不能为空")
|
||||||
private OperatorInfo operator;
|
private OperatorInfo creator;
|
||||||
|
|
||||||
/**
|
@JsonIgnore @JSONField(serialize = false)
|
||||||
* 通过上传PDF发起合同
|
public abstract CreateContractInfo getContract();
|
||||||
*/
|
|
||||||
@Valid
|
|
||||||
@NotNull(message = "byFile不能为空")
|
|
||||||
private CreateContractByFile byFile;
|
|
||||||
|
|
||||||
@Setter @Getter
|
|
||||||
public static class OperatorInfo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发起方单位id
|
|
||||||
*/
|
|
||||||
@NotNull(message = "ouId不能为空")
|
|
||||||
private Long ouId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发起方人员id
|
|
||||||
*/
|
|
||||||
@NotNull(message = "personId不能为空")
|
|
||||||
private Long personId;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
package cn.axzo.nanopart.ess.api.request;
|
package cn.axzo.nanopart.ess.api.request;
|
||||||
|
|
||||||
import cn.axzo.nanopart.ess.api.domain.OrgPerson;
|
import cn.axzo.nanopart.ess.api.domain.OrgPerson;
|
||||||
import cn.axzo.nanopart.ess.api.enums.SignUrlType;
|
import cn.axzo.nanopart.ess.api.enums.SignUrlEndpoint;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
@ -37,6 +37,6 @@ public class GetContractSignUrlRequest implements OrgPerson {
|
|||||||
* PC: 电脑端, WEIXIN_APP: 小程序
|
* PC: 电脑端, WEIXIN_APP: 小程序
|
||||||
*/
|
*/
|
||||||
@NotNull(message = "urlType不能为空")
|
@NotNull(message = "urlType不能为空")
|
||||||
private SignUrlType urlType;
|
private SignUrlEndpoint urlType;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
package cn.axzo.nanopart.ess.api.request;
|
package cn.axzo.nanopart.ess.api.request;
|
||||||
|
|
||||||
import cn.axzo.nanopart.ess.api.domain.OrgPerson;
|
import cn.axzo.nanopart.ess.api.domain.OrgPerson;
|
||||||
import cn.axzo.nanopart.ess.api.enums.SignUrlType;
|
import cn.axzo.nanopart.ess.api.enums.SignUrlEndpoint;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ import javax.validation.constraints.NotNull;
|
|||||||
*/
|
*/
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
public class AssignWeixinAppUrlByOrgRequest implements OrgPerson {
|
public class GetSignUrlRequest implements OrgPerson {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 合同id
|
* 合同id
|
||||||
@ -36,12 +36,15 @@ public class AssignWeixinAppUrlByOrgRequest implements OrgPerson {
|
|||||||
/**
|
/**
|
||||||
* PC: 电脑端, WEIXIN_APP: 小程序
|
* PC: 电脑端, WEIXIN_APP: 小程序
|
||||||
*/
|
*/
|
||||||
@NotNull(message = "urlType不能为空")
|
@NotNull(message = "endpoint不能为空")
|
||||||
private SignUrlType urlType;
|
private SignUrlEndpoint endpoint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 签署方编号, 可以使用该编号指定动态签署方的信息, 或未指定将自动分配
|
* 签署方编号, 可以使用该编号指定动态签署方的信息, 该编号在创建合同的时候会返回
|
||||||
* 该编号在创建合同的时候会返回
|
* <p/>
|
||||||
|
* 如果在创建合同的时候存在任意没有指定具体签署人(Approver#signPersion)的情况下, 该字段必传
|
||||||
|
* <p/>
|
||||||
|
* 如果在创建合同的时候已经指定了所有的具体签署人(Approver#signPersion), 该字段可以不传
|
||||||
*/
|
*/
|
||||||
private String recipientId;
|
private String recipientId;
|
||||||
|
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package cn.axzo.nanopart.ess.api.response;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yanglin
|
||||||
|
*/
|
||||||
|
@Setter @Getter
|
||||||
|
public class CreateContractByFileResponse {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 合同id
|
||||||
|
*/
|
||||||
|
private String essContractId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签署方编号, 可以使用该编号指定动态签署方的信息, 顺序和请求中的approvers一致.
|
||||||
|
* <p/>
|
||||||
|
* 比如在使用了动态签署人的情况下, 就需要保存这个字段
|
||||||
|
* <p/>
|
||||||
|
* 在获取签署链接的时候回传到获取签署链接的请求中, 用以和创建合同的请求中的签署人的其它信息进行匹配
|
||||||
|
*/
|
||||||
|
private List<String> essRecipientIds;
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,24 +0,0 @@
|
|||||||
package cn.axzo.nanopart.ess.api.response;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author yanglin
|
|
||||||
*/
|
|
||||||
@Setter @Getter
|
|
||||||
public class CreateContractResponse {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 合同id
|
|
||||||
*/
|
|
||||||
private String essContractId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 签署方编号, 可以使用该编号指定动态签署方的信息, 顺序和请求中的approvers一致
|
|
||||||
*/
|
|
||||||
private List<String> essRecipientIds;
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -8,7 +8,7 @@ import lombok.Setter;
|
|||||||
*/
|
*/
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
public class AssignWeixinAppUrlByOrgResponse {
|
public class GetSignUrlResponse {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 有效期为5分钟.
|
* 有效期为5分钟.
|
||||||
@ -20,24 +20,21 @@ import java.util.Optional;
|
|||||||
@Repository("essContractDao")
|
@Repository("essContractDao")
|
||||||
public class EssContractDao extends ServiceImpl<EssContractMapper, EssContract> {
|
public class EssContractDao extends ServiceImpl<EssContractMapper, EssContract> {
|
||||||
|
|
||||||
public Optional<EssContract> findByBizCode(String appCode, String bizCode) {
|
|
||||||
return lambdaQuery()
|
|
||||||
.eq(EssContract::getAppCode, appCode)
|
|
||||||
.eq(EssContract::getBizCode, bizCode)
|
|
||||||
.oneOpt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public EssContract getOrThrow(String essContractId) {
|
public EssContract getOrThrow(String essContractId) {
|
||||||
EssContract contract = find(essContractId).orElse(null);
|
EssContract contract = findOrNull(essContractId);
|
||||||
BizAssertions.assertNotNull(contract, "找不到合同信息, essContractId={}", essContractId);
|
BizAssertions.assertNotNull(contract, "找不到合同信息, essContractId={}", essContractId);
|
||||||
return contract;
|
return contract;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<EssContract> find(String essContractId) {
|
public EssContract findOrNull(String essContractId) {
|
||||||
return find(essContractId, false);
|
return find(essContractId, false).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<EssContract> find(String essContractId, boolean forUpdate) {
|
public EssContract findForUpdateOrNull(String essContractId) {
|
||||||
|
return find(essContractId, true).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<EssContract> find(String essContractId, boolean forUpdate) {
|
||||||
return lambdaQuery()
|
return lambdaQuery()
|
||||||
.eq(EssContract::getEssContractId, essContractId)
|
.eq(EssContract::getEssContractId, essContractId)
|
||||||
.last(forUpdate, "FOR UPDATE")
|
.last(forUpdate, "FOR UPDATE")
|
||||||
@ -68,13 +65,6 @@ public class EssContractDao extends ServiceImpl<EssContractMapper, EssContract>
|
|||||||
.update();
|
.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateAssignedApprovers(EssContract contract) {
|
|
||||||
lambdaUpdate()
|
|
||||||
.eq(EssContract::getId, contract.getId())
|
|
||||||
.set(EssContract::getAssignedApprovers, JSON.toJSONString(contract.getAssignedApprovers()))
|
|
||||||
.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOssInfo(EssContract contract, String fileKey) {
|
public void setOssInfo(EssContract contract, String fileKey) {
|
||||||
lambdaUpdate()
|
lambdaUpdate()
|
||||||
.eq(EssContract::getId, contract.getId())
|
.eq(EssContract::getId, contract.getId())
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package cn.axzo.nanopart.ess.server.dao;
|
|||||||
|
|
||||||
import cn.axzo.nanopart.ess.server.entity.EssLog;
|
import cn.axzo.nanopart.ess.server.entity.EssLog;
|
||||||
import cn.axzo.nanopart.ess.server.mapper.EssLogMapper;
|
import cn.axzo.nanopart.ess.server.mapper.EssLogMapper;
|
||||||
|
import cn.axzo.nanopart.ess.server.utils.BizAssertions;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
@ -10,4 +11,23 @@ import org.springframework.stereotype.Repository;
|
|||||||
*/
|
*/
|
||||||
@Repository("essLogDao")
|
@Repository("essLogDao")
|
||||||
public class EssLogDao extends ServiceImpl<EssLogMapper, EssLog> {
|
public class EssLogDao extends ServiceImpl<EssLogMapper, EssLog> {
|
||||||
}
|
|
||||||
|
public void logRequest(String context, Object subject, Object request) {
|
||||||
|
log(context, subject, "request", request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void log(String context, Object subject, Object... logContents) {
|
||||||
|
EssLog log = new EssLog();
|
||||||
|
log.setContext(context);
|
||||||
|
log.setSubject(String.valueOf(subject));
|
||||||
|
if (logContents != null && logContents.length > 0) {
|
||||||
|
BizAssertions.assertTrue(logContents.length % 2 == 0, "logContents must be even");
|
||||||
|
for (int i = 0; i < logContents.length; i += 2) {
|
||||||
|
BizAssertions.assertTrue(logContents[i] instanceof String, "logContents key must be String");
|
||||||
|
log.addLogContent((String) logContents[i], logContents[i + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
save(log);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -24,11 +24,15 @@ public class EssOrgDao extends ServiceImpl<EssOrgMapper, EssOrg> {
|
|||||||
return lambdaQuery().in(EssOrg::getOuId, ouIds).list();
|
return lambdaQuery().in(EssOrg::getOuId, ouIds).list();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<EssOrg> find(Long ouId) {
|
public EssOrg findOrNull(Long ouId) {
|
||||||
return find(ouId, false);
|
return find(ouId, false).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<EssOrg> find(Long ouId, boolean forUpdate) {
|
public EssOrg findForUpdateOrNull(Long ouId) {
|
||||||
|
return find(ouId, true).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<EssOrg> find(Long ouId, boolean forUpdate) {
|
||||||
return lambdaQuery()
|
return lambdaQuery()
|
||||||
.eq(EssOrg::getOuId, ouId)
|
.eq(EssOrg::getOuId, ouId)
|
||||||
.last(forUpdate, "FOR UPDATE")
|
.last(forUpdate, "FOR UPDATE")
|
||||||
|
|||||||
@ -20,18 +20,18 @@ import java.util.Optional;
|
|||||||
public class EssPersonDao extends ServiceImpl<EssPersonMapper, EssPerson> {
|
public class EssPersonDao extends ServiceImpl<EssPersonMapper, EssPerson> {
|
||||||
|
|
||||||
public EssPerson findOrNull(OrgPerson person) {
|
public EssPerson findOrNull(OrgPerson person) {
|
||||||
return find(person.getOuId(), person.getPersonId(), false).orElse(null);
|
return findOrNull(person.getOuId(), person.getPersonId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public EssPerson findOrNull(Long ouId, Long personId) {
|
public EssPerson findOrNull(Long ouId, Long personId) {
|
||||||
return find(ouId, personId, false).orElse(null);
|
return find(ouId, personId, false).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<EssPerson> find(Long ouId, Long personId) {
|
public Optional<EssPerson> find(OrgPerson person, boolean forUpdate) {
|
||||||
return find(ouId, personId, false);
|
return find(person.getOuId(), person.getPersonId(), forUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<EssPerson> find(Long ouId, Long personId, boolean forUpdate) {
|
private Optional<EssPerson> find(Long ouId, Long personId, boolean forUpdate) {
|
||||||
return lambdaQuery()
|
return lambdaQuery()
|
||||||
.eq(EssPerson::getOuId, ouId)
|
.eq(EssPerson::getOuId, ouId)
|
||||||
.eq(EssPerson::getPersonId, personId)
|
.eq(EssPerson::getPersonId, personId)
|
||||||
|
|||||||
@ -1,14 +1,11 @@
|
|||||||
package cn.axzo.nanopart.ess.server.dao;
|
package cn.axzo.nanopart.ess.server.dao;
|
||||||
|
|
||||||
import cn.axzo.nanopart.ess.api.enums.EssSealState;
|
import cn.axzo.nanopart.ess.api.enums.EssSealState;
|
||||||
import cn.axzo.nanopart.ess.api.enums.EssSealType;
|
|
||||||
import cn.axzo.nanopart.ess.server.entity.EssSeal;
|
import cn.axzo.nanopart.ess.server.entity.EssSeal;
|
||||||
import cn.axzo.nanopart.ess.server.mapper.EssSealMapper;
|
import cn.axzo.nanopart.ess.server.mapper.EssSealMapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,10 +27,4 @@ public class EssSealDao extends ServiceImpl<EssSealMapper, EssSeal> {
|
|||||||
.update();
|
.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<EssSeal> getByOrgAndSealTypes(Long ouId, List<EssSealType> sealTypes) {
|
|
||||||
return lambdaQuery()
|
|
||||||
.eq(EssSeal::getOuId, ouId)
|
|
||||||
.in(CollectionUtils.isNotEmpty(sealTypes), EssSeal::getType, sealTypes)
|
|
||||||
.list();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -1,7 +1,6 @@
|
|||||||
package cn.axzo.nanopart.ess.server.dao;
|
package cn.axzo.nanopart.ess.server.dao;
|
||||||
|
|
||||||
import cn.axzo.nanopart.ess.api.utils.YesOrNo;
|
import cn.axzo.nanopart.ess.api.utils.YesOrNo;
|
||||||
import cn.axzo.nanopart.ess.server.dao.domain.OuAndPersonId;
|
|
||||||
import cn.axzo.nanopart.ess.server.entity.EssSealPerson;
|
import cn.axzo.nanopart.ess.server.entity.EssSealPerson;
|
||||||
import cn.axzo.nanopart.ess.server.mapper.EssSealPersonMapper;
|
import cn.axzo.nanopart.ess.server.mapper.EssSealPersonMapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
@ -10,6 +9,7 @@ import org.springframework.stereotype.Repository;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@ -26,6 +26,7 @@ public class EssSealPersonDao extends ServiceImpl<EssSealPersonMapper, EssSealPe
|
|||||||
.set(authorizedByPersonId != null && authorizedByPersonId > 0,
|
.set(authorizedByPersonId != null && authorizedByPersonId > 0,
|
||||||
EssSealPerson::getAuthorizedByPersonId, authorizedByPersonId)
|
EssSealPerson::getAuthorizedByPersonId, authorizedByPersonId)
|
||||||
.set(EssSealPerson::getIsAuthorized, YesOrNo.YES)
|
.set(EssSealPerson::getIsAuthorized, YesOrNo.YES)
|
||||||
|
.set(EssSealPerson::getAuthorizeTime, new Date())
|
||||||
.update();
|
.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,13 +38,6 @@ public class EssSealPersonDao extends ServiceImpl<EssSealPersonMapper, EssSealPe
|
|||||||
.update();
|
.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<EssSealPerson> findBySealAndPersonId(String essSealId, Long personId) {
|
|
||||||
return lambdaQuery()
|
|
||||||
.eq(EssSealPerson::getEssSealId, essSealId)
|
|
||||||
.eq(EssSealPerson::getPersonId, personId)
|
|
||||||
.oneOpt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<EssSealPerson> getBySealAndPersonIds(String essSealId, Collection<Long> personIds) {
|
public List<EssSealPerson> getBySealAndPersonIds(String essSealId, Collection<Long> personIds) {
|
||||||
if (CollectionUtils.isEmpty(personIds))
|
if (CollectionUtils.isEmpty(personIds))
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@ -53,19 +47,6 @@ public class EssSealPersonDao extends ServiceImpl<EssSealPersonMapper, EssSealPe
|
|||||||
.list();
|
.list();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<EssSealPerson> getByOuAndPersonIds(Collection<OuAndPersonId> ouAndPersonIds) {
|
|
||||||
if (CollectionUtils.isEmpty(ouAndPersonIds))
|
|
||||||
return Collections.emptyList();
|
|
||||||
return lambdaQuery()
|
|
||||||
.nested(w -> {
|
|
||||||
for (OuAndPersonId ouAndPersonId : ouAndPersonIds) {
|
|
||||||
w.or().eq(EssSealPerson::getOuId, ouAndPersonId.getOuId())
|
|
||||||
.eq(EssSealPerson::getPersonId, ouAndPersonId.getPersonId());
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.list();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<EssSealPerson> find(String essSealId, Long personId) {
|
public Optional<EssSealPerson> find(String essSealId, Long personId) {
|
||||||
return find(essSealId, personId, false);
|
return find(essSealId, personId, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,20 +3,20 @@ package cn.axzo.nanopart.ess.server.entity;
|
|||||||
import cn.axzo.foundation.dao.support.mysql.type.BaseListTypeHandler;
|
import cn.axzo.foundation.dao.support.mysql.type.BaseListTypeHandler;
|
||||||
import cn.axzo.nanopart.ess.api.domain.contract.Approver;
|
import cn.axzo.nanopart.ess.api.domain.contract.Approver;
|
||||||
import cn.axzo.nanopart.ess.api.domain.contract.EssApproveDetail;
|
import cn.axzo.nanopart.ess.api.domain.contract.EssApproveDetail;
|
||||||
|
import cn.axzo.nanopart.ess.api.enums.Constraint;
|
||||||
import cn.axzo.nanopart.ess.api.enums.EssContractState;
|
import cn.axzo.nanopart.ess.api.enums.EssContractState;
|
||||||
import cn.axzo.nanopart.ess.api.utils.YesOrNo;
|
import cn.axzo.nanopart.ess.server.entity.domain.Assignment;
|
||||||
import cn.axzo.nanopart.ess.api.enums.ApproverAssignType;
|
|
||||||
import cn.axzo.nanopart.ess.server.entity.domain.AssignedApprovers;
|
|
||||||
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
|
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.nacos.common.utils.UuidUtils;
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
|
import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
import javax.swing.table.DefaultTableCellRenderer;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yanglin
|
* @author yanglin
|
||||||
@ -34,7 +34,7 @@ public class EssContract extends BaseEntity<EssContract> {
|
|||||||
/**
|
/**
|
||||||
* 业务编码
|
* 业务编码
|
||||||
*/
|
*/
|
||||||
private String bizCode;
|
private String bizCode = UuidUtils.generateUuid();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 合同发起方单位id
|
* 合同发起方单位id
|
||||||
@ -67,11 +67,6 @@ public class EssContract extends BaseEntity<EssContract> {
|
|||||||
*/
|
*/
|
||||||
private EssContractState state;
|
private EssContractState state;
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否为动态签署人
|
|
||||||
*/
|
|
||||||
private YesOrNo isDynamicApprover;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 合并签署方信息
|
* 合并签署方信息
|
||||||
*/
|
*/
|
||||||
@ -79,10 +74,10 @@ public class EssContract extends BaseEntity<EssContract> {
|
|||||||
private List<Approver> approvers;
|
private List<Approver> approvers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 动态签署人信息
|
* 签署信息(扩展字段)
|
||||||
*/
|
*/
|
||||||
@TableField(typeHandler = FastjsonTypeHandler.class)
|
@TableField(typeHandler = FastjsonTypeHandler.class)
|
||||||
private AssignedApprovers assignedApprovers;
|
private Assignment assignment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 签署方的签署情况
|
* 签署方的签署情况
|
||||||
@ -101,27 +96,49 @@ public class EssContract extends BaseEntity<EssContract> {
|
|||||||
@TableField(typeHandler = FastjsonTypeHandler.class)
|
@TableField(typeHandler = FastjsonTypeHandler.class)
|
||||||
private RecordExt recordExt;
|
private RecordExt recordExt;
|
||||||
|
|
||||||
public boolean isDynamicApprover() {
|
public Assignment getOrCreateAssignment() {
|
||||||
return isDynamicApprover.isYes();
|
if (assignment == null)
|
||||||
|
assignment = new Assignment();
|
||||||
|
return assignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOrgSigned(Long ouId) {
|
public boolean isOrgSigned(Long ouId) {
|
||||||
if (approveDetails == null)
|
if (approveDetails == null)
|
||||||
return false;
|
return false;
|
||||||
return approveDetails.stream()
|
return approveDetails.stream()
|
||||||
.anyMatch(detail -> detail.getOuId().equals(ouId));
|
.anyMatch(detail -> ouId.equals(detail.getOuId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int preciseApproverSize() {
|
public int approverSize() {
|
||||||
return approvers.size();
|
return approvers == null ? 0 : approvers.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Approver getPreciseApprover(Integer idx) {
|
public Approver getApprover(Integer idx) {
|
||||||
return approvers.get(idx);
|
return approvers == null ? null : approvers.get(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApproverAssignType getAssignType() {
|
public Optional<Approver> findApproverByRecipientId(String recipientId) {
|
||||||
return assignedApprovers == null ? null : assignedApprovers.getAssignType();
|
if (approvers == null)
|
||||||
|
return Optional.empty();
|
||||||
|
return approvers.stream()
|
||||||
|
.filter(approver -> approver.getEssRecipientId().equals(recipientId))
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Constraint getAssignType() {
|
||||||
|
return assignment == null ? null : assignment.getConstraint();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAllSignPersonPreset() {
|
||||||
|
return approvers.stream().allMatch(Approver::isSignPersonPresent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFinalState() {
|
||||||
|
return state.isFinalState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Constraint getConstraint() {
|
||||||
|
return assignment == null ? null : assignment.getConstraint();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -48,6 +48,10 @@ public class EssOrg extends BaseEntity<EssOrg> {
|
|||||||
@TableField(typeHandler = FastjsonTypeHandler.class)
|
@TableField(typeHandler = FastjsonTypeHandler.class)
|
||||||
private RecordExt recordExt;
|
private RecordExt recordExt;
|
||||||
|
|
||||||
|
public boolean isAuthorized() {
|
||||||
|
return isAuthorized.isYes();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return JSON.toJSONString(this);
|
return JSON.toJSONString(this);
|
||||||
|
|||||||
@ -10,6 +10,8 @@ import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yanglin
|
* @author yanglin
|
||||||
*/
|
*/
|
||||||
@ -43,12 +45,21 @@ public class EssSealPerson extends BaseEntity<EssSealPerson> implements OrgPerso
|
|||||||
*/
|
*/
|
||||||
private Long authorizedByPersonId;
|
private Long authorizedByPersonId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权时间
|
||||||
|
*/
|
||||||
|
private Date authorizeTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 扩展字段
|
* 扩展字段
|
||||||
*/
|
*/
|
||||||
@TableField(typeHandler = FastjsonTypeHandler.class)
|
@TableField(typeHandler = FastjsonTypeHandler.class)
|
||||||
private RecordExt recordExt;
|
private RecordExt recordExt;
|
||||||
|
|
||||||
|
public boolean isAuthorized() {
|
||||||
|
return isAuthorized.isYes();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return JSON.toJSONString(this);
|
return JSON.toJSONString(this);
|
||||||
|
|||||||
@ -1,18 +0,0 @@
|
|||||||
package cn.axzo.nanopart.ess.server.entity.domain;
|
|
||||||
|
|
||||||
import cn.axzo.nanopart.ess.api.enums.ApproverAssignType;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author yanglin
|
|
||||||
*/
|
|
||||||
@Setter
|
|
||||||
@Getter
|
|
||||||
public class AssignedApprovers {
|
|
||||||
|
|
||||||
private ApproverAssignType assignType;
|
|
||||||
|
|
||||||
private SignByOrg signByOrg = new SignByOrg();
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package cn.axzo.nanopart.ess.server.entity.domain;
|
||||||
|
|
||||||
|
import cn.axzo.nanopart.ess.api.enums.Constraint;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yanglin
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class Assignment {
|
||||||
|
|
||||||
|
private Constraint constraint;
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,74 +0,0 @@
|
|||||||
package cn.axzo.nanopart.ess.server.entity.domain;
|
|
||||||
|
|
||||||
import cn.axzo.basics.common.exception.ServiceException;
|
|
||||||
import cn.axzo.nanopart.ess.api.domain.contract.Approver;
|
|
||||||
import cn.axzo.nanopart.ess.server.utils.BizAssertions;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author yanglin
|
|
||||||
*/
|
|
||||||
@Setter @Getter
|
|
||||||
public class SignByOrg {
|
|
||||||
|
|
||||||
private final List<OrgRecipientId> recipientIds = new ArrayList<>();
|
|
||||||
|
|
||||||
public Approver getApproverOrThrow(List<Approver> approvers, String recipientId) {
|
|
||||||
return approvers.stream()
|
|
||||||
.filter(a -> a.getEssRecipientId().equals(recipientId))
|
|
||||||
.findFirst()
|
|
||||||
.orElseThrow(InternalError::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String assign(List<Approver> approvers, Long ouId, @Nullable String recipientId) {
|
|
||||||
if (recipientId != null) {
|
|
||||||
OrgRecipientId saved = findByRecipientId(recipientId).orElse(null);
|
|
||||||
if (saved != null)
|
|
||||||
BizAssertions.assertTrue(saved.getOuId().equals(ouId), "签署编号已被其它单位占用");
|
|
||||||
else
|
|
||||||
addRecipientId(ouId, recipientId);
|
|
||||||
return recipientId;
|
|
||||||
} else {
|
|
||||||
OrgRecipientId assigned = findByOuId(ouId).orElse(null);
|
|
||||||
if (assigned != null)
|
|
||||||
return assigned.getRecipientId();
|
|
||||||
for (Approver approver : approvers) {
|
|
||||||
if (isRecipientIdUsed(approver.getEssRecipientId()))
|
|
||||||
continue;
|
|
||||||
addRecipientId(ouId, approver.getEssRecipientId());
|
|
||||||
return approver.getEssRecipientId();
|
|
||||||
}
|
|
||||||
throw new ServiceException("签署编号已经用完, 无法将指定新的单位");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRecipientIdUsed(String recipientId) {
|
|
||||||
return findByRecipientId(recipientId).isPresent();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<OrgRecipientId> findByRecipientId(String recipientId) {
|
|
||||||
return recipientIds.stream()
|
|
||||||
.filter(r -> r.getRecipientId().equals(recipientId))
|
|
||||||
.findFirst();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<OrgRecipientId> findByOuId(Long ouId) {
|
|
||||||
return recipientIds.stream()
|
|
||||||
.filter(id -> id.getOuId().equals(ouId))
|
|
||||||
.findFirst();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addRecipientId(Long ouId, String recipientId) {
|
|
||||||
recipientIds.add(new OrgRecipientId() {{
|
|
||||||
setOuId(ouId);
|
|
||||||
setRecipientId(recipientId);
|
|
||||||
}});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,44 +1,30 @@
|
|||||||
package cn.axzo.nanopart.ess.server.ess;
|
package cn.axzo.nanopart.ess.server.ess;
|
||||||
|
|
||||||
import cn.axzo.basics.common.exception.ServiceException;
|
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.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.EssContractState;
|
||||||
import cn.axzo.nanopart.ess.api.enums.EssSealType;
|
import cn.axzo.nanopart.ess.api.request.CreateContractByFileRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.AssignWeixinAppUrlByOrgRequest;
|
|
||||||
import cn.axzo.nanopart.ess.api.request.CreateContractRequest;
|
|
||||||
import cn.axzo.nanopart.ess.api.request.RevokeContractRequest;
|
import cn.axzo.nanopart.ess.api.request.RevokeContractRequest;
|
||||||
import cn.axzo.nanopart.ess.api.response.CreateContractResponse;
|
import cn.axzo.nanopart.ess.api.response.CreateContractByFileResponse;
|
||||||
import cn.axzo.nanopart.ess.server.dao.EssContractDao;
|
import cn.axzo.nanopart.ess.server.dao.EssContractDao;
|
||||||
import cn.axzo.nanopart.ess.server.dao.EssOrgDao;
|
import cn.axzo.nanopart.ess.server.dao.EssLogDao;
|
||||||
import cn.axzo.nanopart.ess.server.dao.EssPersonDao;
|
|
||||||
import cn.axzo.nanopart.ess.server.dao.EssSealDao;
|
|
||||||
import cn.axzo.nanopart.ess.server.dao.EssSealPersonDao;
|
|
||||||
import cn.axzo.nanopart.ess.server.dao.domain.OuAndPersonId;
|
|
||||||
import cn.axzo.nanopart.ess.server.entity.EssContract;
|
import cn.axzo.nanopart.ess.server.entity.EssContract;
|
||||||
import cn.axzo.nanopart.ess.server.entity.EssOrg;
|
|
||||||
import cn.axzo.nanopart.ess.server.entity.EssPerson;
|
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.domain.JsonObjectAsString;
|
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.ContractSupport;
|
||||||
import cn.axzo.nanopart.ess.server.ess.support.EssSupport;
|
|
||||||
import cn.axzo.nanopart.ess.server.utils.BizAssertions;
|
import cn.axzo.nanopart.ess.server.utils.BizAssertions;
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
|
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
|
||||||
|
import com.tencentcloudapi.essbasic.v20210526.models.ApproverItem;
|
||||||
import com.tencentcloudapi.essbasic.v20210526.models.ChannelCreateFlowByFilesResponse;
|
import com.tencentcloudapi.essbasic.v20210526.models.ChannelCreateFlowByFilesResponse;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
|
||||||
import org.springframework.dao.DuplicateKeyException;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static cn.axzo.nanopart.ess.server.utils.BizAssertions.fail;
|
||||||
import static java.util.stream.Collectors.toList;
|
import static java.util.stream.Collectors.toList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -53,90 +39,53 @@ public class ContractManager {
|
|||||||
|
|
||||||
private final OrgManager orgManager;
|
private final OrgManager orgManager;
|
||||||
private final EssClient essClient;
|
private final EssClient essClient;
|
||||||
private final EssOrgDao essOrgDao;
|
|
||||||
private final EssContractDao essContractDao;
|
private final EssContractDao essContractDao;
|
||||||
private final Broadcaster broadcaster;
|
private final EssBroadcaster essBroadcaster;
|
||||||
private final EssPersonDao essPersonDao;
|
private final ContractSupport contractSupport;
|
||||||
private final EssSealDao essSealDao;
|
private final EssLogDao essLogDao;
|
||||||
private final EssSealPersonDao essSealPersonDao;
|
|
||||||
private final EssSupport essSupport;
|
|
||||||
|
|
||||||
public CreateContractResponse createContract(CreateContractRequest request) {
|
@Transactional
|
||||||
checkPermission(request);
|
public CreateContractByFileResponse
|
||||||
EssContract contract = saveContract(request);
|
createContractByFile(CreateContractByFileRequest request) {
|
||||||
|
essLogDao.logRequest("createContractByFile", request.getBizCode(), request);
|
||||||
|
contractSupport.validateCreateContract(request.getContract());
|
||||||
|
EssContract contract = contractSupport.saveContractByFile(request);
|
||||||
try {
|
try {
|
||||||
EssPerson superAdmin = orgManager.getSuperAdminOrThrow(request.getOperator().getOuId());
|
EssPerson superAdmin = orgManager.getSuperAdminOrThrow(request.getCreator().getOuId());
|
||||||
List<String> essFileIds = essClient.uploadDocument(
|
List<String> essFileIds = essClient.uploadDocument(superAdmin, request.getByFile().getBase64Files());
|
||||||
superAdmin, request.getByFile().getBase64Files());
|
|
||||||
ChannelCreateFlowByFilesResponse essResponse = essClient.createContractByFile(
|
ChannelCreateFlowByFilesResponse essResponse = essClient.createContractByFile(
|
||||||
superAdmin, essFileIds, request.getByFile(),
|
superAdmin, essFileIds, request.getByFile(),
|
||||||
JsonObjectAsString.create().put(CONTRACT_ID, contract.getId()).toString());
|
JsonObjectAsString.create().put(CONTRACT_ID, contract.getId()).toString());
|
||||||
List<String> essRecipientIds = EssSupport.collectRecipientIds(essResponse.getApprovers());
|
List<String> essRecipientIds = Arrays.stream(essResponse.getApprovers())
|
||||||
for (int i = 0; i < contract.preciseApproverSize(); i++) {
|
.map(ApproverItem::getRecipientId)
|
||||||
Approver approver = contract.getPreciseApprover(i);
|
.collect(toList());
|
||||||
approver.setEssRecipientId(essRecipientIds.get(i));
|
for (int i = 0; i < contract.approverSize(); i++)
|
||||||
}
|
contract.getApprover(i).setEssRecipientId(essRecipientIds.get(i));
|
||||||
essContractDao.setEssContractCreated(
|
essContractDao.setEssContractCreated(
|
||||||
contract.getId(), essResponse.getFlowId(),
|
contract.getId(), essResponse.getFlowId(),
|
||||||
essFileIds, contract.getApprovers());
|
essFileIds, contract.getApprovers());
|
||||||
contract = essContractDao.getOrThrow(essResponse.getFlowId());
|
contract = essContractDao.getOrThrow(essResponse.getFlowId());
|
||||||
broadcaster.fireContractStateChanged(contract);
|
essBroadcaster.fireContractStateChanged(contract);
|
||||||
CreateContractResponse response = new CreateContractResponse();
|
CreateContractByFileResponse response = new CreateContractByFileResponse();
|
||||||
response.setEssContractId(essResponse.getFlowId());
|
response.setEssContractId(essResponse.getFlowId());
|
||||||
response.setEssRecipientIds(essRecipientIds);
|
response.setEssRecipientIds(essRecipientIds);
|
||||||
return response;
|
return response;
|
||||||
} catch (TencentCloudSDKException e) {
|
} catch (TencentCloudSDKException | ServiceException e) {
|
||||||
log.warn("创建合同失败", e);
|
log.warn("创建合同失败", e);
|
||||||
if (contract != null)
|
if (contract != null)
|
||||||
essContractDao.removeById(contract.getId());
|
essContractDao.removeById(contract.getId());
|
||||||
throw new ServiceException("创建合同失败: " + e.getMessage());
|
throw fail("创建合同失败: {}", e.getMessage());
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkPermission(CreateContractRequest request) {
|
|
||||||
BizAssertions.assertNotNull(request.getByFile(), "合同PDF文件不能为空");
|
|
||||||
List<EssOrg> orgs = essOrgDao.getByOuIds(request.getByFile().getApproverOuIds());
|
|
||||||
List<String> notAuthorizedOrgs = orgs.stream()
|
|
||||||
.filter(i -> i.getIsAuthorized().isNo())
|
|
||||||
.map(EssOrg::getOuName)
|
|
||||||
.collect(toList());
|
|
||||||
BizAssertions.assertEmpty(notAuthorizedOrgs,
|
|
||||||
"创建合同失败. 以下单位还未认证: {}", JSON.toJSONString(notAuthorizedOrgs));
|
|
||||||
SealPersons sealPersons = SealPersons.wrap(getApproverAsSealPersons(request));
|
|
||||||
for (Approver approver : request.getByFile().getApprovers()) {
|
|
||||||
if (approver.getSignPerson() == null) continue;
|
|
||||||
EssSealPerson sealPerson = sealPersons.find(
|
|
||||||
approver.getOuId(), approver.getPersonId()).orElse(null);
|
|
||||||
BizAssertions.assertFalse(sealPerson == null || sealPerson.getIsAuthorized().isNo(),
|
|
||||||
"创建合同失败. 部分签署人员没有印章授权, ouId={}, personId={}", approver.getOuId(), approver.getPersonId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<EssSealPerson> getApproverAsSealPersons(CreateContractRequest request) {
|
|
||||||
List<OuAndPersonId> ouAndPersonIds = request.getByFile().getApprovers().stream()
|
|
||||||
.map(approver -> OuAndPersonId.create(approver.getOuId(), approver.getPersonId()))
|
|
||||||
.distinct()
|
|
||||||
.collect(toList());
|
|
||||||
return essSealPersonDao.getByOuAndPersonIds(ouAndPersonIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
private EssContract saveContract(CreateContractRequest request) {
|
|
||||||
try {
|
|
||||||
EssContract contract = essSupport.createContract(request);
|
|
||||||
essContractDao.save(contract);
|
|
||||||
return contract;
|
|
||||||
} catch (DuplicateKeyException e) {
|
|
||||||
throw new ServiceException("创建合同失败. 重复的业务编号: " + request.getBizCode());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void revokeContract(RevokeContractRequest request) {
|
public void revokeContract(RevokeContractRequest request) {
|
||||||
|
essLogDao.logRequest("revokeContract", request.getEssContractId(), request);
|
||||||
EssContract contract = essContractDao.getOrThrow(request.getEssContractId());
|
EssContract contract = essContractDao.getOrThrow(request.getEssContractId());
|
||||||
BizAssertions.assertFalse(contract.getState().isFinalState(),
|
BizAssertions.assertFalse(contract.isFinalState(),
|
||||||
"合同已是最终状态[{}], 无法撤销", contract.getState().getDescription());
|
"合同已是最终状态 {}, 无法撤销", contract.getState().getDescription());
|
||||||
EssPerson contractCreator = getContractCreatorOrThrow(contract);
|
EssPerson superAdmin = getContractSuperAdmin(contract);
|
||||||
essClient.revokeContract(contractCreator, contract.getEssContractId(), request.getReason());
|
essClient.revokeContract(superAdmin, contract.getEssContractId(), request.getReason());
|
||||||
updateContractState(contract, EssContractState.CANCEL, null);
|
updateContractState(contract, EssContractState.CANCEL, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,61 +93,19 @@ public class ContractManager {
|
|||||||
public void updateContractState(EssContract contract,
|
public void updateContractState(EssContract contract,
|
||||||
EssContractState state,
|
EssContractState state,
|
||||||
List<EssApproveDetail> approveDetails) {
|
List<EssApproveDetail> approveDetails) {
|
||||||
EssContract reloadContract = essContractDao
|
EssContract reloadContract = essContractDao.findForUpdateOrNull(contract.getEssContractId());
|
||||||
.find(contract.getEssContractId(), true)
|
|
||||||
.orElse(null);
|
|
||||||
BizAssertions.assertNotNull(reloadContract, "合同不存在: {}", contract.getEssContractId());
|
BizAssertions.assertNotNull(reloadContract, "合同不存在: {}", contract.getEssContractId());
|
||||||
//noinspection DataFlowIssue
|
if (reloadContract.isFinalState()) {
|
||||||
if (reloadContract.getState().isFinalState()) {
|
log.warn("合同[{}]已是最终状态[{}], 无法更新状态至{}",
|
||||||
log.warn("合同[{}]已是最终状态[{}], 无法更新状态",
|
reloadContract.getEssContractId(), reloadContract.getState(), state);
|
||||||
reloadContract.getEssContractId(),
|
|
||||||
reloadContract.getState().getDescription());
|
|
||||||
} else {
|
} else {
|
||||||
essContractDao.updateState(contract, state, approveDetails);
|
essContractDao.updateState(contract, state, approveDetails);
|
||||||
broadcaster.fireContractStateChanged(contract);
|
essBroadcaster.fireContractStateChanged(contract);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
public EssPerson getContractSuperAdmin(EssContract contract) {
|
||||||
public String assignRecipientIdByOrg(AssignWeixinAppUrlByOrgRequest request) {
|
return orgManager.getSuperAdminOrThrow(contract.getCreatorOuId());
|
||||||
EssContract contract = essContractDao.find(request.getEssContractId(), true).orElse(null);
|
|
||||||
BizAssertions.assertNotNull(contract, "找不到合同信息, essContractId={}", request.getEssContractId());
|
|
||||||
//noinspection DataFlowIssue
|
|
||||||
BizAssertions.assertEquals(ApproverAssignType.ONE_PERSON_PER_ORG, contract.getAssignType(), "签署方式不正确");
|
|
||||||
String recipientId = contract.getAssignedApprovers()
|
|
||||||
.getSignByOrg()
|
|
||||||
.assign(contract.getApprovers(), request.getOuId(), request.getRecipientId());
|
|
||||||
Approver approver = contract.getAssignedApprovers()
|
|
||||||
.getSignByOrg()
|
|
||||||
.getApproverOrThrow(contract.getApprovers(), recipientId);
|
|
||||||
checkApproverSeals(request, approver.getSealTypes());
|
|
||||||
essContractDao.updateAssignedApprovers(contract);
|
|
||||||
return recipientId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkApproverSeals(OrgPerson person, List<EssSealType> sealTypes) {
|
|
||||||
if (CollectionUtils.isEmpty(sealTypes))
|
|
||||||
sealTypes = Arrays.stream(EssSealType.values()).collect(toList());
|
|
||||||
List<EssSeal> seals = essSealDao
|
|
||||||
.getByOrgAndSealTypes(person.getOuId(), sealTypes);
|
|
||||||
BizAssertions.assertNotEmpty(seals, "单位没有指定类型的印章");
|
|
||||||
boolean found = false;
|
|
||||||
for (EssSeal seal : seals) {
|
|
||||||
EssSealPerson sealPerson = essSealPersonDao
|
|
||||||
.findBySealAndPersonId(seal.getEssSealId(), person.getPersonId())
|
|
||||||
.orElse(null);
|
|
||||||
found = sealPerson != null;
|
|
||||||
if (found)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
BizAssertions.assertTrue(found, "签署人员没有指定类型的印章");
|
|
||||||
}
|
|
||||||
|
|
||||||
public EssPerson getContractCreatorOrThrow(EssContract contract) {
|
|
||||||
EssPerson creator = essPersonDao.findOrNull(
|
|
||||||
contract.getCreatorOuId(), contract.getCreatorPersonId());
|
|
||||||
BizAssertions.assertNotNull(creator, "找不到合同发起人信息");
|
|
||||||
return creator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -16,14 +16,15 @@ import org.springframework.stereotype.Component;
|
|||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
class Broadcaster {
|
class EssBroadcaster {
|
||||||
|
|
||||||
private final EssContractDao essContractDao;
|
private final EssContractDao essContractDao;
|
||||||
protected final EventProducer<?> eventProducer;
|
protected final EventProducer<?> eventProducer;
|
||||||
|
|
||||||
void fireContractStateChanged(EssContract contract) {
|
void fireContractStateChanged(EssContract contract) {
|
||||||
EssContract reloadContract = essContractDao
|
EssContract reloadContract = essContractDao.findOrNull(contract.getEssContractId());
|
||||||
.find(contract.getEssContractId()).orElse(null);
|
if (reloadContract == null)
|
||||||
|
return;
|
||||||
EssContractStateChangeMessage message = new EssContractStateChangeMessage();
|
EssContractStateChangeMessage message = new EssContractStateChangeMessage();
|
||||||
message.setContract(BeanMapper.copyBean(reloadContract, EssContractInfo.class));
|
message.setContract(BeanMapper.copyBean(reloadContract, EssContractInfo.class));
|
||||||
eventProducer.send(Event.builder()
|
eventProducer.send(Event.builder()
|
||||||
@ -1,13 +1,12 @@
|
|||||||
package cn.axzo.nanopart.ess.server.ess;
|
package cn.axzo.nanopart.ess.server.ess;
|
||||||
|
|
||||||
import cn.axzo.basics.common.exception.ServiceException;
|
|
||||||
import cn.axzo.basics.profiles.dto.basic.PersonProfileDto;
|
import cn.axzo.basics.profiles.dto.basic.PersonProfileDto;
|
||||||
import cn.axzo.maokai.api.vo.response.OrganizationalUnitVO;
|
import cn.axzo.maokai.api.vo.response.OrganizationalUnitVO;
|
||||||
|
import cn.axzo.nanopart.ess.api.domain.CreateContractInfo;
|
||||||
import cn.axzo.nanopart.ess.api.domain.OrgPerson;
|
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.Approver;
|
||||||
import cn.axzo.nanopart.ess.api.enums.EssConsoleUrlEndpoint;
|
import cn.axzo.nanopart.ess.api.enums.EssConsoleUrlEndpoint;
|
||||||
import cn.axzo.nanopart.ess.api.enums.EssEmbedType;
|
import cn.axzo.nanopart.ess.api.enums.EssEmbedType;
|
||||||
import cn.axzo.nanopart.ess.api.request.CreateContractInfo;
|
|
||||||
import cn.axzo.nanopart.ess.api.utils.YesOrNo;
|
import cn.axzo.nanopart.ess.api.utils.YesOrNo;
|
||||||
import cn.axzo.nanopart.ess.server.dao.EssLogDao;
|
import cn.axzo.nanopart.ess.server.dao.EssLogDao;
|
||||||
import cn.axzo.nanopart.ess.server.entity.EssLog;
|
import cn.axzo.nanopart.ess.server.entity.EssLog;
|
||||||
@ -35,7 +34,6 @@ import com.tencentcloudapi.essbasic.v20210526.models.ApproverOption;
|
|||||||
import com.tencentcloudapi.essbasic.v20210526.models.ChannelCancelFlowRequest;
|
import com.tencentcloudapi.essbasic.v20210526.models.ChannelCancelFlowRequest;
|
||||||
import com.tencentcloudapi.essbasic.v20210526.models.ChannelCreateEmbedWebUrlRequest;
|
import com.tencentcloudapi.essbasic.v20210526.models.ChannelCreateEmbedWebUrlRequest;
|
||||||
import com.tencentcloudapi.essbasic.v20210526.models.ChannelCreateEmbedWebUrlResponse;
|
import com.tencentcloudapi.essbasic.v20210526.models.ChannelCreateEmbedWebUrlResponse;
|
||||||
import com.tencentcloudapi.essbasic.v20210526.models.ChannelCreateFlowApproversRequest;
|
|
||||||
import com.tencentcloudapi.essbasic.v20210526.models.ChannelCreateFlowByFilesRequest;
|
import com.tencentcloudapi.essbasic.v20210526.models.ChannelCreateFlowByFilesRequest;
|
||||||
import com.tencentcloudapi.essbasic.v20210526.models.ChannelCreateFlowByFilesResponse;
|
import com.tencentcloudapi.essbasic.v20210526.models.ChannelCreateFlowByFilesResponse;
|
||||||
import com.tencentcloudapi.essbasic.v20210526.models.ChannelCreateOrganizationBatchSignUrlRequest;
|
import com.tencentcloudapi.essbasic.v20210526.models.ChannelCreateOrganizationBatchSignUrlRequest;
|
||||||
@ -51,7 +49,6 @@ import com.tencentcloudapi.essbasic.v20210526.models.CreateSignUrlsRequest;
|
|||||||
import com.tencentcloudapi.essbasic.v20210526.models.CreateSignUrlsResponse;
|
import com.tencentcloudapi.essbasic.v20210526.models.CreateSignUrlsResponse;
|
||||||
import com.tencentcloudapi.essbasic.v20210526.models.DescribeResourceUrlsByFlowsRequest;
|
import com.tencentcloudapi.essbasic.v20210526.models.DescribeResourceUrlsByFlowsRequest;
|
||||||
import com.tencentcloudapi.essbasic.v20210526.models.DescribeResourceUrlsByFlowsResponse;
|
import com.tencentcloudapi.essbasic.v20210526.models.DescribeResourceUrlsByFlowsResponse;
|
||||||
import com.tencentcloudapi.essbasic.v20210526.models.FillApproverInfo;
|
|
||||||
import com.tencentcloudapi.essbasic.v20210526.models.FlowApproverInfo;
|
import com.tencentcloudapi.essbasic.v20210526.models.FlowApproverInfo;
|
||||||
import com.tencentcloudapi.essbasic.v20210526.models.ProxyOrganizationOperator;
|
import com.tencentcloudapi.essbasic.v20210526.models.ProxyOrganizationOperator;
|
||||||
import com.tencentcloudapi.essbasic.v20210526.models.SyncProxyOrganizationOperatorsRequest;
|
import com.tencentcloudapi.essbasic.v20210526.models.SyncProxyOrganizationOperatorsRequest;
|
||||||
@ -62,6 +59,7 @@ import com.tencentcloudapi.essbasic.v20210526.models.UserInfo;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@ -81,6 +79,7 @@ import java.util.regex.Matcher;
|
|||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import static cn.axzo.nanopart.ess.server.ess.EssClient.Func.func;
|
import static cn.axzo.nanopart.ess.server.ess.EssClient.Func.func;
|
||||||
|
import static cn.axzo.nanopart.ess.server.utils.BizAssertions.fail;
|
||||||
import static java.util.stream.Collectors.toList;
|
import static java.util.stream.Collectors.toList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,8 +103,8 @@ public class EssClient implements InitializingBean {
|
|||||||
|
|
||||||
public String createConsoleLoginUrl(EssOrg org, EssPerson person,
|
public String createConsoleLoginUrl(EssOrg org, EssPerson person,
|
||||||
EssConsoleUrlEndpoint endpoint,
|
EssConsoleUrlEndpoint endpoint,
|
||||||
boolean checkOperator) {
|
boolean essCheckLoginPerson) {
|
||||||
PersonProfileDto personProfile = essSupport.getPersonProfileOrThrow(person.getPersonId());
|
PersonProfileDto personProfile = essSupport.getPersonProfileOrThrow(person);
|
||||||
CreateConsoleLoginUrlRequest request = new CreateConsoleLoginUrlRequest();
|
CreateConsoleLoginUrlRequest request = new CreateConsoleLoginUrlRequest();
|
||||||
request.setEndpoint(endpoint.getCode());
|
request.setEndpoint(endpoint.getCode());
|
||||||
request.setEndpoint(request.getEndpoint());
|
request.setEndpoint(request.getEndpoint());
|
||||||
@ -114,7 +113,7 @@ public class EssClient implements InitializingBean {
|
|||||||
if (props.isTestEnv())
|
if (props.isTestEnv())
|
||||||
orgName = orgName.replaceAll("中国", "zhongguo");
|
orgName = orgName.replaceAll("中国", "zhongguo");
|
||||||
request.setProxyOrganizationName(orgName);
|
request.setProxyOrganizationName(orgName);
|
||||||
if (checkOperator) {
|
if (essCheckLoginPerson) {
|
||||||
request.setProxyOperatorName(personProfile.getRealName());
|
request.setProxyOperatorName(personProfile.getRealName());
|
||||||
request.setProxyOperatorMobile(personProfile.getPhone());
|
request.setProxyOperatorMobile(personProfile.getPhone());
|
||||||
}
|
}
|
||||||
@ -129,11 +128,11 @@ public class EssClient implements InitializingBean {
|
|||||||
return response.getConsoleUrl();
|
return response.getConsoleUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getEmbedWebUrl(EssPerson superAdmin, EssEmbedType embedType, String businessId) {
|
public String getEmbedWebUrl(EssPerson contextPerson, EssEmbedType embedType, String businessId) {
|
||||||
if (embedType.isBusinessIdRequired())
|
if (embedType.isBusinessIdRequired())
|
||||||
BizAssertions.assertNotBlank(businessId, "内嵌类型为{}时业务ID不能为空", embedType.name());
|
BizAssertions.assertNotBlank(businessId, "内嵌类型为{}时业务ID不能为空", embedType.name());
|
||||||
ChannelCreateEmbedWebUrlRequest request = new ChannelCreateEmbedWebUrlRequest();
|
ChannelCreateEmbedWebUrlRequest request = new ChannelCreateEmbedWebUrlRequest();
|
||||||
request.setAgent(agent(superAdmin));
|
request.setAgent(agent(contextPerson));
|
||||||
request.setBusinessId(businessId);
|
request.setBusinessId(businessId);
|
||||||
request.setEmbedType(embedType.getEssCode());
|
request.setEmbedType(embedType.getEssCode());
|
||||||
request.setHiddenComponents(true);
|
request.setHiddenComponents(true);
|
||||||
@ -211,28 +210,25 @@ public class EssClient implements InitializingBean {
|
|||||||
List<String> contractFileIds,
|
List<String> contractFileIds,
|
||||||
CreateContractInfo contract,
|
CreateContractInfo contract,
|
||||||
String customerData) throws TencentCloudSDKException {
|
String customerData) throws TencentCloudSDKException {
|
||||||
OrgProfiles orgProfiles = OrgProfiles.empty();
|
OrgProfiles orgProfiles = OrgProfiles.wrap(essSupport
|
||||||
PersonProfiles personProfiles = PersonProfiles.empty();
|
.getOrgProfiles(contract.getApprovers().stream()
|
||||||
if (!contract.isDynamicApprover()) {
|
.filter(Approver::isSignPersonPresent)
|
||||||
orgProfiles = OrgProfiles.wrap(essSupport
|
.map(Approver::getOuId)
|
||||||
.getOrgProfiles(contract.getApprovers().stream()
|
.collect(toList())));
|
||||||
.map(Approver::getOuId)
|
PersonProfiles personProfiles = PersonProfiles.wrap(essSupport
|
||||||
.collect(toList())));
|
.getPersonProfiles(contract.getApprovers().stream()
|
||||||
personProfiles = PersonProfiles.wrap(essSupport
|
.filter(Approver::isSignPersonPresent)
|
||||||
.getPersonProfiles(contract.getApprovers().stream()
|
.map(Approver::getPersonId)
|
||||||
.map(Approver::getPersonId)
|
.collect(toList())));
|
||||||
.collect(toList())));
|
|
||||||
}
|
|
||||||
ArrayList<FlowApproverInfo> approvers = new ArrayList<>();
|
ArrayList<FlowApproverInfo> approvers = new ArrayList<>();
|
||||||
for (Approver approver : contract.getApprovers()) {
|
for (Approver approver : contract.getApprovers()) {
|
||||||
FlowApproverInfo approverInfo = new FlowApproverInfo();
|
FlowApproverInfo approverInfo = new FlowApproverInfo();
|
||||||
approvers.add(approverInfo);
|
approvers.add(approverInfo);
|
||||||
if (contract.isDynamicApprover()) {
|
if (approver.getSignPerson() == null) {
|
||||||
ApproverOption approverOption = new ApproverOption();
|
ApproverOption approverOption = new ApproverOption();
|
||||||
approverOption.setFillType(1L);
|
approverOption.setFillType(1L);
|
||||||
approverInfo.setApproverOption(approverOption);
|
approverInfo.setApproverOption(approverOption);
|
||||||
} else {
|
} else {
|
||||||
BizAssertions.assertNotNull(approver.getSignPerson(), "非动态签署人合同, 签署人不能为空");
|
|
||||||
OrganizationalUnitVO orgProfile = orgProfiles.getOrThrow(approver.getOuId());
|
OrganizationalUnitVO orgProfile = orgProfiles.getOrThrow(approver.getOuId());
|
||||||
PersonProfileDto personProfile = personProfiles.getOrThrow(approver.getPersonId());
|
PersonProfileDto personProfile = personProfiles.getOrThrow(approver.getPersonId());
|
||||||
approverInfo.setName(personProfile.getRealName());
|
approverInfo.setName(personProfile.getRealName());
|
||||||
@ -271,36 +267,9 @@ public class EssClient implements InitializingBean {
|
|||||||
.command(() -> manage.ChannelCreateFlowByFiles(request)));
|
.command(() -> manage.ChannelCreateFlowByFiles(request)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assignApprover(String essContractId,
|
void revokeContract(EssPerson superAdmin, String essContractId, String reason) {
|
||||||
EssPerson contractCreator,
|
|
||||||
OrgPerson approver,
|
|
||||||
String recipientId) {
|
|
||||||
OrganizationalUnitVO orgProfile = essSupport
|
|
||||||
.getOrgProfileOrThrow(approver.getOuId());
|
|
||||||
PersonProfileDto personProfile = essSupport
|
|
||||||
.getPersonProfileOrThrow(approver.getPersonId());
|
|
||||||
FillApproverInfo approverInfo = new FillApproverInfo();
|
|
||||||
approverInfo.setRecipientId(recipientId);
|
|
||||||
approverInfo.setApproverName(personProfile.getRealName());
|
|
||||||
approverInfo.setApproverMobile(personProfile.getPhone());
|
|
||||||
approverInfo.setOpenId(PersonOpenId.create(approver).toOpenId());
|
|
||||||
approverInfo.setOrganizationName(orgProfile.getName());
|
|
||||||
approverInfo.setOrganizationOpenId(OrgOpenId.ofPerson(approver).toOpenId());
|
|
||||||
ChannelCreateFlowApproversRequest request = new ChannelCreateFlowApproversRequest();
|
|
||||||
request.setAgent(agent(contractCreator));
|
|
||||||
request.setFlowId(essContractId);
|
|
||||||
request.setFillApproverType(1L);
|
|
||||||
request.setApprovers(new FillApproverInfo[]{approverInfo});
|
|
||||||
exec(func()
|
|
||||||
.context("ChannelCreateFlowApprovers")
|
|
||||||
.subject(essContractId)
|
|
||||||
.request(request)
|
|
||||||
.command(() -> manage.ChannelCreateFlowApprovers(request)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void revokeContract(EssPerson contractCreator, String essContractId, String reason) {
|
|
||||||
ChannelCancelFlowRequest request = new ChannelCancelFlowRequest();
|
ChannelCancelFlowRequest request = new ChannelCancelFlowRequest();
|
||||||
request.setAgent(agent(contractCreator));
|
request.setAgent(agent(superAdmin));
|
||||||
request.setFlowId(essContractId);
|
request.setFlowId(essContractId);
|
||||||
request.setCancelMessage(reason);
|
request.setCancelMessage(reason);
|
||||||
exec(func()
|
exec(func()
|
||||||
@ -335,18 +304,20 @@ public class EssClient implements InitializingBean {
|
|||||||
return response.getSignUrl();
|
return response.getSignUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CreateSignUrlsResponse assignWeixinAppUrlByOrg(
|
public CreateSignUrlsResponse getWeixinAppSignUrl(
|
||||||
String essContractId, EssPerson creator,
|
String essContractId, EssPerson superAdmin,
|
||||||
OrgPerson signPerson, String recipientId) {
|
OrgPerson signPerson, String recipientId) {
|
||||||
CreateSignUrlsRequest request = new CreateSignUrlsRequest();
|
CreateSignUrlsRequest request = new CreateSignUrlsRequest();
|
||||||
request.setAgent(agent(creator));
|
request.setAgent(agent(superAdmin));
|
||||||
request.setFlowIds(new String[]{essContractId});
|
request.setFlowIds(new String[]{essContractId});
|
||||||
request.setOpenId(PersonOpenId.create(signPerson).toOpenId());
|
request.setOpenId(PersonOpenId.create(signPerson).toOpenId());
|
||||||
request.setOrganizationOpenId(OrgOpenId.ofPerson(signPerson).toOpenId());
|
request.setOrganizationOpenId(OrgOpenId.ofPerson(signPerson).toOpenId());
|
||||||
request.setRecipientIds(new String[]{recipientId});
|
if (StringUtils.isNotBlank(recipientId)) {
|
||||||
request.setGenerateType("RECIPIENT");
|
request.setRecipientIds(new String[]{recipientId});
|
||||||
|
request.setGenerateType("RECIPIENT");
|
||||||
|
}
|
||||||
return exec(func()
|
return exec(func()
|
||||||
.context("CreateSignUrls:assignWeixinAppUrlByOrg")
|
.context("CreateSignUrls")
|
||||||
.subject(essContractId)
|
.subject(essContractId)
|
||||||
.request(request)
|
.request(request)
|
||||||
.command(() -> manage.CreateSignUrls(request)));
|
.command(() -> manage.CreateSignUrls(request)));
|
||||||
@ -375,7 +346,7 @@ public class EssClient implements InitializingBean {
|
|||||||
.command(() -> manage.SyncProxyOrganizationOperators(request)));
|
.command(() -> manage.SyncProxyOrganizationOperators(request)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelDescribeEmployeesResponse getEmployees(EssPerson superAdmin, EssOrg org, Long offset) {
|
public ChannelDescribeEmployeesResponse getOrgPerson(EssPerson superAdmin, EssOrg org, Long offset) {
|
||||||
ChannelDescribeEmployeesRequest request = new ChannelDescribeEmployeesRequest();
|
ChannelDescribeEmployeesRequest request = new ChannelDescribeEmployeesRequest();
|
||||||
request.setAgent(agent(superAdmin));
|
request.setAgent(agent(superAdmin));
|
||||||
request.setOffset(offset);
|
request.setOffset(offset);
|
||||||
@ -417,7 +388,7 @@ public class EssClient implements InitializingBean {
|
|||||||
try {
|
try {
|
||||||
return call(builder);
|
return call(builder);
|
||||||
} catch (TencentCloudSDKException e) {
|
} catch (TencentCloudSDKException e) {
|
||||||
throw new ServiceException(String.format("腾讯返回: %s", e.getMessage()), e);
|
throw fail(e, String.format("腾讯返回: %s", e.getMessage()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,16 +1,18 @@
|
|||||||
package cn.axzo.nanopart.ess.server.ess;
|
package cn.axzo.nanopart.ess.server.ess;
|
||||||
|
|
||||||
import cn.axzo.basics.common.exception.ServiceException;
|
import cn.axzo.nanopart.ess.api.domain.OrgPerson;
|
||||||
import cn.axzo.nanopart.ess.api.enums.ApproverAssignType;
|
import cn.axzo.nanopart.ess.api.domain.contract.Approver;
|
||||||
|
import cn.axzo.nanopart.ess.api.enums.Constraint;
|
||||||
import cn.axzo.nanopart.ess.api.enums.EssEmbedType.EssContext;
|
import cn.axzo.nanopart.ess.api.enums.EssEmbedType.EssContext;
|
||||||
import cn.axzo.nanopart.ess.api.enums.SignUrlType;
|
import cn.axzo.nanopart.ess.api.enums.SignUrlEndpoint;
|
||||||
import cn.axzo.nanopart.ess.api.request.AddSealAuthorizationRequest;
|
import cn.axzo.nanopart.ess.api.request.AddSealAuthorizationRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.AssignWeixinAppUrlByOrgRequest;
|
|
||||||
import cn.axzo.nanopart.ess.api.request.CreateConsoleLoginUrlRequest;
|
import cn.axzo.nanopart.ess.api.request.CreateConsoleLoginUrlRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.GetEmbedWebUrlRequest;
|
import cn.axzo.nanopart.ess.api.request.GetEmbedWebUrlRequest;
|
||||||
|
import cn.axzo.nanopart.ess.api.request.GetSignUrlRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.RemoveSealAuthorizationRequest;
|
import cn.axzo.nanopart.ess.api.request.RemoveSealAuthorizationRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.SealAndPersonRequest;
|
import cn.axzo.nanopart.ess.api.request.SealAndPersonRequest;
|
||||||
import cn.axzo.nanopart.ess.server.dao.EssContractDao;
|
import cn.axzo.nanopart.ess.server.dao.EssContractDao;
|
||||||
|
import cn.axzo.nanopart.ess.server.dao.EssLogDao;
|
||||||
import cn.axzo.nanopart.ess.server.dao.EssPersonDao;
|
import cn.axzo.nanopart.ess.server.dao.EssPersonDao;
|
||||||
import cn.axzo.nanopart.ess.server.dao.EssSealDao;
|
import cn.axzo.nanopart.ess.server.dao.EssSealDao;
|
||||||
import cn.axzo.nanopart.ess.server.dao.EssSealPersonDao;
|
import cn.axzo.nanopart.ess.server.dao.EssSealPersonDao;
|
||||||
@ -21,6 +23,7 @@ import cn.axzo.nanopart.ess.server.entity.EssSealPerson;
|
|||||||
import cn.axzo.nanopart.ess.server.ess.domain.OrgAndPerson;
|
import cn.axzo.nanopart.ess.server.ess.domain.OrgAndPerson;
|
||||||
import cn.axzo.nanopart.ess.server.ess.domain.SealAndPerson;
|
import cn.axzo.nanopart.ess.server.ess.domain.SealAndPerson;
|
||||||
import cn.axzo.nanopart.ess.server.ess.support.EssProps;
|
import cn.axzo.nanopart.ess.server.ess.support.EssProps;
|
||||||
|
import cn.axzo.nanopart.ess.server.ess.support.EssSupport;
|
||||||
import cn.axzo.nanopart.ess.server.ess.support.OssService;
|
import cn.axzo.nanopart.ess.server.ess.support.OssService;
|
||||||
import cn.axzo.nanopart.ess.server.utils.BizAssertions;
|
import cn.axzo.nanopart.ess.server.utils.BizAssertions;
|
||||||
import com.tencentcloudapi.essbasic.v20210526.models.CreateSignUrlsResponse;
|
import com.tencentcloudapi.essbasic.v20210526.models.CreateSignUrlsResponse;
|
||||||
@ -29,6 +32,11 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import static cn.axzo.nanopart.ess.server.utils.BizAssertions.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yanglin
|
* @author yanglin
|
||||||
*/
|
*/
|
||||||
@ -45,12 +53,15 @@ public class EssService {
|
|||||||
private final EssPersonDao essPersonDao;
|
private final EssPersonDao essPersonDao;
|
||||||
private final EssProps essProps;
|
private final EssProps essProps;
|
||||||
private final OssService ossService;
|
private final OssService ossService;
|
||||||
|
private final EssLogDao essLogDao;
|
||||||
|
private final EssSupport essSupport;
|
||||||
|
|
||||||
public String createConsoleLoginUrl(CreateConsoleLoginUrlRequest request) {
|
public String createConsoleLoginUrl(CreateConsoleLoginUrlRequest request) {
|
||||||
|
essLogDao.logRequest("createConsoleLoginUrl", request.getPersonId(), request);
|
||||||
OrgAndPerson orgAndPerson = orgManager.createConsoleLoginUrl(request);
|
OrgAndPerson orgAndPerson = orgManager.createConsoleLoginUrl(request);
|
||||||
return essClient.createConsoleLoginUrl(
|
return essClient.createConsoleLoginUrl(
|
||||||
orgAndPerson.getOrg(), orgAndPerson.getPerson(),
|
orgAndPerson.getOrg(), orgAndPerson.getPerson(),
|
||||||
request.getEndpoint(), request.isCheckOperator());
|
request.getEndpoint(), request.isEssCheckLoginPerson());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getEmbedWebUrl(GetEmbedWebUrlRequest request) {
|
public String getEmbedWebUrl(GetEmbedWebUrlRequest request) {
|
||||||
@ -58,18 +69,19 @@ public class EssService {
|
|||||||
if (request.getEmbedType().getEssContext() == EssContext.CONTRACT) {
|
if (request.getEmbedType().getEssContext() == EssContext.CONTRACT) {
|
||||||
BizAssertions.assertNotNull(request.getBusinessId(), "合同ID不能为空");
|
BizAssertions.assertNotNull(request.getBusinessId(), "合同ID不能为空");
|
||||||
EssContract contract = essContractDao.getOrThrow(request.getBusinessId());
|
EssContract contract = essContractDao.getOrThrow(request.getBusinessId());
|
||||||
contextPerson = contractManager.getContractCreatorOrThrow(contract);
|
contextPerson = contractManager.getContractSuperAdmin(contract);
|
||||||
} else if (request.getEmbedType().getEssContext() == EssContext.SEAL) {
|
} else if (request.getEmbedType().getEssContext() == EssContext.SEAL) {
|
||||||
BizAssertions.assertNotNull(request.getBusinessId(), "印章ID不能为空");
|
BizAssertions.assertNotNull(request.getBusinessId(), "印章ID不能为空");
|
||||||
contextPerson = orgManager.getSuperAdminOrThrow(request.getOuId());
|
contextPerson = orgManager.getSuperAdminOrThrow(request.getOuId());
|
||||||
} else {
|
} else {
|
||||||
return null;
|
throw fail("不支持的嵌入类型: {}", request.getEmbedType());
|
||||||
}
|
}
|
||||||
return essClient.getEmbedWebUrl(
|
return essClient.getEmbedWebUrl(
|
||||||
contextPerson, request.getEmbedType(), request.getBusinessId());
|
contextPerson, request.getEmbedType(), request.getBusinessId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void essAddSealAuthorization(AddSealAuthorizationRequest request) {
|
public void essAddSealAuthorization(AddSealAuthorizationRequest request) {
|
||||||
|
essLogDao.logRequest("essAddSealAuthorization", request.getPersonId(), request);
|
||||||
SealAndPerson sealAndPerson = getSealAndPersonOrThrow(request);
|
SealAndPerson sealAndPerson = getSealAndPersonOrThrow(request);
|
||||||
EssSealPerson sealPerson = sealAndPerson.getSealPerson();
|
EssSealPerson sealPerson = sealAndPerson.getSealPerson();
|
||||||
if (sealPerson.getIsAuthorized().isYes())
|
if (sealPerson.getIsAuthorized().isYes())
|
||||||
@ -83,6 +95,7 @@ public class EssService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void essRemoveSealAuthorization(RemoveSealAuthorizationRequest request) {
|
public void essRemoveSealAuthorization(RemoveSealAuthorizationRequest request) {
|
||||||
|
essLogDao.logRequest("essRemoveSealAuthorization", request.getPersonId(), request);
|
||||||
SealAndPerson sealAndPerson = getSealAndPersonOrThrow(request);
|
SealAndPerson sealAndPerson = getSealAndPersonOrThrow(request);
|
||||||
if (sealAndPerson.getSealPerson().getIsAuthorized().isNo())
|
if (sealAndPerson.getSealPerson().getIsAuthorized().isNo())
|
||||||
return;
|
return;
|
||||||
@ -102,35 +115,48 @@ public class EssService {
|
|||||||
return new SealAndPerson(seal, sealPerson);
|
return new SealAndPerson(seal, sealPerson);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String assignWeixinAppUrlByOrg(AssignWeixinAppUrlByOrgRequest request) {
|
public String getContractSignUrl(GetSignUrlRequest request) {
|
||||||
|
essLogDao.logRequest("getContractSignUrl", request.getEssContractId(), request);
|
||||||
EssPerson signPerson = essPersonDao.findOrNull(request);
|
EssPerson signPerson = essPersonDao.findOrNull(request);
|
||||||
BizAssertions.assertNotNull(signPerson, "当前签署人员未加入单位, 无法签署");
|
BizAssertions.assertNotNull(signPerson, "当前签署人员未加入单位, 无法签署");
|
||||||
EssContract contract = essContractDao.getOrThrow(request.getEssContractId());
|
EssContract contract = essContractDao.getOrThrow(request.getEssContractId());
|
||||||
BizAssertions.assertTrue(contract.isDynamicApprover(), "合同不支持动态签署");
|
BizAssertions.assertFalse(contract.isFinalState(),
|
||||||
String recipientId;
|
"合同已是最终状态 {}, 无法签署", contract.getState());
|
||||||
if (contract.getAssignedApprovers().getAssignType() == ApproverAssignType.ONE_PERSON_PER_ORG) {
|
if (contract.getConstraint() == Constraint.ONE_PERSON_PER_ORG)
|
||||||
BizAssertions.assertFalse(contract.isOrgSigned(request.getOuId()), "该单位已签署, 无法再次签署");
|
BizAssertions.assertFalse(contract.isOrgSigned(request.getOuId()), "该单位已签署, 无法再次签署");
|
||||||
recipientId = contractManager.assignRecipientIdByOrg(request);
|
Function<String, String> signUrlFun = recipientId -> {
|
||||||
} else {
|
EssPerson superAdmin = contractManager.getContractSuperAdmin(contract);
|
||||||
throw new ServiceException(String.format("暂不支持的动态签署类型: %s", contract.getAssignedApprovers().getAssignType()));
|
CreateSignUrlsResponse essResponse = essClient.getWeixinAppSignUrl(
|
||||||
|
request.getEssContractId(), superAdmin, request, recipientId);
|
||||||
|
SignUrlInfo signUrlInfo = essResponse.getSignUrlInfos()[0];
|
||||||
|
return request.getEndpoint() == SignUrlEndpoint.PC
|
||||||
|
? signUrlInfo.getSignQrcodeUrl()
|
||||||
|
: signUrlInfo.getSignUrl();
|
||||||
|
};
|
||||||
|
if (contract.isAllSignPersonPreset())
|
||||||
|
return signUrlFun.apply(null);
|
||||||
|
BizAssertions.assertFalse(StringUtils.isBlank(request.getRecipientId()),
|
||||||
|
"存在动态签署人的情况下, recipientId不能为空");
|
||||||
|
Approver approver = contract
|
||||||
|
.findApproverByRecipientId(request.getRecipientId())
|
||||||
|
.orElse(null);
|
||||||
|
BizAssertions.assertNotNull(approver, "无效的签署编号: {}", request.getRecipientId());
|
||||||
|
//noinspection DataFlowIssue
|
||||||
|
if (approver.getSignPerson() != null) {
|
||||||
|
BizAssertions.assertTrue(OrgPerson.equals(approver.getSignPerson(), request), "签署人员不匹配");
|
||||||
|
return signUrlFun.apply(null);
|
||||||
}
|
}
|
||||||
EssPerson creator = contractManager.getContractCreatorOrThrow(contract);
|
return signUrlFun.apply(request.getRecipientId());
|
||||||
CreateSignUrlsResponse essResponse = essClient.assignWeixinAppUrlByOrg(
|
|
||||||
request.getEssContractId(), creator, request, recipientId);
|
|
||||||
SignUrlInfo signUrlInfo = essResponse.getSignUrlInfos()[0];
|
|
||||||
return request.getUrlType() == SignUrlType.PC
|
|
||||||
? signUrlInfo.getSignQrcodeUrl()
|
|
||||||
: signUrlInfo.getSignUrl();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getContractPDFUrl(String essContractId) {
|
public String getContractPDFUrl(String essContractId) {
|
||||||
EssContract contract = essContractDao.getOrThrow(essContractId);
|
EssContract contract = essContractDao.getOrThrow(essContractId);
|
||||||
if (essProps.isDownloadContractFromOss()
|
if (essProps.isDownloadContractFromOss()
|
||||||
&& contract.getState().isFinalState()
|
|
||||||
&& StringUtils.isNotBlank(contract.getOssFileKey())) {
|
&& StringUtils.isNotBlank(contract.getOssFileKey())) {
|
||||||
return ossService.getOssUrl(contract.getOssFileKey());
|
return ossService.getOssUrl(contract.getOssFileKey());
|
||||||
}
|
}
|
||||||
ossService.maybeDownloadToOss(contract, () -> getContractPDFUrlFromEss(contract));
|
maybeUploadContractToOss(contract.getEssContractId(),
|
||||||
|
() -> getContractPDFUrlFromEss(contract));
|
||||||
return getContractPDFUrlFromEss(contract);
|
return getContractPDFUrlFromEss(contract);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,4 +164,17 @@ public class EssService {
|
|||||||
EssPerson creator = orgManager.getSuperAdminOrThrow(contract.getCreatorOuId());
|
EssPerson creator = orgManager.getSuperAdminOrThrow(contract.getCreatorOuId());
|
||||||
return essClient.getContractPDFUrl(creator, contract.getEssContractId());
|
return essClient.getContractPDFUrl(creator, contract.getEssContractId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void maybeUploadContractToOss(String essContractId, Supplier<String> essPdfUrl) {
|
||||||
|
essSupport.asyncExec(() -> {
|
||||||
|
EssContract effectiveContract = essContractDao.findOrNull(essContractId);
|
||||||
|
if (!effectiveContract.isFinalState()
|
||||||
|
|| StringUtils.isNotBlank(effectiveContract.getOssFileKey()))
|
||||||
|
return;
|
||||||
|
String fileName = String.format("%s.pdf", effectiveContract.getContractName());
|
||||||
|
String fileKey = ossService.uploadToOss(essPdfUrl.get(), fileName);
|
||||||
|
essContractDao.setOssInfo(effectiveContract, fileKey);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
package cn.axzo.nanopart.ess.server.ess;
|
package cn.axzo.nanopart.ess.server.ess;
|
||||||
|
|
||||||
|
import cn.axzo.nanopart.ess.api.domain.OrgPerson;
|
||||||
import cn.axzo.nanopart.ess.api.enums.EssPersonState;
|
import cn.axzo.nanopart.ess.api.enums.EssPersonState;
|
||||||
import cn.axzo.nanopart.ess.api.enums.EssSealState;
|
import cn.axzo.nanopart.ess.api.enums.EssSealState;
|
||||||
import cn.axzo.nanopart.ess.api.enums.EssSealType;
|
import cn.axzo.nanopart.ess.api.enums.EssSealType;
|
||||||
@ -50,34 +51,33 @@ public class OrgManager {
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public OrgAndPerson createConsoleLoginUrl(CreateConsoleLoginUrlRequest request) {
|
public OrgAndPerson createConsoleLoginUrl(CreateConsoleLoginUrlRequest request) {
|
||||||
EssOrg org = essOrgDao.find(request.getOuId(), true).orElse(null);
|
EssOrg org = essOrgDao.findForUpdateOrNull(request.getOuId());
|
||||||
if (org == null) {
|
if (org == null) {
|
||||||
org = essSupport.createOrg(request);
|
org = essSupport.createOrg(request);
|
||||||
essOrgDao.save(org);
|
essOrgDao.save(org);
|
||||||
}
|
}
|
||||||
EssPerson person = getOrCreateOrgPerson(request.getOuId(), request.getPersonId());
|
EssPerson person = getOrCreateOrgPerson(request);
|
||||||
return new OrgAndPerson(org, person);
|
return new OrgAndPerson(org, person);
|
||||||
}
|
}
|
||||||
|
|
||||||
// !! org and person
|
// !! org and person
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void addAuthorizedOrgPerson(Long ouId, Long personId) {
|
public void addAuthorizedOrgPerson(OrgPerson orgPerson) {
|
||||||
EssPerson person = getOrCreateOrgPerson(ouId, personId);
|
EssPerson person = getOrCreateOrgPerson(orgPerson);
|
||||||
essPersonDao.setState(person, EssPersonState.AUTHORIZED);
|
essPersonDao.setState(person, EssPersonState.AUTHORIZED);
|
||||||
log.info("add authorized person: {}", person);
|
log.info("add authorized person: {}", person);
|
||||||
}
|
}
|
||||||
|
|
||||||
private EssPerson getOrCreateOrgPerson(Long ouId, Long personId) {
|
private EssPerson getOrCreateOrgPerson(OrgPerson orgPerson) {
|
||||||
EssPerson person = essPersonDao
|
EssPerson essPerson = essPersonDao.find(orgPerson, true).orElse(null);
|
||||||
.find(ouId, personId, true).orElse(null);
|
if (essPerson == null) {
|
||||||
if (person == null) {
|
essPerson = essSupport.createPerson(orgPerson);
|
||||||
person = essSupport.createPerson(ouId, personId);
|
essPersonDao.save(essPerson);
|
||||||
essPersonDao.save(person);
|
essPerson = essPersonDao.find(orgPerson, true)
|
||||||
person = essPersonDao.find(ouId, personId, true)
|
|
||||||
.orElseThrow(InternalError::new);
|
.orElseThrow(InternalError::new);
|
||||||
}
|
}
|
||||||
return person;
|
return essPerson;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOrgAuthorized(Long ouId, Long authorizePersonId) {
|
public void setOrgAuthorized(Long ouId, Long authorizePersonId) {
|
||||||
@ -90,14 +90,13 @@ public class OrgManager {
|
|||||||
|
|
||||||
public EssPerson getSuperAdminOrThrow(Long ouId) {
|
public EssPerson getSuperAdminOrThrow(Long ouId) {
|
||||||
EssPerson superAdmin = findSuperAdmin(ouId).orElse(null);
|
EssPerson superAdmin = findSuperAdmin(ouId).orElse(null);
|
||||||
BizAssertions.assertNotNull(superAdmin, "单位还未认证: {}", ouId);
|
BizAssertions.assertNotNull(superAdmin, "单位还未认证");
|
||||||
return superAdmin;
|
return superAdmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<EssPerson> findSuperAdmin(Long ouId) {
|
Optional<EssPerson> findSuperAdmin(Long ouId) {
|
||||||
EssOrg org = essOrgDao.find(ouId).orElse(null);
|
EssOrg org = essOrgDao.findOrNull(ouId);
|
||||||
BizAssertions.assertNotNull(org, "单位不存在: {}", ouId);
|
BizAssertions.assertNotNull(org, "单位不存在");
|
||||||
//noinspection DataFlowIssue
|
|
||||||
if (org.getSuperAdminPersonId() <= 0L)
|
if (org.getSuperAdminPersonId() <= 0L)
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
return Optional.ofNullable(essPersonDao.findOrNull(ouId, org.getSuperAdminPersonId()));
|
return Optional.ofNullable(essPersonDao.findOrNull(ouId, org.getSuperAdminPersonId()));
|
||||||
|
|||||||
@ -5,7 +5,10 @@ import cn.axzo.framework.rocketmq.Event;
|
|||||||
import cn.axzo.framework.rocketmq.EventConsumer;
|
import cn.axzo.framework.rocketmq.EventConsumer;
|
||||||
import cn.axzo.framework.rocketmq.EventHandler;
|
import cn.axzo.framework.rocketmq.EventHandler;
|
||||||
import cn.axzo.maokai.api.domain.event.user.OrgUserStatusChangedEvent;
|
import cn.axzo.maokai.api.domain.event.user.OrgUserStatusChangedEvent;
|
||||||
|
import cn.axzo.nanopart.ess.server.dao.EssLogDao;
|
||||||
|
import cn.axzo.nanopart.ess.server.dao.EssOrgDao;
|
||||||
import cn.axzo.nanopart.ess.server.dao.EssPersonDao;
|
import cn.axzo.nanopart.ess.server.dao.EssPersonDao;
|
||||||
|
import cn.axzo.nanopart.ess.server.entity.EssOrg;
|
||||||
import cn.axzo.nanopart.ess.server.entity.EssPerson;
|
import cn.axzo.nanopart.ess.server.entity.EssPerson;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -38,7 +41,9 @@ public class PersonResignListener extends BaseListener
|
|||||||
private final EventConsumer eventConsumer;
|
private final EventConsumer eventConsumer;
|
||||||
private final EssClient essClient;
|
private final EssClient essClient;
|
||||||
private final OrgManager orgManager;
|
private final OrgManager orgManager;
|
||||||
|
private final EssOrgDao essOrgDao;
|
||||||
private final EssPersonDao essPersonDao;
|
private final EssPersonDao essPersonDao;
|
||||||
|
private final EssLogDao essLogDao;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(MessageExt message) {
|
public void onMessage(MessageExt message) {
|
||||||
@ -57,11 +62,19 @@ public class PersonResignListener extends BaseListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void trySetPersonResigned(OrgUserStatusChangedEvent event) {
|
private void trySetPersonResigned(OrgUserStatusChangedEvent event) {
|
||||||
|
EssOrg org = essOrgDao.findOrNull(event.getOuId());
|
||||||
|
if (org == null) return;
|
||||||
EssPerson person = essPersonDao.findOrNull(event.getOuId(), event.getPersonId());
|
EssPerson person = essPersonDao.findOrNull(event.getOuId(), event.getPersonId());
|
||||||
if (person == null)
|
if (person == null) {
|
||||||
|
essLogDao.log("personResigned", event.getPersonId(),
|
||||||
|
"event", event, "isAuthorized", false);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
EssPerson superAdmin = orgManager.getSuperAdminOrThrow(event.getOuId());
|
EssPerson superAdmin = orgManager.getSuperAdminOrThrow(event.getOuId());
|
||||||
if (superAdmin.getPersonId().equals(event.getPersonId())) {
|
boolean isSuperAdmin = superAdmin.getPersonId().equals(event.getPersonId());
|
||||||
|
essLogDao.log("personResigned", person.getPersonId(),
|
||||||
|
"event", event, "isSuperAdmin", isSuperAdmin);
|
||||||
|
if (isSuperAdmin) {
|
||||||
log.info("ignore super admin resigned: {}", JSON.toJSONString(person));
|
log.info("ignore super admin resigned: {}", JSON.toJSONString(person));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,8 +56,7 @@ public class QueryService {
|
|||||||
private final EssSealPersonDao essSealPersonDao;
|
private final EssSealPersonDao essSealPersonDao;
|
||||||
private final EssSupport essSupport;
|
private final EssSupport essSupport;
|
||||||
|
|
||||||
public List<GetOrgAuthStatesResponse>
|
public List<GetOrgAuthStatesResponse> getOrgAuthStates(GetOrgAuthStatesRequest request) {
|
||||||
getEssUnitAuthStates(GetOrgAuthStatesRequest request) {
|
|
||||||
List<EssOrg> orgs = essOrgDao.getByOuIds(request.getOuIds());
|
List<EssOrg> orgs = essOrgDao.getByOuIds(request.getOuIds());
|
||||||
ArrayList<GetOrgAuthStatesResponse> responses = new ArrayList<>();
|
ArrayList<GetOrgAuthStatesResponse> responses = new ArrayList<>();
|
||||||
for (Long ouId : request.getOuIds()) {
|
for (Long ouId : request.getOuIds()) {
|
||||||
@ -118,7 +117,7 @@ public class QueryService {
|
|||||||
EssOrgAndSealInfo orgAndSeal = new EssOrgAndSealInfo();
|
EssOrgAndSealInfo orgAndSeal = new EssOrgAndSealInfo();
|
||||||
essOrgAndSeals.add(orgAndSeal);
|
essOrgAndSeals.add(orgAndSeal);
|
||||||
orgAndSeal.setOrg(BeanMapper.copyBean(org, EssOrgInfo.class));
|
orgAndSeal.setOrg(BeanMapper.copyBean(org, EssOrgInfo.class));
|
||||||
orgAndSeal.getOrg().setOrgAuthorized(org.getIsAuthorized().isYes());
|
orgAndSeal.getOrg().setOrgAuthorized(org.isAuthorized());
|
||||||
List<EssSeal> seals = ouId2Seals.getOrDefault(org.getOuId(), emptyList());
|
List<EssSeal> seals = ouId2Seals.getOrDefault(org.getOuId(), emptyList());
|
||||||
orgAndSeal.setSeals(BeanMapper.copyList(seals, EssSealInfo.class));
|
orgAndSeal.setSeals(BeanMapper.copyList(seals, EssSealInfo.class));
|
||||||
for (EssSealInfo sealInfo : orgAndSeal.getSeals()) {
|
for (EssSealInfo sealInfo : orgAndSeal.getSeals()) {
|
||||||
@ -133,14 +132,12 @@ public class QueryService {
|
|||||||
sealPersonInfo.setSuperAdmin(org.getSuperAdminPersonId().equals(sealPerson.getPersonId()));
|
sealPersonInfo.setSuperAdmin(org.getSuperAdminPersonId().equals(sealPerson.getPersonId()));
|
||||||
sealPersonInfo.setSealAuthorized(sealPerson.getIsAuthorized().isYes());
|
sealPersonInfo.setSealAuthorized(sealPerson.getIsAuthorized().isYes());
|
||||||
sealPersonInfo.setPersonAuthorized(essPerson.isAuthorized());
|
sealPersonInfo.setPersonAuthorized(essPerson.isAuthorized());
|
||||||
PersonProfileDto personProfile = personProfiles
|
sealPersonInfo.setAuthorizeTimeMs(sealPerson.getAuthorizeTime() == null
|
||||||
.find(sealPerson.getPersonId()).orElse(null);
|
? null : sealPerson.getAuthorizeTime().getTime());
|
||||||
sealPersonInfo.setPersonName(
|
PersonProfileDto person = personProfiles.findOrNull(sealPerson.getPersonId());
|
||||||
personProfile == null ? "" : personProfile.getRealName());
|
sealPersonInfo.setPersonName(person == null ? "" : person.getRealName());
|
||||||
PersonProfileDto authorizedByPersonProfile = personProfiles
|
PersonProfileDto authorizedBy = personProfiles.findOrNull(sealPerson.getPersonId());
|
||||||
.find(sealPerson.getPersonId()).orElse(null);
|
sealPersonInfo.setAuthorizedByPersonName(authorizedBy == null ? "" : authorizedBy.getRealName());
|
||||||
sealPersonInfo.setAuthorizedByPersonName(
|
|
||||||
authorizedByPersonProfile == null ? "" : authorizedByPersonProfile.getRealName());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,28 +7,26 @@ import cn.axzo.nanopart.ess.api.domain.EssOrgAndSealInfo;
|
|||||||
import cn.axzo.nanopart.ess.api.domain.contract.EssContractInfo;
|
import cn.axzo.nanopart.ess.api.domain.contract.EssContractInfo;
|
||||||
import cn.axzo.nanopart.ess.api.request.AddSealAuthorizationRequest;
|
import cn.axzo.nanopart.ess.api.request.AddSealAuthorizationRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.AddSealPersonsRequest;
|
import cn.axzo.nanopart.ess.api.request.AddSealPersonsRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.AssignWeixinAppUrlByOrgRequest;
|
|
||||||
import cn.axzo.nanopart.ess.api.request.CreateConsoleLoginUrlRequest;
|
import cn.axzo.nanopart.ess.api.request.CreateConsoleLoginUrlRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.CreateContractRequest;
|
import cn.axzo.nanopart.ess.api.request.CreateContractByFileRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.DownloadSingedContractPdfRequest;
|
import cn.axzo.nanopart.ess.api.request.DownloadSingedContractPdfRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.GetContractDetailByBizCodeRequest;
|
|
||||||
import cn.axzo.nanopart.ess.api.request.GetContractDetailByContractIdRequest;
|
import cn.axzo.nanopart.ess.api.request.GetContractDetailByContractIdRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.GetEmbedWebUrlRequest;
|
import cn.axzo.nanopart.ess.api.request.GetEmbedWebUrlRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.GetOrgAuthStatesRequest;
|
import cn.axzo.nanopart.ess.api.request.GetOrgAuthStatesRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.GetPersonAuthStateRequest;
|
import cn.axzo.nanopart.ess.api.request.GetPersonAuthStateRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.GetSealsRequest;
|
import cn.axzo.nanopart.ess.api.request.GetSealsRequest;
|
||||||
|
import cn.axzo.nanopart.ess.api.request.GetSignUrlRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.RemoveSealAuthorizationRequest;
|
import cn.axzo.nanopart.ess.api.request.RemoveSealAuthorizationRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.RemoveSealPersonRequest;
|
import cn.axzo.nanopart.ess.api.request.RemoveSealPersonRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.RevokeContractRequest;
|
import cn.axzo.nanopart.ess.api.request.RevokeContractRequest;
|
||||||
import cn.axzo.nanopart.ess.api.response.AssignWeixinAppUrlByOrgResponse;
|
|
||||||
import cn.axzo.nanopart.ess.api.response.CreateConsoleLoginUrlResponse;
|
import cn.axzo.nanopart.ess.api.response.CreateConsoleLoginUrlResponse;
|
||||||
import cn.axzo.nanopart.ess.api.response.CreateContractResponse;
|
import cn.axzo.nanopart.ess.api.response.CreateContractByFileResponse;
|
||||||
import cn.axzo.nanopart.ess.api.response.DownloadSingedContractPdfResponse;
|
import cn.axzo.nanopart.ess.api.response.DownloadSingedContractPdfResponse;
|
||||||
import cn.axzo.nanopart.ess.api.response.GetContractDetailByBizCodeResponse;
|
|
||||||
import cn.axzo.nanopart.ess.api.response.GetContractDetailByContractIdResponse;
|
import cn.axzo.nanopart.ess.api.response.GetContractDetailByContractIdResponse;
|
||||||
import cn.axzo.nanopart.ess.api.response.GetEmbedWebUrlResponse;
|
import cn.axzo.nanopart.ess.api.response.GetEmbedWebUrlResponse;
|
||||||
import cn.axzo.nanopart.ess.api.response.GetOrgAuthStatesResponse;
|
import cn.axzo.nanopart.ess.api.response.GetOrgAuthStatesResponse;
|
||||||
import cn.axzo.nanopart.ess.api.response.GetPersonAuthStateResponse;
|
import cn.axzo.nanopart.ess.api.response.GetPersonAuthStateResponse;
|
||||||
|
import cn.axzo.nanopart.ess.api.response.GetSignUrlResponse;
|
||||||
import cn.axzo.nanopart.ess.server.dao.EssContractDao;
|
import cn.axzo.nanopart.ess.server.dao.EssContractDao;
|
||||||
import cn.axzo.nanopart.ess.server.entity.EssContract;
|
import cn.axzo.nanopart.ess.server.entity.EssContract;
|
||||||
import cn.axzo.nanopart.ess.server.ess.ContractManager;
|
import cn.axzo.nanopart.ess.server.ess.ContractManager;
|
||||||
@ -57,7 +55,7 @@ class ApiController implements EssApi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApiResult<List<GetOrgAuthStatesResponse>> getOrgAuthStates(GetOrgAuthStatesRequest request) {
|
public ApiResult<List<GetOrgAuthStatesResponse>> getOrgAuthStates(GetOrgAuthStatesRequest request) {
|
||||||
return ApiResult.ok(queryService.getEssUnitAuthStates(request));
|
return ApiResult.ok(queryService.getOrgAuthStates(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -109,14 +107,14 @@ class ApiController implements EssApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApiResult<CreateContractResponse> createContract(CreateContractRequest request) {
|
public ApiResult<CreateContractByFileResponse> createContractByFile(CreateContractByFileRequest request) {
|
||||||
return ApiResult.ok(contractManager.createContract(request));
|
return ApiResult.ok(contractManager.createContractByFile(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApiResult<AssignWeixinAppUrlByOrgResponse> assignWeixinAppUrlByOrg(AssignWeixinAppUrlByOrgRequest request) {
|
public ApiResult<GetSignUrlResponse> getContractSignUrl(GetSignUrlRequest request) {
|
||||||
AssignWeixinAppUrlByOrgResponse response = new AssignWeixinAppUrlByOrgResponse();
|
GetSignUrlResponse response = new GetSignUrlResponse();
|
||||||
response.setUrl(essService.assignWeixinAppUrlByOrg(request));
|
response.setUrl(essService.getContractSignUrl(request));
|
||||||
return ApiResult.ok(response);
|
return ApiResult.ok(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,20 +133,11 @@ class ApiController implements EssApi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApiResult<GetContractDetailByContractIdResponse>
|
public ApiResult<GetContractDetailByContractIdResponse>
|
||||||
getContractDetailByContractId(GetContractDetailByContractIdRequest request) {
|
getContractByContractId(GetContractDetailByContractIdRequest request) {
|
||||||
EssContract contract = essContractDao.getOrThrow(request.getEssContractId());
|
EssContract contract = essContractDao.getOrThrow(request.getEssContractId());
|
||||||
GetContractDetailByContractIdResponse response = new GetContractDetailByContractIdResponse();
|
GetContractDetailByContractIdResponse response = new GetContractDetailByContractIdResponse();
|
||||||
response.setContract(BeanMapper.copyBean(contract, EssContractInfo.class));
|
response.setContract(BeanMapper.copyBean(contract, EssContractInfo.class));
|
||||||
return ApiResult.ok(response);
|
return ApiResult.ok(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ApiResult<GetContractDetailByBizCodeResponse>
|
|
||||||
getContractDetailByBizCode(GetContractDetailByBizCodeRequest request) {
|
|
||||||
EssContract contract = essContractDao.findByBizCode(request.getAppCode(), request.getBizCode()).orElse(null);
|
|
||||||
GetContractDetailByBizCodeResponse response = new GetContractDetailByBizCodeResponse();
|
|
||||||
response.setContract(BeanMapper.copyBean(contract, EssContractInfo.class));
|
|
||||||
return ApiResult.ok(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -24,7 +24,6 @@ import cn.axzo.nanopart.ess.server.ess.domain.JsonObjectAsString;
|
|||||||
import cn.axzo.nanopart.ess.server.ess.domain.OrgOpenId;
|
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.domain.PersonOpenId;
|
||||||
import cn.axzo.nanopart.ess.server.ess.support.EssSupport;
|
import cn.axzo.nanopart.ess.server.ess.support.EssSupport;
|
||||||
import cn.axzo.nanopart.ess.server.ess.support.OssService;
|
|
||||||
import cn.axzo.nanopart.ess.server.utils.IdBuilder;
|
import cn.axzo.nanopart.ess.server.utils.IdBuilder;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
@ -56,7 +55,6 @@ class CallbackController implements EssCallbackApi, InitializingBean {
|
|||||||
|
|
||||||
private final OrgManager orgManager;
|
private final OrgManager orgManager;
|
||||||
private final EssService essService;
|
private final EssService essService;
|
||||||
private final OssService ossService;
|
|
||||||
private final ContractManager contractManager;
|
private final ContractManager contractManager;
|
||||||
private final EssLogDao essLogDao;
|
private final EssLogDao essLogDao;
|
||||||
private final EssContractDao essContractDao;
|
private final EssContractDao essContractDao;
|
||||||
@ -72,17 +70,18 @@ class CallbackController implements EssCallbackApi, InitializingBean {
|
|||||||
OrgAuthorizationFinish result = request.readMsgData(OrgAuthorizationFinish.class);
|
OrgAuthorizationFinish result = request.readMsgData(OrgAuthorizationFinish.class);
|
||||||
PersonOpenId person = PersonOpenId.parse(result.getProxyOperatorOpenId());
|
PersonOpenId person = PersonOpenId.parse(result.getProxyOperatorOpenId());
|
||||||
if (result.isOpenSuccess()) {
|
if (result.isOpenSuccess()) {
|
||||||
orgManager.addAuthorizedOrgPerson(person.getOuId(), person.getPersonId());
|
orgManager.addAuthorizedOrgPerson(person);
|
||||||
orgManager.setOrgAuthorized(person.getOuId(), person.getPersonId());
|
orgManager.setOrgAuthorized(person.getOuId(), person.getPersonId());
|
||||||
}
|
}
|
||||||
return IdBuilder.builder()
|
return IdBuilder.builder()
|
||||||
.append(person.getOuId())
|
.append(person.getOuId())
|
||||||
.append(person.getPersonId()).build();
|
.append(person.getPersonId())
|
||||||
|
.build();
|
||||||
});
|
});
|
||||||
// 员工加入子企业的时候发送此通知
|
// 员工加入子企业的时候发送此通知
|
||||||
registerHandler(CallbackType.ORG_PERSON_JOIN, request -> {
|
registerHandler(CallbackType.ORG_PERSON_JOIN, request -> {
|
||||||
PersonOpenId person = PersonOpenId.parse(request.readMsgData(OrgPersonJoin.class).getProxyOperatorOpenId());
|
PersonOpenId person = PersonOpenId.parse(request.readMsgData(OrgPersonJoin.class).getProxyOperatorOpenId());
|
||||||
orgManager.addAuthorizedOrgPerson(person.getOuId(), person.getPersonId());
|
orgManager.addAuthorizedOrgPerson(person);
|
||||||
// 一般情况下只会存在一条记录
|
// 一般情况下只会存在一条记录
|
||||||
for (EssSealPerson sealPerson : essSealPersonDao.getByPersonId(person.getPersonId())) {
|
for (EssSealPerson sealPerson : essSealPersonDao.getByPersonId(person.getPersonId())) {
|
||||||
AddSealAuthorizationRequest addSealAuthorizationRequest = new AddSealAuthorizationRequest();
|
AddSealAuthorizationRequest addSealAuthorizationRequest = new AddSealAuthorizationRequest();
|
||||||
@ -97,7 +96,8 @@ class CallbackController implements EssCallbackApi, InitializingBean {
|
|||||||
}
|
}
|
||||||
return IdBuilder.builder()
|
return IdBuilder.builder()
|
||||||
.append(person.getOuId())
|
.append(person.getOuId())
|
||||||
.append(person.getPersonId()).build();
|
.append(person.getPersonId())
|
||||||
|
.build();
|
||||||
});
|
});
|
||||||
// 印章回调
|
// 印章回调
|
||||||
registerHandler(CallbackType.SEAL_OPERATE, request -> {
|
registerHandler(CallbackType.SEAL_OPERATE, request -> {
|
||||||
@ -157,7 +157,7 @@ class CallbackController implements EssCallbackApi, InitializingBean {
|
|||||||
return detail;
|
return detail;
|
||||||
})
|
})
|
||||||
.collect(toList());
|
.collect(toList());
|
||||||
EssContract contract = essContractDao.find(changes.getFlowId()).orElse(null);
|
EssContract contract = essContractDao.findOrNull(changes.getFlowId());
|
||||||
if (contract == null && StringUtils.isNotBlank(changes.getCustomerData())) {
|
if (contract == null && StringUtils.isNotBlank(changes.getCustomerData())) {
|
||||||
JSONObject customData = JsonObjectAsString.parse(changes.getCustomerData()).asJsonObject();
|
JSONObject customData = JsonObjectAsString.parse(changes.getCustomerData()).asJsonObject();
|
||||||
contract = essContractDao.getById(customData.getLong(ContractManager.CONTRACT_ID));
|
contract = essContractDao.getById(customData.getLong(ContractManager.CONTRACT_ID));
|
||||||
@ -165,7 +165,8 @@ class CallbackController implements EssCallbackApi, InitializingBean {
|
|||||||
if (contract != null) {
|
if (contract != null) {
|
||||||
contractManager.updateContractState(contract, state, approveDetails);
|
contractManager.updateContractState(contract, state, approveDetails);
|
||||||
EssContract finalContract = contract;
|
EssContract finalContract = contract;
|
||||||
ossService.maybeDownloadToOss(contract, () -> essService.getContractPDFUrlFromEss(finalContract));
|
essService.maybeUploadContractToOss(contract.getEssContractId(),
|
||||||
|
() -> essService.getContractPDFUrlFromEss(finalContract));
|
||||||
}
|
}
|
||||||
return changes.getFlowId();
|
return changes.getFlowId();
|
||||||
});
|
});
|
||||||
@ -184,10 +185,18 @@ class CallbackController implements EssCallbackApi, InitializingBean {
|
|||||||
try {
|
try {
|
||||||
CallbackType callbackType = CallbackType.parse(request.getMsgType()).orElse(null);
|
CallbackType callbackType = CallbackType.parse(request.getMsgType()).orElse(null);
|
||||||
CallbackHandler handler = callbackType == null ? null : handlers.get(callbackType);
|
CallbackHandler handler = callbackType == null ? null : handlers.get(callbackType);
|
||||||
if (handler != null)
|
if (handler != null) {
|
||||||
subject = transactionTemplate.execute(unused -> handler.handle(request));
|
subject = transactionTemplate.execute(unused -> {
|
||||||
else
|
try {
|
||||||
|
return handler.handle(request);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("callback failed", e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
log.info("ignore callback: {}", request);
|
log.info("ignore callback: {}", request);
|
||||||
|
}
|
||||||
return ApiResult.ok("success");
|
return ApiResult.ok("success");
|
||||||
} finally {
|
} finally {
|
||||||
saveRequest(request, subject);
|
saveRequest(request, subject);
|
||||||
|
|||||||
@ -29,16 +29,15 @@ public class PrivateController {
|
|||||||
private final EssClient essClient;
|
private final EssClient essClient;
|
||||||
private final EssOrgDao essOrgDao;
|
private final EssOrgDao essOrgDao;
|
||||||
|
|
||||||
@SuppressWarnings("DataFlowIssue")
|
@PostMapping("/private/ess/getOrgPersons")
|
||||||
@PostMapping("/private/ess/getOrgEmployees")
|
public ApiResult<?> getOrgPersons(@RequestParam("ouId") Long ouId) {
|
||||||
public ApiResult<?> getOrgUsers(@RequestParam("ouId") Long ouId) {
|
EssOrg org = essOrgDao.findOrNull(ouId);
|
||||||
EssOrg org = essOrgDao.find(ouId).orElse(null);
|
|
||||||
BizAssertions.assertNotNull(org, "电子签单位不存在");
|
BizAssertions.assertNotNull(org, "电子签单位不存在");
|
||||||
EssPerson superAdmin = orgManager.getSuperAdminOrThrow(ouId);
|
EssPerson superAdmin = orgManager.getSuperAdminOrThrow(ouId);
|
||||||
HashMap<String, Staff> staffs = new HashMap<>();
|
HashMap<String, Staff> staffs = new HashMap<>();
|
||||||
long offset = 0L;
|
long offset = 0L;
|
||||||
while (true) {
|
while (true) {
|
||||||
ChannelDescribeEmployeesResponse response = essClient.getEmployees(superAdmin, org, offset);
|
ChannelDescribeEmployeesResponse response = essClient.getOrgPerson(superAdmin, org, offset);
|
||||||
if (response.getEmployees() == null || response.getEmployees().length == 0)
|
if (response.getEmployees() == null || response.getEmployees().length == 0)
|
||||||
break;
|
break;
|
||||||
offset = response.getOffset() + 1;
|
offset = response.getOffset() + 1;
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import lombok.RequiredArgsConstructor;
|
|||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public class PersonOpenId {
|
public class PersonOpenId implements OrgPerson {
|
||||||
|
|
||||||
private static final PersonOpenId NONE = create(0L, 0L);
|
private static final PersonOpenId NONE = create(0L, 0L);
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,87 @@
|
|||||||
|
package cn.axzo.nanopart.ess.server.ess.support;
|
||||||
|
|
||||||
|
import cn.axzo.basics.common.exception.ServiceException;
|
||||||
|
import cn.axzo.nanopart.ess.api.domain.CreateContractInfo;
|
||||||
|
import cn.axzo.nanopart.ess.api.domain.contract.Approver;
|
||||||
|
import cn.axzo.nanopart.ess.api.enums.Constraint;
|
||||||
|
import cn.axzo.nanopart.ess.api.enums.EssContractState;
|
||||||
|
import cn.axzo.nanopart.ess.api.request.CreateContractByFileRequest;
|
||||||
|
import cn.axzo.nanopart.ess.server.dao.EssContractDao;
|
||||||
|
import cn.axzo.nanopart.ess.server.dao.EssOrgDao;
|
||||||
|
import cn.axzo.nanopart.ess.server.entity.EssContract;
|
||||||
|
import cn.axzo.nanopart.ess.server.entity.EssOrg;
|
||||||
|
import cn.axzo.nanopart.ess.server.utils.BizAssertions;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.dao.DuplicateKeyException;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static java.util.stream.Collectors.toList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yanglin
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ContractSupport {
|
||||||
|
|
||||||
|
private final EssOrgDao essOrgDao;
|
||||||
|
private final EssContractDao essContractDao;
|
||||||
|
|
||||||
|
public void validateCreateContract(CreateContractInfo contract) {
|
||||||
|
checkCreateContractConstraint(contract);
|
||||||
|
ensureOrgAuthorized(contract);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCreateContractConstraint(CreateContractInfo contract) {
|
||||||
|
if (contract.getConstraint() == Constraint.ONE_PERSON_PER_ORG) {
|
||||||
|
HashSet<Long> ouIds = new HashSet<>();
|
||||||
|
for (Approver approver : contract.getApprovers()) {
|
||||||
|
if (approver.getSignPerson() == null)
|
||||||
|
continue;
|
||||||
|
BizAssertions.assertFalse(ouIds.contains(approver.getOuId()),
|
||||||
|
"同一单位不能有多个审批人, constraint={}", Constraint.ONE_PERSON_PER_ORG);
|
||||||
|
ouIds.add(approver.getOuId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureOrgAuthorized(CreateContractInfo contract) {
|
||||||
|
BizAssertions.assertNotNull(contract, "合同信息不能为空");
|
||||||
|
List<EssOrg> orgs = essOrgDao.getByOuIds(contract.getApproverOuIds());
|
||||||
|
List<String> notAuthorizedOrgs = orgs.stream()
|
||||||
|
.filter(org -> !org.isAuthorized())
|
||||||
|
.map(EssOrg::getOuName)
|
||||||
|
.collect(toList());
|
||||||
|
BizAssertions.assertEmpty(notAuthorizedOrgs,
|
||||||
|
"创建合同失败. 以下单位还未认证: {}", JSON.toJSONString(notAuthorizedOrgs));
|
||||||
|
}
|
||||||
|
|
||||||
|
public EssContract saveContractByFile(CreateContractByFileRequest request) {
|
||||||
|
try {
|
||||||
|
EssContract contract = new EssContract();
|
||||||
|
contract.setAppCode(request.getAppCode());
|
||||||
|
contract.setBizCode(request.getBizCode());
|
||||||
|
contract.setCreatorOuId(request.getCreator().getOuId());
|
||||||
|
contract.setCreatorPersonId(request.getCreator().getPersonId());
|
||||||
|
contract.setContractName(request.getByFile().getContractName());
|
||||||
|
contract.setEssContractId("");
|
||||||
|
contract.setEssFieldIds(Collections.emptyList());
|
||||||
|
contract.setState(EssContractState.INIT);
|
||||||
|
contract.setApprovers(request.getByFile().getApprovers());
|
||||||
|
contract.getOrCreateAssignment().setConstraint(
|
||||||
|
request.getContract().getConstraint());
|
||||||
|
contract.setApproveDetails(Collections.emptyList());
|
||||||
|
contract.setRecordExt(new EssContract.RecordExt());
|
||||||
|
essContractDao.save(contract);
|
||||||
|
return contract;
|
||||||
|
} catch (DuplicateKeyException e) {
|
||||||
|
throw new ServiceException("业务编码对应的合同已存在");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -6,31 +6,30 @@ import cn.axzo.basics.profiles.dto.request.QueryPersonProfileByIdOrPhoneDto;
|
|||||||
import cn.axzo.maokai.api.client.OrganizationalUnitApi;
|
import cn.axzo.maokai.api.client.OrganizationalUnitApi;
|
||||||
import cn.axzo.maokai.api.vo.request.OrganizationalUnitQuery;
|
import cn.axzo.maokai.api.vo.request.OrganizationalUnitQuery;
|
||||||
import cn.axzo.maokai.api.vo.response.OrganizationalUnitVO;
|
import cn.axzo.maokai.api.vo.response.OrganizationalUnitVO;
|
||||||
import cn.axzo.nanopart.ess.api.domain.DynamicApproverProps;
|
import cn.axzo.nanopart.ess.api.domain.OrgPerson;
|
||||||
import cn.axzo.nanopart.ess.api.enums.EssContractState;
|
|
||||||
import cn.axzo.nanopart.ess.api.enums.EssPersonState;
|
import cn.axzo.nanopart.ess.api.enums.EssPersonState;
|
||||||
import cn.axzo.nanopart.ess.api.request.CreateConsoleLoginUrlRequest;
|
import cn.axzo.nanopart.ess.api.request.CreateConsoleLoginUrlRequest;
|
||||||
import cn.axzo.nanopart.ess.api.request.CreateContractRequest;
|
|
||||||
import cn.axzo.nanopart.ess.api.utils.YesOrNo;
|
import cn.axzo.nanopart.ess.api.utils.YesOrNo;
|
||||||
import cn.axzo.nanopart.ess.server.entity.EssContract;
|
|
||||||
import cn.axzo.nanopart.ess.server.entity.EssOrg;
|
import cn.axzo.nanopart.ess.server.entity.EssOrg;
|
||||||
import cn.axzo.nanopart.ess.server.entity.EssPerson;
|
import cn.axzo.nanopart.ess.server.entity.EssPerson;
|
||||||
import cn.axzo.nanopart.ess.server.entity.domain.AssignedApprovers;
|
|
||||||
import cn.axzo.nanopart.ess.server.utils.BizAssertions;
|
import cn.axzo.nanopart.ess.server.utils.BizAssertions;
|
||||||
import cn.azxo.framework.common.model.CommonResponse;
|
import cn.azxo.framework.common.model.CommonResponse;
|
||||||
import com.tencentcloudapi.essbasic.v20210526.models.ApproverItem;
|
import cn.hutool.core.thread.NamedThreadFactory;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static cn.axzo.nanopart.ess.server.utils.BizAssertions.assertResponse;
|
import static cn.axzo.nanopart.ess.server.utils.BizAssertions.assertResponse;
|
||||||
import static java.util.stream.Collectors.toList;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,6 +39,12 @@ import static java.util.stream.Collectors.toList;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class EssSupport {
|
public class EssSupport {
|
||||||
|
|
||||||
|
private final ExecutorService executor = new ThreadPoolExecutor(1, 5,
|
||||||
|
0L, TimeUnit.MILLISECONDS,
|
||||||
|
new ArrayBlockingQueue<>(1024),
|
||||||
|
new NamedThreadFactory(EssSupport.class.getName(), false),
|
||||||
|
new CallerRunsPolicy());
|
||||||
|
|
||||||
private final OrganizationalUnitApi organizationalUnitApi;
|
private final OrganizationalUnitApi organizationalUnitApi;
|
||||||
private final UserProfileServiceApi userProfileServiceApi;
|
private final UserProfileServiceApi userProfileServiceApi;
|
||||||
|
|
||||||
@ -55,16 +60,16 @@ public class EssSupport {
|
|||||||
return org;
|
return org;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EssPerson createPerson(Long ouId, Long personId) {
|
public EssPerson createPerson(OrgPerson orgPerson) {
|
||||||
PersonProfileDto personProfile = getPersonProfileOrThrow(personId);
|
PersonProfileDto personProfile = getPersonProfileOrThrow(orgPerson);
|
||||||
EssPerson person = new EssPerson();
|
EssPerson essPerson = new EssPerson();
|
||||||
person.setOuId(ouId);
|
essPerson.setOuId(orgPerson.getOuId());
|
||||||
person.setPersonId(personId);
|
essPerson.setPersonId(orgPerson.getPersonId());
|
||||||
person.setPersonName(personProfile.getRealName());
|
essPerson.setPersonName(personProfile.getRealName());
|
||||||
person.setState(EssPersonState.CREATED);
|
essPerson.setState(EssPersonState.CREATED);
|
||||||
person.setCreateAt(new Date());
|
essPerson.setCreateAt(new Date());
|
||||||
person.setUpdateAt(new Date());
|
essPerson.setUpdateAt(new Date());
|
||||||
return person;
|
return essPerson;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OrganizationalUnitVO getOrgProfileOrThrow(Long ouId) {
|
public OrganizationalUnitVO getOrgProfileOrThrow(Long ouId) {
|
||||||
@ -82,9 +87,9 @@ public class EssSupport {
|
|||||||
return assertResponse(organizationalUnitApi.list(request));
|
return assertResponse(organizationalUnitApi.list(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
public PersonProfileDto getPersonProfileOrThrow(Long personId) {
|
public PersonProfileDto getPersonProfileOrThrow(OrgPerson orgPerson) {
|
||||||
PersonProfileDto person = findPersonProfile(personId).orElse(null);
|
PersonProfileDto person = findPersonProfile(orgPerson).orElse(null);
|
||||||
BizAssertions.assertNotNull(person, "人员不存在: {}", personId);
|
BizAssertions.assertNotNull(person, "人员不存在: {}", orgPerson.getPersonId());
|
||||||
return person;
|
return person;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,8 +100,8 @@ public class EssSupport {
|
|||||||
return CollectionUtils.isEmpty(profiles) ? Optional.empty() : Optional.of(profiles.get(0));
|
return CollectionUtils.isEmpty(profiles) ? Optional.empty() : Optional.of(profiles.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<PersonProfileDto> findPersonProfile(Long personId) {
|
public Optional<PersonProfileDto> findPersonProfile(OrgPerson orgPerson) {
|
||||||
CommonResponse<PersonProfileDto> response = userProfileServiceApi.getPersonProfile(personId);
|
CommonResponse<PersonProfileDto> response = userProfileServiceApi.getPersonProfile(orgPerson.getPersonId());
|
||||||
if (response.getCode() == 404)
|
if (response.getCode() == 404)
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
return Optional.ofNullable(assertResponse(response));
|
return Optional.ofNullable(assertResponse(response));
|
||||||
@ -108,38 +113,8 @@ public class EssSupport {
|
|||||||
return assertResponse(userProfileServiceApi.getPersonProfiles(personIds));
|
return assertResponse(userProfileServiceApi.getPersonProfiles(personIds));
|
||||||
}
|
}
|
||||||
|
|
||||||
public EssContract createContract(CreateContractRequest request) {
|
public void asyncExec(Runnable task) {
|
||||||
EssContract contract = new EssContract();
|
executor.execute(task);
|
||||||
contract.setAppCode(request.getAppCode());
|
|
||||||
contract.setBizCode(request.getBizCode());
|
|
||||||
contract.setCreatorOuId(request.getOperator().getOuId());
|
|
||||||
contract.setCreatorPersonId(request.getOperator().getPersonId());
|
|
||||||
contract.setContractName(request.getByFile().getContractName());
|
|
||||||
contract.setEssContractId("");
|
|
||||||
contract.setEssFieldIds(Collections.emptyList());
|
|
||||||
contract.setState(EssContractState.INIT);
|
|
||||||
contract.setIsDynamicApprover(YesOrNo.valueOf(
|
|
||||||
request.getByFile().isDynamicApprover()));
|
|
||||||
contract.setApprovers(request.getByFile().getApprovers());
|
|
||||||
if (request.getByFile().isDynamicApprover()) {
|
|
||||||
DynamicApproverProps props = request.getByFile().getDynamicApproverProps();
|
|
||||||
if (props == null)
|
|
||||||
props = DynamicApproverProps.defaultProps();
|
|
||||||
AssignedApprovers assignedApprovers = new AssignedApprovers();
|
|
||||||
assignedApprovers.setAssignType(props.getAssignType());
|
|
||||||
contract.setAssignedApprovers(assignedApprovers);
|
|
||||||
}
|
|
||||||
contract.setApproveDetails(Collections.emptyList());
|
|
||||||
contract.setRecordExt(new EssContract.RecordExt());
|
|
||||||
return contract;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<String> collectRecipientIds(ApproverItem[] approvers) {
|
|
||||||
if (approvers == null || approvers.length == 0)
|
|
||||||
return Collections.emptyList();
|
|
||||||
return Arrays.stream(approvers)
|
|
||||||
.map(ApproverItem::getRecipientId)
|
|
||||||
.collect(toList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,8 +1,5 @@
|
|||||||
package cn.axzo.nanopart.ess.server.ess.support;
|
package cn.axzo.nanopart.ess.server.ess.support;
|
||||||
|
|
||||||
import cn.axzo.basics.common.exception.ServiceException;
|
|
||||||
import cn.axzo.nanopart.ess.server.dao.EssContractDao;
|
|
||||||
import cn.axzo.nanopart.ess.server.entity.EssContract;
|
|
||||||
import cn.axzo.nanopart.ess.server.utils.BizAssertions;
|
import cn.axzo.nanopart.ess.server.utils.BizAssertions;
|
||||||
import cn.axzo.oss.http.api.ServerFileServiceApi;
|
import cn.axzo.oss.http.api.ServerFileServiceApi;
|
||||||
import cn.axzo.oss.http.model.ApiSignUrlDownloadRequest;
|
import cn.axzo.oss.http.model.ApiSignUrlDownloadRequest;
|
||||||
@ -12,7 +9,6 @@ import cn.axzo.oss.http.model.ApiSignUrlUploadResponse;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
@ -25,9 +21,8 @@ import java.net.URL;
|
|||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
import static cn.axzo.nanopart.ess.server.utils.BizAssertions.fail;
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yanglin
|
* @author yanglin
|
||||||
@ -37,21 +32,8 @@ import java.util.function.Supplier;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class OssService {
|
public class OssService {
|
||||||
|
|
||||||
private final EssContractDao essContractDao;
|
|
||||||
private final ServerFileServiceApi serverFileServiceApi;
|
private final ServerFileServiceApi serverFileServiceApi;
|
||||||
private final EssProps essProps;
|
private final EssProps essProps;
|
||||||
private final ExecutorService executor = Executors.newSingleThreadExecutor();
|
|
||||||
|
|
||||||
public void maybeDownloadToOss(EssContract contract, Supplier<String> essPdfUrl) {
|
|
||||||
executor.execute(() -> {
|
|
||||||
if (!contract.getState().isFinalState()
|
|
||||||
|| StringUtils.isNotBlank(contract.getOssFileKey()))
|
|
||||||
return;
|
|
||||||
String fileName = String.format("%s.pdf", contract.getContractName());
|
|
||||||
String fileKey = saveToOss(essPdfUrl.get(), fileName);
|
|
||||||
essContractDao.setOssInfo(contract, fileKey);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOssUrl(String fileKey) {
|
public String getOssUrl(String fileKey) {
|
||||||
ApiSignUrlDownloadRequest request = new ApiSignUrlDownloadRequest();
|
ApiSignUrlDownloadRequest request = new ApiSignUrlDownloadRequest();
|
||||||
@ -63,17 +45,6 @@ public class OssService {
|
|||||||
return CollectionUtils.isEmpty(responses) ? null : responses.get(0).getSignUrl();
|
return CollectionUtils.isEmpty(responses) ? null : responses.get(0).getSignUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String saveToOss(String contentUrl, String fileName) {
|
|
||||||
try {
|
|
||||||
ApiSignUrlUploadResponse ossResponse = prepareOss(fileName);
|
|
||||||
streamUpload(ossResponse, urlDownload(contentUrl), fileName);
|
|
||||||
return ossResponse.getFileKey();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("下载合同并上传到OSS失败", e);
|
|
||||||
throw new ServiceException("下载合同并上传到OSS失败", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ApiSignUrlUploadResponse prepareOss(String fileName) {
|
private ApiSignUrlUploadResponse prepareOss(String fileName) {
|
||||||
ApiSignUrlUploadRequest ossRequest = new ApiSignUrlUploadRequest();
|
ApiSignUrlUploadRequest ossRequest = new ApiSignUrlUploadRequest();
|
||||||
ossRequest.setAppCode(essProps.getOssAppCode());
|
ossRequest.setAppCode(essProps.getOssAppCode());
|
||||||
@ -83,10 +54,22 @@ public class OssService {
|
|||||||
.assertResponse(serverFileServiceApi.signUrlFetchUpload(ossRequest));
|
.assertResponse(serverFileServiceApi.signUrlFetchUpload(ossRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String uploadToOss(String contentUrl, String fileName) {
|
||||||
|
try {
|
||||||
|
ApiSignUrlUploadResponse ossResponse = prepareOss(fileName);
|
||||||
|
streamUpload(ossResponse, urlDownload(contentUrl), fileName);
|
||||||
|
return ossResponse.getFileKey();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("下载合同并上传到OSS失败", e);
|
||||||
|
throw fail(e, "下载合同并上传到OSS失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private byte[] urlDownload(String url) throws IOException {
|
private byte[] urlDownload(String url) throws IOException {
|
||||||
HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
|
HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
|
||||||
con.setRequestMethod("GET");
|
con.setRequestMethod("GET");
|
||||||
con.setConnectTimeout(4 * 1000);
|
con.setConnectTimeout(10 * 1000);
|
||||||
|
con.setReadTimeout(10 * 1000);
|
||||||
InputStream inStream = con.getInputStream();
|
InputStream inStream = con.getInputStream();
|
||||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||||
byte[] buffer = new byte[2048];
|
byte[] buffer = new byte[2048];
|
||||||
|
|||||||
@ -26,14 +26,15 @@ public class PersonProfiles {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public PersonProfileDto getOrThrow(Long personId) {
|
public PersonProfileDto getOrThrow(Long personId) {
|
||||||
PersonProfileDto person = find(personId).orElse(null);
|
PersonProfileDto person = findOrNull(personId);
|
||||||
BizAssertions.assertNotNull(person, "找不到人员信息, personId={}", personId);
|
BizAssertions.assertNotNull(person, "找不到人员信息, personId={}", personId);
|
||||||
return person;
|
return person;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<PersonProfileDto> find(Long personId) {
|
public PersonProfileDto findOrNull(Long personId) {
|
||||||
return profiles.stream()
|
return profiles.stream()
|
||||||
.filter(p -> p.getId().equals(personId))
|
.filter(p -> p.getId().equals(personId))
|
||||||
.findFirst();
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -21,6 +21,21 @@ import java.util.Objects;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class BizAssertions {
|
public class BizAssertions {
|
||||||
|
|
||||||
|
public static ServiceException fail(String message, Object... args) {
|
||||||
|
return new ServiceException(MessageFormatter.arrayFormat(message, args).getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ServiceException fail(Exception e, String message, Object... args) {
|
||||||
|
return new ServiceException(MessageFormatter.arrayFormat(message, args).getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言集合为空
|
||||||
|
*/
|
||||||
|
public static void assertEmpty(Collection<?> actual, String message, Object... args) {
|
||||||
|
AssertUtil.isEmpty(actual, MessageFormatter.arrayFormat(message, args).getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 断言为NULL
|
* 断言为NULL
|
||||||
*/
|
*/
|
||||||
@ -42,13 +57,6 @@ public class BizAssertions {
|
|||||||
AssertUtil.notEmpty(actual, MessageFormatter.arrayFormat(message, args).getMessage());
|
AssertUtil.notEmpty(actual, MessageFormatter.arrayFormat(message, args).getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 断言集合为空
|
|
||||||
*/
|
|
||||||
public static void assertEmpty(Collection<?> actual, String message, Object... args) {
|
|
||||||
AssertUtil.isEmpty(actual, MessageFormatter.arrayFormat(message, args).getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 断言数组不为空
|
* 断言数组不为空
|
||||||
*/
|
*/
|
||||||
@ -100,13 +108,21 @@ public class BizAssertions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String messageOrTemplateMessage(String message, String template, Object... args) {
|
||||||
|
if (message != null) {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
return MessageFormatter.arrayFormat(template, args).getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
public static <T> T assertResponse(CommonResponse<T> response) {
|
public static <T> T assertResponse(CommonResponse<T> response) {
|
||||||
return assertResponse(response, "error resp={}", JSON.toJSONString(response));
|
return assertResponse(response, "error resp={}", JSON.toJSONString(response));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> T assertResponse(CommonResponse<T> response, String message, Object... args) {
|
public static <T> T assertResponse(CommonResponse<T> response, String message, Object... args) {
|
||||||
if (response == null || response.getCode() != HttpStatus.HTTP_OK) {
|
if (response == null || response.getCode() != HttpStatus.HTTP_OK) {
|
||||||
ServiceException e = new ServiceException(MessageFormatter.arrayFormat(message, args).getMessage());
|
ServiceException e = new ServiceException(messageOrTemplateMessage(
|
||||||
|
response == null ? null : response.getMsg(), message, args));
|
||||||
log.warn("remote call response with error", e);
|
log.warn("remote call response with error", e);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
@ -119,7 +135,7 @@ public class BizAssertions {
|
|||||||
|
|
||||||
public static <T> T assertResponse(ApiResult<T> response, String message, Object... args) {
|
public static <T> T assertResponse(ApiResult<T> response, String message, Object... args) {
|
||||||
if (!response.isSuccess()) {
|
if (!response.isSuccess()) {
|
||||||
ServiceException e = new ServiceException(MessageFormatter.arrayFormat(message, args).getMessage());
|
ServiceException e = new ServiceException(messageOrTemplateMessage(response.getMsg(), message, args));
|
||||||
log.warn("remote call response with error", e);
|
log.warn("remote call response with error", e);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
@ -132,29 +148,11 @@ public class BizAssertions {
|
|||||||
|
|
||||||
public static <T> List<T> assertResponse(ApiListResult<T> response, String message, Object... args) {
|
public static <T> List<T> assertResponse(ApiListResult<T> response, String message, Object... args) {
|
||||||
if (!response.isSuccess()) {
|
if (!response.isSuccess()) {
|
||||||
ServiceException e = new ServiceException(MessageFormatter.arrayFormat(message, args).getMessage());
|
ServiceException e = new ServiceException(messageOrTemplateMessage(response.getMsg(), message, args));
|
||||||
log.warn("remote call response with error", e);
|
log.warn("remote call response with error", e);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
return response.getData();
|
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user