|
|
@@ -276,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("保护失败");
|
|
|
@@ -483,6 +491,141 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
|
|
|
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) {
|