package jnpf.limsService.impl; import jnpf.limsEntity.LimsWendingxingJianyanCountRow; import jnpf.limsEntity.LimsWendingxingJihuaZhixingCountRow; import jnpf.limsEntity.LimsMessageEvent; import jnpf.limsEntity.LimsMessageRequest; import jnpf.limsEntity.LimsRecipientRef; import jnpf.limsEntity.LimsStabilityCompletionRow; import jnpf.limsMapper.LimsWendingxingWanchengMapper; import jnpf.limsService.LimsMessageService; import jnpf.limsService.LimsWendingxingWanchengService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; /** * 稳定性考察计划自动完成定时任务。 */ @Slf4j @Service public class LimsWendingxingWanchengServiceImpl implements LimsWendingxingWanchengService { private final AtomicBoolean running = new AtomicBoolean(false); @Autowired private LimsWendingxingWanchengMapper limsWendingxingWanchengMapper; @Autowired private LimsMessageService messageService; @Value("${lims.wendingxing.wancheng.page-size:200}") private int pageSize; @Value("${lims.message.enabled:false}") private boolean messageEnabled; @Scheduled(cron = "${lims.wendingxing.wancheng.cron:0 */10 * * * ?}") public void cronTrigger() { if (!running.compareAndSet(false, true)) { log.warn("[wendingxing-wancheng] previous scan is still running, skip this trigger"); return; } try { log.info("[wendingxing-wancheng] cron triggered"); scanAndComplete(); } catch (Exception e) { log.error("[wendingxing-wancheng] scan failed: {}", e.getMessage(), e); } finally { running.set(false); } } @Override public Map scanAndComplete() { int actualPageSize = pageSize > 0 ? pageSize : 200; int scanned = 0; int cycleCompleted = 0; int resultCompleted = 0; int updated = 0; String lastJihuaId = null; while (true) { List page = limsWendingxingWanchengMapper.selectJihuaZhixingPage(lastJihuaId, actualPageSize); if (page.isEmpty()) { break; } scanned += page.size(); lastJihuaId = page.get(page.size() - 1).getKaocaJihuaId(); List allCyclesCompletedIds = new ArrayList<>(); for (LimsWendingxingJihuaZhixingCountRow row : page) { if (row.getTotalCount() == row.getYizhixingCount()) { allCyclesCompletedIds.add(row.getKaocaJihuaId()); } } cycleCompleted += allCyclesCompletedIds.size(); if (allCyclesCompletedIds.isEmpty()) { continue; } List counts = limsWendingxingWanchengMapper.selectJianyanCounts(allCyclesCompletedIds); List allResultsCompletedIds = new ArrayList<>(); for (LimsWendingxingJianyanCountRow row : counts) { if (row.getJianyanXiangCount() != row.getJianyanJieguoLuruCount()) { continue; } allResultsCompletedIds.add(row.getWendingxingJiluId()); } resultCompleted += allResultsCompletedIds.size(); if (!allResultsCompletedIds.isEmpty()) { List updatedIds = limsWendingxingWanchengMapper .updateJihuaYiwanchengReturning(allResultsCompletedIds); updated += updatedIds.size(); notifyCompletedPlans(updatedIds); } } Map stats = new LinkedHashMap<>(); stats.put("scanned", scanned); stats.put("cycleCompleted", cycleCompleted); stats.put("resultCompleted", resultCompleted); stats.put("updated", updated); log.info("[wendingxing-wancheng] done, stats={}", stats); return stats; } private void notifyCompletedPlans(List updatedIds) { if (!messageEnabled || updatedIds.isEmpty()) { return; } Date completedAt = new Date(); for (LimsStabilityCompletionRow row : limsWendingxingWanchengMapper.selectCompletionDetails(updatedIds)) { List recipients = new ArrayList<>(); if (row.getCreatorUserId() != null && !row.getCreatorUserId().trim().isEmpty()) { recipients.add(LimsRecipientRef.user(row.getCreatorUserId())); } recipients.add(LimsRecipientRef.roleEnCode("ROLE.002")); Map parameters = new LinkedHashMap<>(); parameters.put("bizId", row.getId()); parameters.put("planCode", value(row.getPlanCode())); parameters.put("planName", value(row.getPlanName())); parameters.put("sampleName", value(row.getSampleName())); parameters.put("batchNo", value(row.getBatchNo())); parameters.put("stabilityType", value(row.getStabilityType())); parameters.put("cycleCount", row.getCycleCount()); parameters.put("completedAt", new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss") .format(completedAt)); messageService.send(LimsMessageRequest.builder() .event(LimsMessageEvent.STABILITY_PLAN_COMPLETED) .tenantId(value(row.getTenantId())) .bizId(row.getId()) .remindStage("COMPLETED") .occurrenceKey(LimsMessageEvent.STABILITY_PLAN_COMPLETED.getCode() + ":" + row.getId()) .recipients(recipients) .parameters(parameters) .build()); } } private String value(String value) { return value == null ? "" : value; } }