package jnpf.limsService.impl; import jnpf.limsEntity.LimsHaocaiAlertRow; import jnpf.limsEntity.LimsMessageEvent; import jnpf.limsEntity.LimsMessageRequest; import jnpf.limsEntity.LimsMessageSendResult; import jnpf.limsEntity.LimsRecipientRef; import jnpf.limsMapper.LimsHaocaiAlertMapper; import jnpf.limsService.LimsHaocaiAlertService; import jnpf.limsService.LimsMessageService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @Slf4j @Service @RequiredArgsConstructor public class LimsHaocaiAlertServiceImpl implements LimsHaocaiAlertService { private static final String QC_ADMIN_ROLE = "ROLE.005"; private final LimsHaocaiAlertMapper alertMapper; private final LimsMessageService messageService; @Value("${lims.message.enabled:false}") private boolean messageEnabled; @Scheduled(cron = "${lims.haocai.alert.cron:0 0 1 * * ?}") public void cronTrigger() { if (!messageEnabled) { log.info("[haocai-alert] skipped because lims.message.enabled=false"); return; } log.info("[haocai-alert] cron triggered"); scanAndAlert(false); } @Override public Map scanAndAlert(boolean dryRun) { List rows = alertMapper.selectBelowThreshold(); int sent = 0; for (LimsHaocaiAlertRow row : rows) { LimsMessageSendResult result = messageService.send(LimsMessageRequest.builder() .event(LimsMessageEvent.CONSUMABLE_STOCK_LOW) .tenantId(row.getTenantId()) .bizId(row.getId()) .remindStage("DAILY") .occurrenceKey(LimsMessageEvent.CONSUMABLE_STOCK_LOW.getCode() + ":" + row.getId() + ":" + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE)) .recipients(Arrays.asList(LimsRecipientRef.roleEnCode(QC_ADMIN_ROLE))) .parameters(parameters(row)) .dryRun(dryRun) .build()); if (result.isAccepted() && result.getRecipientCount() > 0 && result.getSentCount() == result.getRecipientCount() && result.getFailedCount() == 0) { sent++; } } Map stats = new LinkedHashMap<>(); stats.put("hit", rows.size()); stats.put("sent", sent); stats.put("skipped", rows.size() - sent); log.info("[haocai-alert] done, dryRun={}, stats={}", dryRun, stats); return stats; } private Map parameters(LimsHaocaiAlertRow row) { Map parameters = new HashMap<>(); parameters.put("bizId", row.getId()); parameters.put("bizName", row.getMingcheng() == null ? "" : row.getMingcheng()); parameters.put("currentStock", plain(row.getJieyuSum())); parameters.put("warningStock", row.getQuehuoYujing() == null ? "" : row.getQuehuoYujing()); return parameters; } private String plain(BigDecimal value) { return value == null ? "0" : value.stripTrailingZeros().toPlainString(); } }