|
|
@@ -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.MarketEmailsOpenVO;
|
|
|
import com.storlead.trade.vo.ScheduleStageVO;
|
|
|
import org.springframework.beans.BeanUtils;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
@@ -53,6 +54,7 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
|
|
|
@Resource
|
|
|
private CustomerTradeService customerTradeService;
|
|
|
@Resource
|
|
|
+ @org.springframework.context.annotation.Lazy
|
|
|
private MarketingCampaignSopDetailService marketingCampaignSopDetailEntityService;
|
|
|
@Resource
|
|
|
private SopDetailService sopDetailService;
|
|
|
@@ -76,8 +78,8 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
|
|
|
if (!ObjectUtils.isEmpty(dto.getMarketingCampaignId())) {
|
|
|
wrapper.eq(MarketEmailsEntity::getMarketingCampaignId, dto.getMarketingCampaignId());
|
|
|
}
|
|
|
- if (!ObjectUtils.isEmpty(dto.getSopDetailId())) {
|
|
|
- wrapper.eq(MarketEmailsEntity::getSopDetailId, dto.getSopDetailId());
|
|
|
+ if (!ObjectUtils.isEmpty(dto.getMarketingCampaignSopDetailId())) {
|
|
|
+ wrapper.eq(MarketEmailsEntity::getMarketingCampaignSopDetailId, dto.getMarketingCampaignSopDetailId());
|
|
|
}
|
|
|
if (!ObjectUtils.isEmpty(dto.getEmailId())) {
|
|
|
wrapper.eq(MarketEmailsEntity::getEmailId, dto.getEmailId());
|
|
|
@@ -118,6 +120,135 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
|
|
|
return Result.ok();
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public Result<Object> getOpenList(MarketEmailsDTO dto) {
|
|
|
+ if (dto == null) {
|
|
|
+ dto = new MarketEmailsDTO();
|
|
|
+ }
|
|
|
+ // 打开邮件的客户 = hasReader=1 且 recipient 不为空
|
|
|
+ // 策略:单活动下打开邮件的邮件数通常几百~几千,先查全集在内存里按 recipient 分组 + 分页
|
|
|
+ LambdaQueryWrapper<MarketEmailsEntity> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ wrapper.eq(MarketEmailsEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
|
|
|
+ wrapper.eq(MarketEmailsEntity::getHasReader, 1);
|
|
|
+ if (!ObjectUtils.isEmpty(dto.getMarketingCampaignId())) {
|
|
|
+ wrapper.eq(MarketEmailsEntity::getMarketingCampaignId, dto.getMarketingCampaignId());
|
|
|
+ }
|
|
|
+ if (dto.getRecipient() != null && !dto.getRecipient().trim().isEmpty()) {
|
|
|
+ wrapper.eq(MarketEmailsEntity::getRecipient, dto.getRecipient().trim());
|
|
|
+ }
|
|
|
+ wrapper.isNotNull(MarketEmailsEntity::getRecipient);
|
|
|
+ wrapper.ne(MarketEmailsEntity::getRecipient, "");
|
|
|
+ // 只查需要的列,减少数据传输
|
|
|
+ wrapper.select(MarketEmailsEntity::getRecipient,
|
|
|
+ MarketEmailsEntity::getFirstOpenTime,
|
|
|
+ MarketEmailsEntity::getHasProtect,
|
|
|
+ MarketEmailsEntity::getHasSuspend);
|
|
|
+ List<MarketEmailsEntity> all = this.list(wrapper);
|
|
|
+ // 按 recipient 聚合
|
|
|
+ java.util.Map<String, com.storlead.trade.vo.MarketEmailsOpenVO> aggMap = new java.util.LinkedHashMap<>();
|
|
|
+ if (!CollectionUtils.isEmpty(all)) {
|
|
|
+ for (MarketEmailsEntity e : all) {
|
|
|
+ String r = e.getRecipient();
|
|
|
+ if (r == null || r.isEmpty()) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ com.storlead.trade.vo.MarketEmailsOpenVO vo = aggMap.computeIfAbsent(r, k -> {
|
|
|
+ com.storlead.trade.vo.MarketEmailsOpenVO v = new com.storlead.trade.vo.MarketEmailsOpenVO();
|
|
|
+ v.setRecipient(k);
|
|
|
+ v.setClickCount(0L);
|
|
|
+ return v;
|
|
|
+ });
|
|
|
+ vo.setClickCount(vo.getClickCount() + 1);
|
|
|
+ // 取最早首次打开时间
|
|
|
+ if (e.getFirstOpenTime() != null) {
|
|
|
+ if (vo.getFirstOpenTime() == null || e.getFirstOpenTime().before(vo.getFirstOpenTime())) {
|
|
|
+ vo.setFirstOpenTime(e.getFirstOpenTime());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 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);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 按首次打开时间倒序
|
|
|
+ java.util.List<com.storlead.trade.vo.MarketEmailsOpenVO> sorted = new java.util.ArrayList<>(aggMap.values());
|
|
|
+ sorted.sort((a, b) -> {
|
|
|
+ if (a.getFirstOpenTime() == null && b.getFirstOpenTime() == null) return 0;
|
|
|
+ if (a.getFirstOpenTime() == null) return 1;
|
|
|
+ if (b.getFirstOpenTime() == null) return -1;
|
|
|
+ return b.getFirstOpenTime().compareTo(a.getFirstOpenTime());
|
|
|
+ });
|
|
|
+ // 内存分页
|
|
|
+ long pageIndex = dto.getPageIndex() != null && dto.getPageIndex() > 0 ? dto.getPageIndex() : 1L;
|
|
|
+ long pageSize = dto.getPageSize() != null && dto.getPageSize() > 0 ? dto.getPageSize() : 50L;
|
|
|
+ long total = sorted.size();
|
|
|
+ long from = Math.min((pageIndex - 1) * pageSize, total);
|
|
|
+ long to = Math.min(from + pageSize, total);
|
|
|
+ java.util.List<com.storlead.trade.vo.MarketEmailsOpenVO> pageList = sorted.subList((int) from, (int) to);
|
|
|
+ com.baomidou.mybatisplus.core.metadata.IPage<com.storlead.trade.vo.MarketEmailsOpenVO> page =
|
|
|
+ new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(pageIndex, pageSize, total);
|
|
|
+ page.setRecords(pageList);
|
|
|
+ return Result.result(page);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Result<Object> protect(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);
|
|
|
+ wrapper.set(MarketEmailsEntity::getHasProtect, dto.getHasProtect());
|
|
|
+ boolean ok = this.update(wrapper);
|
|
|
+ if (!ok) {
|
|
|
+ return Result.error("保护失败");
|
|
|
+ }
|
|
|
+ return Result.ok();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Result<Object> suspend(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);
|
|
|
+ wrapper.set(MarketEmailsEntity::getHasSuspend, dto.getHasSuspend());
|
|
|
+ boolean ok = this.update(wrapper);
|
|
|
+ if (!ok) {
|
|
|
+ return Result.error("暂停失败");
|
|
|
+ }
|
|
|
+ return Result.ok();
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
@Transactional(rollbackFor = Throwable.class)
|
|
|
public Result<Object> edit(MarketEmailsDTO dto) {
|
|
|
@@ -247,10 +378,16 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
|
|
|
if (ObjectUtils.isEmpty(sopDetail)) {
|
|
|
continue;
|
|
|
}
|
|
|
+ //取marketingCampaignSopDetailEntityList中marketingId=marketingCampaignEntity.getId()且sopDetailId=sopDetail.getId()的记录
|
|
|
+ MarketingCampaignSopDetailEntity marketingCampaignSopDetail = marketingCampaignSopDetailEntityList.stream()
|
|
|
+ .filter(detail -> detail.getMarketingId().equals(marketingCampaignEntity.getId())
|
|
|
+ && detail.getSopDetailId().equals(sopDetail.getId()))
|
|
|
+ .findFirst()
|
|
|
+ .orElse(null);
|
|
|
MarketEmailsEntity marketEmail = new MarketEmailsEntity();
|
|
|
marketEmail.setMarketingCampaignId(marketingCampaignEntity.getId());
|
|
|
marketEmail.setCustomerId(customerVO.getCustomerId());
|
|
|
- marketEmail.setSopDetailId(sopDetail.getId());
|
|
|
+ marketEmail.setMarketingCampaignSopDetailId(marketingCampaignSopDetail.getId());
|
|
|
marketEmail.setExpectSendTime(scheduleStage.getBeijingDatetime());
|
|
|
marketEmailList.add(marketEmail);
|
|
|
}
|