package jnpf.dmsService;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import jnpf.audit.sdk.annotation.AuditLog;
|
import jnpf.base.ActionResult;
|
import jnpf.base.ActionResultCode;
|
import jnpf.dms.DmsResourceApi;
|
import jnpf.dmsEntity.DmsWenjianBanbenEntity;
|
import jnpf.dmsEntity.fenfa.DmsWenjianDayinRenwuEntity;
|
import jnpf.dmsEntity.permission.form.DmsPersonalFolderFileForm;
|
import jnpf.dmsEntity.print.DmsWenjianDayinShenqingDetailEntity;
|
import jnpf.dmsEntity.print.DmsWenjianDayinShenqingEntity;
|
import jnpf.dmsEntity.print.form.DmsWorkflowPrintFilesGrantForm;
|
import jnpf.dmsEntity.print.vo.DmsWorkflowPrintFilesGrantResultVO;
|
import jnpf.dmsMapper.DmsWenjianBanbenMapper;
|
import jnpf.dmsMapper.DmsWenjianDayinShenqingDetailMapper;
|
import jnpf.dmsMapper.DmsWenjianDayinShenqingMapper;
|
import jnpf.dmsMapper.DmsWenjianFenfaMapper;
|
import jnpf.exception.DataException;
|
import jnpf.util.RandomUtil;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.sql.Timestamp;
|
import java.time.Instant;
|
import java.time.LocalDate;
|
import java.time.LocalDateTime;
|
import java.time.ZoneId;
|
import java.time.format.DateTimeParseException;
|
import java.util.ArrayList;
|
import java.util.Date;
|
import java.util.LinkedHashSet;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Set;
|
import java.util.UUID;
|
import java.util.function.Function;
|
import java.util.stream.Collectors;
|
|
/** 文件辅助管理中的打印授权业务。 */
|
@Service
|
@RequiredArgsConstructor
|
public class DmsWenjianFuzhuGuanliDayinService {
|
|
private static final String FLOWABLE_SERVICE_ID = "jnpf-flowable";
|
private static final String PRINT_REQUEST_SOURCE = "wenjian_dayin";
|
private static final String DOCUMENT_CATEGORY = "[\"wenjian\"]";
|
private static final String PENDING_PRINT = "daidayin";
|
private static final ZoneId BUSINESS_ZONE = ZoneId.of("Asia/Shanghai");
|
|
private final DmsWenjianDayinShenqingMapper shenqingMapper;
|
private final DmsWenjianDayinShenqingDetailMapper zixiangMapper;
|
private final DmsWenjianBanbenMapper banbenMapper;
|
private final DmsWenjianFenfaMapper fenfaMapper;
|
private final DmsWenjianDayinHaomaService numbers;
|
private final DmsResourceApi dmsResourceApi;
|
|
/** 根据流程申请为申请人永久授予获批文件版本的打印权限。 */
|
@Transactional(rollbackFor = Exception.class)
|
@AuditLog(action = "CREATE_PRINT_TASKS_FROM_PRINT_REQUEST", recordSuccess = false,
|
label = "文件打印申请生成打印任务", bizModule = "DMS",
|
bizType = "DMS_PRINT_TASK", bizCodeExpr = "#flowTaskId",
|
targetTable = "dms_wenjian_dayin_renwu", bizCodeRequired = false)
|
public DmsWorkflowPrintFilesGrantResultVO dayinWenjianShouquan(
|
String flowId, String flowTaskId) {
|
String normalizedFlowId = requireValue(flowId, "流程ID(flow_id)");
|
String normalizedFlowTaskId = requireValue(flowTaskId, "流程任务ID(flow_task_id)");
|
DmsWenjianDayinShenqingEntity shenqing = findShenqing(
|
normalizedFlowId, normalizedFlowTaskId);
|
List<DmsWenjianDayinShenqingDetailEntity> zixiangs = findZixiangs(shenqing.getId());
|
Set<String> banbenIds = extractBanbenIds(zixiangs);
|
List<DmsWenjianBanbenEntity> banbens = findBanbens(banbenIds);
|
DmsWorkflowPrintFilesGrantForm grantForm = buildGrantForm(shenqing, banbens);
|
// 全部明细先校验、构造完成,再调用跨服务授权,避免非法数量留下授权副作用。
|
List<DmsWenjianDayinRenwuEntity> tasks = buildPrintTasks(shenqing, zixiangs, banbens);
|
|
ActionResult<DmsWorkflowPrintFilesGrantResultVO> response;
|
try {
|
response = dmsResourceApi.grantWorkflowPrintFiles(
|
FLOWABLE_SERVICE_ID, grantForm);
|
} catch (RuntimeException exception) {
|
throw new DataException("调用DMS文件打印授权接口失败");
|
}
|
if (response == null || !ActionResultCode.SUCCESS.getCode().equals(response.getCode())
|
|| response.getData() == null) {
|
String message = response == null ? null : response.getMsg();
|
throw new DataException(isBlank(message) ? "打印文件授权失败或响应数据不完整" : message);
|
}
|
tasks.sort(java.util.Comparator.comparing(DmsWenjianDayinRenwuEntity::getWenjianBianhao).thenComparing(DmsWenjianDayinRenwuEntity::getBanbenhao).thenComparing(DmsWenjianDayinRenwuEntity::getId));
|
tasks.forEach(task -> {
|
if (fenfaMapper.insertPrintTaskIfAbsent(task) == 1) numbers.ensureTaskNumbers(task.getTenantId(), task, 0);
|
});
|
return response.getData();
|
}
|
|
/** 根据申请明细及获批版本快照构造任务,在任何授权或写入前校验整批数据。 */
|
private List<DmsWenjianDayinRenwuEntity> buildPrintTasks(
|
DmsWenjianDayinShenqingEntity shenqing,
|
List<DmsWenjianDayinShenqingDetailEntity> zixiangs,
|
List<DmsWenjianBanbenEntity> banbens) {
|
Map<String, DmsWenjianBanbenEntity> versions = banbens.stream()
|
.collect(Collectors.toMap(DmsWenjianBanbenEntity::getId, Function.identity()));
|
List<DmsWenjianDayinRenwuEntity> tasks = new ArrayList<>(zixiangs.size());
|
Date now = new Date();
|
String tenantId = shenqing.getTenantId();
|
String requestId = shenqing.getId();
|
String applicantUserId = requireValue(
|
shenqing.getApplicantUserId(), "文件打印申请人(shenqing_ren)");
|
|
for (DmsWenjianDayinShenqingDetailEntity zixiang : zixiangs) {
|
DmsWenjianDayinRenwuEntity task = new DmsWenjianDayinRenwuEntity();
|
task.setId(RandomUtil.uuId());
|
task.setTenantId(tenantId);
|
task.setLaiyuanLeixing(PRINT_REQUEST_SOURCE);
|
task.setLaiyuanDanjuId(requestId);
|
task.setLaiyuanMingxiId(zixiang.getId());
|
task.setWenjianId(zixiang.getFileReferenceId());
|
task.setWenjianBianhao(zixiang.getFileNumber());
|
task.setWenjianMingcheng(zixiang.getFileName());
|
task.setBanbenhao(zixiang.getVersionLabel());
|
task.setShenheWanchengRiqi(shenqing.getFileAdministratorDate());
|
task.setShengxiaoRiqi(parseEffectiveDate(zixiang.getEffectiveDate()));
|
task.setWenjianLeibie(DOCUMENT_CATEGORY);
|
task.setDayinFenshu(parsePrintCopies(zixiang.getPrintCopies(), zixiang.getId()));
|
task.setBeizhuShuoming(zixiang.getPurpose());
|
task.setBizStatus(PENDING_PRINT);
|
task.setCreatorUserId(applicantUserId);
|
task.setCreatorTime(now);
|
task.setJieshouBumenId(shenqing.getShenqingrenBumen());
|
String controlled = requireValue(versions.get(zixiang.getBanbenId()).getShifouShoukong(),
|
"申请文件版本是否受控");
|
if (!"yes".equals(controlled) && !"no".equals(controlled)) {
|
throw new DataException("申请文件版本是否受控必须为yes或no:" + zixiang.getBanbenId());
|
}
|
task.setShifouShoukong(controlled);
|
tasks.add(task);
|
}
|
return tasks;
|
}
|
|
/** 将在线表单保存的日期文本转换为打印任务时间。 */
|
private Date parseEffectiveDate(String value) {
|
if (value == null || value.isEmpty()) {
|
return null;
|
}
|
String normalized = requireValue(value, "文件生效日期(wenjian_shengxiao_riqi)");
|
try {
|
if (normalized.matches("\\d{13}")) {
|
return new Date(Long.parseLong(normalized));
|
}
|
if (normalized.length() == 10) {
|
return Date.from(LocalDate.parse(normalized).atStartOfDay(BUSINESS_ZONE).toInstant());
|
}
|
if (normalized.endsWith("Z")) {
|
return Date.from(Instant.parse(normalized));
|
}
|
return Timestamp.valueOf(LocalDateTime.parse(
|
normalized.replace(' ', 'T')));
|
} catch (DateTimeParseException | IllegalArgumentException exception) {
|
throw new DataException("文件生效日期格式不正确:" + normalized);
|
}
|
}
|
|
/** 解析并校验打印份数。 */
|
private int parsePrintCopies(String value, String detailId) {
|
String normalized = requireValue(value, "打印数量(dayin_shuliang)");
|
try {
|
if (!normalized.matches("[1-9][0-9]*")) {
|
throw new NumberFormatException();
|
}
|
int copies = Integer.parseInt(normalized);
|
if (copies <= 0) {
|
throw new NumberFormatException();
|
}
|
return copies;
|
} catch (NumberFormatException exception) {
|
throw new DataException("打印数量必须是正整数:明细ID=" + detailId);
|
}
|
}
|
|
/** 查询流程唯一对应的未删除打印申请。 */
|
private DmsWenjianDayinShenqingEntity findShenqing(String flowId, String flowTaskId) {
|
LambdaQueryWrapper<DmsWenjianDayinShenqingEntity> query = new LambdaQueryWrapper<>();
|
query.eq(DmsWenjianDayinShenqingEntity::getFlowId, flowId)
|
.eq(DmsWenjianDayinShenqingEntity::getFlowTaskId, flowTaskId)
|
.isNull(DmsWenjianDayinShenqingEntity::getDeleteMark);
|
List<DmsWenjianDayinShenqingEntity> rows = shenqingMapper.selectList(query);
|
if (rows.isEmpty()) {
|
throw new DataException("未找到文件打印申请:flow_id=" + flowId
|
+ ", flow_task_id=" + flowTaskId);
|
}
|
if (rows.size() > 1) {
|
throw new DataException("flow_id与flow_task_id关联了多条文件打印申请,无法授权");
|
}
|
return rows.get(0);
|
}
|
|
/** 根据申请主键查询未删除的打印申请明细。 */
|
private List<DmsWenjianDayinShenqingDetailEntity> findZixiangs(String shenqingId) {
|
LambdaQueryWrapper<DmsWenjianDayinShenqingDetailEntity> query =
|
new LambdaQueryWrapper<>();
|
query.eq(DmsWenjianDayinShenqingDetailEntity::getRequestId, shenqingId)
|
.isNull(DmsWenjianDayinShenqingDetailEntity::getDeleteMark);
|
List<DmsWenjianDayinShenqingDetailEntity> rows = zixiangMapper.selectList(query);
|
if (rows.isEmpty()) {
|
throw new DataException("文件打印申请未关联打印明细,无法授权");
|
}
|
return rows;
|
}
|
|
/** 从打印明细提取业务版本 ID,并保持原顺序去重。 */
|
private Set<String> extractBanbenIds(List<DmsWenjianDayinShenqingDetailEntity> zixiangs) {
|
Set<String> ids = new LinkedHashSet<>();
|
for (DmsWenjianDayinShenqingDetailEntity zixiang : zixiangs) {
|
ids.add(requireValue(zixiang.getBanbenId(), "文件打印明细版本ID(banben_id)"));
|
}
|
return ids;
|
}
|
|
/** 按明细版本 ID 查询未删除的业务文件版本。 */
|
private List<DmsWenjianBanbenEntity> findBanbens(Set<String> banbenIds) {
|
LambdaQueryWrapper<DmsWenjianBanbenEntity> query = new LambdaQueryWrapper<>();
|
query.in(DmsWenjianBanbenEntity::getId, banbenIds)
|
.isNull(DmsWenjianBanbenEntity::getDeleteMark);
|
List<DmsWenjianBanbenEntity> rows = banbenMapper.selectList(query);
|
if (rows.size() != banbenIds.size()) {
|
throw new DataException("部分打印明细未找到对应的有效文件版本");
|
}
|
return rows;
|
}
|
|
/** 组装永久有效的文件打印授权请求。 */
|
private DmsWorkflowPrintFilesGrantForm buildGrantForm(
|
DmsWenjianDayinShenqingEntity shenqing,
|
List<DmsWenjianBanbenEntity> banbens) {
|
List<DmsPersonalFolderFileForm.FileRelation> files = new ArrayList<>(banbens.size());
|
for (DmsWenjianBanbenEntity banben : banbens) {
|
DmsPersonalFolderFileForm.FileRelation relation =
|
new DmsPersonalFolderFileForm.FileRelation();
|
try {
|
relation.setDocumentId(UUID.fromString(banben.getWenjianZhongxinWenjianId()));
|
relation.setFileVersionId(UUID.fromString(banben.getWenjianZhongxinBanbenId()));
|
} catch (IllegalArgumentException exception) {
|
throw new DataException("文件中心文件ID或版本ID格式不正确:banben_id="
|
+ banben.getId());
|
}
|
relation.setValidTo(null);
|
files.add(relation);
|
}
|
|
DmsWorkflowPrintFilesGrantForm form = new DmsWorkflowPrintFilesGrantForm();
|
form.setUserId(requireValue(
|
shenqing.getApplicantUserId(), "文件打印申请人(shenqing_ren)"));
|
form.setFiles(files);
|
return form;
|
}
|
|
private String requireValue(String value, String fieldName) {
|
if (isBlank(value)) {
|
throw new DataException(fieldName + "不能为空");
|
}
|
return value.trim();
|
}
|
|
private boolean isBlank(String value) {
|
return value == null || value.trim().isEmpty();
|
}
|
}
|