- 在 CrmOrderItemMapper 中添加根据订单ID列表查询订单明细的方法 - 实现 MyBatis 查询语句支持批量订单ID查询订单明细 - 修改销售报表服务类注入 CrmOrderItemMapper 依赖 - 扩展销售报表查询逻辑以包含订单明细数据 - 在销售报表 VO 中添加订单明细列表字段 - 使用流式处理和分组收集优化订单明细关联逻辑
272 lines
12 KiB
XML
272 lines
12 KiB
XML
<?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="com.klp.crm.mapper.CrmSalesReportMapper">
|
||
|
||
<!-- 通用查询条件 -->
|
||
<sql id="selectCondition">
|
||
<where>
|
||
o.del_flag = 0 AND c.del_flag = 0
|
||
<if test="bo.startTime != null">
|
||
AND DATE(o.create_time) >= #{bo.startTime}
|
||
</if>
|
||
<if test="bo.endTime != null">
|
||
AND DATE(o.create_time) <= #{bo.endTime}
|
||
</if>
|
||
<if test="bo.salesmanList != null and bo.salesmanList.size() > 0">
|
||
AND o.salesman IN
|
||
<foreach collection="bo.salesmanList" item="salesman" open="(" separator="," close=")">
|
||
#{salesman}
|
||
</foreach>
|
||
</if>
|
||
<if test="bo.customerIdList != null and bo.customerIdList.size() > 0">
|
||
AND o.customer_id IN
|
||
<foreach collection="bo.customerIdList" item="customerId" open="(" separator="," close=")">
|
||
#{customerId}
|
||
</foreach>
|
||
</if>
|
||
<if test="bo.customerLevelList != null and bo.customerLevelList.size() > 0">
|
||
AND c.customer_level IN
|
||
<foreach collection="bo.customerLevelList" item="level" open="(" separator="," close=")">
|
||
#{level}
|
||
</foreach>
|
||
</if>
|
||
<if test="bo.industryList != null and bo.industryList.size() > 0">
|
||
AND c.industry IN
|
||
<foreach collection="bo.industryList" item="industry" open="(" separator="," close=")">
|
||
#{industry}
|
||
</foreach>
|
||
</if>
|
||
<if test="bo.orderStatusList != null and bo.orderStatusList.size() > 0">
|
||
AND o.order_status IN
|
||
<foreach collection="bo.orderStatusList" item="status" open="(" separator="," close=")">
|
||
#{status}
|
||
</foreach>
|
||
</if>
|
||
<if test="bo.financeStatusList != null and bo.financeStatusList.size() > 0">
|
||
AND o.finance_status IN
|
||
<foreach collection="bo.financeStatusList" item="status" open="(" separator="," close=")">
|
||
#{status}
|
||
</foreach>
|
||
</if>
|
||
<if test="bo.orderTypeList != null and bo.orderTypeList.size() > 0">
|
||
AND o.order_type IN
|
||
<foreach collection="bo.orderTypeList" item="type" open="(" separator="," close=")">
|
||
#{type}
|
||
</foreach>
|
||
</if>
|
||
<if test="bo.minOrderAmount != null">
|
||
AND o.order_amount >= #{bo.minOrderAmount}
|
||
</if>
|
||
<if test="bo.maxOrderAmount != null">
|
||
AND o.order_amount <= #{bo.maxOrderAmount}
|
||
</if>
|
||
<if test="bo.onlyUnpaidOrders != null and bo.onlyUnpaidOrders == true">
|
||
AND o.unpaid_amount > 0
|
||
</if>
|
||
<if test="bo.companyNameKeyword != null and bo.companyNameKeyword != ''">
|
||
AND c.company_name LIKE CONCAT('%', #{bo.companyNameKeyword}, '%')
|
||
</if>
|
||
<if test="bo.orderCodeKeyword != null and bo.orderCodeKeyword != ''">
|
||
AND o.order_code LIKE CONCAT('%', #{bo.orderCodeKeyword}, '%')
|
||
</if>
|
||
<if test="bo.includeObjectionOrders != null and bo.includeObjectionOrders == false">
|
||
AND NOT EXISTS (
|
||
SELECT 1 FROM crm_sales_objection obj
|
||
WHERE obj.order_id = o.order_id AND obj.del_flag = 0
|
||
)
|
||
</if>
|
||
</where>
|
||
</sql>
|
||
|
||
<!-- 查询销售汇总统计数据 -->
|
||
<select id="selectSalesSummary" resultType="com.klp.crm.domain.vo.CrmSalesReportVo$SalesSummary">
|
||
SELECT
|
||
COUNT(o.order_id) as totalOrderCount,
|
||
COALESCE(SUM(o.order_amount), 0) as totalSalesAmount,
|
||
COUNT(CASE WHEN o.order_status = 3 THEN 1 END) as completedOrderCount,
|
||
COALESCE(SUM(CASE WHEN o.order_status = 3 THEN o.order_amount ELSE 0 END), 0) as completedSalesAmount,
|
||
COALESCE(SUM(o.unpaid_amount), 0) as totalUnpaidAmount,
|
||
COALESCE(AVG(o.order_amount), 0) as avgOrderAmount
|
||
FROM crm_order o
|
||
LEFT JOIN crm_customer c ON o.customer_id = c.customer_id
|
||
<include refid="selectCondition"/>
|
||
</select>
|
||
|
||
<!-- 查询订单明细列表 -->
|
||
<select id="selectOrderDetailList" resultType="com.klp.crm.domain.vo.CrmSalesReportVo$OrderDetail">
|
||
SELECT
|
||
o.order_id,
|
||
o.order_code,
|
||
c.customer_code,
|
||
c.company_name,
|
||
c.contact_person,
|
||
c.customer_level,
|
||
c.industry,
|
||
o.order_amount,
|
||
o.salesman,
|
||
o.delivery_date,
|
||
o.order_status,
|
||
o.finance_status,
|
||
o.unpaid_amount,
|
||
o.create_time,
|
||
COALESCE(item_stats.item_count, 0) as itemCount,
|
||
COALESCE(obj_stats.objection_count, 0) as objectionCount
|
||
FROM crm_order o
|
||
LEFT JOIN crm_customer c ON o.customer_id = c.customer_id
|
||
LEFT JOIN (
|
||
SELECT
|
||
order_id,
|
||
COUNT(*) as item_count
|
||
FROM crm_order_item
|
||
WHERE del_flag = 0
|
||
GROUP BY order_id
|
||
) item_stats ON o.order_id = item_stats.order_id
|
||
LEFT JOIN (
|
||
SELECT
|
||
order_id,
|
||
COUNT(*) as objection_count
|
||
FROM crm_sales_objection
|
||
WHERE del_flag = 0
|
||
GROUP BY order_id
|
||
) obj_stats ON o.order_id = obj_stats.order_id
|
||
<include refid="selectCondition"/>
|
||
<choose>
|
||
<when test="bo.orderBy != null and bo.orderBy != ''">
|
||
ORDER BY ${bo.orderBy}
|
||
<if test="bo.sortDirection != null and bo.sortDirection != ''">
|
||
${bo.sortDirection}
|
||
</if>
|
||
</when>
|
||
<otherwise>
|
||
ORDER BY o.create_time DESC
|
||
</otherwise>
|
||
</choose>
|
||
</select>
|
||
|
||
<!-- 查询销售员统计数据 -->
|
||
<select id="selectSalesmanStats" resultType="com.klp.crm.domain.vo.CrmSalesReportVo$SalesmanStat">
|
||
SELECT
|
||
o.salesman,
|
||
COUNT(o.order_id) as orderCount,
|
||
COALESCE(SUM(o.order_amount), 0) as salesAmount,
|
||
ROUND(
|
||
COALESCE(SUM(o.order_amount), 0) * 100.0 /
|
||
NULLIF((
|
||
SELECT SUM(o2.order_amount)
|
||
FROM crm_order o2
|
||
LEFT JOIN crm_customer c2 ON o2.customer_id = c2.customer_id
|
||
<!-- 子查询使用独立的条件片段,避免引用外层o/c -->
|
||
<where>
|
||
o2.del_flag = 0 AND c2.del_flag = 0
|
||
<if test="bo.startTime != null">
|
||
AND DATE(o2.create_time) >= #{bo.startTime}
|
||
</if>
|
||
<if test="bo.endTime != null">
|
||
AND DATE(o2.create_time) <= #{bo.endTime}
|
||
</if>
|
||
<if test="bo.salesmanList != null and bo.salesmanList.size() > 0">
|
||
AND o2.salesman IN
|
||
<foreach collection="bo.salesmanList" item="salesman" open="(" separator="," close=")">
|
||
#{salesman}
|
||
</foreach>
|
||
</if>
|
||
<if test="bo.customerIdList != null and bo.customerIdList.size() > 0">
|
||
AND o2.customer_id IN
|
||
<foreach collection="bo.customerIdList" item="customerId" open="(" separator="," close=")">
|
||
#{customerId}
|
||
</foreach>
|
||
</if>
|
||
<if test="bo.customerLevelList != null and bo.customerLevelList.size() > 0">
|
||
AND c2.customer_level IN
|
||
<foreach collection="bo.customerLevelList" item="level" open="(" separator="," close=")">
|
||
#{level}
|
||
</foreach>
|
||
</if>
|
||
<if test="bo.industryList != null and bo.industryList.size() > 0">
|
||
AND c2.industry IN
|
||
<foreach collection="bo.industryList" item="industry" open="(" separator="," close=")">
|
||
#{industry}
|
||
</foreach>
|
||
</if>
|
||
<if test="bo.orderStatusList != null and bo.orderStatusList.size() > 0">
|
||
AND o2.order_status IN
|
||
<foreach collection="bo.orderStatusList" item="status" open="(" separator="," close=")">
|
||
#{status}
|
||
</foreach>
|
||
</if>
|
||
<if test="bo.financeStatusList != null and bo.financeStatusList.size() > 0">
|
||
AND o2.finance_status IN
|
||
<foreach collection="bo.financeStatusList" item="status" open="(" separator="," close=")">
|
||
#{status}
|
||
</foreach>
|
||
</if>
|
||
<if test="bo.orderTypeList != null and bo.orderTypeList.size() > 0">
|
||
AND o2.order_type IN
|
||
<foreach collection="bo.orderTypeList" item="type" open="(" separator="," close=")">
|
||
#{type}
|
||
</foreach>
|
||
</if>
|
||
<if test="bo.minOrderAmount != null">
|
||
AND o2.order_amount >= #{bo.minOrderAmount}
|
||
</if>
|
||
<if test="bo.maxOrderAmount != null">
|
||
AND o2.order_amount <= #{bo.maxOrderAmount}
|
||
</if>
|
||
<if test="bo.onlyUnpaidOrders != null and bo.onlyUnpaidOrders == true">
|
||
AND o2.unpaid_amount > 0
|
||
</if>
|
||
<if test="bo.companyNameKeyword != null and bo.companyNameKeyword != ''">
|
||
AND c2.company_name LIKE CONCAT('%', #{bo.companyNameKeyword}, '%')
|
||
</if>
|
||
<if test="bo.orderCodeKeyword != null and bo.orderCodeKeyword != ''">
|
||
AND o2.order_code LIKE CONCAT('%', #{bo.orderCodeKeyword}, '%')
|
||
</if>
|
||
<if test="bo.includeObjectionOrders != null and bo.includeObjectionOrders == false">
|
||
AND NOT EXISTS (
|
||
SELECT 1 FROM crm_sales_objection obj
|
||
WHERE obj.order_id = o2.order_id AND obj.del_flag = 0
|
||
)
|
||
</if>
|
||
</where>
|
||
), 0),
|
||
2
|
||
) as percentage
|
||
FROM crm_order o
|
||
LEFT JOIN crm_customer c ON o.customer_id = c.customer_id
|
||
<include refid="selectCondition"/>
|
||
GROUP BY o.salesman
|
||
ORDER BY salesAmount DESC
|
||
</select>
|
||
|
||
<!-- 查询客户等级统计数据 -->
|
||
<select id="selectCustomerLevelStats" resultType="com.klp.crm.domain.vo.CrmSalesReportVo$CustomerLevelStat">
|
||
SELECT
|
||
c.customer_level,
|
||
COUNT(DISTINCT c.customer_id) as customerCount,
|
||
COUNT(o.order_id) as orderCount,
|
||
COALESCE(SUM(o.order_amount), 0) as salesAmount
|
||
FROM crm_order o
|
||
LEFT JOIN crm_customer c ON o.customer_id = c.customer_id
|
||
<include refid="selectCondition"/>
|
||
GROUP BY c.customer_level
|
||
ORDER BY salesAmount DESC
|
||
</select>
|
||
|
||
<!-- 查询行业统计数据 -->
|
||
<select id="selectIndustryStats" resultType="com.klp.crm.domain.vo.CrmSalesReportVo$IndustryStat">
|
||
SELECT
|
||
COALESCE(c.industry, '未分类') as industry,
|
||
COUNT(DISTINCT c.customer_id) as customerCount,
|
||
COUNT(o.order_id) as orderCount,
|
||
COALESCE(SUM(o.order_amount), 0) as salesAmount
|
||
FROM crm_order o
|
||
LEFT JOIN crm_customer c ON o.customer_id = c.customer_id
|
||
<include refid="selectCondition"/>
|
||
GROUP BY c.industry
|
||
ORDER BY salesAmount DESC
|
||
</select>
|
||
|
||
</mapper>
|