Quellcode durchsuchen

aps-交期延期预警

sucheng vor 2 Monaten
Ursprung
Commit
3bd5ea6d07

+ 2 - 0
cx-aps/cx-aps-common/src/main/java/com/rongwei/bscommon/sys/dao/ApsProcessOperationProcessEquDao.java

@@ -164,6 +164,8 @@ public interface ApsProcessOperationProcessEquDao extends BaseMapper<ApsProcessO
     List<String> selectAllNeedDelIds();
 
     void myDeleteByIds(@Param("needDelIdList") List<String> needDelIdList);
+
+    List<TenantIdAndUserIdsVo> selectNeedPushMessageUsers();
 }
 
 

+ 115 - 17
cx-aps/cx-aps-common/src/main/java/com/rongwei/bscommon/sys/service/impl/ApsProcessOperationProcessEquServiceImpl.java

@@ -33,6 +33,7 @@ import com.rongwei.rwcommon.utils.StringUtils;
 import com.rongwei.rwcommon.vo.CriteriaQuery;
 import com.rongwei.rwcommon.vo.MailDo;
 import com.rongwei.safecommon.fegin.CXAdminFeginClient;
+import com.rongwei.safecommon.fegin.CXCommonFeginClient;
 import com.rongwei.safecommon.utils.CXCommonUtils;
 import com.rongwei.wfserver.wfcommon.sys.service.impl.ProcessServiceImpl;
 import lombok.extern.log4j.Log4j2;
@@ -46,6 +47,7 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.support.DefaultTransactionDefinition;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
@@ -124,6 +126,8 @@ public class ApsProcessOperationProcessEquServiceImpl extends ServiceImpl<ApsPro
     private ApsDeliveryOffsetService apsDeliveryOffsetService;
     @Autowired
     private ApsDeliveryOffsetDao apsDeliveryOffsetDao;
+    @Resource
+    private CXCommonFeginClient cxCommonFeginClient;
 
 //    /**
 //     * 更新工序的待加工批次号信息
@@ -3100,7 +3104,7 @@ public class ApsProcessOperationProcessEquServiceImpl extends ServiceImpl<ApsPro
             if (Arrays.asList("部分取消", "已完工").contains(productCardVo.getStatus())) {
                 ProductCardAndLatestScheduleEndDateVo latestScheduleEndDateVo = cardIdAndScheduleEndDateList3.stream().filter(item -> item.getCardId().equals(productCardVo.getId())).findFirst().orElse(null);
                 if (latestScheduleEndDateVo != null) {
-                    DateTime latestScheduleEndDate = latestScheduleEndDateVo.getLatestScheduleEndDate();
+                    Date latestScheduleEndDate = latestScheduleEndDateVo.getLatestScheduleEndDate();
                     apsDeliveryOffsetDo.setActualenddate(latestScheduleEndDate);
                 }
             } else {
@@ -3122,26 +3126,26 @@ public class ApsProcessOperationProcessEquServiceImpl extends ServiceImpl<ApsPro
             String[] split = productCardVo.getPromiseDate().split("~");
             DateTime promiseStartDate = DateUtil.parseDate(split[0] + " 00:00:00");
             DateTime promiseEndDate = DateUtil.parseDate(split[1] + " 23:59:59");
-            if (Arrays.asList("待开工", "加工中","部分取消", "已完工").contains(productCardVo.getStatus())) {
+            if (Arrays.asList("待开工", "加工中", "部分取消", "已完工").contains(productCardVo.getStatus())) {
                 DateTime endDate = null;
-                if (Arrays.asList("待开工", "加工中").contains(productCardVo.getStatus())){
-                    endDate = apsDeliveryOffsetDo.getPlanenddate();
-                }else {
-                    endDate = apsDeliveryOffsetDo.getActualenddate();
+                if (Arrays.asList("待开工", "加工中").contains(productCardVo.getStatus())) {
+                    endDate = DateTime.of(apsDeliveryOffsetDo.getPlanenddate());
+                } else {
+                    endDate = DateTime.of(apsDeliveryOffsetDo.getActualenddate());
                 }
                 if (endDate != null) {
                     //如果料卷计划完工时间的日期<坯料计划承诺交货期起,则=料卷计划完工时间的日期-坯料计划承诺交货期起
                     if (endDate.before(promiseStartDate)) {
-                        int offsetDay = (int)DateUtil.between(promiseStartDate, endDate, DateUnit.DAY, false);
+                        int offsetDay = (int) DateUtil.between(promiseStartDate, endDate, DateUnit.DAY, false);
                         apsDeliveryOffsetDo.setDeliveryoffset(offsetDay);
                         // 如果料卷计划完工时间的日期>坯料计划承诺交货期止,则=料卷计划完工时间的日期-坯料计划承诺交货期止
                     } else if (endDate.after(promiseEndDate)) {
-                        int offsetDay = (int)DateUtil.between(promiseEndDate, endDate, DateUnit.DAY, false);
+                        int offsetDay = (int) DateUtil.between(promiseEndDate, endDate, DateUnit.DAY, false);
                         apsDeliveryOffsetDo.setDeliveryoffset(offsetDay);
                     } else {
                         apsDeliveryOffsetDo.setDeliveryoffset(null);
                     }
-                }else {
+                } else {
                     apsDeliveryOffsetDo.setDeliveryoffset(null);
                 }
             } else {
@@ -3152,28 +3156,122 @@ public class ApsProcessOperationProcessEquServiceImpl extends ServiceImpl<ApsPro
 
 
         if (!apsProcessOperationProcessEquDos.isEmpty()) {
-            apsProcessOperationProcessEquService.updateBatchById(apsProcessOperationProcessEquDos);
+            for (ApsProcessOperationProcessEquDo apsProcessOperationProcessEquDo : apsProcessOperationProcessEquDos) {
+                apsProcessOperationProcessEquService.update(new LambdaUpdateWrapper<ApsProcessOperationProcessEquDo>()
+                        .set(ApsProcessOperationProcessEquDo::getTimeoffset, apsProcessOperationProcessEquDo.getTimeoffset())
+                        .eq(ApsProcessOperationProcessEquDo::getId, apsProcessOperationProcessEquDo.getId()));
+            }
         }
         if (!needUpdateOrInsertList.isEmpty()) {
             apsDeliveryOffsetService.saveOrUpdateBatch(needUpdateOrInsertList);
         }
         //反查需要删除的数据
         List<String> needDelIdList = this.baseMapper.selectAllNeedDelIds();
-        if (!needDelIdList.isEmpty()){
+        if (!needDelIdList.isEmpty()) {
             this.baseMapper.myDeleteByIds(needDelIdList);
         }
         if (req.getNeedSendMessage()) {
-            //过滤需要发送消息的数据
-            List<ApsDeliveryOffsetDo> needSendMessageList = needUpdateOrInsertList.stream().filter(item -> Arrays.asList("待开工", "加工中").contains(item.getStatus()) && item.getDeliveryoffset() > 0).collect(Collectors.toList());
-            if (!needSendMessageList.isEmpty()){
-                for (ApsDeliveryOffsetDo apsDeliveryOffsetDo : needSendMessageList) {
-                    ProductCardVo productCardVo = list.stream().filter(item -> item.getId().equals(apsDeliveryOffsetDo.getId())).findFirst().orElse(null);
+            //发送消息和邮件
+            sendMessageAndEmail(needUpdateOrInsertList, list);
+        }
+        return R.ok();
+    }
 
+    private void sendMessageAndEmail(List<ApsDeliveryOffsetDo> needUpdateOrInsertList, List<ProductCardVo> list) {
+        //过滤需要发送消息的数据
+        List<ApsDeliveryOffsetDo> needSendMessageList = needUpdateOrInsertList.stream().filter(item ->
+                Arrays.asList("待开工", "加工中").contains(item.getStatus())
+                        && item.getDeliveryoffset() != null
+                        && item.getDeliveryoffset() > 0).collect(Collectors.toList());
+        if (!needSendMessageList.isEmpty()) {
+            //查询每个工厂的 生产计划主任(role071)、车间调度组长(cjddzz)
+            List<TenantIdAndUserIdsVo> tenantIdAndUserIdsVoList = this.baseMapper.selectNeedPushMessageUsers();
+            Map<String, List<String>> tenantIdAndUserIdListMap = new HashMap<>();
+            Map<String, String> tenantIdAndEmailsListMap = new HashMap<>();
+            for (TenantIdAndUserIdsVo tenantIdAndUserIdsVo : tenantIdAndUserIdsVoList) {
+                List<String> userList = new LinkedList<>();
+                if (StringUtils.isNotBlank(tenantIdAndUserIdsVo.getUserIds())) {
+                    userList = new LinkedList<>(Arrays.asList(tenantIdAndUserIdsVo.getUserIds().split(",")));
+                }
+                tenantIdAndUserIdListMap.putIfAbsent(tenantIdAndUserIdsVo.getTenantId(), userList);
+                tenantIdAndEmailsListMap.putIfAbsent(tenantIdAndUserIdsVo.getTenantId(), tenantIdAndUserIdsVo.getEmails());
+            }
+            //<工厂ID,<订单号,批次号集合>>
+            Map<String, Map<String, List<String>>> resMap = new HashMap<>();
+            for (ApsDeliveryOffsetDo apsDeliveryOffsetDo : needSendMessageList) {
+                ProductCardVo productCardVo = list.stream().filter(item -> item.getId().equals(apsDeliveryOffsetDo.getId())).findFirst().orElse(null);
+                if (productCardVo == null) {
+                    continue;
+                }
+                //订单号 优先使用客户订单号
+                String orderNo = productCardVo.getCustomOrderNo();
+                if (StringUtils.isBlank(orderNo)) {
+                    orderNo = productCardVo.getOrderNo();
+                    if (StringUtils.isBlank(orderNo)) {
+                        continue;
+                    }
+                }
+                //批次号
+                String blankBatchNumber = productCardVo.getBlankBatchNumber();
+                if (StringUtils.isBlank(blankBatchNumber)) {
+                    continue;
+                }
+                String tenantId = productCardVo.getTenantId();
+                if (resMap.containsKey(tenantId)) {
+                    Map<String, List<String>> orderMap = resMap.get(tenantId);
+                    if (orderMap.containsKey(orderNo)) {
+                        List<String> blankNumberList = orderMap.get(orderNo);
+                        blankNumberList.add(blankBatchNumber);
+                    } else {
+                        orderMap.put(orderNo, new LinkedList<>(Collections.singletonList(blankBatchNumber)));
+                    }
+                } else {
+                    Map<String, List<String>> orderMap = new HashMap<>();
+                    orderMap.put(orderNo, new LinkedList<>(Collections.singletonList(blankBatchNumber)));
+                    resMap.put(tenantId, orderMap);
                 }
             }
+            //按照工厂发送消息
+            for (String key : resMap.keySet()) {
+                Map<String, List<String>> orderMap = resMap.get(key);
+                List<String> messageList = new LinkedList<>();
+                for (String orderNo : orderMap.keySet()) {
+                    List<String> numberList = orderMap.get(orderNo);
+                    String message = "订单号:【" + orderNo + "】,料卷批次号:【" + String.join(",", numberList) + "】";
+                    messageList.add(message);
+                }
+                if (messageList.isEmpty()) {
+                    continue;
+                }
+                //获取此工厂需要发送通知的人的ID
+                List<String> userIdList = tenantIdAndUserIdListMap.getOrDefault(key, null);
+                if (userIdList.isEmpty()) {
+                    continue;
+                }
+                //系统通知(移动端和PC端个人工作台)
+                CXCommonUtils.sendNotify("料卷延期",
+                        "以下料卷预计延期,请及时调整计划:\r\n" + String.join("\r\n", messageList),
+                        null,
+                        userIdList,
+                        null,
+                        PROCESSDELAY_REMIND,
+                        false);
 
+                //获取需要邮件的邮箱
+                String emails = tenantIdAndEmailsListMap.getOrDefault(key, null);
+                if (StringUtils.isBlank(emails)) {
+                    continue;
+                }
+                //邮件提醒
+                MailDo mailDo = new MailDo();
+                mailDo.setReceiveEmail(emails.split(","));
+                mailDo.setNeedTransReceive(false);
+                mailDo.setCcEmail(new String[]{});
+                mailDo.setSubject("料卷延期");
+                mailDo.setContent("以下料卷预计延期,请及时调整计划:<br>" + String.join("<br>", messageList));
+                cxCommonFeginClient.sendHtmlMail(mailDo);
+            }
         }
-        return R.ok();
     }
 }
 

+ 16 - 2
cx-aps/cx-aps-common/src/main/resources/mybatis/ApsProcessOperationProcessEquDao.xml

@@ -823,7 +823,7 @@
         group by
         apope.ROOTTASKID
         ) a LEFT JOIN aps_delivery_offset ado ON a.ID = ado.ID AND ado.DELETED = 0
-        where ado.ID is null or (a.`STATUS` = ado.`STATUS` and a.`STATUS` = '已完工')
+        where ado.ID is null or (a.`STATUS` = ado.`STATUS` and a.`STATUS` != '已完工')
     </select>
     <select id="selectAllLatestEndDateByCarIds"
             resultType="com.rongwei.bsentity.vo.ProductCardAndLatestScheduleEndDateVo">
@@ -883,7 +883,7 @@
     <select id="selectAllNeedDelIds" resultType="java.lang.String">
         select ado.ID from (select
         apope.ROOTTASKID as id,
-        max(abo.TENANTID) as tenantid,
+        max(abo.TENANTID) as tenantId,
         max(abo.CUSTOMORDERNO) as customOrderNo,
         max(abo.ORDERNO) as orderNo,
         max(abo.CUSTOMNAME) as customName,
@@ -946,4 +946,18 @@
         ) a RIGHT JOIN aps_delivery_offset ado ON a.ID = ado.ID AND ado.DELETED = 0
         where a.ID is null
     </select>
+    <select id="selectNeedPushMessageUsers" resultType="com.rongwei.bsentity.vo.TenantIdAndUserIdsVo">
+        SELECT
+            su.TENANTID AS 'tenantId',
+            GROUP_CONCAT(DISTINCT su.ID) AS 'userIds',
+            GROUP_CONCAT(DISTINCT IF(su.EMAIL = '',null,su.EMAIL)) AS 'emails'
+        FROM
+            sys_user su
+                LEFT JOIN sys_user_role sur ON su.ID = sur.USERID
+                AND sur.DELETED = 0
+        WHERE
+            su.DELETED = 0
+          AND sur.ROLEID IN (select ID from sys_role where `CODE` IN ('role071','cjddzz'))
+        GROUP BY su.TENANTID
+    </select>
 </mapper>

+ 3 - 3
cx-aps/cx-aps-entity/src/main/java/com/rongwei/bsentity/domain/ApsDeliveryOffsetDo.java

@@ -46,19 +46,19 @@ public class ApsDeliveryOffsetDo extends BaseDo {
      * 料卷计划完工时间
      */
     @TableField(value = "PLANENDDATE")
-    private DateTime planenddate;
+    private Date planenddate;
 
     /**
      * 料卷预计完工时间
      */
     @TableField(value = "GUESSENDDATE",updateStrategy = FieldStrategy.IGNORED)
-    private DateTime guessenddate;
+    private Date guessenddate;
 
     /**
      * 料卷实际完工时间
      */
     @TableField(value = "ACTUALENDDATE",updateStrategy = FieldStrategy.IGNORED)
-    private DateTime actualenddate;
+    private Date actualenddate;
 
     /**
      * 卡片状态

+ 3 - 1
cx-aps/cx-aps-entity/src/main/java/com/rongwei/bsentity/vo/ProductCardAndLatestScheduleEndDateVo.java

@@ -3,6 +3,8 @@ package com.rongwei.bsentity.vo;
 import cn.hutool.core.date.DateTime;
 import lombok.Data;
 
+import java.util.Date;
+
 /**
  * @author :sc
  * @since :2025/5/22
@@ -10,5 +12,5 @@ import lombok.Data;
 @Data
 public class ProductCardAndLatestScheduleEndDateVo {
     private String cardId;
-    private DateTime latestScheduleEndDate;
+    private Date latestScheduleEndDate;
 }

+ 1 - 0
cx-aps/cx-aps-entity/src/main/java/com/rongwei/bsentity/vo/ProductCardVo.java

@@ -12,6 +12,7 @@ import java.util.Date;
 @Data
 public class ProductCardVo extends BaseDo {
     private String id;
+    private String tenantId;
     private String customOrderNo;
     private String orderNo;
     private String customName;

+ 14 - 0
cx-aps/cx-aps-entity/src/main/java/com/rongwei/bsentity/vo/TenantIdAndUserIdsVo.java

@@ -0,0 +1,14 @@
+package com.rongwei.bsentity.vo;
+
+import lombok.Data;
+
+/**
+ * @author :sc
+ * @since :2025/5/23
+ */
+@Data
+public class TenantIdAndUserIdsVo {
+    private String tenantId;
+    private String userIds;
+    private String emails;
+}

+ 11 - 1
cx-aps/cx-aps-server/src/main/java/com/rongwei/bsserver/controller/ApsProcessOperationProcessEquController.java

@@ -174,8 +174,18 @@ public class ApsProcessOperationProcessEquController {
      * 作业延期提醒
      */
     @PostMapping("workDeliveryOffset")
-    @Scheduled(cron = "0 0 23 * * *")
     public R workDeliveryOffset(@RequestBody WorkDeliveryOffsetReq req) {
+        log.info("手动调用作业延期提醒,入参:{}",req);
+        return apsProcessOperationProcessEquService.workDeliveryOffset(req);
+    }
+
+    /**
+     * 作业延期提醒定时任务
+     */
+    @Scheduled(cron = "0 0 23 * * *")
+    public R workDeliveryOffset() {
+        log.info("定时任务调用作业延期提醒");
+        WorkDeliveryOffsetReq req = new WorkDeliveryOffsetReq();
         return apsProcessOperationProcessEquService.workDeliveryOffset(req);
     }
 }