上传源代码版本

This commit is contained in:
Im-Jenisson
2026-06-01 16:30:29 +08:00
commit b2a9b7d3c2
462 changed files with 104365 additions and 0 deletions

View File

@@ -0,0 +1,238 @@
# 没有首次扫描时间的包裹处理逻辑 - 说明文档
**更新日期**: 2026-05-16
**主题**: 边界情况处理 - 当包裹没有扫描记录时
**状态**: ✅ 编译通过
---
## 问题说明
**场景**如果一个交接单标签率达到了80%,但其中有些包裹**从未被扫描过**(即没有首次扫描时间),应该如何处理?
**当前SQL逻辑**
```sql
WHERE l.Label IS NOT NULL AND l.Label != ''
AND (
SELECT MIN(ls.CreatedAt)
FROM label_scan_history ls
WHERE ls.NeutralWaybillNumber = l.NeutralWaybillNumber
) > l.LabelRetrievedAt
```
**问题分析**
-`label_scan_history` 中没有记录时,`MIN(ls.CreatedAt)` 返回 **NULL**
- `NULL > l.LabelRetrievedAt` 的比较结果是 **NULL未知**
- 在 CASE WHEN 中NULL 被视为 FALSE
- 这些包裹**不被计入"高标签率"的分子**
- 导致整个交接单的冻结标签率会**偏低**
---
## 处理方案
### 方案选择
**选择**:当没有首次扫描时间时,按**低标签率处理**
### 原因
1. **业务逻辑**
- 如果一个包裹从未被扫描,说明它**还未开始作业**
- 标签的作用是在**作业过程中发挥作用**
- 如果作业未开始,标签的可用性无法判断
- 保守处理:默认认为标签在此时**不可用**
2. **风险规避**
- 避免高估标签率
- 确保考核时间的合理性
3. **数据质量**
- 如果包裹从未被扫描,可能说明:
- 包裹尚未送达仓库
- 包裹信息不完整
- 系统记录有缺失
### SQL实现细节
**当前逻辑**
```sql
冻结标签率 = (最早扫描时间 > 标签推送时间的包裹数) / 总包裹数
处理规则:
IF 最早扫描时间 IS NOT NULL THEN
IF 最早扫描时间 > 标签推送时间 THEN
计入高标签率分子
ELSE
不计入高标签率分子
END IF
ELSE
-- 没有扫描时间
默认不计入高标签率分子(按低标签率处理)
END IF
```
---
## 具体场景示例
### 场景1交接单中的所有包裹都没有扫描记录
```
交接单A
├─ 总包裹数100
├─ 有标签的包裹80
├─ 扫描过的包裹0全部未扫描
├─ 最早扫描时间NULL
└─ 冻结标签率计算:
分子 = 0因为没有满足"最早扫描时间 > 标签推送时间"的包裹)
分母 = 100
冻结标签率 = 0%(低标签率)
考核规则:按低标签率处理(完成即达标)
```
### 场景2交接单中的部分包裹没有扫描记录
```
交接单B
├─ 总包裹数100
├─ 有标签的包裹90
├─ 扫描过的包裹70
│ ├─ 其中:标签推送时间 < 扫描时间的包裹60
│ └─ 其中:标签推送时间 >= 扫描时间的包裹10
└─ 未扫描的包裹30
└─ 这30个包裹不计入高标签率分子
冻结标签率计算:
分子 = 60符合"最早扫描时间 > 标签推送时间"的包裹)
分母 = 100
冻结标签率 = 60%(低标签率)
考核规则:按低标签率处理(完成即达标)
```
### 场景3交接单中大部分包裹有扫描记录少数没有
```
交接单C
├─ 总包裹数100
├─ 有标签的包裹95
├─ 扫描过的包裹99
│ ├─ 其中:最早扫描时间 > 标签推送时间的包裹85
│ └─ 其中:最早扫描时间 <= 标签推送时间的包裹14
└─ 未扫描的包裹1
└─ 这1个包裹不计入高标签率分子
冻结标签率计算:
分子 = 85满足条件的包裹
分母 = 100
冻结标签率 = 85%(高标签率)
考核规则按高标签率处理16点分段
```
---
## 对各个CTE的影响
### InterchangeUnitLabelRates
**计算逻辑**
```sql
labeled_requests = COUNT(DISTINCT CASE
WHEN l.Label IS NOT NULL
AND MIN(ls.CreatedAt) > l.LabelRetrievedAt
THEN l.Id
END)
```
**对没有扫描时间的包裹**
- ✅ 自动不计入 labeled_requests
- ✅ 因此不会虚高冻结标签率
### DailyHighLabelRateShould
**逻辑**:根据 `label_rate_percent >= 80` 判断
**对影响**
- 如果因为没有扫描记录导致冻结标签率 < 80%
- 该交接单会被分类到"低标签率"
- 所有包裹都按低标签率规则处理
### DailyLowLabelRateShould
**逻辑**根据 `label_rate_percent < 80` 判断
**对影响**
- 包含没有扫描记录的交接单
- 这些包裹按完成即达标处理
- 符合保守处理的原则
---
## 数据质量检查建议
### 建议1监控未扫描的包裹
在报表中补充一个指标
```
未扫描包裹数 = COUNT(DISTINCT 订单) WHERE 首次扫描时间 IS NULL
未扫描率 = 未扫描包裹数 / 总包裹数
```
### 建议2定期检查异常
```
IF 未扫描率 > 某个阈值例如5% THEN
→ 报警,检查系统是否有问题
→ 检查数据导入是否完整
END IF
```
### 建议3与现场对账
定期与现场对账确认
- 是否真的有包裹未被扫描
- 还是系统记录有缺失
---
## 总结
### 当前处理方式
```
没有首次扫描时间
不被计入高标签率分子
冻结标签率偏低(或保持原来的水平)
按低标签率规则处理(完成即达标)
```
### 优点
1. **安全保守**避免高估标签率
2. **符合业务逻辑**作业未开始时标签不可用
3. **自动处理**无需特殊编码SQL逻辑自动应对
4. **考核公平**低标签率的包裹按更宽松的规则考核
### 可能的改进
如果后续发现有频繁的未扫描现象可以
1. 加强数据导入的完整性检查
2. 增加数据质量监控指标
3. 与现场沟通了解根本原因
4. 根据实际情况调整处理策略
---
## 编译状态
**编译成功** (exit code 0)
- SQL逻辑已加注释明确说明处理方式
- 无编译错误
- 业务逻辑清晰