diff --git a/src/main/java/com/biutag/supervision/mapper/SupDepartMapper.java b/src/main/java/com/biutag/supervision/mapper/SupDepartMapper.java index 61a9223..36cadda 100644 --- a/src/main/java/com/biutag/supervision/mapper/SupDepartMapper.java +++ b/src/main/java/com/biutag/supervision/mapper/SupDepartMapper.java @@ -66,4 +66,13 @@ public interface SupDepartMapper extends BaseMapper { List getDepartAndSubDepart(SupDepartGroupParam param); + @Select("") + List> getGroupIdsByDepartIds(List departIds); + + } diff --git a/src/main/java/com/biutag/supervision/mapper/SupExternalDepartMapper.java b/src/main/java/com/biutag/supervision/mapper/SupExternalDepartMapper.java index aecca3f..06ecab5 100644 --- a/src/main/java/com/biutag/supervision/mapper/SupExternalDepartMapper.java +++ b/src/main/java/com/biutag/supervision/mapper/SupExternalDepartMapper.java @@ -3,6 +3,7 @@ package com.biutag.supervision.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.biutag.supervision.pojo.entity.SupExternalDepart; import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import java.util.List; @@ -21,6 +22,26 @@ public interface SupExternalDepartMapper extends BaseMapper { + "") List> getIdsByDepartIds(List departIds); + + /** + * 新增:按 source 动态查询映射(同一张表,不同 source) + * - JJD 用 source='情指行' + * - SA/LA/PA 用 source='执法办案而已' + */ + @Select("") + List> getIdsByExternalIdsAndSource(@Param("departIds") List departIds, + @Param("source") String source); + + @Select("select level from sup_external_depart where internal_id = #{internalDepartId}") SupExternalDepart selectLevelByDepartId(String internalDepartId); diff --git a/src/main/java/com/biutag/supervision/pojo/dto/BusinessDepart/BusinessDepartLogDTO.java b/src/main/java/com/biutag/supervision/pojo/dto/BusinessDepart/BusinessDepartLogDTO.java new file mode 100644 index 0000000..a12e171 --- /dev/null +++ b/src/main/java/com/biutag/supervision/pojo/dto/BusinessDepart/BusinessDepartLogDTO.java @@ -0,0 +1,41 @@ +package com.biutag.supervision.pojo.dto.BusinessDepart; + +import com.biutag.supervision.pojo.entity.GBaseAJJBXX; +import com.biutag.supervision.pojo.entity.GBaseJJD; +import com.biutag.supervision.service.BusinessDepartService; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; +import java.util.Map; + +/** + * @ClassName BusinessDepartLogDTO + * @Description 业务日志dto + * @Author shihao + * @Date 2026/2/4 19:09 + */ +@Getter +@Setter +@Schema(description = "单位业务缺失映射日志 DTO") +public class BusinessDepartLogDTO { + + @Schema(description = "情指行-接警单列表") + private List jjdList; + + @Schema(description = "执法办案-受案列表(案件单位口径:BADWIDdm)") + private List saList; + + @Schema(description = "执法办案-立案列表(案件单位口径:BADWIDdm,沿用旧逻辑)") + private List laList; + + @Schema(description = "执法办案-破案列表(案件单位口径:BADWIDdm,沿用旧逻辑)") + private List paList; + + @Schema(description = "情指行单位映射(source=情指行)") + private BusinessDepartService.DepartMapping qzxMapping; + + @Schema(description = "执法办案单位映射(source=执法办案)") + private BusinessDepartService.DepartMapping zfbaMapping; +} diff --git a/src/main/java/com/biutag/supervision/pojo/entity/GBaseAJJBXX.java b/src/main/java/com/biutag/supervision/pojo/entity/GBaseAJJBXX.java index 8b59fe2..5d2c18c 100644 --- a/src/main/java/com/biutag/supervision/pojo/entity/GBaseAJJBXX.java +++ b/src/main/java/com/biutag/supervision/pojo/entity/GBaseAJJBXX.java @@ -2,9 +2,12 @@ package com.biutag.supervision.pojo.entity; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.Setter; +import java.util.Date; + @Setter @Getter @TableName("dwd_asj_zfba_ajjbxx") @@ -46,6 +49,20 @@ public class GBaseAJJBXX { @TableField("XM") private String XM; + + @Schema(description = "受理日期 统计查询用:SQL 里别名为 SLRQ/LARQ/PARQ 回填,不落库") + @TableField(exist = false) + private Date SLRQ; + + @Schema(description = "立案日期 统计查询用:SQL 里别名为 SLRQ/LARQ/PARQ 回填,不落库") + @TableField(exist = false) + private Date LARQ; + + @Schema(description = "破案日期 统计查询用:SQL 里别名为 SLRQ/LARQ/PARQ 回填,不落库") + @TableField(exist = false) + private Date PARQ; + + // 办案人ID @TableField(exist = false) private String BARID; diff --git a/src/main/java/com/biutag/supervision/service/BusinessDepartService.java b/src/main/java/com/biutag/supervision/service/BusinessDepartService.java index 436a52f..ca9f071 100644 --- a/src/main/java/com/biutag/supervision/service/BusinessDepartService.java +++ b/src/main/java/com/biutag/supervision/service/BusinessDepartService.java @@ -1,6 +1,5 @@ package com.biutag.supervision.service; -import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -8,10 +7,8 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.biutag.supervision.mapper.*; -import com.biutag.supervision.pojo.entity.BusinessDepart; -import com.biutag.supervision.pojo.entity.BusinessLog; -import com.biutag.supervision.pojo.entity.GBaseAJJBXX; -import com.biutag.supervision.pojo.entity.GBaseJJD; +import com.biutag.supervision.pojo.dto.BusinessDepart.BusinessDepartLogDTO; +import com.biutag.supervision.pojo.entity.*; import com.biutag.supervision.pojo.model.BusinessPoliceModel; import com.biutag.supervision.pojo.param.BusinessQueryParam; import lombok.RequiredArgsConstructor; @@ -21,8 +18,8 @@ import org.springframework.stereotype.Service; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.ZoneId; -import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; @@ -47,30 +44,29 @@ public class BusinessDepartService extends ServiceImpl page(BusinessQueryParam businessQueryParam) { - // 测基础数据 - if (businessQueryParam.getDepartName() != null && businessQueryParam.getDepartName().equals("开始导入今年所有的数据")) { - Date now = new Date(); - LocalDate start = DateUtil.beginOfYear(now).toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); - LocalDate end = now.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); - for (LocalDate date = start; !date.isAfter(end); date = date.plusDays(1)) { - List happenTime = new ArrayList<>(); - Date from = Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant()); - Date startDate = DateUtil.beginOfDay(from); - Date endDate = DateUtil.endOfDay(from); - happenTime.add(startDate); - happenTime.add(endDate); - generate(happenTime); - log.info("已经导入{}的单位数据", date.format(DateTimeFormatter.ofPattern("yyyy年M月d日"))); - } - } else if (businessQueryParam.getDepartName() != null && businessQueryParam.getDepartName().equals("开始导入今天所有的数据")) { - List happenTime = new ArrayList<>(); - Date start = DateUtil.beginOfDay(new Date()); - Date end = DateUtil.endOfDay(new Date()); - happenTime.add(start); - happenTime.add(end); + if ("测试导入".equals(businessQueryParam.getDepartName()) && businessQueryParam.getHappenTime() != null && businessQueryParam.getHappenTime().size() == 2) { + Date startInput = businessQueryParam.getHappenTime().get(0); + Date endInput = businessQueryParam.getHappenTime().get(1); + ZoneId zoneId = ZoneId.systemDefault(); + // 起始日期 00:00:00 + LocalDate startDate = startInput.toInstant().atZone(zoneId).toLocalDate(); + LocalDateTime startOfDay = startDate.atStartOfDay(); + // 结束日期 23:59:59.999999999 + LocalDate endDate = endInput.toInstant().atZone(zoneId).toLocalDate(); + LocalDateTime endOfDay = endDate.atTime(LocalTime.MAX); + List happenTime = new ArrayList<>(2); + happenTime.add(Date.from(startOfDay.atZone(zoneId).toInstant())); + happenTime.add(Date.from(endOfDay.atZone(zoneId).toInstant())); + log.info("【单位业务-测试导入】归一化后时间范围=[{} ~ {}]", happenTime.get(0), happenTime.get(1)); generate(happenTime); + log.info("【单位业务-测试导入】导入执行完成"); } // 测模型 String departName = businessQueryParam.getDepartName(); @@ -101,55 +97,91 @@ public class BusinessDepartService extends ServiceImpl happenTime) { - List businessDepartList = new ArrayList<>(); + String range = (happenTime != null && happenTime.size() >= 2) ? "[" + happenTime.get(0) + " ~ " + happenTime.get(1) + "]" : "[未知范围]"; + String trace = UUID.randomUUID().toString().substring(0, 8); + log.info("【单位业务数据】generate start trace={}, 时间范围={}", trace, range); +// List businessDepartList = new ArrayList<>(); List gBaseJJDSList = selectJJDList(happenTime); // 接警单,除去无效、其他等案件 List gBaseAJJBXXListSA = selectAJJBXX(1, happenTime); // 受理日期 List gBaseAJJBXXListLA = selectAJJBXX(2, happenTime); // 立案日期 List gBaseAJJBXXListPA = selectAJJBXX(3, happenTime); // 破案日期 + log.info("【单位业务数据】源数据统计:接警单={},受案={},立案={},破案={},时间范围={}", gBaseJJDSList.size(), gBaseAJJBXXListSA.size(), gBaseAJJBXXListLA.size(), gBaseAJJBXXListPA.size(), range); // 为空就不执行,记录日志 if (gBaseJJDSList.isEmpty() && gBaseAJJBXXListSA.isEmpty() && gBaseAJJBXXListLA.isEmpty() && gBaseAJJBXXListPA.isEmpty()) { - businessLogMapper.insert(new BusinessLog().setType("单位业务数据").setNum(0).setCreateTime(LocalDateTime.now())); - log.info("{}没有单位数据", happenTime.get(0)); + businessLogMapper.insert(new BusinessLog().setType("单位业务数据").setNum(0).setActualNum(0).setCreateTime(LocalDateTime.now())); + log.info("【单位业务数据】无数据,已写入业务日志(type=单位业务数据,num=0),时间范围={}", range); return; } - List departIds = new ArrayList<>(); - // 获取管辖单位代码 - generateDepartIds(gBaseJJDSList, departIds, gBaseAJJBXXListSA, gBaseAJJBXXListLA, gBaseAJJBXXListPA); - if (departIds.isEmpty()) { - return; - } - // 关联表获取单位id和内部id 例如:430105424500——13365 湖南省长沙市公安局开福分局望麓园派出所五中队——(湖南省长沙市公安局开福分局望麓园派出所五中队)望麓园所五中队 - List> idsByDepartIds = supExternalDepartMapper.getIdsByDepartIds(departIds);// - // 单位ID的映射:430100221100-1011(内部ID) - Map resultMap2 = idsByDepartIds.stream().filter(map -> map.get("external_id") != null).collect(Collectors.toMap( - map -> (String) map.get("external_id"), - map -> map.get("internal_id") == null ? "" : (String) map.get("internal_id") - )); - List values = resultMap2.values().stream().filter(Objects::nonNull).toList();// 去空 - // 单位短名的映射:430100221100-望麓园所五中队(这是内部短名) - Map resultMap3 = idsByDepartIds.stream().filter(map -> map.get("external_id") != null).collect(Collectors.toMap( - map -> (String) map.get("external_id"), - map -> map.get("internal_short_name") == null ? "" : (String) map.get("internal_short_name") - )); - List> resultList = new ArrayList<>(); // 分组: 长沙县局ID:xxx派出所ID、xxx派出所ID - if (!values.isEmpty()) { - resultList = statisticsDepartMapper.getGroupIdsByDepartIds(values); - } - if (resultList.isEmpty()) { // 如果没有查到ID,则不执行插入操作 - businessLogMapper.insert(new BusinessLog().setType("单位业务数据").setNum(0).setCreateTime(LocalDateTime.now())); - log.info("{}没有单位数据", happenTime.get(0)); - return; - } - // 分组ID的映射:xxx(内部ID)——长沙县局ID - Map resultMap = resultList.stream().collect(Collectors.toMap(map -> (String) map.get("departId"), map -> (Long) map.get("groupId"))); - List groupIds = new ArrayList<>(); - log.info("映射成是我们单位的数据"); - // 映射成是我们单位的数据 - generateBusinessDepartList(happenTime, gBaseJJDSList, resultMap, resultMap2, resultMap3, groupIds, businessDepartList, gBaseAJJBXXListSA, gBaseAJJBXXListLA, gBaseAJJBXXListPA); - List> nameList = statisticsGroupMapper.getNameByGroupIds(groupIds); - Map names = nameList.stream().collect(Collectors.toMap(map -> (Long) map.get("groupId"), map -> (String) map.get("name"))); + // 1.1 情指行(JJD):externalId = gxdwdm + List jjdExternalIds = gBaseJJDSList.stream().filter(Objects::nonNull).map(GBaseJJD::getGxdwdm).filter(StrUtil::isNotBlank).toList(); + // 1.2 执法办案(CASE):SA 用 BADWIDdm,LA 用 LADWBMdm,PA 用 PADWBMdm + // 注意:这里 externalId 口径就是你明确的对齐规则,后续任何地方不要再随意换字段 + List caseExternalIds = new ArrayList<>(); + caseExternalIds.addAll(gBaseAJJBXXListSA.stream().filter(Objects::nonNull).map(GBaseAJJBXX::getBADWIDdm).filter(StrUtil::isNotBlank).toList()); + caseExternalIds.addAll(gBaseAJJBXXListLA.stream().filter(Objects::nonNull).map(GBaseAJJBXX::getBADWIDdm).filter(StrUtil::isNotBlank).toList()); + caseExternalIds.addAll(gBaseAJJBXXListPA.stream().filter(Objects::nonNull).map(GBaseAJJBXX::getBADWIDdm).filter(StrUtil::isNotBlank).toList()); + DepartMapping qzxMapping = buildMapping(jjdExternalIds, "情指行"); + DepartMapping zfbaMapping = buildMapping(caseExternalIds, "执法办案"); + // 日志 + BusinessDepartLogDTO logDTO = new BusinessDepartLogDTO(); + logDTO.setJjdList(gBaseJJDSList); + logDTO.setSaList(gBaseAJJBXXListSA); + logDTO.setLaList(gBaseAJJBXXListLA); + logDTO.setPaList(gBaseAJJBXXListPA); + logDTO.setQzxMapping(qzxMapping); + logDTO.setZfbaMapping(zfbaMapping); + this.logMissingNoDedup(logDTO); + // 业务组装 + List businessDepartList = new ArrayList<>(); + appendJjdBusiness(businessDepartList, gBaseJJDSList, qzxMapping); + appendCaseBusiness(businessDepartList, gBaseAJJBXXListSA, zfbaMapping, 1); + appendCaseBusiness(businessDepartList, gBaseAJJBXXListLA, zfbaMapping, 2); + appendCaseBusiness(businessDepartList, gBaseAJJBXXListPA, zfbaMapping, 3); +// List departIds = new ArrayList<>(); +// // 获取管辖单位代码 +// generateDepartIds(gBaseJJDSList, departIds, gBaseAJJBXXListSA, gBaseAJJBXXListLA, gBaseAJJBXXListPA); +// if (departIds.isEmpty()) { +// return; +// } +// List> idsByDepartIds = supExternalDepartMapper.getIdsByDepartIds(departIds);// +// // ===== 新增:打印没有映射到 sup_external_depart 的单位 ===== +// BusinessDepartLogDTO businessDepartLogDTO = new BusinessDepartLogDTO(); +// businessDepartLogDTO.setIdsByDepartIds(idsByDepartIds); +// businessDepartLogDTO.setGBaseJJDSList(gBaseJJDSList); +// businessDepartLogDTO.setGBaseAJJBXXListSA(gBaseAJJBXXListSA); +// businessDepartLogDTO.setGBaseAJJBXXListLA(gBaseAJJBXXListLA); +// businessDepartLogDTO.setGBaseAJJBXXListPA(gBaseAJJBXXListPA); +// this.logNoDepart(businessDepartLogDTO); +// Map resultMap2 = idsByDepartIds.stream() +// .filter(map -> map.get("external_id") != null) +// .collect(Collectors.toMap( +// map -> (String) map.get("external_id"), +// map -> map.get("internal_id") == null ? "" : (String) map.get("internal_id") +// )); +// List values = resultMap2.values().stream().filter(Objects::nonNull).toList();// 去空 +// Map resultMap3 = idsByDepartIds.stream().filter(map -> map.get("external_id") != null).collect(Collectors.toMap( +// map -> (String) map.get("external_id"), +// map -> map.get("internal_short_name") == null ? "" : (String) map.get("internal_short_name") +// )); +// List> resultList = new ArrayList<>(); // 分组: 长沙县局ID:xxx派出所ID、xxx派出所ID +// if (!values.isEmpty()) { +// resultList = supDepartMapper.getGroupIdsByDepartIds(values); +// } +// if (resultList.isEmpty()) { +// businessLogMapper.insert(new BusinessLog().setType("单位业务数据").setNum(0).setActualNum(0).setCreateTime(LocalDateTime.now())); +// log.info("{}没有单位数据", happenTime.get(0)); +// return; +// } +// Map resultMap = resultList.stream() +// .filter(m -> m.get("departId") != null && m.get("groupId") != null) +// .collect(Collectors.toMap(map -> String.valueOf(map.get("departId")), map -> ((Number) map.get("groupId")).longValue())); +// List groupIds = new ArrayList<>(); +// generateBusinessDepartList(happenTime, gBaseJJDSList, resultMap, resultMap2, resultMap3, groupIds, businessDepartList, gBaseAJJBXXListSA, gBaseAJJBXXListLA, gBaseAJJBXXListPA); + Map names = statisticsGroupService.groupIdMap(); for (BusinessDepart businessDepart : businessDepartList) { - businessDepart.setGroupName(names.get(businessDepart.getGroupId())); + String groupIdKey = String.valueOf(businessDepart.getGroupId()); + StatisticsGroup group = names.get(groupIdKey); + businessDepart.setGroupName(group != null ? group.getName() : null); businessDepart.setCreateTime(LocalDateTime.now()); } log.info("单位业务数据准备插入:{}", businessDepartList.size()); @@ -159,6 +191,43 @@ public class BusinessDepartService extends ServiceImpl out, List list, DepartMapping mapping, int type) { + if (list == null || list.isEmpty()) return; + for (GBaseAJJBXX a : list) { + if (a == null) continue; + String externalId; +// if (type == 1) { +// externalId = a.getBADWIDdm(); +// } else if (type == 2) { +// externalId = a.getLADWBMdm(); +// } else { +// externalId = a.getPADWBMdm(); +// } + externalId = a.getBADWIDdm(); + Long groupId = mapping.resolveGroupId(externalId); + if (groupId == null) continue; + BusinessDepart bd = new BusinessDepart(); + bd.setDepartId(mapping.resolveInternalId(externalId)); + bd.setDepartName(mapping.resolveInternalShortName(externalId)); + bd.setGroupId(groupId); + bd.setNumber(a.getBADWNum()); + if (type == 1) { + bd.setDate(a.getSLRQ()); + bd.setBusinessType("4"); + bd.setBusinessTypeName("执法办案(受案)"); + } else if (type == 2) { + bd.setDate(a.getLARQ()); + bd.setBusinessType("5"); + bd.setBusinessTypeName("执法办案(立案)"); + } else { + bd.setDate(a.getPARQ()); + bd.setBusinessType("6"); + bd.setBusinessTypeName("执法办案(破案)"); + } + out.add(bd); + } + } + private static void generateBusinessDepartList(List happenTime, List gBaseJJDSList, Map resultMap, Map resultMap2, Map resultMap3, List groupIds, List businessDepartList, List gBaseAJJBXXListSA, List gBaseAJJBXXListLA, List gBaseAJJBXXListPA) { for (GBaseJJD gBaseJJD : gBaseJJDSList) { Long groupId = resultMap.get(resultMap2.get(gBaseJJD.getGxdwdm())); @@ -215,7 +284,7 @@ public class BusinessDepartService extends ServiceImpl happenTime, GBaseJJD gBaseJJD, Long groupId, Map resultMap2, Map resultMap3) { BusinessDepart businessDepart = new BusinessDepart(); - businessDepart.setDate(happenTime.get(0)); + businessDepart.setDate(gBaseJJD.getCjsj()); businessDepart.setDepartId(resultMap2.get(gBaseJJD.getGxdwdm())); businessDepart.setDepartName(resultMap3.get(gBaseJJD.getGxdwdm())); businessDepart.setGroupId(groupId); @@ -234,18 +303,21 @@ public class BusinessDepartService extends ServiceImpl happenTime, GBaseAJJBXX gBasAJJBXX, Long groupId, int type, Map resultMap2, Map resultMap3) { BusinessDepart businessDepart = new BusinessDepart(); - businessDepart.setDate(happenTime.get(0)); +// businessDepart.setDate(gBasAJJBXX.getLARQ()); businessDepart.setDepartId(resultMap2.get(gBasAJJBXX.getBADWIDdm())); businessDepart.setDepartName(resultMap3.get(gBasAJJBXX.getBADWIDdm())); businessDepart.setGroupId(groupId); businessDepart.setNumber(gBasAJJBXX.getBADWNum()); if (type == 1) { + businessDepart.setDate(gBasAJJBXX.getSLRQ()); businessDepart.setBusinessType("4"); businessDepart.setBusinessTypeName("执法办案(受案)"); } else if (type == 2) { + businessDepart.setDate(gBasAJJBXX.getLARQ()); businessDepart.setBusinessType("5"); businessDepart.setBusinessTypeName("执法办案(立案)"); } else if (type == 3) { + businessDepart.setDate(gBasAJJBXX.getPARQ()); businessDepart.setBusinessType("6"); businessDepart.setBusinessTypeName("执法办案(破案)"); } @@ -258,7 +330,7 @@ public class BusinessDepartService extends ServiceImpl result = new ArrayList<>(); QueryWrapper queryWrapper = new QueryWrapper<>(); if (type == 1) { - queryWrapper.select("COUNT(BADWIDdm) as BADWNum, BADWIDdm, BADWIDmc").ne("AJBZdm", "3").between("slrq", happenTime.get(0), happenTime.get(1)).groupBy("BADWIDdm", "BADWIDmc"); + queryWrapper.select("CAST(DATE(SLRQ) AS DATETIME) as SLRQ, COUNT(BADWIDdm) as BADWNum, BADWIDdm, BADWIDmc").ne("AJBZdm", "3").between("slrq", happenTime.get(0), happenTime.get(1)).groupBy("DATE(SLRQ)", "BADWIDdm", "BADWIDmc"); } else if (type == 2) { - queryWrapper.select("COUNT(BADWIDdm) as BADWNum, BADWIDdm, BADWIDmc").ne("AJBZdm", "3").between("larq", happenTime.get(0), happenTime.get(1)).groupBy("BADWIDdm", "BADWIDmc"); + queryWrapper.select("CAST(DATE(LARQ) AS DATETIME) as LARQ, COUNT(BADWIDdm) as BADWNum, BADWIDdm, BADWIDmc").ne("AJBZdm", "3").between("larq", happenTime.get(0), happenTime.get(1)).groupBy("DATE(LARQ)", "BADWIDdm", "BADWIDmc"); } else if (type == 3) { - queryWrapper.select("COUNT(BADWIDdm) as BADWNum, BADWIDdm, BADWIDmc").ne("AJBZdm", "3").between("parq", happenTime.get(0), happenTime.get(1)).groupBy("BADWIDdm", "BADWIDmc"); + queryWrapper.select("CAST(DATE(PARQ) AS DATETIME) as PARQ, COUNT(BADWIDdm) as BADWNum, BADWIDdm, BADWIDmc").ne("AJBZdm", "3").between("parq", happenTime.get(0), happenTime.get(1)).groupBy("DATE(PARQ)", "BADWIDdm", "BADWIDmc"); } List gBaseAJJBXXs = gBaseAJJBXXMapper.selectList(queryWrapper); if (!gBaseAJJBXXs.isEmpty()) { @@ -289,4 +361,263 @@ public class BusinessDepartService extends ServiceImpl out, + List jjdList, + DepartMapping qzxMapping) { + if (out == null || jjdList == null || jjdList.isEmpty()) { + return; + } + + for (GBaseJJD jjd : jjdList) { + if (jjd == null) continue; + + // ===== 1. 情指行 externalId 口径 ===== + // 情指行固定使用 gxdwdm 作为外部单位编码 + String externalId = jjd.getGxdwdm(); + if (StrUtil.isBlank(externalId)) continue; + + // ===== 2. 解析 groupId(核心过滤条件)===== + Long groupId = qzxMapping.resolveGroupId(externalId); + if (groupId == null) { + // 无法映射到 group 的记录直接丢弃(保持旧逻辑行为) + continue; + } + + // ===== 3. 构建 BusinessDepart ===== + BusinessDepart bd = new BusinessDepart(); + bd.setDate(jjd.getCjsj()); + bd.setDepartId(qzxMapping.resolveInternalId(externalId)); + bd.setDepartName(qzxMapping.resolveInternalShortName(externalId)); + bd.setGroupId(groupId); + bd.setNumber(jjd.getJjdbhTotal()); + + // ===== 4. 业务类型判定(情指行专属规则)===== + if (groupId == 10L) { + bd.setBusinessType("1"); + bd.setBusinessTypeName("110接处警"); + } else if (groupId == 11L) { + bd.setBusinessType("2"); + bd.setBusinessTypeName("122接处警"); + } else { + // 理论上不会走到这里(目前只认 10/11) + // 这里留空是为了避免未来扩展时误判 + continue; + } + + out.add(bd); + } + } + + + + // ai生成 + /** + * 缺失单位映射日志(不去重) + */ + private void logMissingNoDedup(BusinessDepartLogDTO dto) { + if (dto == null) return; + // ===== 情指行 ===== + if (dto.getJjdList() != null) { + for (GBaseJJD jjd : dto.getJjdList()) { + if (jjd == null) continue; + logMissingNoDedup( + "JJD", + jjd.getGxdwdm(), + jjd.getGxdwmc(), + dto.getQzxMapping() + ); + } + } + // ===== 执法办案:受案 ===== + if (dto.getSaList() != null) { + for (GBaseAJJBXX a : dto.getSaList()) { + if (a == null) continue; + logMissingNoDedup( + "SA", + a.getBADWIDdm(), + a.getBADWIDmc(), + dto.getZfbaMapping() + ); + } + } + // ===== 执法办案:立案 ===== + if (dto.getLaList() != null) { + for (GBaseAJJBXX a : dto.getLaList()) { + if (a == null) continue; + logMissingNoDedup( + "LA", + a.getBADWIDdm(), + a.getBADWIDmc(), + dto.getZfbaMapping() + ); + } + } + // ===== 执法办案:破案 ===== + if (dto.getPaList() != null) { + for (GBaseAJJBXX a : dto.getPaList()) { + if (a == null) continue; + logMissingNoDedup( + "PA", + a.getBADWIDdm(), + a.getBADWIDmc(), + dto.getZfbaMapping() + ); + } + } + } + + + /** + * 缺失映射日志:不去重,按源记录逐条输出(满足你第 5 条要求) + * + * @param stage JJD/SA/LA/PA + * @param externalId 该条记录对应 externalId + * @param sourceName 源表单位名称(可能为空) + * @param mapping 当前 stage 对应的 mapping + */ + private void logMissingNoDedup(String stage, String externalId, String sourceName, DepartMapping mapping) { + if (StrUtil.isBlank(externalId)) return; + if (!mapping.mappedExternalIds().contains(externalId)) { + log.warn("【单位业务数据-外部单位未映射】stage={}, externalId={}, sourceName={}", + stage, + externalId, + StrUtil.blankToDefault(sourceName, "-")); + } + } + + + /** + * 构建某一个 source(情指行/执法办案)的一套映射。 + * + * 注意:你明确了 supDepartMapper.getGroupIdsByDepartIds 入参是 internal_id, + * 所以这里一定要先拿 internal_id 再查 groupId。 + */ + private DepartMapping buildMapping(Collection externalIds, String source) { + + // 1) 防御:无 externalId 直接返回空映射,避免 SQL IN () 报错 + if (externalIds == null || externalIds.isEmpty()) { + return new DepartMapping(Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap()); + } + // 2) 不做去重也行(你说日志不去重),但映射查询建议还是 distinct,避免 SQL 过长 + // 这里的 distinct 只影响查询入参,不影响你后面的日志逐条输出 + List distinctExternalIds = externalIds.stream() + .filter(StrUtil::isNotBlank) + .distinct() + .toList(); + + if (distinctExternalIds.isEmpty()) { + return new DepartMapping(Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap()); + } + + // 3) 按 source 查 sup_external_depart + List> rows = supExternalDepartMapper.getIdsByExternalIdsAndSource(distinctExternalIds, source); + + // 4) external -> internalId / shortName + // 注意 toMap 冲突要 merge,否则同 externalId 多行会直接抛异常导致任务失败 + Map externalToInternalId = (rows == null ? Collections.>emptyList() : rows) + .stream() + .filter(m -> m != null && m.get("external_id") != null) + .collect(Collectors.toMap( + m -> String.valueOf(m.get("external_id")), + m -> m.get("internal_id") == null ? null : String.valueOf(m.get("internal_id")), + (a, b) -> StrUtil.isNotBlank(a) ? a : b + )); + + Map externalToInternalShortName = (rows == null ? Collections.>emptyList() : rows) + .stream() + .filter(m -> m != null && m.get("external_id") != null) + .collect(Collectors.toMap( + m -> String.valueOf(m.get("external_id")), + m -> m.get("internal_short_name") == null ? null : String.valueOf(m.get("internal_short_name")), + (a, b) -> StrUtil.isNotBlank(a) ? a : b + )); + + // 5) internalIds(你确认 group 查的是 internal_id) + List internalIds = externalToInternalId.values().stream() + .filter(StrUtil::isNotBlank) + .distinct() + .toList(); + + if (internalIds.isEmpty()) { + return new DepartMapping(externalToInternalId, externalToInternalShortName, Collections.emptyMap()); + } + + // 6) internalId -> groupId + List> groupRows = supDepartMapper.getGroupIdsByDepartIds(internalIds); + + Map internalIdToGroupId = (groupRows == null ? Collections.>emptyList() : groupRows) + .stream() + .filter(m -> m != null && m.get("departId") != null && m.get("groupId") != null) + .collect(Collectors.toMap( + m -> String.valueOf(m.get("departId")), // departId 实际为 internal_id + m -> ((Number) m.get("groupId")).longValue(), + (a, b) -> a + )); + + return new DepartMapping(externalToInternalId, externalToInternalShortName, internalIdToGroupId); + } + + + + /** + * 单套单位映射(只服务一种 source 的口径,比如“情指行”或“执法办案”) + * + * external -> internalId + * external -> internalShortName + * internalId -> groupId + * + * 这样组合 BusinessDepart 时只要传对应 mapping,就不会串口径。 + */ + public static class DepartMapping { + private final Map externalToInternalId; + private final Map externalToInternalShortName; + private final Map internalIdToGroupId; + + private DepartMapping(Map externalToInternalId, + Map externalToInternalShortName, + Map internalIdToGroupId) { + this.externalToInternalId = externalToInternalId; + this.externalToInternalShortName = externalToInternalShortName; + this.internalIdToGroupId = internalIdToGroupId; + } + + /** + * 通过 externalId 解析 groupId: + * 1) externalId -> internalId + * 2) internalId -> groupId + */ + public Long resolveGroupId(String externalId) { + if (StrUtil.isBlank(externalId)) return null; + String internalId = externalToInternalId.get(externalId); + if (StrUtil.isBlank(internalId)) return null; + return internalIdToGroupId.get(internalId); + } + + public String resolveInternalId(String externalId) { + return StrUtil.isBlank(externalId) ? null : externalToInternalId.get(externalId); + } + + public String resolveInternalShortName(String externalId) { + return StrUtil.isBlank(externalId) ? null : externalToInternalShortName.get(externalId); + } + + public Set mappedExternalIds() { + return externalToInternalId.keySet(); + } + } + + } diff --git a/src/main/java/com/biutag/supervision/service/StatisticsGroupService.java b/src/main/java/com/biutag/supervision/service/StatisticsGroupService.java index 5012593..c2f7547 100644 --- a/src/main/java/com/biutag/supervision/service/StatisticsGroupService.java +++ b/src/main/java/com/biutag/supervision/service/StatisticsGroupService.java @@ -1,11 +1,41 @@ package com.biutag.supervision.service; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.biutag.supervision.pojo.entity.StatisticsGroup; import com.biutag.supervision.mapper.StatisticsGroupMapper; import org.springframework.stereotype.Service; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + @Service public class StatisticsGroupService extends ServiceImpl { + + /** + * 获取 groupId -> StatisticsGroup 的映射 + * key: groupId + * value: StatisticsGroup + * 若存在重复 groupId,保留第一条 + */ + public Map groupIdMap() { + List list = this.list(); + + if (list == null || list.isEmpty()) { + return Collections.emptyMap(); + } + return list.stream() + .filter(Objects::nonNull) + .filter(g -> StrUtil.isNotBlank(g.getGroupId())) + .collect(Collectors.toMap( + StatisticsGroup::getGroupId, + g -> g, + (oldVal, newVal) -> oldVal // 防止重复 key 抛异常 + )); + } + } diff --git a/src/main/resources/mapper/GBaseJJDMapper.xml b/src/main/resources/mapper/GBaseJJDMapper.xml index 45d98a1..fd49f41 100644 --- a/src/main/resources/mapper/GBaseJJDMapper.xml +++ b/src/main/resources/mapper/GBaseJJDMapper.xml @@ -5,7 +5,7 @@