|
|
|
|
@ -0,0 +1,597 @@
|
|
|
|
|
# Board1/Board4/Board5 新旧设备业务实现方案
|
|
|
|
|
|
|
|
|
|
## 1. 当前理解
|
|
|
|
|
|
|
|
|
|
### 1.1 已确认的真实业务口径
|
|
|
|
|
|
|
|
|
|
1. PDA 填写的不是“设备累计计数器当前值”,而是“今天已经产了多少”。
|
|
|
|
|
2. `board1` 的机台状态必须区分新旧设备:
|
|
|
|
|
- 旧设备:从 `BASE_DEVICE_PARAM_VAL` 取**当天最新一条**三色灯状态。
|
|
|
|
|
- 新设备:从 `BASE_DEVICE_PARAM_VAL_YYYYMM` 取**近两小时内最新一条**三色灯状态。
|
|
|
|
|
3. `board4` 页面上的“设备总产量”是真实的**历史总产量**,不是“今日增量”。
|
|
|
|
|
4. `board4` 的设备历史总产量正确来源应为:
|
|
|
|
|
- 历史部分:`DEVICE_DAILY_PRODUCTION`
|
|
|
|
|
- 当天部分:`RT_DAILY_PROD_STATE`
|
|
|
|
|
5. `board5` 的“机台当日产量 TOP5”应直接基于 `RT_DAILY_PROD_STATE.current_total` 统计。
|
|
|
|
|
|
|
|
|
|
### 1.2 当前代码与真实业务的差异
|
|
|
|
|
|
|
|
|
|
1. `DmsMobileController.updateDeviceDailyOutput(...)` 当前仍把 PDA 当日产量写为 `机台状态-实际产出数量`,这与“PDA 填的是今天已经产了多少”不一致。
|
|
|
|
|
2. `RtDailyProdStateServiceImpl.incrementProduction(...)` 当前采用的是**累计计数器 delta-sum**算法,首条数据仅建立基线、不计产量;这不适合 PDA 手工录入“今日累计值”。
|
|
|
|
|
3. `Board4Mapper.selectDeviceProductionAnalysis` 当前取的是当天 `RT.current_total`,语义是“今日增量/今日累计”,与页面标题“设备总产量”不一致。
|
|
|
|
|
4. `Board5Mapper.selectProductionTop5` 当前仍直接查 `BASE_DEVICE_PARAM_VAL`,且参数名还是 `生产计数-当前日期生产总数`,没有走统一 RT 口径。
|
|
|
|
|
5. `BaseDeviceParamValMapper.xml` 当前对状态查询已经做了新旧分流,但旧设备也被限制为“近两小时”,这不符合 PDA 三色灯的录入特征。
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 2. 具体需求
|
|
|
|
|
|
|
|
|
|
### 2.1 PDA 当日产量需求
|
|
|
|
|
|
|
|
|
|
1. PDA 输入值语义固定为“今天已经产了多少”。
|
|
|
|
|
2. PDA 写入源表参数名应改为:`生产计数-当前日期生产总数`。
|
|
|
|
|
3. 旧设备写入成功后,不能再按累计计数器做 delta-sum 累加 RT。
|
|
|
|
|
4. 旧设备写入成功后,应把 RT 当天产量**直接覆盖为最新的今日累计值**。
|
|
|
|
|
|
|
|
|
|
### 2.2 Board1 机台状态需求
|
|
|
|
|
|
|
|
|
|
1. `board1` 的状态查询必须区分新旧设备。
|
|
|
|
|
2. 旧设备状态来源:`BASE_DEVICE_PARAM_VAL` 当天最新一条三色灯为 `TRUE` 的状态参数。
|
|
|
|
|
3. 新设备状态来源:月分表近两小时最新一条三色灯为 `TRUE` 的状态参数。
|
|
|
|
|
4. `board4` 的状态统计必须复用 `board1` 的同一套后端口径,避免两个页面状态数量不一致。
|
|
|
|
|
|
|
|
|
|
### 2.3 Board4 设备总产量需求
|
|
|
|
|
|
|
|
|
|
1. 页面上的“设备总产量”必须返回各设备**历史累计总产量**。
|
|
|
|
|
2. 历史累计总产量计算公式:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
设备总产量 = SUM(DEVICE_DAILY_PRODUCTION.daily_prod) + RT_DAILY_PROD_STATE.current_total(当天)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
3. 历史总产量不允许再直接回源表取 `BASE_DEVICE_PARAM_VAL` 或月分表的最新参数值。
|
|
|
|
|
|
|
|
|
|
### 2.4 Board5 当日产量 TOP5 需求
|
|
|
|
|
|
|
|
|
|
1. `board5` 的 TOP5 是“今日产量 TOP5”,不是“历史总产量 TOP5”。
|
|
|
|
|
2. 统一从 `RT_DAILY_PROD_STATE` 取当天 `current_total` 排序。
|
|
|
|
|
3. 百分比计算也统一基于 RT 的最大值,不再回源表取最大参数值。
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 3. 需求分析
|
|
|
|
|
|
|
|
|
|
### 3.1 为什么 PDA 不应继续写 `机台状态-实际产出数量`
|
|
|
|
|
|
|
|
|
|
`机台状态-实际产出数量` 在当前方案里被当成“累计计数器型参数”使用,RT 更新逻辑也是围绕这个语义设计的:
|
|
|
|
|
|
|
|
|
|
- 新值大于旧值:按差值累加
|
|
|
|
|
- 新值小于旧值:视为计数器清零,按新值补量
|
|
|
|
|
- 首条记录:只建立基线,不计产量
|
|
|
|
|
|
|
|
|
|
但 PDA 录入的是“今天已经产了多少”,本身就是**当天结果值**,不是设备累计计数器当前值。
|
|
|
|
|
|
|
|
|
|
如果继续把 PDA 今日值写成 `机台状态-实际产出数量`,会出现两个问题:
|
|
|
|
|
|
|
|
|
|
1. 当天首笔录入会被 RT 当成“基线”,直接丢失首笔产量。
|
|
|
|
|
2. 若后续人工修正把 120 改成 118,delta-sum 会误判为“清零重置”,反而把 118 再累加进去。
|
|
|
|
|
|
|
|
|
|
所以 OLD 设备的 PDA 今日产量与 NEW 设备自动采集累计计数器,**不是同一种语义层级的数据**,不能共用同一套 RT 更新算法。
|
|
|
|
|
|
|
|
|
|
### 3.2 为什么 OLD 设备 RT 应改为“覆盖模式”
|
|
|
|
|
|
|
|
|
|
对于 OLD 设备,PDA 每次录入的值就是“截至当前时刻的今日总产量”,因此 RT 表中当天 `current_total` 的正确值应始终等于**最新一次 PDA 录入值**。
|
|
|
|
|
|
|
|
|
|
正确规则应为:
|
|
|
|
|
|
|
|
|
|
1. 首次录入 100,RT=`100`
|
|
|
|
|
2. 再次录入 120,RT=`120`
|
|
|
|
|
3. 人工修正为 118,RT=`118`
|
|
|
|
|
|
|
|
|
|
也就是说,OLD 设备 RT 更新规则应为:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
RT.current_total = 最新 PDA 今日累计值
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
而不是:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
RT.current_total += 差值
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 3.3 为什么 Board4 设备总产量不能直接查源表最新值
|
|
|
|
|
|
|
|
|
|
页面真实要的是历史总产量,而源表最新值只是某个时间点的参数快照:
|
|
|
|
|
|
|
|
|
|
1. 对新设备,`机台状态-实际产出数量` 可能清零或回退,最新值不等于历史总产量。
|
|
|
|
|
2. 对旧设备,PDA 今日累计值本来就只代表“今天”,更不等于历史总产量。
|
|
|
|
|
|
|
|
|
|
因此历史总产量必须从事实汇总层取数:
|
|
|
|
|
|
|
|
|
|
- 历史已结算天:`DEVICE_DAILY_PRODUCTION`
|
|
|
|
|
- 当天实时部分:`RT_DAILY_PROD_STATE`
|
|
|
|
|
|
|
|
|
|
### 3.4 为什么 Board5 TOP5 应直接查 RT
|
|
|
|
|
|
|
|
|
|
`board5` 要的是“今天谁产得最多”,而 RT 本身就是全设备统一的“当天实时累计产量”结果表。
|
|
|
|
|
|
|
|
|
|
直接查 RT 的好处:
|
|
|
|
|
|
|
|
|
|
1. 旧设备和新设备统一口径。
|
|
|
|
|
2. 不需要分别扫旧表和月分表再汇总。
|
|
|
|
|
3. 避免源表参数名不统一带来的 SQL 分叉。
|
|
|
|
|
4. 与 `board4.dayTotal` 保持一致,便于验数。
|
|
|
|
|
|
|
|
|
|
### 3.5 为什么 Board1 状态查询必须旧设备取“当天最新”、新设备取“近两小时最新”
|
|
|
|
|
|
|
|
|
|
新设备是高频采集,近两小时无数据通常意味着设备离线、采集异常或未开机,因此两小时窗口合理。
|
|
|
|
|
旧设备三色灯由 PDA 事件驱动写入,不会像自动采集那样高频上报。如果也强行加两小时窗口,下午很容易把上午录过状态的旧设备误判成“未开机”。
|
|
|
|
|
|
|
|
|
|
所以状态窗口必须区分:
|
|
|
|
|
|
|
|
|
|
1. 旧设备:当天最新
|
|
|
|
|
2. 新设备:近两小时最新
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 4. 目标实现方案
|
|
|
|
|
|
|
|
|
|
### 4.1 统一分层
|
|
|
|
|
|
|
|
|
|
1. 源明细层
|
|
|
|
|
- 旧设备:`BASE_DEVICE_PARAM_VAL`
|
|
|
|
|
- 新设备:`BASE_DEVICE_PARAM_VAL_YYYYMM`
|
|
|
|
|
2. 当天实时层
|
|
|
|
|
- `RT_DAILY_PROD_STATE`
|
|
|
|
|
3. 历史日汇总层
|
|
|
|
|
- `DEVICE_DAILY_PRODUCTION`
|
|
|
|
|
|
|
|
|
|
### 4.2 统一统计口径
|
|
|
|
|
|
|
|
|
|
1. `board4.dayTotal`:查 RT 当天总和
|
|
|
|
|
2. `board4.monthTotal`:查 DAY 当月累计 + 今天 RT
|
|
|
|
|
3. `board4.设备总产量`:查每台设备 `DAY 累计 + 今天 RT`
|
|
|
|
|
4. `board5.TOP5`:查 RT 当天每台设备 `current_total`
|
|
|
|
|
|
|
|
|
|
### 4.3 RT 更新策略分流
|
|
|
|
|
|
|
|
|
|
#### NEW 设备
|
|
|
|
|
|
|
|
|
|
1. 来源参数:`机台状态-实际产出数量`
|
|
|
|
|
2. 写入位置:月分表
|
|
|
|
|
3. 更新 RT 方式:数据库触发器 delta-sum
|
|
|
|
|
|
|
|
|
|
#### OLD 设备
|
|
|
|
|
|
|
|
|
|
1. 来源参数:`生产计数-当前日期生产总数`
|
|
|
|
|
2. 写入位置:`BASE_DEVICE_PARAM_VAL`
|
|
|
|
|
3. 更新 RT 方式:Java Service 覆盖当天总量
|
|
|
|
|
|
|
|
|
|
### 4.4 RT/DAY 参数名的统一策略
|
|
|
|
|
|
|
|
|
|
虽然 OLD 设备源表写入的是 `生产计数-当前日期生产总数`,但 RT/DAY 作为统计事实表,建议继续统一使用:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
param_name = '机台状态-实际产出数量'
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
这样做的原因:
|
|
|
|
|
|
|
|
|
|
1. RT/DAY 面向的是“统一产量事实”,不是“来源参数原样搬运”。
|
|
|
|
|
2. 下游 `Board4Mapper`、`Board5Mapper` 无需因为新旧设备来源不同而拆两套 SQL。
|
|
|
|
|
3. 后续若还有别的来源参数接入,也可以统一沉淀到同一个统计事实口径。
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 5. 注意点
|
|
|
|
|
|
|
|
|
|
### 5.1 必须区分“源参数语义”和“统计事实语义”
|
|
|
|
|
|
|
|
|
|
1. OLD 源参数是“今日累计值”
|
|
|
|
|
2. NEW 源参数是“累计计数器当前值”
|
|
|
|
|
3. RT/DAY 保存的是“统一统计产量事实”
|
|
|
|
|
|
|
|
|
|
不能因为 RT/DAY 继续使用同一个 `param_name`,就误以为源数据语义也相同。
|
|
|
|
|
|
|
|
|
|
### 5.2 旧设备不能再走 delta-sum
|
|
|
|
|
|
|
|
|
|
这条是本次方案最关键的边界。
|
|
|
|
|
只要 PDA 输入值语义是“今天已经产了多少”,OLD 设备 RT 就必须走覆盖逻辑,而不能走差值累加逻辑。
|
|
|
|
|
|
|
|
|
|
### 5.3 Board4 文案与返回值必须一致
|
|
|
|
|
|
|
|
|
|
当前旧文档里把 `selectDeviceProductionAnalysis` 定义成“今日增量”,但页面标题是“设备总产量”。本次方案以页面真实语义为准,后端返回值改为历史总产量。
|
|
|
|
|
|
|
|
|
|
### 5.4 Board5 TOP5 不再直接扫源表
|
|
|
|
|
|
|
|
|
|
当 RT/DAY 链路跑通后,TOP5 不应再回源表按参数名硬查,否则会再次引入:
|
|
|
|
|
|
|
|
|
|
1. 新旧设备源不同
|
|
|
|
|
2. 参数名不同
|
|
|
|
|
3. 算法不同
|
|
|
|
|
|
|
|
|
|
这三个分叉点。
|
|
|
|
|
|
|
|
|
|
### 5.5 Board1 与 Board4 状态必须复用同一接口口径
|
|
|
|
|
|
|
|
|
|
`board4` 不能自己另写一套设备状态统计 SQL。
|
|
|
|
|
应继续复用 `aucma-base` 的状态统计接口,只修改底层 SQL 口径。
|
|
|
|
|
|
|
|
|
|
### 5.6 Oracle 11 兼容约束
|
|
|
|
|
|
|
|
|
|
1. SQL 继续使用当前项目已采用的 `ROW_NUMBER()`、`NVL()`、`TRUNC(SYSDATE)` 风格。
|
|
|
|
|
2. 避免引入 Oracle 11 不支持的高级 JSON/递归查询写法。
|
|
|
|
|
3. 动态分表名仍必须经后端受控生成,禁止前端透传表名。
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 6. 具体修改代码方案
|
|
|
|
|
|
|
|
|
|
## 6.1 修改 PDA 当日产量写入参数
|
|
|
|
|
|
|
|
|
|
### 文件位置
|
|
|
|
|
|
|
|
|
|
`zs_aucma-mes-back/aucma-dms/src/main/java/com/aucma/dms/controller/DmsMobileController.java`
|
|
|
|
|
|
|
|
|
|
### 修改目标
|
|
|
|
|
|
|
|
|
|
1. 把 PDA 当日产量写入参数从 `机台状态-实际产出数量` 改为 `生产计数-当前日期生产总数`
|
|
|
|
|
2. 保留源表完整时间序列,供追溯查询使用
|
|
|
|
|
|
|
|
|
|
### 建议代码
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
// 文件:zs_aucma-mes-back/aucma-dms/src/main/java/com/aucma/dms/controller/DmsMobileController.java
|
|
|
|
|
|
|
|
|
|
private static final String PARAM_NAME_PDA_DAILY_TOTAL = "生产计数-当前日期生产总数";
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* PDA-选择设备后更新当日产量(写入参数:生产计数-当前日期生产总数)
|
|
|
|
|
*/
|
|
|
|
|
@PostMapping("/device/updateDailyOutput")
|
|
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
|
|
public AjaxResult updateDeviceDailyOutput(@RequestBody DmsPdaDeviceParamUpdateVo request) {
|
|
|
|
|
if (request == null) {
|
|
|
|
|
throw new ServiceException("请求体不能为空");
|
|
|
|
|
}
|
|
|
|
|
return updatePdaDeviceParamValue(
|
|
|
|
|
request.getDeviceCode(),
|
|
|
|
|
request.getDeviceId(),
|
|
|
|
|
request.getParamValue(),
|
|
|
|
|
PARAM_NAME_PDA_DAILY_TOTAL,
|
|
|
|
|
true,
|
|
|
|
|
"当日产量"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 行间注释要求
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
// 为什么这样做:PDA 录入的是“今天已经产了多少”,
|
|
|
|
|
// 它在业务语义上就是“生产计数-当前日期生产总数”,不能再伪装成累计计数器参数。
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 6.2 新增 OLD 设备 RT 覆盖写入能力
|
|
|
|
|
|
|
|
|
|
### 文件位置
|
|
|
|
|
|
|
|
|
|
1. `zs_aucma-mes-back/aucma-base/src/main/java/com/aucma/base/service/IRtDailyProdStateService.java`
|
|
|
|
|
2. `zs_aucma-mes-back/aucma-base/src/main/java/com/aucma/base/service/impl/RtDailyProdStateServiceImpl.java`
|
|
|
|
|
3. `zs_aucma-mes-back/aucma-base/src/main/java/com/aucma/base/service/impl/BaseDeviceParamValServiceImpl.java`
|
|
|
|
|
|
|
|
|
|
### 修改目标
|
|
|
|
|
|
|
|
|
|
1. OLD 设备写入 `生产计数-当前日期生产总数` 后,直接覆盖 RT 当天总量
|
|
|
|
|
2. RT 中的 `param_name` 继续统一写为 `机台状态-实际产出数量`
|
|
|
|
|
|
|
|
|
|
### 建议接口
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
// 文件:IRtDailyProdStateService.java
|
|
|
|
|
|
|
|
|
|
void overwriteTodayProduction(String deviceCode, String paramName, BigDecimal todayTotal, Date collectTime);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 建议实现
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
// 文件:RtDailyProdStateServiceImpl.java
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
|
|
public void overwriteTodayProduction(String deviceCode, String paramName, BigDecimal todayTotal, Date collectTime) {
|
|
|
|
|
if (deviceCode == null || paramName == null || todayTotal == null || collectTime == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Date prodDate = truncateToDay(collectTime);
|
|
|
|
|
RtDailyProdState state = rtDailyProdStateMapper.selectForUpdate(prodDate, deviceCode, paramName);
|
|
|
|
|
Date now = new Date();
|
|
|
|
|
|
|
|
|
|
if (state == null) {
|
|
|
|
|
RtDailyProdState insertState = new RtDailyProdState();
|
|
|
|
|
insertState.setProdDate(prodDate);
|
|
|
|
|
insertState.setDeviceCode(deviceCode);
|
|
|
|
|
insertState.setParamName(paramName);
|
|
|
|
|
insertState.setLastParamVal(todayTotal);
|
|
|
|
|
insertState.setCurrentTotal(todayTotal);
|
|
|
|
|
insertState.setResetCount(0L);
|
|
|
|
|
insertState.setDirtyFlag(0L);
|
|
|
|
|
insertState.setLastCollectTime(collectTime);
|
|
|
|
|
insertState.setUpdateTime(now);
|
|
|
|
|
rtDailyProdStateMapper.insertRtDailyProdState(insertState);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 为什么这样做:OLD 设备上报的是“今天当前总量”,
|
|
|
|
|
// 这里必须直接覆盖 RT 结果,不能按差值累加,否则人工修正会把产量越改越大。
|
|
|
|
|
state.setLastParamVal(todayTotal);
|
|
|
|
|
state.setCurrentTotal(todayTotal);
|
|
|
|
|
state.setLastCollectTime(collectTime);
|
|
|
|
|
state.setUpdateTime(now);
|
|
|
|
|
rtDailyProdStateMapper.updateRtDailyProdState(state);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Base Service 路由建议
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
// 文件:BaseDeviceParamValServiceImpl.java
|
|
|
|
|
|
|
|
|
|
private static final String DAILY_OUTPUT_PARAM_NAME = "机台状态-实际产出数量";
|
|
|
|
|
private static final String PDA_DAILY_TOTAL_PARAM_NAME = "生产计数-当前日期生产总数";
|
|
|
|
|
|
|
|
|
|
private void syncRtStateIfNeeded(BaseDeviceParamVal entity, int rows) {
|
|
|
|
|
if (rows <= 0 || !deviceParamTableRouter.isOldDevice(entity.getDeviceCode())) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
BigDecimal newVal = new BigDecimal(entity.getParamValue());
|
|
|
|
|
|
|
|
|
|
if (PDA_DAILY_TOTAL_PARAM_NAME.equals(entity.getParamName())) {
|
|
|
|
|
// 为什么这样做:OLD 设备源数据是“今日累计值”,
|
|
|
|
|
// RT 要保存的是当天权威总量,因此采用覆盖模式。
|
|
|
|
|
rtDailyProdStateService.overwriteTodayProduction(
|
|
|
|
|
entity.getDeviceCode(),
|
|
|
|
|
DAILY_OUTPUT_PARAM_NAME,
|
|
|
|
|
newVal,
|
|
|
|
|
entity.getCollectTime()
|
|
|
|
|
);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (DAILY_OUTPUT_PARAM_NAME.equals(entity.getParamName())) {
|
|
|
|
|
// 保留历史兼容能力:如果旧链路仍写累计计数器参数,则继续按旧规则处理。
|
|
|
|
|
rtDailyProdStateService.incrementProduction(
|
|
|
|
|
entity.getDeviceCode(),
|
|
|
|
|
entity.getParamName(),
|
|
|
|
|
newVal,
|
|
|
|
|
entity.getCollectTime()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
} catch (NumberFormatException ex) {
|
|
|
|
|
log.warn("OLD设备产量值不是合法数字,跳过RT同步 | deviceCode={}, paramValue={}",
|
|
|
|
|
entity.getDeviceCode(), entity.getParamValue());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 6.3 修改 Board1 状态 SQL
|
|
|
|
|
|
|
|
|
|
### 文件位置
|
|
|
|
|
|
|
|
|
|
`zs_aucma-mes-back/aucma-base/src/main/resources/mapper/base/BaseDeviceParamValMapper.xml`
|
|
|
|
|
|
|
|
|
|
### 修改目标
|
|
|
|
|
|
|
|
|
|
1. 旧设备:当天最新三色灯
|
|
|
|
|
2. 新设备:近两小时最新三色灯
|
|
|
|
|
|
|
|
|
|
### 建议 SQL 结构
|
|
|
|
|
|
|
|
|
|
```xml
|
|
|
|
|
<!-- 文件:zs_aucma-mes-back/aucma-base/src/main/resources/mapper/base/BaseDeviceParamValMapper.xml -->
|
|
|
|
|
|
|
|
|
|
<select id="selectDeviceStatusStatistics" parameterType="java.util.Map" resultType="java.util.Map">
|
|
|
|
|
WITH merged_param AS (
|
|
|
|
|
<trim suffixOverrides="UNION ALL">
|
|
|
|
|
SELECT device_code, param_name, collect_time, record_time
|
|
|
|
|
FROM BASE_DEVICE_PARAM_VAL
|
|
|
|
|
WHERE device_code LIKE 'OLD-%'
|
|
|
|
|
AND param_name IN ('机台状态-三色灯机器运行', '机台状态-三色灯机器暂停', '机台状态-三色灯机器待机', '机台状态-三色灯机器报警')
|
|
|
|
|
AND UPPER(param_value) = 'TRUE'
|
|
|
|
|
AND collect_time >= TRUNC(SYSDATE)
|
|
|
|
|
AND collect_time < TRUNC(SYSDATE) + 1
|
|
|
|
|
UNION ALL
|
|
|
|
|
<if test="tableSuffixes != null and tableSuffixes.size() > 0">
|
|
|
|
|
<foreach item="suffix" collection="tableSuffixes" separator=" UNION ALL ">
|
|
|
|
|
SELECT device_code, param_name, collect_time, record_time
|
|
|
|
|
FROM BASE_DEVICE_PARAM_VAL_${suffix}
|
|
|
|
|
WHERE device_code NOT LIKE 'OLD-%'
|
|
|
|
|
AND param_name IN ('机台状态-三色灯机器运行', '机台状态-三色灯机器暂停', '机台状态-三色灯机器待机', '机台状态-三色灯机器报警')
|
|
|
|
|
AND UPPER(param_value) = 'TRUE'
|
|
|
|
|
AND collect_time >= SYSDATE - (2/24)
|
|
|
|
|
AND collect_time < SYSDATE
|
|
|
|
|
</foreach>
|
|
|
|
|
</if>
|
|
|
|
|
</trim>
|
|
|
|
|
)
|
|
|
|
|
...
|
|
|
|
|
</select>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 行间注释要求
|
|
|
|
|
|
|
|
|
|
```xml
|
|
|
|
|
<!-- 为什么这样做:OLD 设备三色灯由 PDA 事件驱动写入,不是高频自动采集;
|
|
|
|
|
如果也强制限制近两小时,会把当天早些时候录过状态的设备误判成未开机。 -->
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
同样的窗口规则要同步应用到:
|
|
|
|
|
|
|
|
|
|
1. `selectDeviceStatusStatistics`
|
|
|
|
|
2. `selectDeviceStatusList`
|
|
|
|
|
|
|
|
|
|
## 6.4 修改 Board4 设备总产量 SQL
|
|
|
|
|
|
|
|
|
|
### 文件位置
|
|
|
|
|
|
|
|
|
|
`zs_aucma-mes-back/aucma-report/src/main/resources/mapper/report/Board4Mapper.xml`
|
|
|
|
|
|
|
|
|
|
### 修改目标
|
|
|
|
|
|
|
|
|
|
将 `selectDeviceProductionAnalysis` 从“今日 RT”改为“历史总产量”。
|
|
|
|
|
|
|
|
|
|
### 建议 SQL
|
|
|
|
|
|
|
|
|
|
```xml
|
|
|
|
|
<!-- 文件:zs_aucma-mes-back/aucma-report/src/main/resources/mapper/report/Board4Mapper.xml -->
|
|
|
|
|
|
|
|
|
|
<select id="selectDeviceProductionAnalysis" resultType="com.aucma.report.domain.vo.Board4DeviceProductionVo">
|
|
|
|
|
SELECT d.DEVICE_NAME AS deviceName,
|
|
|
|
|
NVL(h.history_total, 0) + NVL(r.current_total, 0) AS production
|
|
|
|
|
FROM BASE_DEVICELEDGER d
|
|
|
|
|
LEFT JOIN (
|
|
|
|
|
SELECT device_code,
|
|
|
|
|
SUM(daily_prod) AS history_total
|
|
|
|
|
FROM DEVICE_DAILY_PRODUCTION
|
|
|
|
|
WHERE param_name = '机台状态-实际产出数量'
|
|
|
|
|
GROUP BY device_code
|
|
|
|
|
) h
|
|
|
|
|
ON d.device_code = h.device_code
|
|
|
|
|
LEFT JOIN RT_DAILY_PROD_STATE r
|
|
|
|
|
ON d.device_code = r.device_code
|
|
|
|
|
AND r.prod_date = TRUNC(SYSDATE)
|
|
|
|
|
AND r.param_name = '机台状态-实际产出数量'
|
|
|
|
|
WHERE d.IS_FLAG = 1
|
|
|
|
|
ORDER BY production DESC, d.device_code
|
|
|
|
|
</select>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 行间注释要求
|
|
|
|
|
|
|
|
|
|
```xml
|
|
|
|
|
<!-- 为什么这样做:页面真实语义是“设备总产量”,
|
|
|
|
|
因此必须使用“历史 DAY 汇总 + 今日 RT”两段式结果,而不是只看今天 RT。 -->
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 6.5 修改 Board5 TOP5 SQL
|
|
|
|
|
|
|
|
|
|
### 文件位置
|
|
|
|
|
|
|
|
|
|
`zs_aucma-mes-back/aucma-report/src/main/resources/mapper/report/Board5Mapper.xml`
|
|
|
|
|
|
|
|
|
|
### 修改目标
|
|
|
|
|
|
|
|
|
|
1. `selectProductionTop5` 改为直接查 RT
|
|
|
|
|
2. `selectMaxProduction` 改为直接查 RT
|
|
|
|
|
|
|
|
|
|
### 建议 SQL
|
|
|
|
|
|
|
|
|
|
```xml
|
|
|
|
|
<!-- 文件:zs_aucma-mes-back/aucma-report/src/main/resources/mapper/report/Board5Mapper.xml -->
|
|
|
|
|
|
|
|
|
|
<select id="selectProductionTop5" resultType="com.aucma.report.domain.vo.Board5ProductionTopVo">
|
|
|
|
|
SELECT * FROM (
|
|
|
|
|
SELECT d.DEVICE_NAME AS deviceName,
|
|
|
|
|
NVL(r.current_total, 0) AS production,
|
|
|
|
|
0 AS percent
|
|
|
|
|
FROM BASE_DEVICELEDGER d
|
|
|
|
|
LEFT JOIN RT_DAILY_PROD_STATE r
|
|
|
|
|
ON d.DEVICE_CODE = r.DEVICE_CODE
|
|
|
|
|
AND r.prod_date = TRUNC(SYSDATE)
|
|
|
|
|
AND r.param_name = '机台状态-实际产出数量'
|
|
|
|
|
WHERE d.IS_FLAG = 1
|
|
|
|
|
ORDER BY production DESC, d.device_code
|
|
|
|
|
)
|
|
|
|
|
WHERE ROWNUM <= 5
|
|
|
|
|
</select>
|
|
|
|
|
|
|
|
|
|
<select id="selectMaxProduction" resultType="java.lang.Long">
|
|
|
|
|
SELECT NVL(MAX(current_total), 1)
|
|
|
|
|
FROM RT_DAILY_PROD_STATE
|
|
|
|
|
WHERE prod_date = TRUNC(SYSDATE)
|
|
|
|
|
AND param_name = '机台状态-实际产出数量'
|
|
|
|
|
</select>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 行间注释要求
|
|
|
|
|
|
|
|
|
|
```xml
|
|
|
|
|
<!-- 为什么这样做:TOP5 要的是“今日产量排名”,RT 已经是新旧设备统一后的当天实时累计结果,
|
|
|
|
|
再回源表分开查只会把统计口径重新打散。 -->
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 7. 代码文件位置汇总
|
|
|
|
|
|
|
|
|
|
### 必改文件
|
|
|
|
|
|
|
|
|
|
1. `zs_aucma-mes-back/aucma-dms/src/main/java/com/aucma/dms/controller/DmsMobileController.java`
|
|
|
|
|
2. `zs_aucma-mes-back/aucma-base/src/main/java/com/aucma/base/service/IRtDailyProdStateService.java`
|
|
|
|
|
3. `zs_aucma-mes-back/aucma-base/src/main/java/com/aucma/base/service/impl/RtDailyProdStateServiceImpl.java`
|
|
|
|
|
4. `zs_aucma-mes-back/aucma-base/src/main/java/com/aucma/base/service/impl/BaseDeviceParamValServiceImpl.java`
|
|
|
|
|
5. `zs_aucma-mes-back/aucma-base/src/main/resources/mapper/base/BaseDeviceParamValMapper.xml`
|
|
|
|
|
6. `zs_aucma-mes-back/aucma-report/src/main/resources/mapper/report/Board4Mapper.xml`
|
|
|
|
|
7. `zs_aucma-mes-back/aucma-report/src/main/resources/mapper/report/Board5Mapper.xml`
|
|
|
|
|
|
|
|
|
|
### 需同步确认但本次可不改的文件
|
|
|
|
|
|
|
|
|
|
1. `zs_aucma-mes-ui/src/views/board/board1/index.vue`
|
|
|
|
|
2. `zs_aucma-mes-ui/src/views/board/board4/index.vue`
|
|
|
|
|
3. `zs_aucma-mes-ui/src/views/board/board5/index.vue`
|
|
|
|
|
4. `zs_aucma-mes-back/aucma-base/src/main/resources/board4_end_to_end_full_implementation_guide.md`
|
|
|
|
|
5. `zs_aucma-mes-back/aucma-base/src/main/resources/梳理.md`
|
|
|
|
|
|
|
|
|
|
说明:
|
|
|
|
|
|
|
|
|
|
前端接口名本次可保持不变,主要修正后端返回语义;但旧文档中“设备总产量=今日增量”的描述必须后续同步修正,避免再次误导实现。
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 8. 验证清单
|
|
|
|
|
|
|
|
|
|
### 8.1 OLD 设备 PDA 录入验证
|
|
|
|
|
|
|
|
|
|
1. 09:00 录入 OLD-01 当日产量 `100`
|
|
|
|
|
- 源表写入参数名应为 `生产计数-当前日期生产总数`
|
|
|
|
|
- RT 中 OLD-01 当天 `current_total=100`
|
|
|
|
|
2. 11:00 再录入 `120`
|
|
|
|
|
- RT 应直接变为 `120`
|
|
|
|
|
3. 11:30 修正为 `118`
|
|
|
|
|
- RT 应直接变为 `118`
|
|
|
|
|
- 不允许变成 `238`
|
|
|
|
|
|
|
|
|
|
### 8.2 Board1 状态验证
|
|
|
|
|
|
|
|
|
|
1. OLD 设备上午 9 点录入“暂停”,下午 3 点未再录入
|
|
|
|
|
- `board1` 仍应显示“停机/暂停”
|
|
|
|
|
2. NEW 设备超过两小时无采集
|
|
|
|
|
- `board1` 应按无有效状态数据处理
|
|
|
|
|
|
|
|
|
|
### 8.3 Board4 历史总产量验证
|
|
|
|
|
|
|
|
|
|
1. `DEVICE_DAILY_PRODUCTION` 中某设备历史累计 `3000`
|
|
|
|
|
2. `RT_DAILY_PROD_STATE` 当天 `200`
|
|
|
|
|
3. 页面“设备总产量”应显示 `3200`
|
|
|
|
|
|
|
|
|
|
### 8.4 Board5 TOP5 验证
|
|
|
|
|
|
|
|
|
|
1. 取 RT 当天数据做排序
|
|
|
|
|
2. TOP5 与 `board4.dayTotal` 的设备明细求和口径应一致
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 9. 最终结论
|
|
|
|
|
|
|
|
|
|
本次业务梳理后的关键结论只有三条:
|
|
|
|
|
|
|
|
|
|
1. OLD 设备 PDA 录入值是“今日累计值”,因此源表应写 `生产计数-当前日期生产总数`,RT 更新必须走**覆盖模式**。
|
|
|
|
|
2. NEW 设备自动采集值是“累计计数器当前值”,因此继续通过月分表触发器按 **delta-sum** 更新 RT。
|
|
|
|
|
3. 所有大屏统计最终都应尽量读取 RT/DAY 事实层,而不是重新回源表拼业务逻辑。
|
|
|
|
|
|
|
|
|
|
只要这三条不被打破,`board1`、`board4`、`board5` 的状态、今日产量、历史总产量三套口径就能统一起来。
|