package jnpf.dmsService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import jnpf.base.ActionResult; import jnpf.base.ActionResultCode; import jnpf.dms.DmsResourceApi; import jnpf.dmsEntity.DmsWenjianBanbenEntity; import jnpf.dmsEntity.DmsWenjianChayueShenqingEntity; import jnpf.dmsEntity.DmsWenjianChayueShenqingZixiangEntity; import jnpf.dmsEntity.permission.form.DmsPersonalFolderBorrowForm; import jnpf.dmsEntity.permission.vo.DmsPersonalFolderAddResultVO; import jnpf.dmsMapper.DmsWenjianBanbenMapper; import jnpf.dmsMapper.DmsWenjianChayueShenqingMapper; import jnpf.dmsMapper.DmsWenjianChayueShenqingZixiangMapper; import jnpf.exception.DataException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.time.LocalDate; import java.time.ZoneId; import java.util.ArrayList; import java.util.Date; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; /** 文件辅助管理中的查阅授权业务。 */ @Service @RequiredArgsConstructor public class DmsWenjianFuzhuGuanliChayueService { private static final String FLOWABLE_SERVICE_ID = "jnpf-flowable"; private static final ZoneId BUSINESS_ZONE = ZoneId.of("Asia/Shanghai"); private final DmsWenjianChayueShenqingMapper shenqingMapper; private final DmsWenjianChayueShenqingZixiangMapper zixiangMapper; private final DmsWenjianBanbenMapper banbenMapper; private final DmsResourceApi dmsResourceApi; /** * 根据流程申请把获批查阅的文件版本加入申请人的个人文件夹。 */ public DmsPersonalFolderAddResultVO chayueWenjianShouquan(String flowId, String flowTaskId) { String normalizedFlowId = requireValue(flowId, "流程ID(flow_id)"); String normalizedFlowTaskId = requireValue(flowTaskId, "流程任务ID(flow_task_id)"); DmsWenjianChayueShenqingEntity shenqing = findShenqing( normalizedFlowId, normalizedFlowTaskId); List zixiangs = findZixiangs(shenqing.getId()); Set banbenIds = extractBanbenIds(zixiangs); Map chayueQixianMap = extractChayueQixianMap(zixiangs); List banbens = findBanbens(banbenIds); DmsPersonalFolderBorrowForm borrowForm = buildBorrowForm( shenqing, banbens, chayueQixianMap); ActionResult response; try { response = dmsResourceApi.addBorrowedFilesToPersonalFolder( FLOWABLE_SERVICE_ID, borrowForm); } 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); } return response.getData(); } /** 查询流程唯一对应的未删除查阅申请。 */ private DmsWenjianChayueShenqingEntity findShenqing(String flowId, String flowTaskId) { LambdaQueryWrapper query = new LambdaQueryWrapper<>(); query.eq(DmsWenjianChayueShenqingEntity::getFlowId, flowId) .eq(DmsWenjianChayueShenqingEntity::getFlowTaskId, flowTaskId) .isNull(DmsWenjianChayueShenqingEntity::getDeleteMark); List 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 findZixiangs(String shenqingId) { LambdaQueryWrapper query = new LambdaQueryWrapper<>(); query.eq(DmsWenjianChayueShenqingZixiangEntity::getForeignId, shenqingId) .isNull(DmsWenjianChayueShenqingZixiangEntity::getDeleteMark); List rows = zixiangMapper.selectList(query); if (rows.isEmpty()) { throw new DataException("文件查阅申请未关联查阅明细,无法授权"); } return rows; } /** 从申请明细提取业务版本 ID 并保持原顺序去重。 */ private Set extractBanbenIds( List zixiangs) { Set ids = new LinkedHashSet<>(); for (DmsWenjianChayueShenqingZixiangEntity zixiang : zixiangs) { ids.add(requireValue(zixiang.getBanbenId(), "文件查阅明细版本ID(banben_id)")); } return ids; } /** 按业务版本 ID 提取查阅期限(天)。 */ private Map extractChayueQixianMap( List zixiangs) { Map result = new LinkedHashMap<>(); for (DmsWenjianChayueShenqingZixiangEntity zixiang : zixiangs) { String banbenId = requireValue(zixiang.getBanbenId(), "文件查阅明细版本ID(banben_id)"); String rawQixian = requireValue(zixiang.getChayueQixian(), "文件查阅期限(chayue_qixian)"); int chayueQixian; try { chayueQixian = Integer.parseInt(rawQixian); } catch (NumberFormatException exception) { throw new DataException("文件查阅期限(chayue_qixian)必须是非负整数"); } if (chayueQixian < 0) { throw new DataException("文件查阅期限(chayue_qixian)必须是非负整数"); } Integer existing = result.putIfAbsent(banbenId, chayueQixian); if (existing != null && existing != chayueQixian) { throw new DataException("同一文件版本存在不同的查阅期限:banben_id=" + banbenId); } } return result; } /** 按明细版本 ID 查询未删除的业务文件版本。 */ private List findBanbens(Set banbenIds) { LambdaQueryWrapper query = new LambdaQueryWrapper<>(); query.in(DmsWenjianBanbenEntity::getId, banbenIds) .isNull(DmsWenjianBanbenEntity::getDeleteMark); List banbens = banbenMapper.selectList(query); if (banbens.size() != banbenIds.size()) { throw new DataException("部分查阅明细未找到对应的有效文件版本"); } return banbens; } /** 组装个人文件夹借阅文件请求。 */ private DmsPersonalFolderBorrowForm buildBorrowForm( DmsWenjianChayueShenqingEntity shenqing, List banbens, Map chayueQixianMap) { List files = new ArrayList<>(banbens.size()); for (DmsWenjianBanbenEntity banben : banbens) { DmsPersonalFolderBorrowForm.FileRelation relation = new DmsPersonalFolderBorrowForm.FileRelation(); relation.setDocumentId(UUID.fromString(banben.getWenjianZhongxinWenjianId())); relation.setFileVersionId(UUID.fromString(banben.getWenjianZhongxinBanbenId())); relation.setValidTo(calculateValidTo(chayueQixianMap.get(banben.getId()), banben.getId())); files.add(relation); } DmsPersonalFolderBorrowForm form = new DmsPersonalFolderBorrowForm(); form.setUserId(shenqing.getShenqingren().trim()); form.setFiles(files); return form; } private Date calculateValidTo(Integer chayueQixian, String banbenId) { if (chayueQixian == null) { throw new DataException("文件版本缺少查阅期限:banben_id=" + banbenId); } return Date.from(LocalDate.now(BUSINESS_ZONE) .plusDays(chayueQixian) .atTime(23, 59, 59) .atZone(BUSINESS_ZONE) .toInstant()); } 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(); } }