|
|
@@ -21,6 +21,7 @@ import com.storlead.trade.entity.*;
|
|
|
import com.storlead.trade.mapper.MarketEmailsMapper;
|
|
|
import com.storlead.trade.service.*;
|
|
|
import com.storlead.trade.vo.MarketEmailsCustomerVO;
|
|
|
+import com.storlead.trade.vo.MarketEmailsManagementVO;
|
|
|
import com.storlead.trade.vo.MarketEmailsOpenVO;
|
|
|
import com.storlead.trade.vo.ScheduleStageVO;
|
|
|
import org.slf4j.Logger;
|
|
|
@@ -64,6 +65,10 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
|
|
|
@Resource
|
|
|
private WorkflowsService workflowsService;
|
|
|
|
|
|
+ @Resource
|
|
|
+ @org.springframework.context.annotation.Lazy
|
|
|
+ private MarketingCampaignService marketingCampaignService;
|
|
|
+
|
|
|
|
|
|
@Override
|
|
|
public Result<Object> getList(MarketEmailsDTO dto) {
|
|
|
@@ -228,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());
|
|
|
}
|
|
|
@@ -271,6 +276,14 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
|
|
|
wrapper.in(MarketEmailsEntity::getId, ids);
|
|
|
wrapper.eq(MarketEmailsEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
|
|
|
wrapper.set(MarketEmailsEntity::getHasProtect, dto.getHasProtect());
|
|
|
+ // 如果是开启保护 且 前端传了保护原因 -> 一并写入
|
|
|
+ if (Integer.valueOf(1).equals(dto.getHasProtect()) && !ObjectUtils.isEmpty(dto.getProtectReason())) {
|
|
|
+ wrapper.set(MarketEmailsEntity::getProtectReason, dto.getProtectReason());
|
|
|
+ }
|
|
|
+ // 如果是移除保护 -> 清空保护原因
|
|
|
+ if (Integer.valueOf(0).equals(dto.getHasProtect())) {
|
|
|
+ wrapper.set(MarketEmailsEntity::getProtectReason, null);
|
|
|
+ }
|
|
|
boolean ok = this.update(wrapper);
|
|
|
if (!ok) {
|
|
|
return Result.error("保护失败");
|
|
|
@@ -315,6 +328,372 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
|
|
|
return Result.ok();
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 取消发送邮件:status 置 -2(软取消,不删数据,isDelete 保持 0)
|
|
|
+ * 支持单条(dto.id)或批量(dto.idList)
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Result<Object> cancel(MarketEmailsDTO dto) {
|
|
|
+ if (dto == null) {
|
|
|
+ return Result.error("请求体不能为空");
|
|
|
+ }
|
|
|
+ List<Long> ids = new ArrayList<>();
|
|
|
+ if (!ObjectUtils.isEmpty(dto.getId())) {
|
|
|
+ ids.add(dto.getId());
|
|
|
+ }
|
|
|
+ if (!CollectionUtils.isEmpty(dto.getIdList())) {
|
|
|
+ ids.addAll(dto.getIdList());
|
|
|
+ }
|
|
|
+ if (ids.isEmpty()) {
|
|
|
+ return Result.error("id 或 idList 不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ LambdaUpdateWrapper<MarketEmailsEntity> wrapper = new LambdaUpdateWrapper<>();
|
|
|
+ wrapper.in(MarketEmailsEntity::getId, ids);
|
|
|
+ wrapper.eq(MarketEmailsEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
|
|
|
+ // status = -2 表示取消发送
|
|
|
+ wrapper.set(MarketEmailsEntity::getStatus, -2);
|
|
|
+ boolean ok = this.update(wrapper);
|
|
|
+ if (!ok) {
|
|
|
+ return Result.error("取消发送失败");
|
|
|
+ }
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 人工干预列表:tabType = protect / suspend
|
|
|
+ * 策略:单活动下保护/暂停的邮件数通常几百~几千,先查全集在内存里按 recipient 分组
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Result<Object> getInterventionList(Long marketingCampaignId, String tabType) {
|
|
|
+ if (ObjectUtils.isEmpty(marketingCampaignId)) {
|
|
|
+ return Result.error("marketingCampaignId不能为空");
|
|
|
+ }
|
|
|
+ if (!"protect".equalsIgnoreCase(tabType) && !"suspend".equalsIgnoreCase(tabType)) {
|
|
|
+ return Result.error("tabType 必须是 protect 或 suspend");
|
|
|
+ }
|
|
|
+
|
|
|
+ LambdaQueryWrapper<MarketEmailsEntity> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ wrapper.eq(MarketEmailsEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
|
|
|
+ wrapper.eq(MarketEmailsEntity::getMarketingCampaignId, marketingCampaignId);
|
|
|
+ wrapper.isNotNull(MarketEmailsEntity::getRecipient);
|
|
|
+ wrapper.ne(MarketEmailsEntity::getRecipient, "");
|
|
|
+ if ("protect".equalsIgnoreCase(tabType)) {
|
|
|
+ wrapper.eq(MarketEmailsEntity::getHasProtect, 1);
|
|
|
+ } else {
|
|
|
+ wrapper.eq(MarketEmailsEntity::getHasSuspend, 1);
|
|
|
+ }
|
|
|
+ wrapper.select(MarketEmailsEntity::getId,
|
|
|
+ MarketEmailsEntity::getRecipient,
|
|
|
+ MarketEmailsEntity::getCustomerId,
|
|
|
+ MarketEmailsEntity::getHasProtect,
|
|
|
+ MarketEmailsEntity::getHasSuspend,
|
|
|
+ MarketEmailsEntity::getProtectReason,
|
|
|
+ MarketEmailsEntity::getUpdateTime);
|
|
|
+ List<MarketEmailsEntity> all = this.list(wrapper);
|
|
|
+
|
|
|
+ // 按 recipient 聚合(同一客户多个保护/暂停记录合并为一张卡片)
|
|
|
+ Map<String, com.storlead.trade.vo.MarketEmailsProtectVO> 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.MarketEmailsProtectVO vo = aggMap.computeIfAbsent(r, k -> {
|
|
|
+ com.storlead.trade.vo.MarketEmailsProtectVO v = new com.storlead.trade.vo.MarketEmailsProtectVO();
|
|
|
+ v.setRecipient(k);
|
|
|
+ v.setHasProtect(0);
|
|
|
+ v.setHasSuspend(0);
|
|
|
+ return v;
|
|
|
+ });
|
|
|
+ // 记下第一条(最早设置保护/暂停的那一条)
|
|
|
+ if (vo.getId() == null) {
|
|
|
+ vo.setId(e.getId());
|
|
|
+ }
|
|
|
+ if (vo.getCustomerId() == null && e.getCustomerId() != null) {
|
|
|
+ vo.setCustomerId(e.getCustomerId());
|
|
|
+ }
|
|
|
+ if (e.getHasProtect() != null && e.getHasProtect() == 1) {
|
|
|
+ vo.setHasProtect(1);
|
|
|
+ }
|
|
|
+ if (e.getHasSuspend() != null && e.getHasSuspend() == 1) {
|
|
|
+ vo.setHasSuspend(1);
|
|
|
+ }
|
|
|
+ // 取最早的 updateTime 作为保护/暂停时间
|
|
|
+ if (e.getUpdateTime() != null) {
|
|
|
+ if (vo.getProtectTime() == null || e.getUpdateTime().before(vo.getProtectTime())) {
|
|
|
+ vo.setProtectTime(e.getUpdateTime());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 保护原因:取该 recipient 下任意一条非空的(多条一致时取最先写入的)
|
|
|
+ if (vo.getProtectReason() == null && e.getProtectReason() != null && !e.getProtectReason().isEmpty()) {
|
|
|
+ vo.setProtectReason(e.getProtectReason());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 保护时间 DESC 排序
|
|
|
+ List<com.storlead.trade.vo.MarketEmailsProtectVO> voList = new java.util.ArrayList<>(aggMap.values());
|
|
|
+ voList.sort((a, b) -> {
|
|
|
+ if (a.getProtectTime() == null && b.getProtectTime() == null) return 0;
|
|
|
+ if (a.getProtectTime() == null) return 1;
|
|
|
+ if (b.getProtectTime() == null) return -1;
|
|
|
+ return b.getProtectTime().compareTo(a.getProtectTime());
|
|
|
+ });
|
|
|
+
|
|
|
+ // 批量回填客户名
|
|
|
+ if (!voList.isEmpty()) {
|
|
|
+ java.util.Set<Long> customerIdSet = new java.util.LinkedHashSet<>();
|
|
|
+ for (com.storlead.trade.vo.MarketEmailsProtectVO v : voList) {
|
|
|
+ if (v.getCustomerId() != null) customerIdSet.add(v.getCustomerId());
|
|
|
+ }
|
|
|
+ if (!customerIdSet.isEmpty()) {
|
|
|
+ try {
|
|
|
+ java.util.List<com.storlead.trade.entity.CustomerEntity> customers =
|
|
|
+ customerTradeService.listByIds(new java.util.ArrayList<>(customerIdSet));
|
|
|
+ java.util.Map<Long, com.storlead.trade.entity.CustomerEntity> customerMap = new java.util.HashMap<>();
|
|
|
+ if (!CollectionUtils.isEmpty(customers)) {
|
|
|
+ for (com.storlead.trade.entity.CustomerEntity c : customers) {
|
|
|
+ if (c.getId() != null) customerMap.put(c.getId(), c);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (com.storlead.trade.vo.MarketEmailsProtectVO v : voList) {
|
|
|
+ com.storlead.trade.entity.CustomerEntity c = customerMap.get(v.getCustomerId());
|
|
|
+ if (c != null) {
|
|
|
+ v.setCustomerName(c.getCustomerName());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception ex) {
|
|
|
+ log.warn("回填客户名失败,customerIds={} err={}", customerIdSet, ex.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return Result.ok(voList);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 移除保护:按邮件主键 id 把 has_protect 置 0(保留 has_suspend)
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Result<Object> removeProtect(Long id) {
|
|
|
+ if (ObjectUtils.isEmpty(id)) {
|
|
|
+ return Result.error("id不能为空");
|
|
|
+ }
|
|
|
+ MarketEmailsEntity exist = this.getById(id);
|
|
|
+ if (exist == null || CommonConstant.DEL_FLAG_1.equals(exist.getIsDelete())) {
|
|
|
+ return Result.error("邮件不存在或已删除");
|
|
|
+ }
|
|
|
+ LambdaUpdateWrapper<MarketEmailsEntity> wrapper = new LambdaUpdateWrapper<>();
|
|
|
+ wrapper.eq(MarketEmailsEntity::getId, id);
|
|
|
+ wrapper.eq(MarketEmailsEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
|
|
|
+ wrapper.set(MarketEmailsEntity::getHasProtect, 0);
|
|
|
+ // 同步清空保护原因
|
|
|
+ wrapper.set(MarketEmailsEntity::getProtectReason, null);
|
|
|
+ boolean ok = this.update(wrapper);
|
|
|
+ if (!ok) {
|
|
|
+ return Result.error("移除保护失败");
|
|
|
+ }
|
|
|
+ return Result.ok();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Result<Object> getManagementDetail(Long marketingCampaignId) {
|
|
|
+ if (ObjectUtils.isEmpty(marketingCampaignId)) {
|
|
|
+ return Result.error("marketingCampaignId不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 营销活动名(用于拼接在卡片标题位置或返回顶部)
|
|
|
+ String campaignName = null;
|
|
|
+ MarketingCampaignEntity campaign = marketingCampaignService.getById(marketingCampaignId);
|
|
|
+ if (campaign != null) {
|
|
|
+ campaignName = campaign.getName();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查该营销活动下所有未软删的邮件
|
|
|
+ LambdaQueryWrapper<MarketEmailsEntity> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ wrapper.eq(MarketEmailsEntity::getMarketingCampaignId, marketingCampaignId);
|
|
|
+ wrapper.eq(MarketEmailsEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
|
|
|
+ wrapper.orderByAsc(MarketEmailsEntity::getExpectSendTime);
|
|
|
+ List<MarketEmailsEntity> entityList = this.list(wrapper);
|
|
|
+ if (CollectionUtils.isEmpty(entityList)) {
|
|
|
+ return Result.ok(new ArrayList<MarketEmailsManagementVO>());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 批量收 ID,减少 N+1
|
|
|
+ java.util.Set<Long> customerIdSet = new java.util.HashSet<>();
|
|
|
+ java.util.Set<Long> sopDetailIdSet = new java.util.HashSet<>();
|
|
|
+ for (MarketEmailsEntity e : entityList) {
|
|
|
+ if (e.getCustomerId() != null) customerIdSet.add(e.getCustomerId());
|
|
|
+ if (e.getMarketingCampaignSopDetailId() != null) sopDetailIdSet.add(e.getMarketingCampaignSopDetailId());
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<Long, CustomerEntity> customerMap = customerIdSet.isEmpty()
|
|
|
+ ? Collections.emptyMap()
|
|
|
+ : customerTradeService.listByIds(new java.util.ArrayList<>(customerIdSet)).stream()
|
|
|
+ .collect(Collectors.toMap(CustomerEntity::getId, c -> c, (a, c) -> a));
|
|
|
+ Map<Long, MarketingCampaignSopDetailEntity> sopDetailMap = sopDetailIdSet.isEmpty()
|
|
|
+ ? Collections.emptyMap()
|
|
|
+ : marketingCampaignSopDetailEntityService.listByIds(new java.util.ArrayList<>(sopDetailIdSet)).stream()
|
|
|
+ .collect(Collectors.toMap(MarketingCampaignSopDetailEntity::getId, s -> s, (a, c) -> a));
|
|
|
+
|
|
|
+ // 组装 VO
|
|
|
+ List<MarketEmailsManagementVO> voList = new ArrayList<>(entityList.size());
|
|
|
+ for (MarketEmailsEntity entity : entityList) {
|
|
|
+ MarketEmailsManagementVO vo = new MarketEmailsManagementVO();
|
|
|
+ BeanUtils.copyProperties(entity, vo);
|
|
|
+ // expectSendTime 是 DateTime,VO 是 Date,手动 set(BeanUtils 类型不一致不复制)
|
|
|
+ if (entity.getExpectSendTime() != null) {
|
|
|
+ vo.setExpectSendTime(entity.getExpectSendTime());
|
|
|
+ }
|
|
|
+ vo.setCampaignName(campaignName);
|
|
|
+
|
|
|
+ CustomerEntity customer = customerMap.get(entity.getCustomerId());
|
|
|
+ if (customer != null) {
|
|
|
+ vo.setCustomerName(customer.getCustomerName());
|
|
|
+ vo.setCustomerContact(customer.getCollaborator());
|
|
|
+ }
|
|
|
+
|
|
|
+ MarketingCampaignSopDetailEntity sopDetail = sopDetailMap.get(entity.getMarketingCampaignSopDetailId());
|
|
|
+ if (sopDetail != null) {
|
|
|
+ vo.setStageName(sopDetail.getName());
|
|
|
+ }
|
|
|
+
|
|
|
+ voList.add(vo);
|
|
|
+ }
|
|
|
+ return Result.ok(voList);
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
@Override
|
|
|
public void addSendTime(MarketingCampaignEntity marketingCampaignEntity) {
|