|
@@ -15,7 +15,9 @@ import com.storlead.trade.entity.CustomerCompanyEntity;
|
|
|
import com.storlead.trade.entity.CustomerEntity;
|
|
import com.storlead.trade.entity.CustomerEntity;
|
|
|
import com.storlead.trade.entity.CustomerAnalysisResultEntity;
|
|
import com.storlead.trade.entity.CustomerAnalysisResultEntity;
|
|
|
import com.storlead.trade.entity.LiaisonEntity;
|
|
import com.storlead.trade.entity.LiaisonEntity;
|
|
|
|
|
+import com.storlead.trade.entity.MarketEmailsEntity;
|
|
|
import com.storlead.trade.mapper.CustomerEntityMapper;
|
|
import com.storlead.trade.mapper.CustomerEntityMapper;
|
|
|
|
|
+import com.storlead.trade.mapper.MarketEmailsMapper;
|
|
|
import com.storlead.trade.service.CustomerCompanyTradeService;
|
|
import com.storlead.trade.service.CustomerCompanyTradeService;
|
|
|
import com.storlead.trade.service.CustomerTradeService;
|
|
import com.storlead.trade.service.CustomerTradeService;
|
|
|
import com.storlead.trade.service.CustomerAnalysisResultEntityService;
|
|
import com.storlead.trade.service.CustomerAnalysisResultEntityService;
|
|
@@ -30,7 +32,11 @@ import org.springframework.util.CollectionUtils;
|
|
|
import org.springframework.util.ObjectUtils;
|
|
import org.springframework.util.ObjectUtils;
|
|
|
import org.springframework.util.StringUtils;
|
|
import org.springframework.util.StringUtils;
|
|
|
|
|
|
|
|
|
|
+import java.time.LocalDate;
|
|
|
|
|
+import java.time.ZoneId;
|
|
|
|
|
+import java.time.temporal.ChronoUnit;
|
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
|
|
|
+import java.util.Date;
|
|
|
import java.util.HashMap;
|
|
import java.util.HashMap;
|
|
|
import java.util.HashSet;
|
|
import java.util.HashSet;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
@@ -51,16 +57,24 @@ public class CustomerTradeServiceImpl
|
|
|
private final LiaisonTradeService liaisonTradeService;
|
|
private final LiaisonTradeService liaisonTradeService;
|
|
|
private final CustomerAnalysisResultEntityService customerAnalysisResultEntityService;
|
|
private final CustomerAnalysisResultEntityService customerAnalysisResultEntityService;
|
|
|
private final SysDictService sysDictService;
|
|
private final SysDictService sysDictService;
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 直接注入 Mapper 而非 MarketEmailsService:MarketEmailsServiceImpl 依赖 CustomerTradeService,
|
|
|
|
|
+ * 而本类是构造器注入,再引 MarketEmailsService 会形成构造器循环依赖,启动时抛
|
|
|
|
|
+ * BeanCurrentlyInCreationException。Mapper 已由 TradeBaseMapper 统一路由到 trade 库。
|
|
|
|
|
+ */
|
|
|
|
|
+ private final MarketEmailsMapper marketEmailsMapper;
|
|
|
|
|
|
|
|
public CustomerTradeServiceImpl(
|
|
public CustomerTradeServiceImpl(
|
|
|
CustomerCompanyTradeService customerCompanyTradeService,
|
|
CustomerCompanyTradeService customerCompanyTradeService,
|
|
|
LiaisonTradeService liaisonTradeService,
|
|
LiaisonTradeService liaisonTradeService,
|
|
|
CustomerAnalysisResultEntityService customerAnalysisResultEntityService,
|
|
CustomerAnalysisResultEntityService customerAnalysisResultEntityService,
|
|
|
- SysDictService sysDictService) {
|
|
|
|
|
|
|
+ SysDictService sysDictService,
|
|
|
|
|
+ MarketEmailsMapper marketEmailsMapper) {
|
|
|
this.customerCompanyTradeService = customerCompanyTradeService;
|
|
this.customerCompanyTradeService = customerCompanyTradeService;
|
|
|
this.liaisonTradeService = liaisonTradeService;
|
|
this.liaisonTradeService = liaisonTradeService;
|
|
|
this.customerAnalysisResultEntityService = customerAnalysisResultEntityService;
|
|
this.customerAnalysisResultEntityService = customerAnalysisResultEntityService;
|
|
|
this.sysDictService = sysDictService;
|
|
this.sysDictService = sysDictService;
|
|
|
|
|
+ this.marketEmailsMapper = marketEmailsMapper;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
@@ -268,9 +282,42 @@ public class CustomerTradeServiceImpl
|
|
|
.eq(CustomerAnalysisResultEntity::getIsDelete, CommonConstant.DEL_FLAG_0)
|
|
.eq(CustomerAnalysisResultEntity::getIsDelete, CommonConstant.DEL_FLAG_0)
|
|
|
.eq(CustomerAnalysisResultEntity::getCustomerId, customerId)
|
|
.eq(CustomerAnalysisResultEntity::getCustomerId, customerId)
|
|
|
.last("LIMIT 1")));
|
|
.last("LIMIT 1")));
|
|
|
|
|
+
|
|
|
|
|
+ // 互动记录:该客户全部已发送成功邮件(按发送时间倒序,首条即最后一次联系)
|
|
|
|
|
+ List<MarketEmailsEntity> sentEmailList = findSentEmailList(customerId);
|
|
|
|
|
+ vo.setInteractionRecordList(sentEmailList);
|
|
|
|
|
+
|
|
|
|
|
+ // 最后联系时间 / 天数:取互动记录首条,省掉一次查询
|
|
|
|
|
+ Date lastContactTime = sentEmailList.isEmpty() ? null : sentEmailList.get(0).getExpectSendTime();
|
|
|
|
|
+ vo.setLastContactTime(lastContactTime);
|
|
|
|
|
+ vo.setLastContactDays(calcDaysSince(lastContactTime));
|
|
|
return vo;
|
|
return vo;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 互动记录:该客户全部「发送成功」邮件(market_emails.status = 1),按预计发送时间倒序;
|
|
|
|
|
+ * 无记录时返回空数组(不返回 null)。
|
|
|
|
|
+ */
|
|
|
|
|
+ private List<MarketEmailsEntity> findSentEmailList(Long customerId) {
|
|
|
|
|
+ return marketEmailsMapper.selectList(
|
|
|
|
|
+ new LambdaQueryWrapper<MarketEmailsEntity>()
|
|
|
|
|
+ .eq(MarketEmailsEntity::getCustomerId, customerId)
|
|
|
|
|
+ .eq(MarketEmailsEntity::getStatus, 1)
|
|
|
|
|
+ .eq(MarketEmailsEntity::getIsDelete, CommonConstant.DEL_FLAG_0)
|
|
|
|
|
+ .orderByDesc(MarketEmailsEntity::getExpectSendTime));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 按自然日计算 date 距今的天数(当天为 0);date 为 null 时返回 null。
|
|
|
|
|
+ */
|
|
|
|
|
+ private Integer calcDaysSince(Date date) {
|
|
|
|
|
+ if (date == null) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ LocalDate day = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
|
|
|
|
+ return (int) ChronoUnit.DAYS.between(day, LocalDate.now());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
@Override
|
|
@Override
|
|
|
@Transactional(rollbackFor = Throwable.class)
|
|
@Transactional(rollbackFor = Throwable.class)
|
|
|
public Result<Object> add(CustomerDTO dto) {
|
|
public Result<Object> add(CustomerDTO dto) {
|