|
|
# DmsMobileController 故障报修重构方案
|
|
|
|
|
|
> **文档版本**: 3.1
|
|
|
> **创建日期**: 2026-02-05
|
|
|
> **最后更新**: 2026-02-05
|
|
|
> **作者**: Claude AI
|
|
|
> **项目**: AUCMA-MES 设备管理系统
|
|
|
> **模块**: DMS 设备管理 - PDA故障报修
|
|
|
|
|
|
> **重要说明**:
|
|
|
> 1. 本方案仅关注 DmsMobileController 的重构,保持PDA完美兼容,内部补全完整业务流程
|
|
|
> 2. DmsBillsFaultInstanceController 为Web端接口,不在本次重构范围
|
|
|
> 3. **设备信息改为使用 BaseDeviceLedger(base模块),但返回类型为 DmsBaseDeviceLedger(dms模块),需要进行字段转换**
|
|
|
|
|
|
---
|
|
|
|
|
|
## 一、重构背景
|
|
|
|
|
|
### 1.1 当前问题分析
|
|
|
|
|
|
#### 1.1.1 DmsMobileController 故障报修方法现状
|
|
|
|
|
|
**现有方法**:
|
|
|
| 方法 | 行号范围 | 当前问题 |
|
|
|
|------|---------|----------|
|
|
|
| insertFaultInstsanceActivity | ~ | 基本正常,创建故障报修 |
|
|
|
| startRepair | ~ | **关键问题**:缺少维修工单和派工计划创建逻辑 |
|
|
|
| completeRepair | ~ | **关键问题**:缺少维修记录创建逻辑 |
|
|
|
| getBillsFaultInstance4Repair | ~ | 方法复杂,包含知识库匹配逻辑 |
|
|
|
|
|
|
#### 1.1.2 业务流程不完整
|
|
|
|
|
|
**PDA端当前流程**:
|
|
|
```
|
|
|
PDA创建故障报修 → dms_bills_fault_instance 表
|
|
|
↓
|
|
|
PDA开始维修 → ❌ 缺少:创建维修工单(dms_repair_work_order)
|
|
|
❌ 缺少:创建派工计划(dms_dispatch_plan)
|
|
|
❌ 缺少:触发断点1(故障报修状态→维修中)
|
|
|
↓
|
|
|
PDA完成维修 → ❌ 缺少:触发断点3(创建维修记录 dms_repair_record)
|
|
|
❌ 缺少:触发断点3(故障报修状态→维修完成)
|
|
|
```
|
|
|
|
|
|
**Web端完整流程**(参考):
|
|
|
```
|
|
|
故障报修 (dms_bills_fault_instance)
|
|
|
↓
|
|
|
维修工单 (dms_repair_work_order) ← 【断点1】更新故障报修状态
|
|
|
↓
|
|
|
派工计划 (dms_dispatch_plan) ← 【断点2】派工时自动创建
|
|
|
↓
|
|
|
维修完成
|
|
|
↓
|
|
|
维修记录 (dms_repair_record) ← 【断点3】自动创建,更新故障报修状态
|
|
|
```
|
|
|
|
|
|
#### 1.1.3 问题影响
|
|
|
|
|
|
- **数据完整性缺失**:PDA操作后,Web端的维修工单和派工计划模块看不到数据
|
|
|
- **状态不一致**:故障报修、维修工单、派工计划、维修记录之间的状态无法同步
|
|
|
- **业务流程断裂**:3个断点修复机制在PDA端无法工作
|
|
|
|
|
|
### 1.2 重构目标
|
|
|
|
|
|
1. **PDA完美兼容**:PDA端不需要做任何修改,接口路径和参数格式完全不变
|
|
|
2. **业务流程补全**:DmsMobileController 内部补全维修工单和派工计划的创建
|
|
|
3. **数据一致性**:确保4个Service之间的数据完全同步
|
|
|
4. **最小改动**:仅修改 DmsMobileController,不涉及 Web 端的 DmsBillsFaultInstanceController
|
|
|
|
|
|
---
|
|
|
|
|
|
## 二、架构设计
|
|
|
|
|
|
### 2.1 DmsMobileController 重构架构
|
|
|
|
|
|
```
|
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
|
│ PDA 端(Android) │
|
|
|
└────────────────────────┬────────────────────────────────────┘
|
|
|
│ HTTP/Multipart
|
|
|
▼
|
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
|
│ DmsMobileController(代理模式) │
|
|
|
├─────────────────────────────────────────────────────────────┤
|
|
|
│ 保持所有 /dms/mobile/* 接口路径不变 │
|
|
|
│ 保持所有参数格式不变 │
|
|
|
│ 内部转换为业务逻辑调用 │
|
|
|
├─────────────────────────────────────────────────────────────┤
|
|
|
│ 依赖注入的4个Service: │
|
|
|
│ - DmsBillsFaultInstanceService(故障报修服务) │
|
|
|
│ - DmsRepairWorkOrderService(维修工单服务) │
|
|
|
│ - DmsDispatchPlanService(派工计划服务) │
|
|
|
│ - DmsRepairRecordService(维修记录服务) │
|
|
|
└────────────────────────┬────────────────────────────────────┘
|
|
|
│
|
|
|
▼
|
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
|
│ 业务服务层(现有4个Service) │
|
|
|
├─────────────────────────────────────────────────────────────┤
|
|
|
│ DmsBillsFaultInstanceServiceImpl │
|
|
|
│ DmsRepairWorkOrderServiceImpl │
|
|
|
│ DmsDispatchPlanServiceImpl │
|
|
|
│ DmsRepairRecordServiceImpl │
|
|
|
└─────────────────────────────────────────────────────────────┘
|
|
|
```
|
|
|
|
|
|
### 2.2 核心方法改造方案
|
|
|
|
|
|
#### 2.2.1 startRepair 方法改造
|
|
|
|
|
|
**改造前**:
|
|
|
```java
|
|
|
@PostMapping("/startRepair")
|
|
|
public AjaxResult startRepair(@RequestBody DmsFaultInstanceActivity activity) {
|
|
|
// 直接更新操作记录
|
|
|
// ❌ 缺少维修工单创建
|
|
|
// ❌ 缺少派工计划创建
|
|
|
// ❌ 缺少状态同步
|
|
|
}
|
|
|
```
|
|
|
|
|
|
**改造后**:
|
|
|
```java
|
|
|
@PostMapping("/startRepair")
|
|
|
public AjaxResult startRepair(@RequestBody DmsFaultInstanceActivity activity) {
|
|
|
// 1. 查询故障报修
|
|
|
// 2. 检查是否已有维修工单,没有则创建
|
|
|
// 3. 【断点1】更新故障报修状态为"维修中"
|
|
|
// 4. 创建派工计划
|
|
|
// 5. 【断点2】自动接收派工
|
|
|
// 6. 更新维修工单状态为"维修中"
|
|
|
// 7. 更新操作记录
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 2.2.2 completeRepair 方法改造
|
|
|
|
|
|
**改造前**:
|
|
|
```java
|
|
|
@PostMapping("/completeRepair")
|
|
|
public AjaxResult completeRepair(...) {
|
|
|
// 直接更新操作记录
|
|
|
// ❌ 缺少维修记录创建
|
|
|
// ❌ 缺少状态同步
|
|
|
}
|
|
|
```
|
|
|
|
|
|
**改造后**:
|
|
|
```java
|
|
|
@PostMapping("/completeRepair")
|
|
|
public AjaxResult completeRepair(...) {
|
|
|
// 1. 查询故障报修和维修工单
|
|
|
// 2. 更新维修工单状态为"已完成"
|
|
|
// 3. 【断点3】创建维修记录
|
|
|
// 4. 【断点3】更新故障报修状态为"维修完成"
|
|
|
// 5. 处理配件消耗
|
|
|
// 6. 更新操作记录
|
|
|
}
|
|
|
```
|
|
|
|
|
|
---
|
|
|
|
|
|
## 三、需要新建的DTO类
|
|
|
|
|
|
### 3.1 DTO清单(可选,用于内部转换)
|
|
|
|
|
|
| 序号 | DTO类名 | 文件路径 | 用途 |
|
|
|
|------|---------|----------|------|
|
|
|
| 1 | DmsFaultRepairContext | aucma-dms/src/main/java/com/aucma/dms/dto/ | 维修上下文信息(内部使用) |
|
|
|
|
|
|
**说明**:DTO类主要用于内部参数传递,也可以直接使用现有的实体类。
|
|
|
|
|
|
---
|
|
|
|
|
|
## 四、DmsMobileController 重构方案
|
|
|
|
|
|
### 4.1 文件路径
|
|
|
|
|
|
**文件**: `aucma-dms/src/main/java/com/aucma/dms/controller/DmsMobileController.java`
|
|
|
|
|
|
### 4.2 依赖注入(新增)
|
|
|
|
|
|
```java
|
|
|
@RestController
|
|
|
@RequestMapping("/dms/mobile")
|
|
|
public class DmsMobileController extends BaseController {
|
|
|
|
|
|
// 现有依赖
|
|
|
@Autowired
|
|
|
private IDmsBillsFaultInstanceService dmsBillsFaultInstanceService;
|
|
|
|
|
|
// 【新增】维修工单服务
|
|
|
@Autowired
|
|
|
private IDmsRepairWorkOrderService dmsRepairWorkOrderService;
|
|
|
|
|
|
// 【新增】派工计划服务
|
|
|
@Autowired
|
|
|
private IDmsDispatchPlanService dmsDispatchPlanService;
|
|
|
|
|
|
// 【新增】维修记录服务
|
|
|
@Autowired
|
|
|
private IDmsRepairRecordService dmsRepairRecordService;
|
|
|
|
|
|
// 【新增】维修知识库服务(可选,用于 getBillsFaultInstance4Repair)
|
|
|
@Autowired
|
|
|
private IDmsKnowledgeRepairService dmsKnowledgeRepairService;
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 4.3 startRepair 方法完整重构
|
|
|
|
|
|
```java
|
|
|
/**
|
|
|
* 开始维修
|
|
|
*
|
|
|
* 【重构说明】
|
|
|
* - 保持接口路径和参数格式不变
|
|
|
* - 内部补全维修工单和派工计划的创建逻辑
|
|
|
* - 触发断点1和断点2,确保数据完整性
|
|
|
*/
|
|
|
@PostMapping("/startRepair")
|
|
|
public AjaxResult startRepair(@RequestBody DmsFaultInstanceActivity activity) {
|
|
|
try {
|
|
|
Long faultInstanceId = activity.getRepairInstanceId();
|
|
|
String repairer = activity.getRepairer();
|
|
|
|
|
|
log.info("PDA开始维修,故障报修ID: {}, 维修人: {}", faultInstanceId, repairer);
|
|
|
|
|
|
// ========== 步骤1:查询故障报修 ==========
|
|
|
DmsBillsFaultInstance fault = dmsBillsFaultInstanceService
|
|
|
.selectDmsBillsFaultInstanceByRepairInstanceId(faultInstanceId);
|
|
|
if (fault == null) {
|
|
|
return AjaxResult.error("故障报修不存在");
|
|
|
}
|
|
|
|
|
|
// ========== 步骤2:检查是否已有维修工单 ==========
|
|
|
DmsRepairWorkOrder existingOrder = dmsRepairWorkOrderService
|
|
|
.selectByFaultInstanceId(faultInstanceId);
|
|
|
|
|
|
DmsRepairWorkOrder order;
|
|
|
if (existingOrder == null) {
|
|
|
// ========== 步骤3:创建维修工单 ==========
|
|
|
order = new DmsRepairWorkOrder();
|
|
|
order.setFaultInstanceId(faultInstanceId);
|
|
|
order.setOrderStatus("0"); // 待派工
|
|
|
order.setRepairer(repairer);
|
|
|
order.setCreateTime(new Date());
|
|
|
dmsRepairWorkOrderService.insertRepairWorkOrder(order);
|
|
|
|
|
|
log.info("自动创建维修工单,工单ID: {}", order.getRepairOrderId());
|
|
|
|
|
|
// 【断点1】更新故障报修状态为"维修中"
|
|
|
fault.setBillsStatus("1");
|
|
|
fault.setUpdateTime(new Date());
|
|
|
dmsBillsFaultInstanceService.updateDmsBillsFaultInstance(fault);
|
|
|
|
|
|
log.info("【断点1】故障报修状态已更新为维修中");
|
|
|
} else {
|
|
|
order = existingOrder;
|
|
|
}
|
|
|
|
|
|
// ========== 步骤4:创建派工计划 ==========
|
|
|
DmsDispatchPlan plan = new DmsDispatchPlan();
|
|
|
plan.setRepairOrderId(order.getRepairOrderId());
|
|
|
plan.setRepairer(repairer);
|
|
|
plan.setReceiveStatus("0"); // 待接收
|
|
|
plan.setExecutionStatus("0"); // 未开始
|
|
|
plan.setCreateTime(new Date());
|
|
|
dmsDispatchPlanService.insertDispatchPlan(plan);
|
|
|
|
|
|
// 【断点2】派工时自动创建派工计划(自动接收)
|
|
|
plan.setReceiveStatus("1"); // 已接收
|
|
|
plan.setExecutionStatus("1"); // 维修中
|
|
|
plan.setReceiveTime(new Date());
|
|
|
plan.setUpdateTime(new Date());
|
|
|
dmsDispatchPlanService.updateDispatchPlan(plan);
|
|
|
|
|
|
log.info("【断点2】派工计划已创建并自动接收");
|
|
|
|
|
|
// ========== 步骤5:更新维修工单状态为"维修中" ==========
|
|
|
order.setOrderStatus("2"); // 维修中
|
|
|
order.setRealBeginTime(new Date());
|
|
|
order.setUpdateTime(new Date());
|
|
|
dmsRepairWorkOrderService.updateRepairWorkOrder(order);
|
|
|
|
|
|
log.info("维修工单状态已更新为维修中");
|
|
|
|
|
|
// ========== 步骤6:更新操作记录(原有逻辑) ==========
|
|
|
activity.setProcessHandleStatus("1"); // 执行中
|
|
|
activity.setStartTime(new Date());
|
|
|
dmsBillsFaultInstanceService.updateDmsFaultInstanceActivity(activity);
|
|
|
|
|
|
return AjaxResult.success("开始维修成功");
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
log.error("开始维修失败", e);
|
|
|
return AjaxResult.error("开始维修失败:" + e.getMessage());
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 4.4 completeRepair 方法完整重构
|
|
|
|
|
|
```java
|
|
|
/**
|
|
|
* 完成维修
|
|
|
*
|
|
|
* 【重构说明】
|
|
|
* - 保持接口路径和参数格式不变
|
|
|
* - 内部补全维修记录的创建逻辑
|
|
|
* - 触发断点3,确保数据完整性
|
|
|
*/
|
|
|
@PostMapping("/completeRepair")
|
|
|
public AjaxResult completeRepair(
|
|
|
@RequestParam("repairInstanceId") Long repairInstanceId,
|
|
|
@RequestParam("instanceActivityId") Long instanceActivityId,
|
|
|
@RequestParam(value = "checkedFault", required = false) String checkedFault,
|
|
|
@RequestParam(value = "repairContent", required = false) String repairContent,
|
|
|
@RequestParam(value = "protectedMethod", required = false) String protectedMethod,
|
|
|
@RequestParam(value = "repairer", required = false) String repairer,
|
|
|
@RequestParam(value = "parts1", required = false) String parts1,
|
|
|
@RequestParam(value = "files", required = false) List<MultipartFile> files) {
|
|
|
|
|
|
try {
|
|
|
log.info("PDA完成维修,故障报修ID: {}, 维修人: {}", repairInstanceId, repairer);
|
|
|
|
|
|
// ========== 步骤1:查询故障报修和维修工单 ==========
|
|
|
DmsBillsFaultInstance fault = dmsBillsFaultInstanceService
|
|
|
.selectDmsBillsFaultInstanceByRepairInstanceId(repairInstanceId);
|
|
|
if (fault == null) {
|
|
|
return AjaxResult.error("故障报修不存在");
|
|
|
}
|
|
|
|
|
|
DmsRepairWorkOrder order = dmsRepairWorkOrderService
|
|
|
.selectByFaultInstanceId(repairInstanceId);
|
|
|
if (order == null) {
|
|
|
return AjaxResult.error("维修工单不存在,请先开始维修");
|
|
|
}
|
|
|
|
|
|
// ========== 步骤2:更新维修工单状态为"已完成" ==========
|
|
|
order.setOrderStatus("3"); // 已完成
|
|
|
order.setRealEndTime(new Date());
|
|
|
order.setUpdateTime(new Date());
|
|
|
dmsRepairWorkOrderService.updateRepairWorkOrder(order);
|
|
|
|
|
|
log.info("维修工单状态已更新为已完成");
|
|
|
|
|
|
// ========== 步骤3:【断点3】创建维修记录 ==========
|
|
|
DmsRepairRecord record = new DmsRepairRecord();
|
|
|
record.setRepairOrderId(order.getRepairOrderId());
|
|
|
record.setFaultInstanceId(repairInstanceId);
|
|
|
record.setRepairContent(repairContent);
|
|
|
record.setRepairer(repairer);
|
|
|
record.setCheckedFault(checkedFault);
|
|
|
record.setProtectedMethod(protectedMethod);
|
|
|
record.setIsArchived("0"); // 未存档
|
|
|
record.setRepairEndTime(new Date());
|
|
|
record.setCreateTime(new Date());
|
|
|
dmsRepairRecordService.insertDmsRepairRecord(record);
|
|
|
|
|
|
log.info("【断点3】维修记录已创建,记录ID: {}", record.getRecordId());
|
|
|
|
|
|
// ========== 步骤4:【断点3】更新故障报修状态为"维修完成" ==========
|
|
|
fault.setBillsStatus("2"); // 维修完成
|
|
|
fault.setRealEndTime(new Date());
|
|
|
fault.setUpdateTime(new Date());
|
|
|
dmsBillsFaultInstanceService.updateDmsBillsFaultInstance(fault);
|
|
|
|
|
|
log.info("【断点3】故障报修状态已更新为维修完成");
|
|
|
|
|
|
// ========== 步骤5:处理配件消耗 ==========
|
|
|
if (parts1 != null && !parts1.isEmpty()) {
|
|
|
List<DmsFaultCompentsParts> parts = parsePartsJson(parts1);
|
|
|
for (DmsFaultCompentsParts part : parts) {
|
|
|
part.setFaultId(repairInstanceId);
|
|
|
// 保存配件信息
|
|
|
}
|
|
|
log.info("配件信息已保存,共{}个", parts.size());
|
|
|
}
|
|
|
|
|
|
// ========== 步骤6:更新操作记录(原有逻辑) ==========
|
|
|
DmsFaultInstanceActivity activity = new DmsFaultInstanceActivity();
|
|
|
activity.setInstanceActivityId(instanceActivityId);
|
|
|
activity.setCheckedFault(checkedFault);
|
|
|
activity.setRepairContent(repairContent);
|
|
|
activity.setProtectedMethod(protectedMethod);
|
|
|
activity.setRepairer(repairer);
|
|
|
activity.setProcessHandleStatus("2"); // 已完成
|
|
|
activity.setEndTime(new Date());
|
|
|
activity.setRepairConfirm(2); // 已确认
|
|
|
activity.setConfirmTime(new Date());
|
|
|
dmsBillsFaultInstanceService.updateDmsFaultInstanceActivity(activity);
|
|
|
|
|
|
return AjaxResult.success("完成维修成功");
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
log.error("完成维修失败", e);
|
|
|
return AjaxResult.error("完成维修失败:" + e.getMessage());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 解析配件JSON字符串
|
|
|
*/
|
|
|
private List<DmsFaultCompentsParts> parsePartsJson(String parts1) {
|
|
|
try {
|
|
|
ObjectMapper objectMapper = new ObjectMapper();
|
|
|
return objectMapper.readValue(parts1,
|
|
|
new TypeReference<List<DmsFaultCompentsParts>>() {});
|
|
|
} catch (Exception e) {
|
|
|
log.error("解析配件JSON失败", e);
|
|
|
return new ArrayList<>();
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 4.5 设备信息字段转换(重要)
|
|
|
|
|
|
#### 4.5.1 字段差异说明
|
|
|
|
|
|
**需求**:DmsMobileController 中所有设备信息改为使用 `BaseDeviceLedger`(aucma-base模块),但返回类型为 `DmsBaseDeviceLedger`(aucma-dms模块),需要进行字段转换。
|
|
|
|
|
|
**字段映射表**:
|
|
|
|
|
|
| 业务含义 | BaseDeviceLedger | DmsBaseDeviceLedger | 转换规则 |
|
|
|
|---------|------------------|---------------------|----------|
|
|
|
| 主键ID | `objId` | `deviceId` | `objId → deviceId` |
|
|
|
| 设备编号 | `deviceCode` | `deviceCode` | 直接映射 |
|
|
|
| 设备名称 | `deviceName` | `deviceName` | 直接映射 |
|
|
|
| 设备类型 | `deviceType` | `deviceTypeId` | `deviceType → deviceTypeId` |
|
|
|
| 设备型号 | `deviceModel` | `deviceSpec` | `deviceModel → deviceSpec` |
|
|
|
| 设备状态 | `deviceStatus` | `deviceStatus` | 直接映射 |
|
|
|
| 设备位置 | - | `deviceLocation` | 可为空 |
|
|
|
| 资产编号 | - | `assetNumber` | 可为空 |
|
|
|
| 供应商 | `manufacturer` | - | 需映射到 `suplierName` |
|
|
|
|
|
|
#### 4.5.2 字段转换方法
|
|
|
|
|
|
```java
|
|
|
/**
|
|
|
* 将 BaseDeviceLedger 转换为 DmsBaseDeviceLedger
|
|
|
* 用于PDA接口返回值转换
|
|
|
*/
|
|
|
private DmsBaseDeviceLedger convertToDmsBaseDeviceLedger(BaseDeviceLedger baseLedger) {
|
|
|
if (baseLedger == null) {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
DmsBaseDeviceLedger dmsLedger = new DmsBaseDeviceLedger();
|
|
|
|
|
|
// 主键映射
|
|
|
dmsLedger.setDeviceId(baseLedger.getObjId());
|
|
|
|
|
|
// 直接映射字段
|
|
|
dmsLedger.setDeviceCode(baseLedger.getDeviceCode());
|
|
|
dmsLedger.setDeviceName(baseLedger.getDeviceName());
|
|
|
dmsLedger.setDeviceStatus(baseLedger.getDeviceStatus());
|
|
|
|
|
|
// 字段名称转换
|
|
|
dmsLedger.setDeviceTypeId(baseLedger.getDeviceType()); // deviceType → deviceTypeId
|
|
|
dmsLedger.setDeviceSpec(baseLedger.getDeviceModel()); // deviceModel → deviceSpec
|
|
|
dmsLedger.setSuplierName(baseLedger.getManufacturer()); // manufacturer → suplierName
|
|
|
|
|
|
// 可为空字段
|
|
|
dmsLedger.setDeviceLocation(baseLedger.getUsedDepartment()); // 使用部门 → 设备位置
|
|
|
|
|
|
// 复制审计字段
|
|
|
dmsLedger.setCreateTime(baseLedger.getCreateTime());
|
|
|
dmsLedger.setCreateBy(baseLedger.getCreateBy());
|
|
|
dmsLedger.setUpdateTime(baseLedger.getUpdateTime());
|
|
|
dmsLedger.setUpdateBy(baseLedger.getUpdateBy());
|
|
|
dmsLedger.setIsFlag(baseLedger.getIsFlag());
|
|
|
|
|
|
return dmsLedger;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 批量转换 BaseDeviceLedger 列表
|
|
|
*/
|
|
|
private List<DmsBaseDeviceLedger> convertToDmsBaseDeviceLedgerList(List<BaseDeviceLedger> baseLedgerList) {
|
|
|
if (CollectionUtils.isEmpty(baseLedgerList)) {
|
|
|
return new ArrayList<>();
|
|
|
}
|
|
|
|
|
|
List<DmsBaseDeviceLedger> dmsLedgerList = new ArrayList<>();
|
|
|
for (BaseDeviceLedger baseLedger : baseLedgerList) {
|
|
|
dmsLedgerList.add(convertToDmsBaseDeviceLedger(baseLedger));
|
|
|
}
|
|
|
return dmsLedgerList;
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 4.5.3 需要修改的方法
|
|
|
|
|
|
**方法1:getDeviceByDeviceCode(Line 75-79)**
|
|
|
|
|
|
**修改前**:
|
|
|
```java
|
|
|
@GetMapping("/getDeviceByDeviceCode/{deviceCode}")
|
|
|
public AjaxResult getDeviceByDeviceCode(@PathVariable("deviceCode") String deviceCode) {
|
|
|
DmsBaseDeviceLedger dmsBaseDeviceLedger = baseDeviceLedgerService.selectDmsBaseDeviceLedgerByDeviceCode(deviceCode);
|
|
|
return success(dmsBaseDeviceLedger);
|
|
|
}
|
|
|
```
|
|
|
|
|
|
**修改后**:
|
|
|
```java
|
|
|
@Autowired
|
|
|
private IBaseDeviceLedgerService baseDeviceLedgerService; // 改为使用 base 模块的 Service
|
|
|
|
|
|
@GetMapping("/getDeviceByDeviceCode/{deviceCode}")
|
|
|
public AjaxResult getDeviceByDeviceCode(@PathVariable("deviceCode") String deviceCode) {
|
|
|
// 1. 使用 BaseDeviceLedger 查询
|
|
|
BaseDeviceLedger baseLedger = baseDeviceLedgerService.selectBaseDeviceLedgerByDeviceCode(deviceCode);
|
|
|
|
|
|
// 2. 转换为 DmsBaseDeviceLedger 返回
|
|
|
DmsBaseDeviceLedger dmsBaseDeviceLedger = convertToDmsBaseDeviceLedger(baseLedger);
|
|
|
|
|
|
return success(dmsBaseDeviceLedger);
|
|
|
}
|
|
|
```
|
|
|
|
|
|
**方法2:likeDeviceName(Line 102-106)**
|
|
|
|
|
|
**修改前**:
|
|
|
```java
|
|
|
@GetMapping("/likeDeviceName")
|
|
|
public AjaxResult likeDeviceName(String deviceName) {
|
|
|
List<DmsBaseDeviceLedger> deviceLedgerList = baseDeviceLedgerService.likeDeviceName(deviceName);
|
|
|
return success(deviceLedgerList);
|
|
|
}
|
|
|
```
|
|
|
|
|
|
**修改后**:
|
|
|
```java
|
|
|
@GetMapping("/likeDeviceName")
|
|
|
public AjaxResult likeDeviceName(String deviceName) {
|
|
|
// 1. 使用 BaseDeviceLedger 查询
|
|
|
List<BaseDeviceLedger> baseLedgerList = baseDeviceLedgerService.likeBaseDeviceName(deviceName);
|
|
|
|
|
|
// 2. 批量转换为 DmsBaseDeviceLedger 返回
|
|
|
List<DmsBaseDeviceLedger> dmsLedgerList = convertToDmsBaseDeviceLedgerList(baseLedgerList);
|
|
|
|
|
|
return success(dmsLedgerList);
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 4.6 其他方法保持不变
|
|
|
|
|
|
以下方法保持原有逻辑不变:
|
|
|
- insertFaultInstsanceActivity - 创建故障报修
|
|
|
- getBillsFaultInstances - 查询故障列表
|
|
|
- getBillsFaultInstanceByRepairInstanceId - 查询故障详情
|
|
|
- updateFaultInstanceActivity - 更新故障信息
|
|
|
- scanDevice4Repair - 扫码设备验证
|
|
|
|
|
|
---
|
|
|
|
|
|
## 五、数据流图
|
|
|
|
|
|
### 5.1 startRepair 数据流(重构后)
|
|
|
|
|
|
```
|
|
|
PDA调用 startRepair(faultInstanceId, repairer)
|
|
|
↓
|
|
|
DmsMobileController.startRepair()
|
|
|
↓
|
|
|
1. 查询故障报修
|
|
|
↓
|
|
|
2. 检查是否已有维修工单
|
|
|
├→ 没有 → 创建维修工单
|
|
|
│ └→ 【断点1】更新故障报修状态为"维修中"
|
|
|
└→ 已有 → 使用现有工单
|
|
|
↓
|
|
|
3. 创建派工计划
|
|
|
└→ 【断点2】自动接收派工
|
|
|
↓
|
|
|
4. 更新维修工单状态为"维修中"
|
|
|
↓
|
|
|
5. 更新操作记录
|
|
|
↓
|
|
|
返回成功
|
|
|
```
|
|
|
|
|
|
### 5.2 completeRepair 数据流(重构后)
|
|
|
|
|
|
```
|
|
|
PDA调用 completeRepair(faultInstanceId, repairContent, parts)
|
|
|
↓
|
|
|
DmsMobileController.completeRepair()
|
|
|
↓
|
|
|
1. 查询故障报修和维修工单
|
|
|
↓
|
|
|
2. 更新维修工单状态为"已完成"
|
|
|
↓
|
|
|
3. 【断点3】创建维修记录
|
|
|
↓
|
|
|
4. 【断点3】更新故障报修状态为"维修完成"
|
|
|
↓
|
|
|
5. 处理配件消耗
|
|
|
↓
|
|
|
6. 更新操作记录
|
|
|
↓
|
|
|
返回成功
|
|
|
```
|
|
|
|
|
|
---
|
|
|
|
|
|
## 六、测试方案
|
|
|
|
|
|
### 6.1 单元测试
|
|
|
|
|
|
```java
|
|
|
@SpringBootTest
|
|
|
class DmsMobileControllerTest {
|
|
|
|
|
|
@Autowired
|
|
|
private DmsMobileController dmsMobileController;
|
|
|
|
|
|
@Test
|
|
|
void testStartRepair() {
|
|
|
// 准备测试数据
|
|
|
DmsFaultInstanceActivity activity = new DmsFaultInstanceActivity();
|
|
|
activity.setRepairInstanceId(1L);
|
|
|
activity.setRepairer("张三");
|
|
|
|
|
|
// 调用接口
|
|
|
AjaxResult result = dmsMobileController.startRepair(activity);
|
|
|
|
|
|
// 验证结果
|
|
|
assertEquals("开始维修成功", result.get("msg"));
|
|
|
|
|
|
// 验证:维修工单已创建
|
|
|
DmsRepairWorkOrder order = repairWorkOrderService.selectByFaultInstanceId(1L);
|
|
|
assertNotNull(order);
|
|
|
assertEquals("2", order.getOrderStatus()); // 维修中
|
|
|
|
|
|
// 验证:派工计划已创建
|
|
|
DmsDispatchPlan plan = dispatchPlanService.selectByRepairOrderId(order.getRepairOrderId());
|
|
|
assertNotNull(plan);
|
|
|
assertEquals("1", plan.getReceiveStatus()); // 已接收
|
|
|
|
|
|
// 验证:故障报修状态已更新
|
|
|
DmsBillsFaultInstance fault = faultInstanceService.selectByRepairInstanceId(1L);
|
|
|
assertEquals("1", fault.getBillsStatus()); // 维修中
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
void testCompleteRepair() {
|
|
|
// 准备测试数据
|
|
|
// ...
|
|
|
|
|
|
// 调用接口
|
|
|
AjaxResult result = dmsMobileController.completeRepair(...);
|
|
|
|
|
|
// 验证结果
|
|
|
assertEquals("完成维修成功", result.get("msg"));
|
|
|
|
|
|
// 验证:维修记录已创建
|
|
|
DmsRepairRecord record = repairRecordService.selectByRepairOrderId(1L);
|
|
|
assertNotNull(record);
|
|
|
|
|
|
// 验证:故障报修状态已更新
|
|
|
DmsBillsFaultInstance fault = faultInstanceService.selectByRepairInstanceId(1L);
|
|
|
assertEquals("2", fault.getBillsStatus()); // 维修完成
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 6.2 PDA兼容性测试(关键)
|
|
|
|
|
|
| 测试场景 | 测试步骤 | 预期结果 |
|
|
|
|---------|----------|----------|
|
|
|
| PDA开始维修 | 调用 /startRepair | 1. 维修工单自动创建<br>2. 派工计划自动创建<br>3. 故障报修状态→维修中<br>4. 返回格式不变 |
|
|
|
| PDA完成维修 | 调用 /completeRepair | 1. 维修记录自动创建<br>2. 故障报修状态→维修完成<br>3. 返回格式不变 |
|
|
|
| PDA完整流程 | 创建→开始维修→完成维修 | 4个表数据完整,状态同步正确 |
|
|
|
|
|
|
### 6.3 Web端数据验证
|
|
|
|
|
|
| 模块 | 验证内容 | 验证方法 |
|
|
|
|------|----------|----------|
|
|
|
| 维修工单 | PDA创建的工单可见 | 查询 dms_repair_work_order 表 |
|
|
|
| 派工计划 | PDA自动创建的派工可见 | 查询 dms_dispatch_plan 表 |
|
|
|
| 维修记录 | PDA自动创建的记录可见 | 查询 dms_repair_record 表 |
|
|
|
| 故障报修 | 状态同步正确 | 查询 dms_bills_fault_instance.bills_status |
|
|
|
|
|
|
---
|
|
|
|
|
|
## 七、文件清单
|
|
|
|
|
|
### 7.1 需要修改的文件(1个)
|
|
|
|
|
|
| 序号 | 文件路径 | 修改内容 | 影响范围 |
|
|
|
|------|----------|----------|----------|
|
|
|
| 1 | aucma-dms/src/main/java/com/aucma/dms/controller/DmsMobileController.java | **1. 新增依赖注入**:<br> - IBaseDeviceLedgerService(base模块)<br> - IDmsRepairWorkOrderService<br> - IDmsDispatchPlanService<br> - IDmsRepairRecordService<br><br> **2. 新增字段转换方法**:<br> - convertToDmsBaseDeviceLedger() - 单个对象转换<br> - convertToDmsBaseDeviceLedgerList() - 批量转换<br><br> **3. 修改设备查询方法**:<br> - getDeviceByDeviceCode() - 改用 BaseDeviceLedger<br> - likeDeviceName() - 改用 BaseDeviceLedger<br><br> **4. 重构核心方法**:<br> - startRepair() - 补全工单和派工创建<br> - completeRepair() - 补全维修记录创建<br><br> **5. 新增辅助方法**:<br> - parsePartsJson() - 解析配件JSON | 仅PDA端,Web端不受影响 |
|
|
|
|
|
|
**修改详细说明**:
|
|
|
|
|
|
**新增导入**:
|
|
|
```java
|
|
|
import com.aucma.base.domain.BaseDeviceLedger;
|
|
|
import com.aucma.base.service.IBaseDeviceLedgerService;
|
|
|
import org.springframework.beans.BeanUtils;
|
|
|
```
|
|
|
|
|
|
**字段转换关键点**:
|
|
|
- 主键:`objId` → `deviceId`
|
|
|
- 设备类型:`deviceType` → `deviceTypeId`
|
|
|
- 设备型号:`deviceModel` → `deviceSpec`
|
|
|
- 供应商:`manufacturer` → `suplierName`
|
|
|
|
|
|
### 7.2 需要新建的文件(0个)
|
|
|
|
|
|
**说明**:本次重构不需要新建DTO类,直接使用现有实体类 + 字段转换方法即可。
|
|
|
|
|
|
### 7.3 不需要修改的文件
|
|
|
|
|
|
| 文件 | 说明 |
|
|
|
|------|------|
|
|
|
| DmsBillsFaultInstanceController.java | Web端接口,不在本次重构范围 |
|
|
|
| DmsBillsFaultInstanceServiceImpl.java | 现有服务,直接调用 |
|
|
|
| DmsRepairWorkOrderServiceImpl.java | 现有服务,直接调用 |
|
|
|
| DmsDispatchPlanServiceImpl.java | 现有服务,直接调用 |
|
|
|
| DmsRepairRecordServiceImpl.java | 现有服务,直接调用 |
|
|
|
|
|
|
---
|
|
|
|
|
|
## 八、实施步骤
|
|
|
|
|
|
### 阶段1:准备工作(半天)
|
|
|
|
|
|
- [ ] 备份 DmsMobileController.java
|
|
|
- [ ] 创建开发分支
|
|
|
- [ ] 确认4个Service的可用性
|
|
|
- [ ] 准备测试数据
|
|
|
|
|
|
### 阶段2:代码重构(1天)
|
|
|
|
|
|
- [ ] 新增4个Service依赖注入
|
|
|
- [ ] 重构 startRepair 方法
|
|
|
- [ ] 重构 completeRepair 方法
|
|
|
- [ ] 新增 parsePartsJson 辅助方法
|
|
|
- [ ] 添加日志记录
|
|
|
|
|
|
### 阶段3:单元测试(半天)
|
|
|
|
|
|
- [ ] 编写 startRepair 测试用例
|
|
|
- [ ] 编写 completeRepair 测试用例
|
|
|
- [ ] 验证数据一致性
|
|
|
|
|
|
### 阶段4:集成测试(1天)
|
|
|
|
|
|
- [ ] PDA端联调测试
|
|
|
- [ ] Web端数据验证
|
|
|
- [ ] 完整流程测试
|
|
|
|
|
|
### 阶段5:部署和验证(半天)
|
|
|
|
|
|
- [ ] 部署到测试环境
|
|
|
- [ ] PDA端功能验证
|
|
|
- [ ] Web端数据验证
|
|
|
- [ ] 性能测试
|
|
|
|
|
|
**总计:3-4天**
|
|
|
|
|
|
---
|
|
|
|
|
|
## 九、风险控制
|
|
|
|
|
|
### 9.1 风险识别
|
|
|
|
|
|
| 风险 | 影响 | 概率 | 应对措施 |
|
|
|
|------|------|------|----------|
|
|
|
| PDA接口变更导致PDA无法使用 | 高 | 低 | 严格保持接口路径和参数不变 |
|
|
|
| 业务流程补全导致数据错误 | 高 | 中 | 充分的单元测试和集成测试 |
|
|
|
| 性能下降 | 中 | 低 | 优化查询,添加必要的日志 |
|
|
|
| 事务回滚导致数据不一致 | 中 | 低 | 添加事务注解,确保原子性 |
|
|
|
|
|
|
### 9.2 回滚方案
|
|
|
|
|
|
1. **代码备份**:重构前备份 DmsMobileController.java
|
|
|
2. **快速回滚**:如出现问题,立即恢复备份文件
|
|
|
3. **灰度发布**:先在部分PDA设备上测试
|
|
|
4. **监控观察**:部署后密切关注日志和数据
|
|
|
|
|
|
---
|
|
|
|
|
|
## 十、成功标准
|
|
|
|
|
|
### 10.1 功能标准
|
|
|
|
|
|
- [ ] PDA端功能完全正常,无需修改
|
|
|
- [ ] startRepair 后自动创建维修工单和派工计划
|
|
|
- [ ] completeRepair 后自动创建维修记录
|
|
|
- [ ] Web端4个模块能看到完整的PDA操作数据
|
|
|
- [ ] 3个断点修复机制正常工作
|
|
|
|
|
|
### 10.2 质量标准
|
|
|
|
|
|
- [ ] 单元测试覆盖率 > 80%
|
|
|
- [ ] 集成测试全部通过
|
|
|
- [ ] 数据一致性检查无错误
|
|
|
- [ ] PDA兼容性测试全部通过
|
|
|
|
|
|
### 10.3 性能标准
|
|
|
|
|
|
- [ ] startRepair 接口响应时间 < 500ms
|
|
|
- [ ] completeRepair 接口响应时间 < 500ms
|
|
|
- [ ] 系统吞吐量无明显下降
|
|
|
|
|
|
---
|
|
|
|
|
|
## 十一、附录
|
|
|
|
|
|
### 11.1 状态流转图
|
|
|
|
|
|
```
|
|
|
故障报修状态 (bills_status)
|
|
|
0 (待维修) ──────────────→ 1 (维修中) ──────────────→ 2 (维修完成)
|
|
|
↑ ↓ ↓
|
|
|
└──── 创建报修 └─ startRepair └─ completeRepair
|
|
|
|
|
|
维修工单状态 (order_status)
|
|
|
0 (待派工) ──→ 1 (已派工) ──→ 2 (维修中) ──→ 3 (已完成)
|
|
|
↑ ↓ ↓ ↓
|
|
|
└─ startRepair创建 └─ 派工 └─ 接收派工 └─ completeRepair
|
|
|
计划
|
|
|
|
|
|
派工计划状态 (receive_status / execution_status)
|
|
|
0 (待接收) ──→ 1 (已接收)
|
|
|
↓ ↓
|
|
|
└─ startRepair创建 └─ 自动接收
|
|
|
|
|
|
维修记录状态 (is_archived)
|
|
|
0 (未存档)
|
|
|
↑
|
|
|
└─ completeRepair 自动创建
|
|
|
```
|
|
|
|
|
|
### 11.2 依赖注入清单
|
|
|
|
|
|
```java
|
|
|
// DmsMobileController 需要注入的Service
|
|
|
|
|
|
// 【原有】故障报修服务
|
|
|
@Autowired
|
|
|
private IDmsBillsFaultInstanceService dmsBillsFaultInstanceService;
|
|
|
|
|
|
// 【重构新增】设备台账服务(base模块)- 用于设备信息查询和转换
|
|
|
@Autowired
|
|
|
private IBaseDeviceLedgerService baseDeviceLedgerService;
|
|
|
|
|
|
// 【重构新增】维修工单服务 - 用于PDA端自动创建维修工单
|
|
|
@Autowired
|
|
|
private IDmsRepairWorkOrderService dmsRepairWorkOrderService;
|
|
|
|
|
|
// 【重构新增】派工计划服务 - 用于PDA端自动创建派工计划
|
|
|
@Autowired
|
|
|
private IDmsDispatchPlanService dmsDispatchPlanService;
|
|
|
|
|
|
// 【重构新增】维修记录服务 - 用于PDA端自动创建维修记录
|
|
|
@Autowired
|
|
|
private IDmsRepairRecordService dmsRepairRecordService;
|
|
|
```
|
|
|
|
|
|
**说明**:
|
|
|
- `IBaseDeviceLedgerService` 来自 `com.aucma.base.service` 包
|
|
|
- 其他Service来自 `com.aucma.dms.service` 包
|
|
|
|
|
|
### 11.3 核心方法签名
|
|
|
|
|
|
```java
|
|
|
// startRepair
|
|
|
@PostMapping("/startRepair")
|
|
|
public AjaxResult startRepair(@RequestBody DmsFaultInstanceActivity activity)
|
|
|
|
|
|
// completeRepair
|
|
|
@PostMapping("/completeRepair")
|
|
|
public AjaxResult completeRepair(
|
|
|
@RequestParam("repairInstanceId") Long repairInstanceId,
|
|
|
@RequestParam("instanceActivityId") Long instanceActivityId,
|
|
|
@RequestParam(value = "checkedFault", required = false) String checkedFault,
|
|
|
@RequestParam(value = "repairContent", required = false) String repairContent,
|
|
|
@RequestParam(value = "protectedMethod", required = false) String protectedMethod,
|
|
|
@RequestParam(value = "repairer", required = false) String repairer,
|
|
|
@RequestParam(value = "parts1", required = false) String parts1,
|
|
|
@RequestParam(value = "files", required = false) List<MultipartFile> files)
|
|
|
```
|
|
|
|
|
|
---
|
|
|
|
|
|
## 文档变更记录
|
|
|
|
|
|
| 版本 | 日期 | 变更内容 | 作者 |
|
|
|
|------|------|----------|------|
|
|
|
| 1.0 | 2025-02-05 | 初始版本 | Claude AI |
|
|
|
| 2.0 | 2026-02-05 | 基于4个Service分析,完全重写 | Claude AI |
|
|
|
| 3.0 | 2026-02-05 | **聚焦 DmsMobileController 重构,不涉及 Web 端** | Claude AI |
|
|
|
| 3.1 | 2026-02-05 | **新增设备信息字段转换方案(BaseDeviceLedger → DmsBaseDeviceLedger)** | Claude AI |
|
|
|
|
|
|
---
|
|
|
|
|
|
**文档结束**
|
|
|
|
|
|
> 本方案仅关注 DmsMobileController 的重构,保持PDA完美兼容,内部补全完整业务流程。DmsBillsFaultInstanceController 为Web端接口,不在本次重构范围。
|
|
|
>
|
|
|
> **重要更新**:设备信息查询改为使用 BaseDeviceLedger(base模块),通过字段转换方法转换为 DmsBaseDeviceLedger(dms模块)返回给PDA端。
|