Files
klp-oa/klp-da/src/main/java/com/klp/da/task/AcidOeeMonthTask.java
Joshi 56b05a02a1 fix(wms): 解决已发货钢卷占用实际库区的问题
- 添加了对已发货钢卷的状态检查,防止其占用实际库区
- 实现了已发货钢卷释放旧库区的功能
- 优化了库区状态更新逻辑,增加了对-1标识的判断
- 在钢卷占用库区时添加了发货状态验证

refactor(da): 优化酸轧OEE月度任务初始化方式

- 将@PostConstruct替换为ApplicationRunner接口实现
- 添加@Async注解实现异步执行,避免阻塞项目启动
- 重构了启动时OEE汇总计算的执行时机和方式
2026-03-13 10:58:59 +08:00

144 lines
5.1 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.klp.da.task;
import com.alibaba.fastjson2.JSON;
import com.klp.pocket.acid.domain.vo.AcidOeeDailySummaryVo;
import com.klp.pocket.acid.service.IAcidOeeService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* 酸轧线 OEE 当月预计算任务
*
* 需求对应 docs/oee-report-design.md 第 12.2 节:
* - 项目启动完成后即计算当月 OEE 聚合结果并写入 Redis
* - 每天凌晨 04:00 重新计算当月数据并覆盖缓存。
*
* 当前仅实现酸轧线SY的当月日汇总预计算
* key 约定:
* - 汇总结果oee:report:month:summary:{yyyyMM}:SY
* - 元信息: oee:report:month:meta:{yyyyMM}:SY
*/
@Slf4j
@RequiredArgsConstructor
@Component
public class AcidOeeMonthTask implements ApplicationRunner {
/** Redis 缓存 key 模板:当月 OEE 汇总(酸轧线) */
private static final String SUMMARY_KEY_PATTERN = "oee:report:month:summary:%s:SY";
/** Redis 缓存 key 模板:当月元信息(酸轧线) */
private static final String META_KEY_PATTERN = "oee:report:month:meta:%s:SY";
private static final DateTimeFormatter YEAR_MONTH_FMT = DateTimeFormatter.ofPattern("yyyyMM");
private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ISO_DATE;
private static final DateTimeFormatter DATE_TIME_FMT = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
private final IAcidOeeService acidOeeService;
private final StringRedisTemplate stringRedisTemplate;
/**
* 项目启动完成后计算一次当月酸轧 OEE 汇总并写入 Redis。
* 使用 ApplicationRunner 在 Spring Boot 启动完成后执行。
* 使用 @Async 异步执行,不阻塞项目启动。
*/
@Async
@Override
public void run(ApplicationArguments args) throws Exception {
try {
computeCurrentMonth("startup");
} catch (Exception e) {
log.error("[AcidOeeMonthTask] startup compute failed", e);
}
}
/**
* 每天凌晨 04:00 重新计算当月酸轧 OEE 汇总并覆盖 Redis 缓存。
*/
@Scheduled(cron = "0 0 4 * * ?")
public void scheduleDaily() {
try {
computeCurrentMonth("schedule-04");
} catch (Exception e) {
log.error("[AcidOeeMonthTask] 4am compute failed", e);
}
}
/**
* 计算当前月份从当月1号到今天的酸轧 OEE 日汇总,并写入 Redis。
*
* @param trigger 触发来源标记startup / schedule-04 等)
*/
private void computeCurrentMonth(String trigger) {
long startNs = System.nanoTime();
LocalDate now = LocalDate.now();
String yyyyMM = now.format(YEAR_MONTH_FMT);
LocalDate startDate = now.withDayOfMonth(1);
LocalDate endDate = now;
String startStr = startDate.format(DATE_FMT);
String endStr = endDate.format(DATE_FMT);
log.info("[AcidOeeMonthTask] trigger={}, computing acid OEE month summary for {} ({} ~ {})",
trigger, yyyyMM, startStr, endStr);
// 1. 调用 pocket 的 AcidOeeService 获取当月日汇总
List<AcidOeeDailySummaryVo> dailySummaryList = acidOeeService.getDailySummary(startStr, endStr);
// 2. 写入 Redissummary
String summaryKey = String.format(SUMMARY_KEY_PATTERN, yyyyMM);
String summaryJson = JSON.toJSONString(dailySummaryList);
stringRedisTemplate.opsForValue().set(summaryKey, summaryJson, 1, TimeUnit.DAYS);
long durationMs = (System.nanoTime() - startNs) / 1_000_000L;
// 3. 写入 Redismeta
Meta meta = new Meta();
meta.setComputedAt(LocalDateTime.now().format(DATE_TIME_FMT));
meta.setDurationMs(durationMs);
meta.setStartDate(startStr);
meta.setEndDate(endStr);
meta.setTrigger(trigger);
String metaKey = String.format(META_KEY_PATTERN, yyyyMM);
stringRedisTemplate.opsForValue().set(metaKey, JSON.toJSONString(meta), 1, TimeUnit.DAYS);
log.info("[AcidOeeMonthTask] compute finish for {} dailySize={}, durationMs={}ms, summaryKey={}",
yyyyMM, dailySummaryList.size(), durationMs, summaryKey);
}
/**
* 当月预计算元信息
*/
@Data
private static class Meta {
/** 计算完成时间ISO-8601 字符串) */
private String computedAt;
/** 计算耗时(毫秒) */
private long durationMs;
/** 统计起始日期yyyy-MM-dd */
private String startDate;
/** 统计结束日期yyyy-MM-dd */
private String endDate;
/** 触发来源startup / schedule-04 等) */
private String trigger;
}
}