From 7c2b68615207bfae95e208d1f0f16eb0612e8394 Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期一, 24 八月 2026 22:50:09 +0800
Subject: [PATCH] feat(mes): 计量器具已过期提醒接入系统消息提示(站内信)

---
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/metering/MesDvMeteringMapper.java          |    6 ++++++
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/RedisKeyConstants.java                        |   10 ++++++++++
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/dv/metering/MesDvMeteringRemindRedisDAO.java  |   14 ++++++++++++++
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/metering/MesDvMeteringRemindServiceImpl.java |   30 ++++++++++++++++++++++--------
 4 files changed, 52 insertions(+), 8 deletions(-)

diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/metering/MesDvMeteringMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/metering/MesDvMeteringMapper.java
index a4078de..1583a20 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/metering/MesDvMeteringMapper.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/metering/MesDvMeteringMapper.java
@@ -42,4 +42,10 @@
                 .le(MesDvMeteringDO::getNextCheckDate, end));
     }
 
+    default List<MesDvMeteringDO> selectListByNextCheckDateBefore(LocalDate date) {
+        return selectList(new LambdaQueryWrapperX<MesDvMeteringDO>()
+                .isNotNull(MesDvMeteringDO::getNextCheckDate)
+                .lt(MesDvMeteringDO::getNextCheckDate, date));
+    }
+
 }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/RedisKeyConstants.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/RedisKeyConstants.java
index ca7c0fe..74929ab 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/RedisKeyConstants.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/RedisKeyConstants.java
@@ -31,4 +31,14 @@
      */
     String METERING_EXPIRE_REMIND_SCAN = "mes:dv:metering:remind:scan:";
 
+    /**
+     * 璁¢噺鍣ㄥ叿宸茶繃鏈熸彁閱掑幓閲�
+     *
+     * KEY 鏍煎紡锛歮es:dv:metering:overdue:remind:{meteringId}:{nextCheckDate}
+     * VALUE 鏁版嵁鏍煎紡锛�1
+     *
+     * 涓� {@link #METERING_EXPIRE_REMIND} 鐩镐簰鐙珛锛屼繚璇佸櫒鍏疯繃鏈熷悗浠嶈兘鍗曠嫭鎻愰啋涓�娆�
+     */
+    String METERING_EXPIRE_REMIND_OVERDUE = "mes:dv:metering:overdue:remind:";
+
 }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/dv/metering/MesDvMeteringRemindRedisDAO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/dv/metering/MesDvMeteringRemindRedisDAO.java
index a12e6f7..5424456 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/dv/metering/MesDvMeteringRemindRedisDAO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/dv/metering/MesDvMeteringRemindRedisDAO.java
@@ -41,6 +41,20 @@
     }
 
     /**
+     * 灏濊瘯鏍囪宸叉彁閱掞紙宸茶繃鏈熷満鏅紝60 澶╁唴鍙彁閱掍竴娆★級
+     *
+     * 浣跨敤鐙珛鐨� KEY锛屼笌 {@link #tryMarkReminded} 鐩镐簰闅旂锛屼繚璇佸櫒鍏疯繃鏈熷悗浠嶈兘鍗曠嫭鎻愰啋涓�娆�
+     *
+     * @param meteringId 璁¢噺鍣ㄥ叿缂栧彿
+     * @param nextCheckDate 鍒版湡鏃�
+     * @return true 琛ㄧず棣栨鏍囪鎴愬姛锛岄渶瑕佸彂閫佹彁閱�
+     */
+    public boolean tryMarkOverdueReminded(Long meteringId, LocalDate nextCheckDate) {
+        String key = RedisKeyConstants.METERING_EXPIRE_REMIND_OVERDUE + meteringId + ":" + nextCheckDate;
+        return Boolean.TRUE.equals(stringRedisTemplate.opsForValue().setIfAbsent(key, "1", REMIND_TIMEOUT));
+    }
+
+    /**
      * 灏濊瘯鑾峰彇褰撳ぉ鐨勬壂鎻忛棬闂╋紝閬垮厤澶氬疄渚嬪苟鍙戦噸澶嶆壂鎻�
      *
      * @param today 褰撳ぉ鏃ユ湡
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/metering/MesDvMeteringRemindServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/metering/MesDvMeteringRemindServiceImpl.java
index 2c8416c..90a0cb1 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/metering/MesDvMeteringRemindServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/metering/MesDvMeteringRemindServiceImpl.java
@@ -34,9 +34,13 @@
      */
     private static final int DEFAULT_REMIND_DAYS = 30;
     /**
-     * 鍒版湡鎻愰啋绔欏唴淇℃ā鏉跨紪鍙�
+     * 鍗冲皢鍒版湡鎻愰啋绔欏唴淇℃ā鏉跨紪鍙�
      */
     private static final String REMIND_TEMPLATE_CODE = "mes_metering_expire_remind";
+    /**
+     * 宸茶繃鏈熸彁閱掔珯鍐呬俊妯℃澘缂栧彿
+     */
+    private static final String OVERDUE_TEMPLATE_CODE = "mes_metering_expire_overdue";
 
     @Resource
     private MesDvMeteringMapper meteringMapper;
@@ -57,18 +61,28 @@
             }
             // 2. 璇诲彇鎻愰啋澶╂暟锛堥粯璁� 30锛�
             int remindDays = getRemindDays();
-            // 3. 鏌ヨ [today, today + remindDays] 鍒版湡鐨勫櫒鍏�
-            List<MesDvMeteringDO> list = meteringMapper.selectListByNextCheckDateBetween(
+            // 3. 鏌ヨ宸茶繃鏈燂紙鍒版湡鏃� < 浠婂ぉ锛変笌鍗冲皢鍒版湡锛堝埌鏈熸棩鍦� [today, today + remindDays]锛夌殑鍣ㄥ叿
+            List<MesDvMeteringDO> overdueList = meteringMapper.selectListByNextCheckDateBefore(today);
+            List<MesDvMeteringDO> dueList = meteringMapper.selectListByNextCheckDateBetween(
                     today, today.plusDays(remindDays));
-            // 4. 閫愬彴鍙戦�佺珯鍐呬俊锛堟寜鍣ㄥ叿 + 鍒版湡鏃ュ幓閲嶏級
-            for (MesDvMeteringDO metering : list) {
+            // 4. 閫愬彴鍙戦�佺珯鍐呬俊锛堟寜鍣ㄥ叿 + 鍒版湡鏃ュ幓閲嶏紝涓ょ被鐩镐簰鐙珛锛�
+            for (MesDvMeteringDO metering : overdueList) {
+                if (metering.getChargeUserId() == null || metering.getNextCheckDate() == null) {
+                    continue;
+                }
+                if (!meteringRemindRedisDAO.tryMarkOverdueReminded(metering.getId(), metering.getNextCheckDate())) {
+                    continue;
+                }
+                sendRemindMessage(metering, OVERDUE_TEMPLATE_CODE);
+            }
+            for (MesDvMeteringDO metering : dueList) {
                 if (metering.getChargeUserId() == null || metering.getNextCheckDate() == null) {
                     continue;
                 }
                 if (!meteringRemindRedisDAO.tryMarkReminded(metering.getId(), metering.getNextCheckDate())) {
                     continue;
                 }
-                sendRemindMessage(metering);
+                sendRemindMessage(metering, REMIND_TEMPLATE_CODE);
             }
         } catch (Exception ex) {
             // best-effort锛氭彁閱掑け璐ヤ笉褰卞搷鍒楄〃鏌ヨ
@@ -89,14 +103,14 @@
         }
     }
 
-    private void sendRemindMessage(MesDvMeteringDO metering) {
+    private void sendRemindMessage(MesDvMeteringDO metering, String templateCode) {
         Map<String, Object> params = new HashMap<>();
         params.put("meteringCode", metering.getCode());
         params.put("meteringName", metering.getName());
         params.put("nextCheckDate", metering.getNextCheckDate().toString());
         NotifySendSingleToUserReqDTO reqDTO = new NotifySendSingleToUserReqDTO()
                 .setUserId(metering.getChargeUserId())
-                .setTemplateCode(REMIND_TEMPLATE_CODE)
+                .setTemplateCode(templateCode)
                 .setTemplateParams(params);
         notifyMessageSendApi.sendSingleMessageToAdmin(reqDTO);
     }

--
Gitblit v1.9.3