package jnpf.dmsService;
|
|
import jnpf.base.UserInfo;
|
import jnpf.dmsEntity.permission.entity.DmsDocumentEntity;
|
import jnpf.dmsEntity.permission.entity.DmsFileVersionEntity;
|
import jnpf.dmsEntity.permission.entity.DmsPermissionResourceEntity;
|
import jnpf.dmsEntity.permission.enums.DmsPermissionAction;
|
import jnpf.dmsEntity.permission.enums.DmsResourceType;
|
import jnpf.dmsEntity.storage.entity.DmsFileObjectEntity;
|
import jnpf.dmsEntity.storage.form.DmsFileRevisionRegisterForm;
|
import jnpf.dmsEntity.storage.vo.DmsFileUploadVO;
|
import jnpf.dmsIntegration.audit.DmsAuditAdapter;
|
import jnpf.dmsMapper.DmsDocumentMapper;
|
import jnpf.dmsMapper.DmsFileObjectMapper;
|
import jnpf.dmsMapper.DmsFileVersionMapper;
|
import jnpf.dmsMapper.DmsPermissionResourceMapper;
|
import jnpf.dmsMapper.DmsVersionStateMapper;
|
import jnpf.dmsPermission.DmsCurrentIdentity;
|
import jnpf.dmsPermission.DmsPermissionError;
|
import jnpf.dmsPermission.DmsPermissionException;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.dao.DuplicateKeyException;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.util.Locale;
|
import java.util.Objects;
|
|
@Service
|
@RequiredArgsConstructor
|
public class DmsFileRevisionService {
|
private static final String SOURCE_PREFIX = "revision:";
|
|
private final DmsCurrentIdentity currentIdentity;
|
private final DmsPermissionDecisionService decisionService;
|
private final DmsDocumentMapper documentMapper;
|
private final DmsFileVersionMapper fileVersionMapper;
|
private final DmsPermissionResourceMapper resourceMapper;
|
private final DmsFileObjectMapper fileObjectMapper;
|
private final DmsVersionStateMapper versionStateMapper;
|
private final DmsAuditAdapter auditAdapter;
|
|
@Transactional
|
public DmsFileUploadVO register(DmsFileRevisionRegisterForm form, String serviceId) {
|
UserInfo user = currentIdentity.requireUser();
|
String tenantId = currentIdentity.tenantId(user);
|
String sourceId = form.getSourceId().trim();
|
decisionService.requireAllowed(DmsResourceType.DOCUMENT, form.getDocumentId(),
|
DmsPermissionAction.UPDATE);
|
|
fileObjectMapper.lockSource(tenantId, serviceId, sourceId);
|
DmsFileUploadVO existing = fileObjectMapper.selectUploadBySource(tenantId, serviceId, sourceId);
|
if (existing != null) {
|
validateRetry(existing, form);
|
return existing;
|
}
|
|
DmsDocumentEntity document = documentMapper.selectByTenantAndIdForUpdate(tenantId,
|
form.getDocumentId());
|
if (document == null) {
|
throw DmsPermissionException.of(DmsPermissionError.RESOURCE_NOT_FOUND, "待修订文件不存在");
|
}
|
DmsFileVersionEntity current = fileVersionMapper.selectCurrentEffective(tenantId,
|
form.getDocumentId());
|
if (current == null || !Objects.equals(current.getId(), form.getBaseFileVersionId())) {
|
throw DmsPermissionException.of(DmsPermissionError.REVISION_CONFLICT,
|
"待修订版本已不是现行有效版本,请刷新后重试");
|
}
|
|
long nextVersionNo = fileVersionMapper.selectNextVersionNo(tenantId, form.getDocumentId());
|
try {
|
insertFileVersion(form, tenantId, user.getUserId(), nextVersionNo);
|
insertRegistry(form, tenantId, serviceId, sourceId);
|
insertFileObject(form, tenantId, user.getUserId(), serviceId, sourceId);
|
int superseded = versionStateMapper.supersedeCurrent(tenantId, form.getDocumentId(),
|
form.getBaseFileVersionId(), form.getVersionLabel().trim(), user.getUserId());
|
if (superseded != 1) {
|
throw DmsPermissionException.of(DmsPermissionError.REVISION_CONFLICT,
|
"现行有效版本已发生变化,请刷新后重试");
|
}
|
versionStateMapper.insertRevisionEffective(tenantId, form.getDocumentId(),
|
form.getBaseFileVersionId(), form.getFileVersionId(), sourceId,
|
form.getRevisionReason().trim(), user.getUserId());
|
} catch (DuplicateKeyException exception) {
|
throw conflict("修订登记的资源 ID、source_id、版本号、版本标签或对象键已被占用", exception);
|
}
|
|
auditAdapter.dataChange("UPDATE", "模拟修订 DMS 文件", "dms_documents",
|
form.getDocumentId().toString(),
|
"{\"fileVersionId\":\"" + form.getBaseFileVersionId() + "\"}",
|
"{\"fileVersionId\":\"" + form.getFileVersionId() + "\",\"versionLabel\":\""
|
+ escapeJson(form.getVersionLabel().trim()) + "\"}");
|
return fileObjectMapper.selectUploadBySource(tenantId, serviceId, sourceId);
|
}
|
|
private void insertFileVersion(DmsFileRevisionRegisterForm form, String tenantId,
|
String userId, long versionNo) {
|
DmsFileVersionEntity version = new DmsFileVersionEntity();
|
version.setId(form.getFileVersionId());
|
version.setTenantId(tenantId);
|
version.setDocumentId(form.getDocumentId());
|
version.setVersionNo(versionNo);
|
version.setVersionLabel(form.getVersionLabel().trim());
|
version.setFileName(form.getFileName().trim());
|
version.setMimeType(trimToNull(form.getMimeType()));
|
version.setSizeBytes(form.getSizeBytes());
|
version.setChecksumSha256(form.getChecksumSha256().toLowerCase(Locale.ROOT));
|
version.setPreparedBy(form.getPreparedBy().trim());
|
version.setPreparedOn(form.getPreparedOn());
|
version.setCreatedBy(userId);
|
fileVersionMapper.insert(version);
|
}
|
|
private void insertRegistry(DmsFileRevisionRegisterForm form, String tenantId,
|
String serviceId, String sourceId) {
|
DmsPermissionResourceEntity registry = new DmsPermissionResourceEntity();
|
registry.setId(form.getFileVersionId());
|
registry.setTenantId(tenantId);
|
registry.setResourceType(DmsResourceType.FILE_VERSION.name());
|
registry.setSourceType("SYSTEM");
|
registry.setSourceId(SOURCE_PREFIX + sourceId + ":version");
|
registry.setRegisteredBy(serviceId);
|
resourceMapper.insert(registry);
|
}
|
|
private void insertFileObject(DmsFileRevisionRegisterForm form, String tenantId, String userId,
|
String serviceId, String sourceId) {
|
DmsFileObjectEntity object = new DmsFileObjectEntity();
|
object.setId(form.getFileObjectId());
|
object.setTenantId(tenantId);
|
object.setFileVersionId(form.getFileVersionId());
|
object.setStoragePlatform(form.getStoragePlatform().trim());
|
object.setBucketName(form.getBucketName().trim());
|
object.setBasePath(trimToEmpty(form.getBasePath()));
|
object.setObjectPath(form.getObjectPath().trim());
|
object.setObjectName(form.getObjectName().trim());
|
object.setSourceServiceId(serviceId);
|
object.setSourceId(sourceId);
|
object.setCreatedBy(userId);
|
fileObjectMapper.insert(object);
|
}
|
|
private void validateRetry(DmsFileUploadVO existing, DmsFileRevisionRegisterForm form) {
|
if (!Objects.equals(existing.getDocumentId(), form.getDocumentId())
|
|| !Objects.equals(existing.getBaseFileVersionId(), form.getBaseFileVersionId())
|
|| !Objects.equals(existing.getVersionLabel(), form.getVersionLabel().trim())
|
|| !Objects.equals(existing.getFileName(), form.getFileName().trim())
|
|| !Objects.equals(existing.getMimeType(), trimToNull(form.getMimeType()))
|
|| !Objects.equals(existing.getSizeBytes(), form.getSizeBytes())
|
|| !equalsIgnoreCase(existing.getChecksumSha256(), form.getChecksumSha256())
|
|| !Objects.equals(existing.getPreparedBy(), form.getPreparedBy().trim())
|
|| !Objects.equals(existing.getPreparedOn(), form.getPreparedOn())
|
|| !Objects.equals(existing.getRevisionReason(), form.getRevisionReason().trim())) {
|
throw DmsPermissionException.of(DmsPermissionError.IDEMPOTENCY_CONFLICT,
|
"source_id 对应的修订内容与本次请求不一致");
|
}
|
}
|
|
private String trimToNull(String value) {
|
return value == null || value.trim().isEmpty() ? null : value.trim();
|
}
|
|
private String trimToEmpty(String value) {
|
return value == null ? "" : value.trim();
|
}
|
|
private boolean equalsIgnoreCase(String left, String right) {
|
return left == null ? right == null : right != null && left.equalsIgnoreCase(right);
|
}
|
|
private String escapeJson(String value) {
|
return value.replace("\\", "\\\\").replace("\"", "\\\"");
|
}
|
|
private DmsPermissionException conflict(String message, Throwable cause) {
|
DmsPermissionException exception = DmsPermissionException.of(DmsPermissionError.SOURCE_CONFLICT, message);
|
exception.initCause(cause);
|
return exception;
|
}
|
}
|