14 changed files with 1056 additions and 0 deletions
@ -0,0 +1,51 @@ |
|||||||
|
package apelet.association.controller; |
||||||
|
|
||||||
|
import apelet.association.service.ClueStatService; |
||||||
|
import apelet.association.vo.ClueStatSummaryVo; |
||||||
|
import apelet.association.vo.ClueTransformStatVo; |
||||||
|
import apelet.common.core.object.MyPageData; |
||||||
|
import apelet.common.core.object.ResponseResult; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.web.bind.annotation.GetMapping; |
||||||
|
import org.springframework.web.bind.annotation.RequestMapping; |
||||||
|
import org.springframework.web.bind.annotation.RequestParam; |
||||||
|
import org.springframework.web.bind.annotation.RestController; |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索转化统计接口 |
||||||
|
*/ |
||||||
|
@RestController |
||||||
|
@RequestMapping("/tenantadmin") |
||||||
|
public class ClueStatController { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private ClueStatService clueStatService; |
||||||
|
|
||||||
|
/** |
||||||
|
* 查询每种线索来源的转化统计数据(固定返回展会论坛/电话咨询/营销号/其他 4 行)。 |
||||||
|
* 支持分页:按 pageNum/pageSize 对统计结果做内存分页,返回分页包装数据。 |
||||||
|
* |
||||||
|
* @param pageNum 页码,从 1 开始,默认 1 |
||||||
|
* @param pageSize 每页条数,默认 10 |
||||||
|
* @return 线索转化统计的分页数据 |
||||||
|
*/ |
||||||
|
@GetMapping("/clueTransformStat") |
||||||
|
public ResponseResult<MyPageData<ClueTransformStatVo>> clueTransformStat( |
||||||
|
@RequestParam(defaultValue = "1") Integer pageNum, |
||||||
|
@RequestParam(defaultValue = "10") Integer pageSize) { |
||||||
|
MyPageData<ClueTransformStatVo> result = clueStatService.getClueTransformStat(pageNum, pageSize); |
||||||
|
return ResponseResult.success(result); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 查询线索转化统计整体汇总(不分线索来源,全量一行)。 |
||||||
|
* 指标:转化商机金额、赢单商机金额、已转商机成交金额、线索总数、线索转化数、线索转化率、商机转化率。 |
||||||
|
* |
||||||
|
* @return 整体汇总统计结果 |
||||||
|
*/ |
||||||
|
@GetMapping("/clueStatSummary") |
||||||
|
public ResponseResult<ClueStatSummaryVo> clueStatSummary() { |
||||||
|
ClueStatSummaryVo result = clueStatService.getClueStatSummary(); |
||||||
|
return ResponseResult.success(result); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,50 @@ |
|||||||
|
package apelet.association.dao; |
||||||
|
|
||||||
|
import apelet.association.model.BusinessOpportunities; |
||||||
|
import apelet.association.vo.DealTransformStatVo; |
||||||
|
import apelet.association.vo.OppTransformStatVo; |
||||||
|
import apelet.common.core.base.dao.BaseDaoMapper; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* 商机表 Mapper |
||||||
|
*/ |
||||||
|
public interface BusinessOpportunitiesMapper extends BaseDaoMapper<BusinessOpportunities> { |
||||||
|
|
||||||
|
/** |
||||||
|
* 按线索来源统计商机转化数据(转化商机数、赢单商机数、赢单商机金额、商机转化金额)。 |
||||||
|
* 商机通过 clue_id 关联线索表 member_clue,再按线索来源 source 分组。 |
||||||
|
* |
||||||
|
* @return 线索来源维度的商机转化统计列表 |
||||||
|
*/ |
||||||
|
List<OppTransformStatVo> selectOppTransformStatBySource(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 按线索来源统计"线索→商机→合同"成交数据(成交数、成交金额)。 |
||||||
|
* <p> |
||||||
|
* 当前合同表 contract 暂无数据(报价单反写逻辑未做), |
||||||
|
* 暂以报价单 status = '3'(通过,即已成合同)作为成交口径: |
||||||
|
* 报价单 quotation 通过 srcbillid 关联商机 business_opportunities, |
||||||
|
* 商机再通过 clue_id 关联线索 member_clue,按线索来源 source 分组。 |
||||||
|
* |
||||||
|
* @return 线索来源维度的成交统计列表 |
||||||
|
*/ |
||||||
|
List<DealTransformStatVo> selectDealStatBySource(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 整体汇总统计商机转化数据(转化商机数、赢单商机数、赢单商机金额、商机转化金额),不分来源。 |
||||||
|
* 商机通过 clue_id 关联线索表 member_clue。 |
||||||
|
* |
||||||
|
* @return 整体商机转化统计(单行,字段同 OppTransformStatVo,source 为空) |
||||||
|
*/ |
||||||
|
OppTransformStatVo selectOppSummary(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 整体汇总统计"线索→商机→合同"成交数据(成交数、成交金额),不分来源。 |
||||||
|
* 成交口径同 selectDealStatBySource(报价单 status='3')。 |
||||||
|
* |
||||||
|
* @return 整体成交统计(单行,字段同 DealTransformStatVo,source 为空) |
||||||
|
*/ |
||||||
|
DealTransformStatVo selectDealSummary(); |
||||||
|
} |
||||||
@ -0,0 +1,27 @@ |
|||||||
|
package apelet.association.dao; |
||||||
|
|
||||||
|
import apelet.association.model.MemberClue; |
||||||
|
import apelet.association.vo.ClueSourceCountVo; |
||||||
|
import apelet.common.core.base.dao.BaseDaoMapper; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索表 Mapper |
||||||
|
*/ |
||||||
|
public interface MemberClueMapper extends BaseDaoMapper<MemberClue> { |
||||||
|
|
||||||
|
/** |
||||||
|
* 按线索来源统计每种来源的线索总数。 |
||||||
|
* |
||||||
|
* @return 线索来源维度的线索总数列表 |
||||||
|
*/ |
||||||
|
List<ClueSourceCountVo> selectClueTotalBySource(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 统计线索总数(不分来源,全量一行)。 |
||||||
|
* |
||||||
|
* @return 线索总数 |
||||||
|
*/ |
||||||
|
Long selectClueTotalCount(); |
||||||
|
} |
||||||
@ -0,0 +1,195 @@ |
|||||||
|
package apelet.association.model; |
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType; |
||||||
|
import com.baomidou.mybatisplus.annotation.TableField; |
||||||
|
import com.baomidou.mybatisplus.annotation.TableId; |
||||||
|
import com.baomidou.mybatisplus.annotation.TableName; |
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
import java.io.Serializable; |
||||||
|
import java.math.BigDecimal; |
||||||
|
import java.util.Date; |
||||||
|
|
||||||
|
/** |
||||||
|
* 商机表 business_opportunities |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
@TableName("business_opportunities") |
||||||
|
public class BusinessOpportunities implements Serializable { |
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L; |
||||||
|
|
||||||
|
/** |
||||||
|
* 主键ID |
||||||
|
*/ |
||||||
|
@TableId(value = "id", type = IdType.ASSIGN_ID) |
||||||
|
private Long id; |
||||||
|
|
||||||
|
/** |
||||||
|
* 创建人登录名称 |
||||||
|
*/ |
||||||
|
@TableField("create_user_id") |
||||||
|
private String createUserId; |
||||||
|
|
||||||
|
/** |
||||||
|
* 创建日期 |
||||||
|
*/ |
||||||
|
@TableField("create_time") |
||||||
|
private Date createTime; |
||||||
|
|
||||||
|
/** |
||||||
|
* 更新人登录名称 |
||||||
|
*/ |
||||||
|
@TableField("update_user_id") |
||||||
|
private String updateUserId; |
||||||
|
|
||||||
|
/** |
||||||
|
* 更新日期 |
||||||
|
*/ |
||||||
|
@TableField("update_time") |
||||||
|
private Date updateTime; |
||||||
|
|
||||||
|
/** |
||||||
|
* 逻辑删除标记(1: 正常 -1: 已删除) |
||||||
|
*/ |
||||||
|
@TableField("deleted_flag") |
||||||
|
private Integer deletedFlag; |
||||||
|
|
||||||
|
/** |
||||||
|
* 商机编号 |
||||||
|
*/ |
||||||
|
@TableField("number") |
||||||
|
private String number; |
||||||
|
|
||||||
|
/** |
||||||
|
* 商机名称 |
||||||
|
*/ |
||||||
|
@TableField("name") |
||||||
|
private String name; |
||||||
|
|
||||||
|
/** |
||||||
|
* 流程状态 |
||||||
|
*/ |
||||||
|
@TableField("flow_status") |
||||||
|
private Integer flowStatus; |
||||||
|
|
||||||
|
/** |
||||||
|
* 流程最新状态 |
||||||
|
*/ |
||||||
|
@TableField("flow_approval_status") |
||||||
|
private Integer flowApprovalStatus; |
||||||
|
|
||||||
|
/** |
||||||
|
* 流程实例id |
||||||
|
*/ |
||||||
|
@TableField("pro_ins_id") |
||||||
|
private String proInsId; |
||||||
|
|
||||||
|
/** |
||||||
|
* 单据状态 |
||||||
|
*/ |
||||||
|
@TableField("billstatus") |
||||||
|
private String billstatus; |
||||||
|
|
||||||
|
/** |
||||||
|
* 公司 |
||||||
|
*/ |
||||||
|
@TableField("org") |
||||||
|
private Integer org; |
||||||
|
|
||||||
|
/** |
||||||
|
* 来源单据ID |
||||||
|
*/ |
||||||
|
@TableField("srcbillid") |
||||||
|
private Integer srcbillid; |
||||||
|
|
||||||
|
/** |
||||||
|
* 来源单据编码 |
||||||
|
*/ |
||||||
|
@TableField("srcbillnumber") |
||||||
|
private Integer srcbillnumber; |
||||||
|
|
||||||
|
/** |
||||||
|
* 来源分录Id |
||||||
|
*/ |
||||||
|
@TableField("srcentryid") |
||||||
|
private Integer srcentryid; |
||||||
|
|
||||||
|
/** |
||||||
|
* 单位ID |
||||||
|
*/ |
||||||
|
@TableField("unit_id") |
||||||
|
private String unitId; |
||||||
|
|
||||||
|
/** |
||||||
|
* 寻求类型 |
||||||
|
*/ |
||||||
|
@TableField("seek_type") |
||||||
|
private String seekType; |
||||||
|
|
||||||
|
/** |
||||||
|
* 寻求信息 |
||||||
|
*/ |
||||||
|
@TableField("seek_info") |
||||||
|
private String seekInfo; |
||||||
|
|
||||||
|
/** |
||||||
|
* 阶段表现(字典: 5表示赢单) |
||||||
|
*/ |
||||||
|
@TableField("stage_manifestation") |
||||||
|
private String stageManifestation; |
||||||
|
|
||||||
|
/** |
||||||
|
* 预计成交金额 |
||||||
|
*/ |
||||||
|
@TableField("predicted_price") |
||||||
|
private BigDecimal predictedPrice; |
||||||
|
|
||||||
|
/** |
||||||
|
* 预计成交日期 |
||||||
|
*/ |
||||||
|
@TableField("predicted_signdate") |
||||||
|
private Date predictedSigndate; |
||||||
|
|
||||||
|
/** |
||||||
|
* 下一步计划 |
||||||
|
*/ |
||||||
|
@TableField("next_plan") |
||||||
|
private String nextPlan; |
||||||
|
|
||||||
|
/** |
||||||
|
* 商机类型 |
||||||
|
*/ |
||||||
|
@TableField("clue_type") |
||||||
|
private String clueType; |
||||||
|
|
||||||
|
/** |
||||||
|
* 开始时间 |
||||||
|
*/ |
||||||
|
@TableField("start_time") |
||||||
|
private Date startTime; |
||||||
|
|
||||||
|
/** |
||||||
|
* 结束时间 |
||||||
|
*/ |
||||||
|
@TableField("end_time") |
||||||
|
private Date endTime; |
||||||
|
|
||||||
|
/** |
||||||
|
* 说明事项 |
||||||
|
*/ |
||||||
|
@TableField("explanation_matters") |
||||||
|
private String explanationMatters; |
||||||
|
|
||||||
|
/** |
||||||
|
* 关联线索ID |
||||||
|
*/ |
||||||
|
@TableField("clue_id") |
||||||
|
private Long clueId; |
||||||
|
|
||||||
|
/** |
||||||
|
* 实际成交日期 |
||||||
|
*/ |
||||||
|
@TableField("actual_signdate") |
||||||
|
private Date actualSigndate; |
||||||
|
} |
||||||
@ -0,0 +1,158 @@ |
|||||||
|
package apelet.association.model; |
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType; |
||||||
|
import com.baomidou.mybatisplus.annotation.TableField; |
||||||
|
import com.baomidou.mybatisplus.annotation.TableId; |
||||||
|
import com.baomidou.mybatisplus.annotation.TableName; |
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
import java.io.Serializable; |
||||||
|
import java.util.Date; |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索表 member_clue |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
@TableName("member_clue") |
||||||
|
public class MemberClue implements Serializable { |
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L; |
||||||
|
|
||||||
|
/** |
||||||
|
* 主键ID |
||||||
|
*/ |
||||||
|
@TableId(value = "id", type = IdType.ASSIGN_ID) |
||||||
|
private Long id; |
||||||
|
|
||||||
|
/** |
||||||
|
* 创建人登录名称 |
||||||
|
*/ |
||||||
|
@TableField("create_user_id") |
||||||
|
private String createUserId; |
||||||
|
|
||||||
|
/** |
||||||
|
* 创建日期 |
||||||
|
*/ |
||||||
|
@TableField("create_time") |
||||||
|
private Date createTime; |
||||||
|
|
||||||
|
/** |
||||||
|
* 更新人登录名称 |
||||||
|
*/ |
||||||
|
@TableField("update_user_id") |
||||||
|
private String updateUserId; |
||||||
|
|
||||||
|
/** |
||||||
|
* 更新日期 |
||||||
|
*/ |
||||||
|
@TableField("update_time") |
||||||
|
private Date updateTime; |
||||||
|
|
||||||
|
/** |
||||||
|
* 逻辑删除标记(1: 正常 -1: 已删除) |
||||||
|
*/ |
||||||
|
@TableField("deleted_flag") |
||||||
|
private Integer deletedFlag; |
||||||
|
|
||||||
|
/** |
||||||
|
* 单位ID |
||||||
|
*/ |
||||||
|
@TableField("unit_id") |
||||||
|
private Long unitId; |
||||||
|
|
||||||
|
/** |
||||||
|
* 寻求类型 |
||||||
|
*/ |
||||||
|
@TableField("seek_type") |
||||||
|
private String seekType; |
||||||
|
|
||||||
|
/** |
||||||
|
* 寻求信息 |
||||||
|
*/ |
||||||
|
@TableField("seek_info") |
||||||
|
private String seekInfo; |
||||||
|
|
||||||
|
/** |
||||||
|
* 下一步计划 |
||||||
|
*/ |
||||||
|
@TableField("next_plan") |
||||||
|
private String nextPlan; |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索编号 |
||||||
|
*/ |
||||||
|
@TableField("number") |
||||||
|
private String number; |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索名称 |
||||||
|
*/ |
||||||
|
@TableField("name") |
||||||
|
private String name; |
||||||
|
|
||||||
|
/** |
||||||
|
* 流程状态 |
||||||
|
*/ |
||||||
|
@TableField("flow_status") |
||||||
|
private Integer flowStatus; |
||||||
|
|
||||||
|
/** |
||||||
|
* 流程最新状态 |
||||||
|
*/ |
||||||
|
@TableField("flow_approval_status") |
||||||
|
private Integer flowApprovalStatus; |
||||||
|
|
||||||
|
/** |
||||||
|
* 流程实例id |
||||||
|
*/ |
||||||
|
@TableField("pro_ins_id") |
||||||
|
private String proInsId; |
||||||
|
|
||||||
|
/** |
||||||
|
* 单据状态 |
||||||
|
*/ |
||||||
|
@TableField("billstatus") |
||||||
|
private String billstatus; |
||||||
|
|
||||||
|
/** |
||||||
|
* 公司 |
||||||
|
*/ |
||||||
|
@TableField("org") |
||||||
|
private Integer org; |
||||||
|
|
||||||
|
/** |
||||||
|
* 来源单据ID |
||||||
|
*/ |
||||||
|
@TableField("srcbillid") |
||||||
|
private Integer srcbillid; |
||||||
|
|
||||||
|
/** |
||||||
|
* 来源单据编码 |
||||||
|
*/ |
||||||
|
@TableField("srcbillnumber") |
||||||
|
private Integer srcbillnumber; |
||||||
|
|
||||||
|
/** |
||||||
|
* 来源分录Id |
||||||
|
*/ |
||||||
|
@TableField("srcentryid") |
||||||
|
private Integer srcentryid; |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索类型 |
||||||
|
*/ |
||||||
|
@TableField("clue_type") |
||||||
|
private String clueType; |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索来源(字典: 1展会论坛 2电话咨询 3营销号 4其他) |
||||||
|
*/ |
||||||
|
@TableField("source") |
||||||
|
private Integer source; |
||||||
|
|
||||||
|
/** |
||||||
|
* 状态 |
||||||
|
*/ |
||||||
|
@TableField("status") |
||||||
|
private String status; |
||||||
|
} |
||||||
@ -0,0 +1,28 @@ |
|||||||
|
package apelet.association.service; |
||||||
|
|
||||||
|
import apelet.association.vo.ClueStatSummaryVo; |
||||||
|
import apelet.association.vo.ClueTransformStatVo; |
||||||
|
import apelet.common.core.object.MyPageData; |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索转化统计 Service |
||||||
|
*/ |
||||||
|
public interface ClueStatService { |
||||||
|
|
||||||
|
/** |
||||||
|
* 查询按线索来源分组的线索转化统计数据(固定返回4种来源的行),并做内存分页包装。 |
||||||
|
* |
||||||
|
* @param pageNum 页码,从 1 开始 |
||||||
|
* @param pageSize 每页条数 |
||||||
|
* @return 线索转化统计分页数据 |
||||||
|
*/ |
||||||
|
MyPageData<ClueTransformStatVo> getClueTransformStat(int pageNum, int pageSize); |
||||||
|
|
||||||
|
/** |
||||||
|
* 查询线索转化统计整体汇总数据(不分线索来源,全量一行)。 |
||||||
|
* 指标:转化商机金额、赢单商机金额、已转商机成交金额、线索总数、线索转化数、线索转化率、商机转化率。 |
||||||
|
* |
||||||
|
* @return 整体汇总统计结果 |
||||||
|
*/ |
||||||
|
ClueStatSummaryVo getClueStatSummary(); |
||||||
|
} |
||||||
@ -0,0 +1,203 @@ |
|||||||
|
package apelet.association.service.impl; |
||||||
|
|
||||||
|
import apelet.association.dao.BusinessOpportunitiesMapper; |
||||||
|
import apelet.association.dao.MemberClueMapper; |
||||||
|
import apelet.association.service.ClueStatService; |
||||||
|
import apelet.association.vo.ClueSourceCountVo; |
||||||
|
import apelet.association.vo.ClueStatSummaryVo; |
||||||
|
import apelet.association.vo.ClueTransformStatVo; |
||||||
|
import apelet.association.vo.DealTransformStatVo; |
||||||
|
import apelet.association.vo.OppTransformStatVo; |
||||||
|
import apelet.common.core.object.MyPageData; |
||||||
|
import apelet.common.core.util.MyPageUtil; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
import java.math.BigDecimal; |
||||||
|
import java.math.RoundingMode; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索转化统计 Service 实现 |
||||||
|
*/ |
||||||
|
@Service |
||||||
|
public class ClueStatServiceImpl implements ClueStatService { |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索来源字典:1展会论坛 2电话咨询 3营销号 4其他 |
||||||
|
* 与在线表单 zz_online_dict 中的"线索来源"字典保持一致。 |
||||||
|
*/ |
||||||
|
private static final Map<Integer, String> SOURCE_MAP = new HashMap<>(); |
||||||
|
|
||||||
|
static { |
||||||
|
SOURCE_MAP.put(1, "展会论坛"); |
||||||
|
SOURCE_MAP.put(2, "电话咨询"); |
||||||
|
SOURCE_MAP.put(3, "营销号"); |
||||||
|
SOURCE_MAP.put(4, "其他"); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 赢单阶段值:stage_manifestation = 5 表示赢单 |
||||||
|
*/ |
||||||
|
private static final String WIN_STAGE = "5"; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private MemberClueMapper memberClueMapper; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private BusinessOpportunitiesMapper businessOpportunitiesMapper; |
||||||
|
|
||||||
|
@Override |
||||||
|
public MyPageData<ClueTransformStatVo> getClueTransformStat(int pageNum, int pageSize) { |
||||||
|
// 0. 兜底处理非法分页参数(页码从1开始、每页至少1条)
|
||||||
|
int safePageNum = Math.max(pageNum, 1); |
||||||
|
int safePageSize = Math.max(pageSize, 1); |
||||||
|
|
||||||
|
// 1. 查询每种来源的线索总数
|
||||||
|
List<ClueSourceCountVo> clueTotalList = memberClueMapper.selectClueTotalBySource(); |
||||||
|
Map<Integer, Long> clueTotalMap = new HashMap<>(); |
||||||
|
for (ClueSourceCountVo item : clueTotalList) { |
||||||
|
clueTotalMap.put(item.getSource(), item.getClueTotalCount()); |
||||||
|
} |
||||||
|
|
||||||
|
// 2. 查询每种来源的商机转化统计(转化商机数、赢单商机数、赢单商机金额、商机转化金额)
|
||||||
|
List<OppTransformStatVo> oppStatList = businessOpportunitiesMapper.selectOppTransformStatBySource(); |
||||||
|
Map<Integer, OppTransformStatVo> oppStatMap = new HashMap<>(); |
||||||
|
for (OppTransformStatVo item : oppStatList) { |
||||||
|
oppStatMap.put(item.getSource(), item); |
||||||
|
} |
||||||
|
|
||||||
|
// 3. 查询每种来源的成交统计(已转商机成交数、已转商机成交金额)
|
||||||
|
// 当前合同表 contract 暂无数据,暂以报价单 status='3'(通过,即已成合同)作为成交口径
|
||||||
|
List<DealTransformStatVo> dealStatList = businessOpportunitiesMapper.selectDealStatBySource(); |
||||||
|
Map<Integer, DealTransformStatVo> dealStatMap = new HashMap<>(); |
||||||
|
for (DealTransformStatVo item : dealStatList) { |
||||||
|
dealStatMap.put(item.getSource(), item); |
||||||
|
} |
||||||
|
|
||||||
|
// 4. 固定返回4种来源的行,组装统计结果
|
||||||
|
List<ClueTransformStatVo> resultList = new ArrayList<>(SOURCE_MAP.size()); |
||||||
|
for (Map.Entry<Integer, String> entry : SOURCE_MAP.entrySet()) { |
||||||
|
Integer source = entry.getKey(); |
||||||
|
String sourceName = entry.getValue(); |
||||||
|
|
||||||
|
Long clueTotalCount = clueTotalMap.getOrDefault(source, 0L); |
||||||
|
OppTransformStatVo oppStat = oppStatMap.get(source); |
||||||
|
long oppCount = oppStat == null ? 0L : oppStat.getOppCount(); |
||||||
|
long winOppCount = oppStat == null ? 0L : oppStat.getWinOppCount(); |
||||||
|
BigDecimal winOppAmount = oppStat == null ? BigDecimal.ZERO : oppStat.getWinOppAmount(); |
||||||
|
BigDecimal oppTransformAmount = oppStat == null ? BigDecimal.ZERO : oppStat.getOppTransformAmount(); |
||||||
|
|
||||||
|
DealTransformStatVo dealStat = dealStatMap.get(source); |
||||||
|
long dealCount = dealStat == null ? 0L : dealStat.getDealCount(); |
||||||
|
BigDecimal dealAmount = dealStat == null ? BigDecimal.ZERO : dealStat.getDealAmount(); |
||||||
|
|
||||||
|
ClueTransformStatVo vo = new ClueTransformStatVo(); |
||||||
|
vo.setSource(source); |
||||||
|
vo.setSourceName(sourceName); |
||||||
|
// 线索转化数 = 转化商机数(该来源关联出的商机数量)
|
||||||
|
vo.setClueTransformCount(oppCount); |
||||||
|
// 线索总数
|
||||||
|
vo.setClueTotalCount(clueTotalCount); |
||||||
|
// 线索转化率 = 线索转化数 / 线索总数
|
||||||
|
vo.setClueTransformRate(calcRate(oppCount, clueTotalCount)); |
||||||
|
// 转化商机数 = 线索转化数
|
||||||
|
vo.setTransformOppCount(oppCount); |
||||||
|
// 赢单商机数
|
||||||
|
vo.setWinOppCount(winOppCount); |
||||||
|
// 赢单商机金额
|
||||||
|
vo.setWinOppAmount(winOppAmount); |
||||||
|
// 商机转化金额 = 该来源所有商机的金额合计
|
||||||
|
vo.setOppTransformAmount(oppTransformAmount); |
||||||
|
// 商机转化率 = 赢单商机数 / 转化商机数
|
||||||
|
vo.setOppTransformRate(calcRate(winOppCount, oppCount)); |
||||||
|
// 已转商机成交数 = 线索转商机转合同的数量
|
||||||
|
vo.setDealCount(dealCount); |
||||||
|
// 已转商机成交金额 = 线索转商机转合同的金额合计
|
||||||
|
vo.setDealAmount(dealAmount); |
||||||
|
// 已转商机成交率 = 已转商机成交数 / 赢单商机数
|
||||||
|
vo.setDealRate(calcRate(dealCount, winOppCount)); |
||||||
|
|
||||||
|
resultList.add(vo); |
||||||
|
} |
||||||
|
|
||||||
|
// 5. 对统计结果做内存分页并包装返回(总行数为固定来源数,最多 4 行)
|
||||||
|
return paginate(resultList, safePageNum, safePageSize); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 对统计结果列表做内存分页,并包装为 {@link MyPageData}。 |
||||||
|
* 分页在内存中完成(该接口固定返回少量汇总行,无 SQL 分页的必要)。 |
||||||
|
* |
||||||
|
* @param list 全量统计结果 |
||||||
|
* @param pageNum 页码,从 1 开始 |
||||||
|
* @param pageSize 每页条数 |
||||||
|
* @return 分页包装数据 |
||||||
|
*/ |
||||||
|
private MyPageData<ClueTransformStatVo> paginate(List<ClueTransformStatVo> list, int pageNum, int pageSize) { |
||||||
|
int total = list.size(); |
||||||
|
int fromIndex = (pageNum - 1) * pageSize; |
||||||
|
// 起始位置超出总行数时返回空列表,但保留总数供前端分页组件使用
|
||||||
|
if (fromIndex >= total) { |
||||||
|
return MyPageUtil.makeResponseData(new ArrayList<>(), (long) total); |
||||||
|
} |
||||||
|
int toIndex = Math.min(fromIndex + pageSize, total); |
||||||
|
return MyPageUtil.makeResponseData(new ArrayList<>(list.subList(fromIndex, toIndex)), (long) total); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public ClueStatSummaryVo getClueStatSummary() { |
||||||
|
// 1. 线索总数(全量)
|
||||||
|
Long clueTotalCount = memberClueMapper.selectClueTotalCount(); |
||||||
|
long clueTotal = clueTotalCount == null ? 0L : clueTotalCount; |
||||||
|
|
||||||
|
// 2. 商机转化整体统计(转化商机数、赢单商机数、赢单商机金额、商机转化金额)
|
||||||
|
OppTransformStatVo oppStat = businessOpportunitiesMapper.selectOppSummary(); |
||||||
|
long oppCount = oppStat == null ? 0L : oppStat.getOppCount(); |
||||||
|
long winOppCount = oppStat == null ? 0L : oppStat.getWinOppCount(); |
||||||
|
BigDecimal winOppAmount = oppStat == null ? BigDecimal.ZERO : oppStat.getWinOppAmount(); |
||||||
|
BigDecimal oppTransformAmount = oppStat == null ? BigDecimal.ZERO : oppStat.getOppTransformAmount(); |
||||||
|
|
||||||
|
// 3. 成交整体统计(已转商机成交金额)
|
||||||
|
DealTransformStatVo dealStat = businessOpportunitiesMapper.selectDealSummary(); |
||||||
|
BigDecimal dealAmount = dealStat == null ? BigDecimal.ZERO : dealStat.getDealAmount(); |
||||||
|
|
||||||
|
ClueStatSummaryVo vo = new ClueStatSummaryVo(); |
||||||
|
// 转化商机金额(所有关联到线索的商机金额合计)
|
||||||
|
vo.setOppTransformAmount(oppTransformAmount); |
||||||
|
// 赢单商机金额
|
||||||
|
vo.setWinOppAmount(winOppAmount); |
||||||
|
// 已转商机成交金额(线索转商机转合同的金额合计)
|
||||||
|
vo.setDealAmount(dealAmount); |
||||||
|
// 线索总数
|
||||||
|
vo.setClueTotalCount(clueTotal); |
||||||
|
// 线索转化数 = 转化商机数(关联到线索的商机数量)
|
||||||
|
vo.setClueTransformCount(oppCount); |
||||||
|
// 线索转化率 = 线索转化数 / 线索总数
|
||||||
|
vo.setClueTransformRate(calcRate(oppCount, clueTotal)); |
||||||
|
// 商机转化率 = 赢单商机数 / 转化商机数
|
||||||
|
vo.setOppTransformRate(calcRate(winOppCount, oppCount)); |
||||||
|
return vo; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 计算转化率,返回保留两位小数的百分比字符串(如 66.67%)。 |
||||||
|
* 分子或分母为空、或分母为 0 时返回 null,表示无法计算。 |
||||||
|
* |
||||||
|
* @param numerator 分子 |
||||||
|
* @param denominator 分母 |
||||||
|
* @return 百分比字符串,无法计算时返回 null |
||||||
|
*/ |
||||||
|
private String calcRate(long numerator, long denominator) { |
||||||
|
if (denominator == 0L) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
BigDecimal rate = BigDecimal.valueOf(numerator) |
||||||
|
.multiply(BigDecimal.valueOf(100)) |
||||||
|
.divide(BigDecimal.valueOf(denominator), 2, RoundingMode.HALF_UP); |
||||||
|
return rate.setScale(2).stripTrailingZeros().toPlainString() + "%"; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,20 @@ |
|||||||
|
package apelet.association.vo; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索来源对应的线索总数统计结果(中间结果) |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class ClueSourceCountVo { |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索来源(字典: 1展会论坛 2电话咨询 3营销号 4其他) |
||||||
|
*/ |
||||||
|
private Integer source; |
||||||
|
|
||||||
|
/** |
||||||
|
* 该来源的线索总数 |
||||||
|
*/ |
||||||
|
private Long clueTotalCount; |
||||||
|
} |
||||||
@ -0,0 +1,56 @@ |
|||||||
|
package apelet.association.vo; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
import java.math.BigDecimal; |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索转化统计整体汇总结果对象(不分线索来源,全量一行) |
||||||
|
* <p> |
||||||
|
* 指标口径: |
||||||
|
* - 转化商机金额:所有关联到线索的商机 predicted_price 合计 |
||||||
|
* - 赢单商机金额:stage_manifestation=5 的商机 predicted_price 合计 |
||||||
|
* - 已转商机成交金额:报价单 status='3'(通过,即已成合同)的 qty 合计 |
||||||
|
* - 线索总数:member_clue 总条数 |
||||||
|
* - 线索转化数:关联到线索的商机数(线索→商机) |
||||||
|
* - 线索转化率:线索转化数 / 线索总数 |
||||||
|
* - 商机转化率:赢单商机数 / 转化商机数 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class ClueStatSummaryVo { |
||||||
|
|
||||||
|
/** |
||||||
|
* 转化商机金额(所有关联到线索的商机 predicted_price 合计) |
||||||
|
*/ |
||||||
|
private BigDecimal oppTransformAmount; |
||||||
|
|
||||||
|
/** |
||||||
|
* 赢单商机金额(stage_manifestation=5 的 predicted_price 合计) |
||||||
|
*/ |
||||||
|
private BigDecimal winOppAmount; |
||||||
|
|
||||||
|
/** |
||||||
|
* 已转商机成交金额(线索→商机→合同的金额合计,当前以报价单 status='3' 作为成交口径) |
||||||
|
*/ |
||||||
|
private BigDecimal dealAmount; |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索总数 |
||||||
|
*/ |
||||||
|
private Long clueTotalCount; |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索转化数(关联到线索的商机数) |
||||||
|
*/ |
||||||
|
private Long clueTransformCount; |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索转化率(线索转化数 / 线索总数,百分比字符串) |
||||||
|
*/ |
||||||
|
private String clueTransformRate; |
||||||
|
|
||||||
|
/** |
||||||
|
* 商机转化率(赢单商机数 / 转化商机数,百分比字符串) |
||||||
|
*/ |
||||||
|
private String oppTransformRate; |
||||||
|
} |
||||||
@ -0,0 +1,82 @@ |
|||||||
|
package apelet.association.vo; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
import java.math.BigDecimal; |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索转化统计结果对象(按线索来源维度展示每种线索的转化数据) |
||||||
|
* <p> |
||||||
|
* 对应表头: |
||||||
|
* 1 线索来源 / 2 线索转化数 / 3 线索总数 / 4 线索转化率 / 5 转化商机数 / |
||||||
|
* 6 赢单商机数 / 7 赢单商机金额 / 8 商机转化金额 / 9 商机转化率 / |
||||||
|
* 10 已转商机成交数 / 11 已转商机成交金额 / 12 已转商机成交率 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class ClueTransformStatVo { |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索来源key(字典: 1展会论坛 2电话咨询 3营销号 4其他) |
||||||
|
*/ |
||||||
|
private Integer source; |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索来源中文名 |
||||||
|
*/ |
||||||
|
private String sourceName; |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索转化数(该来源关联出的商机数量) |
||||||
|
*/ |
||||||
|
private Long clueTransformCount; |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索总数(该来源的线索数量) |
||||||
|
*/ |
||||||
|
private Long clueTotalCount; |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索转化率(线索转化数 / 线索总数,百分比字符串) |
||||||
|
*/ |
||||||
|
private String clueTransformRate; |
||||||
|
|
||||||
|
/** |
||||||
|
* 转化商机数(= 线索转化数) |
||||||
|
*/ |
||||||
|
private Long transformOppCount; |
||||||
|
|
||||||
|
/** |
||||||
|
* 赢单商机数(stage_manifestation=5 的商机数量) |
||||||
|
*/ |
||||||
|
private Long winOppCount; |
||||||
|
|
||||||
|
/** |
||||||
|
* 赢单商机金额(stage_manifestation=5 的 predicted_price 合计) |
||||||
|
*/ |
||||||
|
private BigDecimal winOppAmount; |
||||||
|
|
||||||
|
/** |
||||||
|
* 商机转化金额(该来源线索关联出的所有商机 predicted_price 合计,与是否赢单无关) |
||||||
|
*/ |
||||||
|
private BigDecimal oppTransformAmount; |
||||||
|
|
||||||
|
/** |
||||||
|
* 商机转化率(赢单商机数 / 转化商机数,百分比字符串) |
||||||
|
*/ |
||||||
|
private String oppTransformRate; |
||||||
|
|
||||||
|
/** |
||||||
|
* 已转商机成交数(线索→商机→合同的数量,当前以报价单 status='3' 作为成交口径) |
||||||
|
*/ |
||||||
|
private Long dealCount; |
||||||
|
|
||||||
|
/** |
||||||
|
* 已转商机成交金额(线索→商机→合同的金额合计,报价单 status='3' 的 qty 求和) |
||||||
|
*/ |
||||||
|
private BigDecimal dealAmount; |
||||||
|
|
||||||
|
/** |
||||||
|
* 已转商机成交率(已转商机成交数 / 赢单商机数,百分比字符串) |
||||||
|
*/ |
||||||
|
private String dealRate; |
||||||
|
} |
||||||
@ -0,0 +1,31 @@ |
|||||||
|
package apelet.association.vo; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
import java.math.BigDecimal; |
||||||
|
|
||||||
|
/** |
||||||
|
* 按线索来源维度统计的"线索→商机→合同"成交中间结果 |
||||||
|
* <p> |
||||||
|
* 说明:合同表 contract 暂未接入数据(报价单反写逻辑未做), |
||||||
|
* 当前以报价单 status = '3'(通过,即已成合同)作为成交口径, |
||||||
|
* 报价单通过 srcbillid 关联商机 business_opportunities。 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class DealTransformStatVo { |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索来源(字典: 1展会论坛 2电话咨询 3营销号 4其他) |
||||||
|
*/ |
||||||
|
private Integer source; |
||||||
|
|
||||||
|
/** |
||||||
|
* 该来源已转商机成交数(报价单 status='3' 的数量,即线索→商机→合同的数量) |
||||||
|
*/ |
||||||
|
private Long dealCount; |
||||||
|
|
||||||
|
/** |
||||||
|
* 该来源已转商机成交金额合计(报价单 status='3' 的 qty 求和,即合同金额合计) |
||||||
|
*/ |
||||||
|
private BigDecimal dealAmount; |
||||||
|
} |
||||||
@ -0,0 +1,37 @@ |
|||||||
|
package apelet.association.vo; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
import java.math.BigDecimal; |
||||||
|
|
||||||
|
/** |
||||||
|
* 按线索来源维度统计的商机转化中间结果 |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class OppTransformStatVo { |
||||||
|
|
||||||
|
/** |
||||||
|
* 线索来源(字典: 1展会论坛 2电话咨询 3营销号 4其他) |
||||||
|
*/ |
||||||
|
private Integer source; |
||||||
|
|
||||||
|
/** |
||||||
|
* 该来源转化的商机数(商机关联线索后按来源分组) |
||||||
|
*/ |
||||||
|
private Long oppCount; |
||||||
|
|
||||||
|
/** |
||||||
|
* 该来源赢单商机数(stage_manifestation=5) |
||||||
|
*/ |
||||||
|
private Long winOppCount; |
||||||
|
|
||||||
|
/** |
||||||
|
* 该来源赢单商机金额合计(stage_manifestation=5 的 predicted_price 求和) |
||||||
|
*/ |
||||||
|
private BigDecimal winOppAmount; |
||||||
|
|
||||||
|
/** |
||||||
|
* 该来源商机转化金额合计(该来源线索关联出的所有商机 predicted_price 求和,与是否赢单无关) |
||||||
|
*/ |
||||||
|
private BigDecimal oppTransformAmount; |
||||||
|
} |
||||||
@ -0,0 +1,94 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" |
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||||
|
<mapper namespace="apelet.association.dao.BusinessOpportunitiesMapper"> |
||||||
|
|
||||||
|
<!-- |
||||||
|
按线索来源统计商机转化数据: |
||||||
|
- oppCount 转化商机数(该来源关联出的商机总数) |
||||||
|
- winOppCount 赢单商机数(stage_manifestation = '5') |
||||||
|
- winOppAmount 赢单商机金额(stage_manifestation = '5' 的 predicted_price 合计) |
||||||
|
- oppTransformAmount 商机转化金额(该来源关联出的所有商机 predicted_price 合计,与是否赢单无关) |
||||||
|
商机通过 clue_id 关联线索表 member_clue,按线索来源 source 分组统计。 |
||||||
|
--> |
||||||
|
<select id="selectOppTransformStatBySource" |
||||||
|
resultType="apelet.association.vo.OppTransformStatVo"> |
||||||
|
SELECT |
||||||
|
mc.source AS source, |
||||||
|
COUNT(bo.id) AS oppCount, |
||||||
|
SUM(CASE WHEN bo.stage_manifestation = '5' THEN 1 ELSE 0 END) AS winOppCount, |
||||||
|
COALESCE(SUM(CASE WHEN bo.stage_manifestation = '5' THEN bo.predicted_price ELSE 0 END), 0) AS winOppAmount, |
||||||
|
COALESCE(SUM(bo.predicted_price), 0) AS oppTransformAmount |
||||||
|
FROM business_opportunities bo |
||||||
|
INNER JOIN member_clue mc ON bo.clue_id = mc.id |
||||||
|
WHERE bo.deleted_flag = 1 |
||||||
|
AND mc.deleted_flag = 1 |
||||||
|
GROUP BY mc.source |
||||||
|
</select> |
||||||
|
|
||||||
|
<!-- |
||||||
|
按线索来源统计"线索→商机→合同"成交数据: |
||||||
|
- dealCount 已转商机成交数(报价单 status = '3' 的数量) |
||||||
|
- dealAmount 已转商机成交金额(报价单 status = '3' 的 qty 合计) |
||||||
|
说明:合同表 contract 暂无数据(报价单反写逻辑未做), |
||||||
|
暂以报价单 status = '3'(通过,即已成合同)作为成交口径。 |
||||||
|
报价单 quotation 通过 srcbillid 关联商机 business_opportunities, |
||||||
|
商机再通过 clue_id 关联线索表 member_clue,按线索来源 source 分组统计。 |
||||||
|
--> |
||||||
|
<select id="selectDealStatBySource" |
||||||
|
resultType="apelet.association.vo.DealTransformStatVo"> |
||||||
|
SELECT |
||||||
|
mc.source AS source, |
||||||
|
COUNT(DISTINCT q.id) AS dealCount, |
||||||
|
COALESCE(SUM(q.qty), 0) AS dealAmount |
||||||
|
FROM quotation q |
||||||
|
INNER JOIN business_opportunities bo ON q.srcbillid = bo.id |
||||||
|
INNER JOIN member_clue mc ON bo.clue_id = mc.id |
||||||
|
WHERE q.status = '3' |
||||||
|
AND q.deleted_flag = 1 |
||||||
|
AND bo.deleted_flag = 1 |
||||||
|
AND mc.deleted_flag = 1 |
||||||
|
GROUP BY mc.source |
||||||
|
</select> |
||||||
|
|
||||||
|
<!-- |
||||||
|
整体汇总统计商机转化数据(不分线索来源,返回单行): |
||||||
|
- oppCount 转化商机数(关联到线索的商机总数) |
||||||
|
- winOppCount 赢单商机数(stage_manifestation = '5') |
||||||
|
- winOppAmount 赢单商机金额(stage_manifestation = '5' 的 predicted_price 合计) |
||||||
|
- oppTransformAmount 商机转化金额(所有商机 predicted_price 合计,与是否赢单无关) |
||||||
|
--> |
||||||
|
<select id="selectOppSummary" |
||||||
|
resultType="apelet.association.vo.OppTransformStatVo"> |
||||||
|
SELECT |
||||||
|
COUNT(bo.id) AS oppCount, |
||||||
|
COALESCE(SUM(CASE WHEN bo.stage_manifestation = '5' THEN 1 ELSE 0 END), 0) AS winOppCount, |
||||||
|
COALESCE(SUM(CASE WHEN bo.stage_manifestation = '5' THEN bo.predicted_price ELSE 0 END), 0) AS winOppAmount, |
||||||
|
COALESCE(SUM(bo.predicted_price), 0) AS oppTransformAmount |
||||||
|
FROM business_opportunities bo |
||||||
|
INNER JOIN member_clue mc ON bo.clue_id = mc.id |
||||||
|
WHERE bo.deleted_flag = 1 |
||||||
|
AND mc.deleted_flag = 1 |
||||||
|
</select> |
||||||
|
|
||||||
|
<!-- |
||||||
|
整体汇总统计"线索→商机→合同"成交数据(不分线索来源,返回单行): |
||||||
|
- dealCount 已转商机成交数(报价单 status = '3' 的数量) |
||||||
|
- dealAmount 已转商机成交金额(报价单 status = '3' 的 qty 合计) |
||||||
|
成交口径同 selectDealStatBySource(合同表 contract 暂无数据,暂以报价单 status='3' 作为成交口径)。 |
||||||
|
--> |
||||||
|
<select id="selectDealSummary" |
||||||
|
resultType="apelet.association.vo.DealTransformStatVo"> |
||||||
|
SELECT |
||||||
|
COUNT(DISTINCT q.id) AS dealCount, |
||||||
|
COALESCE(SUM(q.qty), 0) AS dealAmount |
||||||
|
FROM quotation q |
||||||
|
INNER JOIN business_opportunities bo ON q.srcbillid = bo.id |
||||||
|
INNER JOIN member_clue mc ON bo.clue_id = mc.id |
||||||
|
WHERE q.status = '3' |
||||||
|
AND q.deleted_flag = 1 |
||||||
|
AND bo.deleted_flag = 1 |
||||||
|
AND mc.deleted_flag = 1 |
||||||
|
</select> |
||||||
|
|
||||||
|
</mapper> |
||||||
@ -0,0 +1,24 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" |
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||||
|
<mapper namespace="apelet.association.dao.MemberClueMapper"> |
||||||
|
|
||||||
|
<!-- 按线索来源统计每种来源的线索总数 --> |
||||||
|
<select id="selectClueTotalBySource" |
||||||
|
resultType="apelet.association.vo.ClueSourceCountVo"> |
||||||
|
SELECT |
||||||
|
source AS source, |
||||||
|
COUNT(*) AS clueTotalCount |
||||||
|
FROM member_clue |
||||||
|
WHERE deleted_flag = 1 |
||||||
|
GROUP BY source |
||||||
|
</select> |
||||||
|
|
||||||
|
<!-- 统计线索总数(不分来源,全量一行) --> |
||||||
|
<select id="selectClueTotalCount" resultType="java.lang.Long"> |
||||||
|
SELECT COUNT(*) |
||||||
|
FROM member_clue |
||||||
|
WHERE deleted_flag = 1 |
||||||
|
</select> |
||||||
|
|
||||||
|
</mapper> |
||||||
Loading…
Reference in new issue