package jnpf.limsService.impl;
|
|
import jnpf.limsEntity.*;
|
import jnpf.limsMapper.LimsBusinessReminderMapper;
|
import jnpf.limsMapper.LimsMessageAudienceMapper;
|
import jnpf.limsService.LimsBusinessReminderService;
|
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.time.LocalDateTime;
|
import java.time.format.DateTimeFormatter;
|
import java.util.Collections;
|
import java.util.Date;
|
import java.util.ArrayList;
|
import java.util.Arrays;
|
import java.util.LinkedHashSet;
|
import java.util.LinkedHashMap;
|
import java.util.List;
|
import java.util.Map;
|
|
@Slf4j
|
@Service
|
@RequiredArgsConstructor
|
public class LimsBusinessReminderServiceImpl implements LimsBusinessReminderService {
|
private static final DateTimeFormatter DATE = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
private static final DateTimeFormatter KEY_DATE = DateTimeFormatter.ofPattern("yyyyMMdd");
|
|
private final LimsBusinessReminderMapper reminderMapper;
|
private final LimsMessageAudienceMapper audienceMapper;
|
private final LimsMessageService messageService;
|
|
@Value("${lims.message.enabled:false}")
|
private boolean messageEnabled;
|
|
@Scheduled(cron = "${lims.message.business-reminder-cron:0 10 8 * * ?}")
|
public void cronTrigger() {
|
if (!messageEnabled) {
|
log.info("[lims-business-reminder] skipped because lims.message.enabled=false");
|
return;
|
}
|
scanAndRemind(false);
|
}
|
|
@Override
|
public Map<String, Map<String, Integer>> scanAndRemind(boolean dryRun) {
|
Map<String, Map<String, Integer>> stats = new LinkedHashMap<>();
|
stats.put("equipmentCalibration", remindEquipment(dryRun));
|
stats.put("equipmentVerification", remindEquipmentVerification(dryRun));
|
stats.put("retainObservation", remindRetainObservation(dryRun));
|
stats.put("environmentSampling", remindEnvironmentSampling(dryRun));
|
stats.put("consumableExpiry", remindConsumableExpiry(dryRun));
|
stats.put("retainDestruction", remindRetainDestruction(dryRun));
|
stats.put("stabilityPeriod", remindStabilityPeriod(dryRun));
|
log.info("[lims-business-reminder] done, dryRun={}, stats={}", dryRun, stats);
|
return stats;
|
}
|
|
private Map<String, Integer> remindEquipment(boolean dryRun) {
|
List<LimsEquipmentCalibrationReminderRow> rows = reminderMapper.selectEquipmentCalibrationDue();
|
int sent = 0;
|
for (LimsEquipmentCalibrationReminderRow row : rows) {
|
Map<String, Object> parameters = new LinkedHashMap<>();
|
parameters.put("bizId", row.getId());
|
parameters.put("equipmentName", value(row.getName()));
|
parameters.put("equipmentCode", value(row.getCode()));
|
parameters.put("reminderDate", format(row.getReminderDate()));
|
parameters.put("dueDate", format(row.getDueDate()));
|
LimsMessageSendResult result = messageService.send(LimsMessageRequest.builder()
|
.event(LimsMessageEvent.EQUIPMENT_CALIBRATION_DUE)
|
.tenantId(row.getTenantId())
|
.bizId(row.getId())
|
.remindStage("DUE")
|
.occurrenceKey(LimsMessageEvent.EQUIPMENT_CALIBRATION_DUE.getCode() + ":"
|
+ row.getId() + ":" + keyDate(row.getDueDate()))
|
.recipients(Collections.singletonList(LimsRecipientRef.user(row.getRecipientUserId())))
|
.parameters(parameters)
|
.dryRun(dryRun)
|
.build());
|
if (isComplete(result)) {
|
sent++;
|
}
|
}
|
return stat(rows.size(), sent);
|
}
|
|
private Map<String, Integer> remindRetainObservation(boolean dryRun) {
|
List<LimsRetainObservationReminderRow> rows = reminderMapper.selectRetainObservationDue();
|
int sent = 0;
|
for (LimsRetainObservationReminderRow row : rows) {
|
Map<String, Object> parameters = new LinkedHashMap<>();
|
parameters.put("bizId", row.getId());
|
parameters.put("planId", value(row.getPlanId()));
|
parameters.put("sampleName", value(row.getSampleName()));
|
parameters.put("sampleCode", value(row.getSampleCode()));
|
parameters.put("batchNo", value(row.getBatchNo()));
|
parameters.put("observationDate", format(row.getObservationDate()));
|
LimsMessageSendResult result = messageService.send(LimsMessageRequest.builder()
|
.event(LimsMessageEvent.RETAIN_SAMPLE_OBSERVATION_DUE)
|
.tenantId(row.getTenantId())
|
.bizId(row.getId())
|
.remindStage("DUE")
|
.occurrenceKey(LimsMessageEvent.RETAIN_SAMPLE_OBSERVATION_DUE.getCode() + ":"
|
+ row.getId() + ":" + keyDate(row.getObservationDate()))
|
.recipients(Collections.singletonList(LimsRecipientRef.user(row.getRecipientUserId())))
|
.parameters(parameters)
|
.dryRun(dryRun)
|
.build());
|
if (isComplete(result)) {
|
sent++;
|
}
|
}
|
return stat(rows.size(), sent);
|
}
|
|
private Map<String, Integer> remindEquipmentVerification(boolean dryRun) {
|
List<LimsEquipmentCalibrationReminderRow> rows = reminderMapper.selectEquipmentVerificationDue();
|
int sent = 0;
|
for (LimsEquipmentCalibrationReminderRow row : rows) {
|
Map<String, Object> parameters = new LinkedHashMap<>();
|
parameters.put("bizId", row.getId());
|
parameters.put("equipmentName", value(row.getName()));
|
parameters.put("equipmentCode", value(row.getCode()));
|
parameters.put("reminderDate", format(row.getReminderDate()));
|
parameters.put("dueDate", format(row.getDueDate()));
|
LimsMessageSendResult result = send(LimsMessageEvent.EQUIPMENT_VERIFICATION_DUE,
|
row.getTenantId(), row.getId(), "DUE", keyDate(row.getDueDate()),
|
Collections.singletonList(LimsRecipientRef.user(row.getRecipientUserId())),
|
parameters, dryRun);
|
if (isComplete(result)) {
|
sent++;
|
}
|
}
|
return stat(rows.size(), sent);
|
}
|
|
private Map<String, Integer> remindEnvironmentSampling(boolean dryRun) {
|
List<LimsEnvironmentSamplingReminderRow> rows = reminderMapper.selectEnvironmentSamplingDue();
|
int sent = 0;
|
for (LimsEnvironmentSamplingReminderRow row : rows) {
|
Map<String, Object> parameters = new LinkedHashMap<>();
|
parameters.put("bizId", row.getPlanId());
|
parameters.put("planName", value(row.getPlanName()));
|
parameters.put("planType", value(row.getPlanType()));
|
parameters.put("plannedDate", format(row.getPlannedDate()));
|
parameters.put("monitoringArea", value(row.getMonitoringArea()));
|
parameters.put("cleanlinessLevel", value(row.getCleanlinessLevel()));
|
parameters.put("monitoringItems", value(row.getMonitoringItems()));
|
LimsMessageSendResult result = send(LimsMessageEvent.ENVIRONMENT_SAMPLING_DUE,
|
row.getTenantId(), row.getPlanId(), "DUE", keyDate(row.getPlannedDate()),
|
Collections.singletonList(LimsRecipientRef.roleEnCode("ROLE.004")),
|
parameters, dryRun);
|
if (isComplete(result)) {
|
sent++;
|
}
|
}
|
return stat(rows.size(), sent);
|
}
|
|
private Map<String, Integer> remindConsumableExpiry(boolean dryRun) {
|
List<LimsConsumableExpiryReminderRow> rows = reminderMapper.selectConsumableExpiryDue();
|
int sent = 0;
|
for (LimsConsumableExpiryReminderRow row : rows) {
|
Map<String, Object> parameters = new LinkedHashMap<>();
|
parameters.put("bizId", row.getId());
|
parameters.put("batchCode", value(row.getBatchCode()));
|
parameters.put("barcode", value(row.getBarcode()));
|
parameters.put("consumableName", value(row.getName()));
|
parameters.put("specification", value(row.getSpecification()));
|
parameters.put("remainingQuantity", value(row.getRemainingQuantity()));
|
parameters.put("unit", value(row.getUnit()));
|
parameters.put("storageLocation", value(row.getStorageLocation()));
|
parameters.put("expiryDate", format(row.getExpiryDate()));
|
parameters.put("reminderStage", row.getReminderStage());
|
parameters.put("remainingDays", row.getRemainingDays());
|
LimsMessageSendResult result = send(LimsMessageEvent.CONSUMABLE_BATCH_EXPIRY_DUE,
|
row.getTenantId(), row.getId(), row.getReminderStage(),
|
keyDate(row.getExpiryDate()) + ":" + row.getReminderStage(),
|
Collections.singletonList(LimsRecipientRef.roleEnCode("ROLE.005")),
|
parameters, dryRun);
|
if (isComplete(result)) {
|
sent++;
|
}
|
}
|
return stat(rows.size(), sent);
|
}
|
|
private Map<String, Integer> remindRetainDestruction(boolean dryRun) {
|
List<LimsRetainDestructionReminderRow> rows = reminderMapper.selectRetainDestructionDue();
|
int sent = 0;
|
for (LimsRetainDestructionReminderRow row : rows) {
|
Map<String, Object> parameters = new LinkedHashMap<>();
|
parameters.put("bizId", row.getId());
|
parameters.put("sampleName", value(row.getSampleName()));
|
parameters.put("sampleCode", value(row.getSampleCode()));
|
parameters.put("batchNo", value(row.getBatchNo()));
|
parameters.put("currentQuantity", value(row.getCurrentQuantity()));
|
parameters.put("unit", value(row.getUnit()));
|
parameters.put("storageLocation", value(row.getStorageLocation()));
|
parameters.put("retentionDeadline", format(row.getRetentionDeadline()));
|
LimsMessageSendResult result = send(LimsMessageEvent.RETAIN_SAMPLE_DESTRUCTION_DUE,
|
row.getTenantId(), row.getId(), "DUE", keyDate(row.getRetentionDeadline()),
|
Collections.singletonList(LimsRecipientRef.roleEnCode("ROLE.005")),
|
parameters, dryRun);
|
if (isComplete(result)) {
|
sent++;
|
}
|
}
|
return stat(rows.size(), sent);
|
}
|
|
private Map<String, Integer> remindStabilityPeriod(boolean dryRun) {
|
List<LimsStabilityPeriodReminderRow> rows = reminderMapper.selectStabilityPeriodDue();
|
int sent = 0;
|
for (LimsStabilityPeriodReminderRow row : rows) {
|
LinkedHashSet<String> users = new LinkedHashSet<>();
|
if (value(row.getOrganizationIds()).length() > 0) {
|
Arrays.stream(row.getOrganizationIds().split(","))
|
.map(String::trim).filter(item -> !item.isEmpty())
|
.forEach(organizationId -> users.addAll(audienceMapper.selectOrganizationRoleUsers(
|
row.getTenantId(), organizationId, "ROLE.004")));
|
}
|
List<LimsRecipientRef> recipients = new ArrayList<>();
|
users.forEach(userId -> recipients.add(LimsRecipientRef.user(userId)));
|
Map<String, Object> parameters = new LinkedHashMap<>();
|
parameters.put("bizId", row.getId());
|
parameters.put("planId", row.getPlanId());
|
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("period", row.getPeriod());
|
parameters.put("periodUnit", value(row.getPeriodUnit()));
|
parameters.put("plannedDate", format(row.getPlannedDate()));
|
parameters.put("inspectionItems", value(row.getInspectionItems()));
|
LimsMessageSendResult result = send(LimsMessageEvent.STABILITY_PERIOD_DUE,
|
row.getTenantId(), row.getId(), "DUE", keyDate(row.getPlannedDate()),
|
recipients, parameters, dryRun);
|
if (isComplete(result)) {
|
sent++;
|
}
|
}
|
return stat(rows.size(), sent);
|
}
|
|
private LimsMessageSendResult send(LimsMessageEvent event, String tenantId, String bizId,
|
String stage, String keySuffix, List<LimsRecipientRef> recipients,
|
Map<String, Object> parameters, boolean dryRun) {
|
return messageService.send(LimsMessageRequest.builder().event(event).tenantId(tenantId)
|
.bizId(bizId).remindStage(stage)
|
.occurrenceKey(event.getCode() + ":" + bizId + ":" + keySuffix)
|
.recipients(recipients).parameters(parameters).dryRun(dryRun).build());
|
}
|
|
private boolean isComplete(LimsMessageSendResult result) {
|
return result.isAccepted() && result.getRecipientCount() > 0
|
&& result.getSentCount() == result.getRecipientCount() && result.getFailedCount() == 0;
|
}
|
|
private Map<String, Integer> stat(int hit, int sent) {
|
Map<String, Integer> stats = new LinkedHashMap<>();
|
stats.put("hit", hit);
|
stats.put("sent", sent);
|
stats.put("skipped", hit - sent);
|
return stats;
|
}
|
|
private String format(LocalDateTime value) {
|
return value == null ? "" : value.format(DATE);
|
}
|
|
private String format(Date value) {
|
return value == null ? "" : new java.text.SimpleDateFormat("yyyy-MM-dd").format(value);
|
}
|
|
private String keyDate(LocalDateTime value) {
|
return value == null ? "NO_DATE" : value.format(KEY_DATE);
|
}
|
|
private String keyDate(Date value) {
|
return value == null ? "NO_DATE" : new java.text.SimpleDateFormat("yyyyMMdd").format(value);
|
}
|
|
private String value(String value) {
|
return value == null ? "" : value;
|
}
|
}
|