|
@@ -5,6 +5,7 @@ import com.storlead.framework.common.constant.DSConstants;
|
|
|
|
|
|
|
|
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
@@ -35,6 +36,7 @@ import java.util.Date;
|
|
|
import java.util.HashMap;
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
|
|
+import java.util.function.Consumer;
|
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
|
import java.time.LocalDate;
|
|
import java.time.LocalDate;
|
|
|
import java.time.ZoneId;
|
|
import java.time.ZoneId;
|
|
@@ -125,9 +127,88 @@ public class MarketingCampaignServiceImpl
|
|
|
marketingCampaignVOList.get(i).setCustomerList(customerListI);
|
|
marketingCampaignVOList.get(i).setCustomerList(customerListI);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // ===== 营销活动维度统计(基于 market_emails 表)=====
|
|
|
|
|
+ if (!CollectionUtils.isEmpty(marketingCampaignIdList)) {
|
|
|
|
|
+ Map<Long, Long> openedMap = countEmailsByCampaign(marketingCampaignIdList,
|
|
|
|
|
+ "count(distinct customer_id) as cnt", qw -> qw.eq("has_reader", 1));
|
|
|
|
|
+ Map<Long, Long> repliedMap = countEmailsByCampaign(marketingCampaignIdList,
|
|
|
|
|
+ "count(distinct customer_id) as cnt", qw -> qw.eq("has_reply", 1));
|
|
|
|
|
+ Map<Long, Long> protectMap = countEmailsByCampaign(marketingCampaignIdList,
|
|
|
|
|
+ "count(distinct customer_id) as cnt", qw -> qw.eq("has_protect", 1));
|
|
|
|
|
+ Map<Long, Long> pendingMap = countEmailsByCampaign(marketingCampaignIdList,
|
|
|
|
|
+ "count(*) as cnt", qw -> qw.eq("status", -1));
|
|
|
|
|
+ Map<Long, Long> sentMap = countEmailsByCampaign(marketingCampaignIdList,
|
|
|
|
|
+ "count(*) as cnt", qw -> qw.eq("status", 1));
|
|
|
|
|
+ Map<Long, Long> sentCustomerMap = countEmailsByCampaign(marketingCampaignIdList,
|
|
|
|
|
+ "count(distinct customer_id) as cnt", qw -> qw.eq("status", 1));
|
|
|
|
|
+ Map<Long, Long> cancelledMap = countEmailsByCampaign(marketingCampaignIdList,
|
|
|
|
|
+ "count(*) as cnt", qw -> qw.eq("status", -3));
|
|
|
|
|
+ for (MarketingCampaignVO vo : marketingCampaignVOList) {
|
|
|
|
|
+ Long id = vo.getId();
|
|
|
|
|
+ vo.setOpenedCustomerCount(toInt(openedMap.get(id)));
|
|
|
|
|
+ vo.setRepliedCustomerCount(toInt(repliedMap.get(id)));
|
|
|
|
|
+ vo.setProtectWhitelistCount(toInt(protectMap.get(id)));
|
|
|
|
|
+ vo.setPendingEmailCount(toInt(pendingMap.get(id)));
|
|
|
|
|
+ vo.setSentEmailCount(toInt(sentMap.get(id)));
|
|
|
|
|
+ vo.setCancelledEmailCount(toInt(cancelledMap.get(id)));
|
|
|
|
|
+ int sentCustomer = toInt(sentCustomerMap.get(id));
|
|
|
|
|
+ vo.setSentCustomerCount(sentCustomer);
|
|
|
|
|
+ vo.setOpenRateText(buildRate(toInt(openedMap.get(id)), sentCustomer));
|
|
|
|
|
+ vo.setReplyRateText(buildRate(toInt(repliedMap.get(id)), sentCustomer));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return Result.result(pageVO);
|
|
return Result.result(pageVO);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 按营销活动分组统计 market_emails 数量。
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param campaignIds 营销活动 id 列表
|
|
|
|
|
+ * @param selectExpr 聚合表达式,例如 "count(distinct customer_id) as cnt" 或 "count(*) as cnt"
|
|
|
|
|
+ * @param extra 额外过滤条件(如 has_reader=1 / status=-1)
|
|
|
|
|
+ * @return key=marketing_campaign_id, value=聚合结果
|
|
|
|
|
+ */
|
|
|
|
|
+ private Map<Long, Long> countEmailsByCampaign(List<Long> campaignIds, String selectExpr,
|
|
|
|
|
+ Consumer<QueryWrapper<MarketEmailsEntity>> extra) {
|
|
|
|
|
+ QueryWrapper<MarketEmailsEntity> qw = new QueryWrapper<>();
|
|
|
|
|
+ qw.select("marketing_campaign_id, " + selectExpr);
|
|
|
|
|
+ qw.in("marketing_campaign_id", campaignIds);
|
|
|
|
|
+ qw.eq("is_delete", CommonConstant.DEL_FLAG_0);
|
|
|
|
|
+ if (extra != null) {
|
|
|
|
|
+ extra.accept(qw);
|
|
|
|
|
+ }
|
|
|
|
|
+ qw.groupBy("marketing_campaign_id");
|
|
|
|
|
+ List<Map<String, Object>> maps = marketEmailsService.listMaps(qw);
|
|
|
|
|
+ Map<Long, Long> result = new HashMap<>(maps == null ? 1 : maps.size());
|
|
|
|
|
+ if (maps != null) {
|
|
|
|
|
+ for (Map<String, Object> m : maps) {
|
|
|
|
|
+ Object cid = m.get("marketing_campaign_id");
|
|
|
|
|
+ Object cnt = m.get("cnt");
|
|
|
|
|
+ if (cid == null || cnt == null) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ result.put(((Number) cid).longValue(), ((Number) cnt).longValue());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Integer toInt(Long v) {
|
|
|
|
|
+ return v == null ? 0 : v.intValue();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 计算百分比并带 % 返回。denominator <= 0 时返回 "0%"。
|
|
|
|
|
+ */
|
|
|
|
|
+ private String buildRate(int numerator, int denominator) {
|
|
|
|
|
+ if (denominator <= 0) {
|
|
|
|
|
+ return "0%";
|
|
|
|
|
+ }
|
|
|
|
|
+ int pct = (int) Math.round(numerator * 100.0 / denominator);
|
|
|
|
|
+ return pct + "%";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
@Override
|
|
@Override
|
|
|
public Result<Object> getDetailById(Long id) {
|
|
public Result<Object> getDetailById(Long id) {
|
|
|
if (id == null) {
|
|
if (id == null) {
|