PeriodScheduler.java 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package com.yimeng.okr.schedule;
  2. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  3. import com.yimeng.okr.entity.AssessmentPeriod;
  4. import com.yimeng.okr.entity.KrKeyResult;
  5. import com.yimeng.okr.entity.OkrObjective;
  6. import com.yimeng.okr.entity.SysUser;
  7. import com.yimeng.okr.enums.PeriodStatus;
  8. import com.yimeng.okr.event.NotificationEvent;
  9. import com.yimeng.okr.mapper.AssessmentPeriodMapper;
  10. import com.yimeng.okr.mapper.KrKeyResultMapper;
  11. import com.yimeng.okr.mapper.OkrObjectiveMapper;
  12. import com.yimeng.okr.mapper.SysUserMapper;
  13. import com.yimeng.okr.service.AssessmentPeriodService;
  14. import lombok.RequiredArgsConstructor;
  15. import lombok.extern.slf4j.Slf4j;
  16. import org.springframework.context.ApplicationEventPublisher;
  17. import org.springframework.scheduling.annotation.Scheduled;
  18. import org.springframework.stereotype.Component;
  19. import java.time.LocalDate;
  20. import java.time.temporal.ChronoUnit;
  21. import java.util.List;
  22. @Slf4j
  23. @Component
  24. @RequiredArgsConstructor
  25. public class PeriodScheduler {
  26. private final AssessmentPeriodService periodService;
  27. private final AssessmentPeriodMapper periodMapper;
  28. private final SysUserMapper userMapper;
  29. private final OkrObjectiveMapper objectiveMapper;
  30. private final KrKeyResultMapper krMapper;
  31. private final ApplicationEventPublisher publisher;
  32. @Scheduled(cron = "0 0 2 * * ?")
  33. public void autoAdvancePeriods() {
  34. log.info("Running period auto-advance check...");
  35. periodService.checkAndAutoAdvance();
  36. }
  37. @Scheduled(cron = "0 0 10 * * ?")
  38. public void checkPeriodDeadlines() {
  39. log.info("Checking period deadlines...");
  40. List<AssessmentPeriod> periods = periodMapper.selectList(
  41. new LambdaQueryWrapper<AssessmentPeriod>()
  42. .eq(AssessmentPeriod::getStatus, PeriodStatus.EXECUTING));
  43. LocalDate today = LocalDate.now();
  44. for (AssessmentPeriod p : periods) {
  45. try {
  46. if (ChronoUnit.DAYS.between(today, p.getEndDate()) == 3) {
  47. List<SysUser> users = userMapper.selectList(null);
  48. for (SysUser u : users) {
  49. publisher.publishEvent(new NotificationEvent(
  50. this, u.getId(), "PERIOD_DEADLINE",
  51. "周期即将结束", "考核周期「" + p.getName() + "」将于3天后结束",
  52. "period", p.getId()));
  53. }
  54. }
  55. } catch (Exception e) {
  56. log.warn("Failed to check deadline for period {}: {}", p.getId(), e.getMessage());
  57. }
  58. }
  59. }
  60. @Scheduled(cron = "0 7 10 * * ?")
  61. public void checkKrLagging() {
  62. log.info("Checking KR lagging...");
  63. List<AssessmentPeriod> periods = periodMapper.selectList(
  64. new LambdaQueryWrapper<AssessmentPeriod>()
  65. .eq(AssessmentPeriod::getStatus, PeriodStatus.EXECUTING));
  66. LocalDate today = LocalDate.now();
  67. for (AssessmentPeriod p : periods) {
  68. try {
  69. long totalDays = ChronoUnit.DAYS.between(p.getStartDate(), p.getEndDate());
  70. if (totalDays <= 0) continue;
  71. long elapsedDays = ChronoUnit.DAYS.between(p.getStartDate(), today);
  72. if (elapsedDays < 3) continue; // ignore first 3 days
  73. double elapsedRatio = Math.min(1.0, (double) elapsedDays / totalDays);
  74. double expectedProgress = elapsedRatio * 100;
  75. List<OkrObjective> objectives = objectiveMapper.selectList(
  76. new LambdaQueryWrapper<OkrObjective>()
  77. .eq(OkrObjective::getPeriodId, p.getId())
  78. .eq(OkrObjective::getStatus, "APPROVED"));
  79. for (OkrObjective obj : objectives) {
  80. List<KrKeyResult> krs = krMapper.selectList(
  81. new LambdaQueryWrapper<KrKeyResult>()
  82. .eq(KrKeyResult::getObjectiveId, obj.getId()));
  83. for (KrKeyResult kr : krs) {
  84. if ("COMPLETED".equals(kr.getStatus())) continue;
  85. double actualProgress = kr.getTargetValue() > 0
  86. ? (kr.getCurrentValue() / kr.getTargetValue()) * 100 : 0;
  87. if (actualProgress < expectedProgress - 20) {
  88. publisher.publishEvent(new NotificationEvent(
  89. this, obj.getUserId(), "KR_LAGGING",
  90. "KR 进度滞后",
  91. "「" + kr.getTitle() + "」进度落后于时间线(当前 "
  92. + Math.round(actualProgress) + "%,预期 " + Math.round(expectedProgress) + "%),请及时更新",
  93. "objective", obj.getId()));
  94. }
  95. }
  96. }
  97. } catch (Exception e) {
  98. log.warn("Failed to check KR lagging for period {}: {}", p.getId(), e.getMessage());
  99. }
  100. }
  101. }
  102. }