Commit a33a8369 authored by lixuan's avatar lixuan

feat: 需求

parent bd32f53f
Pipeline #147218 failed with stages
in 0 seconds
...@@ -20,15 +20,18 @@ import java.util.List; ...@@ -20,15 +20,18 @@ import java.util.List;
* *
* <h3>经营主体(BUSINESS_ENTITY_INFO)维度</h3> * <h3>经营主体(BUSINESS_ENTITY_INFO)维度</h3>
* <ul> * <ul>
* <li>{@link #businessEntityInsertCount} / {@link #businessEntityInsertIds}: * <li>{@link #businessEntityInsert} / {@link #businessEntityUpdate} / {@link #businessEntityDelete}:
* 新增经营主体的数量和 id 列表(可传给 drilldown);</li> * 结构与房源三桶一致,按关联房源的 {@code house_resource.type} 分组,补齐 type = 1/4/5/6/7 五档;
* <li>{@link #businessEntityUpdateCount} / {@link #businessEntityUpdateIds}:同上;</li> * 一个经营主体若关联到多种 type 的房源,会在对应的多个 type 桶里各出现一次。</li>
* <li>{@link #businessEntityDeleteCount}:只给 count,无 id。</li> * <li>{@code insert} / {@code update} 桶的每个档位带 {@code ids} 列表,前端 drilldown 时应同时传
* {@code businessEntityInfoIds} + {@code wgType = type},以和档位计数保持一致;</li>
* <li>{@code delete} 桶同样只给 count 不给 ids。</li>
* </ul> * </ul>
* *
* <h3>计数口径</h3> * <h3>计数口径</h3>
* <p>insert / update 桶会过滤 {@code delete_flag = 0},保证和 pageHouseResources 的 drilldown * <p>insert / update 桶要求 JOIN 链路 entity / mapping / house 均 {@code delete_flag = 0},保证
* 列表能一一对上;delete 桶不过滤 {@code delete_flag},用于统计窗内发生过删除事件的数量。</p> * 和 pageHouseResources 的 drilldown 列表能一一对上;delete 桶只要求 entity 历史上至少关联过某个房源,
* 不限 mapping / house 的 {@code delete_flag}。</p>
*/ */
@Data @Data
public class HouseResourceDataCollection { public class HouseResourceDataCollection {
...@@ -39,13 +42,9 @@ public class HouseResourceDataCollection { ...@@ -39,13 +42,9 @@ public class HouseResourceDataCollection {
private List<HouseResourceDataCollectionSimpleObject> houseResourceDelete; private List<HouseResourceDataCollectionSimpleObject> houseResourceDelete;
private long businessEntityInsertCount; private List<HouseResourceDataCollectionSimpleObject> businessEntityInsert;
private List<String> businessEntityInsertIds; private List<HouseResourceDataCollectionSimpleObject> businessEntityUpdate;
private long businessEntityUpdateCount; private List<HouseResourceDataCollectionSimpleObject> businessEntityDelete;
private List<String> businessEntityUpdateIds;
private long businessEntityDeleteCount;
} }
...@@ -688,24 +688,16 @@ public class HouseResourceServiceImpl implements HouseResourceService { ...@@ -688,24 +688,16 @@ public class HouseResourceServiceImpl implements HouseResourceService {
result.setHouseResourceUpdate(buildHouseTypeBuckets(houseDetails, OperationType.UPDATE.getCode(), true)); result.setHouseResourceUpdate(buildHouseTypeBuckets(houseDetails, OperationType.UPDATE.getCode(), true));
result.setHouseResourceDelete(buildHouseTypeBucketsFromCount(houseDeleteRows)); result.setHouseResourceDelete(buildHouseTypeBucketsFromCount(houseDeleteRows));
// BUSINESS_ENTITY_INFO: insert / update 拿 ids + count;delete 只拿 count。 // BUSINESS_ENTITY_INFO:结构与房源对称,按关联房源 hr2.type 分桶(1/4/5/6/7)。
// insert / update 出详情(带 ids,前端 drilldown 时需配合 wgType = type 使用),delete 只出 count。
List<HouseResourceDataCollectionDetailRow> entityDetails = List<HouseResourceDataCollectionDetailRow> entityDetails =
houseResourceMapper.selectBusinessEntityChangeDetails(query); houseResourceMapper.selectBusinessEntityChangeDetails(query);
Map<Integer, List<String>> entityIdsByOp = entityDetails.stream() List<HouseResourceDataCollectionRow> entityDeleteRows =
.collect(Collectors.groupingBy( houseResourceMapper.selectBusinessEntityDeleteCount(query);
HouseResourceDataCollectionDetailRow::getOperationType,
Collectors.mapping(HouseResourceDataCollectionDetailRow::getSubjectId, Collectors.toList()))); result.setBusinessEntityInsert(buildHouseTypeBuckets(entityDetails, OperationType.INSERT.getCode(), true));
List<String> entityInsertIds = entityIdsByOp.getOrDefault(OperationType.INSERT.getCode(), Collections.emptyList()); result.setBusinessEntityUpdate(buildHouseTypeBuckets(entityDetails, OperationType.UPDATE.getCode(), true));
List<String> entityUpdateIds = entityIdsByOp.getOrDefault(OperationType.UPDATE.getCode(), Collections.emptyList()); result.setBusinessEntityDelete(buildHouseTypeBucketsFromCount(entityDeleteRows));
result.setBusinessEntityInsertIds(entityInsertIds);
result.setBusinessEntityInsertCount(entityInsertIds.size());
result.setBusinessEntityUpdateIds(entityUpdateIds);
result.setBusinessEntityUpdateCount(entityUpdateIds.size());
long entityDeleteCount = houseResourceMapper.selectBusinessEntityDeleteCount(query).stream()
.mapToLong(HouseResourceDataCollectionRow::getCount)
.sum();
result.setBusinessEntityDeleteCount(entityDeleteCount);
return result; return result;
} }
......
...@@ -1005,47 +1005,43 @@ ...@@ -1005,47 +1005,43 @@
</select> </select>
<!-- <!--
时间窗内经营主体(BUSINESS_ENTITY_INFO)的新增 / 修改**详情**行:每行一个 (operation_type, subject_id)。 时间窗内经营主体(BUSINESS_ENTITY_INFO)的新增 / 修改**详情**行:每行一个 (type, operation_type, subject_id)。
口径对齐 pageHouseResources 的 drilldown(t1.delete_flag = 0 + t3.delete_flag = 0 + t4.delete_flag = 0): 说明:
* bei.delete_flag = 0:entity 本身必须存活; * 这里的 type 取自关联房源 hr2.type(经营主体本身无 type 字段)。一个 entity 关联到多种 type
* EXISTS 子查询**恒生效**:要求经营主体至少关联到一条"有效 mapping + 有效 house", 的房源时,会在对应的多个桶里分别出现一次(DISTINCT 已对 (type, operation_type, subject_id) 去重)。
否则 drilldown 侧展示不出来,也就不计入 dataCollection。这样保证 dataCollection 返回的 * INNER JOIN 链路:bei → mapping → house_resource,且三者都要求 delete_flag = 0,与
id 列表都能在 /api/house/page?businessEntityInfoIds=... 里查到对应行。 pageHouseResources 的 drilldown 口径一致,保证 dataCollection 返回的每个 id 在
* 传 two/three/four/wgCodes 时,EXISTS 内部按网格进一步收紧。 /api/house/page?businessEntityInfoIds=...&wgType=type 里都能查到对应行。
* 传 two/three/four/wgCodes 时,按网格进一步收紧 hr2。
--> -->
<select id="selectBusinessEntityChangeDetails" <select id="selectBusinessEntityChangeDetails"
resultType="com.ruoyi.system.domain.house.vo.HouseResourceDataCollectionDetailRow"> resultType="com.ruoyi.system.domain.house.vo.HouseResourceDataCollectionDetailRow">
SELECT DISTINCT SELECT DISTINCT
0 AS type, hr2.type AS type,
dcr.operation_type AS operationType, dcr.operation_type AS operationType,
dcr.subject_id AS subjectId dcr.subject_id AS subjectId
FROM data_change_record dcr FROM data_change_record dcr
INNER JOIN business_entity_info bei ON bei.id = dcr.subject_id AND bei.delete_flag = 0 INNER JOIN business_entity_info bei ON bei.id = dcr.subject_id AND bei.delete_flag = 0
INNER JOIN house_resource_business_entity_info_mapping m ON m.business_entity_info_id = bei.id AND m.delete_flag = 0
INNER JOIN house_resource hr2 ON hr2.id = m.house_resource_id AND hr2.delete_flag = 0
WHERE dcr.subject_type = 'BUSINESS_ENTITY_INFO' WHERE dcr.subject_type = 'BUSINESS_ENTITY_INFO'
AND dcr.operation_type IN (1, 2) AND dcr.operation_type IN (1, 2)
AND dcr.operation_time <![CDATA[ >= ]]> #{query.changeStartTime} AND dcr.operation_time <![CDATA[ >= ]]> #{query.changeStartTime}
AND dcr.operation_time <![CDATA[ <= ]]> #{query.changeEndTime} AND dcr.operation_time <![CDATA[ <= ]]> #{query.changeEndTime}
AND EXISTS ( <if test="query.two != null and query.two != ''">
SELECT 1 AND hr2.two = #{query.two}
FROM house_resource_business_entity_info_mapping m </if>
INNER JOIN house_resource hr2 ON hr2.id = m.house_resource_id AND hr2.delete_flag = 0 <if test="query.three != null and query.three != ''">
WHERE m.business_entity_info_id = bei.id AND hr2.three = #{query.three}
AND m.delete_flag = 0 </if>
<if test="query.two != null and query.two != ''"> <if test="query.four != null and query.four != ''">
AND hr2.two = #{query.two} AND hr2.four = #{query.four}
</if> </if>
<if test="query.three != null and query.three != ''"> <if test="query.wgCodes != null and query.wgCodes.size() > 0">
AND hr2.three = #{query.three} AND hr2.two IN
</if> <foreach collection="query.wgCodes" item="wg" open="(" separator="," close=")">#{wg}</foreach>
<if test="query.four != null and query.four != ''"> </if>
AND hr2.four = #{query.four}
</if>
<if test="query.wgCodes != null and query.wgCodes.size() > 0">
AND hr2.two IN
<foreach collection="query.wgCodes" item="wg" open="(" separator="," close=")">#{wg}</foreach>
</if>
)
</select> </select>
<!-- <!--
...@@ -1054,41 +1050,41 @@ ...@@ -1054,41 +1050,41 @@
匹配网格的房源"即计入,覆盖"经营主体删除前房源或 mapping 已经被解除"的场景。 匹配网格的房源"即计入,覆盖"经营主体删除前房源或 mapping 已经被解除"的场景。
--> -->
<!-- <!--
时间窗内经营主体(BUSINESS_ENTITY_INFO)被删除的数量。 时间窗内经营主体(BUSINESS_ENTITY_INFO)被删除的数量,按关联房源 hr2.type 分组。
与 insert/update 口径保持一致:EXISTS 恒生效,要求经营主体历史上至少关联过某个房源(不限
delete_flag,因为被删的 entity 本身的 mapping/house 也可能已被删)。这样"从未挂过房源"的 与 insert/update 口径保持一致:INNER JOIN 链路 bei → mapping → house_resource 恒生效,
孤儿 entity 不计入删除数,保证和看得见的业务实体口径统一。 要求经营主体历史上至少关联过某个房源;但 mapping / hr2 **不**限 delete_flag,因为被删除
的 entity 其 mapping/house 可能也已逻辑删除。一个 entity 若关联过多种 type 的房源,会在
对应的多个 type 桶里分别被 COUNT DISTINCT 计入一次(聚合层面)。"从未挂过房源"的孤儿
entity 不计入删除数,保证和看得见的业务口径统一。
--> -->
<select id="selectBusinessEntityDeleteCount" <select id="selectBusinessEntityDeleteCount"
resultType="com.ruoyi.system.domain.house.vo.HouseResourceDataCollectionRow"> resultType="com.ruoyi.system.domain.house.vo.HouseResourceDataCollectionRow">
SELECT SELECT
0 AS type, hr2.type AS type,
3 AS operationType, 3 AS operationType,
COUNT(DISTINCT dcr.subject_id) AS count COUNT(DISTINCT dcr.subject_id) AS count
FROM data_change_record dcr FROM data_change_record dcr
INNER JOIN business_entity_info bei ON bei.id = dcr.subject_id INNER JOIN business_entity_info bei ON bei.id = dcr.subject_id
INNER JOIN house_resource_business_entity_info_mapping m ON m.business_entity_info_id = bei.id
INNER JOIN house_resource hr2 ON hr2.id = m.house_resource_id
WHERE dcr.subject_type = 'BUSINESS_ENTITY_INFO' WHERE dcr.subject_type = 'BUSINESS_ENTITY_INFO'
AND dcr.operation_type = 3 AND dcr.operation_type = 3
AND dcr.operation_time <![CDATA[ >= ]]> #{query.changeStartTime} AND dcr.operation_time <![CDATA[ >= ]]> #{query.changeStartTime}
AND dcr.operation_time <![CDATA[ <= ]]> #{query.changeEndTime} AND dcr.operation_time <![CDATA[ <= ]]> #{query.changeEndTime}
AND EXISTS ( <if test="query.two != null and query.two != ''">
SELECT 1 AND hr2.two = #{query.two}
FROM house_resource_business_entity_info_mapping m </if>
INNER JOIN house_resource hr2 ON hr2.id = m.house_resource_id <if test="query.three != null and query.three != ''">
WHERE m.business_entity_info_id = bei.id AND hr2.three = #{query.three}
<if test="query.two != null and query.two != ''"> </if>
AND hr2.two = #{query.two} <if test="query.four != null and query.four != ''">
</if> AND hr2.four = #{query.four}
<if test="query.three != null and query.three != ''"> </if>
AND hr2.three = #{query.three} <if test="query.wgCodes != null and query.wgCodes.size() > 0">
</if> AND hr2.two IN
<if test="query.four != null and query.four != ''"> <foreach collection="query.wgCodes" item="wg" open="(" separator="," close=")">#{wg}</foreach>
AND hr2.four = #{query.four} </if>
</if> GROUP BY hr2.type
<if test="query.wgCodes != null and query.wgCodes.size() > 0">
AND hr2.two IN
<foreach collection="query.wgCodes" item="wg" open="(" separator="," close=")">#{wg}</foreach>
</if>
)
</select> </select>
</mapper> </mapper>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment