|
|
@@ -233,11 +233,11 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
|
|
|
}
|
|
|
if (!customerIdSet.isEmpty()) {
|
|
|
try {
|
|
|
- java.util.List<com.storlead.trade.entity.CustomerEntity> customers =
|
|
|
+ java.util.List<CustomerEntity> customers =
|
|
|
customerTradeService.listByIds(new java.util.ArrayList<>(customerIdSet));
|
|
|
if (!CollectionUtils.isEmpty(customers)) {
|
|
|
java.util.Map<Long, String> idToName = new java.util.HashMap<>(customers.size());
|
|
|
- for (com.storlead.trade.entity.CustomerEntity c : customers) {
|
|
|
+ for (CustomerEntity c : customers) {
|
|
|
if (c.getId() != null) {
|
|
|
idToName.put(c.getId(), c.getCustomerName());
|
|
|
}
|
|
|
@@ -353,6 +353,136 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
|
|
|
return Result.ok();
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 回复邮件的客户列表(按 marketingCampaignId 过滤 + hasReply=1 + recipient 聚合)
|
|
|
+ * 不分页:全部/已保护/营销暂停 三个 Tab 由前端在结果中过滤计数。
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Result<Object> getReplyList(Long marketingCampaignId) {
|
|
|
+ if (ObjectUtils.isEmpty(marketingCampaignId)) {
|
|
|
+ return Result.error("marketingCampaignId不能为空");
|
|
|
+ }
|
|
|
+ // 查该营销活动下 has_reply=1 且未软删的邮件
|
|
|
+ LambdaQueryWrapper<MarketEmailsEntity> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ wrapper.eq(MarketEmailsEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
|
|
|
+ wrapper.eq(MarketEmailsEntity::getHasReply, 1);
|
|
|
+ wrapper.eq(MarketEmailsEntity::getMarketingCampaignId, marketingCampaignId);
|
|
|
+ wrapper.isNotNull(MarketEmailsEntity::getRecipient);
|
|
|
+ wrapper.ne(MarketEmailsEntity::getRecipient, "");
|
|
|
+ wrapper.select(MarketEmailsEntity::getRecipient,
|
|
|
+ MarketEmailsEntity::getCustomerId,
|
|
|
+ MarketEmailsEntity::getHasProtect,
|
|
|
+ MarketEmailsEntity::getHasSuspend,
|
|
|
+ MarketEmailsEntity::getFirstReplyTime,
|
|
|
+ MarketEmailsEntity::getFirstReplyEmailId,
|
|
|
+ MarketEmailsEntity::getFirstReplyTheme,
|
|
|
+ MarketEmailsEntity::getCreateTime);
|
|
|
+ List<MarketEmailsEntity> all = this.list(wrapper);
|
|
|
+
|
|
|
+ // 按 recipient 聚合
|
|
|
+ Map<String, com.storlead.trade.vo.MarketEmailsReplyVO> aggMap = new HashMap<>();
|
|
|
+ if (!CollectionUtils.isEmpty(all)) {
|
|
|
+ for (MarketEmailsEntity e : all) {
|
|
|
+ String r = e.getRecipient();
|
|
|
+ if (r == null || r.isEmpty()) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ com.storlead.trade.vo.MarketEmailsReplyVO vo = aggMap.computeIfAbsent(r, k -> {
|
|
|
+ com.storlead.trade.vo.MarketEmailsReplyVO v = new com.storlead.trade.vo.MarketEmailsReplyVO();
|
|
|
+ v.setRecipient(k);
|
|
|
+ v.setReplyCount(0L);
|
|
|
+ return v;
|
|
|
+ });
|
|
|
+ vo.setReplyCount(vo.getReplyCount() + 1);
|
|
|
+ // 记下最早一条所属的 customerId(用于回填客户名)
|
|
|
+ if (vo.getCustomerId() == null && e.getCustomerId() != null) {
|
|
|
+ vo.setCustomerId(e.getCustomerId());
|
|
|
+ }
|
|
|
+ // 取最早的 firstReplyTime + 同时记录主题/emailId
|
|
|
+ if (e.getFirstReplyTime() != null) {
|
|
|
+ if (vo.getFirstReplyTime() == null || e.getFirstReplyTime().before(vo.getFirstReplyTime())) {
|
|
|
+ vo.setFirstReplyTime(e.getFirstReplyTime());
|
|
|
+ vo.setReplyContent(e.getFirstReplyTheme());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // MAX(has_protect) / MAX(has_suspend) 语义
|
|
|
+ if (e.getHasProtect() != null && e.getHasProtect() == 1) {
|
|
|
+ vo.setHasProtect(1);
|
|
|
+ }
|
|
|
+ if (e.getHasSuspend() != null && e.getHasSuspend() == 1) {
|
|
|
+ vo.setHasSuspend(1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 默认未保护/未暂停为 0
|
|
|
+ for (com.storlead.trade.vo.MarketEmailsReplyVO vo : aggMap.values()) {
|
|
|
+ if (vo.getHasProtect() == null) vo.setHasProtect(0);
|
|
|
+ if (vo.getHasSuspend() == null) vo.setHasSuspend(0);
|
|
|
+ }
|
|
|
+ // 按首次回复时间倒序(最近回复的排前)
|
|
|
+ List<com.storlead.trade.vo.MarketEmailsReplyVO> voList = new java.util.ArrayList<>(aggMap.values());
|
|
|
+ voList.sort((a, b) -> {
|
|
|
+ if (a.getFirstReplyTime() == null && b.getFirstReplyTime() == null) return 0;
|
|
|
+ if (a.getFirstReplyTime() == null) return 1;
|
|
|
+ if (b.getFirstReplyTime() == null) return -1;
|
|
|
+ return b.getFirstReplyTime().compareTo(a.getFirstReplyTime());
|
|
|
+ });
|
|
|
+
|
|
|
+ // 批量回填:客户名 / 客户等级 / 核心标签
|
|
|
+ if (!voList.isEmpty()) {
|
|
|
+ java.util.Set<Long> customerIdSet = new java.util.LinkedHashSet<>();
|
|
|
+ for (com.storlead.trade.vo.MarketEmailsReplyVO v : voList) {
|
|
|
+ if (v.getCustomerId() != null) customerIdSet.add(v.getCustomerId());
|
|
|
+ }
|
|
|
+ if (!customerIdSet.isEmpty()) {
|
|
|
+ try {
|
|
|
+ // 回填客户名
|
|
|
+ java.util.List<CustomerEntity> customers =
|
|
|
+ customerTradeService.listByIds(new java.util.ArrayList<>(customerIdSet));
|
|
|
+ java.util.Map<Long, CustomerEntity> customerMap = new java.util.HashMap<>();
|
|
|
+ if (!CollectionUtils.isEmpty(customers)) {
|
|
|
+ for (CustomerEntity c : customers) {
|
|
|
+ if (c.getId() != null) customerMap.put(c.getId(), c);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 回填客户等级 / 核心标签(从 CustomerAnalysisResultEntity)
|
|
|
+ // 一个 customer 可能有多个分析结果,取最新一条(id 最大)
|
|
|
+ java.util.List<CustomerAnalysisResultEntity> analysisList =
|
|
|
+ customerAnalysisResultEntityService.list(
|
|
|
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<CustomerAnalysisResultEntity>()
|
|
|
+ .in(CustomerAnalysisResultEntity::getCustomerId, customerIdSet)
|
|
|
+ .eq(CustomerAnalysisResultEntity::getIsDelete, CommonConstant.DEL_FLAG_0)
|
|
|
+ .orderByDesc(CustomerAnalysisResultEntity::getId));
|
|
|
+ java.util.Map<Long, CustomerAnalysisResultEntity> analysisMap = new java.util.HashMap<>();
|
|
|
+ if (!CollectionUtils.isEmpty(analysisList)) {
|
|
|
+ for (CustomerAnalysisResultEntity a : analysisList) {
|
|
|
+ if (a.getCustomerId() != null && !analysisMap.containsKey(a.getCustomerId())) {
|
|
|
+ analysisMap.put(a.getCustomerId(), a);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (com.storlead.trade.vo.MarketEmailsReplyVO v : voList) {
|
|
|
+ CustomerEntity c = customerMap.get(v.getCustomerId());
|
|
|
+ if (c != null) {
|
|
|
+ v.setCustomerName(c.getCustomerName());
|
|
|
+ }
|
|
|
+ CustomerAnalysisResultEntity a = analysisMap.get(v.getCustomerId());
|
|
|
+ if (a != null) {
|
|
|
+ v.setCustomerLevel(a.getCustomerLevel());
|
|
|
+ v.setCoreTags(a.getCoreTags());
|
|
|
+ if (a.getCustomerLevel() != null) {
|
|
|
+ v.setCustomerLevelLabel(a.getCustomerLevel());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception ex) {
|
|
|
+ log.warn("回填客户名/标签失败,customerIds={} err={}", customerIdSet, ex.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return Result.ok(voList);
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
@Override
|
|
|
public Result<Object> getManagementDetail(Long marketingCampaignId) {
|