|
@@ -165,8 +165,7 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
|
|
|
if (dto == null) {
|
|
if (dto == null) {
|
|
|
dto = new MarketEmailsDTO();
|
|
dto = new MarketEmailsDTO();
|
|
|
}
|
|
}
|
|
|
- // 打开邮件的客户 = hasReader=1 且 recipient 不为空
|
|
|
|
|
- // 字段都可直接从 market_emails 查出,无需聚合,直接 DB 分页
|
|
|
|
|
|
|
+ // 打开邮件的客户 = hasReader=1 且 recipient / customerId 不为空
|
|
|
LambdaQueryWrapper<MarketEmailsEntity> wrapper = new LambdaQueryWrapper<>();
|
|
LambdaQueryWrapper<MarketEmailsEntity> wrapper = new LambdaQueryWrapper<>();
|
|
|
wrapper.eq(MarketEmailsEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
|
|
wrapper.eq(MarketEmailsEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
|
|
|
wrapper.eq(MarketEmailsEntity::getHasReader, 1);
|
|
wrapper.eq(MarketEmailsEntity::getHasReader, 1);
|
|
@@ -178,23 +177,70 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
|
|
|
}
|
|
}
|
|
|
wrapper.isNotNull(MarketEmailsEntity::getRecipient);
|
|
wrapper.isNotNull(MarketEmailsEntity::getRecipient);
|
|
|
wrapper.ne(MarketEmailsEntity::getRecipient, "");
|
|
wrapper.ne(MarketEmailsEntity::getRecipient, "");
|
|
|
- // DB 层直接分页 + 按首次打开时间倒序
|
|
|
|
|
|
|
+ wrapper.isNotNull(MarketEmailsEntity::getCustomerId);
|
|
|
wrapper.orderByDesc(MarketEmailsEntity::getFirstOpenTime);
|
|
wrapper.orderByDesc(MarketEmailsEntity::getFirstOpenTime);
|
|
|
- Page<MarketEmailsEntity> page = new Page<>(dto.getPageIndex(), dto.getPageSize());
|
|
|
|
|
- IPage<MarketEmailsEntity> entityPage = this.page(page, wrapper);
|
|
|
|
|
|
|
|
|
|
- // 实体 → VO(字段直接映射,openCount 来自 entity.openCount,无需 clickCount)
|
|
|
|
|
- List<MarketEmailsOpenVO> voList = entityPage.getRecords().stream().map(e -> {
|
|
|
|
|
- MarketEmailsOpenVO vo = new MarketEmailsOpenVO();
|
|
|
|
|
- vo.setRecipient(e.getRecipient());
|
|
|
|
|
- vo.setId(e.getId());
|
|
|
|
|
- vo.setCustomerId(e.getCustomerId());
|
|
|
|
|
- vo.setOpenCount(e.getOpenCount());
|
|
|
|
|
- vo.setFirstOpenTime(e.getFirstOpenTime());
|
|
|
|
|
- vo.setHasProtect(e.getHasProtect());
|
|
|
|
|
- vo.setHasSuspend(e.getHasSuspend());
|
|
|
|
|
- return vo;
|
|
|
|
|
- }).collect(Collectors.toList());
|
|
|
|
|
|
|
+ List<MarketEmailsEntity> all = this.list(wrapper);
|
|
|
|
|
+
|
|
|
|
|
+ // 按 customerId 聚合(同一客户多封已打开邮件合并为一张卡片):
|
|
|
|
|
+ // firstOpenTime 取最新,openCount 求和(总点击数),recipient 取最新打开时间那条,
|
|
|
|
|
+ // hasProtect / hasSuspend 取 MAX
|
|
|
|
|
+ Map<Long, MarketEmailsOpenVO> aggMap = new LinkedHashMap<>();
|
|
|
|
|
+ if (!CollectionUtils.isEmpty(all)) {
|
|
|
|
|
+ for (MarketEmailsEntity e : all) {
|
|
|
|
|
+ Long cid = e.getCustomerId();
|
|
|
|
|
+ if (cid == null) continue;
|
|
|
|
|
+ MarketEmailsOpenVO vo = aggMap.computeIfAbsent(cid, k -> {
|
|
|
|
|
+ MarketEmailsOpenVO v = new MarketEmailsOpenVO();
|
|
|
|
|
+ v.setCustomerId(k);
|
|
|
|
|
+ v.setHasProtect(0);
|
|
|
|
|
+ v.setHasSuspend(0);
|
|
|
|
|
+ v.setOpenCount(0);
|
|
|
|
|
+ return v;
|
|
|
|
|
+ });
|
|
|
|
|
+ // id: 取第一条(后续护/暂停操作以 customerId 为准)
|
|
|
|
|
+ if (vo.getId() == null) {
|
|
|
|
|
+ vo.setId(e.getId());
|
|
|
|
|
+ }
|
|
|
|
|
+ // 比较 firstOpenTime:isLater = 当前记录更新
|
|
|
|
|
+ Date eFirstOpen = e.getFirstOpenTime();
|
|
|
|
|
+ Date voFirstOpen = vo.getFirstOpenTime();
|
|
|
|
|
+ boolean isLater = eFirstOpen != null && (voFirstOpen == null || eFirstOpen.after(voFirstOpen));
|
|
|
|
|
+ // firstOpenTime / recipient: 取最新打开时间那条的
|
|
|
|
|
+ if (isLater) {
|
|
|
|
|
+ vo.setFirstOpenTime(eFirstOpen);
|
|
|
|
|
+ if (e.getRecipient() != null && !e.getRecipient().isEmpty()) {
|
|
|
|
|
+ vo.setRecipient(e.getRecipient());
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if ((vo.getRecipient() == null || vo.getRecipient().isEmpty())
|
|
|
|
|
+ && e.getRecipient() != null && !e.getRecipient().isEmpty()) {
|
|
|
|
|
+ // firstOpenTime 没更新,但 vo.recipient 仍为空 → 补齐
|
|
|
|
|
+ vo.setRecipient(e.getRecipient());
|
|
|
|
|
+ }
|
|
|
|
|
+ // openCount: 累加(总点击数)
|
|
|
|
|
+ if (e.getOpenCount() != null) {
|
|
|
|
|
+ vo.setOpenCount((vo.getOpenCount() == null ? 0 : vo.getOpenCount()) + e.getOpenCount());
|
|
|
|
|
+ }
|
|
|
|
|
+ // hasProtect / hasSuspend: MAX
|
|
|
|
|
+ if (e.getHasProtect() != null && e.getHasProtect() == 1) {
|
|
|
|
|
+ vo.setHasProtect(1);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (e.getHasSuspend() != null && e.getHasSuspend() == 1) {
|
|
|
|
|
+ vo.setHasSuspend(1);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 按 firstOpenTime DESC 排序
|
|
|
|
|
+ List<MarketEmailsOpenVO> voList = new ArrayList<>(aggMap.values());
|
|
|
|
|
+ voList.sort((a, b) -> {
|
|
|
|
|
+ Date at = a.getFirstOpenTime();
|
|
|
|
|
+ Date bt = b.getFirstOpenTime();
|
|
|
|
|
+ if (at == null && bt == null) return 0;
|
|
|
|
|
+ if (at == null) return 1;
|
|
|
|
|
+ if (bt == null) return -1;
|
|
|
|
|
+ return bt.compareTo(at);
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
// 回填客户名称(批量查 customer 表)
|
|
// 回填客户名称(批量查 customer 表)
|
|
|
Set<Long> customerIdSet = new LinkedHashSet<>();
|
|
Set<Long> customerIdSet = new LinkedHashSet<>();
|
|
@@ -225,7 +271,8 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- IPage<MarketEmailsOpenVO> voPage = new Page<>(entityPage.getCurrent(), entityPage.getSize(), entityPage.getTotal());
|
|
|
|
|
|
|
+ // 包装为 IPage(保持 API 契约;total = 客户数,size = 总数)
|
|
|
|
|
+ IPage<MarketEmailsOpenVO> voPage = new Page<>(1, voList.size(), voList.size());
|
|
|
voPage.setRecords(voList);
|
|
voPage.setRecords(voList);
|
|
|
return Result.result(voPage);
|
|
return Result.result(voPage);
|
|
|
}
|
|
}
|
|
@@ -516,25 +563,26 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
|
|
|
// MarketEmailsEntity::getUpdateTime);
|
|
// MarketEmailsEntity::getUpdateTime);
|
|
|
List<MarketEmailsEntity> all = this.list(wrapper);
|
|
List<MarketEmailsEntity> all = this.list(wrapper);
|
|
|
|
|
|
|
|
- // 按 recipient 聚合(同一客户多个保护/暂停记录合并为一张卡片)
|
|
|
|
|
- Map<String, MarketEmailsProtectVO> aggMap = new HashMap<>();
|
|
|
|
|
|
|
+ // 按 customerId 聚合(同一客户多个邮箱合并为一张卡片)
|
|
|
|
|
+ Map<Long, MarketEmailsProtectVO> aggMap = new LinkedHashMap<>();
|
|
|
if (!CollectionUtils.isEmpty(all)) {
|
|
if (!CollectionUtils.isEmpty(all)) {
|
|
|
for (MarketEmailsEntity e : all) {
|
|
for (MarketEmailsEntity e : all) {
|
|
|
- String r = e.getRecipient();
|
|
|
|
|
- if (r == null || r.isEmpty()) continue;
|
|
|
|
|
- MarketEmailsProtectVO vo = aggMap.computeIfAbsent(r, k -> {
|
|
|
|
|
|
|
+ Long cid = e.getCustomerId();
|
|
|
|
|
+ if (cid == null) continue;
|
|
|
|
|
+ MarketEmailsProtectVO vo = aggMap.computeIfAbsent(cid, k -> {
|
|
|
MarketEmailsProtectVO v = new MarketEmailsProtectVO();
|
|
MarketEmailsProtectVO v = new MarketEmailsProtectVO();
|
|
|
- v.setRecipient(k);
|
|
|
|
|
|
|
+ v.setCustomerId(k);
|
|
|
v.setHasProtect(0);
|
|
v.setHasProtect(0);
|
|
|
v.setHasSuspend(0);
|
|
v.setHasSuspend(0);
|
|
|
return v;
|
|
return v;
|
|
|
});
|
|
});
|
|
|
- // 记下第一条(最早设置保护/暂停的那一条)
|
|
|
|
|
|
|
+ // 记下第一条记录的 id 和 recipient
|
|
|
if (vo.getId() == null) {
|
|
if (vo.getId() == null) {
|
|
|
vo.setId(e.getId());
|
|
vo.setId(e.getId());
|
|
|
}
|
|
}
|
|
|
- if (vo.getCustomerId() == null && e.getCustomerId() != null) {
|
|
|
|
|
- vo.setCustomerId(e.getCustomerId());
|
|
|
|
|
|
|
+ if ((vo.getRecipient() == null || vo.getRecipient().isEmpty())
|
|
|
|
|
+ && e.getRecipient() != null && !e.getRecipient().isEmpty()) {
|
|
|
|
|
+ vo.setRecipient(e.getRecipient());
|
|
|
}
|
|
}
|
|
|
if (e.getHasProtect() != null && e.getHasProtect() == 1) {
|
|
if (e.getHasProtect() != null && e.getHasProtect() == 1) {
|
|
|
vo.setHasProtect(1);
|
|
vo.setHasProtect(1);
|
|
@@ -542,11 +590,11 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
|
|
|
if (e.getHasSuspend() != null && e.getHasSuspend() == 1) {
|
|
if (e.getHasSuspend() != null && e.getHasSuspend() == 1) {
|
|
|
vo.setHasSuspend(1);
|
|
vo.setHasSuspend(1);
|
|
|
}
|
|
}
|
|
|
- // 取最早的 updateTime 作为保护/暂停时间
|
|
|
|
|
- if (e.getProtectTime() != null) {
|
|
|
|
|
|
|
+ // 保护/暂停时间取第一条非空的(同一客户多邮箱一般是同时设置)
|
|
|
|
|
+ if (vo.getProtectTime() == null && e.getProtectTime() != null) {
|
|
|
vo.setProtectTime(e.getProtectTime());
|
|
vo.setProtectTime(e.getProtectTime());
|
|
|
}
|
|
}
|
|
|
- if (e.getSuspendTime() != null) {
|
|
|
|
|
|
|
+ if (vo.getSuspendTime() == null && e.getSuspendTime() != null) {
|
|
|
vo.setSuspendTime(e.getSuspendTime());
|
|
vo.setSuspendTime(e.getSuspendTime());
|
|
|
}
|
|
}
|
|
|
// if (e.getUpdateTime() != null) {
|
|
// if (e.getUpdateTime() != null) {
|
|
@@ -554,7 +602,7 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
|
|
|
// vo.setProtectTime(e.getUpdateTime());
|
|
// vo.setProtectTime(e.getUpdateTime());
|
|
|
// }
|
|
// }
|
|
|
// }
|
|
// }
|
|
|
- // 保护原因:取该 recipient 下任意一条非空的(多条一致时取最先写入的)
|
|
|
|
|
|
|
+ // 保护原因:取该 customerId 下第一条非空的(多条同时设置时取先进入循环的)
|
|
|
if (vo.getProtectReason() == null && e.getProtectReason() != null && !e.getProtectReason().isEmpty()) {
|
|
if (vo.getProtectReason() == null && e.getProtectReason() != null && !e.getProtectReason().isEmpty()) {
|
|
|
vo.setProtectReason(e.getProtectReason());
|
|
vo.setProtectReason(e.getProtectReason());
|
|
|
}
|
|
}
|