From ca5b6e4672e6efaef8ec191ab96288e5fb4065af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=A6=E9=B8=BF=E5=B1=95?= <18031053041@163.com> Date: Tue, 15 Sep 2026 17:13:30 +0800 Subject: [PATCH] =?UTF-8?q?BI=E5=9B=AD=E5=8C=BA=E5=A4=A7=E5=B1=8F=E6=8C=87?= =?UTF-8?q?=E6=A0=87=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapper/BiPlatformRealDataMapper.java | 30 ++ .../po/RealMonthlyAvgDurationPO.java | 32 ++ .../po/RealMonthlyTaskDurationPO.java | 2 +- .../repository/po/RealOvertimeRecordPO.java | 30 ++ .../repository/po/RealOvertimeStatPO.java | 27 ++ .../po/RealPlatformFloorStatPO.java | 4 + .../repository/po/RealTaskLoadPO.java | 10 +- .../repository/po/RealTodayAvgDurationPO.java | 34 ++ .../service/BiPlatformRealDataService.java | 297 ++++++++++++++---- .../BiReportSnapshotMapperSupport.java | 2 + .../service/BiReportSnapshotSyncService.java | 97 ++++-- .../BiSnapshotWeeklyRandomDataBuilder.java | 29 +- .../mapper/BiStaticFieldMapper.java | 23 ++ .../repository/po/BiStaticFieldPO.java | 38 +++ .../service/BiStaticFieldService.java | 108 +++++++ .../BiWarehouseTransportRealDataMapper.java | 32 ++ .../repository/po/RealCustomerRankPO.java | 21 ++ .../po/RealWarehouseOrderStatPO.java | 25 ++ .../BiWarehouseTransportRealDataService.java | 99 ++++++ .../BiWarehouseTransportReportService.java | 108 ++++++- .../vo/CustomerContributionRankVO.java | 2 +- .../vo/platform/OvertimeRecordItemVO.java | 31 ++ .../vo/platform/PlatformSurveillanceVO.java | 6 + .../BiPlatformRealDataMapper.xml | 201 ++++++++++-- .../biStaticField/BiStaticFieldMapper.xml | 52 +++ .../BiWarehouseTransportRealDataMapper.xml | 77 +++++ 26 files changed, 1284 insertions(+), 133 deletions(-) create mode 100644 mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealMonthlyAvgDurationPO.java create mode 100644 mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealOvertimeRecordPO.java create mode 100644 mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealOvertimeStatPO.java create mode 100644 mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealTodayAvgDurationPO.java create mode 100644 mhd-bi/src/main/java/com/mhd/bi/domain/biStaticField/repository/mapper/BiStaticFieldMapper.java create mode 100644 mhd-bi/src/main/java/com/mhd/bi/domain/biStaticField/repository/po/BiStaticFieldPO.java create mode 100644 mhd-bi/src/main/java/com/mhd/bi/domain/biStaticField/service/BiStaticFieldService.java create mode 100644 mhd-bi/src/main/java/com/mhd/bi/domain/biWarehouseTransport/repository/mapper/BiWarehouseTransportRealDataMapper.java create mode 100644 mhd-bi/src/main/java/com/mhd/bi/domain/biWarehouseTransport/repository/po/RealCustomerRankPO.java create mode 100644 mhd-bi/src/main/java/com/mhd/bi/domain/biWarehouseTransport/repository/po/RealWarehouseOrderStatPO.java create mode 100644 mhd-bi/src/main/java/com/mhd/bi/domain/biWarehouseTransport/service/BiWarehouseTransportRealDataService.java create mode 100644 mhd-bi/src/main/java/com/mhd/bi/interfaces/facadeApi/biReport/vo/platform/OvertimeRecordItemVO.java create mode 100644 mhd-bi/src/main/resources/mapper/biStaticField/BiStaticFieldMapper.xml create mode 100644 mhd-bi/src/main/resources/mapper/biWarehouseTransport/BiWarehouseTransportRealDataMapper.xml diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/mapper/BiPlatformRealDataMapper.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/mapper/BiPlatformRealDataMapper.java index dae04e97d..e371d48ce 100644 --- a/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/mapper/BiPlatformRealDataMapper.java +++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/mapper/BiPlatformRealDataMapper.java @@ -10,6 +10,15 @@ import com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformInfoPO; import com.mhd.bi.domain.biPlatformRealData.repository.po.RealOnTimeStatPO; import com.mhd.bi.domain.biPlatformRealData.repository.po.RealTaskTypeStatPO; import com.mhd.bi.domain.biPlatformRealData.repository.po.RealMonthlyTaskDurationPO; +import com.mhd.bi.domain.biPlatformRealData.repository.po.RealMonthlyAvgDurationPO; +import com.mhd.bi.domain.biPlatformRealData.repository.po.RealTodayAvgDurationPO; +import com.mhd.bi.domain.biPlatformRealData.repository.po.RealOvertimeStatPO; +import com.mhd.bi.domain.biPlatformRealData.repository.po.RealOvertimeRecordPO; + + + + +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -41,6 +50,27 @@ public interface BiPlatformRealDataMapper { /** 任务负荷(今日 24 小时) */ List queryTaskLoadToday(); + /** 近半年平均作业时长(按月分组:月台作业时长 / 园区作业时长 合计 + 任务数) */ + List queryMonthlyAvgDuration(); + + /** 今日平均作业时长(月台作业平均时长 / 园区平均时长,仅统计两端时间都非空的记录) */ + RealTodayAvgDurationPO queryTodayAvgDuration(); + + /** + * 今日月台作业超时统计(超时记录数 / 有效记录总数)。 + * 参考用时取自 YMS QMS_STATIC_FIELD.FIELD_CODE = 'platform_work_ref_minutes' + */ + RealOvertimeStatPO queryTodayOvertimeStat(@Param("refCode") String refCode); + + /** + * 今日园区作业超时统计(超时记录数 / 有效记录总数)。 + * 参考用时取自 YMS QMS_STATIC_FIELD.FIELD_CODE = 'yard_work_ref_minutes' + */ + RealOvertimeStatPO queryTodayYardOvertimeStat(@Param("refCode") String refCode); + + /** 今日月台作业超时记录列表(月台名称 / 车牌号 / 超时时长) */ + List queryTodayOvertimeList(@Param("refCode") String refCode); + /** 今日预约-业务类型统计(按 businessName 分组统计今日预约数量) */ List queryTodayBusinessTypeStats(); diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealMonthlyAvgDurationPO.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealMonthlyAvgDurationPO.java new file mode 100644 index 000000000..f96bd0832 --- /dev/null +++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealMonthlyAvgDurationPO.java @@ -0,0 +1,32 @@ +package com.mhd.bi.domain.biPlatformRealData.repository.po; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 按月平均作业时长(真实数据,来自 TEST_NGWL_YMS.QMS_MAIN_BUSINESS) + * + *

用于「平均作业时长」近半年趋势图,双系列:月台作业 / 园区作业。

+ *
    + *
  • 月台作业时长 = 离开月台时间(OUT_WINDOWS_TIME) - 进入月台时间(IN_WINDOWS_TIME)
  • + *
  • 园区作业时长 = 实际出场时间(EXIT_TIME) - 实际进入时间(ENTRY_TIME)
  • + *
+ *

各月平均 = 该月有效记录的时长合计 ÷ 该月任务数。

+ */ +@Data +public class RealMonthlyAvgDurationPO implements Serializable { + private static final long serialVersionUID = 1L; + + /** 月份,格式 yyyy-MM */ + private String monthOfYear; + + /** 该月任务数(预约记录数,作为平均时长的分母) */ + private Long taskCount; + + /** 该月月台作业时长合计(小时);未进入月台计 0,已进入未离开按 SYSDATE - IN_WINDOWS_TIME */ + private Double platformWorkHours; + + /** 该月园区作业时长合计(小时);未进场计 0,已进场未出场按 SYSDATE - ENTRY_TIME */ + private Double yardWorkHours; +} diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealMonthlyTaskDurationPO.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealMonthlyTaskDurationPO.java index fab9f2046..c5d41e89c 100644 --- a/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealMonthlyTaskDurationPO.java +++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealMonthlyTaskDurationPO.java @@ -6,7 +6,7 @@ import java.io.Serializable; /** * 本月任务平均时长 / 完成率统计(真实数据,来自 TEST_NGWL_YMS.QMS_MAIN_BUSINESS) - * totalWorkHours:本月任务作业时长合计(小时),未进入月台计 0、已进入未离开按 SYSDATE-ENTRY_TIME + * totalWorkHours:本月任务作业时长合计(小时),未进入月台计 0、已进入未离开按 SYSDATE - IN_WINDOWS_TIME * completedCount:已出场(EXIT_TIME IS NOT NULL)且预约日期在本月的数量 * totalCount:本月(TARGET_DATE)预约总数量(作为平均时长的分母) * diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealOvertimeRecordPO.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealOvertimeRecordPO.java new file mode 100644 index 000000000..53e323efb --- /dev/null +++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealOvertimeRecordPO.java @@ -0,0 +1,30 @@ +package com.mhd.bi.domain.biPlatformRealData.repository.po; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 今日月台作业超时记录(真实数据) + * + *

用于「超时记录列表」:月台名称 / 车牌号码 / 超时时长(分钟)。

+ */ +@Data +public class RealOvertimeRecordPO implements Serializable { + private static final long serialVersionUID = 1L; + + /** 月台名称 */ + private String windowName; + + /** 车牌号码 */ + private String carNo; + + /** 超时时长(分钟)= 月台作业时长 - 参考用时 */ + private Long overtimeMinutes; + + /** 月台作业参考用时(分钟) */ + private Long refMinutes; + + /** 月台作业时长(分钟) */ + private Long platformMinutes; +} diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealOvertimeStatPO.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealOvertimeStatPO.java new file mode 100644 index 000000000..bc89d07bb --- /dev/null +++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealOvertimeStatPO.java @@ -0,0 +1,27 @@ +package com.mhd.bi.domain.biPlatformRealData.repository.po; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 今日作业超时统计(月台作业 / 园区作业 通用) + * + *

分母只计入「能取到参考用时 且 作业时长两端时间都非空」的记录。

+ *
    + *
  • 月台作业:参考用时 code = platform_work_ref_minutes; + * 时长 = OUT_WINDOWS_TIME - IN_WINDOWS_TIME
  • + *
  • 园区作业:参考用时 code = yard_work_ref_minutes; + * 时长 = EXIT_TIME - ENTRY_TIME
  • + *
+ */ +@Data +public class RealOvertimeStatPO implements Serializable { + private static final long serialVersionUID = 1L; + + /** 超时记录数:作业时长 > 参考用时 */ + private Long overtimeCount; + + /** 有效记录总数(分母) */ + private Long totalCount; +} diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealPlatformFloorStatPO.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealPlatformFloorStatPO.java index c3c600faf..30511432d 100644 --- a/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealPlatformFloorStatPO.java +++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealPlatformFloorStatPO.java @@ -23,4 +23,8 @@ public class RealPlatformFloorStatPO implements Serializable { /** 当前作业车辆数(FLOW_STATUS IN 5,6,7,8,9,10) */ private Long operatingVehicles; + + /** 该楼层月台作业平均时长(分钟)= SUM(该楼层有效月台作业时长) ÷ 该楼层有效记录数 */ + private Double avgPlatformMinutes; } + diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealTaskLoadPO.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealTaskLoadPO.java index d9c70f669..486e182f3 100644 --- a/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealTaskLoadPO.java +++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealTaskLoadPO.java @@ -4,15 +4,17 @@ import lombok.Data; import java.io.Serializable; /** - * 任务负荷统计(按小时,来自 TEST_NGWL_YMS.QMS_MAIN_BUSINESS) + * 任务负荷统计(按 2 小时分组,来自 TEST_NGWL_YMS.QMS_MAIN_BUSINESS) + * + *

「小时趋势」需求:每 2 小时分组统计一次,按车辆进入月台时间 IN_WINDOWS_TIME 分桶。

*/ @Data public class RealTaskLoadPO implements Serializable { private static final long serialVersionUID = 1L; - /** 0-23 小时 */ + /** 2 小时分组的起始小时,取值 0,2,4,...,22 */ private Integer hourOfDay; - /** 该小时段任务数 */ + /** 该 2 小时时段任务数 */ private Long taskCount; -} \ No newline at end of file +} diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealTodayAvgDurationPO.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealTodayAvgDurationPO.java new file mode 100644 index 000000000..41f4898f8 --- /dev/null +++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/repository/po/RealTodayAvgDurationPO.java @@ -0,0 +1,34 @@ +package com.mhd.bi.domain.biPlatformRealData.repository.po; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 今日平均作业时长(真实数据,来自 TEST_NGWL_YMS.QMS_MAIN_BUSINESS) + * + *

用于「效率统计(本日)」中的:

+ *
    + *
  • 月台作业平均时长 avgPlatformDurationHours
  • + *
  • 园区平均时长 avgYardDurationHours
  • + *
+ * + *

统计范围:今日预约记录(TARGET_DATE = 今天),且只统计时长两端的字段都非空的记录:

+ *
    + *
  • 月台作业时长 = 离开月台时间(OUT_WINDOWS_TIME) - 进入月台时间(IN_WINDOWS_TIME) + * → 只统计 IN_WINDOWS_TIME 与 OUT_WINDOWS_TIME 都非空的记录
  • + *
  • 园区作业时长 = 实际出场时间(EXIT_TIME) - 实际进入时间(ENTRY_TIME) + * → 只统计 ENTRY_TIME 与 EXIT_TIME 都非空的记录
  • + *
+ *

平均时长 = 有效记录时长合计 ÷ 有效记录数,由 Service 层或 SQL 直接完成。

+ */ +@Data +public class RealTodayAvgDurationPO implements Serializable { + private static final long serialVersionUID = 1L; + + /** 月台作业平均时长(小时),仅统计同时有进入与离开月台时间的记录 */ + private Double avgPlatformDurationHours; + + /** 园区平均时长(小时),仅统计同时有实际进入与实际出场时间的记录 */ + private Double avgYardDurationHours; +} diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/service/BiPlatformRealDataService.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/service/BiPlatformRealDataService.java index 8b68e5892..682b07691 100644 --- a/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/service/BiPlatformRealDataService.java +++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biPlatformRealData/service/BiPlatformRealDataService.java @@ -12,13 +12,23 @@ import com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformInfoPO; import com.mhd.bi.domain.biPlatformRealData.repository.po.RealOnTimeStatPO; import com.mhd.bi.domain.biPlatformRealData.repository.po.RealTaskTypeStatPO; import com.mhd.bi.domain.biPlatformRealData.repository.po.RealMonthlyTaskDurationPO; +import com.mhd.bi.domain.biPlatformRealData.repository.po.RealMonthlyAvgDurationPO; +import com.mhd.bi.domain.biPlatformRealData.repository.po.RealTodayAvgDurationPO; +import com.mhd.bi.domain.biPlatformRealData.repository.po.RealOvertimeStatPO; +import com.mhd.bi.domain.biPlatformRealData.repository.po.RealOvertimeRecordPO; + import com.mhd.bi.domain.biPlatformSurveillance.repository.mapper.BiPlatformSurveillanceReportMapper; +import com.mhd.bi.domain.biStaticField.service.BiStaticFieldService; + import com.mhd.bi.domain.biSnapshotSync.repository.mapper.BiSnapshotWriteMapper; import com.mhd.bi.domain.biSnapshotSync.support.BiSnapshotWeeklyRandomDataBuilder; +import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.AvgOperationDurationTrendItemVO; +import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.OvertimeRecordItemVO; import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.PlatformSurveillanceVO; import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.PlatformVehicleItemVO; + import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.TaskLoadItemVO; import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.TaskTypeStatisticsVO; import com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.TaskTypeCountItemVO; @@ -102,9 +112,13 @@ public class BiPlatformRealDataService { fp.put("todayTasks", vo.getPlatformOverview().getTodayTasks()); fp.put("platformTurnoverRate", vo.getPlatformOverview().getPlatformTurnoverRate()); } + // 入园超时率/超时数量 按业务要求恒为 0,不纳入指纹 + // 准时率与平均时长为实时业务数据,纳入指纹 if (vo.getEfficiencyStatistics() != null) { fp.put("platformOnTimeRate", vo.getEfficiencyStatistics().getPlatformOnTimeRate()); + fp.put("yardOnTimeRate", vo.getEfficiencyStatistics().getYardOnTimeRate()); fp.put("avgPlatformDuration", vo.getEfficiencyStatistics().getAvgPlatformDuration()); + fp.put("avgYardDuration", vo.getEfficiencyStatistics().getAvgYardDuration()); } if (vo.getVehicleStatus() != null) { fp.put("todayReservedVehicles", vo.getVehicleStatus().getTodayReservedVehicles()); @@ -146,7 +160,34 @@ public class BiPlatformRealDataService { } fp.put("taskLoadStatistics", loads); } + if (vo.getAvgOperationDurationTrend() != null) { + + + List> trend = new ArrayList<>(); + for (AvgOperationDurationTrendItemVO item : vo.getAvgOperationDurationTrend()) { + Map m = new LinkedHashMap<>(); + m.put("month", item.getMonth()); + m.put("yardDuration", item.getYardDuration()); + m.put("platformDuration", item.getPlatformDuration()); + trend.add(m); + } + fp.put("avgOperationDurationTrend", trend); + } + fp.put("taskOvertimeRate", vo.getTaskOvertimeRate()); + if (vo.getOvertimeRecords() != null) { + List> recs = new ArrayList<>(); + for (OvertimeRecordItemVO r : vo.getOvertimeRecords()) { + Map m = new LinkedHashMap<>(); + m.put("windowName", r.getWindowName()); + m.put("carNo", r.getCarNo()); + m.put("overtimeMinutes", r.getOvertimeMinutes()); + recs.add(m); + } + fp.put("overtimeRecords", recs); + } + if (vo.getTaskTypeStatistics() != null) { + Map m = new LinkedHashMap<>(); m.put("totalTasks", vo.getTaskTypeStatistics().getTotalTasks()); if (vo.getTaskTypeStatistics().getTaskTypes() != null) { @@ -255,41 +296,9 @@ public class BiPlatformRealDataService { } - /** - * 月台作业平均时长(小时)= 今日作业车辆「月台作业时长(分钟)」之和 ÷ 车辆数 ÷ 60。 - * 仅统计已进入月台(platformDuration 大于 0)的车辆;无有效数据返回 0。 - * 保留两位小数。 - */ - public double calcTodayAvgPlatformDuration(List vehicles) { - try { - if (vehicles == null || vehicles.isEmpty()) { - return 0d; - } - long sumMinutes = 0L; - int count = 0; - for (PlatformVehicleItemVO v : vehicles) { - if (v == null || v.getPlatformDuration() == null) { - continue; - } - // 仅统计已进入月台的车辆(未进入月台时长为 0,不参与平均) - if (v.getPlatformDuration() > 0) { - sumMinutes += v.getPlatformDuration(); - count++; - } - } - if (count <= 0) { - return 0d; - } - double avgHours = (double) sumMinutes / (double) count / 60.0; - return Math.round(avgHours * 100.0) / 100.0; - } catch (Exception e) { - log.error("【YMS】计算月台作业平均时长失败: {}", e.getMessage(), e); - return 0d; - } - } - public long countMonthTasks() { + try { Long n = biPlatformRealDataMapper.countMonthTasks(); return n == null ? 0L : n; @@ -301,7 +310,7 @@ public class BiPlatformRealDataService { /** * 本月任务平均时长 / 完成率统计: - * - totalWorkHours:本月任务作业时长合计(小时);未进入月台计 0,已进入未离开按 SYSDATE-ENTRY_TIME + * - totalWorkHours:本月任务作业时长合计(小时);未进入月台计 0,已进入未离开按 SYSDATE - IN_WINDOWS_TIME * - avgDurationHours:任务平均作业时长 = totalWorkHours ÷ 本月任务数(totalCount),保留两位小数 * - taskCompletionRate:已完成(EXIT_TIME 不为空 且 预约日期在本月)/ 本月预约总数量 ×100 * 任一查询失败均返回 null,由调用方决定是否覆盖模板值。 @@ -452,12 +461,27 @@ public class BiPlatformRealDataService { template.getPlatformOverview().setCurrentOccupancyRate(rate); template.getPlatformOverview().setTodayTasks(todayTasks); - // 作业准时率(实际进入时间 < 预约日期+预约结束时间 的车辆 / 今日预约总数 × 100% 取整) - if (template.getEfficiencyStatistics() != null) { - template.getEfficiencyStatistics().setPlatformOnTimeRate(calcTodayOnTimeRate()); - } + // 作业准时率:任务超时率 + 月台作业准时率 = 100%(需求约定) + // 月台作业准时率 = 100 - 月台作业超时率 + double platformOvertime = calcTodayTaskOvertimeRate(); + template.getEfficiencyStatistics().setPlatformOnTimeRate( + (int) Math.round(100.0 - platformOvertime)); + // 园区作业准时率 = 100 - 园区作业超时率 + double yardOvertime = calcTodayYardOvertimeRate(); + template.getEfficiencyStatistics().setYardOnTimeRate( + (int) Math.round(100.0 - yardOvertime)); } + + // 平均作业时长(本日):月台作业平均时长 / 园区平均时长(真实数据,仅统计两端时间都非空的今日记录) + if (template.getEfficiencyStatistics() != null) { + RealTodayAvgDurationPO avg = queryTodayAvgDuration(); + template.getEfficiencyStatistics().setAvgPlatformDuration(avg.getAvgPlatformDurationHours()); + template.getEfficiencyStatistics().setAvgYardDuration(avg.getAvgYardDurationHours()); + } + + + // 作业车辆状态统计:真实数据源,无条件覆盖(含等待作业 waiting = 今日预约且 已预约/已签到/已叫号) if (template.getVehicleStatus() != null) { RealVehicleStatusPO vs = queryVehicleStatusToday(); @@ -502,47 +526,208 @@ public class BiPlatformRealDataService { } } - // 平均装卸时长 = 月台作业平均时长(今日作业车辆 platformDuration 的平均值,保留两位小数) - if (template.getEfficiencyStatistics() != null) { - template.getEfficiencyStatistics().setAvgPlatformDuration(calcTodayAvgPlatformDuration(vehicleVos)); - } + // 平均装卸时长按业务要求恒为 0,不用真实值覆盖 - // 任务负荷:有真实数据源;真实为空则清空不用模板模拟,有数据则按真实小时覆盖 + + // 小时趋势(今日,每 2 小时分组):有真实数据源则按真实分桶重建,无数据则清空 List loads = queryTaskLoadToday(); if (loads.isEmpty()) { template.setTaskLoadStatistics(new ArrayList<>()); - } else if (template.getTaskLoadStatistics() != null) { - Map hourMap = new HashMap<>(); + } else { + Map bucketMap = new HashMap<>(); for (RealTaskLoadPO l : loads) { - hourMap.put(l.getHourOfDay(), l.getTaskCount()); - } - for (TaskLoadItemVO item : template.getTaskLoadStatistics()) { - Integer hour = parseHourFromLabel(item.getTime()); - if (hour != null && hourMap.containsKey(hour)) { - item.setTaskCount(hourMap.get(hour).intValue()); + if (l != null && l.getHourOfDay() != null) { + bucketMap.put(l.getHourOfDay(), l.getTaskCount() == null ? 0L : l.getTaskCount()); } } + // 固定输出 0,2,4,...,22 共 12 个桶,无数据桶补 0,保证前端坐标轴连续 + List items = new ArrayList<>(); + for (int h = 0; h < 24; h += 2) { + Long cnt = bucketMap.get(h); + items.add(TaskLoadItemVO.builder() + .time(String.format("%02d:00", h)) + .taskCount(cnt == null ? 0 : cnt.intValue()) + .build()); + } + template.setTaskLoadStatistics(items); } + // 任务类型统计:本月 YMS QMS_MAIN_BUSINESS 按业务类型 BUSINESS_NAME 分组(真实业务数据) template.setTaskTypeStatistics(queryMonthTransportOrderByType()); + // 平均作业时长趋势:近半年按月统计(月台作业平均时长 / 园区作业平均时长) + template.setAvgOperationDurationTrend(queryAvgOperationDurationTrend()); + + // 任务超时率 + 月台作业超时记录列表(依赖 YMS QMS_STATIC_FIELD 参考用时配置) + template.setTaskOvertimeRate(calcTodayTaskOvertimeRate()); + template.setOvertimeRecords(queryTodayOvertimeRecords()); + return template; } - private static Integer parseHourFromLabel(String label) { - if (label == null) return null; + + + /** + * 今日平均作业时长(效率统计-本日),保留两位小数,单位:小时。 + * - avgPlatformDurationHours:月台作业平均时长;仅统计同时有进入与离开月台时间的今日记录 + * - avgYardDurationHours: 园区平均时长;仅统计同时有实际进入与实际出场时间的今日记录 + * 查询失败或无有效记录时返回 0。 + */ + public RealTodayAvgDurationPO queryTodayAvgDuration() { + RealTodayAvgDurationPO po = new RealTodayAvgDurationPO(); + po.setAvgPlatformDurationHours(0d); + po.setAvgYardDurationHours(0d); try { - String s = label.replace("时", "").trim(); - return Integer.parseInt(s); + RealTodayAvgDurationPO row = biPlatformRealDataMapper.queryTodayAvgDuration(); + if (row != null) { + if (row.getAvgPlatformDurationHours() != null) { + po.setAvgPlatformDurationHours( + Math.round(row.getAvgPlatformDurationHours() * 100.0) / 100.0); + } + if (row.getAvgYardDurationHours() != null) { + po.setAvgYardDurationHours( + Math.round(row.getAvgYardDurationHours() * 100.0) / 100.0); + } + } } catch (Exception e) { - return null; + log.error("【YMS】统计今日平均作业时长失败: {}", e.getMessage(), e); + } + return po; + } + + /** + * 今日任务超时率(%)= 超时记录数 ÷ 有效记录总数 × 100%,保留两位小数。 + * 有效记录:月台已配置参考用时(platform_work_ref_minutes),且该记录同时有进入/离开月台时间。 + * 无有效记录时返回 0。 + */ + public double calcTodayTaskOvertimeRate() { + try { + RealOvertimeStatPO po = biPlatformRealDataMapper + .queryTodayOvertimeStat(BiStaticFieldService.CODE_PLATFORM_WORK_REF_MINUTES); + return calcRateFromStat(po); + } catch (Exception e) { + log.error("【YMS】统计今日任务超时率失败: {}", e.getMessage(), e); + return 0d; } } + /** + * 今日园区作业超时率(%)= 园区作业时长 > 园区参考用时的记录数 ÷ 有效记录总数 × 100%。 + * 有效记录:能取到园区参考用时(yard_work_ref_minutes),且记录同时有实际进入/实际出场时间。 + * 无有效记录时返回 0。 + */ + public double calcTodayYardOvertimeRate() { + try { + RealOvertimeStatPO po = biPlatformRealDataMapper + .queryTodayYardOvertimeStat(BiStaticFieldService.CODE_YARD_WORK_REF_MINUTES); + return calcRateFromStat(po); + } catch (Exception e) { + log.error("【YMS】统计今日园区作业超时率失败: {}", e.getMessage(), e); + return 0d; + } + } + + /** 由超时统计 PO 计算百分比,保留两位小数;无有效记录返回 0 */ + private static double calcRateFromStat(RealOvertimeStatPO po) { + if (po == null) { + return 0d; + } + long total = po.getTotalCount() == null ? 0L : po.getTotalCount(); + long overtime = po.getOvertimeCount() == null ? 0L : po.getOvertimeCount(); + if (total <= 0) { + return 0d; + } + return Math.round(((double) overtime / (double) total) * 100.0 * 100.0) / 100.0; + } + + /** + * 今日月台作业超时记录列表(月台名称 / 车牌号码 / 超时时长分钟)。 + * 查询失败返回空列表。 + */ + public List queryTodayOvertimeRecords() { + List result = new ArrayList<>(); + try { + List rows = biPlatformRealDataMapper + .queryTodayOvertimeList(BiStaticFieldService.CODE_PLATFORM_WORK_REF_MINUTES); + + if (rows == null) { + return result; + } + for (RealOvertimeRecordPO r : rows) { + if (r == null) { + continue; + } + result.add(OvertimeRecordItemVO.builder() + .windowName(r.getWindowName()) + .carNo(r.getCarNo()) + .overtimeMinutes(r.getOvertimeMinutes()) + .refMinutes(r.getRefMinutes()) + .platformMinutes(r.getPlatformMinutes()) + .build()); + } + } catch (Exception e) { + log.error("【YMS】查询今日月台作业超时记录失败: {}", e.getMessage(), e); + } + return result; + } + + /** + * 近半年「平均作业时长」趋势(近 6 个月,按月正序,含无数据月份补 0): + + + * - platformDuration:月台作业平均时长 = SUM(月台作业时长) ÷ 该月任务数 + * - yardDuration: 园区作业平均时长 = SUM(园区作业时长) ÷ 该月任务数 + * 均保留两位小数,单位:小时。 + */ + public List queryAvgOperationDurationTrend() { + List result = new ArrayList<>(); + Map map = new HashMap<>(); + try { + List rows = biPlatformRealDataMapper.queryMonthlyAvgDuration(); + if (rows != null) { + for (RealMonthlyAvgDurationPO r : rows) { + if (r != null && r.getMonthOfYear() != null) { + map.put(r.getMonthOfYear().trim(), r); + } + } + } + } catch (Exception e) { + log.error("【YMS】统计近半年平均作业时长失败: {}", e.getMessage(), e); + return result; + } + + // 生成近 6 个月的标签(含当前月),保证无数据月份也返回一条(值为 0) + java.time.LocalDate now = java.time.LocalDate.now(); + java.time.format.DateTimeFormatter keyFmt = java.time.format.DateTimeFormatter.ofPattern("yyyy-MM"); + for (int i = 5; i >= 0; i--) { + java.time.LocalDate m = now.minusMonths(i); + String key = m.format(keyFmt); + RealMonthlyAvgDurationPO po = map.get(key); + AvgOperationDurationTrendItemVO item = new AvgOperationDurationTrendItemVO(); + // 展示用月份标签,如 "9月" + item.setMonth(m.getMonthValue() + "月"); + if (po != null) { + long cnt = po.getTaskCount() == null ? 0L : po.getTaskCount(); + double platformHours = po.getPlatformWorkHours() == null ? 0d : po.getPlatformWorkHours(); + double yardHours = po.getYardWorkHours() == null ? 0d : po.getYardWorkHours(); + item.setPlatformDuration(cnt > 0 + ? Math.round((platformHours / (double) cnt) * 100.0) / 100.0 : 0d); + item.setYardDuration(cnt > 0 + ? Math.round((yardHours / (double) cnt) * 100.0) / 100.0 : 0d); + } else { + item.setPlatformDuration(0d); + item.setYardDuration(0d); + } + result.add(item); + } + return result; + } + /** * FLOW_STATUS 数字转中文:1已预约 2已签到 3已叫号 4已过号 5已进场 6已称重 7已装车 8二次称重 9已结算 10已还卡 11已出场 12已取消 + */ private static String translateFlowStatus(String flowStatus) { if (flowStatus == null) return null; diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biReport/support/BiReportSnapshotMapperSupport.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biReport/support/BiReportSnapshotMapperSupport.java index 0189558d3..39bfddc83 100644 --- a/mhd-bi/src/main/java/com/mhd/bi/domain/biReport/support/BiReportSnapshotMapperSupport.java +++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biReport/support/BiReportSnapshotMapperSupport.java @@ -102,6 +102,8 @@ public final class BiReportSnapshotMapperSupport { .platformAlarmStatistics(PlatformAlarmStatisticsVO.builder() .todayAlarmTotal(0).handled(0).unhandled(0).build()) .platformAlarmDistribution(Collections.emptyList()) + .taskOvertimeRate(0d) + .overtimeRecords(Collections.emptyList()) .build(); } diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biSnapshotSync/service/BiReportSnapshotSyncService.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biSnapshotSync/service/BiReportSnapshotSyncService.java index 25a3fa275..00847af19 100644 --- a/mhd-bi/src/main/java/com/mhd/bi/domain/biSnapshotSync/service/BiReportSnapshotSyncService.java +++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biSnapshotSync/service/BiReportSnapshotSyncService.java @@ -19,6 +19,8 @@ import com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformVehiclePO; import com.mhd.bi.domain.biPlatformRealData.repository.po.RealPlatformInfoPO; import com.mhd.bi.domain.biPlatformRealData.repository.po.RealVehicleStatusPO; import com.mhd.bi.domain.biPlatformRealData.repository.po.RealTaskLoadPO; +import com.mhd.bi.domain.biWarehouseTransport.repository.po.RealWarehouseOrderStatPO; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -45,6 +47,8 @@ public class BiReportSnapshotSyncService { private final BiSnapshotWriteMapper biSnapshotWriteMapper; private final ObjectMapper objectMapper; private final BiPlatformRealDataService biPlatformRealDataService; + private final com.mhd.bi.domain.biWarehouseTransport.service.BiWarehouseTransportRealDataService biWarehouseTransportRealDataService; + /** * 依次同步各快照表;单表失败不影响其它表,只记日志。 @@ -143,11 +147,33 @@ public class BiReportSnapshotSyncService { return BiSnapshotWeeklyRandomDataBuilder.comprehensive(new Random()); } - /** TODO 业务落地:改为查询真实数据。临时实现见 {@link BiSnapshotWeeklyRandomDataBuilder#warehouseTransport(Random)}。 */ + /** + * 仓储运输:订单量 / 今日订单 / 今日运输车次 / 客户贡献排名 用真实数据覆盖; + * 其余(趋势类、周转率、货量等)仍为写死模板。 + */ protected WarehouseTransportSituationVO buildWarehouseTransportSnapshot() { - return BiSnapshotWeeklyRandomDataBuilder.warehouseTransport(new Random()); + WarehouseTransportSituationVO template = + BiSnapshotWeeklyRandomDataBuilder.warehouseTransport(new Random(20260825L)); + + // ====== 真实数据:仓储订单量(WMS 入库单 + 出库单,本年度/本季度/本月度,全部组织) ====== + RealWarehouseOrderStatPO orderStat = biWarehouseTransportRealDataService.queryWarehouseOrderStat(); + template.setCurrentYearOrders(orderStat.getCurrentYearOrders()); + template.setCurrentQuarterOrders(orderStat.getCurrentQuarterOrders().intValue()); + template.setCurrentMonthOrders(orderStat.getCurrentMonthOrders().intValue()); + + // ====== 真实数据:今日订单数量(OMS 运输业务单) ====== + template.setOrderCount((int) biWarehouseTransportRealDataService.countTodayTransportOrders()); + + // ====== 真实数据:今日运输车次(TMS 运输单) ====== + template.setTransportTrips((int) biWarehouseTransportRealDataService.countTodayTransportTrips()); + + // ====== 真实数据:客户贡献排名(OMS 近半年前 5 名货主) ====== + template.setCustomerContributionRank(biWarehouseTransportRealDataService.queryCustomerContributionRank()); + + return template; } + /** TODO 业务落地:部分字段改为真实数据,其余仍写死。 */ protected PlatformSurveillanceVO buildPlatformSurveillanceSnapshot() { // 固定种子,保证写死字段每次生成值一致(真实字段随后实时覆盖) @@ -194,19 +220,25 @@ public class BiReportSnapshotSyncService { template.getPlatformOverview().setCurrentOccupancyRate(rate); template.getPlatformOverview().setTodayTasks(todayTasks); - // 作业准时率 = 实际进入时间 < 预约日期+预约结束时间 的车辆 / 今日预约总数 × 100%(取整) - if (template.getEfficiencyStatistics() != null) { - template.getEfficiencyStatistics().setPlatformOnTimeRate(biPlatformRealDataService.calcTodayOnTimeRate()); - } + // 作业准时率:任务超时率 + 月台作业准时率 = 100%;园区作业准时率 = 100 - 园区超时率 + template.getEfficiencyStatistics().setPlatformOnTimeRate( + (int) Math.round(100.0 - biPlatformRealDataService.calcTodayTaskOvertimeRate())); + template.getEfficiencyStatistics().setYardOnTimeRate( + (int) Math.round(100.0 - biPlatformRealDataService.calcTodayYardOvertimeRate())); } - // 平均装卸时长 = 月台作业平均时长(今日作业车辆 platformDuration 的平均值,保留两位小数) + + // ====== 真实数据:平均作业时长(本日)月台作业平均时长 / 园区平均时长 ====== if (template.getEfficiencyStatistics() != null) { - template.getEfficiencyStatistics() - .setAvgPlatformDuration(biPlatformRealDataService.calcTodayAvgPlatformDuration(vehicleVos)); + com.mhd.bi.domain.biPlatformRealData.repository.po.RealTodayAvgDurationPO avg = + biPlatformRealDataService.queryTodayAvgDuration(); + template.getEfficiencyStatistics().setAvgPlatformDuration(avg.getAvgPlatformDurationHours()); + template.getEfficiencyStatistics().setAvgYardDuration(avg.getAvgYardDurationHours()); } + + // ====== 真实数据:作业车辆状态统计 ====== RealVehicleStatusPO vs = biPlatformRealDataService.queryVehicleStatusToday(); if (template.getVehicleStatus() != null) { @@ -253,42 +285,49 @@ public class BiReportSnapshotSyncService { } } - // ====== 真实数据:任务负荷(今日 24 小时) ====== + // ====== 真实数据:小时趋势(今日,每 2 小时分组) ====== List loads = biPlatformRealDataService.queryTaskLoadToday(); - if (!loads.isEmpty() && template.getTaskLoadStatistics() != null) { - Map hourMap = new HashMap<>(); + if (loads.isEmpty()) { + template.setTaskLoadStatistics(new ArrayList<>()); + } else { + Map bucketMap = new HashMap<>(); for (RealTaskLoadPO l : loads) { - hourMap.put(l.getHourOfDay(), l.getTaskCount()); - } - for (com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.TaskLoadItemVO item : template.getTaskLoadStatistics()) { - Integer hour = parseHourFromLabel(item.getTime()); - if (hour != null) { - Long n = hourMap.get(hour); - if (n != null) item.setTaskCount(n.intValue()); + if (l != null && l.getHourOfDay() != null) { + bucketMap.put(l.getHourOfDay(), l.getTaskCount() == null ? 0L : l.getTaskCount()); } } + // 固定输出 0,2,4,...,22 共 12 个桶,无数据桶补 0 + List items = new ArrayList<>(); + for (int h = 0; h < 24; h += 2) { + Long cnt = bucketMap.get(h); + items.add(com.mhd.bi.interfaces.facadeApi.biReport.vo.platform.TaskLoadItemVO.builder() + .time(String.format("%02d:00", h)) + .taskCount(cnt == null ? 0 : cnt.intValue()) + .build()); + } + template.setTaskLoadStatistics(items); } + // ====== 真实数据:任务类型统计(本月 YMS QMS_MAIN_BUSINESS 按业务类型 BUSINESS_NAME 分组) ====== template.setTaskTypeStatistics(biPlatformRealDataService.queryMonthTransportOrderByType()); + // ====== 真实数据:平均作业时长趋势(近半年按月:月台作业平均时长 / 园区作业平均时长) ====== + template.setAvgOperationDurationTrend(biPlatformRealDataService.queryAvgOperationDurationTrend()); + + // ====== 真实数据:任务超时率 + 月台作业超时记录列表(依赖 YMS QMS_STATIC_FIELD 参考用时) ====== + template.setTaskOvertimeRate(biPlatformRealDataService.calcTodayTaskOvertimeRate()); + template.setOvertimeRecords(biPlatformRealDataService.queryTodayOvertimeRecords()); + return template; } - private static Integer parseHourFromLabel(String label) { - if (label == null) return null; - // "15时" -> 15 - try { - String s = label.replace("时", "").trim(); - return Integer.parseInt(s); - } catch (Exception e) { - return null; - } - } + /** * TODO 业务落地:改为查询真实数据组装 VO。当前为 {@link WarehouseOperationZoneDemoData} 静态示例。 */ + protected WarehouseOperationZoneVO buildWarehouseOperationZoneSnapshot() { return WarehouseOperationZoneDemoData.build(); } diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biSnapshotSync/support/BiSnapshotWeeklyRandomDataBuilder.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biSnapshotSync/support/BiSnapshotWeeklyRandomDataBuilder.java index d9e6eb371..e80f166c7 100644 --- a/mhd-bi/src/main/java/com/mhd/bi/domain/biSnapshotSync/support/BiSnapshotWeeklyRandomDataBuilder.java +++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biSnapshotSync/support/BiSnapshotWeeklyRandomDataBuilder.java @@ -136,13 +136,14 @@ public final class BiSnapshotWeeklyRandomDataBuilder { .build()); } + // 效率统计(本日):入园区超时率、超时数量、月台作业准时率、园区作业准时率 按业务要求恒为 0 EfficiencyStatisticsVO eff = EfficiencyStatisticsVO.builder() - .entryOvertimeRate(jitterPercentInt(Baseline.P_ENT_OT, r)) - .overtimeCount(Math.max(0, jitterInt(Baseline.P_OT_CNT, r))) - .platformOnTimeRate(jitterPercentInt(Baseline.P_PL_OT, r)) - .avgPlatformDuration(Math.max(0.1, jitterDouble(Baseline.P_AVG_PL, r))) - .yardOnTimeRate(jitterPercentInt(Baseline.P_YD_OT, r)) - .avgYardDuration(Math.max(0.1, jitterDouble(Baseline.P_AVG_YD, r))) + .entryOvertimeRate(0) + .overtimeCount(0) + .platformOnTimeRate(0) + .avgPlatformDuration(0d) + .yardOnTimeRate(0) + .avgYardDuration(0d) .build(); PlatformOverviewVO overview = PlatformOverviewVO.builder() @@ -225,9 +226,13 @@ public final class BiSnapshotWeeklyRandomDataBuilder { .unhandled(unhandled) .build()) .platformAlarmDistribution(dist) + // 任务超时率 / 超时记录列表:实时查库覆盖,模板给 0/空兜底 + .taskOvertimeRate(0d) + .overtimeRecords(new ArrayList<>()) .build(); } + /** * 总体运营态势:与 {@code create_bi_overall_operation_dm.sql} 内置 PAYLOAD_JSON 一致(不随 Random 抖动)。 */ @@ -395,12 +400,6 @@ public final class BiSnapshotWeeklyRandomDataBuilder { {"闽D99887", "作业中", "#07", "142"}, {"粤B66220", "已离园", "#29", "201"} }; - static final int P_ENT_OT = 42; - static final int P_OT_CNT = 28; - static final int P_PL_OT = 88; - static final double P_AVG_PL = 3.8; - static final int P_YD_OT = 91; - static final double P_AVG_YD = 5.2; static final int P_TOT_PL = 58; static final int P_OCC = 62; static final int P_OP = 31; @@ -421,8 +420,10 @@ public final class BiSnapshotWeeklyRandomDataBuilder { static final int P_MT_AVG_YOY = -3; static final int P_MT_CR = 97; static final int P_MT_CR_YOY = 2; - static final String[] P_LOAD_T = {"8时", "10时", "14时"}; - static final int[] P_LOAD_C = {45, 120, 156}; + /** 小时趋势:每 2 小时一个桶,0:00 ~ 22:00 共 12 个 */ + static final String[] P_LOAD_T = {"00:00", "02:00", "04:00", "06:00", "08:00", "10:00", + "12:00", "14:00", "16:00", "18:00", "20:00", "22:00"}; + static final int[] P_LOAD_C = {5, 3, 2, 8, 45, 120, 130, 156, 110, 70, 30, 12}; static final String[] P_AL_D = {"1日", "2日", "3日"}; static final int[] P_AL_C = {6, 9, 4}; static final int P_TT_TOT = 5_100; diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biStaticField/repository/mapper/BiStaticFieldMapper.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biStaticField/repository/mapper/BiStaticFieldMapper.java new file mode 100644 index 000000000..0ef74b10b --- /dev/null +++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biStaticField/repository/mapper/BiStaticFieldMapper.java @@ -0,0 +1,23 @@ +package com.mhd.bi.domain.biStaticField.repository.mapper; + +import com.mhd.bi.domain.biStaticField.repository.po.BiStaticFieldPO; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * BI 业务静态字段配置 Mapper(YMS 库 NGWL_TEST_YMS.QMS_STATIC_FIELD) + * + *

SQL 见 BiStaticFieldMapper.xml。

+ */ +public interface BiStaticFieldMapper { + + /** 按字段编码查询全部有效配置(含 GLOBAL / FLOOR / WINDOW 各作用域,供程序按优先级取值) */ + List queryByCode(@Param("fieldCode") String fieldCode); + + /** 批量按字段编码查询有效配置 */ + List queryByCodes(@Param("fieldCodes") List fieldCodes); + + /** 查询全部有效配置 */ + List queryAll(); +} diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biStaticField/repository/po/BiStaticFieldPO.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biStaticField/repository/po/BiStaticFieldPO.java new file mode 100644 index 000000000..d2dd28784 --- /dev/null +++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biStaticField/repository/po/BiStaticFieldPO.java @@ -0,0 +1,38 @@ +package com.mhd.bi.domain.biStaticField.repository.po; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 业务静态字段配置(来自 NGWL_TEST_YMS.QMS_STATIC_FIELD) + * + *

集中存放指标计算所需的参考值/基准值,当前使用:

+ *
    + *
  • platform_work_ref_minutes 月台作业参考用时(分钟)
  • + *
  • yard_work_ref_minutes 园区作业参考用时(分钟)
  • + *
+ *

后续新增静态字段只需往表里 INSERT,无需改代码结构。

+ */ +@Data +public class BiStaticFieldPO implements Serializable { + private static final long serialVersionUID = 1L; + + /** 静态字段编码 */ + private String fieldCode; + + /** 静态字段名称 */ + private String fieldName; + + /** 作用域类型:GLOBAL-全局 FLOOR-按楼层 WINDOW-按月台 */ + private String scopeType; + + /** 作用域编码:GLOBAL 时为 ALL;FLOOR 时为楼层;WINDOW 时为月台名 */ + private String scopeCode; + + /** 字段值(字符串,程序按需转换) */ + private String fieldValue; + + /** 单位 */ + private String unit; +} diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biStaticField/service/BiStaticFieldService.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biStaticField/service/BiStaticFieldService.java new file mode 100644 index 000000000..bd1e25b1f --- /dev/null +++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biStaticField/service/BiStaticFieldService.java @@ -0,0 +1,108 @@ +package com.mhd.bi.domain.biStaticField.service; + +import com.mhd.bi.domain.biStaticField.repository.mapper.BiStaticFieldMapper; +import com.mhd.bi.domain.biStaticField.repository.po.BiStaticFieldPO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Collections; +import java.util.List; + +/** + * BI 业务静态字段配置业务层(YMS 库 QMS_STATIC_FIELD) + * + *

集中提供参考值/基准值等静态配置的读取能力,后续新增静态字段只需往表里 INSERT。

+ */ +@Slf4j +@Service +public class BiStaticFieldService { + + /** 月台作业参考用时(分钟) */ + public static final String CODE_PLATFORM_WORK_REF_MINUTES = "platform_work_ref_minutes"; + + /** 园区作业参考用时(分钟) */ + public static final String CODE_YARD_WORK_REF_MINUTES = "yard_work_ref_minutes"; + + /** 作用域:全局 */ + private static final String SCOPE_GLOBAL = "GLOBAL"; + /** 作用域:按月台 */ + private static final String SCOPE_WINDOW = "WINDOW"; + /** 作用域:按楼层 */ + private static final String SCOPE_FLOOR = "FLOOR"; + + @Resource + private BiStaticFieldMapper biStaticFieldMapper; + + /** + * 按字段编码查询全部有效配置;查询失败返回空列表。 + */ + public List queryByCode(String fieldCode) { + try { + List list = biStaticFieldMapper.queryByCode(fieldCode); + return list == null ? Collections.emptyList() : list; + } catch (Exception e) { + log.error("【YMS】查询静态字段配置失败, fieldCode={}: {}", fieldCode, e.getMessage(), e); + return Collections.emptyList(); + } + } + + /** + * 按「WINDOW > FLOOR > GLOBAL」优先级取静态字段值(字符串)。取不到返回 null。 + * + * @param fieldCode 字段编码 + * @param windowName 月台名(可为空) + * @param floor 楼层(可为空) + */ + public String resolveValue(String fieldCode, String windowName, String floor) { + List list = queryByCode(fieldCode); + if (list.isEmpty()) { + return null; + } + String globalVal = null; + String floorVal = null; + for (BiStaticFieldPO po : list) { + if (po == null || po.getFieldValue() == null) { + continue; + } + String scopeType = po.getScopeType() == null ? "" : po.getScopeType().trim().toUpperCase(); + String scopeCode = po.getScopeCode(); + if (SCOPE_WINDOW.equals(scopeType) && windowName != null && windowName.equals(scopeCode)) { + return po.getFieldValue(); // 最高优先级,直接返回 + } + if (SCOPE_FLOOR.equals(scopeType) && floor != null && floor.equals(scopeCode)) { + floorVal = po.getFieldValue(); + } + if (SCOPE_GLOBAL.equals(scopeType)) { + globalVal = po.getFieldValue(); + } + } + return floorVal != null ? floorVal : globalVal; + } + + /** + * 取静态字段的数值(分钟等整数),取不到或非数字返回 null。 + */ + public Long resolveLongValue(String fieldCode, String windowName, String floor) { + String v = resolveValue(fieldCode, windowName, floor); + if (v == null || v.trim().isEmpty()) { + return null; + } + try { + return Long.valueOf(v.trim()); + } catch (Exception e) { + log.warn("【YMS】静态字段值非数字, fieldCode={}, value={}", fieldCode, v); + return null; + } + } + + /** 月台作业参考用时(分钟),按月台/楼层解析;取不到返回 null */ + public Long resolvePlatformWorkRefMinutes(String windowName, String floor) { + return resolveLongValue(CODE_PLATFORM_WORK_REF_MINUTES, windowName, floor); + } + + /** 园区作业参考用时(分钟),按月台/楼层解析;取不到返回 null */ + public Long resolveYardWorkRefMinutes(String windowName, String floor) { + return resolveLongValue(CODE_YARD_WORK_REF_MINUTES, windowName, floor); + } +} diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biWarehouseTransport/repository/mapper/BiWarehouseTransportRealDataMapper.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biWarehouseTransport/repository/mapper/BiWarehouseTransportRealDataMapper.java new file mode 100644 index 000000000..4158d6278 --- /dev/null +++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biWarehouseTransport/repository/mapper/BiWarehouseTransportRealDataMapper.java @@ -0,0 +1,32 @@ +package com.mhd.bi.domain.biWarehouseTransport.repository.mapper; + +import com.mhd.bi.domain.biWarehouseTransport.repository.po.RealCustomerRankPO; +import com.mhd.bi.domain.biWarehouseTransport.repository.po.RealWarehouseOrderStatPO; + +import java.util.List; + +/** + * 仓储运输-真实业务数据 Mapper(跨库查询,与月台监测同方案) + * + *

数据来源:

+ *
    + *
  • 库存订单量:NGWL_TEST_WMS.STOCK_IN_ORDER + NGWL_TEST_WMS.STOCK_OUT_ORDER
  • + *
  • 今日订单数量:NGWL_TEST_OMS.BUSINESS_DOCUMENT_ORDER
  • + *
  • 今日运输车次:NGWL_TEST_WLHY.TMS_TRANSPORT_NOTE
  • + *
  • 客户贡献排名:NGWL_TEST_OMS.BUSINESS_DOCUMENT_ORDER 按货主聚合近半年
  • + *
+ */ +public interface BiWarehouseTransportRealDataMapper { + + /** 仓储订单量:本年度 / 本季度 / 本月度(WMS 入库单 + 出库单),全部组织 */ + RealWarehouseOrderStatPO queryWarehouseOrderStat(); + + /** 今日订单数量:OMS 运输业务单,今日创建 */ + Long countTodayTransportOrders(); + + /** 今日运输车次:TMS 运单(运输单),今日创建,一个单 = 一个车次 */ + Long countTodayTransportTrips(); + + /** 客户贡献排名:OMS 运输业务单,近半年按货主聚合订单数,取前 5 名 */ + List queryCustomerRankTop5(); +} diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biWarehouseTransport/repository/po/RealCustomerRankPO.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biWarehouseTransport/repository/po/RealCustomerRankPO.java new file mode 100644 index 000000000..d6411083c --- /dev/null +++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biWarehouseTransport/repository/po/RealCustomerRankPO.java @@ -0,0 +1,21 @@ +package com.mhd.bi.domain.biWarehouseTransport.repository.po; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 客户贡献排名项(真实数据,来自 OMS 运输业务单) + * + *

统计范围:全部组织,近半年,按货主聚合作业量,取前 5 名。

+ */ +@Data +public class RealCustomerRankPO implements Serializable { + private static final long serialVersionUID = 1L; + + /** 货主/客户名称 */ + private String customerName; + + /** 订单数(单) */ + private Long customerAmount; +} diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biWarehouseTransport/repository/po/RealWarehouseOrderStatPO.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biWarehouseTransport/repository/po/RealWarehouseOrderStatPO.java new file mode 100644 index 000000000..f2c5f7631 --- /dev/null +++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biWarehouseTransport/repository/po/RealWarehouseOrderStatPO.java @@ -0,0 +1,25 @@ +package com.mhd.bi.domain.biWarehouseTransport.repository.po; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 仓储订单量统计(真实数据) + * + *

数据来源:WMS 入库业务单 NGWL_TEST_WMS.STOCK_IN_ORDER + 出库业务单 NGWL_TEST_WMS.STOCK_OUT_ORDER

+ *

统计范围:全部组织

+ */ +@Data +public class RealWarehouseOrderStatPO implements Serializable { + private static final long serialVersionUID = 1L; + + /** 本年度订单数(入库 + 出库) */ + private Long currentYearOrders; + + /** 本季度订单数(入库 + 出库) */ + private Long currentQuarterOrders; + + /** 本月度订单数(入库 + 出库) */ + private Long currentMonthOrders; +} diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biWarehouseTransport/service/BiWarehouseTransportRealDataService.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biWarehouseTransport/service/BiWarehouseTransportRealDataService.java new file mode 100644 index 000000000..160f85437 --- /dev/null +++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biWarehouseTransport/service/BiWarehouseTransportRealDataService.java @@ -0,0 +1,99 @@ +package com.mhd.bi.domain.biWarehouseTransport.service; + +import com.mhd.bi.domain.biWarehouseTransport.repository.mapper.BiWarehouseTransportRealDataMapper; +import com.mhd.bi.domain.biWarehouseTransport.repository.po.RealCustomerRankPO; +import com.mhd.bi.domain.biWarehouseTransport.repository.po.RealWarehouseOrderStatPO; +import com.mhd.bi.interfaces.facadeApi.biReport.vo.CustomerContributionRankVO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * 仓储运输-真实业务数据业务层(封装 WMS / OMS / TMS 跨库查询) + * + *

实现方案与「月台监测指标查询」一致:实时查库,查不到或异常返回 0/空,不影响其它字段。

+ */ +@Slf4j +@Service +public class BiWarehouseTransportRealDataService { + + @Resource + private BiWarehouseTransportRealDataMapper biWarehouseTransportRealDataMapper; + + /** + * 仓储订单量:本年度 / 本季度 / 本月度(WMS 入库单 + 出库单),全部组织。 + * 查询失败返回全 0。 + */ + public RealWarehouseOrderStatPO queryWarehouseOrderStat() { + RealWarehouseOrderStatPO po = new RealWarehouseOrderStatPO(); + po.setCurrentYearOrders(0L); + po.setCurrentQuarterOrders(0L); + po.setCurrentMonthOrders(0L); + try { + RealWarehouseOrderStatPO row = biWarehouseTransportRealDataMapper.queryWarehouseOrderStat(); + if (row != null) { + po.setCurrentYearOrders(row.getCurrentYearOrders() == null ? 0L : row.getCurrentYearOrders()); + po.setCurrentQuarterOrders(row.getCurrentQuarterOrders() == null ? 0L : row.getCurrentQuarterOrders()); + po.setCurrentMonthOrders(row.getCurrentMonthOrders() == null ? 0L : row.getCurrentMonthOrders()); + } + } catch (Exception e) { + log.error("【WMS】统计仓储订单量失败: {}", e.getMessage(), e); + } + return po; + } + + /** 今日订单数量:OMS 运输业务单,今日创建;查询失败返回 0 */ + public long countTodayTransportOrders() { + try { + Long n = biWarehouseTransportRealDataMapper.countTodayTransportOrders(); + return n == null ? 0L : n; + } catch (Exception e) { + log.error("【OMS】统计今日订单数量失败: {}", e.getMessage(), e); + return 0L; + } + } + + /** 今日运输车次:TMS 运输单,今日创建(一个单 = 一个车次);查询失败返回 0 */ + public long countTodayTransportTrips() { + try { + Long n = biWarehouseTransportRealDataMapper.countTodayTransportTrips(); + return n == null ? 0L : n; + } catch (Exception e) { + log.error("【TMS】统计今日运输车次失败: {}", e.getMessage(), e); + return 0L; + } + } + + /** + * 客户贡献排名(前 5 名货主,近半年订单数)。 + * 查询失败返回空数组结构的对象,前端可正常渲染。 + */ + public CustomerContributionRankVO queryCustomerContributionRank() { + List names = new ArrayList<>(); + List amounts = new ArrayList<>(); + try { + List rows = biWarehouseTransportRealDataMapper.queryCustomerRankTop5(); + if (rows != null) { + for (RealCustomerRankPO r : rows) { + if (r == null || r.getCustomerName() == null) { + continue; + } + names.add(r.getCustomerName()); + amounts.add(r.getCustomerAmount() == null ? 0 : r.getCustomerAmount().intValue()); + } + } + } catch (Exception e) { + log.error("【OMS】查询客户贡献排名失败: {}", e.getMessage(), e); + names = new ArrayList<>(); + amounts = new ArrayList<>(); + } + return CustomerContributionRankVO.builder() + .customerName(names.isEmpty() ? Collections.emptyList() : names) + .customerAmount(amounts.isEmpty() ? Collections.emptyList() : amounts) + .build(); + } +} diff --git a/mhd-bi/src/main/java/com/mhd/bi/domain/biWarehouseTransport/service/BiWarehouseTransportReportService.java b/mhd-bi/src/main/java/com/mhd/bi/domain/biWarehouseTransport/service/BiWarehouseTransportReportService.java index 58ae0c060..6cb8b1682 100644 --- a/mhd-bi/src/main/java/com/mhd/bi/domain/biWarehouseTransport/service/BiWarehouseTransportReportService.java +++ b/mhd-bi/src/main/java/com/mhd/bi/domain/biWarehouseTransport/service/BiWarehouseTransportReportService.java @@ -1,18 +1,124 @@ package com.mhd.bi.domain.biWarehouseTransport.service; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.mhd.bi.domain.biSnapshotSync.repository.mapper.BiSnapshotWriteMapper; import com.mhd.bi.domain.biWarehouseTransport.repository.mapper.BiWarehouseTransportReportMapper; +import com.mhd.bi.domain.biWarehouseTransport.repository.po.RealWarehouseOrderStatPO; import com.mhd.bi.interfaces.facadeApi.biReport.vo.WarehouseTransportSituationVO; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import javax.annotation.Resource; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; +/** + * 仓储运输:数据访问仅经 Mapper(含 XML 内 SQL 与 Mapper 默认方法组装)。 + * + *

实现方案与「月台监测指标查询」完全一致:

+ *
    + *
  1. 先读快照最新一条作为基底;
  2. + *
  3. 实时查业务库,用真实数据覆盖以下字段: + * 本年度订单 / 本季度订单 / 本月度订单(WMS 入库业务单 + 出库业务单)、 + * 今日订单数量(OMS 运输业务单)、今日运输车次(TMS 运单)、 + * 客户贡献排名(OMS 近半年前 5 名货主);
  4. + *
  5. 对「真实业务数据」计算指纹,与快照最新一条比对: + * 未变化则跳过落库直接返回;已变化则覆盖更新快照最新一条,无记录时插入兜底。
  6. + *
+ *

其余字段(趋势类、周转率、货量等)仍取自快照模板值,不纳入指纹。

+ */ +@Slf4j @Service public class BiWarehouseTransportReportService { + private static final String REMARK_REALTIME = "realtime warehouse-transport"; + @Resource private BiWarehouseTransportReportMapper biWarehouseTransportReportMapper; + @Resource + private BiWarehouseTransportRealDataService biWarehouseTransportRealDataService; + + @Resource + private BiSnapshotWriteMapper biSnapshotWriteMapper; + + @Resource + private ObjectMapper objectMapper; + + /** + * 实时组装仓储运输数据:快照基底 + 实时业务数据覆盖; + * 仅当实时业务数据(WMS/OMS/TMS 查出的字段)发生变化时,才覆盖更新 + * BI_WAREHOUSE_TRANSPORT_SNAPSHOT 快照表最新一条后返回。 + * 表中尚无记录时插入一条兜底。 + */ public WarehouseTransportSituationVO loadLatestWarehouseTransport() { - return biWarehouseTransportReportMapper.loadLatestWarehouseTransport(); + WarehouseTransportSituationVO vo = biWarehouseTransportReportMapper.loadLatestWarehouseTransport(); + if (vo == null) { + vo = new WarehouseTransportSituationVO(); + } + + // 仓储订单量:WMS 入库业务单 + 出库业务单(本年度 / 本季度 / 本月度,全部组织) + RealWarehouseOrderStatPO orderStat = biWarehouseTransportRealDataService.queryWarehouseOrderStat(); + vo.setCurrentYearOrders(orderStat.getCurrentYearOrders()); + vo.setCurrentQuarterOrders(orderStat.getCurrentQuarterOrders().intValue()); + vo.setCurrentMonthOrders(orderStat.getCurrentMonthOrders().intValue()); + + // 今日订单数量:OMS 运输业务单 + vo.setOrderCount((int) biWarehouseTransportRealDataService.countTodayTransportOrders()); + + // 今日运输车次:TMS 运输单(一个单 = 一个车次) + vo.setTransportTrips((int) biWarehouseTransportRealDataService.countTodayTransportTrips()); + + // 客户贡献排名:OMS 运输业务单,近半年前 5 名货主(订单数) + vo.setCustomerContributionRank(biWarehouseTransportRealDataService.queryCustomerContributionRank()); + + try { + String fullJson = objectMapper.writeValueAsString(vo); + String fingerprint = realDataFingerprint(vo); + + String latestJson = biWarehouseTransportReportMapper.selectLatestPayloadJson(); + if (StringUtils.isNotBlank(latestJson)) { + WarehouseTransportSituationVO latestVo = + objectMapper.readValue(latestJson.trim(), WarehouseTransportSituationVO.class); + if (Objects.equals(fingerprint, realDataFingerprint(latestVo))) { + log.info("BI 仓储运输实时业务数据未变化,跳过落库"); + return vo; + } + } + + int rows = biSnapshotWriteMapper.updateLatestWarehouseTransportSnapshot(fullJson, REMARK_REALTIME); + if (rows < 1) { + // 表中无最新记录可更新,插入一条兜底 + biSnapshotWriteMapper.insertWarehouseTransportSnapshot(fullJson, REMARK_REALTIME); + } + log.info("BI 仓储运输实时数据已落库(覆盖最新, 数据变化), affectedRows={}", rows); + } catch (Exception e) { + log.error("BI 仓储运输实时数据落库失败", e); + } + return vo; + } + + /** + * 实时业务数据指纹:仅含实时查库得到的字段(本年度/本季度/本月度订单、今日订单数量、 + * 今日运输车次、客户贡献排名),用于判断是否需要覆盖更新快照; + * 其余字段取自快照模板,不纳入指纹,其变化不会触发更新。 + */ + private String realDataFingerprint(WarehouseTransportSituationVO vo) throws Exception { + Map fp = new LinkedHashMap<>(); + if (vo == null) { + return objectMapper.writeValueAsString(fp); + } + fp.put("currentYearOrders", vo.getCurrentYearOrders()); + fp.put("currentQuarterOrders", vo.getCurrentQuarterOrders()); + fp.put("currentMonthOrders", vo.getCurrentMonthOrders()); + fp.put("orderCount", vo.getOrderCount()); + fp.put("transportTrips", vo.getTransportTrips()); + if (vo.getCustomerContributionRank() != null) { + fp.put("customerName", vo.getCustomerContributionRank().getCustomerName()); + fp.put("customerAmount", vo.getCustomerContributionRank().getCustomerAmount()); + } + return objectMapper.writeValueAsString(fp); } } diff --git a/mhd-bi/src/main/java/com/mhd/bi/interfaces/facadeApi/biReport/vo/CustomerContributionRankVO.java b/mhd-bi/src/main/java/com/mhd/bi/interfaces/facadeApi/biReport/vo/CustomerContributionRankVO.java index f61e98183..3b05b7a6a 100644 --- a/mhd-bi/src/main/java/com/mhd/bi/interfaces/facadeApi/biReport/vo/CustomerContributionRankVO.java +++ b/mhd-bi/src/main/java/com/mhd/bi/interfaces/facadeApi/biReport/vo/CustomerContributionRankVO.java @@ -19,6 +19,6 @@ public class CustomerContributionRankVO { @ApiModelProperty("客户名称") private List customerName; - @ApiModelProperty("客户金额,单位:万元") + @ApiModelProperty("客户订单数,单位:单") private List customerAmount; } diff --git a/mhd-bi/src/main/java/com/mhd/bi/interfaces/facadeApi/biReport/vo/platform/OvertimeRecordItemVO.java b/mhd-bi/src/main/java/com/mhd/bi/interfaces/facadeApi/biReport/vo/platform/OvertimeRecordItemVO.java new file mode 100644 index 000000000..08fe6a0c6 --- /dev/null +++ b/mhd-bi/src/main/java/com/mhd/bi/interfaces/facadeApi/biReport/vo/platform/OvertimeRecordItemVO.java @@ -0,0 +1,31 @@ +package com.mhd.bi.interfaces.facadeApi.biReport.vo.platform; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@ApiModel("月台监测-月台作业超时记录") +public class OvertimeRecordItemVO { + + @ApiModelProperty("月台名称") + private String windowName; + + @ApiModelProperty("车牌号码") + private String carNo; + + @ApiModelProperty("超时时长,单位:分钟(= 月台作业时长 - 参考用时)") + private Long overtimeMinutes; + + @ApiModelProperty("月台作业参考用时,单位:分钟") + private Long refMinutes; + + @ApiModelProperty("月台作业时长,单位:分钟") + private Long platformMinutes; +} diff --git a/mhd-bi/src/main/java/com/mhd/bi/interfaces/facadeApi/biReport/vo/platform/PlatformSurveillanceVO.java b/mhd-bi/src/main/java/com/mhd/bi/interfaces/facadeApi/biReport/vo/platform/PlatformSurveillanceVO.java index 0efd4039f..624777d13 100644 --- a/mhd-bi/src/main/java/com/mhd/bi/interfaces/facadeApi/biReport/vo/platform/PlatformSurveillanceVO.java +++ b/mhd-bi/src/main/java/com/mhd/bi/interfaces/facadeApi/biReport/vo/platform/PlatformSurveillanceVO.java @@ -48,4 +48,10 @@ public class PlatformSurveillanceVO { @ApiModelProperty("月台告警分布") private List platformAlarmDistribution; + + @ApiModelProperty("任务超时率,单位:%(月台作业时长 > 参考用时的记录数 ÷ 总记录数 × 100)") + private Double taskOvertimeRate; + + @ApiModelProperty("月台作业超时记录列表(月台名称 / 车牌号码 / 超时时长分钟)") + private List overtimeRecords; } diff --git a/mhd-bi/src/main/resources/mapper/biPlatformRealData/BiPlatformRealDataMapper.xml b/mhd-bi/src/main/resources/mapper/biPlatformRealData/BiPlatformRealDataMapper.xml index b58c8bc82..ada96acb8 100644 --- a/mhd-bi/src/main/resources/mapper/biPlatformRealData/BiPlatformRealDataMapper.xml +++ b/mhd-bi/src/main/resources/mapper/biPlatformRealData/BiPlatformRealDataMapper.xml @@ -8,10 +8,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" plateNumber <- qms_main_business.CAR_NO status <- qms_main_business.FLOW_STATUS platformId <- qms_main_business.WINDOW_NAME(叫号月台,主业务表直接有) - platformDuration <- 月台作业时长(分钟): - 未进入月台(ENTRY_TIME 为空) -> 0 - 已进入且已离开 -> EXIT_TIME - ENTRY_TIME - 已进入但未离开 -> SYSDATE - ENTRY_TIME + platformDuration <- 月台作业时长(分钟),用「进入月台 / 离开月台」时间: + 未进入月台(IN_WINDOWS_TIME 为空) -> 0 + 已进入且已离开月台(OUT_WINDOWS_TIME 非空) -> OUT_WINDOWS_TIME - IN_WINDOWS_TIME + 已进入但未离开月台 -> SYSDATE - IN_WINDOWS_TIME appointmentTime <- qms_main_business.CREATE_TIME workFloor <- qms_window_info.PLATFORM_FLOOR(按 WINDOW_NAME 关联) --> @@ -21,10 +21,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" mb.FLOW_STATUS AS status, mb.WINDOW_NAME AS platformId, CASE - WHEN mb.ENTRY_TIME IS NULL THEN 0 - WHEN mb.EXIT_TIME IS NOT NULL - THEN CAST((mb.EXIT_TIME - mb.ENTRY_TIME) * 24 * 60 AS BIGINT) - ELSE CAST((SYSDATE - mb.ENTRY_TIME) * 24 * 60 AS BIGINT) + WHEN mb.IN_WINDOWS_TIME IS NULL THEN 0 + WHEN mb.OUT_WINDOWS_TIME IS NOT NULL + THEN CAST((mb.OUT_WINDOWS_TIME - mb.IN_WINDOWS_TIME) * 24 * 60 AS BIGINT) + ELSE CAST((SYSDATE - mb.IN_WINDOWS_TIME) * 24 * 60 AS BIGINT) END AS platformDuration, TO_CHAR(mb.CREATE_TIME, 'YYYY-MM-DD HH24:MI:SS') AS appointmentTime, wi.PLATFORM_FLOOR AS workFloor @@ -37,6 +37,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + SELECT @@ -86,14 +88,97 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" SUM(CASE WHEN FLOW_STATUS IN ('2','3','4') AND TRUNC(TARGET_DATE) = TRUNC(SYSDATE) THEN 1 ELSE 0 END) AS callStatusTotal, SUM(CASE WHEN FLOW_STATUS = '11' AND TRUNC(TARGET_DATE) = TRUNC(SYSDATE) THEN 1 ELSE 0 END) AS todayExited, SUM(CASE WHEN FLOW_STATUS IN ('5','6','7','8','9','10') AND TRUNC(CREATE_TIME) = TRUNC(SYSDATE) THEN 1 ELSE 0 END) AS operatingVehicles, - SUM(CASE WHEN FLOW_STATUS = '11' AND TRUNC(CREATE_TIME) = TRUNC(SYSDATE) THEN 1 ELSE 0 END) AS completedVehicles + SUM(CASE WHEN FLOW_STATUS = '11' AND TRUNC(TARGET_DATE) = TRUNC(SYSDATE) THEN 1 ELSE 0 END) AS completedVehicles FROM NGWL_TEST_YMS.QMS_MAIN_BUSINESS + + + + + + INNER JOIN NGWL_TEST_YMS.QMS_STATIC_FIELD ref + ON ref.FIELD_CODE = #{refCode} + AND ref.DEL_FLAG = 1 + AND ref.FIELD_VALUE IS NOT NULL + AND ( + (ref.SCOPE_TYPE = 'WINDOW' AND ref.SCOPE_CODE = mb.WINDOW_NAME) + OR (ref.SCOPE_TYPE = 'FLOOR' AND ref.SCOPE_CODE = wi.PLATFORM_FLOOR) + OR (ref.SCOPE_TYPE = 'GLOBAL') + ) + + + + + + + + + + + + + + + avgPlatformMinutes 该楼层月台作业平均时长(分钟) + 公式:SUM(该楼层有效记录的月台作业时长) ÷ 该楼层有效记录数 + 有效记录:同时有进入月台(IN_WINDOWS_TIME)与离开月台(OUT_WINDOWS_TIME)时间 + 说明:楼层维度以「月台表」为准;车辆预约时若已选月台(WINDOW_NAME 非空)即计入对应楼层。 --> + - + + + + + + + + + + + + + + + + + diff --git a/mhd-bi/src/main/resources/mapper/biWarehouseTransport/BiWarehouseTransportRealDataMapper.xml b/mhd-bi/src/main/resources/mapper/biWarehouseTransport/BiWarehouseTransportRealDataMapper.xml new file mode 100644 index 000000000..6aa344d37 --- /dev/null +++ b/mhd-bi/src/main/resources/mapper/biWarehouseTransport/BiWarehouseTransportRealDataMapper.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + +