package jnpf.dmsService; import jnpf.audit.sdk.annotation.AuditLog; import jnpf.base.ActionResultCode; import jnpf.dmsEntity.storage.DmsTemplateNotification; import jnpf.dmsMapper.DmsTemplateNotificationMapper; import jnpf.exception.DataException; import jnpf.message.SentMessageApi; import jnpf.message.model.DmsUpgradeMessage; import jnpf.util.JsonUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import java.util.*; /** 与文件登记重试独立;通知重试每次查询模板最新部门,远端按事件/用户幂等落站内信。 */ @Slf4j @Service @RequiredArgsConstructor public class DmsTemplateNotificationService { private final DmsTemplateNotificationMapper mapper; private final SentMessageApi messages; @Scheduled(cron = "${dms.template-upgrade-notification.cron:0 * * * * ?}") @AuditLog(action = "DMS_TEMPLATE_UPGRADE_NOTIFY", bizCodeExpr = "''", recordSuccess = false) public void recover() { mapper.discover(); for (DmsTemplateNotification event : mapper.pending()) deliver(event); } /** 工作流回调即时尝试;失败只留通知重试,不阻塞已有文件登记。 */ public void approved(String tenant, String task) { try { mapper.discover(); DmsTemplateNotification event = mapper.find(tenant, task); if (event != null) deliver(event); } catch (RuntimeException failure) { log.error("升版通知待自动恢复 tenant={} task={}", tenant, task, failure); } } void deliver(DmsTemplateNotification event) { String token = UUID.randomUUID().toString(); if (mapper.claim(event, token) != 1) return; try { Map template = mapper.template(event.getTenantId(), event.getTemplateId()); if (template == null) throw new DataException("来源模板不存在或已删除"); List departments = departmentIds(template.get("departments")); List users = departments.isEmpty() ? List.of() : mapper.recipients(event.getTenantId(), departments); if (!users.isEmpty()) { DmsUpgradeMessage request = new DmsUpgradeMessage(); request.setTenantId(event.getTenantId()); request.setTaskId(event.getTaskId()); request.setActorId(event.getActorId()); request.setToUserIds(users); Map parameters = new LinkedHashMap<>(); parameters.put("DocumentNo", Objects.toString(event.getDocumentNo(), "")); parameters.put("DocumentName", Objects.toString(event.getDocumentName(), "")); parameters.put("Version", Objects.toString(event.getVersionLabel(), "")); parameters.put("TemplateName", Objects.toString(template.get("name"), "")); request.setParameters(parameters); var result = messages.sendDmsUpgrade(request); if (result == null || !ActionResultCode.SUCCESS.getCode().equals(result.getCode()) || !Boolean.TRUE.equals(result.getData())) throw new DataException("站内信未返回持久化成功确认"); } if (mapper.finish(event, token, null, users.isEmpty() ? "NO_RECIPIENTS" : "SENT") != 1) throw new DataException("通知执行租约已变化"); } catch (RuntimeException failure) { String error = Objects.toString(failure.getMessage(), failure.getClass().getSimpleName()); mapper.finish(event, token, error.substring(0, Math.min(error.length(), 1000)), "RETRY"); log.error("升版模板部门通知失败,保留任务待重试 tenant={} task={}", event.getTenantId(), event.getTaskId(), failure); } } static List departmentIds(Object value) { if (value == null || value instanceof String && ((String) value).isBlank()) return List.of(); Object parsed = value instanceof String ? JsonUtil.getJsonToBean((String) value, List.class) : value; if (!(parsed instanceof List)) throw new DataException("模板提醒部门配置不是数组"); Set result = new LinkedHashSet<>(); for (Object id : (List) parsed) { if (!(id instanceof String) || ((String) id).isBlank()) throw new DataException("模板提醒部门ID无效"); result.add((String) id); } return new ArrayList<>(result); } }