v1.0.14 #21

Merged
timi merged 6 commits from dev into master 2026-08-14 17:26:10 +00:00
4 changed files with 174 additions and 130 deletions
Showing only changes of commit 457e716b38 - Show all commits
@@ -282,13 +282,29 @@ public class GaoEventRecordServiceImplement extends AbstractEntityService<GaoEve
@Override @Override
public PageResult<GaoCustomerEventRankView> pageRankByRange(GaoEventRecordRankPage page) { public PageResult<GaoCustomerEventRankView> pageRankByRange(GaoEventRecordRankPage page) {
TimiException.required(page.getStoreId(), "not found page.storeId"); TimiException.required(page.getStoreId(), "not found page.storeId");
page.setTodayDateValue(dateValue(Time.now())); validateRankPage(page);
if (page.getRankType() == GaoEventRecordRankPage.RankType.CONTINUOUS_DAYS) {
page.setTodayDateValue(dateValue(Time.now()));
}
PageResult<GaoCustomerEventRankView> result = new PageResult<>(); PageResult<GaoCustomerEventRankView> result = new PageResult<>();
result.setTotal(mapper.countRankByRange(page)); result.setTotal(mapper.countRankByRange(page));
result.setList(mapper.selectRankByRange(page)); result.setList(mapper.selectRankByRange(page));
return result; return result;
} }
/// 校验登记数值排行的事件范围
///
/// @param page 排行榜查询请求
private void validateRankPage(GaoEventRecordRankPage page) {
if (page.getRankType() != GaoEventRecordRankPage.RankType.TOTAL_NUMBER_VALUE) {
return;
}
List<String> eventIdList = page.getEventIdList();
TimiException.requiredTrue(eventIdList != null && eventIdList.size() == 1, "按登记数值排行必须选择单个事件");
GaoEvent event = eventService.mapByIdList(eventIdList).get(eventIdList.get(0));
TimiException.requiredTrue(event != null && event.getValueType() == GaoEvent.ValueType.NUMBER, "按登记数值排行只能选择 NUMBER 事件");
}
private void checkEventPermission(GaoEvent event) { private void checkEventPermission(GaoEvent event) {
List<String> roleCodeList = eventService.listRoleCode(event.getId()); List<String> roleCodeList = eventService.listRoleCode(event.getId());
TimiException.requiredTrue(roleCodeList != null && !roleCodeList.isEmpty(), "登记事件未配置可登记角色"); TimiException.requiredTrue(roleCodeList != null && !roleCodeList.isEmpty(), "登记事件未配置可登记角色");
@@ -29,6 +29,9 @@ public class GaoCustomerEventRankView {
/// 最近连续登记天数 /// 最近连续登记天数
private Long recentContinuousEventDays; private Long recentContinuousEventDays;
/// 登记数值合计
private Long totalNumberValue;
/// 最后登记时间 /// 最后登记时间
private Long latestRegisteredAt; private Long latestRegisteredAt;
} }
@@ -41,6 +41,8 @@ public class GaoEventRecordRankPage extends BasePage {
/// 按累计登记次数 /// 按累计登记次数
TOTAL_COUNT, TOTAL_COUNT,
/// 按最近连续登记天数 /// 按最近连续登记天数
CONTINUOUS_DAYS CONTINUOUS_DAYS,
/// 按登记数值合计
TOTAL_NUMBER_VALUE
} }
} }
@@ -160,6 +160,9 @@
#{eventId} #{eventId}
</foreach> </foreach>
</if> </if>
<if test="rankType != null and rankType.name() == 'TOTAL_NUMBER_VALUE'">
AND r.`number_value` IS NOT NULL
</if>
</sql> </sql>
<select id="countRankByRange" resultType="long"> <select id="countRankByRange" resultType="long">
SELECT SELECT
@@ -170,134 +173,154 @@
<include refid="rankWhere"/> <include refid="rankWhere"/>
</select> </select>
<select id="selectRankByRange" resultType="com.imyeyu.api.modules.gao.vo.GaoCustomerEventRankView"> <select id="selectRankByRange" resultType="com.imyeyu.api.modules.gao.vo.GaoCustomerEventRankView">
WITH RECURSIVE `daily_stat` AS ( <choose>
SELECT <when test="rankType == null or rankType.name() == 'TOTAL_DAYS'">
r.`customer_id` AS `customerId`, SELECT
r.`registered_date_value` AS `registeredDateValue`, ROW_NUMBER() OVER (
COUNT(1) AS `dailyCount`, ORDER BY COUNT(DISTINCT r.`registered_date_value`) DESC, r.`customer_id`
MAX(r.`registered_at`) AS `latestRegisteredAt` ) AS `rank`,
FROM `gao_event_record` r r.`customer_id` AS `customerId`,
LEFT JOIN `gao_customer` c ON r.`customer_id` = c.`id` COUNT(DISTINCT r.`registered_date_value`) AS `totalEventDays`,
WHERE NULL AS `totalEventCount`,
<include refid="rankWhere"/> NULL AS `recentContinuousEventDays`,
GROUP BY NULL AS `totalNumberValue`,
r.`customer_id`, NULL AS `latestRegisteredAt`
r.`registered_date_value` FROM `gao_event_record` r
), LEFT JOIN `gao_customer` c ON r.`customer_id` = c.`id`
`range_bound` AS ( WHERE
SELECT <include refid="rankWhere"/>
LEAST( GROUP BY r.`customer_id`
STR_TO_DATE(CAST(MIN(`registeredDateValue`) AS CHAR), '%Y%m%d'), ORDER BY `rank`
STR_TO_DATE(CAST(#{todayDateValue} AS CHAR), '%Y%m%d') LIMIT #{offset}, #{limit}
) AS `beginDate`, </when>
STR_TO_DATE(CAST(#{todayDateValue} AS CHAR), '%Y%m%d') AS `endDate` <when test="rankType.name() == 'TOTAL_COUNT'">
FROM `daily_stat` SELECT
), ROW_NUMBER() OVER (
`calendar` AS ( ORDER BY COUNT(1) DESC, r.`customer_id`
SELECT ) AS `rank`,
CAST(DATE_FORMAT(`beginDate`, '%Y%m%d') AS UNSIGNED) AS `dateValue`, r.`customer_id` AS `customerId`,
`beginDate` AS `dateDate` NULL AS `totalEventDays`,
FROM `range_bound` COUNT(1) AS `totalEventCount`,
WHERE `beginDate` IS NOT NULL NULL AS `recentContinuousEventDays`,
UNION ALL NULL AS `totalNumberValue`,
SELECT NULL AS `latestRegisteredAt`
CAST(DATE_FORMAT(DATE_ADD(c.`dateDate`, INTERVAL 1 DAY), '%Y%m%d') AS UNSIGNED) AS `dateValue`, FROM `gao_event_record` r
DATE_ADD(c.`dateDate`, INTERVAL 1 DAY) AS `dateDate` LEFT JOIN `gao_customer` c ON r.`customer_id` = c.`id`
FROM `calendar` c WHERE
JOIN `range_bound` b ON c.`dateDate` &lt; b.`endDate` <include refid="rankWhere"/>
), GROUP BY r.`customer_id`
`open_calendar` AS ( ORDER BY `rank`
SELECT LIMIT #{offset}, #{limit}
c.`dateValue`, </when>
ROW_NUMBER() OVER (ORDER BY c.`dateDate`) AS `openIndex` <when test="rankType.name() == 'TOTAL_NUMBER_VALUE'">
FROM `calendar` c SELECT
LEFT JOIN `gao_store_business_day` b ON b.`store_id` = #{storeId} ROW_NUMBER() OVER (
AND b.`date_value` = c.`dateValue` ORDER BY SUM(r.`number_value`) DESC, r.`customer_id`
AND b.`deleted_at` IS NULL ) AS `rank`,
WHERE COALESCE(b.`status`, 'OPEN') != 'CLOSED' r.`customer_id` AS `customerId`,
), NULL AS `totalEventDays`,
`rank_stat` AS ( NULL AS `totalEventCount`,
SELECT NULL AS `recentContinuousEventDays`,
`customerId`, SUM(r.`number_value`) AS `totalNumberValue`,
COUNT(1) AS `totalEventDays`, NULL AS `latestRegisteredAt`
SUM(`dailyCount`) AS `totalEventCount`, FROM `gao_event_record` r
MAX(`latestRegisteredAt`) AS `latestRegisteredAt` LEFT JOIN `gao_customer` c ON r.`customer_id` = c.`id`
FROM `daily_stat` WHERE
GROUP BY `customerId` <include refid="rankWhere"/>
), GROUP BY r.`customer_id`
`continuous_ordered` AS ( ORDER BY `rank`
SELECT LIMIT #{offset}, #{limit}
d.`customerId`, </when>
o.`openIndex`, <otherwise>
ROW_NUMBER() OVER (PARTITION BY d.`customerId` ORDER BY o.`openIndex` DESC) AS `dayIndex` WITH RECURSIVE `daily_stat` AS (
FROM `daily_stat` d SELECT
JOIN `open_calendar` o ON d.`registeredDateValue` = o.`dateValue` r.`customer_id` AS `customerId`,
), r.`registered_date_value` AS `registeredDateValue`
`anchor_date` AS ( FROM `gao_event_record` r
SELECT LEFT JOIN `gao_customer` c ON r.`customer_id` = c.`id`
MAX(`openIndex`) AS `anchorOpenIndex` WHERE
FROM `open_calendar` <include refid="rankWhere"/>
), GROUP BY
`continuous_stat` AS ( r.`customer_id`,
SELECT r.`registered_date_value`
o.`customerId`, ),
CASE `range_bound` AS (
WHEN COUNT(1) &lt; 2 THEN 0 SELECT
ELSE COUNT(1) LEAST(
END AS `recentContinuousEventDays` STR_TO_DATE(CAST(MIN(`registeredDateValue`) AS CHAR), '%Y%m%d'),
FROM `continuous_ordered` o STR_TO_DATE(CAST(#{todayDateValue} AS CHAR), '%Y%m%d')
JOIN `anchor_date` a ) AS `beginDate`,
WHERE STR_TO_DATE(CAST(#{todayDateValue} AS CHAR), '%Y%m%d') AS `endDate`
o.`openIndex` + o.`dayIndex` = a.`anchorOpenIndex` + 1 FROM `daily_stat`
<if test="eventIdList == null or eventIdList.size() != 1"> ),
AND 1 = 0 `calendar` AS (
</if> SELECT
GROUP BY o.`customerId` CAST(DATE_FORMAT(`beginDate`, '%Y%m%d') AS UNSIGNED) AS `dateValue`,
), `beginDate` AS `dateDate`
`ranked` AS ( FROM `range_bound`
SELECT WHERE `beginDate` IS NOT NULL
ROW_NUMBER() OVER ( UNION ALL
ORDER BY SELECT
<choose> CAST(DATE_FORMAT(DATE_ADD(c.`dateDate`, INTERVAL 1 DAY), '%Y%m%d') AS UNSIGNED) AS `dateValue`,
<when test="rankType != null and rankType.name() == 'TOTAL_COUNT'"> DATE_ADD(c.`dateDate`, INTERVAL 1 DAY) AS `dateDate`
r.`totalEventCount` DESC, FROM `calendar` c
r.`totalEventDays` DESC, JOIN `range_bound` b ON c.`dateDate` &lt; b.`endDate`
r.`latestRegisteredAt` DESC, ),
r.`customerId` `open_calendar` AS (
</when> SELECT
<when test="rankType != null and rankType.name() == 'CONTINUOUS_DAYS'"> c.`dateValue`,
COALESCE(c.`recentContinuousEventDays`, 0) DESC, ROW_NUMBER() OVER (ORDER BY c.`dateDate`) AS `openIndex`
r.`totalEventDays` DESC, FROM `calendar` c
r.`totalEventCount` DESC, LEFT JOIN `gao_store_business_day` b ON b.`store_id` = #{storeId}
r.`latestRegisteredAt` DESC, AND b.`date_value` = c.`dateValue`
r.`customerId` AND b.`deleted_at` IS NULL
</when> WHERE COALESCE(b.`status`, 'OPEN') != 'CLOSED'
<otherwise> ),
r.`totalEventDays` DESC, `continuous_ordered` AS (
r.`totalEventCount` DESC, SELECT
r.`latestRegisteredAt` DESC, d.`customerId`,
r.`customerId` o.`openIndex`,
</otherwise> ROW_NUMBER() OVER (PARTITION BY d.`customerId` ORDER BY o.`openIndex` DESC) AS `dayIndex`
</choose> FROM `daily_stat` d
) AS `rank`, JOIN `open_calendar` o ON d.`registeredDateValue` = o.`dateValue`
r.`customerId`, ),
r.`totalEventDays`, `anchor_date` AS (
r.`totalEventCount`, SELECT
COALESCE(c.`recentContinuousEventDays`, 0) AS `recentContinuousEventDays`, MAX(`openIndex`) AS `anchorOpenIndex`
r.`latestRegisteredAt` FROM `open_calendar`
FROM `rank_stat` r ),
LEFT JOIN `continuous_stat` c ON r.`customerId` = c.`customerId` `continuous_stat` AS (
) SELECT
SELECT o.`customerId`,
`rank`, CASE
`customerId`, WHEN COUNT(1) &lt; 2 THEN 0
`totalEventDays`, ELSE COUNT(1)
`totalEventCount`, END AS `recentContinuousEventDays`
`recentContinuousEventDays`, FROM `continuous_ordered` o
`latestRegisteredAt` JOIN `anchor_date` a
FROM `ranked` WHERE
ORDER BY `rank` o.`openIndex` + o.`dayIndex` = a.`anchorOpenIndex` + 1
LIMIT #{offset}, #{limit} <if test="eventIdList == null or eventIdList.size() != 1">
AND 1 = 0
</if>
GROUP BY o.`customerId`
)
SELECT
ROW_NUMBER() OVER (
ORDER BY COALESCE(c.`recentContinuousEventDays`, 0) DESC, r.`customerId`
) AS `rank`,
r.`customerId`,
NULL AS `totalEventDays`,
NULL AS `totalEventCount`,
COALESCE(c.`recentContinuousEventDays`, 0) AS `recentContinuousEventDays`,
NULL AS `totalNumberValue`,
NULL AS `latestRegisteredAt`
FROM (SELECT DISTINCT `customerId` FROM `daily_stat`) r
LEFT JOIN `continuous_stat` c ON r.`customerId` = c.`customerId`
ORDER BY `rank`
LIMIT #{offset}, #{limit}
</otherwise>
</choose>
</select> </select>
<sql id="storeChartRangeWhere"> <sql id="storeChartRangeWhere">