package jnpf.dmsService;
|
|
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import jnpf.dmsEntity.DmsWenjianBanbenEntity;
|
import jnpf.dmsEntity.DmsWenjianXinzengShenheEntity;
|
import jnpf.dmsEntity.DmsWenjianXiudingShenheEntity;
|
import jnpf.dmsEntity.DmsWenjianXiudingShenqingZixiangEntity;
|
import jnpf.dmsEntity.storage.form.DmsWorkflowFilePrepareForm;
|
import jnpf.dmsEntity.storage.DmsWorkflowSourceKey;
|
import jnpf.dmsEntity.storage.enums.DmsWorkflowFileType;
|
import jnpf.dmsEntity.storage.vo.DmsFileUploadVO;
|
import jnpf.dmsMapper.DmsFileObjectMapper;
|
import jnpf.dmsMapper.DmsWenjianXinzengShenheMapper;
|
import jnpf.dmsMapper.DmsWenjianXiudingShenheMapper;
|
import jnpf.dmsMapper.DmsWenjianBanbenMapper;
|
import jnpf.dmsMapper.DmsWenjianXiudingShenqingZixiangMapper;
|
import jnpf.exception.DataException;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.stereotype.Component;
|
|
import java.net.URI;
|
import java.util.UUID;
|
|
@Component
|
@RequiredArgsConstructor
|
public class DmsWorkflowApprovalValidator {
|
private final ObjectMapper objectMapper;
|
private final DmsWenjianBanbenMapper businessVersionMapper;
|
private final DmsWenjianXiudingShenqingZixiangMapper revisionDetailMapper;
|
private final DmsFileObjectMapper fileObjectMapper;
|
private final DmsWenjianXinzengShenheMapper newAuditMapper;
|
private final DmsWenjianXiudingShenheMapper revisionAuditMapper;
|
|
public String validateNew(DmsWenjianXinzengShenheEntity audit,
|
DmsWorkflowFilePrepareForm form) {
|
requireEqual(audit.getWenjianBianhao(), form.getDocumentNo(), "文件编号");
|
requireEqual(audit.getWenjianMingcheng(), form.getDocumentName(), "文件名称");
|
requireEqual(audit.getWenjianMuluId(), form.getFolderId() == null ? null : form.getFolderId().toString(), "文件目录");
|
requireEqual(audit.getGuishuBumenId(), form.getResponsibleDeptId(), "归属部门");
|
return approvedFile(audit.getWenjian(), form.getUrl());
|
}
|
|
public String validateRevision(String tenantId, DmsWenjianXiudingShenheEntity audit,
|
DmsWorkflowFilePrepareForm form) {
|
requireEqual(audit.getWenjianMingcheng(), form.getDocumentName(), "文件名称");
|
requireEqual(audit.getWenjianMuluId(), form.getFolderId() == null ? null : form.getFolderId().toString(), "文件目录");
|
requireEqual(audit.getGuishuBumenId(), form.getResponsibleDeptId(), "归属部门");
|
String businessVersionId = audit.getYuanWenjianBanbenId();
|
String businessFileId = audit.getWenjianId();
|
if (audit.getXiudingShenqingZixiangId() != null) {
|
DmsWenjianXiudingShenqingZixiangEntity detail = revisionDetailMapper.selectByIdForUpdate(
|
tenantId, audit.getXiudingShenqingZixiangId());
|
if (detail == null) {
|
throw new DataException("修订审核单关联的申请子项不存在");
|
}
|
businessVersionId = detail.getYuanWenjianBanbenId();
|
businessFileId = detail.getWenjianId();
|
}
|
if (businessVersionId == null || businessFileId == null) {
|
throw new DataException("修订审核单缺少批准的原文件版本");
|
}
|
DmsWenjianBanbenEntity version = businessVersionMapper.selectById(tenantId, businessVersionId);
|
if (version == null || !businessFileId.equals(version.getWenjianId())) {
|
throw new DataException("修订审核单关联的业务文件版本不存在或不匹配");
|
}
|
// 业务版本ID与文件中心UUID不是同一套ID,必须通过已有映射核对。
|
try {
|
if (form.getVersionId() == null || !form.getVersionId().equals(fileCenterVersion(tenantId, version))) {
|
throw new DataException("versionId与审核批准的文件中心版本不一致");
|
}
|
} catch (IllegalArgumentException | NullPointerException exception) {
|
throw new DataException("审核批准的原版本尚未关联有效的文件中心版本");
|
}
|
return approvedFile(audit.getWenjian(), form.getUrl());
|
}
|
|
private UUID fileCenterVersion(String tenantId, DmsWenjianBanbenEntity version) {
|
if (version.getWenjianZhongxinBanbenId() != null) {
|
return UUID.fromString(version.getWenjianZhongxinBanbenId());
|
}
|
// 兼容尚未回写映射的业务版本,只从其来源审核单的任务登记解析,不能信任请求UUID。
|
if (version.getLaiyuanDanjuId() == null || version.getLaiyuanZixiangId() != null) {
|
throw new DataException("审核批准的原版本尚未关联文件中心版本");
|
}
|
String key = null;
|
if ("xinzeng_shenhe".equals(version.getLaiyuanDanjuLeixing())) {
|
DmsWenjianXinzengShenheEntity source = newAuditMapper.selectOne(
|
new LambdaQueryWrapper<DmsWenjianXinzengShenheEntity>()
|
.eq(DmsWenjianXinzengShenheEntity::getTenantId, tenantId)
|
.eq(DmsWenjianXinzengShenheEntity::getId, version.getLaiyuanDanjuId())
|
.isNull(DmsWenjianXinzengShenheEntity::getDeleteMark));
|
if (source != null) {
|
key = DmsWorkflowSourceKey.of(source.getFlowId(), source.getFlowTaskId(), DmsWorkflowFileType.CREATE);
|
}
|
} else if ("xiuding_shenhe".equals(version.getLaiyuanDanjuLeixing())) {
|
DmsWenjianXiudingShenheEntity source = revisionAuditMapper.selectOne(
|
new LambdaQueryWrapper<DmsWenjianXiudingShenheEntity>()
|
.eq(DmsWenjianXiudingShenheEntity::getTenantId, tenantId)
|
.eq(DmsWenjianXiudingShenheEntity::getId, version.getLaiyuanDanjuId())
|
.isNull(DmsWenjianXiudingShenheEntity::getDeleteMark));
|
if (source != null) {
|
key = DmsWorkflowSourceKey.of(source.getFlowId(), source.getFlowTaskId(), DmsWorkflowFileType.REVISE);
|
}
|
}
|
DmsFileUploadVO registered = key == null ? null
|
: fileObjectMapper.selectUploadBySource(tenantId, "jnpf-file", key);
|
if (registered == null || registered.getFileVersionId() == null) {
|
throw new DataException("审核批准的原版本尚未登记到文件中心");
|
}
|
return registered.getFileVersionId();
|
}
|
|
private void requireEqual(String approved, String requested, String label) {
|
if (approved == null || approved.trim().isEmpty() || requested == null
|
|| !approved.trim().equals(requested.trim())) {
|
throw new DataException(label + "与审核批准的内容不一致");
|
}
|
}
|
|
String approvedFile(String json, String url) {
|
try {
|
JsonNode root = objectMapper.readTree(json);
|
JsonNode file = findFile(root, filePath(url));
|
if (file == null) {
|
throw new DataException("文件URL不在审核批准的附件中");
|
}
|
return objectMapper.writeValueAsString(file);
|
} catch (DataException exception) {
|
throw exception;
|
} catch (Exception exception) {
|
throw new DataException("审核单附件信息无效,无法验证批准的文件");
|
}
|
}
|
|
private JsonNode findFile(JsonNode node, String path) {
|
if (node == null) {
|
return null;
|
}
|
if (node.isObject() && node.path("url").isTextual()) {
|
if (path.equals(filePath(node.get("url").asText()))) {
|
return node;
|
}
|
}
|
if (node.isContainerNode()) {
|
for (JsonNode child : node) {
|
JsonNode found = findFile(child, path);
|
if (found != null) {
|
return found;
|
}
|
}
|
}
|
return null;
|
}
|
|
private String filePath(String url) {
|
URI uri = URI.create(url.trim());
|
if (uri.getScheme() != null && !"http".equalsIgnoreCase(uri.getScheme())
|
&& !"https".equalsIgnoreCase(uri.getScheme())) {
|
throw new DataException("审核附件不是公共文件路径");
|
}
|
String path = uri.getPath();
|
String prefix = "/api/file/Image/";
|
int start = path == null ? -1 : path.indexOf(prefix);
|
if (start < 0) {
|
throw new DataException("审核附件不是公共文件路径");
|
}
|
String suffix = path.substring(start + prefix.length());
|
String[] parts = suffix.split("/", -1);
|
if (parts.length != 2) {
|
throw new DataException("审核附件路径格式不正确");
|
}
|
for (String part : parts) {
|
if (part.isBlank() || part.contains("\\") || ".".equals(part) || "..".equals(part)) {
|
throw new DataException("审核附件路径格式不正确");
|
}
|
}
|
return suffix;
|
}
|
}
|