瀏覽代碼

修改邮件定时任务

YPZ 18 小時之前
父節點
當前提交
6c5b616381

+ 3 - 0
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/MarketEmailsService.java

@@ -150,4 +150,7 @@ public interface MarketEmailsService extends MyBaseService<MarketEmailsEntity> {
      * @return 被置为已取消的邮件条数
      */
     int cancelOverduePending();
+
+    @Async
+    void updateEmailContent(MarketEmailsEntity marketEmailsEntity);
 }

+ 67 - 6
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/MarketEmailsServiceImpl.java

@@ -97,10 +97,13 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
     @Resource
     private LiaisonTradeService liaisonTradeService;
 
-    @Autowired
+    @Resource
     @Lazy
     private RedissonClient redissonClient;
 
+    @Resource
+    private CustomerAnalysisResultEntityService customerAnalysisResultService;
+
 
     @Override
     public Result<Object> getList(MarketEmailsDTO dto) {
@@ -533,6 +536,44 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
         return rows;
     }
 
+    @Override
+    public void updateEmailContent(MarketEmailsEntity marketEmailsEntity) {
+        //通过客户id获取客户分析结果
+        CustomerAnalysisResultEntity customerAnalysisResult = new CustomerAnalysisResultEntity();
+        LambdaQueryWrapper<CustomerAnalysisResultEntity> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(CustomerAnalysisResultEntity::getCustomerId, marketEmailsEntity.getCustomerId());
+        queryWrapper.last("limit 1");
+        customerAnalysisResult = customerAnalysisResultService.getOne(queryWrapper);
+        String reasonSummary = "";
+        if (customerAnalysisResult != null){
+            reasonSummary = customerAnalysisResult.getReasonSummary();
+        }
+        Map sendMap = new HashMap();
+        sendMap.put("email", marketEmailsEntity.getContent());
+        sendMap.put("reason_summary", reasonSummary);
+
+        ChatDTO chatDTO = new ChatDTO();
+        chatDTO.setInputs(sendMap);
+//            chatDTO.setQuery("send_time");
+        chatDTO.setResponseMode("blocking");
+        chatDTO.setAppId("app-CVPtLUPO0zd2SeGPvZv3Q4Ev");
+        chatDTO.setUser("1");
+
+        // 调取 AI  获取新的content
+        Result<Object> r = workflowsService.AiWorkflows(chatDTO);
+        if (r == null) {
+            log.warn("无内容生成");
+            return;
+        }
+        // 从结构化结果里取出 AI 真正输出的 text 字段(多个结束节点拼接)。
+        // 不再做 inner.toString() 兜底——整串 Result 里有 files=[]/inputs=[] 等空数组
+        // 会被误当成 AI 输出的 JSON 数组(如 [models]),污染解析。
+        String text = extractCleanText(r.getResult());
+        marketEmailsEntity.setContent(text);
+
+        this.updateById(marketEmailsEntity);
+    }
+
     /**
      * 回复邮件的客户列表(按 marketingCampaignId 过滤 + hasReply=1 + recipient 聚合)
      * 不分页:全部/已保护/营销暂停 三个 Tab 由前端在结果中过滤计数。
@@ -1310,9 +1351,11 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
         queryStopWrapper.eq(MarketEmailsEntity::getHasReply, 1);
         queryStopWrapper.eq(MarketEmailsEntity::getHasReader, 1);
         List<MarketEmailsEntity> marketEmailsStopList = this.list(queryStopWrapper);
-        List<Long> customerIdList = new ArrayList<>();
+        List<Long> customerIdList;
         if (!CollectionUtils.isEmpty(marketEmailsStopList)){
             customerIdList = marketEmailsStopList.stream().map(MarketEmailsEntity::getCustomerId).collect(Collectors.toList());
+        } else {
+            customerIdList = new ArrayList<>();
         }
 
 
@@ -1326,16 +1369,34 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
         queryWrapper.between(MarketEmailsEntity::getExpectSendTime, start, end);
 
         queryWrapper.eq(MarketEmailsEntity::getStatus, -1);
-        queryWrapper.notIn(!CollectionUtils.isEmpty(customerIdList), MarketEmailsEntity::getCustomerId, customerIdList);
+//        queryWrapper.notIn(!CollectionUtils.isEmpty(customerIdList), MarketEmailsEntity::getCustomerId, customerIdList);
         queryWrapper.eq(MarketEmailsEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
-        queryWrapper.eq(MarketEmailsEntity::getHasProtect,0);
-        queryWrapper.eq(MarketEmailsEntity::getHasSuspend,0);
+//        queryWrapper.eq(MarketEmailsEntity::getHasProtect,0);
+//        queryWrapper.eq(MarketEmailsEntity::getHasSuspend,0);
         queryWrapper.in(MarketEmailsEntity::getMarketingCampaignId, marketingCampaignIdList);
-        List<MarketEmailsEntity> marketEmailList = this.list(queryWrapper);
+        List<MarketEmailsEntity> marketEmailFirstList = this.list(queryWrapper);
 
+        if (CollectionUtils.isEmpty(marketEmailFirstList)){
+            return;
+        }
+        List<MarketEmailsEntity> marketEmailList = marketEmailFirstList;
+                //获取客户id在customerIdList或者已开启保护或者已暂停的marketEmailList
+                List<MarketEmailsEntity> marketEmailNotList = marketEmailFirstList.stream()
+                        .filter(marketEmail -> customerIdList.contains(marketEmail.getCustomerId()) ||
+                                marketEmail.getHasProtect() == 1 ||
+                                marketEmail.getHasSuspend() == 1)
+                        .collect(Collectors.toList());
+        if (!CollectionUtils.isEmpty(marketEmailNotList)) {
+            for (MarketEmailsEntity marketEmail : marketEmailNotList) {
+                marketEmail.setStatus(-3);
+            }
+            this.updateBatchById(marketEmailNotList);
+            marketEmailList.removeAll(marketEmailNotList);
+        }
         if (CollectionUtils.isEmpty(marketEmailList)){
             return;
         }
+
         log.info("queryWrapper: {}", queryWrapper);
         log.info("marketEmailList: {}", marketEmailList);
         for (MarketEmailsEntity marketEmail : marketEmailList){

+ 49 - 15
java/storlead-sasa/storlead-trade/src/main/java/com/storlead/trade/service/impl/MarketingCampaignSopDetailServiceImpl.java

@@ -4,6 +4,7 @@ import com.baomidou.dynamic.datasource.annotation.DS;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.storlead.framework.common.constant.CommonConstant;
 import com.storlead.framework.common.constant.DSConstants;
 import com.storlead.framework.common.result.Result;
 import com.storlead.mail.pojo.entity.MktMailMessageEntity;
@@ -17,12 +18,14 @@ import com.storlead.trade.service.*;
 import com.storlead.trade.service.impl.support.TradeDataSourceServiceImpl;
 import com.storlead.trade.vo.CustomerVO;
 import org.springframework.beans.BeanUtils;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.ObjectUtils;
 
 import javax.annotation.Resource;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
@@ -43,6 +46,9 @@ public class MarketingCampaignSopDetailServiceImpl
     private MktMailMessageService mktMailMessageService;
     @Resource
     private SysDictService sysDictService;
+    @Resource
+    @Lazy
+    private MarketingCampaignService marketingCampaignService;
 
 
     @Override
@@ -62,6 +68,21 @@ public class MarketingCampaignSopDetailServiceImpl
             return Result.error("存在已发送的邮件,不能进行修改");
         }
 
+        // 要更新邮件内容时,先确认该步骤下确实有邮件可写。
+        // 放在 updateById 之前:否则步骤已改、内容却没写进去,前后端数据就对不上了。
+        List<MarketEmailsEntity> pendingEmailList = Collections.emptyList();
+        if (!ObjectUtils.isEmpty(dto.getEmailContent())) {
+            LambdaQueryWrapper<MarketEmailsEntity> pendingWrapper = new LambdaQueryWrapper<>();
+            pendingWrapper.eq(MarketEmailsEntity::getMarketingCampaignSopDetailId, dto.getId());
+            pendingWrapper.eq(MarketEmailsEntity::getMarketingCampaignId, dto.getMarketingCampaignId());
+            pendingWrapper.eq(MarketEmailsEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
+            pendingEmailList = marketEmailsService.list(pendingWrapper);
+            if (CollectionUtils.isEmpty(pendingEmailList)) {
+                MarketingCampaignEntity marketingCampaignEntity = marketingCampaignService.getById(dto.getMarketingCampaignId());
+                marketEmailsService.addSendTime(marketingCampaignEntity);
+                return Result.error("邮件还未生成或生成失败,请稍后重试");
+            }
+        }
 
         MarketingCampaignSopDetailEntity entity = new MarketingCampaignSopDetailEntity();
         BeanUtils.copyProperties(dto, entity);
@@ -69,22 +90,28 @@ public class MarketingCampaignSopDetailServiceImpl
         if (!isOk) {
             return Result.error("修改失败");
         }
-        if (!ObjectUtils.isEmpty(dto.getEmailContent())){
+        if (!ObjectUtils.isEmpty(dto.getEmailContent())) {
             //写入每个客户的邮件内容
-            this.updateEmailContent(dto.getId(),dto.getEmailSubject(), dto.getEmailContent(), dto.getMarketingCampaignId());
+            Result<?> writeResult = this.updateEmailContent(pendingEmailList, dto.getEmailSubject(), dto.getEmailContent());
+            if (writeResult != null) {
+                return writeResult;
+            }
         }
         return Result.result(entity);
     }
 
-    private void updateEmailContent(Long id, String emailSubject, String emailContent, Long marketingCampaignId) {
-        //查询营销活动关联的所有客户
-//        MarketingCampaignSopDetailEntity entity = this.getById(id);
-        LambdaQueryWrapper<MarketEmailsEntity> marketEmailsEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
-        marketEmailsEntityLambdaQueryWrapper.eq(MarketEmailsEntity::getMarketingCampaignSopDetailId, id);
-        marketEmailsEntityLambdaQueryWrapper.eq(MarketEmailsEntity::getMarketingCampaignId, marketingCampaignId);
-        marketEmailsEntityLambdaQueryWrapper.eq(MarketEmailsEntity::getIsDelete, 0);
-        List<MarketEmailsEntity> marketEmailsEntityList = marketEmailsService.list(marketEmailsEntityLambdaQueryWrapper);
-
+    /**
+     * 把邮件模板内容写入该步骤下的每封邮件(含 ${变量}$ 占位符替换)。
+     * <p>
+     * 注意:这里<strong>不抛异常</strong>。抛 RuntimeException 会走全局异常处理器,
+     * 返回的是 code=900000 的兜底结构、HTTP 状态码也可能不是 200,前端拦截器往往识别不了,
+     * 表现为「接口一直卡着没有任何返回」。业务性失败统一返回 {@link Result},由上层直接透传。
+     *
+     * @param marketEmailsEntityList 该步骤下待写入的邮件(调用方已保证非空)
+     * @return null 表示成功;非 null 为失败原因,由上层直接透传给前端
+     */
+    private Result<?> updateEmailContent(List<MarketEmailsEntity> marketEmailsEntityList,
+                                         String emailSubject, String emailContent) {
         List<Long> customerIdList = marketEmailsEntityList.stream().map(MarketEmailsEntity::getCustomerId).collect(Collectors.toList());
         CustomerDTO dto = new CustomerDTO();
         dto.setIdList(customerIdList);
@@ -92,7 +119,7 @@ public class MarketingCampaignSopDetailServiceImpl
         dto.setPageSize(customerIdList.size());
         IPage<CustomerVO> customerPageList = customerService.getList(dto);
         if (customerPageList == null || customerPageList.getRecords() == null || customerPageList.getRecords().size() == 0) {
-            return;
+            return Result.error("未查询到关联的客户,邮件内容写入失败");
         }
         List<CustomerVO> customerVOList = customerPageList.getRecords();
 
@@ -168,13 +195,20 @@ public class MarketingCampaignSopDetailServiceImpl
 //            }
 
         }
-        boolean isOk = marketEmailsService.updateBatchById(marketEmailsEntityList);
-        if (!isOk) {
-            return;
+        for (MarketEmailsEntity marketEmailsEntity : marketEmailsEntityList){
+            //异步修改邮件内容并写入
+
+            marketEmailsService.updateEmailContent(marketEmailsEntity);
+
+
         }
+//        if (!isOk) {
+//            return Result.error("邮件内容写入失败");
+//        }
 
         //异步写入邮件发送时间及内容
 //        this.insertMailMessage(marketEmailsEntityList,customerEntityMap);
+        return null;
     }
 
     @Async