From 227eff61120aaca63e068035d745d86452e6499a Mon Sep 17 00:00:00 2001
From: hsy <1029150275@qq.com>
Date: 星期一, 17 八月 2026 09:35:12 +0800
Subject: [PATCH] feat(mes): 优化生产订单与排产任务列表显示,新增启停工及校验逻辑 1. 生产订单列表展示优化 (WorkOrder) - 新增「生产状态」列,全局注册 `ORDER_PRODUCTION_STATUS` 常量并绑定系统动态字典。 - 彻底重构「工序生产进度」单元格显示:弃用臃肿的 Steps 组件,改为极简横向布局(彩色状态圆点 + 进度百分比),解决表格行高被强行撑开及内容截断问题,支持横向滚动。 - 优化「完成进度」列宽及展示样式,将百分比数值外置同行显示,更加直观。 2. 排产任务列表改造 (Task) - 顶部表头重构,由单一标题重构为「全部 / 未完成 / 已完成」的 Tabs 标签页切换结构。 - 重写数据过滤逻辑,剥离写死的 status 查询,改为使用 `scheduleStatus` 字段动态响应 Tabs 切换 (0: 未完成, 1: 已完成)。 3. 工单业务逻辑增强与状态流转 - 落实「工单查询逻辑设计方案」,优化底层的工单条件检索逻辑。 - 实现「添加工单启停功能」与「停工状态」,支持工单在执行过程中的暂停与恢复业务流转。 - 强化容错与防呆设计:操作「完成订单」时增加前置校验 `handleCheckFinish`,若生产状态为未完成,强制弹出二次确认 Modal,避免误操作。 # 相关讨论/参考方案 # - 添加工单启停功能 # - 停工状态功能设计方案 # - 工单查询逻辑设计方案 # - 工单完成进度显示优化
---
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java | 59 ++++
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskController.java | 57 ++++
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskMapper.java | 2
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderServiceImpl.java | 7
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskPauseRecordDO.java | 68 ++++
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderProcessService.java | 16 +
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderController.java | 98 ++++++
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskPauseReqVO.java | 25 +
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskResumeReqVO.java | 17 +
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderProcessMapper.java | 13
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProTaskStatusEnum.java | 10
yudao-module-mes/src/main/resources/mapper/pro/workorder/MesProWorkOrderMapper.xml | 108 +++++++
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderRespVO.java | 15
yudao-server/src/main/resources/application-local.yaml | 6
sql/mysql/task_pause_record.sql | 20 +
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderProcessServiceImpl.java | 13
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderMapper.java | 14 +
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskPauseRecordMapper.java | 28 ++
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderService.java | 10
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkOrderProductionStatusEnum.java | 47 +++
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskService.java | 14 +
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskPauseRecordRespVO.java | 42 +++
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java | 65 +++-
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java | 5
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderProcessProgressVO.java | 17 +
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskRespVO.java | 4
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderPageReqVO.java | 3
27 files changed, 745 insertions(+), 38 deletions(-)
diff --git a/sql/mysql/task_pause_record.sql b/sql/mysql/task_pause_record.sql
new file mode 100644
index 0000000..927afbb
--- /dev/null
+++ b/sql/mysql/task_pause_record.sql
@@ -0,0 +1,20 @@
+CREATE TABLE `mes_pro_task_pause_record` (
+ `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '缂栧彿',
+ `task_id` bigint(20) NOT NULL COMMENT '浠诲姟缂栧彿',
+ `work_order_id` bigint(20) DEFAULT NULL COMMENT '宸ュ崟缂栧彿',
+ `workstation_id` bigint(20) DEFAULT NULL COMMENT '宸ヤ綔绔欑紪鍙�',
+ `reason` varchar(255) NOT NULL COMMENT '鍋滃伐鍘熷洜',
+ `pause_time` datetime NOT NULL COMMENT '鍋滃伐鏃堕棿',
+ `pause_user_id` bigint(20) NOT NULL COMMENT '鍋滃伐鎿嶄綔浜篒D',
+ `resume_time` datetime DEFAULT NULL COMMENT '澶嶅伐鏃堕棿',
+ `resume_user_id` bigint(20) DEFAULT NULL COMMENT '澶嶅伐鎿嶄綔浜篒D',
+ `remark` varchar(500) DEFAULT NULL COMMENT '澶囨敞',
+ `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '鍒涘缓鑰�',
+ `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿',
+ `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '鏇存柊鑰�',
+ `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿',
+ `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '鏄惁鍒犻櫎',
+ `tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '绉熸埛缂栧彿',
+ PRIMARY KEY (`id`) USING BTREE,
+ KEY `idx_task_id` (`task_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='鐢熶骇浠诲姟鍋滃伐璁板綍琛�';
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskController.java
index a0cca8c..ff141d7 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskController.java
@@ -12,6 +12,8 @@
import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.GanttDataRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskAutoGeneratePreviewRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskAutoGenerateReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskPauseReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskResumeReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskPageReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskSaveReqVO;
@@ -48,6 +50,11 @@
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO;
import cn.iocoder.yudao.module.mes.enums.pro.MesProFeedbackStatusEnum;
import cn.iocoder.yudao.module.mes.service.pro.feedback.MesProFeedbackService;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskPauseRecordDO;
+import cn.iocoder.yudao.module.mes.dal.mysql.pro.task.MesProTaskPauseRecordMapper;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskPauseRecordRespVO;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import java.io.IOException;
import java.math.BigDecimal;
@@ -83,6 +90,10 @@
private MesProRouteProcessService routeProcessService;
@Resource
private MesProFeedbackService feedbackService;
+ @Resource
+ private MesProTaskPauseRecordMapper pauseRecordMapper;
+ @Resource
+ private AdminUserApi adminUserApi;
@PostMapping("/create")
@Operation(summary = "鍒涘缓鐢熶骇浠诲姟")
@@ -119,6 +130,22 @@
@PreAuthorize("@ss.hasPermission('mes:pro-task:delete')")
public CommonResult<Boolean> deleteTask(@RequestParam("id") Long id) {
taskService.deleteTask(id);
+ return success(true);
+ }
+
+ @PutMapping("/pause")
+ @Operation(summary = "鐢熶骇浠诲姟鍋滃伐")
+ @PreAuthorize("@ss.hasPermission('mes:pro-task:update')")
+ public CommonResult<Boolean> pauseTask(@Valid @RequestBody MesProTaskPauseReqVO pauseReqVO) {
+ taskService.pauseTask(pauseReqVO);
+ return success(true);
+ }
+
+ @PutMapping("/resume")
+ @Operation(summary = "鐢熶骇浠诲姟澶嶅伐")
+ @PreAuthorize("@ss.hasPermission('mes:pro-task:update')")
+ public CommonResult<Boolean> resumeTask(@Valid @RequestBody MesProTaskResumeReqVO resumeReqVO) {
+ taskService.resumeTask(resumeReqVO);
return success(true);
}
@@ -164,7 +191,35 @@
@PreAuthorize("@ss.hasPermission('mes:pro-task:query')")
public CommonResult<PageResult<MesProTaskRespVO>> getPendingFeedbackPage(@Valid MesProTaskPageReqVO pageReqVO) {
PageResult<MesProTaskDO> pageResult = taskService.getPendingFeedbackPage(pageReqVO);
- return success(new PageResult<>(buildTaskRespVOList(pageResult.getList()), pageResult.getTotal()));
+ List<MesProTaskRespVO> respVOList = buildTaskRespVOList(pageResult.getList());
+
+ if (CollUtil.isNotEmpty(respVOList)) {
+ Set<Long> taskIds = convertSet(respVOList, MesProTaskRespVO::getId);
+ List<MesProTaskPauseRecordDO> records = pauseRecordMapper.selectListByTaskIds(taskIds);
+ if (CollUtil.isNotEmpty(records)) {
+ Set<Long> userIds = new HashSet<>();
+ records.forEach(r -> {
+ if (r.getPauseUserId() != null) userIds.add(r.getPauseUserId());
+ if (r.getResumeUserId() != null) userIds.add(r.getResumeUserId());
+ });
+ Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
+
+ Map<Long, List<MesProTaskPauseRecordRespVO>> pauseRecordMap = new HashMap<>();
+ for (MesProTaskPauseRecordDO record : records) {
+ MesProTaskPauseRecordRespVO vo = BeanUtils.toBean(record, MesProTaskPauseRecordRespVO.class);
+ if (record.getPauseUserId() != null && userMap.containsKey(record.getPauseUserId())) {
+ vo.setPauseUserName(userMap.get(record.getPauseUserId()).getNickname());
+ }
+ if (record.getResumeUserId() != null && userMap.containsKey(record.getResumeUserId())) {
+ vo.setResumeUserName(userMap.get(record.getResumeUserId()).getNickname());
+ }
+ pauseRecordMap.computeIfAbsent(record.getTaskId(), k -> new ArrayList<>()).add(vo);
+ }
+ respVOList.forEach(vo -> vo.setPauseRecords(pauseRecordMap.get(vo.getId())));
+ }
+ }
+
+ return success(new PageResult<>(respVOList, pageResult.getTotal()));
}
@GetMapping("/gantt-list")
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskPauseRecordRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskPauseRecordRespVO.java
new file mode 100644
index 0000000..e6fb87d
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskPauseRecordRespVO.java
@@ -0,0 +1,42 @@
+package cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "绠$悊鍚庡彴 - MES 鐢熶骇浠诲姟鍋滃伐鍘嗗彶璁板綍 Response VO")
+@Data
+public class MesProTaskPauseRecordRespVO {
+
+ @Schema(description = "缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long id;
+
+ @Schema(description = "鐢熶骇浠诲姟ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ private Long taskId;
+
+ @Schema(description = "鍋滃伐鎿嶄綔浜篒D", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long pauseUserId;
+
+ @Schema(description = "鍋滃伐鎿嶄綔浜哄鍚�", requiredMode = Schema.RequiredMode.REQUIRED, example = "寮犱笁")
+ private String pauseUserName;
+
+ @Schema(description = "鍋滃伐鏃堕棿", requiredMode = Schema.RequiredMode.REQUIRED)
+ private LocalDateTime pauseTime;
+
+ @Schema(description = "鍋滃伐鍘熷洜", example = "璁惧鏁呴殰")
+ private String reason;
+
+ @Schema(description = "澶囨敞", example = "绱ф�ュ仠宸�")
+ private String remark;
+
+ @Schema(description = "澶嶅伐浜篒D", example = "2")
+ private Long resumeUserId;
+
+ @Schema(description = "澶嶅伐浜哄鍚�", example = "鏉庡洓")
+ private String resumeUserName;
+
+ @Schema(description = "澶嶅伐鏃堕棿")
+ private LocalDateTime resumeTime;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskPauseReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskPauseReqVO.java
new file mode 100644
index 0000000..63eddeb
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskPauseReqVO.java
@@ -0,0 +1,25 @@
+package cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+
+
+@Schema(description = "绠$悊鍚庡彴 - 鐢熶骇浠诲姟鍋滃伐 Request VO")
+@Data
+public class MesProTaskPauseReqVO {
+
+ @Schema(description = "浠诲姟缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @NotNull(message = "浠诲姟缂栧彿涓嶈兘涓虹┖")
+ private Long id;
+
+ @Schema(description = "鍋滃伐鍘熷洜", requiredMode = Schema.RequiredMode.REQUIRED, example = "璁惧鏁呴殰")
+ @NotEmpty(message = "鍋滃伐鍘熷洜涓嶈兘涓虹┖")
+ private String reason;
+
+ @Schema(description = "澶囨敞", example = "缁翠慨涓�")
+ private String remark;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskRespVO.java
index eb3c490..f4c0dd1 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskRespVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskRespVO.java
@@ -5,6 +5,7 @@
import java.math.BigDecimal;
import java.time.LocalDateTime;
+import java.util.List;
@Schema(description = "绠$悊鍚庡彴 - MES 鐢熶骇浠诲姟 Response VO")
@Data
@@ -130,4 +131,7 @@
@Schema(description = "鍒涘缓鏃堕棿", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
+ @Schema(description = "鍋滃伐鍘嗗彶璁板綍")
+ private List<MesProTaskPauseRecordRespVO> pauseRecords;
+
}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskResumeReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskResumeReqVO.java
new file mode 100644
index 0000000..3654bf3
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskResumeReqVO.java
@@ -0,0 +1,17 @@
+package cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+
+
+@Schema(description = "绠$悊鍚庡彴 - 鐢熶骇浠诲姟澶嶅伐 Request VO")
+@Data
+public class MesProTaskResumeReqVO {
+
+ @Schema(description = "浠诲姟缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @NotNull(message = "浠诲姟缂栧彿涓嶈兘涓虹┖")
+ private Long id;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderController.java
index 2cd70bb..b6233cd 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderController.java
@@ -9,20 +9,24 @@
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
-import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderPageReqVO;
-import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderProgressRespVO;
-import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderRespVO;
-import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderSaveReqVO;
import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO;
-import cn.iocoder.yudao.module.srm.api.supplier.SrmSupplierApi;
-import cn.iocoder.yudao.module.srm.api.supplier.dto.SrmSupplierRespDTO;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.*;
import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderProcessDO;
+import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderProductionStatusEnum;
import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService;
+import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService;
+import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService;
+import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderProcessService;
import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService;
+import cn.iocoder.yudao.module.srm.api.supplier.SrmSupplierApi;
+import cn.iocoder.yudao.module.srm.api.supplier.dto.SrmSupplierRespDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -34,10 +38,12 @@
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
+import java.math.BigDecimal;
import java.util.*;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@Tag(name = "绠$悊鍚庡彴 - MES 鐢熶骇宸ュ崟")
@@ -56,6 +62,12 @@
private SrmSupplierApi srmSupplierApi;
@Resource
private MesMdUnitMeasureService unitMeasureService;
+ @Resource
+ private MesProWorkOrderProcessService workOrderProcessService;
+ @Resource
+ private MesProTaskService taskService;
+ @Resource
+ private MesProProcessService processService;
@PostMapping("/create")
@Operation(summary = "鍒涘缓鐢熶骇宸ュ崟")
@@ -98,6 +110,14 @@
@PreAuthorize("@ss.hasPermission('mes:pro-work-order:query')")
public CommonResult<PageResult<MesProWorkOrderRespVO>> getWorkOrderPage(@Valid MesProWorkOrderPageReqVO pageReqVO) {
PageResult<MesProWorkOrderDO> pageResult = workOrderService.getWorkOrderPage(pageReqVO);
+ return success(new PageResult<>(buildWorkOrderRespVOList(pageResult.getList()), pageResult.getTotal()));
+ }
+
+ @GetMapping("/schedule-page")
+ @Operation(summary = "鑾峰緱鐢熶骇宸ュ崟璋冨害鐘舵�佸垎椤�")
+ @PreAuthorize("@ss.hasPermission('mes:pro-work-order:query')")
+ public CommonResult<PageResult<MesProWorkOrderRespVO>> getWorkOrderSchedulePage(@Valid MesProWorkOrderPageReqVO pageReqVO) {
+ PageResult<MesProWorkOrderDO> pageResult = workOrderService.getWorkOrderSchedulePage(pageReqVO);
return success(new PageResult<>(buildWorkOrderRespVOList(pageResult.getList()), pageResult.getTotal()));
}
@@ -163,6 +183,7 @@
return Collections.emptyList();
}
// 1. 鎵归噺鑾峰彇鍏宠仈鏁版嵁
+ Set<Long> workOrderIds = convertSet(list, MesProWorkOrderDO::getId);
Map<Long, MesMdItemDO> itemMap = itemService.getItemMap(
convertSet(list, MesProWorkOrderDO::getProductId));
Map<Long, CrmCustomerRespDTO> customerMap = customerApi.getCustomerMap(
@@ -175,6 +196,17 @@
convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId));
Map<Long, MesProWorkOrderDO> parentMap = workOrderService.getWorkOrderMap(
convertSet(list, MesProWorkOrderDO::getParentId));
+
+ // 鑾峰彇鎵�鏈夊叧鑱旂殑宸ュ崟宸ュ簭鍜屼换鍔�
+ List<MesProWorkOrderProcessDO> allProcesses = workOrderProcessService.getWorkOrderProcessListByWorkOrderIds(workOrderIds);
+ List<MesProTaskDO> allTasks = taskService.getTaskListByWorkOrderIds(workOrderIds);
+
+ Set<Long> processIds = convertSet(allProcesses, MesProWorkOrderProcessDO::getProcessId);
+ Map<Long, MesProProcessDO> processMap = processService.getProcessMap(processIds);
+
+ Map<Long, List<MesProWorkOrderProcessDO>> woProcessMap = convertMultiMap(allProcesses, MesProWorkOrderProcessDO::getWorkOrderId);
+ Map<Long, List<MesProTaskDO>> woTaskMap = convertMultiMap(allTasks, MesProTaskDO::getWorkOrderId);
+
// 2. 鎷兼帴 VO锛堝崟浣嶅悕绉颁粠浜у搧鍏宠仈鐨� item 鑾峰緱锛�
return BeanUtils.toBean(list, MesProWorkOrderRespVO.class, vo -> {
MapUtils.findAndThen(itemMap, vo.getProductId(), item -> {
@@ -189,6 +221,60 @@
supplier -> vo.setVendorName(supplier.getName()));
MapUtils.findAndThen(parentMap, vo.getParentId(),
parent -> vo.setParentCode(parent.getCode()));
+
+ // 璁$畻瀹屽伐杩涘害 (quantityProduced / quantity * 100)
+ BigDecimal produced = vo.getQuantityProduced() != null ? vo.getQuantityProduced() : BigDecimal.ZERO;
+ if (vo.getQuantity() != null && vo.getQuantity().compareTo(BigDecimal.ZERO) > 0) {
+ vo.setCompletionProgress(produced.multiply(new BigDecimal("100")).divide(vo.getQuantity(), 2, java.math.RoundingMode.HALF_UP));
+ } else {
+ vo.setCompletionProgress(produced.compareTo(BigDecimal.ZERO) > 0 ? new BigDecimal("100.00") : BigDecimal.ZERO);
+ }
+
+ // 璁$畻杩涘害鍜岀姸鎬�
+ List<MesProWorkOrderProcessDO> processes = woProcessMap.getOrDefault(vo.getId(), Collections.emptyList());
+ List<MesProTaskDO> tasks = woTaskMap.getOrDefault(vo.getId(), Collections.emptyList());
+
+ List<MesProWorkOrderProcessProgressVO> progressList = new ArrayList<>();
+ boolean allCompleted = !processes.isEmpty();
+ boolean anyStarted = false;
+
+ Map<Long, List<MesProTaskDO>> processTaskMap = convertMultiMap(tasks, MesProTaskDO::getProcessId);
+
+ for (MesProWorkOrderProcessDO process : processes) {
+ List<MesProTaskDO> pTasks = processTaskMap.getOrDefault(process.getProcessId(), Collections.emptyList());
+
+ BigDecimal totalQty = pTasks.stream().map(t -> t.getQuantity() != null ? t.getQuantity() : BigDecimal.ZERO).reduce(BigDecimal.ZERO, BigDecimal::add);
+ BigDecimal totalProduced = pTasks.stream().map(t -> t.getProducedQuantity() != null ? t.getProducedQuantity() : BigDecimal.ZERO).reduce(BigDecimal.ZERO, BigDecimal::add);
+
+ MesProWorkOrderProcessProgressVO progressVO = new MesProWorkOrderProcessProgressVO();
+ MesProProcessDO processDO = processMap.get(process.getProcessId());
+ progressVO.setProcessName(processDO != null ? processDO.getName() : "");
+
+ if (totalQty.compareTo(BigDecimal.ZERO) > 0) {
+ progressVO.setProgress(totalProduced.multiply(new BigDecimal("100")).divide(totalQty, 2, java.math.RoundingMode.HALF_UP));
+ } else {
+ progressVO.setProgress(totalProduced.compareTo(BigDecimal.ZERO) > 0 ? new BigDecimal("100.00") : BigDecimal.ZERO);
+ }
+ progressList.add(progressVO);
+
+ if (totalProduced.compareTo(BigDecimal.ZERO) > 0) {
+ anyStarted = true;
+ }
+ if (totalQty.compareTo(BigDecimal.ZERO) == 0 || totalProduced.compareTo(totalQty) < 0) {
+ allCompleted = false;
+ }
+ }
+
+ vo.setProcessProgressList(progressList);
+ if (processes.isEmpty()) {
+ vo.setProductionStatus(MesProWorkOrderProductionStatusEnum.WAITING.getStatus()); // 寰呯敓浜�
+ } else if (allCompleted) {
+ vo.setProductionStatus(MesProWorkOrderProductionStatusEnum.FINISHED.getStatus()); // 鐢熶骇瀹屾垚
+ } else if (anyStarted) {
+ vo.setProductionStatus(MesProWorkOrderProductionStatusEnum.PRODUCING.getStatus()); // 鐢熶骇涓�
+ } else {
+ vo.setProductionStatus(MesProWorkOrderProductionStatusEnum.WAITING.getStatus()); // 寰呯敓浜�
+ }
});
}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderPageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderPageReqVO.java
index cc17629..1508916 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderPageReqVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderPageReqVO.java
@@ -42,4 +42,7 @@
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] requestDate;
+ @Schema(description = "璋冨害鐘舵�侊紙绌�=鎵�鏈夛紝0=鏈畬鎴愶紝1=宸插畬鎴愶級", example = "1")
+ private Integer scheduleStatus;
+
}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderProcessProgressVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderProcessProgressVO.java
new file mode 100644
index 0000000..7e9612b
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderProcessProgressVO.java
@@ -0,0 +1,17 @@
+package cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Schema(description = "绠$悊鍚庡彴 - MES 宸ュ崟宸ュ簭杩涘害 VO")
+@Data
+public class MesProWorkOrderProcessProgressVO {
+
+ @Schema(description = "宸ュ簭鍚嶇О", example = "鎵撶(宸ュ簭")
+ private String processName;
+
+ @Schema(description = "宸ュ簭杩涘害(%)", example = "50.00")
+ private BigDecimal progress;
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderRespVO.java
index 70e1530..beb178f 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderRespVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderRespVO.java
@@ -61,13 +61,17 @@
@ExcelProperty("鍗曚綅")
private String unitMeasureName;
- @Schema(description = "鐢熶骇鏁伴噺", example = "100.00")
- @ExcelProperty("鐢熶骇鏁伴噺")
+ @Schema(description = "璁㈠崟鏁伴噺", example = "100.00")
+ @ExcelProperty("璁㈠崟鏁伴噺")
private BigDecimal quantity;
@Schema(description = "宸茬敓浜ф暟閲�", example = "50.00")
@ExcelProperty("宸茬敓浜ф暟閲�")
private BigDecimal quantityProduced;
+
+ @Schema(description = "瀹屽伐杩涘害", example = "50.00")
+ @ExcelProperty("瀹屽伐杩涘害")
+ private BigDecimal completionProgress;
@Schema(description = "璋冩暣鏁伴噺", example = "0")
@ExcelProperty("璋冩暣鏁伴噺")
@@ -134,4 +138,11 @@
@ExcelProperty("鍒涘缓鏃堕棿")
private LocalDateTime createTime;
+ @Schema(description = "宸ュ簭杩涘害鍒楄〃")
+ private java.util.List<MesProWorkOrderProcessProgressVO> processProgressList;
+
+ @Schema(description = "鐢熶骇鐘舵�� (0: 寰呯敓浜�, 1: 鐢熶骇涓�, 2: 鐢熶骇瀹屾垚)")
+ @ExcelProperty("鐢熶骇鐘舵��")
+ private Integer productionStatus;
+
}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskPauseRecordDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskPauseRecordDO.java
new file mode 100644
index 0000000..ecba5e9
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskPauseRecordDO.java
@@ -0,0 +1,68 @@
+package cn.iocoder.yudao.module.mes.dal.dataobject.pro.task;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.time.LocalDateTime;
+
+/**
+ * MES 鐢熶骇浠诲姟鍋滃伐璁板綍 DO
+ *
+ * @author 瓒呯骇绠$悊鍛�
+ */
+@TableName("mes_pro_task_pause_record")
+@KeySequence("mes_pro_task_pause_record_seq")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class MesProTaskPauseRecordDO extends BaseDO {
+
+ /**
+ * 缂栧彿
+ */
+ @TableId
+ private Long id;
+ /**
+ * 浠诲姟缂栧彿
+ */
+ private Long taskId;
+ /**
+ * 宸ュ崟缂栧彿
+ */
+ private Long workOrderId;
+ /**
+ * 宸ヤ綔绔欑紪鍙�
+ */
+ private Long workstationId;
+ /**
+ * 鍋滃伐鍘熷洜
+ */
+ private String reason;
+ /**
+ * 鍋滃伐鏃堕棿
+ */
+ private LocalDateTime pauseTime;
+ /**
+ * 鍋滃伐鎿嶄綔浜篒D
+ */
+ private Long pauseUserId;
+ /**
+ * 澶嶅伐鏃堕棿
+ */
+ private LocalDateTime resumeTime;
+ /**
+ * 澶嶅伐鎿嶄綔浜篒D
+ */
+ private Long resumeUserId;
+ /**
+ * 澶囨敞
+ */
+ private String remark;
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskMapper.java
index 57d2111..503445b 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskMapper.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskMapper.java
@@ -49,7 +49,7 @@
MPJLambdaWrapperX<MesProTaskDO> query = new MPJLambdaWrapperX<>();
query.selectAll(MesProTaskDO.class);
// 寰呮姤宸ュ彴璐︼細杩涜涓殑浠诲姟锛堟帓闄ゅ凡瀹屾垚/宸插彇娑堬級锛屼笖浠嶆湁寰呮姤宸ラ噺
- query.eq(MesProTaskDO::getStatus, MesProTaskStatusEnum.PREPARE.getStatus());
+ query.in(MesProTaskDO::getStatus, MesProTaskStatusEnum.PREPARE.getStatus(),MesProTaskStatusEnum.PAUSED.getStatus());
query.apply("(quantity - IFNULL(produced_quantity, 0)) > 0");
query.likeIfPresent(MesProTaskDO::getCode, reqVO.getCode())
.likeIfPresent(MesProTaskDO::getName, reqVO.getName())
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskPauseRecordMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskPauseRecordMapper.java
new file mode 100644
index 0000000..c005603
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskPauseRecordMapper.java
@@ -0,0 +1,28 @@
+package cn.iocoder.yudao.module.mes.dal.mysql.pro.task;
+
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskPauseRecordDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.Collection;
+import java.util.List;
+
+@Mapper
+public interface MesProTaskPauseRecordMapper extends BaseMapperX<MesProTaskPauseRecordDO> {
+
+ default MesProTaskPauseRecordDO selectLastUnresumedByTaskId(Long taskId) {
+ return selectOne(new LambdaQueryWrapperX<MesProTaskPauseRecordDO>()
+ .eq(MesProTaskPauseRecordDO::getTaskId, taskId)
+ .isNull(MesProTaskPauseRecordDO::getResumeTime)
+ .orderByDesc(MesProTaskPauseRecordDO::getId)
+ .last("LIMIT 1"));
+ }
+
+ default List<MesProTaskPauseRecordDO> selectListByTaskIds(Collection<Long> taskIds) {
+ return selectList(new LambdaQueryWrapperX<MesProTaskPauseRecordDO>()
+ .inIfPresent(MesProTaskPauseRecordDO::getTaskId, taskIds)
+ .orderByDesc(MesProTaskPauseRecordDO::getId));
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderMapper.java
index d6d43f9..da54452 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderMapper.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderMapper.java
@@ -58,6 +58,20 @@
return selectPage(reqVO, wrapper);
}
+ /**
+ * 鍒嗛〉鏌ヨ锛堝甫瀹㈡埛鏉冮檺杩囨护涓旀敮鎸佽皟搴︾姸鎬佹煡璇級
+ */
+ default PageResult<MesProWorkOrderDO> selectSchedulePage(MesProWorkOrderPageReqVO pageReqVO, List<Long> permittedClientIds) {
+ com.baomidou.mybatisplus.core.metadata.IPage<MesProWorkOrderDO> mpPage = cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils.buildPage(pageReqVO);
+ com.baomidou.mybatisplus.core.metadata.IPage<MesProWorkOrderDO> result = selectSchedulePage(mpPage, pageReqVO, permittedClientIds);
+ return new PageResult<>(result.getRecords(), result.getTotal());
+ }
+
+ com.baomidou.mybatisplus.core.metadata.IPage<MesProWorkOrderDO> selectSchedulePage(
+ com.baomidou.mybatisplus.core.metadata.IPage<MesProWorkOrderDO> page,
+ @org.apache.ibatis.annotations.Param("pageReqVO") MesProWorkOrderPageReqVO pageReqVO,
+ @org.apache.ibatis.annotations.Param("permittedClientIds") List<Long> permittedClientIds);
+
default MesProWorkOrderDO selectByCode(String code) {
return selectOne(MesProWorkOrderDO::getCode, code);
}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderProcessMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderProcessMapper.java
index ec76498..c3626a2 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderProcessMapper.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderProcessMapper.java
@@ -29,9 +29,22 @@
.orderByAsc(MesProWorkOrderProcessDO::getSort));
}
+ default MesProWorkOrderProcessDO selectLastByWorkOrderId(Long workOrderId) {
+ return selectOne(new LambdaQueryWrapperX<MesProWorkOrderProcessDO>()
+ .eq(MesProWorkOrderProcessDO::getWorkOrderId, workOrderId)
+ .orderByDesc(MesProWorkOrderProcessDO::getSort)
+ .last("LIMIT 1"));
+ }
+
default void deleteByWorkOrderId(Long workOrderId) {
delete(new LambdaQueryWrapperX<MesProWorkOrderProcessDO>()
.eq(MesProWorkOrderProcessDO::getWorkOrderId, workOrderId));
}
+ default List<MesProWorkOrderProcessDO> selectListByWorkOrderIds(java.util.Collection<Long> workOrderIds) {
+ return selectList(new LambdaQueryWrapperX<MesProWorkOrderProcessDO>()
+ .in(MesProWorkOrderProcessDO::getWorkOrderId, workOrderIds)
+ .orderByAsc(MesProWorkOrderProcessDO::getWorkOrderId, MesProWorkOrderProcessDO::getSort));
+ }
+
}
\ No newline at end of file
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
index 1e5d6ff..368ebf4 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
@@ -286,7 +286,9 @@
ErrorCode PRO_TASK_ROUTE_PROCESS_MISMATCH = new ErrorCode(1_040_503_004, "鐢熶骇浠诲姟涓庡綋鍓嶅伐鑹鸿矾绾挎垨宸ュ簭涓嶄竴鑷�");
ErrorCode PRO_TASK_ITEM_MISMATCH = new ErrorCode(1_040_503_005, "妫�楠岀墿鏂欎笌鐢熶骇浠诲姟鐗╂枡涓嶄竴鑷�");
ErrorCode PRO_TASK_HAS_FEEDBACK = new ErrorCode(1_040_503_006, "璇ヤ换鍔′笅瀛樺湪鎶ュ伐璁板綍锛屾棤娉曞垹闄わ紙閬垮厤鎶ュ伐杩芥函鏂摼锛�");
- ErrorCode PRO_WORKSTATION_PROCESS_MISMATCH = new ErrorCode(1_040_503_006, "宸ヤ綔绔欐墍灞炲伐搴忎笌褰撳墠宸ュ簭涓嶄竴鑷�");
+ ErrorCode PRO_WORKSTATION_PROCESS_MISMATCH = new ErrorCode(1_040_503_009, "宸ヤ綔绔欐墍灞炲伐搴忎笌褰撳墠宸ュ簭涓嶄竴鑷�"); // 淇缂栧彿鍐茬獊
+ ErrorCode PRO_TASK_CANNOT_PAUSE = new ErrorCode(1_040_503_007, "鍙湁銆愮敓浜т腑銆戞垨銆愰儴鍒嗗畬鎴愩�戠殑浠诲姟鍙互鍋滃伐");
+ ErrorCode PRO_TASK_NOT_PAUSED = new ErrorCode(1_040_503_008, "浠诲姟涓嶅浜庛�愬凡鍋滃伐銆戠姸鎬侊紝鏃犳硶澶嶅伐");
// ========== MES 鐢熶骇绠$悊-鐢熶骇浠诲姟鎶曟枡锛�1-040-503-100锛� ==========
ErrorCode PRO_TASK_ISSUE_NOT_EXISTS = new ErrorCode(1_040_503_100, "鐢熶骇浠诲姟鎶曟枡璁板綍涓嶅瓨鍦�");
@@ -314,6 +316,7 @@
ErrorCode PRO_FEEDBACK_QUALIFIED_UNQUALIFIED_REQUIRED = new ErrorCode(1_040_506_011, "璇疯緭鍏ュ悎鏍煎搧鍜屼笉鑹搧鏁伴噺锛屼笖鍚堣椤诲ぇ浜� 0");
ErrorCode PRO_FEEDBACK_UNCHECK_QUANTITY_EXISTS = new ErrorCode(1_040_506_012, "褰撳墠鎶ュ伐鍗曟湭瀹屾垚妫�楠岋紙寰呮鏁伴噺锛歿}锛夛紝鏃犳硶鎵ц鎶ュ伐");
ErrorCode PRO_FEEDBACK_BACKFLUSH_BOM_REQUIRED = new ErrorCode(1_040_506_013, "褰撳墠宸ュ簭涓哄�掑啿宸ュ簭锛屼絾鏈厤缃瓸OM娑堣�楋紝鏃犳硶鎶ュ伐");
+ ErrorCode PRO_FEEDBACK_CANNOT_CREATE_WHEN_PAUSED = new ErrorCode(1_040_506_014, "鐢熶骇浠诲姟澶勪簬鍋滃伐鐘舵�侊紝鏃犳硶鎶ュ伐");
// ========== MES 鐢熶骇绠$悊-鐢熶骇娴佽浆鍗★紙1-040-507-000锛� ==========
ErrorCode PRO_CARD_NOT_EXISTS = new ErrorCode(1_040_507_000, "鐢熶骇娴佽浆鍗′笉瀛樺湪");
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProTaskStatusEnum.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProTaskStatusEnum.java
index bb0986f..2d64ed5 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProTaskStatusEnum.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProTaskStatusEnum.java
@@ -46,7 +46,11 @@
*
* 瀵瑰簲 MesProTaskService#cancelTaskByOrderId 鏂规硶
*/
- CANCELED(MesOrderStatusConstants.CANCELLED, "宸插彇娑�");
+ CANCELED(MesOrderStatusConstants.CANCELLED, "宸插彇娑�"),
+ /**
+ * 宸插仠宸�
+ */
+ PAUSED(9, "宸插仠宸�");
public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesProTaskStatusEnum::getStatus).toArray(Integer[]::new);
@@ -75,13 +79,13 @@
}
/**
- * 鍒ゆ柇鏄惁鍙互鎶ュ伐锛堥潪缁堟�侊級
+ * 鍒ゆ柇鏄惁鍙互鎶ュ伐锛堥潪缁堟�佷笖闈炲仠宸ワ級
*
* @param status 鐘舵�佸��
* @return 鏄惁鍙互鎶ュ伐
*/
public static boolean canFeedback(Integer status) {
- return !isEndStatus(status);
+ return !isEndStatus(status) && !ObjectUtils.equalsAny(status, PAUSED.status);
}
}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkOrderProductionStatusEnum.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkOrderProductionStatusEnum.java
new file mode 100644
index 0000000..d2336dd
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkOrderProductionStatusEnum.java
@@ -0,0 +1,47 @@
+package cn.iocoder.yudao.module.mes.enums.pro;
+
+import cn.iocoder.yudao.framework.common.core.ArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * MES 鐢熶骇宸ュ崟鐢熶骇鐘舵�佹灇涓�
+ *
+ * @author 瓒呯骇绠$悊鍛�
+ */
+@Getter
+@AllArgsConstructor
+public enum MesProWorkOrderProductionStatusEnum implements ArrayValuable<Integer> {
+
+ /**
+ * 寰呯敓浜�
+ */
+ WAITING(0, "寰呯敓浜�"),
+ /**
+ * 鐢熶骇涓�
+ */
+ PRODUCING(1, "鐢熶骇涓�"),
+ /**
+ * 鐢熶骇瀹屾垚
+ */
+ FINISHED(2, "鐢熶骇瀹屾垚");
+
+ public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesProWorkOrderProductionStatusEnum::getStatus).toArray(Integer[]::new);
+
+ /**
+ * 鐘舵�佸��
+ */
+ private final Integer status;
+ /**
+ * 鐘舵�佸悕
+ */
+ private final String name;
+
+ @Override
+ public Integer[] array() {
+ return ARRAYS;
+ }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java
index abc010f..d5401e9 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java
@@ -15,15 +15,18 @@
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderBomDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderProcessDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume.MesWmItemConsumeDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceLineDO;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.feedback.MesProFeedbackMapper;
import cn.iocoder.yudao.module.mes.enums.pro.MesProFeedbackStatusEnum;
+import cn.iocoder.yudao.module.mes.enums.pro.MesProTaskStatusEnum;
import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum;
import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProcessService;
import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService;
import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderBomService;
+import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderProcessService;
import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService;
import cn.iocoder.yudao.module.mes.service.wm.itemconsume.MesWmItemConsumeService;
import cn.iocoder.yudao.module.mes.service.wm.productproduce.MesWmProductProduceLineService;
@@ -70,6 +73,8 @@
private MesProRouteProcessService routeProcessService;
@Resource
private MesProWorkOrderBomService workOrderBomService;
+ @Resource
+ private MesProWorkOrderProcessService workOrderProcessService;
@Resource
@Lazy // 閬垮厤寰幆渚濊禆
private MesProTaskService taskService;
@@ -215,6 +220,18 @@
.setUncheckQuantity(BigDecimal.ZERO));
// 6. 鏍规嵁鏄惁闇�瑕佹楠岋紝鍐冲畾浜у嚭鍜屽叆搴撴柟寮�
+ // 6.2 璋冩暣 鍙瀹℃壒鎴愬姛鐩存帴鏇存柊
+ // 鍏抽敭宸ュ簭锛氭洿鏂颁换鍔� + 宸ュ崟鐨勫凡鐢熶骇鏁伴噺锛涢潪鍏抽敭宸ュ簭锛氬彧鏇存柊浠诲姟鐨勫凡鐢熶骇鏁伴噺锛堝伐鍗曞彧鐪嬪叧閿伐搴忎骇鍑猴級
+ if (keyFlag) {
+ updateTaskAndWorkOrderByFeedback(feedback);
+ } else {
+ taskService.updateProducedQuantity(feedback.getTaskId(),
+ feedback.getFeedbackQuantity(),
+ ObjectUtil.defaultIfNull(feedback.getQualifiedQuantity(), BigDecimal.ZERO),
+ ObjectUtil.defaultIfNull(feedback.getUnqualifiedQuantity(), BigDecimal.ZERO));
+ checkAndPublishProductionFinished(feedback.getWorkOrderId());
+
+ }
if (checkFlag) {
// 6.1 闇�瑕佹楠岋細鐢熸垚浜у嚭鍗曪紙璐ㄩ噺鐘舵��=寰呮楠岋級锛屾洿鏂版姤宸ョ姸鎬佷负寰呮楠岋紝绛夎川妫�瀹屾垚鍥炶皟鍚庡啀鍏ュ簱
// 瀹屾垚鏃跺洖璋冭锛歁esQcIpqcServiceImpl#finishIpqc 鈫� splitPendingAndFinishProduce + updateProFeedbackWhenIpqcFinish
@@ -226,16 +243,7 @@
// 6.2 鏃犻渶妫�楠岋細鐢熸垚浜у嚭鍗曪紙鎸夊悎鏍�/涓嶅悎鏍兼媶琛岋級锛岀洿鎺ュ畬鎴愬叆搴�
MesWmProductProduceDO produce = productProduceService.generateProductProduce(feedback, false, reqVO);
productProduceService.finishProductProduce(produce.getId());
- // 鍏抽敭宸ュ簭锛氭洿鏂颁换鍔� + 宸ュ崟鐨勫凡鐢熶骇鏁伴噺锛涢潪鍏抽敭宸ュ簭锛氬彧鏇存柊浠诲姟鐨勫凡鐢熶骇鏁伴噺锛堝伐鍗曞彧鐪嬪叧閿伐搴忎骇鍑猴級
- if (keyFlag) {
- updateTaskAndWorkOrderByFeedback(feedback);
- } else {
- taskService.updateProducedQuantity(feedback.getTaskId(),
- feedback.getFeedbackQuantity(),
- ObjectUtil.defaultIfNull(feedback.getQualifiedQuantity(), BigDecimal.ZERO),
- ObjectUtil.defaultIfNull(feedback.getUnqualifiedQuantity(), BigDecimal.ZERO));
- checkAndPublishProductionFinished(feedback.getWorkOrderId());
- }
+
}
return true; // 宸插畬鎴�
@@ -248,6 +256,7 @@
* <li>浣跨敤鎶ュ伐鏁伴噺锛坒eedbackQuantity锛夛紝绱姞浠诲姟鍜屽伐鍗曠殑宸茬敓浜ф暟閲�</li>
* <li>浣跨敤浜у嚭鍗曡鎸� qualityStatus 鑱氬悎鐨勫悎鏍煎搧/涓嶅悎鏍煎搧鏁伴噺锛岀疮鍔犱换鍔$殑鍚堟牸鍝�/涓嶅悎鏍煎搧鏁伴噺
* 锛堜笉鐩存帴鐢� feedback 涓婄殑鏁伴噺锛岀‘淇濊川妫�鍥炶皟鍦烘櫙涓嬫暟閲忔潵婧愭纭級</li>
+ * isPush 鏄惁鎺ㄩ�佺敓浜у畬鎴愪簨浠�
* </ul>
*
* @param feedback 鎶ュ伐鍗�
@@ -266,18 +275,22 @@
}
}
- // 2. 鏇存柊浠诲姟鐨勫凡鐢熶骇/鍚堟牸/涓嶅悎鏍兼暟閲�
+ // 2. 鏇存柊浠诲姟鐨勫凡鐢熶骇/鍚堟牸/涓嶅悎鏍兼暟閲�
taskService.updateProducedQuantity(feedback.getTaskId(),
feedback.getFeedbackQuantity(), qualifiedQty, unqualifiedQty);
- // 3. 鏇存柊宸ュ崟鐨勫凡鐢熶骇鏁伴噺
- workOrderService.updateProducedQuantity(feedback.getWorkOrderId(),
- feedback.getFeedbackQuantity());
-
- // 4. 鏇存柊 MPS 鐨勫凡鐢熶骇鏁伴噺锛堝鏋滄槸閿�鍞鍗曟潵婧愶級
- MesProMpsRespDTO mps = mpsApi.getMpsByWorkOrderId(feedback.getWorkOrderId());
- if (mps != null) {
- mpsApi.updateMpsProducedQuantity(mps.getId(), feedback.getFeedbackQuantity());
+ // 3. 鏇存柊璁㈠崟鐨勫凡鐢熶骇鏁伴噺
+ // 鏂板閫昏緫锛氬彧鏈夊湪璇ョ瑪璁㈠崟鏈�鍚庝竴涓伐搴忔墠鏇存柊鐢熶骇璁㈠崟鐨勫凡鐢熶骇鏁伴噺
+ MesProWorkOrderProcessDO lastProcess = workOrderProcessService.getLastWorkOrderProcessByWorkOrderId(feedback.getWorkOrderId());
+ if (lastProcess != null && ObjUtil.equal(lastProcess.getProcessId(), feedback.getProcessId())) {
+ workOrderService.updateProducedQuantity(feedback.getWorkOrderId(),
+ feedback.getFeedbackQuantity());
+ // 4. 鏇存柊 MPS 鐨勫凡鐢熶骇鏁伴噺锛堝鏋滄槸閿�鍞鍗曟潵婧愶級
+ MesProMpsRespDTO mps = mpsApi.getMpsByWorkOrderId(feedback.getWorkOrderId());
+ if (mps != null) {
+ mpsApi.updateMpsProducedQuantity(mps.getId(), feedback.getFeedbackQuantity());
+ }
}
+
// 5. 妫�鏌ュ苟鍙戝竷鐢熶骇瀹屾垚浜嬩欢
checkAndPublishProductionFinished(feedback.getWorkOrderId());
@@ -342,6 +355,11 @@
// 1. 鏍¢獙浠诲姟瀛樺湪涓旀湭缁堟��
MesProTaskDO task = taskService.validateTaskNotFinished(reqVO.getTaskId());
+ // 鏍¢獙鍋滃伐鐘舵�佷笉鑳芥姤宸�
+ if (!MesProTaskStatusEnum.canFeedback(task.getStatus())) {
+ throw exception(PRO_FEEDBACK_CANNOT_CREATE_WHEN_PAUSED);
+ }
+
// 2. 浠庝换鍔¤嚜鍔ㄥ~鍏呭叧鑱斿瓧娈碉紙鍓嶇鏃犻渶浼犲叆锛屽悗绔粺涓�浠庝换鍔¤幏鍙栵級
reqVO.setWorkOrderId(task.getWorkOrderId());
reqVO.setRouteId(task.getRouteId());
@@ -380,6 +398,12 @@
public MesProFeedbackQuickCreateRespVO quickCreateFeedback(MesProFeedbackQuickCreateReqVO reqVO) {
// 1. 鏍¢獙浠诲姟瀛樺湪涓旈潪缁堟��
MesProTaskDO task = taskService.validateTaskNotFinished(reqVO.getTaskId());
+
+ // 鏍¢獙鍋滃伐鐘舵�佷笉鑳芥姤宸�
+ if (!MesProTaskStatusEnum.canFeedback(task.getStatus())) {
+ throw exception(PRO_FEEDBACK_CANNOT_CREATE_WHEN_PAUSED);
+ }
+
// 2. 鏍¢獙宸ヨ壓璺嚎宸ュ簭閰嶇疆
MesProRouteProcessDO routeProcess = routeProcessService.getRouteProcessByRouteIdAndProcessId(
task.getRouteId(), task.getProcessId());
@@ -486,7 +510,8 @@
// 4. 鏇存柊浠诲姟/宸ュ崟鐨勫凡鐢熶骇鏁伴噺
feedback.setQualifiedQuantity(qualifiedQty).setUnqualifiedQuantity(unqualifiedQty);
- updateTaskAndWorkOrderByFeedback(feedback);
+ //5.妫�鏌ュ苟鍙戝竷鐢熶骇瀹屾垚浜嬩欢
+ checkAndPublishProductionFinished(feedback.getWorkOrderId());
}
@Override
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskService.java
index eac0b94..d98de42 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskService.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskService.java
@@ -162,4 +162,18 @@
List<Long> autoGenerateTasks(
cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskAutoGenerateReqVO reqVO);
+ /**
+ * 鐢熶骇浠诲姟鍋滃伐
+ *
+ * @param pauseReqVO 鍋滃伐璇锋眰
+ */
+ void pauseTask(cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskPauseReqVO pauseReqVO);
+
+ /**
+ * 鐢熶骇浠诲姟澶嶅伐
+ *
+ * @param resumeReqVO 澶嶅伐璇锋眰
+ */
+ void resumeTask(cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskResumeReqVO resumeReqVO);
+
}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java
index 2510e7a..d6ebc52 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java
@@ -50,8 +50,16 @@
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_ALREADY_FINISHED;
+import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_CANNOT_PAUSE;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_HAS_FEEDBACK;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_NOT_EXISTS;
+import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_NOT_PAUSED;
+import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
+import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskPauseRecordDO;
+import cn.iocoder.yudao.module.mes.dal.mysql.pro.task.MesProTaskPauseRecordMapper;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskPauseReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskResumeReqVO;
/**
* MES 鐢熶骇浠诲姟 Service 瀹炵幇绫�
@@ -67,6 +75,9 @@
@Resource
private MesProFeedbackMapper feedbackMapper;
+
+ @Resource
+ private MesProTaskPauseRecordMapper taskPauseRecordMapper;
@Resource
@Lazy
@@ -429,4 +440,52 @@
return taskIds;
}
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void pauseTask(MesProTaskPauseReqVO pauseReqVO) {
+ // 1. 鏍¢獙浠诲姟瀛樺湪
+ MesProTaskDO task = validateTaskExists(pauseReqVO.getId());
+ // 2. 鏍¢獙鐘舵�佹槸鍚﹀厑璁稿仠宸ワ紙濡傚繀椤绘槸 鐢熶骇涓� 鎴� 閮ㄥ垎瀹屾垚锛�
+ if (!ObjectUtils.equalsAny(task.getStatus(), MesProTaskStatusEnum.PREPARE.getStatus())) {
+ throw exception(PRO_TASK_CANNOT_PAUSE);
+ }
+
+ // 3. 淇敼浠诲姟鐘舵�佷负宸插仠宸�
+ taskMapper.updateById(new MesProTaskDO().setId(task.getId()).setStatus(MesProTaskStatusEnum.PAUSED.getStatus()));
+
+ // 4. 鍒涘缓鍋滃伐璁板綍
+ MesProTaskPauseRecordDO pauseRecord = new MesProTaskPauseRecordDO()
+ .setTaskId(task.getId())
+ .setWorkOrderId(task.getWorkOrderId())
+ .setWorkstationId(task.getWorkstationId())
+ .setReason(pauseReqVO.getReason())
+ .setRemark(pauseReqVO.getRemark())
+ .setPauseTime(LocalDateTime.now())
+ .setPauseUserId(SecurityFrameworkUtils.getLoginUserId());
+ taskPauseRecordMapper.insert(pauseRecord);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void resumeTask(MesProTaskResumeReqVO resumeReqVO) {
+ // 1. 鏍¢獙浠诲姟瀛樺湪
+ MesProTaskDO task = validateTaskExists(resumeReqVO.getId());
+ // 2. 鏍¢獙鐘舵�佸繀椤绘槸宸插仠宸�
+ if (!ObjectUtils.equalsAny(task.getStatus(), MesProTaskStatusEnum.PAUSED.getStatus())) {
+ throw exception(PRO_TASK_NOT_PAUSED);
+ }
+
+ // 3. 鎭㈠浠诲姟鐘舵��
+ Integer resumeStatus = MesProTaskStatusEnum.PREPARE.getStatus();
+ taskMapper.updateById(new MesProTaskDO().setId(task.getId()).setStatus(resumeStatus));
+
+ // 4. 鏇存柊鏈�鏂扮殑涓�鏉″仠宸ヨ褰�
+ MesProTaskPauseRecordDO pauseRecord = taskPauseRecordMapper.selectLastUnresumedByTaskId(task.getId());
+ if (pauseRecord != null) {
+ pauseRecord.setResumeTime(LocalDateTime.now());
+ pauseRecord.setResumeUserId(SecurityFrameworkUtils.getLoginUserId());
+ taskPauseRecordMapper.updateById(pauseRecord);
+ }
+ }
+
}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderProcessService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderProcessService.java
index 1a740cc..d1d3ef0 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderProcessService.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderProcessService.java
@@ -62,6 +62,22 @@
List<MesProWorkOrderProcessDO> getWorkOrderProcessListByWorkOrderId(Long workOrderId);
/**
+ * 鏍规嵁宸ュ崟缂栧彿鑾峰緱鏈�鍚庝竴閬撳伐搴�
+ *
+ * @param workOrderId 宸ュ崟缂栧彿
+ * @return 鏈�鍚庝竴閬撳伐搴�
+ */
+ MesProWorkOrderProcessDO getLastWorkOrderProcessByWorkOrderId(Long workOrderId);
+
+ /**
+ * 鏍规嵁宸ュ崟缂栧彿鍒楄〃鑾峰緱宸ュ簭鍒楄〃
+ *
+ * @param workOrderIds 宸ュ崟缂栧彿鍒楄〃
+ * @return 宸ュ簭鍒楄〃
+ */
+ List<MesProWorkOrderProcessDO> getWorkOrderProcessListByWorkOrderIds(java.util.Collection<Long> workOrderIds);
+
+ /**
* 鏍规嵁宸ュ崟缂栧彿鍒犻櫎宸ュ簭
*
* @param workOrderId 宸ュ崟缂栧彿
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderProcessServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderProcessServiceImpl.java
index ebee3db..073b4e6 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderProcessServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderProcessServiceImpl.java
@@ -122,6 +122,19 @@
}
@Override
+ public MesProWorkOrderProcessDO getLastWorkOrderProcessByWorkOrderId(Long workOrderId) {
+ return workOrderProcessMapper.selectLastByWorkOrderId(workOrderId);
+ }
+
+ @Override
+ public List<MesProWorkOrderProcessDO> getWorkOrderProcessListByWorkOrderIds(java.util.Collection<Long> workOrderIds) {
+ if (CollUtil.isEmpty(workOrderIds)) {
+ return Collections.emptyList();
+ }
+ return workOrderProcessMapper.selectListByWorkOrderIds(workOrderIds);
+ }
+
+ @Override
public void deleteWorkOrderProcessByWorkOrderId(Long workOrderId) {
workOrderProcessMapper.deleteByWorkOrderId(workOrderId);
}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderService.java
index 91a93ac..08c4657 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderService.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderService.java
@@ -75,12 +75,20 @@
PageResult<MesProWorkOrderDO> getWorkOrderPage(MesProWorkOrderPageReqVO pageReqVO);
/**
+ * 鑾峰緱鐢熶骇宸ュ崟鍒嗛〉锛堝甫璋冨害鐘舵�侊級
+ *
+ * @param pageReqVO 鍒嗛〉鏌ヨ
+ * @return 鐢熶骇宸ュ崟鍒嗛〉
+ */
+ PageResult<MesProWorkOrderDO> getWorkOrderSchedulePage(MesProWorkOrderPageReqVO pageReqVO);
+
+ /**
* 鑾峰緱宸ュ崟鍒楄〃
*
* @param ids 缂栧彿鏁扮粍
* @return 宸ュ崟鍒楄〃
*/
- List<MesProWorkOrderDO> getWorkOrderList(Collection<Long> ids);
+ List<MesProWorkOrderDO> getWorkOrderList(java.util.Collection<Long> ids);
/**
* 鑾峰緱宸ュ崟 Map
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderServiceImpl.java
index c824d07..c4cb972 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderServiceImpl.java
@@ -167,6 +167,13 @@
}
@Override
+ public PageResult<MesProWorkOrderDO> getWorkOrderSchedulePage(MesProWorkOrderPageReqVO pageReqVO) {
+ // 鑾峰彇鐢ㄦ埛鏈夋潈闄愮殑瀹㈡埛 ID 鍒楄〃
+ List<Long> permittedClientIds = customerApi.getPermittedCustomerIds();
+ return workOrderMapper.selectSchedulePage(pageReqVO, permittedClientIds);
+ }
+
+ @Override
public List<MesProWorkOrderDO> getWorkOrderList(Collection<Long> ids) {
if (CollUtil.isEmpty(ids)) {
return Collections.emptyList();
diff --git a/yudao-module-mes/src/main/resources/mapper/pro/workorder/MesProWorkOrderMapper.xml b/yudao-module-mes/src/main/resources/mapper/pro/workorder/MesProWorkOrderMapper.xml
new file mode 100644
index 0000000..db118f3
--- /dev/null
+++ b/yudao-module-mes/src/main/resources/mapper/pro/workorder/MesProWorkOrderMapper.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.iocoder.yudao.module.mes.dal.mysql.pro.workorder.MesProWorkOrderMapper">
+
+ <select id="selectSchedulePage" resultType="cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO">
+ SELECT
+ t.*
+ FROM
+ mes_pro_work_order t
+ <where>
+ t.deleted = 0
+ <if test="pageReqVO.code != null and pageReqVO.code != ''">
+ AND t.code LIKE CONCAT('%', #{pageReqVO.code}, '%')
+ </if>
+ <if test="pageReqVO.name != null and pageReqVO.name != ''">
+ AND t.name LIKE CONCAT('%', #{pageReqVO.name}, '%')
+ </if>
+ <if test="pageReqVO.type != null">
+ AND t.type = #{pageReqVO.type}
+ </if>
+ <if test="pageReqVO.orderSourceCode != null and pageReqVO.orderSourceCode != ''">
+ AND t.order_source_code LIKE CONCAT('%', #{pageReqVO.orderSourceCode}, '%')
+ </if>
+ <if test="pageReqVO.productId != null">
+ AND t.product_id = #{pageReqVO.productId}
+ </if>
+ <if test="pageReqVO.clientId != null">
+ AND t.client_id = #{pageReqVO.clientId}
+ </if>
+ <if test="pageReqVO.status != null">
+ AND t.status = #{pageReqVO.status}
+ </if>
+ <if test="pageReqVO.requestDate != null and pageReqVO.requestDate.length > 0">
+ AND t.request_date >= #{pageReqVO.requestDate[0]}
+ <if test="pageReqVO.requestDate.length > 1">
+ AND t.request_date <= #{pageReqVO.requestDate[1]}
+ </if>
+ </if>
+
+ <if test="permittedClientIds != null">
+ <choose>
+ <when test="permittedClientIds.size() > 0">
+ AND (t.client_id IN
+ <foreach collection="permittedClientIds" item="id" open="(" separator="," close=")">
+ #{id}
+ </foreach>
+ OR t.client_id IS NULL)
+ </when>
+ <otherwise>
+ AND 1 = 0
+ </otherwise>
+ </choose>
+ </if>
+
+ <if test="pageReqVO.scheduleStatus != null">
+ <choose>
+ <!-- scheduleStatus: 1=宸插畬鎴� (宸ュ崟鐘舵��=4 鎴栬�� (鏈夊伐搴� 涓� 鎵�鏈夊伐搴忛兘鏈変换鍔� 涓� 鎵�鏈変换鍔″凡瀹屾垚)) -->
+ <when test="pageReqVO.scheduleStatus == 1">
+ AND (
+ t.status = 2
+ OR (
+ t.status != 4
+ AND EXISTS (SELECT 1 FROM mes_pro_work_order_process wp WHERE wp.work_order_id = t.id AND wp.deleted = 0)
+ AND NOT EXISTS (
+ SELECT 1 FROM mes_pro_work_order_process wp
+ WHERE wp.work_order_id = t.id AND wp.deleted = 0
+ AND NOT EXISTS (
+ SELECT 1 FROM mes_pro_task task
+ WHERE task.work_order_id = t.id AND task.process_id = wp.process_id AND task.deleted = 0
+ )
+ )
+ AND NOT EXISTS (
+ SELECT 1 FROM mes_pro_task task
+ WHERE task.work_order_id = t.id AND task.deleted = 0
+ AND IFNULL(task.produced_quantity, 0) < IFNULL(task.quantity, 0)
+ )
+ )
+ )
+ </when>
+ <!-- scheduleStatus: 0=鏈畬鎴� (宸ュ崟鐘舵��!=4 骞朵笖 (鏃犲伐搴� 鎴� 鏈夋煇宸ュ簭鏃犱换鍔� 鎴� 瀛樺湪鏈畬鎴愮殑浠诲姟)) -->
+ <when test="pageReqVO.scheduleStatus == 0">
+ AND (
+ t.status in (1)
+ AND (
+ NOT EXISTS (SELECT 1 FROM mes_pro_work_order_process wp WHERE wp.work_order_id = t.id AND wp.deleted = 0)
+ OR EXISTS (
+ SELECT 1 FROM mes_pro_work_order_process wp
+ WHERE wp.work_order_id = t.id AND wp.deleted = 0
+ AND NOT EXISTS (
+ SELECT 1 FROM mes_pro_task task
+ WHERE task.work_order_id = t.id AND task.process_id = wp.process_id AND task.deleted = 0
+ )
+ )
+ OR EXISTS (
+ SELECT 1 FROM mes_pro_task task
+ WHERE task.work_order_id = t.id AND task.deleted = 0
+ AND IFNULL(task.produced_quantity, 0) < IFNULL(task.quantity, 0)
+ )
+ )
+ )
+ </when>
+ </choose>
+ </if>
+ </where>
+ ORDER BY t.id DESC
+ </select>
+
+</mapper>
diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml
index 309ae9d..e4847d4 100644
--- a/yudao-server/src/main/resources/application-local.yaml
+++ b/yudao-server/src/main/resources/application-local.yaml
@@ -75,7 +75,7 @@
# url: jdbc:postgresql://127.0.0.1:5432/postgres # OpenGauss 杩炴帴鐨勭ず渚�
# url: jdbc:postgresql://127.0.0.1:5866/ruoyi-vue-pro # 鐎氶珮 HighGo 杩炴帴鐨勭ず渚�
username: root
- password: 123456
+ password: root@2026
# username: sa # SQL Server 杩炴帴鐨勭ず渚�
# password: Yudao@2024 # SQL Server 杩炴帴鐨勭ず渚�
# username: SYSDBA # DM 杩炴帴鐨勭ず渚�
@@ -88,7 +88,7 @@
lazy: true # 寮�鍚噿鍔犺浇锛屼繚璇佸惎鍔ㄩ�熷害
url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true
username: root
- password: 123456
+ password: root@2026
# tdengine: # IoT 鏁版嵁搴擄紙闇�瑕� IoT 鐗╄仈缃戝啀寮�鍚櫌锛侊級
# lazy: true # 寮�鍚噿鍔犺浇锛屼繚璇佸惎鍔ㄩ�熷害
# url: jdbc:TAOS-WS://127.0.0.1:6041/ruoyi_vue_pro?varcharAsString=true&enableAutoReconnect=true # 鍙傝锛歨ttps://t.zsxq.com/qaX9c锛屽紑鍚� TDengine WebSocket 鑷姩閲嶈繛
@@ -104,7 +104,7 @@
host: 127.0.0.1 # 鍦板潃
port: 6379 # 绔彛
database: 0 # 鏁版嵁搴撶储寮�
-# password: dev # 瀵嗙爜锛屽缓璁敓浜х幆澧冨紑鍚�
+ password: root@2026 # 瀵嗙爜锛屽缓璁敓浜х幆澧冨紑鍚�
--- #################### 瀹氭椂浠诲姟鐩稿叧閰嶇疆 ####################
--
Gitblit v1.9.3